diff -Nurd linux-orig/Documentation/Configure.help linux/Documentation/Configure.help --- linux-orig/Documentation/Configure.help Fri Nov 2 08:39:05 2001 +++ linux/Documentation/Configure.help Fri Nov 2 22:58:38 2001 @@ -3485,7 +3485,75 @@ through the old netlink interface. However, a better option is to say Y to "Kernel/User network link driver" and to "Routing messages" instead. - + +IP: port/socket pseudo ACLs +CONFIG_PSEUDO_ACLS + If you say yes here, config will ask a few more questions about port + and socket ACLs. + +IP: port pseudo ACLs +CONFIG_PORT_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]/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. + + For instance, perhaps one would like to run snmpd as non-privileged + user "snmp," simply: + + Say yes here and compile a new kernel, then reboot into it. + 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.$gid /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. + + For more info, check http://original.killa.net/infosec/acls/index.html + +IP: Raw socket group +CONFIG_SOCK_RAW_GROUP + Say yes here if you wish to give 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 or mtr. + + SOCK_RAW sockets work at the IP level, layer 3 (Network) in the + OSI model. + + You will need to setgid any binaries needing raw sockets to a new gid, + and specify that gid in /proc/sys/net/ipv[46]/ip_sock_raw_gid for it to + take effect. + + For more info, check http://original.killa.net/infosec/acls/index.html + +IP: Packet socket group +CONFIG_SOCK_PACKET_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 (e.g. tcpdump). + + You will need to setgid any binaries needing packet sockets to a new + gid, and specify that gid in /proc/sys/net/sock_packet_gid for it to + take effect. + + NOTE: I recommend you say yes, unless you have a (weird) application + that needs both raw and packet sockets. This will protect you from + any ping/traceroute exploits leading to a sniffer attack. + + For more info, check http://original.killa.net/infosec/acls/index.html + IPX networking CONFIG_IPX This is support for the Novell networking protocol, IPX, commonly diff -Nurd linux-orig/include/linux/sysctl.h linux/include/linux/sysctl.h --- linux-orig/include/linux/sysctl.h Sun Mar 25 08:37:40 2001 +++ linux/include/linux/sysctl.h Fri Nov 2 22:58:39 2001 @@ -231,7 +231,11 @@ NET_IPV4_ICMP_IGNORE_BOGUS_ERROR_RESPONSES=64, NET_IPV4_IGMP_MAX_MEMBERSHIPS=65, NET_IPV4_ALWAYS_DEFRAG=67, - NET_IPV4_IP_MASQ_UDP_DLOOSE=68 + NET_IPV4_IP_MASQ_UDP_DLOOSE=68, + NET_IP_PORT_ACL_GID=69, + NET_IP_SOCK_RAW_GID=70, + NET_IP_SOCK_PACKET_GID=71 + }; enum { diff -Nurd linux-orig/net/ipv4/Config.in linux/net/ipv4/Config.in --- linux-orig/net/ipv4/Config.in Sun Mar 25 08:31:12 2001 +++ linux/net/ipv4/Config.in Fri Nov 2 22:58:40 2001 @@ -74,6 +74,16 @@ fi fi bool 'IP: TCP syncookie support (not enabled per default)' CONFIG_SYN_COOKIES +if [ "$CONFIG_SYSCTL" = "y" ]; then + bool 'IP: Socket/port pseudo acls' CONFIG_PSEUDO_ACLS + if [ "$CONFIG_PSEUDO_ACLS" = "y" ]; then + bool 'IP: Port ACLs' CONFIG_PORT_ACLS + bool 'IP: Raw socket group' CONFIG_SOCK_RAW_GROUP + if [ "$CONFIG_SOCK_RAW_GROUP" = "y" -a "$CONFIG_PACKET" != "n" ]; then + bool 'IP: Packet socket group' CONFIG_SOCK_PACKET_GROUP + fi + fi +fi comment '(it is safe to leave these untouched)' #bool 'IP: PC/TCP compatibility mode' CONFIG_INET_PCTCP tristate 'IP: Reverse ARP' CONFIG_INET_RARP @@ -83,4 +93,3 @@ #if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then #bool 'IP: support experimental checksum copy to user for UDP' CONFIG_UDP_DELAY_CSUM #fi - diff -Nurd linux-orig/net/ipv4/af_inet.c linux/net/ipv4/af_inet.c --- linux-orig/net/ipv4/af_inet.c Fri Nov 2 08:39:16 2001 +++ linux/net/ipv4/af_inet.c Fri Nov 2 22:58:40 2001 @@ -123,6 +123,14 @@ #define min(a,b) ((a)<(b)?(a):(b)) +#ifdef CONFIG_PORT_ACLS +int sysctl_port_acl_gid; +#endif + +#ifdef CONFIG_SOCK_RAW_GROUP +int sysctl_sock_raw_gid; +#endif + extern int raw_get_info(char *, char **, off_t, int, int); extern int snmp_get_info(char *, char **, off_t, int, int); extern int netstat_get_info(char *, char **, off_t, int, int); @@ -380,7 +388,11 @@ sock->ops = &inet_dgram_ops; break; case SOCK_RAW: - if (!capable(CAP_NET_RAW)) + if (!capable(CAP_NET_RAW) +#ifdef CONFIG_SOCK_RAW_GROUP + && current->egid != sysctl_sock_raw_gid +#endif + ) goto free_and_badperm; if (!protocol) goto free_and_noproto; @@ -545,7 +557,12 @@ chk_addr_ret != RTN_MULTICAST) return -EADDRINUSE; #endif - if (snum && snum < PROT_SOCK && !capable(CAP_NET_BIND_SERVICE)) + if (snum && snum < PROT_SOCK && !capable(CAP_NET_BIND_SERVICE) +#ifdef CONFIG_PORT_ACLS + && !(current->uid == snum + && current->egid == sysctl_port_acl_gid) +#endif + ) return(-EACCES); /* Make sure we are allowed to bind here. */ diff -Nurd linux-orig/net/ipv4/sysctl_net_ipv4.c linux/net/ipv4/sysctl_net_ipv4.c --- linux-orig/net/ipv4/sysctl_net_ipv4.c Fri Nov 2 08:39:16 2001 +++ linux/net/ipv4/sysctl_net_ipv4.c Fri Nov 2 22:58:40 2001 @@ -61,6 +61,14 @@ /* From igmp.c */ extern int sysctl_igmp_max_memberships; +#ifdef CONFIG_PORT_ACLS +extern int sysctl_port_acl_gid; +#endif + +#ifdef CONFIG_SOCK_RAW_GROUP +extern int sysctl_sock_raw_gid; +#endif + static int tcp_retr1_max = 255; static int ip_local_port_range_min[] = { 1, 1 }; @@ -197,6 +205,14 @@ #ifdef CONFIG_IP_MULTICAST {NET_IPV4_IGMP_MAX_MEMBERSHIPS, "igmp_max_memberships", &sysctl_igmp_max_memberships, sizeof(int), 0644, NULL, &proc_dointvec}, +#endif +#ifdef CONFIG_PORT_ACLS + {NET_IP_PORT_ACL_GID, "ip_port_acl_gid", &sysctl_port_acl_gid, + sizeof(int), 0644, NULL, &proc_dointvec}, +#endif +#ifdef CONFIG_SOCK_RAW_GROUP + {NET_IP_SOCK_RAW_GID, "ip_sock_raw_gid", &sysctl_sock_raw_gid, + sizeof(int), 0644, NULL, &proc_dointvec}, #endif {0} }; diff -Nurd linux-orig/net/ipv6/af_inet6.c linux/net/ipv6/af_inet6.c --- linux-orig/net/ipv6/af_inet6.c Sun Mar 25 08:31:13 2001 +++ linux/net/ipv6/af_inet6.c Fri Nov 2 22:58:40 2001 @@ -82,8 +82,17 @@ #ifdef CONFIG_SYSCTL extern void ipv6_sysctl_register(void); extern void ipv6_sysctl_unregister(void); + +#ifdef CONFIG_PORT_ACLS +int sysctl_port_acl_gid; #endif +#ifdef CONFIG_SOCK_RAW_GROUP +int sysctl_sock_raw_gid; +#endif + +#endif /* CONFIG_SYSCTL */ + static int inet6_create(struct socket *sock, int protocol) { struct sock *sk; @@ -107,7 +116,11 @@ prot=&udpv6_prot; sock->ops = &inet6_dgram_ops; } else if(sock->type == SOCK_RAW) { - if (!capable(CAP_NET_RAW)) + if (!capable(CAP_NET_RAW) +#ifdef CONFIG_SOCK_RAW_GROUP + && current->egid != sysctl_sock_raw_gid +#endif + ) goto free_and_badperm; if (!protocol) goto free_and_noproto; @@ -236,7 +249,12 @@ sizeof(struct in6_addr)); snum = ntohs(addr->sin6_port); - if (snum && snum < PROT_SOCK && !capable(CAP_NET_BIND_SERVICE)) + if (snum && snum < PROT_SOCK && !capable(CAP_NET_BIND_SERVICE) +#ifdef CONFIG_PORT_ACLS + && !(current->uid == snum + && current->egid == sysctl_port_acl_gid) +#endif /* CONFIG_PORT_ACLS */ + ) return(-EACCES); /* Make sure we are allowed to bind here. */ diff -Nurd linux-orig/net/ipv6/sysctl_net_ipv6.c linux/net/ipv6/sysctl_net_ipv6.c --- linux-orig/net/ipv6/sysctl_net_ipv6.c Sun Mar 25 08:31:13 2001 +++ linux/net/ipv6/sysctl_net_ipv6.c Fri Nov 2 22:58:40 2001 @@ -15,8 +15,24 @@ #ifdef CONFIG_SYSCTL +#ifdef CONFIG_PORT_ACLS +int sysctl_port_acl_gid; +#endif + +#ifdef CONFIG_SOCK_RAW_GROUP +extern int sysctl_sock_raw_gid; +#endif + ctl_table ipv6_table[] = { {NET_IPV6_ROUTE, "route", NULL, 0, 0555, ipv6_route_table}, +#ifdef CONFIG_PORT_ACLS + {NET_IP_PORT_ACL_GID, "ip_port_acl_gid", &sysctl_port_acl_gid, + sizeof(int), 0644, NULL, &proc_dointvec}, +#endif +#ifdef CONFIG_SOCK_RAW_GROUP + {NET_IP_SOCK_RAW_GID, "ip_sock_raw_gid", &sysctl_sock_raw_gid, + sizeof(int), 0644, NULL, &proc_dointvec}, +#endif {0} }; diff -Nurd linux-orig/net/packet/af_packet.c linux/net/packet/af_packet.c --- linux-orig/net/packet/af_packet.c Sun Mar 25 08:31:14 2001 +++ linux/net/packet/af_packet.c Fri Nov 2 22:58:40 2001 @@ -80,6 +80,14 @@ extern int dlci_ioctl(unsigned int, void*); #endif +#ifdef CONFIG_SOCK_RAW_GROUP +#ifdef CONFIG_SOCK_PACKET_GROUP +int sysctl_sock_packet_gid; +#else +int sysctl_sock_raw_gid; +#endif /* CONFIG_SOCK_PACKET_GROUP */ +#endif /* CONFIG_SOCK_RAW_GROUP */ + /* Old SOCK_PACKET. Do exist programs, which use it? (not counting tcpdump) - lots of them yes - AC. @@ -692,7 +700,15 @@ struct sock *sk; int err; - if (!capable(CAP_NET_RAW)) + if (!capable(CAP_NET_RAW) +#ifdef CONFIG_SOCK_RAW_GROUP +#ifdef CONFIG_SOCK_PACKET_GROUP + && current->egid != sysctl_sock_packet_gid +#else + && current->egid != sysctl_sock_raw_gid +#endif /* CONFIG_SOCK_PACKET_GROUP */ +#endif /* CONFIG_SOCK_RAW_GROUP */ + ) return -EPERM; if (sock->type != SOCK_DGRAM && sock->type != SOCK_RAW #ifdef CONFIG_SOCK_PACKET diff -Nurd linux-orig/net/sysctl_net.c linux/net/sysctl_net.c --- linux-orig/net/sysctl_net.c Sun Mar 25 08:31:13 2001 +++ linux/net/sysctl_net.c Fri Nov 2 22:58:41 2001 @@ -46,6 +46,10 @@ extern ctl_table tr_table[]; #endif +#ifdef CONFIG_SOCK_PACKET_GROUP +extern int sysctl_sock_packet_gid; +#endif + ctl_table net_table[] = { {NET_CORE, "core", NULL, 0, 0555, core_table}, #ifdef CONFIG_UNIX @@ -70,5 +74,11 @@ #ifdef CONFIG_TR {NET_TR, "token-ring", NULL, 0, 0555, tr_table}, #endif +#ifdef CONFIG_SOCK_PACKET_GROUP + {NET_IP_SOCK_PACKET_GID, "ip_sock_packet_gid", &sysctl_sock_packet_gid, + sizeof(int), 0644, NULL, &proc_dointvec}, +#endif {0} }; + +