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