Received: by 10.213.65.68 with SMTP id h4csp271990imn; Mon, 12 Mar 2018 13:19:54 -0700 (PDT) X-Google-Smtp-Source: AG47ELsYvZuwWRrLyBITb4g3jW9Ej1yd7us2JYcY8pUEtwA8dEyVogRKOGIsCyc2rEqFo1zhFxrX X-Received: by 10.99.45.194 with SMTP id t185mr7550489pgt.267.1520885994209; Mon, 12 Mar 2018 13:19:54 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1520885994; cv=none; d=google.com; s=arc-20160816; b=gUdL15DwdtDEf55/3qjBvLgKSdj5jLQ0awv6JmxMBE31B4ceYZHGqXn+m8ivpiZg0B AAGNll3l6bbOscGVS1Ia8Umg0oz7XscVCFzrNGuppwM3KUbvAox+iooc1l5SWHcSYWRt RTrB1DGyXFRpmMipE/XVYGhYVnyI7ruUfK9lbrX9VxT5x7wtYLzd5qvjoXUMS6f+fHZf 0KzbhFWuyyAS3WSQdClA1s+dI1A+sXkx62vowcvQlU5MVlAdRhsxEhYcXOu7T2yyZ69P GHkIencv+imj9SztZ641XPVL9EZQAHmrqRb5en8DUo86WEfbC/WmZrgx76/bxkUD43Jw 5F5w== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:arc-authentication-results; bh=wDRhXZkOIOgjYNmM4DXNswS/SqC2CImhSrc7HV+i8fQ=; b=ylAmzpFlnbde9iJ3isAy6f6eAE0AFZsE54rZOOPsmhV2CaMlUGeGe2jfE4p2dQ1Ffk UaqifwKfcNqKeNUjw5liD3ghnvYOkgIasTxz5vRJj/mh+7d3c6pHNSaN6lrvvuHL0YK+ DhEVPKcP4D0hykNR6CV62tdPbeDa73b3aTPy2W/Q4mTSEZYaHT7Ez1SAgKdUM+COXQNb x7Xpt748Jz9dMojQsDIiKwSF7v/9d9SMLfoJzNXW7i5G5YAS65Hvotz74pswhnVxN+tS Yw5RTE5QR+LyD+dWumbc2l4njctJLi4GuGUIXeawTjSzL4E9YqzWe85oKJkubw5sA+QD Ouuw== 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; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=redhat.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id 38-v6si6562703pld.47.2018.03.12.13.19.39; Mon, 12 Mar 2018 13:19:54 -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; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=redhat.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932457AbeCLUQL (ORCPT + 99 others); Mon, 12 Mar 2018 16:16:11 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:56208 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S932365AbeCLUQK (ORCPT ); Mon, 12 Mar 2018 16:16:10 -0400 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.rdu2.redhat.com [10.11.54.3]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 6E028406E8B9; Mon, 12 Mar 2018 20:16:09 +0000 (UTC) Received: from llong.com (dhcp-17-75.bos.redhat.com [10.18.17.75]) by smtp.corp.redhat.com (Postfix) with ESMTP id 289271102E22; Mon, 12 Mar 2018 20:16:09 +0000 (UTC) From: Waiman Long To: "Luis R. Rodriguez" , Kees Cook Cc: linux-kernel@vger.kernel.org, linux-fsdevel@vger.kernel.org, Andrew Morton , Al Viro , Matthew Wilcox , Waiman Long Subject: [PATCH v4 3/6] sysctl: Warn when a clamped sysctl parameter is set out of range Date: Mon, 12 Mar 2018 16:15:41 -0400 Message-Id: <1520885744-1546-4-git-send-email-longman@redhat.com> In-Reply-To: <1520885744-1546-1-git-send-email-longman@redhat.com> References: <1520885744-1546-1-git-send-email-longman@redhat.com> X-Scanned-By: MIMEDefang 2.78 on 10.11.54.3 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.7]); Mon, 12 Mar 2018 20:16:09 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.7]); Mon, 12 Mar 2018 20:16:09 +0000 (UTC) for IP:'10.11.54.3' DOMAIN:'int-mx03.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'longman@redhat.com' RCPT:'' Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Even with clamped sysctl parameters, it is still not that straight forward to figure out the exact range of those parameters. One may try to write extreme parameter values to see if they get clamped. To make it easier, a warning with the expected range will now be printed into the kernel ring buffer when a clamped sysctl parameter receives an out of range value. The pr_warn_ratelimited() macro is used to limit the number of warning messages that can be printed within a given period of time. Signed-off-by: Waiman Long --- kernel/sysctl.c | 48 ++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 40 insertions(+), 8 deletions(-) diff --git a/kernel/sysctl.c b/kernel/sysctl.c index 3d65f41..14aca92 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c @@ -2505,6 +2505,7 @@ static int proc_dointvec_minmax_sysadmin(struct ctl_table *table, int write, * @min: pointer to minimum allowable value * @max: pointer to maximum allowable value * @flags: pointer to flags + * @name: sysctl parameter name * * The do_proc_dointvec_minmax_conv_param structure provides the * minimum and maximum values for doing range checking for those sysctl @@ -2514,31 +2515,48 @@ struct do_proc_dointvec_minmax_conv_param { int *min; int *max; unsigned int *flags; + const char *name; }; +#ifdef pr_fmt +#undef pr_fmt +#endif +#define pr_fmt(fmt) "sysctl: " fmt + static int do_proc_dointvec_minmax_conv(bool *negp, unsigned long *lvalp, int *valp, int write, void *data) { struct do_proc_dointvec_minmax_conv_param *param = data; + if (write) { int val = *negp ? -*lvalp : *lvalp; + bool clamped = false; bool clamp = param->flags && (*param->flags & CTL_FLAGS_CLAMP_RANGE); if (param->min && *param->min > val) { - if (clamp) + if (clamp) { val = *param->min; - else + clamped = true; + } else { return -EINVAL; + } } if (param->max && *param->max < val) { - if (clamp) + if (clamp) { val = *param->max; - else + clamped = true; + } else { return -EINVAL; + } } *valp = val; + if (clamped && param->name) + pr_warn_ratelimited("\"%s\" was set out of range [%d, %d], clamped to %d.\n", + param->name, + param->min ? *param->min : -INT_MAX, + param->max ? *param->max : INT_MAX, val); } else { int val = *valp; if (val < 0) { @@ -2576,6 +2594,7 @@ int proc_dointvec_minmax(struct ctl_table *table, int write, .min = (int *) table->extra1, .max = (int *) table->extra2, .flags = &table->flags, + .name = table->procname, }; return do_proc_dointvec(table, write, buffer, lenp, ppos, do_proc_dointvec_minmax_conv, ¶m); @@ -2586,6 +2605,7 @@ int proc_dointvec_minmax(struct ctl_table *table, int write, * @min: pointer to minimum allowable value * @max: pointer to maximum allowable value * @flags: pointer to flags + * @name: sysctl parameter name * * The do_proc_douintvec_minmax_conv_param structure provides the * minimum and maximum values for doing range checking for those sysctl @@ -2595,6 +2615,7 @@ struct do_proc_douintvec_minmax_conv_param { unsigned int *min; unsigned int *max; unsigned int *flags; + const char *name; }; static int do_proc_douintvec_minmax_conv(unsigned long *lvalp, @@ -2605,6 +2626,7 @@ static int do_proc_douintvec_minmax_conv(unsigned long *lvalp, if (write) { unsigned int val = *lvalp; + bool clamped = false; bool clamp = param->flags && (*param->flags & CTL_FLAGS_CLAMP_RANGE); @@ -2612,18 +2634,27 @@ static int do_proc_douintvec_minmax_conv(unsigned long *lvalp, return -EINVAL; if (param->min && *param->min > val) { - if (clamp) + if (clamp) { val = *param->min; - else + clamped = true; + } else { return -ERANGE; + } } if (param->max && *param->max < val) { - if (clamp) + if (clamp) { val = *param->max; - else + clamped = true; + } else { return -ERANGE; + } } *valp = val; + if (clamped && param->name) + pr_warn_ratelimited("\"%s\" was set out of range [%u, %u], clamped to %u.\n", + param->name, + param->min ? *param->min : 0, + param->max ? *param->max : UINT_MAX, val); } else { unsigned int val = *valp; *lvalp = (unsigned long) val; @@ -2659,6 +2690,7 @@ int proc_douintvec_minmax(struct ctl_table *table, int write, .min = (unsigned int *) table->extra1, .max = (unsigned int *) table->extra2, .flags = &table->flags, + .name = table->procname, }; return do_proc_douintvec(table, write, buffer, lenp, ppos, do_proc_douintvec_minmax_conv, ¶m); -- 1.8.3.1