aboutsummaryrefslogtreecommitdiffstats
path: root/net/netlink
diff options
context:
space:
mode:
Diffstat (limited to 'net/netlink')
-rw-r--r--net/netlink/af_netlink.c75
-rw-r--r--net/netlink/genetlink.c2
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
1367static 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 */
1377bool __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}
1382EXPORT_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 */
1394bool 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}
1399EXPORT_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 */
1410bool netlink_capable(const struct sk_buff *skb, int cap)
1411{
1412 return netlink_ns_capable(skb, &init_user_ns, cap);
1413}
1414EXPORT_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 */
1426bool 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}
1430EXPORT_SYMBOL(netlink_net_capable);
1431
1432static 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) {