Skip to content

Commit 1a50307

Browse files
ummakynesdavem330
authored andcommitted
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 <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 73852e8 commit 1a50307

File tree

2 files changed

+15
-4
lines changed

2 files changed

+15
-4
lines changed

include/linux/netlink.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,7 @@ extern int netlink_has_listeners(struct sock *sk, unsigned int group);
188188
extern int netlink_unicast(struct sock *ssk, struct sk_buff *skb, __u32 pid, int nonblock);
189189
extern int netlink_broadcast(struct sock *ssk, struct sk_buff *skb, __u32 pid,
190190
__u32 group, gfp_t allocation);
191-
extern void netlink_set_err(struct sock *ssk, __u32 pid, __u32 group, int code);
191+
extern int netlink_set_err(struct sock *ssk, __u32 pid, __u32 group, int code);
192192
extern int netlink_register_notifier(struct notifier_block *nb);
193193
extern int netlink_unregister_notifier(struct notifier_block *nb);
194194

net/netlink/af_netlink.c

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1093,6 +1093,7 @@ static inline int do_one_set_err(struct sock *sk,
10931093
struct netlink_set_err_data *p)
10941094
{
10951095
struct netlink_sock *nlk = nlk_sk(sk);
1096+
int ret = 0;
10961097

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

1108+
if (p->code == ENOBUFS && nlk->flags & NETLINK_RECV_NO_ENOBUFS) {
1109+
ret = 1;
1110+
goto out;
1111+
}
1112+
11071113
sk->sk_err = p->code;
11081114
sk->sk_error_report(sk);
11091115
out:
1110-
return 0;
1116+
return ret;
11111117
}
11121118

11131119
/**
@@ -1116,12 +1122,16 @@ static inline int do_one_set_err(struct sock *sk,
11161122
* @pid: the PID of a process that we want to skip (if any)
11171123
* @groups: the broadcast group that will notice the error
11181124
* @code: error code, must be negative (as usual in kernelspace)
1125+
*
1126+
* This function returns the number of broadcast listeners that have set the
1127+
* NETLINK_RECV_NO_ENOBUFS socket option.
11191128
*/
1120-
void netlink_set_err(struct sock *ssk, u32 pid, u32 group, int code)
1129+
int netlink_set_err(struct sock *ssk, u32 pid, u32 group, int code)
11211130
{
11221131
struct netlink_set_err_data info;
11231132
struct hlist_node *node;
11241133
struct sock *sk;
1134+
int ret = 0;
11251135

11261136
info.exclude_sk = ssk;
11271137
info.pid = pid;
@@ -1132,9 +1142,10 @@ void netlink_set_err(struct sock *ssk, u32 pid, u32 group, int code)
11321142
read_lock(&nl_table_lock);
11331143

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

11371147
read_unlock(&nl_table_lock);
1148+
return ret;
11381149
}
11391150
EXPORT_SYMBOL(netlink_set_err);
11401151

0 commit comments

Comments
 (0)