The patch titled Subject: kernel/sysctl.c: define minmax conv functions in terms of non-minmax versions has been added to the -mm tree. Its filename is kernel-sysctlc-define-minmax-conv-functions-in-terms-of-non-minmax-versions.patch This patch should soon appear at http://ozlabs.org/~akpm/mmots/broken-out/kernel-sysctlc-define-minmax-conv-functions-in-terms-of-non-minmax-versions.patch and later at http://ozlabs.org/~akpm/mmotm/broken-out/kernel-sysctlc-define-minmax-conv-functions-in-terms-of-non-minmax-versions.patch Before you just go and hit "reply", please: a) Consider who else should be cc'ed b) Prefer to cc a suitable mailing list as well c) Ideally: find the original patch on the mailing list and do a reply-to-all to that, adding suitable additional cc's *** Remember to use Documentation/process/submit-checklist.rst when testing your code *** The -mm tree is included into linux-next and is updated there every 3-4 working days ------------------------------------------------------ From: Zev Weiss <zev@xxxxxxxxxxxxxxxxx> Subject: kernel/sysctl.c: define minmax conv functions in terms of non-minmax versions do_proc_do[u]intvec_minmax_conv() had included open-coded versions of do_proc_do[u]intvec_conv(); the duplication led to buggy inconsistencies (missing range checks). To reduce the likelihood of such problems in the future, we can instead refactor both to be defined in terms of their non-bounded counterparts (plus the added check). Link: http://lkml.kernel.org/r/20190207165138.5oud57vq4ozwb4kh@xxxxxxxxxxxxxxxxxxxxxxxx Signed-off-by: Zev Weiss <zev@xxxxxxxxxxxxxxxxx> Cc: Brendan Higgins <brendanhiggins@xxxxxxxxxx> Cc: Iurii Zaikin <yzaikin@xxxxxxxxxx> Cc: Kees Cook <keescook@xxxxxxxxxxxx> Cc: Luis Chamberlain <mcgrof@xxxxxxxxxx> Signed-off-by: Andrew Morton <akpm@xxxxxxxxxxxxxxxxxxxx> --- --- a/kernel/sysctl.c~kernel-sysctlc-define-minmax-conv-functions-in-terms-of-non-minmax-versions +++ a/kernel/sysctl.c @@ -2577,32 +2577,25 @@ static int do_proc_dointvec_minmax_conv( int *valp, int write, void *data) { + int tmp, ret; struct do_proc_dointvec_minmax_conv_param *param = data; + /* + * If writing, first do so via a temporary local int so we can + * bounds-check it before touching *valp. + */ + int *ip = write ? &tmp : valp; + + ret = do_proc_dointvec_conv(negp, lvalp, ip, write, data); + if (ret) + return ret; + if (write) { - int val; - if (*negp) { - if (*lvalp > (unsigned long) INT_MAX + 1) - return -EINVAL; - val = -*lvalp; - } else { - if (*lvalp > (unsigned long) INT_MAX) - return -EINVAL; - val = *lvalp; - } - if ((param->min && *param->min > val) || - (param->max && *param->max < val)) + if ((param->min && *param->min > tmp) || + (param->max && *param->max < tmp)) return -EINVAL; - *valp = val; - } else { - int val = *valp; - if (val < 0) { - *negp = true; - *lvalp = -(unsigned long)val; - } else { - *negp = false; - *lvalp = (unsigned long)val; - } + *valp = tmp; } + return 0; } @@ -2651,22 +2644,22 @@ static int do_proc_douintvec_minmax_conv unsigned int *valp, int write, void *data) { + int ret; + unsigned int tmp; struct do_proc_douintvec_minmax_conv_param *param = data; + /* write via temporary local uint for bounds-checking */ + unsigned int *up = write ? &tmp : valp; - if (write) { - unsigned int val = *lvalp; - - if (*lvalp > UINT_MAX) - return -EINVAL; + ret = do_proc_douintvec_conv(lvalp, up, write, data); + if (ret) + return ret; - if ((param->min && *param->min > val) || - (param->max && *param->max < val)) + if (write) { + if ((param->min && *param->min > tmp) || + (param->max && *param->max < tmp)) return -ERANGE; - *valp = val; - } else { - unsigned int val = *valp; - *lvalp = (unsigned long) val; + *valp = tmp; } return 0; _ Patches currently in -mm which might be from zev@xxxxxxxxxxxxxxxxx are test_sysctl-add-tests-for-32-bit-values-written-to-32-bit-integers.patch kernel-sysctlc-add-missing-range-check-in-do_proc_dointvec_minmax_conv.patch kernel-sysctlc-define-minmax-conv-functions-in-terms-of-non-minmax-versions.patch