netlink: fix NETLINK_RECV_NO_ENOBUFS in netlink_set_err()
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>
This commit is contained in:
parent
73852e8151
commit
1a50307ba1
@ -188,7 +188,7 @@ extern int netlink_has_listeners(struct sock *sk, unsigned int group);
|
||||
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);
|
||||
|
||||
|
@ -1093,6 +1093,7 @@ static inline int do_one_set_err(struct sock *sk,
|
||||
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 sock *sk,
|
||||
!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, u32 pid, u32 group, int code)
|
||||
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);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user