Commit 9d0b3c1f authored by Yonghong Song's avatar Yonghong Song Committed by Alexei Starovoitov

tools/bpf: fix a netlink recv issue

Commit f7010770 ("tools/bpf: move bpf/lib netlink related
functions into a new file") introduced a while loop for the
netlink recv path. This while loop is needed since the
buffer in recv syscall may not be enough to hold all the
information and in such cases multiple recv calls are needed.

There is a bug introduced by the above commit as
the while loop may block on recv syscall if there is no
more messages are expected. The netlink message header
flag NLM_F_MULTI is used to indicate that more messages
are expected and this patch fixed the bug by doing
further recv syscall only if multipart message is expected.

The patch added another fix regarding to message length of 0.
When netlink recv returns message length of 0, there will be
no more messages for returning data so the while loop
can end.

Fixes: f7010770 ("tools/bpf: move bpf/lib netlink related functions into a new file")
Reported-by: default avatarBjörn Töpel <bjorn.topel@intel.com>
Tested-by: default avatarBjörn Töpel <bjorn.topel@intel.com>
Signed-off-by: default avatarYonghong Song <yhs@fb.com>
Signed-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
parent 2e2a0c96
...@@ -65,18 +65,23 @@ static int bpf_netlink_recv(int sock, __u32 nl_pid, int seq, ...@@ -65,18 +65,23 @@ static int bpf_netlink_recv(int sock, __u32 nl_pid, int seq,
__dump_nlmsg_t _fn, dump_nlmsg_t fn, __dump_nlmsg_t _fn, dump_nlmsg_t fn,
void *cookie) void *cookie)
{ {
bool multipart = true;
struct nlmsgerr *err; struct nlmsgerr *err;
struct nlmsghdr *nh; struct nlmsghdr *nh;
char buf[4096]; char buf[4096];
int len, ret; int len, ret;
while (1) { while (multipart) {
multipart = false;
len = recv(sock, buf, sizeof(buf), 0); len = recv(sock, buf, sizeof(buf), 0);
if (len < 0) { if (len < 0) {
ret = -errno; ret = -errno;
goto done; goto done;
} }
if (len == 0)
break;
for (nh = (struct nlmsghdr *)buf; NLMSG_OK(nh, len); for (nh = (struct nlmsghdr *)buf; NLMSG_OK(nh, len);
nh = NLMSG_NEXT(nh, len)) { nh = NLMSG_NEXT(nh, len)) {
if (nh->nlmsg_pid != nl_pid) { if (nh->nlmsg_pid != nl_pid) {
...@@ -87,6 +92,8 @@ static int bpf_netlink_recv(int sock, __u32 nl_pid, int seq, ...@@ -87,6 +92,8 @@ static int bpf_netlink_recv(int sock, __u32 nl_pid, int seq,
ret = -LIBBPF_ERRNO__INVSEQ; ret = -LIBBPF_ERRNO__INVSEQ;
goto done; goto done;
} }
if (nh->nlmsg_flags & NLM_F_MULTI)
multipart = true;
switch (nh->nlmsg_type) { switch (nh->nlmsg_type) {
case NLMSG_ERROR: case NLMSG_ERROR:
err = (struct nlmsgerr *)NLMSG_DATA(nh); err = (struct nlmsgerr *)NLMSG_DATA(nh);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment