SecurityTracker.com
Keep Track of the Latest Vulnerabilities
with SecurityTracker!
    Home    |    View Topics    |    Search    |    Contact Us    |   

SecurityTracker
Archives


 
Sign Up
Sign Up for Your FREE Weekly SecurityTracker E-mail Alert Summary
Instant Alerts
Buy our Premium Vulnerability Notification Service to receive customized, instant alerts
Affiliates
Put SecurityTracker Vulnerability Alerts on Your Web Site -- It's Free!
Partners
Become a Partner and License Our Database or Notification Service





Category:   OS (Linux)  >   Linux Kernel Vendors:   kernel.org
Linux Kernel packet_set_ring() Race Condition Lets Local Users Obtain Root Privileges
SecurityTracker Alert ID:  1037403
SecurityTracker URL:  http://securitytracker.com/id/1037403
CVE Reference:   CVE-2016-8655   (Links to External Site)
Date:  Dec 8 2016
Impact:   Execution of arbitrary code via local system, Root access via local system
Fix Available:  Yes  Vendor Confirmed:  Yes  

Description:   A vulnerability was reported in the Linux kernel. A local user can obtain root privileges on the target system.

A local user that can create AF_PACKET sockets can trigger a race condition and use-after-free memory error in packet_set_ring() to execute arbitrary code on the target system with root privileges.

Philip Pettersson reported this vulnerability.

Impact:   A local user can obtain root privileges on the target system.
Solution:   The vendor has issued a source code fix, available at:

https://github.com/torvalds/linux/commit/f6fb8f100b807378fda19e83e5ac6828b638603a

Vendor URL:  www.kernel.org/ (Links to External Site)
Cause:   Access control error, State error

Message History:   None.


 Source Message Contents

Subject:  [oss-security] CVE-2016-8655 Linux af_packet.c race condition (local root)

Hello,

This is an announcement about CVE-2016-8655 which is a race-condition
I found in Linux (net/packet/af_packet.c). It can be exploited to gain
kernel code execution from unprivileged processes.

The bug was introduced on Aug 19, 2011:
https://github.com/torvalds/linux/commit/f6fb8f100b807378fda19e83e5ac6828b638603a

Fixed on Nov 30, 2016:
https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=84ac7260236a49c79eede91617700174c2c19b0c

=*=*=*=*=*=*=*=*=   BUG DETAILS  =*=*=*=*=*=*=*=*=

To create AF_PACKET sockets you need CAP_NET_RAW in your network
namespace, which can be acquired by unprivileged processes on
systems where unprivileged namespaces are enabled (Ubuntu, Fedora, etc).
It can be triggered from within containers to compromise the host kernel.
On Android, processes with gid=3004/AID_NET_RAW are able to create
AF_PACKET sockets (mediaserver) and can trigger the bug.

I found the bug by reading code paths that have been opened up by the
emergence of unprivileged namespaces, something I think should be
off by default in all Linux distributions given its history of
security vulnerabilities.

The problem is inside packet_set_ring() and packet_setsockopt().
We can reach packet_set_ring() by calling setsockopt() on the socket
using the PACKET_RX_RING option.

If the version of the packet socket is TPACKET_V3, a timer_list
object will be initialized by packet_set_ring() when it calls
init_prb_bdqc().

...
                switch (po->tp_version) {
                case TPACKET_V3:
                /* Transmit path is not supported. We checked
                 * it above but just being paranoid
                 */
                        if (!tx_ring)
                                init_prb_bdqc(po, rb, pg_vec, req_u);
                        break;
                default:
                        break;
                }
...

The function flow to set up the timer is:
packet_set_ring()->init_prb_bdqc()->prb_setup_retire_blk_timer()->
prb_init_blk_timer()->prb_init_blk_timer()->init_timer()

When the socket is closed, packet_set_ring() is called again
to free the ring buffer and delete the previously initialized
timer if the packet version is > TPACKET_V2:

...
        if (closing && (po->tp_version > TPACKET_V2)) {
                /* Because we don't support block-based V3 on tx-ring */
                if (!tx_ring)
                        prb_shutdown_retire_blk_timer(po, rb_queue);
        }
...

The issue is that we can change the packet version to TPACKET_V1
with packet_setsockopt() after init_prb_bdqc() has been executed
and before packet_set_ring() has returned.

There is an attempt to deny changing socket versions after a ring
buffer has been initialized, but it is insufficient:

...
        case PACKET_VERSION:
        {
...
                if (po->rx_ring.pg_vec || po->tx_ring.pg_vec)
                        return -EBUSY;
...

There's plenty of room to race this code path between the calls to
init_prb_bdqc() and swap(rb->pg_vec, pg_vec) in packet_set_ring().

When the socket is closed, packet_set_ring() will not delete the
timer since the socket version is now TPACKET_V1. The struct
timer_list that describes the timer object is located inside the
struct packet_sock for the socket itself however and will be
freed with a call to kfree().

We then have a use-after-free on a timer object that can be
exploited by various poisoning attacks on the SLAB allocator (I find
add_key() to be the most reliable). This will ultimately lead to the
kernel jumping to a manipulated function pointer when the timer expires.

The bug is fixed by taking lock_sock(sk) in packet_setsockopt() when
changing the packet version while also taking the lock at the start
of packet_set_ring().

My exploit defeats SMEP/SMAP and will give a rootshell on Ubuntu 16.04,
I will hold off a day on publishing it so people have some time to update.

New Ubuntu kernels are out so please update as soon as possible.

=*=*=*=*=*=*=*=*=    TIMELINE    =*=*=*=*=*=*=*=*=

2016-11-28: Bug reported to security@kernel.org
2016-11-30: Patch submitted to netdev, notification sent to linux-distros
2016-12-02: Patch committed to mainline kernel
2016-12-06: Public announcement

=*=*=*=*=*=*=*=*=     LINKS      =*=*=*=*=*=*=*=*=

https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2016-8655
https://github.com/torvalds/linux/commit/f6fb8f100b807378fda19e83e5ac6828b638603a
https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=84ac7260236a49c79eede91617700174c2c19b0c
https://www.ubuntu.com/usn/usn-3151-1/

=*=*=*=*=*=*=*=*=     CREDIT     =*=*=*=*=*=*=*=*=

Philip Pettersson
 
 


Go to the Top of This SecurityTracker Archive Page





Home   |    View Topics   |    Search   |    Contact Us

This web site uses cookies for web analytics. Learn More

Copyright 2018, SecurityGlobal.net LLC