diff options
author | Xi Wang <xi.wang@gmail.com> | 2011-12-27 04:43:19 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2011-12-28 14:08:08 -0500 |
commit | ba1cffe0257bcd4d0070bc0e64f8ead97fefd148 (patch) | |
tree | 5584b7816f7eb46953611ec35628c6924ea5a2af | |
parent | fa84309533025eb3f03dc1d2d2be1c3ca206882a (diff) |
ax25: avoid overflows in ax25_setsockopt()
Commit be639ac6 ("NET: AX.25: Check ioctl arguments to avoid overflows
further down the road") rejects very large arguments, but doesn't
completely fix overflows on 64-bit systems. Consider the AX25_T2 case.
int opt;
...
if (opt < 1 || opt > ULONG_MAX / HZ) {
res = -EINVAL;
break;
}
ax25->t2 = opt * HZ;
The 32-bit multiplication opt * HZ would overflow before being assigned
to 64-bit ax25->t2. This patch changes "opt" to unsigned long.
Signed-off-by: Xi Wang <xi.wang@gmail.com>
Cc: Ralf Baechle <ralf@linux-mips.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | net/ax25/af_ax25.c | 11 |
1 files changed, 6 insertions, 5 deletions
diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c index b863c1877c80..3cd0a0dc91cb 100644 --- a/net/ax25/af_ax25.c +++ b/net/ax25/af_ax25.c | |||
@@ -545,15 +545,16 @@ static int ax25_setsockopt(struct socket *sock, int level, int optname, | |||
545 | ax25_cb *ax25; | 545 | ax25_cb *ax25; |
546 | struct net_device *dev; | 546 | struct net_device *dev; |
547 | char devname[IFNAMSIZ]; | 547 | char devname[IFNAMSIZ]; |
548 | int opt, res = 0; | 548 | unsigned long opt; |
549 | int res = 0; | ||
549 | 550 | ||
550 | if (level != SOL_AX25) | 551 | if (level != SOL_AX25) |
551 | return -ENOPROTOOPT; | 552 | return -ENOPROTOOPT; |
552 | 553 | ||
553 | if (optlen < sizeof(int)) | 554 | if (optlen < sizeof(unsigned int)) |
554 | return -EINVAL; | 555 | return -EINVAL; |
555 | 556 | ||
556 | if (get_user(opt, (int __user *)optval)) | 557 | if (get_user(opt, (unsigned int __user *)optval)) |
557 | return -EFAULT; | 558 | return -EFAULT; |
558 | 559 | ||
559 | lock_sock(sk); | 560 | lock_sock(sk); |
@@ -609,7 +610,7 @@ static int ax25_setsockopt(struct socket *sock, int level, int optname, | |||
609 | break; | 610 | break; |
610 | 611 | ||
611 | case AX25_IDLE: | 612 | case AX25_IDLE: |
612 | if (opt < 0 || opt > ULONG_MAX / (60 * HZ)) { | 613 | if (opt > ULONG_MAX / (60 * HZ)) { |
613 | res = -EINVAL; | 614 | res = -EINVAL; |
614 | break; | 615 | break; |
615 | } | 616 | } |
@@ -617,7 +618,7 @@ static int ax25_setsockopt(struct socket *sock, int level, int optname, | |||
617 | break; | 618 | break; |
618 | 619 | ||
619 | case AX25_BACKOFF: | 620 | case AX25_BACKOFF: |
620 | if (opt < 0 || opt > 2) { | 621 | if (opt > 2) { |
621 | res = -EINVAL; | 622 | res = -EINVAL; |
622 | break; | 623 | break; |
623 | } | 624 | } |