aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'kernel')
-rw-r--r--kernel/sysctl.c59
1 files changed, 26 insertions, 33 deletions
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index 0854197e0e67..e5da394d1ca3 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -2643,32 +2643,25 @@ static int do_proc_dointvec_minmax_conv(bool *negp, unsigned long *lvalp,
2643 int *valp, 2643 int *valp,
2644 int write, void *data) 2644 int write, void *data)
2645{ 2645{
2646 int tmp, ret;
2646 struct do_proc_dointvec_minmax_conv_param *param = data; 2647 struct do_proc_dointvec_minmax_conv_param *param = data;
2648 /*
2649 * If writing, first do so via a temporary local int so we can
2650 * bounds-check it before touching *valp.
2651 */
2652 int *ip = write ? &tmp : valp;
2653
2654 ret = do_proc_dointvec_conv(negp, lvalp, ip, write, data);
2655 if (ret)
2656 return ret;
2657
2647 if (write) { 2658 if (write) {
2648 int val; 2659 if ((param->min && *param->min > tmp) ||
2649 if (*negp) { 2660 (param->max && *param->max < tmp))
2650 if (*lvalp > (unsigned long) INT_MAX + 1)
2651 return -EINVAL;
2652 val = -*lvalp;
2653 } else {
2654 if (*lvalp > (unsigned long) INT_MAX)
2655 return -EINVAL;
2656 val = *lvalp;
2657 }
2658 if ((param->min && *param->min > val) ||
2659 (param->max && *param->max < val))
2660 return -EINVAL; 2661 return -EINVAL;
2661 *valp = val; 2662 *valp = tmp;
2662 } else {
2663 int val = *valp;
2664 if (val < 0) {
2665 *negp = true;
2666 *lvalp = -(unsigned long)val;
2667 } else {
2668 *negp = false;
2669 *lvalp = (unsigned long)val;
2670 }
2671 } 2663 }
2664
2672 return 0; 2665 return 0;
2673} 2666}
2674 2667
@@ -2717,22 +2710,22 @@ static int do_proc_douintvec_minmax_conv(unsigned long *lvalp,
2717 unsigned int *valp, 2710 unsigned int *valp,
2718 int write, void *data) 2711 int write, void *data)
2719{ 2712{
2713 int ret;
2714 unsigned int tmp;
2720 struct do_proc_douintvec_minmax_conv_param *param = data; 2715 struct do_proc_douintvec_minmax_conv_param *param = data;
2716 /* write via temporary local uint for bounds-checking */
2717 unsigned int *up = write ? &tmp : valp;
2721 2718
2722 if (write) { 2719 ret = do_proc_douintvec_conv(lvalp, up, write, data);
2723 unsigned int val = *lvalp; 2720 if (ret)
2721 return ret;
2724 2722
2725 if (*lvalp > UINT_MAX) 2723 if (write) {
2726 return -EINVAL; 2724 if ((param->min && *param->min > tmp) ||
2727 2725 (param->max && *param->max < tmp))
2728 if ((param->min && *param->min > val) ||
2729 (param->max && *param->max < val))
2730 return -ERANGE; 2726 return -ERANGE;
2731 2727
2732 *valp = val; 2728 *valp = tmp;
2733 } else {
2734 unsigned int val = *valp;
2735 *lvalp = (unsigned long) val;
2736 } 2729 }
2737 2730
2738 return 0; 2731 return 0;