mirror of
https://github.com/systemd/systemd.git
synced 2024-10-30 06:25:37 +03:00
Merge pull request #21041 from yuwata/network-bpf-neighbor
network: introduce BPF to reject netlink messages about non-static neighbor
This commit is contained in:
commit
231c7645ca
@ -1023,3 +1023,18 @@ int sd_netlink_add_match(
|
||||
return netlink_add_match_internal(rtnl, ret_slot, groups, n_groups, type, 0, callback,
|
||||
destroy_callback, userdata, description);
|
||||
}
|
||||
|
||||
int sd_netlink_attach_filter(sd_netlink *nl, size_t len, struct sock_filter *filter) {
|
||||
assert_return(nl, -EINVAL);
|
||||
assert_return(len == 0 || filter, -EINVAL);
|
||||
|
||||
if (setsockopt(nl->fd, SOL_SOCKET,
|
||||
len == 0 ? SO_DETACH_FILTER : SO_ATTACH_FILTER,
|
||||
&(struct sock_fprog) {
|
||||
.len = len,
|
||||
.filter = filter,
|
||||
}, sizeof(struct sock_fprog)) < 0)
|
||||
return -errno;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include <inttypes.h>
|
||||
#include <net/ethernet.h>
|
||||
#include <netinet/in.h>
|
||||
#include <linux/filter.h>
|
||||
#include <linux/neighbour.h>
|
||||
#include <linux/rtnetlink.h>
|
||||
|
||||
@ -68,6 +69,7 @@ int sd_netlink_add_match(sd_netlink *nl, sd_netlink_slot **ret_slot, uint16_t ma
|
||||
|
||||
int sd_netlink_attach_event(sd_netlink *nl, sd_event *e, int64_t priority);
|
||||
int sd_netlink_detach_event(sd_netlink *nl);
|
||||
int sd_netlink_attach_filter(sd_netlink *nl, size_t len, struct sock_filter *filter);
|
||||
|
||||
/* message */
|
||||
int sd_netlink_message_append_string(sd_netlink_message *m, unsigned short type, const char *data);
|
||||
|
Loading…
Reference in New Issue
Block a user