diff options
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/sysctl.c | 59 |
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; |