The commit is pushed to "branch-rh7-3.10.0-327.36.1.vz7.20.x-ovz" and will 
appear at https://src.openvz.org/scm/ovz/vzkernel.git
after rh7-3.10.0-327.36.1.vz7.20.11
------>
commit e8993d723121f3d9303db373849bcd01df2def48
Author: Philip Pettersson <[email protected]>
Date:   Wed Nov 30 14:55:36 2016 -0800

    ms/packet: fix race condition in packet_set_ring
    
    When packet_set_ring creates a ring buffer it will initialize a
    struct timer_list if the packet version is TPACKET_V3. This value
    can then be raced by a different thread calling setsockopt to
    set the version to TPACKET_V1 before packet_set_ring has finished.
    
    This leads to a use-after-free on a function pointer in the
    struct timer_list when the socket is closed as the previously
    initialized timer will not be deleted.
    
    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.
    
    Fixes: f6fb8f100b80 ("af-packet: TPACKET_V3 flexible buffer 
implementation.")
    Signed-off-by: Philip Pettersson <[email protected]>
    Signed-off-by: Eric Dumazet <[email protected]>
    Signed-off-by: David S. Miller <[email protected]>
    
    ============================================================
    CVE-2016-8655: Linux af_packet.c race condition (local root)
    
    Philip Pettersson discovered a race condition in the af_packet 
implementation
    in the Linux kernel. A local unprivileged attacker could use this to cause a
    denial of service (system crash) or run arbitrary code with administrative
    privileges.
    
    https://jira.sw.ru/browse/PSBM-56699
---
 net/packet/af_packet.c | 18 ++++++++++++------
 1 file changed, 12 insertions(+), 6 deletions(-)

diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
index 2a1b15a..0e662e3 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -3313,19 +3313,25 @@ packet_setsockopt(struct socket *sock, int level, int 
optname, char __user *optv
 
                if (optlen != sizeof(val))
                        return -EINVAL;
-               if (po->rx_ring.pg_vec || po->tx_ring.pg_vec)
-                       return -EBUSY;
                if (copy_from_user(&val, optval, sizeof(val)))
                        return -EFAULT;
                switch (val) {
                case TPACKET_V1:
                case TPACKET_V2:
                case TPACKET_V3:
-                       po->tp_version = val;
-                       return 0;
+                       break;
                default:
                        return -EINVAL;
                }
+               lock_sock(sk);
+               if (po->rx_ring.pg_vec || po->tx_ring.pg_vec) {
+                       ret = -EBUSY;
+               } else {
+                       po->tp_version = val;
+                       ret = 0;
+               }
+               release_sock(sk);
+               return ret;
        }
        case PACKET_RESERVE:
        {
@@ -3781,6 +3787,7 @@ static int packet_set_ring(struct sock *sk, union 
tpacket_req_u *req_u,
        /* Added to avoid minimal code churn */
        struct tpacket_req *req = &req_u->req;
 
+       lock_sock(sk);
        /* Opening a Tx-ring is NOT supported in TPACKET_V3 */
        if (!closing && tx_ring && (po->tp_version > TPACKET_V2)) {
                WARN(1, "Tx-ring is not supported.\n");
@@ -3869,7 +3876,6 @@ static int packet_set_ring(struct sock *sk, union 
tpacket_req_u *req_u,
                        goto out;
        }
 
-       lock_sock(sk);
 
        /* Detach socket from network */
        spin_lock(&po->bind_lock);
@@ -3918,7 +3924,6 @@ static int packet_set_ring(struct sock *sk, union 
tpacket_req_u *req_u,
                if (!tx_ring)
                        prb_shutdown_retire_blk_timer(po, tx_ring, rb_queue);
        }
-       release_sock(sk);
 
        if (pg_vec) {
                if (psc)
@@ -3927,6 +3932,7 @@ static int packet_set_ring(struct sock *sk, union 
tpacket_req_u *req_u,
                free_pg_vec(pg_vec, order, req->tp_block_nr);
        }
 out:
+       release_sock(sk);
        return err;
 }
 
_______________________________________________
Devel mailing list
[email protected]
https://lists.openvz.org/mailman/listinfo/devel

Reply via email to