diff options
author | Yu Watanabe <watanabe.yu+github@gmail.com> | 2021-10-20 13:30:32 +0900 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-10-20 13:30:32 +0900 |
commit | 231c7645ca761f0347c98fa48c68b3fde00fbc15 (patch) | |
tree | 5fa581a4b4d084ca8eb72796af5687833cf1ad4a /src/network/networkd-manager.c | |
parent | 952d873f56354c835c1af4bf7fd147d6253ae371 (diff) | |
parent | 26a8be48bc53fdf1f67bc2ae91c80c7f11295d9d (diff) | |
download | systemd-231c7645ca761f0347c98fa48c68b3fde00fbc15.tar.gz |
Merge pull request #21041 from yuwata/network-bpf-neighbor
network: introduce BPF to reject netlink messages about non-static neighbor
Diffstat (limited to 'src/network/networkd-manager.c')
-rw-r--r-- | src/network/networkd-manager.c | 36 |
1 files changed, 35 insertions, 1 deletions
diff --git a/src/network/networkd-manager.c b/src/network/networkd-manager.c index c5ccfb4b58..e25092058b 100644 --- a/src/network/networkd-manager.c +++ b/src/network/networkd-manager.c @@ -263,6 +263,40 @@ static int manager_connect_genl(Manager *m) { return 0; } +static int manager_setup_rtnl_filter(Manager *manager) { + struct sock_filter filter[] = { + /* Check the packet length. */ + BPF_STMT(BPF_LD + BPF_W + BPF_LEN, 0), /* A <- packet length */ + BPF_JUMP(BPF_JMP + BPF_JGE + BPF_K, sizeof(struct nlmsghdr), 1, 0), /* A (packet length) >= sizeof(struct nlmsghdr) ? */ + BPF_STMT(BPF_RET + BPF_K, 0), /* reject */ + /* Always accept multipart message. */ + BPF_STMT(BPF_LD + BPF_H + BPF_ABS, offsetof(struct nlmsghdr, nlmsg_flags)), /* A <- message flags */ + BPF_JUMP(BPF_JMP + BPF_JSET + BPF_K, htobe16(NLM_F_MULTI), 0, 1), /* message flags has NLM_F_MULTI ? */ + BPF_STMT(BPF_RET + BPF_K, UINT32_MAX), /* accept */ + /* Accept all message types except for RTM_NEWNEIGH or RTM_DELNEIGH. */ + BPF_STMT(BPF_LD + BPF_H + BPF_ABS, offsetof(struct nlmsghdr, nlmsg_type)), /* A <- message type */ + BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, htobe16(RTM_NEWNEIGH), 2, 0), /* message type == RTM_NEWNEIGH ? */ + BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, htobe16(RTM_DELNEIGH), 1, 0), /* message type == RTM_DELNEIGH ? */ + BPF_STMT(BPF_RET + BPF_K, UINT32_MAX), /* accept */ + /* Check the packet length. */ + BPF_STMT(BPF_LD + BPF_W + BPF_LEN, 0), /* A <- packet length */ + BPF_JUMP(BPF_JMP + BPF_JGE + BPF_K, sizeof(struct nlmsghdr) + sizeof(struct ndmsg), 1, 0), + /* packet length >= sizeof(struct nlmsghdr) + sizeof(struct ndmsg) ? */ + BPF_STMT(BPF_RET + BPF_K, 0), /* reject */ + /* Reject the message when the neighbor state does not have NUD_PERMANENT flag. */ + BPF_STMT(BPF_LD + BPF_H + BPF_ABS, sizeof(struct nlmsghdr) + offsetof(struct ndmsg, ndm_state)), + /* A <- neighbor state */ + BPF_JUMP(BPF_JMP + BPF_JSET + BPF_K, htobe16(NUD_PERMANENT), 1, 0), /* neighbor state has NUD_PERMANENT ? */ + BPF_STMT(BPF_RET + BPF_K, 0), /* reject */ + BPF_STMT(BPF_RET + BPF_K, UINT32_MAX), /* accept */ + }; + + assert(manager); + assert(manager->rtnl); + + return sd_netlink_attach_filter(manager->rtnl, ELEMENTSOF(filter), filter); +} + static int manager_connect_rtnl(Manager *m) { int fd, r; @@ -337,7 +371,7 @@ static int manager_connect_rtnl(Manager *m) { if (r < 0) return r; - return 0; + return manager_setup_rtnl_filter(m); } static int manager_dirty_handler(sd_event_source *s, void *userdata) { |