Skip to content

Commit

Permalink
sysctl: fix int -> unsigned long assignments in INT_MIN case
Browse files Browse the repository at this point in the history
The following

    if (val < 0)
        *lvalp = (unsigned long)-val;

is incorrect because the compiler is free to assume -val to be positive
and use a sign-extend instruction for extending the bit pattern.  This is
a problem if val == INT_MIN:

    # echo -2147483648 >/proc/sys/dev/scsi/logging_level
    # cat /proc/sys/dev/scsi/logging_level
    -18446744071562067968

Cast to unsigned long before negation - that way we first sign-extend and
then negate an unsigned, which is well defined.  With this:

    # cat /proc/sys/dev/scsi/logging_level
    -2147483648

Signed-off-by: Ilya Dryomov <[email protected]>
Cc: Mikulas Patocka <[email protected]>
Cc: Robert Xiao <[email protected]>
Cc: "Eric W. Biederman" <[email protected]>
Cc: Kees Cook <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
  • Loading branch information
idryomov authored and torvalds committed Sep 10, 2015
1 parent 1303a27 commit 9a5bc72
Showing 1 changed file with 5 additions and 5 deletions.
10 changes: 5 additions & 5 deletions kernel/sysctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -1995,7 +1995,7 @@ static int do_proc_dointvec_conv(bool *negp, unsigned long *lvalp,
int val = *valp;
if (val < 0) {
*negp = true;
*lvalp = (unsigned long)-val;
*lvalp = -(unsigned long)val;
} else {
*negp = false;
*lvalp = (unsigned long)val;
Expand Down Expand Up @@ -2201,7 +2201,7 @@ static int do_proc_dointvec_minmax_conv(bool *negp, unsigned long *lvalp,
int val = *valp;
if (val < 0) {
*negp = true;
*lvalp = (unsigned long)-val;
*lvalp = -(unsigned long)val;
} else {
*negp = false;
*lvalp = (unsigned long)val;
Expand Down Expand Up @@ -2436,7 +2436,7 @@ static int do_proc_dointvec_jiffies_conv(bool *negp, unsigned long *lvalp,
unsigned long lval;
if (val < 0) {
*negp = true;
lval = (unsigned long)-val;
lval = -(unsigned long)val;
} else {
*negp = false;
lval = (unsigned long)val;
Expand All @@ -2459,7 +2459,7 @@ static int do_proc_dointvec_userhz_jiffies_conv(bool *negp, unsigned long *lvalp
unsigned long lval;
if (val < 0) {
*negp = true;
lval = (unsigned long)-val;
lval = -(unsigned long)val;
} else {
*negp = false;
lval = (unsigned long)val;
Expand All @@ -2484,7 +2484,7 @@ static int do_proc_dointvec_ms_jiffies_conv(bool *negp, unsigned long *lvalp,
unsigned long lval;
if (val < 0) {
*negp = true;
lval = (unsigned long)-val;
lval = -(unsigned long)val;
} else {
*negp = false;
lval = (unsigned long)val;
Expand Down

0 comments on commit 9a5bc72

Please sign in to comment.