Skip to content

Commit 26a8be4

Browse files
committed
network: introduce BPF to reject netlink messages about non-static neighbor
Fixes systemd#21031.
1 parent dc317a9 commit 26a8be4

File tree

1 file changed

+35
-1
lines changed

1 file changed

+35
-1
lines changed

src/network/networkd-manager.c

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,40 @@ static int manager_connect_genl(Manager *m) {
263263
return 0;
264264
}
265265

266+
static int manager_setup_rtnl_filter(Manager *manager) {
267+
struct sock_filter filter[] = {
268+
/* Check the packet length. */
269+
BPF_STMT(BPF_LD + BPF_W + BPF_LEN, 0), /* A <- packet length */
270+
BPF_JUMP(BPF_JMP + BPF_JGE + BPF_K, sizeof(struct nlmsghdr), 1, 0), /* A (packet length) >= sizeof(struct nlmsghdr) ? */
271+
BPF_STMT(BPF_RET + BPF_K, 0), /* reject */
272+
/* Always accept multipart message. */
273+
BPF_STMT(BPF_LD + BPF_H + BPF_ABS, offsetof(struct nlmsghdr, nlmsg_flags)), /* A <- message flags */
274+
BPF_JUMP(BPF_JMP + BPF_JSET + BPF_K, htobe16(NLM_F_MULTI), 0, 1), /* message flags has NLM_F_MULTI ? */
275+
BPF_STMT(BPF_RET + BPF_K, UINT32_MAX), /* accept */
276+
/* Accept all message types except for RTM_NEWNEIGH or RTM_DELNEIGH. */
277+
BPF_STMT(BPF_LD + BPF_H + BPF_ABS, offsetof(struct nlmsghdr, nlmsg_type)), /* A <- message type */
278+
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, htobe16(RTM_NEWNEIGH), 2, 0), /* message type == RTM_NEWNEIGH ? */
279+
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, htobe16(RTM_DELNEIGH), 1, 0), /* message type == RTM_DELNEIGH ? */
280+
BPF_STMT(BPF_RET + BPF_K, UINT32_MAX), /* accept */
281+
/* Check the packet length. */
282+
BPF_STMT(BPF_LD + BPF_W + BPF_LEN, 0), /* A <- packet length */
283+
BPF_JUMP(BPF_JMP + BPF_JGE + BPF_K, sizeof(struct nlmsghdr) + sizeof(struct ndmsg), 1, 0),
284+
/* packet length >= sizeof(struct nlmsghdr) + sizeof(struct ndmsg) ? */
285+
BPF_STMT(BPF_RET + BPF_K, 0), /* reject */
286+
/* Reject the message when the neighbor state does not have NUD_PERMANENT flag. */
287+
BPF_STMT(BPF_LD + BPF_H + BPF_ABS, sizeof(struct nlmsghdr) + offsetof(struct ndmsg, ndm_state)),
288+
/* A <- neighbor state */
289+
BPF_JUMP(BPF_JMP + BPF_JSET + BPF_K, htobe16(NUD_PERMANENT), 1, 0), /* neighbor state has NUD_PERMANENT ? */
290+
BPF_STMT(BPF_RET + BPF_K, 0), /* reject */
291+
BPF_STMT(BPF_RET + BPF_K, UINT32_MAX), /* accept */
292+
};
293+
294+
assert(manager);
295+
assert(manager->rtnl);
296+
297+
return sd_netlink_attach_filter(manager->rtnl, ELEMENTSOF(filter), filter);
298+
}
299+
266300
static int manager_connect_rtnl(Manager *m) {
267301
int fd, r;
268302

@@ -337,7 +371,7 @@ static int manager_connect_rtnl(Manager *m) {
337371
if (r < 0)
338372
return r;
339373

340-
return 0;
374+
return manager_setup_rtnl_filter(m);
341375
}
342376

343377
static int manager_dirty_handler(sd_event_source *s, void *userdata) {

0 commit comments

Comments
 (0)