Re: Signedness bug in sctp_setsockopt() (security vulnerability).

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



SCTP_SOCKOPT_DEBUG_NAME is an internal option that was supposed to be used
only by the developers of SCTP, not users. Even the developers found that
this isn't really needed and hence this option was removed in 2.4.26 and
also from the 2.6 tree.

As Shaun pointed out, if this code was present it could have been a security
issue, but as the code is no longer present, this is a non-issue.

Thanks
Sridhar

On Sat, 8 May 2004, Shaun Colley wrote:

> Hi guys,
>
> After skipping through some of the SCTP Linux Kernel
> net code, I discovered what appears to be a signedness
> bug, potentially allowing overwriting of kernel memory
> - thus presenting a security vulnerability.
>
> Please note that this issue is present in 2.4.25, but
> I think the socket option vulnerable was for some
> reason removed in the 2.4.26 patch.  I've only really
> checked 2.4.25 for this.
>
> The issue presents itself in net/sctp/socket.c in the
> source tree:
>
> --- net/sctp/socket.c ---
> SCTP_STATIC int sctp_setsockopt(struct sock *sk, int
> level, int optname,
>                                 char *optval, int
> optlen)
> {
>         int retval = 0;
>         char *tmp;
>
>         SCTP_DEBUG_PRINTK("sctp_setsockopt(sk: %p...
> optname: %d)\n",
>                           sk, optname);
>
>
> [ ... ]
>
>  switch (optname) {
>         case SCTP_SOCKOPT_DEBUG_NAME:
>                 /* BUG! we don't ever seem to free
> this memory. --jgrimm */
>                 if (NULL == (tmp = kmalloc(optlen + 1,
> GFP_KERNEL))) {
>                         retval = -ENOMEM;
>                         goto out_unlock;
>                 }
>
>                 if (copy_from_user(tmp, optval,
> optlen)) {
>                         retval = -EFAULT;
>                         goto out_unlock;
>                 }
>                 tmp[optlen] = '\000';
>                 sctp_sk(sk)->ep->debug_name = tmp;
>                 break;
>
> [ ... ]
>
> --- EO snippet ---
>
> >From the code above, we can see that the 'optname'
> variable passed to sctp_setsockopt() is parsed, and
> should the option be 'SCTP_SOCKOPT_DEBUG_NAME', the
> above code is ran.  Notice, from the declaration of
> sctp_setsockopt(), 'optlen' is an integer variable,
> and remains unsanitised or checked throughout the
> entire function.  Now, here is where the bug
> manifests:
>
> ---
> if (NULL == (tmp = kmalloc(optlen + 1, GFP_KERNEL))) {
>                         retval = -ENOMEM;
>                         goto out_unlock;
>                 }
> ---
>
> As I can recall, kmalloc takes the size of memory to
> be allocated as an unsigned int, and due to the lack
> of checks on 'optlen' passed by the user, HUGE numbers
> could end up being interpreted by kmalloc() if a
> negative integer is passed to sctp_setsockopt() in the
> 'optlen' variable.  Of course, kmalloc() would fail,
> because such a large amount of memory cannot be
> allocated.  However, with a bit of thinking, it is
> easy to remember that the signed integer '-1' is
> represented as 0xffffffff by unsigned variables - and
> this is the maximum number representable by unsigned
> integers (at least on my hardware).  All would be
> well, except for the fact that 'optlen + 1' is infact
> allocated.  This, in itself, is a major flaw;
>
> What if -1 is passed to sctp_setsockopt() as optlen?
> Let's do the calculation:
>
> (optlen = -1)
>
> -1 will be represented as 0xffffffff by unsigned ints,
> thus the equivalent of this kmalloc() call is invoked
> (assuming optlen = -1):
>
> (kmalloc(0xffffffff + 1, GFP_KERNEL) )
>
> However, this will cause the maximum value
> representable by an unsigned integer variable to be
> exceeded, causing the value to wrap around - to 0.
> Thus, we now have the equivalent of the below
> kmalloc() call:
>
> kmalloc(0x0, GFP_KERNEL)
>
>
> Hence, 0 bytes are attempted to be allocated (however,
> around 32 bytes will probably be allocated, if I
> remember correctly).
>
>
> Now, assuming the kmalloc() call succeeded, a
> copy_from_user call is invoked:
>
> ---
> copy_from_user(tmp, optval, optlen)
> ---
>
> Assuming we did infact pass -1 to optlen when calling
> the sctp_setsockopt() function, we have a
> copy_from_user call looking like this:
>
> ---
> copy_from_user(tmp, optval, 0xffffffff)
> ---
>
> Of course, a would-be attacker is unlikely to pass
> 0xffffffff bytes to the function (as optval), but due
> to the nature of copy_from_user, copying will be
> performed until the end of the data is reached.
>
>
> >From my sloppy explanations above, the vulnerability
> should be apparent: by exploiting the signedness
> bug/sanity check bug above, an amount of memory LESS
> than the length of 'optval' can be allocated - thus
> causing writing into unallocated kernel memory.  If I
> haven't fudged up, this is most probably a security
> issue in itself.  Does anyone agree?  Please note that
> this bug only manifests when parsing and acting upon
> the SCTP_SOCKOPT_DEBUG_NAME sctp socket option!
>
> By the way, please note that I HAVEN'T actually tested
> this issue on my system, because I forgot to compile
> SCTP support into my kernel.  However, it should be
> pretty simple for all of you SCTP experts out there.
> A small example snippet:
>
> --- test.c ---
> [ ... ]
>
> char buf[200];
> memset(buf, 'a', sizeof(buf));
>
> sctp_setsockopt(sock, SOL_SCTP,
> SCTP_SOCKOPT_DEBUG_NAME, &buf, -1);
>
> [ ... ]
>
> --- EOF ---
>
>
> Due to the fact that I haven't had the resources to
> test the impact of the issue, I am posting here for
> discussion of the bug, if it actually exists.  If I
> have made a mistake, or sanity checks are performed
> somewhere earlier down the line, please let me know
> kindly.  Other than that, just by auditing the code,
> it looks to me like a definite security hole.  Does
> anyone else agree?
>
>
>
> Thank you for your time.
> Shaun.
>
>
>
>
>
>
>
>
>
>
>
> ____________________________________________________________
> Yahoo! Messenger - Communicate instantly..."Ping"
> your friends today! Download Messenger Now
> http://uk.messenger.yahoo.com/download/index.html
> -
> : send the line "unsubscribe linux-net" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>
-
: send the line "unsubscribe linux-net" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Netdev]     [Ethernet Bridging]     [Linux 802.1Q VLAN]     [Linux Wireless]     [Kernel Newbies]     [Security]     [Linux for Hams]     [Netfilter]     [Git]     [Bugtraq]     [Yosemite News and Information]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux PCI]     [Linux Admin]     [Samba]

  Powered by Linux