Reputation: 3581
I wrote a kernel module that sends generic Netlink multicasts, and wrote a userland client using libmnl that receives them.
That all works fine, but my client works even when it's not the root user, and I want to prevent that.
man 7 netlink says:
Only processes with an effective UID of 0 or the CAP_NET_ADMIN capability
may send or listen to a netlink multicast group.
Obviously the listen part of this is not true. I've tried CentOS 5 (2.6.18), CentOS 6 (2.6.32) and Ubuntu 14.04 (3.13).
I know that restricting receiving generic netlink commands incoming to the kernel to being only from root is possible with GENL_ADMIN_PERM flag, but is it possible to send multicasts from the kernel that can only be received by root?
EDIT: I shared some code for a kernel module that sends netlink multicasts, and client that receives them, at https://github.com/craig65535/mcast-exmpl. Build instructions are in the README.md, but I'll paste them here.
In one terminal:
$ make
$ sudo insmod mcast-exmpl.ko
$ cd client
$ make
$ ./client
genl ctrl msg
Family ID: 26
Mcast group ID: 4
(IDs may be different)
In another terminal, run a command that will do a TCP connect. mcast-exmpl hooks connects via a jprobe, so doing this will cause it to send a netlink multicast.
$ nc yahoo.com 80
^C
$
In the first terminal, you'll see a netlink multicast was received, even if you did not run client as root:
mcast-exmpl msg
SEND_NUM 55555
I'd like to modify this so the multicasts are only received when client
is running as root, or, failing that, confirmation that I've found a bug either in the Linux documentation or Linux itself.
Upvotes: 3
Views: 1715
Reputation: 4233
First off, I'm not familiar with the netlink IPC mechanism. However, I believe I have some useful information to share.
The reason you're able to receive despite being non-root is because of this change made to the kernel some time back which allowed non-root users to be able to read uevents.
Looking at Multicast from kernel to user space via Netlink in C, it appears that the kernel module can/should specify a struct netlink_kernel_cfg
.
From LXR, it seems to be defined as
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);
};
Googling for the flags
attribute yielded this result which says
The flags member can be
NL_CFG_F_NONROOT_RECV
orNL_CFG_F_NONROOT_SEND
. WhenNL_CFG_F_NONROOT_RECV
is set, a non-superuser can bind to a multicast group.
Upvotes: 2