Received: by 2002:a25:4158:0:0:0:0:0 with SMTP id o85csp4078457yba; Wed, 17 Apr 2019 04:14:27 -0700 (PDT) X-Google-Smtp-Source: APXvYqysvCEIbkQaV71oJv3n/rjygtUktUPAlDkDCNlfhWvp4Bk1JEKYEo7udBTP1MbU7qxQTVKT X-Received: by 2002:a17:902:7885:: with SMTP id q5mr89577399pll.12.1555499667116; Wed, 17 Apr 2019 04:14:27 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1555499667; cv=none; d=google.com; s=arc-20160816; b=DxP15zQaPO6Lyy6jtACjLDkY4/LCYztEJUN80sOAVXOYmOqC6565we65dFlcr0fsj9 ZdesgdrH9WxBQwN8BtDFTfUZK5enFuSPD+6tGrKLzd7mCsh7JDThpFZzdyVOgdUowCjg s7SWJ9zxlwZ7+ZDkZ9N30xzQEJ1K929tyFWlIhjVt5OvwMmgc3LAWn0IzKI63agIg5JA /iC6YIL6L2XMyTtlMhai7JtmLsplCwdoTOsh6Lfd0ZtdkRmVhPMy/dzKJUmE5C9iaPxs SjH/M3Un1M7mfDoqzqLhvTBSQmVqrQBDoasF77CHTXRzHO5fNGp8x74yGVOLZIwsjFtC 19AQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :user-agent:date:message-id:subject:from:cc:to; bh=qb8Bd4f/EGR5eoedCxcEviEvaZH9xaAbfAQMRSyKLu0=; b=tw9IZFM3Tzb845uayTQ+/NKQPiVh7OaDFlCcyiCpkre43zT8HEk7Z1nlI5SPp3E5dI UMKndmCqLMqXeCe7Rnc2G8D4XRuzfsomJ+4lFBkbw0MeODfaHRGEpYgAnZpZNaGzviD3 4cGm5Bc2uukqo6fyEfAfErckok23p97y7bDM5WY4NdIOoh1hn6wQypr9mdT3A02klpzx FctFGEgDWmDZhIYJrVQikIkeQ6180STR30V+8Eey3x/Qq2wKaQHKbK1xVvdMelglsK4L /UAPICppRXRU7x/uXfst4MH6P3tGdWSMkns/uMbSxUH1T+L8Hn4AXqas7skzbzOuCXog UKJw== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id i70si2078654pge.476.2019.04.17.04.14.11; Wed, 17 Apr 2019 04:14:27 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1731717AbfDQLNU (ORCPT + 99 others); Wed, 17 Apr 2019 07:13:20 -0400 Received: from szxga07-in.huawei.com ([45.249.212.35]:46872 "EHLO huawei.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1729522AbfDQLNU (ORCPT ); Wed, 17 Apr 2019 07:13:20 -0400 Received: from DGGEMS410-HUB.china.huawei.com (unknown [172.30.72.59]) by Forcepoint Email with ESMTP id C26418AC2282557F7E6C; Wed, 17 Apr 2019 19:13:16 +0800 (CST) Received: from [127.0.0.1] (10.184.225.177) by DGGEMS410-HUB.china.huawei.com (10.3.19.210) with Microsoft SMTP Server id 14.3.408.0; Wed, 17 Apr 2019 19:13:07 +0800 To: , , , CC: , , "Zhoukang (A)" From: Zhiqiang Liu Subject: [PATCH next] sysctl: add proc_dointvec_jiffies_minmax to limit the min/max write value Message-ID: <032e024f-2b1b-a980-1b53-d903bc8db297@huawei.com> Date: Wed, 17 Apr 2019 19:12:58 +0800 User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:60.0) Gecko/20100101 Thunderbird/60.5.0 MIME-Version: 1.0 Content-Type: text/plain; charset="gbk" Content-Transfer-Encoding: 7bit X-Originating-IP: [10.184.225.177] X-CFilter-Loop: Reflected Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Zhiqiang Liu In proc_dointvec_jiffies func, the write value is only checked whether it is larger than INT_MAX. If the write value is less than zero, it can also be successfully writen in the data. However, in some scenarios, users would adopt the data to set timers or check whether time is expired. Generally, the data will be cast to an unsigned type variable, then the negative data becomes a very large unsigned value, which leads to long waits or other unpredictable problems. Here, we add a new func, proc_dointvec_jiffies_minmax, to limit the min/max write value, which is similar to the proc_dointvec_minmax func. Signed-off-by: Zhiqiang Liu Reported-by: Qiang Ning Reviewed-by: Jie Liu --- include/linux/sysctl.h | 2 ++ kernel/sysctl.c | 44 +++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 45 insertions(+), 1 deletion(-) diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h index b769ecf..8bde8a0 100644 --- a/include/linux/sysctl.h +++ b/include/linux/sysctl.h @@ -53,6 +53,8 @@ extern int proc_douintvec_minmax(struct ctl_table *table, int write, loff_t *ppos); extern int proc_dointvec_jiffies(struct ctl_table *, int, void __user *, size_t *, loff_t *); +extern int proc_dointvec_jiffies_minmax(struct ctl_table *, int, + void __user *, size_t *, loff_t *); extern int proc_dointvec_userhz_jiffies(struct ctl_table *, int, void __user *, size_t *, loff_t *); extern int proc_dointvec_ms_jiffies(struct ctl_table *, int, diff --git a/kernel/sysctl.c b/kernel/sysctl.c index c9ec050..8e1eb59 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c @@ -2967,10 +2967,15 @@ static int do_proc_dointvec_jiffies_conv(bool *negp, unsigned long *lvalp, int *valp, int write, void *data) { + struct do_proc_dointvec_minmax_conv_param *param = data; + if (write) { if (*lvalp > INT_MAX / HZ) return 1; *valp = *negp ? -(*lvalp*HZ) : (*lvalp*HZ); + if ((param->min && (*param->min)*HZ > *valp) || + (param->max && (*param->max)*HZ < *valp)) + return -EINVAL; } else { int val = *valp; unsigned long lval; @@ -3053,7 +3058,37 @@ int proc_dointvec_jiffies(struct ctl_table *table, int write, void __user *buffer, size_t *lenp, loff_t *ppos) { return do_proc_dointvec(table,write,buffer,lenp,ppos, - do_proc_dointvec_jiffies_conv,NULL); + do_proc_dointvec_jiffies_conv, NULL); +} + +/** + * proc_dointvec_jiffies_minmax - read a vector of integers as seconds with min/max values + * @table: the sysctl table + * @write: %TRUE if this is a write to the sysctl file + * @buffer: the user buffer + * @lenp: the size of the user buffer + * @ppos: file position + * + * Reads/writes up to table->maxlen/sizeof(unsigned int) integer + * values from/to the user buffer, treated as an ASCII string. + * The values read are assumed to be in seconds, and are converted into + * jiffies. + * + * This routine will ensure the values are within the range specified by + * table->extra1 (min) and table->extra2 (max). + * + * Returns 0 on success or -EINVAL on write when the range check fails. + */ +int proc_dointvec_jiffies_minmax(struct ctl_table *table, int write, + void __user *buffer, size_t *lenp, loff_t *ppos) +{ + struct do_proc_dointvec_minmax_conv_param param = { + .min = (int *) table->extra1, + .max = (int *) table->extra2, + }; + + return do_proc_dointvec(table, write, buffer, lenp, ppos, + do_proc_dointvec_jiffies_conv, ¶m); } /** @@ -3301,6 +3336,12 @@ int proc_dointvec_jiffies(struct ctl_table *table, int write, return -ENOSYS; } +int proc_dointvec_jiffies_minmax(struct ctl_table *table, int write, + void __user *buffer, size_t *lenp, loff_t *ppos) +{ + return -ENOSYS; +} + int proc_dointvec_userhz_jiffies(struct ctl_table *table, int write, void __user *buffer, size_t *lenp, loff_t *ppos) { @@ -3359,6 +3400,7 @@ static int proc_dointvec_minmax_bpf_stats(struct ctl_table *table, int write, EXPORT_SYMBOL(proc_dointvec); EXPORT_SYMBOL(proc_douintvec); EXPORT_SYMBOL(proc_dointvec_jiffies); +EXPORT_SYMBOL(proc_dointvec_jiffies_minmax); EXPORT_SYMBOL(proc_dointvec_minmax); EXPORT_SYMBOL_GPL(proc_douintvec_minmax); EXPORT_SYMBOL(proc_dointvec_userhz_jiffies); -- 1.8.3.1