Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[NETLINK]: Use group numbers instead of bitmasks internally

Using the group number allows increasing the number of groups without
beeing limited by the size of the bitmask. It introduces one limitation
for netlink users: messages can't be broadcasted to multiple groups anymore,
however this feature was never used inside the kernel.

Signed-off-by: Patrick McHardy <kaber@trash.net>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Patrick McHardy and committed by
David S. Miller
d629b836 77247bbb

+21 -16
+1 -1
include/linux/netlink.h
··· 107 107 struct ucred creds; /* Skb credentials */ 108 108 __u32 pid; 109 109 __u32 dst_pid; 110 - __u32 dst_groups; 110 + __u32 dst_group; 111 111 kernel_cap_t eff_cap; 112 112 __u32 loginuid; /* Login (audit) uid */ 113 113 };
+20 -15
net/netlink/af_netlink.c
··· 67 67 u32 pid; 68 68 unsigned int groups; 69 69 u32 dst_pid; 70 - unsigned int dst_groups; 70 + u32 dst_group; 71 71 unsigned long state; 72 72 wait_queue_head_t wait; 73 73 struct netlink_callback *cb; ··· 115 115 static atomic_t nl_table_users = ATOMIC_INIT(0); 116 116 117 117 static struct notifier_block *netlink_chain; 118 + 119 + static u32 netlink_group_mask(u32 group) 120 + { 121 + return group ? 1 << (group - 1) : 0; 122 + } 118 123 119 124 static struct hlist_head *nl_pid_hashfn(struct nl_pid_hash *hash, u32 pid) 120 125 { ··· 538 533 if (addr->sa_family == AF_UNSPEC) { 539 534 sk->sk_state = NETLINK_UNCONNECTED; 540 535 nlk->dst_pid = 0; 541 - nlk->dst_groups = 0; 536 + nlk->dst_group = 0; 542 537 return 0; 543 538 } 544 539 if (addr->sa_family != AF_NETLINK) ··· 554 549 if (err == 0) { 555 550 sk->sk_state = NETLINK_CONNECTED; 556 551 nlk->dst_pid = nladdr->nl_pid; 557 - nlk->dst_groups = nladdr->nl_groups; 552 + nlk->dst_group = ffs(nladdr->nl_groups); 558 553 } 559 554 560 555 return err; ··· 572 567 573 568 if (peer) { 574 569 nladdr->nl_pid = nlk->dst_pid; 575 - nladdr->nl_groups = nlk->dst_groups; 570 + nladdr->nl_groups = netlink_group_mask(nlk->dst_group); 576 571 } else { 577 572 nladdr->nl_pid = nlk->pid; 578 - nladdr->nl_groups = nlk->groups; 573 + nladdr->nl_groups = nlk->groups; 579 574 } 580 575 return 0; 581 576 } ··· 776 771 if (p->exclude_sk == sk) 777 772 goto out; 778 773 779 - if (nlk->pid == p->pid || !(nlk->groups & p->group)) 774 + if (nlk->pid == p->pid || !(nlk->groups & netlink_group_mask(p->group))) 780 775 goto out; 781 776 782 777 if (p->failure) { ··· 872 867 if (sk == p->exclude_sk) 873 868 goto out; 874 869 875 - if (nlk->pid == p->pid || !(nlk->groups & p->group)) 870 + if (nlk->pid == p->pid || !(nlk->groups & netlink_group_mask(p->group))) 876 871 goto out; 877 872 878 873 sk->sk_err = p->code; ··· 918 913 struct netlink_sock *nlk = nlk_sk(sk); 919 914 struct sockaddr_nl *addr=msg->msg_name; 920 915 u32 dst_pid; 921 - u32 dst_groups; 916 + u32 dst_group; 922 917 struct sk_buff *skb; 923 918 int err; 924 919 struct scm_cookie scm; ··· 936 931 if (addr->nl_family != AF_NETLINK) 937 932 return -EINVAL; 938 933 dst_pid = addr->nl_pid; 939 - dst_groups = addr->nl_groups; 940 - if (dst_groups && !netlink_capable(sock, NL_NONROOT_SEND)) 934 + dst_group = ffs(addr->nl_groups); 935 + if (dst_group && !netlink_capable(sock, NL_NONROOT_SEND)) 941 936 return -EPERM; 942 937 } else { 943 938 dst_pid = nlk->dst_pid; 944 - dst_groups = nlk->dst_groups; 939 + dst_group = nlk->dst_group; 945 940 } 946 941 947 942 if (!nlk->pid) { ··· 960 955 961 956 NETLINK_CB(skb).pid = nlk->pid; 962 957 NETLINK_CB(skb).dst_pid = dst_pid; 963 - NETLINK_CB(skb).dst_groups = dst_groups; 958 + NETLINK_CB(skb).dst_group = dst_group; 964 959 NETLINK_CB(skb).loginuid = audit_get_loginuid(current->audit_context); 965 960 memcpy(NETLINK_CREDS(skb), &siocb->scm->creds, sizeof(struct ucred)); 966 961 ··· 982 977 goto out; 983 978 } 984 979 985 - if (dst_groups) { 980 + if (dst_group) { 986 981 atomic_inc(&skb->users); 987 - netlink_broadcast(sk, skb, dst_pid, dst_groups, GFP_KERNEL); 982 + netlink_broadcast(sk, skb, dst_pid, dst_group, GFP_KERNEL); 988 983 } 989 984 err = netlink_unicast(sk, skb, dst_pid, msg->msg_flags&MSG_DONTWAIT); 990 985 ··· 1030 1025 addr->nl_family = AF_NETLINK; 1031 1026 addr->nl_pad = 0; 1032 1027 addr->nl_pid = NETLINK_CB(skb).pid; 1033 - addr->nl_groups = NETLINK_CB(skb).dst_groups; 1028 + addr->nl_groups = netlink_group_mask(NETLINK_CB(skb).dst_group); 1034 1029 msg->msg_namelen = sizeof(*addr); 1035 1030 } 1036 1031