Skip to content

Commit af4a02b

Browse files
segoongregkh
authored andcommitted
net: don't allow CAP_NET_ADMIN to load non-netdev kernel modules
commit 8909c9a upstream. Since a8f80e8 any process with CAP_NET_ADMIN may load any module from /lib/modules/. This doesn't mean that CAP_NET_ADMIN is a superset of CAP_SYS_MODULE as modules are limited to /lib/modules/**. However, CAP_NET_ADMIN capability shouldn't allow anybody load any module not related to networking. This patch restricts an ability of autoloading modules to netdev modules with explicit aliases. This fixes CVE-2011-1019. Arnd Bergmann suggested to leave untouched the old pre-v2.6.32 behavior of loading netdev modules by name (without any prefix) for processes with CAP_SYS_MODULE to maintain the compatibility with network scripts that use autoloading netdev modules by aliases like "eth0", "wlan0". Currently there are only three users of the feature in the upstream kernel: ipip, ip_gre and sit. root@albatros:~# capsh --drop=$(seq -s, 0 11),$(seq -s, 13 34) -- root@albatros:~# grep Cap /proc/$$/status CapInh: 0000000000000000 CapPrm: fffffff800001000 CapEff: fffffff800001000 CapBnd: fffffff800001000 root@albatros:~# modprobe xfs FATAL: Error inserting xfs (/lib/modules/2.6.38-rc6-00001-g2bf4ca3/kernel/fs/xfs/xfs.ko): Operation not permitted root@albatros:~# lsmod | grep xfs root@albatros:~# ifconfig xfs xfs: error fetching interface information: Device not found root@albatros:~# lsmod | grep xfs root@albatros:~# lsmod | grep sit root@albatros:~# ifconfig sit sit: error fetching interface information: Device not found root@albatros:~# lsmod | grep sit root@albatros:~# ifconfig sit0 sit0 Link encap:IPv6-in-IPv4 NOARP MTU:1480 Metric:1 root@albatros:~# lsmod | grep sit sit 10457 0 tunnel4 2957 1 sit For CAP_SYS_MODULE module loading is still relaxed: root@albatros:~# grep Cap /proc/$$/status CapInh: 0000000000000000 CapPrm: ffffffffffffffff CapEff: ffffffffffffffff CapBnd: ffffffffffffffff root@albatros:~# ifconfig xfs xfs: error fetching interface information: Device not found root@albatros:~# lsmod | grep xfs xfs 745319 0 Reference: https://lkml.org/lkml/2011/2/24/203 Signed-off-by: Vasiliy Kulikov <segoon@openwall.com> Signed-off-by: Michael Tokarev <mjt@tls.msk.ru> Acked-by: David S. Miller <davem@davemloft.net> Acked-by: Kees Cook <kees.cook@canonical.com> Signed-off-by: James Morris <jmorris@namei.org> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
1 parent 1021236 commit af4a02b

File tree

5 files changed

+17
-3
lines changed

5 files changed

+17
-3
lines changed

include/linux/netdevice.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2015,6 +2015,10 @@ static inline u32 dev_ethtool_get_flags(struct net_device *dev)
20152015
return 0;
20162016
return dev->ethtool_ops->get_flags(dev);
20172017
}
2018+
2019+
#define MODULE_ALIAS_NETDEV(device) \
2020+
MODULE_ALIAS("netdev-" device)
2021+
20182022
#endif /* __KERNEL__ */
20192023

20202024
#endif /* _LINUX_NETDEVICE_H */

net/core/dev.c

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1037,13 +1037,21 @@ EXPORT_SYMBOL(netdev_bonding_change);
10371037
void dev_load(struct net *net, const char *name)
10381038
{
10391039
struct net_device *dev;
1040+
int no_module;
10401041

10411042
read_lock(&dev_base_lock);
10421043
dev = __dev_get_by_name(net, name);
10431044
read_unlock(&dev_base_lock);
10441045

1045-
if (!dev && capable(CAP_NET_ADMIN))
1046-
request_module("%s", name);
1046+
no_module = !dev;
1047+
if (no_module && capable(CAP_NET_ADMIN))
1048+
no_module = request_module("netdev-%s", name);
1049+
if (no_module && capable(CAP_SYS_MODULE)) {
1050+
if (!request_module("%s", name))
1051+
pr_err("Loading kernel module for a network device "
1052+
"with CAP_SYS_MODULE (deprecated). Use CAP_NET_ADMIN and alias netdev-%s "
1053+
"instead\n", name);
1054+
}
10471055
}
10481056
EXPORT_SYMBOL(dev_load);
10491057

net/ipv4/ip_gre.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1708,3 +1708,4 @@ module_exit(ipgre_fini);
17081708
MODULE_LICENSE("GPL");
17091709
MODULE_ALIAS_RTNL_LINK("gre");
17101710
MODULE_ALIAS_RTNL_LINK("gretap");
1711+
MODULE_ALIAS_NETDEV("gre0");

net/ipv4/ipip.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -853,3 +853,4 @@ static void __exit ipip_fini(void)
853853
module_init(ipip_init);
854854
module_exit(ipip_fini);
855855
MODULE_LICENSE("GPL");
856+
MODULE_ALIAS_NETDEV("tunl0");

net/ipv6/sit.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1101,4 +1101,4 @@ static int __init sit_init(void)
11011101
module_init(sit_init);
11021102
module_exit(sit_cleanup);
11031103
MODULE_LICENSE("GPL");
1104-
MODULE_ALIAS("sit0");
1104+
MODULE_ALIAS_NETDEV("sit0");

0 commit comments

Comments
 (0)