aboutsummaryrefslogtreecommitdiffstats
path: root/net/core
diff options
context:
space:
mode:
authorEric W. Biederman <ebiederm@xmission.com>2014-04-23 17:29:27 -0400
committerDavid S. Miller <davem@davemloft.net>2014-04-24 13:44:54 -0400
commit90f62cf30a78721641e08737bda787552428061e (patch)
tree85d43e6c5d8b10fb79fcb9c402217f8eb54bbe12 /net/core
parentaa4cf9452f469f16cea8c96283b641b4576d4a7b (diff)
net: Use netlink_ns_capable to verify the permisions of netlink messages
It is possible by passing a netlink socket to a more privileged executable and then to fool that executable into writing to the socket data that happens to be valid netlink message to do something that privileged executable did not intend to do. To keep this from happening replace bare capable and ns_capable calls with netlink_capable, netlink_net_calls and netlink_ns_capable calls. Which act the same as the previous calls except they verify that the opener of the socket had the desired permissions as well. Reported-by: Andy Lutomirski <luto@amacapital.net> Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/core')
-rw-r--r--net/core/rtnetlink.c20
1 files changed, 11 insertions, 9 deletions
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index d4ff41739b0f..64ad17d077ed 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -1395,7 +1395,8 @@ static int do_set_master(struct net_device *dev, int ifindex)
1395 return 0; 1395 return 0;
1396} 1396}
1397 1397
1398static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm, 1398static int do_setlink(const struct sk_buff *skb,
1399 struct net_device *dev, struct ifinfomsg *ifm,
1399 struct nlattr **tb, char *ifname, int modified) 1400 struct nlattr **tb, char *ifname, int modified)
1400{ 1401{
1401 const struct net_device_ops *ops = dev->netdev_ops; 1402 const struct net_device_ops *ops = dev->netdev_ops;
@@ -1407,7 +1408,7 @@ static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm,
1407 err = PTR_ERR(net); 1408 err = PTR_ERR(net);
1408 goto errout; 1409 goto errout;
1409 } 1410 }
1410 if (!ns_capable(net->user_ns, CAP_NET_ADMIN)) { 1411 if (!netlink_ns_capable(skb, net->user_ns, CAP_NET_ADMIN)) {
1411 err = -EPERM; 1412 err = -EPERM;
1412 goto errout; 1413 goto errout;
1413 } 1414 }
@@ -1661,7 +1662,7 @@ static int rtnl_setlink(struct sk_buff *skb, struct nlmsghdr *nlh)
1661 if (err < 0) 1662 if (err < 0)
1662 goto errout; 1663 goto errout;
1663 1664
1664 err = do_setlink(dev, ifm, tb, ifname, 0); 1665 err = do_setlink(skb, dev, ifm, tb, ifname, 0);
1665errout: 1666errout:
1666 return err; 1667 return err;
1667} 1668}
@@ -1778,7 +1779,8 @@ err:
1778} 1779}
1779EXPORT_SYMBOL(rtnl_create_link); 1780EXPORT_SYMBOL(rtnl_create_link);
1780 1781
1781static int rtnl_group_changelink(struct net *net, int group, 1782static int rtnl_group_changelink(const struct sk_buff *skb,
1783 struct net *net, int group,
1782 struct ifinfomsg *ifm, 1784 struct ifinfomsg *ifm,
1783 struct nlattr **tb) 1785 struct nlattr **tb)
1784{ 1786{
@@ -1787,7 +1789,7 @@ static int rtnl_group_changelink(struct net *net, int group,
1787 1789
1788 for_each_netdev(net, dev) { 1790 for_each_netdev(net, dev) {
1789 if (dev->group == group) { 1791 if (dev->group == group) {
1790 err = do_setlink(dev, ifm, tb, NULL, 0); 1792 err = do_setlink(skb, dev, ifm, tb, NULL, 0);
1791 if (err < 0) 1793 if (err < 0)
1792 return err; 1794 return err;
1793 } 1795 }
@@ -1929,12 +1931,12 @@ replay:
1929 modified = 1; 1931 modified = 1;
1930 } 1932 }
1931 1933
1932 return do_setlink(dev, ifm, tb, ifname, modified); 1934 return do_setlink(skb, dev, ifm, tb, ifname, modified);
1933 } 1935 }
1934 1936
1935 if (!(nlh->nlmsg_flags & NLM_F_CREATE)) { 1937 if (!(nlh->nlmsg_flags & NLM_F_CREATE)) {
1936 if (ifm->ifi_index == 0 && tb[IFLA_GROUP]) 1938 if (ifm->ifi_index == 0 && tb[IFLA_GROUP])
1937 return rtnl_group_changelink(net, 1939 return rtnl_group_changelink(skb, net,
1938 nla_get_u32(tb[IFLA_GROUP]), 1940 nla_get_u32(tb[IFLA_GROUP]),
1939 ifm, tb); 1941 ifm, tb);
1940 return -ENODEV; 1942 return -ENODEV;
@@ -2321,7 +2323,7 @@ static int rtnl_fdb_del(struct sk_buff *skb, struct nlmsghdr *nlh)
2321 int err = -EINVAL; 2323 int err = -EINVAL;
2322 __u8 *addr; 2324 __u8 *addr;
2323 2325
2324 if (!capable(CAP_NET_ADMIN)) 2326 if (!netlink_capable(skb, CAP_NET_ADMIN))
2325 return -EPERM; 2327 return -EPERM;
2326 2328
2327 err = nlmsg_parse(nlh, sizeof(*ndm), tb, NDA_MAX, NULL); 2329 err = nlmsg_parse(nlh, sizeof(*ndm), tb, NDA_MAX, NULL);
@@ -2773,7 +2775,7 @@ static int rtnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
2773 sz_idx = type>>2; 2775 sz_idx = type>>2;
2774 kind = type&3; 2776 kind = type&3;
2775 2777
2776 if (kind != 2 && !ns_capable(net->user_ns, CAP_NET_ADMIN)) 2778 if (kind != 2 && !netlink_net_capable(skb, CAP_NET_ADMIN))
2777 return -EPERM; 2779 return -EPERM;
2778 2780
2779 if (kind == 2 && nlh->nlmsg_flags&NLM_F_DUMP) { 2781 if (kind == 2 && nlh->nlmsg_flags&NLM_F_DUMP) {