craig65535
craig65535

Reputation: 3581

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

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

Answers (1)

Guru Prasad
Guru Prasad

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 or NL_CFG_F_NONROOT_SEND. When NL_CFG_F_NONROOT_RECV is set, a non-superuser can bind to a multicast group.

Upvotes: 2

Related Questions