如何限制向 root 用户接收通用 netlink 多播?

How to restrict receiving a generic netlink multicast to the root user?

我编写了一个发送通用 Netlink 多播的内核模块,并使用 libmnl 编写了一个用户态客户端来接收它们。

一切正常,但我的客户端即使不是 root 用户也能正常工作,我想阻止这种情况。

man 7 netlink 说:

Only processes with an effective UID of 0 or the CAP_NET_ADMIN capability
may send or listen to a netlink multicast group.

显然这听的部分是不正确的。我试过 CentOS 5 (2.6.18)、CentOS 6 (2.6.32) 和 Ubuntu 14.04 (3.13)。

我知道可以使用 GENL_ADMIN_PERM 标志将传入内核的通用网络链接命令限制为仅来自 root,但是是否可以从内核发送只能由 root 接收的多播?

编辑:我在 https://github.com/craig65535/mcast-exmpl 分享了一些用于发送 netlink 多播的内核模块和接收它们的客户端的代码。构建说明在 README.md 中,但我会将它们粘贴在这里。

在一个终端中:

$ make
$ sudo insmod mcast-exmpl.ko
$ cd client
$ make
$ ./client
genl ctrl msg
Family ID: 26
Mcast group ID: 4

(ID 可能不同)

在另一个终端中,运行 执行 TCP 连接的命令。 mcast-exmpl hooks 通过 jprobe 连接,所以这样做会导致它发送 netlink 多播。

$ nc yahoo.com 80
^C
$

在第一个终端中,您会看到收到了一个网络链接多播,即使您没有运行 root 客户端:

mcast-exmpl msg
SEND_NUM 55555

我想修改它,以便仅当 client 以 root 用户身份 运行 时才接收多播,或者,如果失败,请确认我在Linux 文档或 Linux 本身。

首先,我对netlink IPC机制不熟悉。不过,我相信我有一些有用的信息可以分享。

尽管您不是 root 用户,但您能够接收到的原因是 this change 一段时间前对内核进行了修改,允许非 root 用户能够读取 uevents。

查看Multicast from kernel to user space via Netlink in C,似乎内核模块can/should指定了一个struct netlink_kernel_cfg

LXR开始,好像定义为

struct netlink_kernel_cfg {
        unsigned int    groups;
        unsigned int    flags;
        void            (*input)(struct sk_buff *skb);
        struct mutex    *cb_mutex;
        int             (*bind)(struct net *net, int group);
        void            (*unbind)(struct net *net, int group);
        bool            (*compare)(struct net *net, struct sock *sk);
};

谷歌搜索 flags 属性得到 this 结果说

The flags member can be NL_CFG_F_NONROOT_RECV or NL_CFG_F_NONROOT_SEND. When NL_CFG_F_NONROOT_RECV is set, a non-superuser can bind to a multicast group.