Linux 2.x port/socket pseudo ACLs.


These patches allow an administrator to delegate privilege for some protected network resources to non-root users. They are generally used to run untrusted or insecure applications as an unprivileged process, thereby mitigating some undiscovered denial of service or root compromise.

The ACLs currently cover protected ports, raw sockets, and packet sockets.


Port pseudo ACLs

This simple hack allows root to delegate the ability to bind to a reserved port (port < 1024) to non-privileged users, much like CAP_NET_BIND_SERVICE; however, it allows much finer access control than the capability.

By setgid-ing any binary owned by the gid specified in /proc/sys/net/ipv[46]/ip_port_acl_gid, non-root users will be able to use that binary to bind to the tcp or udp port equal to their system uid.

Raw socket group

This option allows a special group access to raw sockets. Any raw-socket-needing binary setgid this group will not require root access to do its duty. This may mitigate any as yet unknown exploits for a class of setuid zero networking applications, such as ping, traceroute and mtr.

SOCK_RAW sockets work at the IP level, layer 3 (Network) in the OSI model.

Note: This would have protected you from the lbnl-traceroute heap overflow bug, the mtr/ncurses bugs, the recent ping/modutils bugs, and the glibc-2.2 RESOLV_HOST_CONF env bug.

Packet socket group

This option allows you to split off packet socket privileges to a seperate group. Unlike CAP_NET_RAW, you will have finer control over which binaries will get SOCK_PACKET privs and which get SOCK_RAW privs.

SOCK_PACKET sockets work at the device driver level, layer 2 (data link) in the OSI model. As such, it is a lower level interface than SOCK_RAW. The most common binaries that require packet socket access are those which use the functionality of libpcap.

Note: packet socket privs do not provide the privilege to put an interface into promiscuous mode...


To setup the port ACLs:

The protected port ACLs are similar to CAP_NET_BIND_SERVICE; however they allow for much finer access control than the capability.

This contrived example uses snmpd, just replace snmp with your daemon name, and 161 with the tcp/udp port it listens on...

Create a user snmp in /etc/passwd with a uid of 161.

Create a group portacl with an unused gid, $gid here.

# echo $gid > /proc/sys/net/ipv4/ip_port_acl_gid
# chown root.portacl /usr/sbin/snmpd
# chmod 2755 /usr/sbin/snmpd
# su - snmp -c /usr/sbin/snmpd -r

You will most likely need to tweak the snmpd configs a bit, too.

To setup the raw socket group:

The raw socket group is roughly equivilent to CAP_NET_RAW; however, when configuring the kernel, you can choose to seperate packet socket privs into a seperate group.

Create a group raw with an unused gid, $gid here.

# echo $gid > /proc/sys/net/ipv4/ip_sock_raw_gid
# chown root.raw /usr/bin/ping /usr/bin/traceroute /usr/bin/mtr ...
# chmod 2755 /usr/bin/ping /usr/bin/traceroute /usr/bin/mtr ...

Now your users can use ping, traceroute, mtr, etc. without it being setuid root.

To setup the packet socket group:

Create a group packet with an unused gid, $gid here.

# echo $gid > /proc/sys/net/core/sock_packet_gid
# chown root.packet /usr/sbin/tcpdump ...
# chmod 2755 /usr/sbin/tcpdump ...

Now your users can use tcpdump without it being suid root, though you probably wouldn't want them to; however, with restrictive file-system controls this can be used as an effective defense against further possible remote exploits against tcpdump/libpcap parsers. Just set up the group and run tcpdump as a non-root user.

Here are the current patches...

Apply thusly:

# ( cd /usr/src && patch -p0 < /path/to/the/patch )

And some additional support tools...

Install it in /etc/init.d, and add something like this to your startup scripts:

[ -r /etc/init.d/ ] && . /etc/init.d/