diff options
Diffstat (limited to 'net/netlink')
-rw-r--r-- | net/netlink/af_netlink.c | 75 | ||||
-rw-r--r-- | net/netlink/genetlink.c | 2 |
2 files changed, 71 insertions, 6 deletions
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index 92f4b6915e89..e0ccd84d4d67 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c | |||
@@ -1364,7 +1364,72 @@ retry: | |||
1364 | return err; | 1364 | return err; |
1365 | } | 1365 | } |
1366 | 1366 | ||
1367 | static inline int netlink_capable(const struct socket *sock, unsigned int flag) | 1367 | /** |
1368 | * __netlink_ns_capable - General netlink message capability test | ||
1369 | * @nsp: NETLINK_CB of the socket buffer holding a netlink command from userspace. | ||
1370 | * @user_ns: The user namespace of the capability to use | ||
1371 | * @cap: The capability to use | ||
1372 | * | ||
1373 | * Test to see if the opener of the socket we received the message | ||
1374 | * from had when the netlink socket was created and the sender of the | ||
1375 | * message has has the capability @cap in the user namespace @user_ns. | ||
1376 | */ | ||
1377 | bool __netlink_ns_capable(const struct netlink_skb_parms *nsp, | ||
1378 | struct user_namespace *user_ns, int cap) | ||
1379 | { | ||
1380 | return sk_ns_capable(nsp->sk, user_ns, cap); | ||
1381 | } | ||
1382 | EXPORT_SYMBOL(__netlink_ns_capable); | ||
1383 | |||
1384 | /** | ||
1385 | * netlink_ns_capable - General netlink message capability test | ||
1386 | * @skb: socket buffer holding a netlink command from userspace | ||
1387 | * @user_ns: The user namespace of the capability to use | ||
1388 | * @cap: The capability to use | ||
1389 | * | ||
1390 | * Test to see if the opener of the socket we received the message | ||
1391 | * from had when the netlink socket was created and the sender of the | ||
1392 | * message has has the capability @cap in the user namespace @user_ns. | ||
1393 | */ | ||
1394 | bool netlink_ns_capable(const struct sk_buff *skb, | ||
1395 | struct user_namespace *user_ns, int cap) | ||
1396 | { | ||
1397 | return __netlink_ns_capable(&NETLINK_CB(skb), user_ns, cap); | ||
1398 | } | ||
1399 | EXPORT_SYMBOL(netlink_ns_capable); | ||
1400 | |||
1401 | /** | ||
1402 | * netlink_capable - Netlink global message capability test | ||
1403 | * @skb: socket buffer holding a netlink command from userspace | ||
1404 | * @cap: The capability to use | ||
1405 | * | ||
1406 | * Test to see if the opener of the socket we received the message | ||
1407 | * from had when the netlink socket was created and the sender of the | ||
1408 | * message has has the capability @cap in all user namespaces. | ||
1409 | */ | ||
1410 | bool netlink_capable(const struct sk_buff *skb, int cap) | ||
1411 | { | ||
1412 | return netlink_ns_capable(skb, &init_user_ns, cap); | ||
1413 | } | ||
1414 | EXPORT_SYMBOL(netlink_capable); | ||
1415 | |||
1416 | /** | ||
1417 | * netlink_net_capable - Netlink network namespace message capability test | ||
1418 | * @skb: socket buffer holding a netlink command from userspace | ||
1419 | * @cap: The capability to use | ||
1420 | * | ||
1421 | * Test to see if the opener of the socket we received the message | ||
1422 | * from had when the netlink socket was created and the sender of the | ||
1423 | * message has has the capability @cap over the network namespace of | ||
1424 | * the socket we received the message from. | ||
1425 | */ | ||
1426 | bool netlink_net_capable(const struct sk_buff *skb, int cap) | ||
1427 | { | ||
1428 | return netlink_ns_capable(skb, sock_net(skb->sk)->user_ns, cap); | ||
1429 | } | ||
1430 | EXPORT_SYMBOL(netlink_net_capable); | ||
1431 | |||
1432 | static inline int netlink_allowed(const struct socket *sock, unsigned int flag) | ||
1368 | { | 1433 | { |
1369 | return (nl_table[sock->sk->sk_protocol].flags & flag) || | 1434 | return (nl_table[sock->sk->sk_protocol].flags & flag) || |
1370 | ns_capable(sock_net(sock->sk)->user_ns, CAP_NET_ADMIN); | 1435 | ns_capable(sock_net(sock->sk)->user_ns, CAP_NET_ADMIN); |
@@ -1446,7 +1511,7 @@ static int netlink_bind(struct socket *sock, struct sockaddr *addr, | |||
1446 | 1511 | ||
1447 | /* Only superuser is allowed to listen multicasts */ | 1512 | /* Only superuser is allowed to listen multicasts */ |
1448 | if (groups) { | 1513 | if (groups) { |
1449 | if (!netlink_capable(sock, NL_CFG_F_NONROOT_RECV)) | 1514 | if (!netlink_allowed(sock, NL_CFG_F_NONROOT_RECV)) |
1450 | return -EPERM; | 1515 | return -EPERM; |
1451 | err = netlink_realloc_groups(sk); | 1516 | err = netlink_realloc_groups(sk); |
1452 | if (err) | 1517 | if (err) |
@@ -1516,7 +1581,7 @@ static int netlink_connect(struct socket *sock, struct sockaddr *addr, | |||
1516 | return -EINVAL; | 1581 | return -EINVAL; |
1517 | 1582 | ||
1518 | if ((nladdr->nl_groups || nladdr->nl_pid) && | 1583 | if ((nladdr->nl_groups || nladdr->nl_pid) && |
1519 | !netlink_capable(sock, NL_CFG_F_NONROOT_SEND)) | 1584 | !netlink_allowed(sock, NL_CFG_F_NONROOT_SEND)) |
1520 | return -EPERM; | 1585 | return -EPERM; |
1521 | 1586 | ||
1522 | if (!nlk->portid) | 1587 | if (!nlk->portid) |
@@ -2122,7 +2187,7 @@ static int netlink_setsockopt(struct socket *sock, int level, int optname, | |||
2122 | break; | 2187 | break; |
2123 | case NETLINK_ADD_MEMBERSHIP: | 2188 | case NETLINK_ADD_MEMBERSHIP: |
2124 | case NETLINK_DROP_MEMBERSHIP: { | 2189 | case NETLINK_DROP_MEMBERSHIP: { |
2125 | if (!netlink_capable(sock, NL_CFG_F_NONROOT_RECV)) | 2190 | if (!netlink_allowed(sock, NL_CFG_F_NONROOT_RECV)) |
2126 | return -EPERM; | 2191 | return -EPERM; |
2127 | err = netlink_realloc_groups(sk); | 2192 | err = netlink_realloc_groups(sk); |
2128 | if (err) | 2193 | if (err) |
@@ -2277,7 +2342,7 @@ static int netlink_sendmsg(struct kiocb *kiocb, struct socket *sock, | |||
2277 | dst_group = ffs(addr->nl_groups); | 2342 | dst_group = ffs(addr->nl_groups); |
2278 | err = -EPERM; | 2343 | err = -EPERM; |
2279 | if ((dst_group || dst_portid) && | 2344 | if ((dst_group || dst_portid) && |
2280 | !netlink_capable(sock, NL_CFG_F_NONROOT_SEND)) | 2345 | !netlink_allowed(sock, NL_CFG_F_NONROOT_SEND)) |
2281 | goto out; | 2346 | goto out; |
2282 | } else { | 2347 | } else { |
2283 | dst_portid = nlk->dst_portid; | 2348 | dst_portid = nlk->dst_portid; |
diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c index b1dcdb932a86..a3ba3ca0ff92 100644 --- a/net/netlink/genetlink.c +++ b/net/netlink/genetlink.c | |||
@@ -561,7 +561,7 @@ static int genl_family_rcv_msg(struct genl_family *family, | |||
561 | return -EOPNOTSUPP; | 561 | return -EOPNOTSUPP; |
562 | 562 | ||
563 | if ((ops->flags & GENL_ADMIN_PERM) && | 563 | if ((ops->flags & GENL_ADMIN_PERM) && |
564 | !capable(CAP_NET_ADMIN)) | 564 | !netlink_capable(skb, CAP_NET_ADMIN)) |
565 | return -EPERM; | 565 | return -EPERM; |
566 | 566 | ||
567 | if ((nlh->nlmsg_flags & NLM_F_DUMP) == NLM_F_DUMP) { | 567 | if ((nlh->nlmsg_flags & NLM_F_DUMP) == NLM_F_DUMP) { |