From nobody Wed Dec 17 10:00:14 2025 Received: from out-175.mta0.migadu.com (out-175.mta0.migadu.com [91.218.175.175]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 04B41B64E for ; Sun, 14 Jul 2024 17:39:43 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=91.218.175.175 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1720978788; cv=none; b=CTDwrexJK8O0a4sv7YSclEekHMW47ErAzOAJqLt2I9+wu6YhDmW2p8eNqJdCKemI5RKAjE/8AtCHsG1rYgdXqC1fV8/YTJwdq/q0Lhv5ZVo/W0bMiqSdIjoLZCF0hrGu/3sqpPCmqA/xNe/2U7PYh3jiW85NWPjN1CBjDVIAl+Y= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1720978788; c=relaxed/simple; bh=S+HLUVtEC8JRD8Fxtr8++OIjIkdlqjKWuSFtDhOBK6o=; h=From:To:Cc:Subject:Date:Message-Id:MIME-Version; b=D7zHHnZ+DB2eBGNv8NVhvwpW4mzFlocHeZNUrHnOQnQlcK51fAwX3y8ajJV/9YNsALoD4LdjvwDQ64omw5l1Hr1mS/LH1YsHngoT1QlToECuTA9baJwP+EA6n3X5OpS60CtxrbD6b013+NZ4AXbaHaL6ZcjjJQVPXZllFPbdY5w= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev; spf=pass smtp.mailfrom=linux.dev; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b=O/5h0ZcN; arc=none smtp.client-ip=91.218.175.175 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b="O/5h0ZcN" X-Envelope-To: ebiederm@xmission.com DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1720978780; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding; bh=wR6neTBRVsBQbwOYI2WuLar72mKO6WfMr5X+0o8BApQ=; b=O/5h0ZcN92GP1ttm67CuoHoeGoYFGFbP+bS1aytfUHTBIwOLOYiuSESCjADD7x1PqZTjU/ /kVy9ZBfVCayDD7gfvfviQua5OWiQPX5dXA1n2u1MPPKTOqhIP8A1kn3VKkljtAITmMmwg 8QW/ZhcR8alLml8wozjhRdOwcHbVXDQ= X-Envelope-To: mcgrof@kernel.org X-Envelope-To: keescook@chromium.org X-Envelope-To: j.granados@samsung.com X-Envelope-To: brauner@kernel.org X-Envelope-To: wen.yang@linux.dev X-Envelope-To: linux-kernel@vger.kernel.org X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. From: Wen Yang To: "Eric W . Biederman" , Luis Chamberlain , Kees Cook , Joel Granados , Christian Brauner Cc: Wen Yang , linux-kernel@vger.kernel.org Subject: [PATCH] sysctl: simplify the min/max boundary check Date: Mon, 15 Jul 2024 01:38:58 +0800 Message-Id: <20240714173858.52163-1-wen.yang@linux.dev> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Migadu-Flow: FLOW_OUT Content-Type: text/plain; charset="utf-8" The do_proc_dointvec_minmax_conv_param structure provides the minimum and maximum values for doing range checking for the proc_dointvec_minmax() handler, while the do_proc_douintvec_minmax_conv_param structure also provides the minimumand maximum values for doing range checking for the proc_douintvec_minmax()/proc_dou8vec_minmax() handlers. Introduce a new do_proc_dointvec_minmax_conv_param structure to replace the do_proc_dointvec_minmax_conv_param and do_proc_douintvec_minmax_conv_param structures mentioned above. This simplifies the code and also prepares for the removal of sysctl_vals. Signed-off-by: Wen Yang Cc: Luis Chamberlain Cc: Kees Cook Cc: Joel Granados Cc: Eric W. Biederman Cc: Christian Brauner Cc: linux-kernel@vger.kernel.org --- kernel/sysctl.c | 107 ++++++++++++++++++++++++++---------------------- 1 file changed, 57 insertions(+), 50 deletions(-) diff --git a/kernel/sysctl.c b/kernel/sysctl.c index e4421594fc25..bc784d726e09 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c @@ -809,17 +809,18 @@ static int proc_taint(struct ctl_table *table, int wr= ite, } =20 /** - * struct do_proc_dointvec_minmax_conv_param - proc_dointvec_minmax() rang= e checking structure - * @min: pointer to minimum allowable value - * @max: pointer to maximum allowable value + * struct do_proc_minmax_conv_param - proc_dointvec_minmax() range checkin= g structure + * @min: the minimum allowable value + * @max: the maximum allowable value * - * The do_proc_dointvec_minmax_conv_param structure provides the + * The do_proc_minmax_conv_param structure provides the * minimum and maximum values for doing range checking for those sysctl - * parameters that use the proc_dointvec_minmax() handler. + * parameters that use the proc_dointvec_minmax(), proc_douintvec_minmax(), + * proc_dou8vec_minmax() and so on. */ -struct do_proc_dointvec_minmax_conv_param { - int *min; - int *max; +struct do_proc_minmax_conv_param { + long min; + long max; }; =20 static int do_proc_dointvec_minmax_conv(bool *negp, unsigned long *lvalp, @@ -827,7 +828,7 @@ static int do_proc_dointvec_minmax_conv(bool *negp, uns= igned long *lvalp, int write, void *data) { int tmp, ret; - struct do_proc_dointvec_minmax_conv_param *param =3D data; + struct do_proc_minmax_conv_param *param =3D data; /* * If writing, first do so via a temporary local int so we can * bounds-check it before touching *valp. @@ -839,8 +840,7 @@ static int do_proc_dointvec_minmax_conv(bool *negp, uns= igned long *lvalp, return ret; =20 if (write) { - if ((param->min && *param->min > tmp) || - (param->max && *param->max < tmp)) + if ((param->min > tmp) || (param->max < tmp)) return -EINVAL; WRITE_ONCE(*valp, tmp); } @@ -867,35 +867,27 @@ static int do_proc_dointvec_minmax_conv(bool *negp, u= nsigned long *lvalp, int proc_dointvec_minmax(struct ctl_table *table, int write, void *buffer, size_t *lenp, loff_t *ppos) { - struct do_proc_dointvec_minmax_conv_param param =3D { - .min =3D (int *) table->extra1, - .max =3D (int *) table->extra2, + struct do_proc_minmax_conv_param param =3D { + .min =3D INT_MIN, + .max =3D INT_MAX, }; + + if (table->extra1) + param.min =3D *(int *) table->extra1; + if (table->extra2) + param.max =3D *(int *) table->extra2; + return do_proc_dointvec(table, write, buffer, lenp, ppos, do_proc_dointvec_minmax_conv, ¶m); } =20 -/** - * struct do_proc_douintvec_minmax_conv_param - proc_douintvec_minmax() ra= nge checking structure - * @min: pointer to minimum allowable value - * @max: pointer to maximum allowable value - * - * The do_proc_douintvec_minmax_conv_param structure provides the - * minimum and maximum values for doing range checking for those sysctl - * parameters that use the proc_douintvec_minmax() handler. - */ -struct do_proc_douintvec_minmax_conv_param { - unsigned int *min; - unsigned int *max; -}; - static int do_proc_douintvec_minmax_conv(unsigned long *lvalp, unsigned int *valp, int write, void *data) { int ret; unsigned int tmp; - struct do_proc_douintvec_minmax_conv_param *param =3D data; + struct do_proc_minmax_conv_param *param =3D data; /* write via temporary local uint for bounds-checking */ unsigned int *up =3D write ? &tmp : valp; =20 @@ -904,8 +896,7 @@ static int do_proc_douintvec_minmax_conv(unsigned long = *lvalp, return ret; =20 if (write) { - if ((param->min && *param->min > tmp) || - (param->max && *param->max < tmp)) + if ((param->min > tmp) || (param->max < tmp)) return -ERANGE; =20 WRITE_ONCE(*valp, tmp); @@ -936,10 +927,16 @@ static int do_proc_douintvec_minmax_conv(unsigned lon= g *lvalp, int proc_douintvec_minmax(struct ctl_table *table, int write, void *buffer, size_t *lenp, loff_t *ppos) { - struct do_proc_douintvec_minmax_conv_param param =3D { - .min =3D (unsigned int *) table->extra1, - .max =3D (unsigned int *) table->extra2, + struct do_proc_minmax_conv_param param =3D { + .min =3D 0, + .max =3D UINT_MAX, }; + + if (table->extra1) + param.min =3D *(unsigned int *) table->extra1; + if (table->extra2) + param.max =3D *(unsigned int *) table->extra2; + return do_proc_douintvec(table, write, buffer, lenp, ppos, do_proc_douintvec_minmax_conv, ¶m); } @@ -965,11 +962,11 @@ int proc_dou8vec_minmax(struct ctl_table *table, int = write, void *buffer, size_t *lenp, loff_t *ppos) { struct ctl_table tmp; - unsigned int min =3D 0, max =3D 255U, val; + unsigned int val; u8 *data =3D table->data; - struct do_proc_douintvec_minmax_conv_param param =3D { - .min =3D &min, - .max =3D &max, + struct do_proc_minmax_conv_param param =3D { + .min =3D 0, + .max =3D 255U, }; int res; =20 @@ -978,9 +975,9 @@ int proc_dou8vec_minmax(struct ctl_table *table, int wr= ite, return -EINVAL; =20 if (table->extra1) - min =3D *(unsigned int *) table->extra1; + param.min =3D *(unsigned int *) table->extra1; if (table->extra2) - max =3D *(unsigned int *) table->extra2; + param.max =3D *(unsigned int *) table->extra2; =20 tmp =3D *table; =20 @@ -1022,7 +1019,8 @@ static int __do_proc_doulongvec_minmax(void *data, void *buffer, size_t *lenp, loff_t *ppos, unsigned long convmul, unsigned long convdiv) { - unsigned long *i, *min, *max; + unsigned long min =3D 0, max =3D ULONG_MAX; + unsigned long *i; int vleft, first =3D 1, err =3D 0; size_t left; char *p; @@ -1033,8 +1031,12 @@ static int __do_proc_doulongvec_minmax(void *data, } =20 i =3D data; - min =3D table->extra1; - max =3D table->extra2; + + if (table->extra1) + min =3D *(unsigned long *) table->extra1; + if (table->extra2) + max =3D *(unsigned long *) table->extra2; + vleft =3D table->maxlen / sizeof(unsigned long); left =3D *lenp; =20 @@ -1066,7 +1068,7 @@ static int __do_proc_doulongvec_minmax(void *data, } =20 val =3D convmul * val / convdiv; - if ((min && val < *min) || (max && val > *max)) { + if ((val < min) || (val > max)) { err =3D -EINVAL; break; } @@ -1224,7 +1226,7 @@ static int do_proc_dointvec_ms_jiffies_minmax_conv(bo= ol *negp, unsigned long *lv int *valp, int write, void *data) { int tmp, ret; - struct do_proc_dointvec_minmax_conv_param *param =3D data; + struct do_proc_minmax_conv_param *param =3D data; /* * If writing, first do so via a temporary local int so we can * bounds-check it before touching *valp. @@ -1236,8 +1238,7 @@ static int do_proc_dointvec_ms_jiffies_minmax_conv(bo= ol *negp, unsigned long *lv return ret; =20 if (write) { - if ((param->min && *param->min > tmp) || - (param->max && *param->max < tmp)) + if ((param->min > tmp) || (param->max < tmp)) return -EINVAL; *valp =3D tmp; } @@ -1269,10 +1270,16 @@ int proc_dointvec_jiffies(struct ctl_table *table, = int write, int proc_dointvec_ms_jiffies_minmax(struct ctl_table *table, int write, void *buffer, size_t *lenp, loff_t *ppos) { - struct do_proc_dointvec_minmax_conv_param param =3D { - .min =3D (int *) table->extra1, - .max =3D (int *) table->extra2, + struct do_proc_minmax_conv_param param =3D { + .min =3D INT_MIN, + .max =3D INT_MAX, }; + + if (table->extra1) + param.min =3D *(int *) table->extra1; + if (table->extra2) + param.max =3D *(int *) table->extra2; + return do_proc_dointvec(table, write, buffer, lenp, ppos, do_proc_dointvec_ms_jiffies_minmax_conv, ¶m); } --=20 2.25.1