sysctl: fix int -> unsigned long assignments in INT_MIN case
authorIlya Dryomov <[email protected]>
Wed, 9 Sep 2015 22:39:06 +0000 (15:39 -0700)
committerLinus Torvalds <[email protected]>
Thu, 10 Sep 2015 20:29:01 +0000 (13:29 -0700)
commit9a5bc726d559221a3394bb8ef97d0abc1ee94d00
tree8d6bcc02409b4754e9641488b03599b28af8e6e4
parent1303a27c9c32020a3b6ac89be270d2ab1f28be24
sysctl: fix int -> unsigned long assignments in INT_MIN case

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]>
kernel/sysctl.c