af_iucv and potentially buggy use of sk_filter()

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

 



Hi folks,

during an audit of sk_filter() users, I stumbled upon af_iucv, where
I suppose some weird things are going on when socket filters are
attached to an af_iucv socket (f.e. setsockopt() with SO_ATTACH_FILTER).

You have three invocation of sock_queue_rcv_skb():

*** iucv_process_message():

    [...]
    IUCV_SKB_CB(skb)->offset = 0;
    if (sock_queue_rcv_skb(sk, skb))
        skb_queue_head(&iucv_sk(sk)->backlog_skb_q, skb);
    [...]

*** iucv_sock_recvmsg():

    [...]
    spin_lock_bh(&iucv->message_q.lock);
    rskb = skb_dequeue(&iucv->backlog_skb_q);
    while (rskb) {
        IUCV_SKB_CB(rskb)->offset = 0;
        if (sock_queue_rcv_skb(sk, rskb)) {
            skb_queue_head(&iucv->backlog_skb_q, rskb);
            break;
        } else {
            rskb = skb_dequeue(&iucv->backlog_skb_q);
        }
    }
    [...]
    spin_unlock_bh(&iucv->message_q.lock);
    [...]

**** afiucv_hs_callback_rx():

    [...]
    spin_lock(&iucv->message_q.lock);
    if (skb_queue_empty(&iucv->backlog_skb_q)) {
        if (sock_queue_rcv_skb(sk, skb)) {
            /* handle rcv queue full */
            skb_queue_tail(&iucv->backlog_skb_q, skb);
        }
    } else
            skb_queue_tail(&iucv_sk(sk)->backlog_skb_q, skb);
    spin_unlock(&iucv->message_q.lock);
    return NET_RX_SUCCESS;
    [...]

As you probably know, sock_queue_rcv_skb() calls into sk_filter(),
then into __sock_queue_rcv_skb() for actual queuing. Now, when for
example a cBPF filter is attached where some path of it ends up with ...

    { 0x06,  0,  0, 0x00000000 },  // ret K   (K := 0)

... is attached, for example, then due to return code 0, it means
skb will be tossed, and as a result sk_filter() will return -EPERM.

In all above cases, this means sock_queue_rcv_skb() will return a
non-0 code, and thus you either re-queue the skb to the head or tail
of the backlog queue. So, in case of head, no matter what other skbs
come in, the previous 'to-be-dropped' skb will be dequeued and put
back again into the backlog queue's head. tail case, well, it will
probably let the skb linger in that queue until socket destruction.

What you probably meant for all three is to just call __sock_queue_rcv_skb()
and place a sk_filter() call to some safe to use location or so.
Please have a look / fix at this, if I'm not mistaken.

Thanks,
Daniel
--
To unsubscribe from this list: send the line "unsubscribe linux-s390" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [Kernel Development]     [Kernel Newbies]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite Info]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Samba]     [Linux Media]     [Device Mapper]

  Powered by Linux