summaryrefslogtreecommitdiffstats
path: root/net/netlink
diff options
context:
space:
mode:
authorGao feng <gaofeng@cn.fujitsu.com>2013-06-06 02:49:11 -0400
committerDavid S. Miller <davem@davemloft.net>2013-06-11 05:39:42 -0400
commitda12c90e099789a63073fc82a19542ce54d4efb9 (patch)
treeb4343bfeaa8f929225268dd0ef3c92b31efbd4ae /net/netlink
parent8249152c472e10c18936b774737fd58c60335154 (diff)
netlink: Add compare function for netlink_table
As we know, netlink sockets are private resource of net namespace, they can communicate with each other only when they in the same net namespace. this works well until we try to add namespace support for other subsystems which use netlink. Don't like ipv4 and route table.., it is not suited to make these subsytems belong to net namespace, Such as audit and crypto subsystems,they are more suitable to user namespace. So we must have the ability to make the netlink sockets in same user namespace can communicate with each other. This patch adds a new function pointer "compare" for netlink_table, we can decide if the netlink sockets can communicate with each other through this netlink_table self-defined compare function. The behavior isn't changed if we don't provide the compare function for netlink_table. Signed-off-by: Gao feng <gaofeng@cn.fujitsu.com> Acked-by: Serge E. Hallyn <serge.hallyn@ubuntu.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/netlink')
-rw-r--r--net/netlink/af_netlink.c33
-rw-r--r--net/netlink/af_netlink.h1
2 files changed, 26 insertions, 8 deletions
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index 68c167374394..9b6b115e008f 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -858,16 +858,23 @@ netlink_unlock_table(void)
858 wake_up(&nl_table_wait); 858 wake_up(&nl_table_wait);
859} 859}
860 860
861static bool netlink_compare(struct net *net, struct sock *sk)
862{
863 return net_eq(sock_net(sk), net);
864}
865
861static struct sock *netlink_lookup(struct net *net, int protocol, u32 portid) 866static struct sock *netlink_lookup(struct net *net, int protocol, u32 portid)
862{ 867{
863 struct nl_portid_hash *hash = &nl_table[protocol].hash; 868 struct netlink_table *table = &nl_table[protocol];
869 struct nl_portid_hash *hash = &table->hash;
864 struct hlist_head *head; 870 struct hlist_head *head;
865 struct sock *sk; 871 struct sock *sk;
866 872
867 read_lock(&nl_table_lock); 873 read_lock(&nl_table_lock);
868 head = nl_portid_hashfn(hash, portid); 874 head = nl_portid_hashfn(hash, portid);
869 sk_for_each(sk, head) { 875 sk_for_each(sk, head) {
870 if (net_eq(sock_net(sk), net) && (nlk_sk(sk)->portid == portid)) { 876 if (table->compare(net, sk) &&
877 (nlk_sk(sk)->portid == portid)) {
871 sock_hold(sk); 878 sock_hold(sk);
872 goto found; 879 goto found;
873 } 880 }
@@ -980,7 +987,8 @@ netlink_update_listeners(struct sock *sk)
980 987
981static int netlink_insert(struct sock *sk, struct net *net, u32 portid) 988static int netlink_insert(struct sock *sk, struct net *net, u32 portid)
982{ 989{
983 struct nl_portid_hash *hash = &nl_table[sk->sk_protocol].hash; 990 struct netlink_table *table = &nl_table[sk->sk_protocol];
991 struct nl_portid_hash *hash = &table->hash;
984 struct hlist_head *head; 992 struct hlist_head *head;
985 int err = -EADDRINUSE; 993 int err = -EADDRINUSE;
986 struct sock *osk; 994 struct sock *osk;
@@ -990,7 +998,8 @@ static int netlink_insert(struct sock *sk, struct net *net, u32 portid)
990 head = nl_portid_hashfn(hash, portid); 998 head = nl_portid_hashfn(hash, portid);
991 len = 0; 999 len = 0;
992 sk_for_each(osk, head) { 1000 sk_for_each(osk, head) {
993 if (net_eq(sock_net(osk), net) && (nlk_sk(osk)->portid == portid)) 1001 if (table->compare(net, osk) &&
1002 (nlk_sk(osk)->portid == portid))
994 break; 1003 break;
995 len++; 1004 len++;
996 } 1005 }
@@ -1165,6 +1174,7 @@ static int netlink_release(struct socket *sock)
1165 kfree_rcu(old, rcu); 1174 kfree_rcu(old, rcu);
1166 nl_table[sk->sk_protocol].module = NULL; 1175 nl_table[sk->sk_protocol].module = NULL;
1167 nl_table[sk->sk_protocol].bind = NULL; 1176 nl_table[sk->sk_protocol].bind = NULL;
1177 nl_table[sk->sk_protocol].compare = NULL;
1168 nl_table[sk->sk_protocol].flags = 0; 1178 nl_table[sk->sk_protocol].flags = 0;
1169 nl_table[sk->sk_protocol].registered = 0; 1179 nl_table[sk->sk_protocol].registered = 0;
1170 } 1180 }
@@ -1187,7 +1197,8 @@ static int netlink_autobind(struct socket *sock)
1187{ 1197{
1188 struct sock *sk = sock->sk; 1198 struct sock *sk = sock->sk;
1189 struct net *net = sock_net(sk); 1199 struct net *net = sock_net(sk);
1190 struct nl_portid_hash *hash = &nl_table[sk->sk_protocol].hash; 1200 struct netlink_table *table = &nl_table[sk->sk_protocol];
1201 struct nl_portid_hash *hash = &table->hash;
1191 struct hlist_head *head; 1202 struct hlist_head *head;
1192 struct sock *osk; 1203 struct sock *osk;
1193 s32 portid = task_tgid_vnr(current); 1204 s32 portid = task_tgid_vnr(current);
@@ -1199,7 +1210,7 @@ retry:
1199 netlink_table_grab(); 1210 netlink_table_grab();
1200 head = nl_portid_hashfn(hash, portid); 1211 head = nl_portid_hashfn(hash, portid);
1201 sk_for_each(osk, head) { 1212 sk_for_each(osk, head) {
1202 if (!net_eq(sock_net(osk), net)) 1213 if (!table->compare(net, osk))
1203 continue; 1214 continue;
1204 if (nlk_sk(osk)->portid == portid) { 1215 if (nlk_sk(osk)->portid == portid) {
1205 /* Bind collision, search negative portid values. */ 1216 /* Bind collision, search negative portid values. */
@@ -2315,9 +2326,12 @@ __netlink_kernel_create(struct net *net, int unit, struct module *module,
2315 rcu_assign_pointer(nl_table[unit].listeners, listeners); 2326 rcu_assign_pointer(nl_table[unit].listeners, listeners);
2316 nl_table[unit].cb_mutex = cb_mutex; 2327 nl_table[unit].cb_mutex = cb_mutex;
2317 nl_table[unit].module = module; 2328 nl_table[unit].module = module;
2329 nl_table[unit].compare = netlink_compare;
2318 if (cfg) { 2330 if (cfg) {
2319 nl_table[unit].bind = cfg->bind; 2331 nl_table[unit].bind = cfg->bind;
2320 nl_table[unit].flags = cfg->flags; 2332 nl_table[unit].flags = cfg->flags;
2333 if (cfg->compare)
2334 nl_table[unit].compare = cfg->compare;
2321 } 2335 }
2322 nl_table[unit].registered = 1; 2336 nl_table[unit].registered = 1;
2323 } else { 2337 } else {
@@ -2740,6 +2754,7 @@ static void *netlink_seq_next(struct seq_file *seq, void *v, loff_t *pos)
2740{ 2754{
2741 struct sock *s; 2755 struct sock *s;
2742 struct nl_seq_iter *iter; 2756 struct nl_seq_iter *iter;
2757 struct net *net;
2743 int i, j; 2758 int i, j;
2744 2759
2745 ++*pos; 2760 ++*pos;
@@ -2747,11 +2762,12 @@ static void *netlink_seq_next(struct seq_file *seq, void *v, loff_t *pos)
2747 if (v == SEQ_START_TOKEN) 2762 if (v == SEQ_START_TOKEN)
2748 return netlink_seq_socket_idx(seq, 0); 2763 return netlink_seq_socket_idx(seq, 0);
2749 2764
2765 net = seq_file_net(seq);
2750 iter = seq->private; 2766 iter = seq->private;
2751 s = v; 2767 s = v;
2752 do { 2768 do {
2753 s = sk_next(s); 2769 s = sk_next(s);
2754 } while (s && sock_net(s) != seq_file_net(seq)); 2770 } while (s && !nl_table[s->sk_protocol].compare(net, s));
2755 if (s) 2771 if (s)
2756 return s; 2772 return s;
2757 2773
@@ -2763,7 +2779,8 @@ static void *netlink_seq_next(struct seq_file *seq, void *v, loff_t *pos)
2763 2779
2764 for (; j <= hash->mask; j++) { 2780 for (; j <= hash->mask; j++) {
2765 s = sk_head(&hash->table[j]); 2781 s = sk_head(&hash->table[j]);
2766 while (s && sock_net(s) != seq_file_net(seq)) 2782
2783 while (s && !nl_table[s->sk_protocol].compare(net, s))
2767 s = sk_next(s); 2784 s = sk_next(s);
2768 if (s) { 2785 if (s) {
2769 iter->link = i; 2786 iter->link = i;
diff --git a/net/netlink/af_netlink.h b/net/netlink/af_netlink.h
index ed8522265f4e..eaa88d187cdc 100644
--- a/net/netlink/af_netlink.h
+++ b/net/netlink/af_netlink.h
@@ -73,6 +73,7 @@ struct netlink_table {
73 struct mutex *cb_mutex; 73 struct mutex *cb_mutex;
74 struct module *module; 74 struct module *module;
75 void (*bind)(int group); 75 void (*bind)(int group);
76 bool (*compare)(struct net *net, struct sock *sock);
76 int registered; 77 int registered;
77}; 78};
78 79