lkml.org 
[lkml]   [2010]   [Mar]   [30]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    Subject[138/156] netlink: fix NETLINK_RECV_NO_ENOBUFS in netlink_set_err()
    2.6.33-stable review patch.  If anyone has any objections, please let us know.

    ------------------

    From: Pablo Neira Ayuso <pablo@netfilter.org>

    [ Upstream commit 1a50307ba1826e4da0024e64b245ce4eadf7688a ]

    Currently, ENOBUFS errors are reported to the socket via
    netlink_set_err() even if NETLINK_RECV_NO_ENOBUFS is set. However,
    that should not happen. This fixes this problem and it changes the
    prototype of netlink_set_err() to return the number of sockets that
    have set the NETLINK_RECV_NO_ENOBUFS socket option. This return
    value is used in the next patch in these bugfix series.

    Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
    Signed-off-by: David S. Miller <davem@davemloft.net>
    Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

    ---
    include/linux/netlink.h | 2 +-
    net/netlink/af_netlink.c | 17 ++++++++++++++---
    2 files changed, 15 insertions(+), 4 deletions(-)

    --- a/include/linux/netlink.h
    +++ b/include/linux/netlink.h
    @@ -188,7 +188,7 @@ extern int netlink_has_listeners(struct
    extern int netlink_unicast(struct sock *ssk, struct sk_buff *skb, __u32 pid, int nonblock);
    extern int netlink_broadcast(struct sock *ssk, struct sk_buff *skb, __u32 pid,
    __u32 group, gfp_t allocation);
    -extern void netlink_set_err(struct sock *ssk, __u32 pid, __u32 group, int code);
    +extern int netlink_set_err(struct sock *ssk, __u32 pid, __u32 group, int code);
    extern int netlink_register_notifier(struct notifier_block *nb);
    extern int netlink_unregister_notifier(struct notifier_block *nb);

    --- a/net/netlink/af_netlink.c
    +++ b/net/netlink/af_netlink.c
    @@ -1093,6 +1093,7 @@ static inline int do_one_set_err(struct
    struct netlink_set_err_data *p)
    {
    struct netlink_sock *nlk = nlk_sk(sk);
    + int ret = 0;

    if (sk == p->exclude_sk)
    goto out;
    @@ -1104,10 +1105,15 @@ static inline int do_one_set_err(struct
    !test_bit(p->group - 1, nlk->groups))
    goto out;

    + if (p->code == ENOBUFS && nlk->flags & NETLINK_RECV_NO_ENOBUFS) {
    + ret = 1;
    + goto out;
    + }
    +
    sk->sk_err = p->code;
    sk->sk_error_report(sk);
    out:
    - return 0;
    + return ret;
    }

    /**
    @@ -1116,12 +1122,16 @@ out:
    * @pid: the PID of a process that we want to skip (if any)
    * @groups: the broadcast group that will notice the error
    * @code: error code, must be negative (as usual in kernelspace)
    + *
    + * This function returns the number of broadcast listeners that have set the
    + * NETLINK_RECV_NO_ENOBUFS socket option.
    */
    -void netlink_set_err(struct sock *ssk, u32 pid, u32 group, int code)
    +int netlink_set_err(struct sock *ssk, u32 pid, u32 group, int code)
    {
    struct netlink_set_err_data info;
    struct hlist_node *node;
    struct sock *sk;
    + int ret = 0;

    info.exclude_sk = ssk;
    info.pid = pid;
    @@ -1132,9 +1142,10 @@ void netlink_set_err(struct sock *ssk, u
    read_lock(&nl_table_lock);

    sk_for_each_bound(sk, node, &nl_table[ssk->sk_protocol].mc_list)
    - do_one_set_err(sk, &info);
    + ret += do_one_set_err(sk, &info);

    read_unlock(&nl_table_lock);
    + return ret;
    }
    EXPORT_SYMBOL(netlink_set_err);




    \
     
     \ /
      Last update: 2010-03-31 01:27    [W:4.228 / U:0.196 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site