15
15
#include <linux/file.h>
16
16
#include <linux/export.h>
17
17
#include <linux/user_namespace.h>
18
+ #include <linux/net_namespace.h>
19
+ #include <linux/rtnetlink.h>
20
+ #include <net/sock.h>
21
+ #include <net/netlink.h>
18
22
#include <net/net_namespace.h>
19
23
#include <net/netns/generic.h>
20
24
@@ -144,6 +148,77 @@ static void ops_free_list(const struct pernet_operations *ops,
144
148
}
145
149
}
146
150
151
+ static int alloc_netid (struct net * net , struct net * peer , int reqid )
152
+ {
153
+ int min = 0 , max = 0 ;
154
+
155
+ ASSERT_RTNL ();
156
+
157
+ if (reqid >= 0 ) {
158
+ min = reqid ;
159
+ max = reqid + 1 ;
160
+ }
161
+
162
+ return idr_alloc (& net -> netns_ids , peer , min , max , GFP_KERNEL );
163
+ }
164
+
165
+ /* This function is used by idr_for_each(). If net is equal to peer, the
166
+ * function returns the id so that idr_for_each() stops. Because we cannot
167
+ * returns the id 0 (idr_for_each() will not stop), we return the magic value
168
+ * NET_ID_ZERO (-1) for it.
169
+ */
170
+ #define NET_ID_ZERO -1
171
+ static int net_eq_idr (int id , void * net , void * peer )
172
+ {
173
+ if (net_eq (net , peer ))
174
+ return id ? : NET_ID_ZERO ;
175
+ return 0 ;
176
+ }
177
+
178
+ static int __peernet2id (struct net * net , struct net * peer , bool alloc )
179
+ {
180
+ int id = idr_for_each (& net -> netns_ids , net_eq_idr , peer );
181
+
182
+ ASSERT_RTNL ();
183
+
184
+ /* Magic value for id 0. */
185
+ if (id == NET_ID_ZERO )
186
+ return 0 ;
187
+ if (id > 0 )
188
+ return id ;
189
+
190
+ if (alloc )
191
+ return alloc_netid (net , peer , -1 );
192
+
193
+ return - ENOENT ;
194
+ }
195
+
196
+ /* This function returns the id of a peer netns. If no id is assigned, one will
197
+ * be allocated and returned.
198
+ */
199
+ int peernet2id (struct net * net , struct net * peer )
200
+ {
201
+ int id = __peernet2id (net , peer , true);
202
+
203
+ return id >= 0 ? id : NETNSA_NSID_NOT_ASSIGNED ;
204
+ }
205
+
206
+ struct net * get_net_ns_by_id (struct net * net , int id )
207
+ {
208
+ struct net * peer ;
209
+
210
+ if (id < 0 )
211
+ return NULL ;
212
+
213
+ rcu_read_lock ();
214
+ peer = idr_find (& net -> netns_ids , id );
215
+ if (peer )
216
+ get_net (peer );
217
+ rcu_read_unlock ();
218
+
219
+ return peer ;
220
+ }
221
+
147
222
/*
148
223
* setup_net runs the initializers for the network namespace object.
149
224
*/
@@ -158,6 +233,7 @@ static __net_init int setup_net(struct net *net, struct user_namespace *user_ns)
158
233
atomic_set (& net -> passive , 1 );
159
234
net -> dev_base_seq = 1 ;
160
235
net -> user_ns = user_ns ;
236
+ idr_init (& net -> netns_ids );
161
237
162
238
#ifdef NETNS_REFCNT_DEBUG
163
239
atomic_set (& net -> use_count , 0 );
@@ -288,6 +364,14 @@ static void cleanup_net(struct work_struct *work)
288
364
list_for_each_entry (net , & net_kill_list , cleanup_list ) {
289
365
list_del_rcu (& net -> list );
290
366
list_add_tail (& net -> exit_list , & net_exit_list );
367
+ for_each_net (tmp ) {
368
+ int id = __peernet2id (tmp , net , false);
369
+
370
+ if (id >= 0 )
371
+ idr_remove (& tmp -> netns_ids , id );
372
+ }
373
+ idr_destroy (& net -> netns_ids );
374
+
291
375
}
292
376
rtnl_unlock ();
293
377
@@ -402,6 +486,130 @@ static struct pernet_operations __net_initdata net_ns_ops = {
402
486
.exit = net_ns_net_exit ,
403
487
};
404
488
489
+ static struct nla_policy rtnl_net_policy [NETNSA_MAX + 1 ] = {
490
+ [NETNSA_NONE ] = { .type = NLA_UNSPEC },
491
+ [NETNSA_NSID ] = { .type = NLA_S32 },
492
+ [NETNSA_PID ] = { .type = NLA_U32 },
493
+ [NETNSA_FD ] = { .type = NLA_U32 },
494
+ };
495
+
496
+ static int rtnl_net_newid (struct sk_buff * skb , struct nlmsghdr * nlh )
497
+ {
498
+ struct net * net = sock_net (skb -> sk );
499
+ struct nlattr * tb [NETNSA_MAX + 1 ];
500
+ struct net * peer ;
501
+ int nsid , err ;
502
+
503
+ err = nlmsg_parse (nlh , sizeof (struct rtgenmsg ), tb , NETNSA_MAX ,
504
+ rtnl_net_policy );
505
+ if (err < 0 )
506
+ return err ;
507
+ if (!tb [NETNSA_NSID ])
508
+ return - EINVAL ;
509
+ nsid = nla_get_s32 (tb [NETNSA_NSID ]);
510
+
511
+ if (tb [NETNSA_PID ])
512
+ peer = get_net_ns_by_pid (nla_get_u32 (tb [NETNSA_PID ]));
513
+ else if (tb [NETNSA_FD ])
514
+ peer = get_net_ns_by_fd (nla_get_u32 (tb [NETNSA_FD ]));
515
+ else
516
+ return - EINVAL ;
517
+ if (IS_ERR (peer ))
518
+ return PTR_ERR (peer );
519
+
520
+ if (__peernet2id (net , peer , false) >= 0 ) {
521
+ err = - EEXIST ;
522
+ goto out ;
523
+ }
524
+
525
+ err = alloc_netid (net , peer , nsid );
526
+ if (err > 0 )
527
+ err = 0 ;
528
+ out :
529
+ put_net (peer );
530
+ return err ;
531
+ }
532
+
533
+ static int rtnl_net_get_size (void )
534
+ {
535
+ return NLMSG_ALIGN (sizeof (struct rtgenmsg ))
536
+ + nla_total_size (sizeof (s32 )) /* NETNSA_NSID */
537
+ ;
538
+ }
539
+
540
+ static int rtnl_net_fill (struct sk_buff * skb , u32 portid , u32 seq , int flags ,
541
+ int cmd , struct net * net , struct net * peer )
542
+ {
543
+ struct nlmsghdr * nlh ;
544
+ struct rtgenmsg * rth ;
545
+ int id ;
546
+
547
+ ASSERT_RTNL ();
548
+
549
+ nlh = nlmsg_put (skb , portid , seq , cmd , sizeof (* rth ), flags );
550
+ if (!nlh )
551
+ return - EMSGSIZE ;
552
+
553
+ rth = nlmsg_data (nlh );
554
+ rth -> rtgen_family = AF_UNSPEC ;
555
+
556
+ id = __peernet2id (net , peer , false);
557
+ if (id < 0 )
558
+ id = NETNSA_NSID_NOT_ASSIGNED ;
559
+ if (nla_put_s32 (skb , NETNSA_NSID , id ))
560
+ goto nla_put_failure ;
561
+
562
+ nlmsg_end (skb , nlh );
563
+ return 0 ;
564
+
565
+ nla_put_failure :
566
+ nlmsg_cancel (skb , nlh );
567
+ return - EMSGSIZE ;
568
+ }
569
+
570
+ static int rtnl_net_getid (struct sk_buff * skb , struct nlmsghdr * nlh )
571
+ {
572
+ struct net * net = sock_net (skb -> sk );
573
+ struct nlattr * tb [NETNSA_MAX + 1 ];
574
+ struct sk_buff * msg ;
575
+ int err = - ENOBUFS ;
576
+ struct net * peer ;
577
+
578
+ err = nlmsg_parse (nlh , sizeof (struct rtgenmsg ), tb , NETNSA_MAX ,
579
+ rtnl_net_policy );
580
+ if (err < 0 )
581
+ return err ;
582
+ if (tb [NETNSA_PID ])
583
+ peer = get_net_ns_by_pid (nla_get_u32 (tb [NETNSA_PID ]));
584
+ else if (tb [NETNSA_FD ])
585
+ peer = get_net_ns_by_fd (nla_get_u32 (tb [NETNSA_FD ]));
586
+ else
587
+ return - EINVAL ;
588
+
589
+ if (IS_ERR (peer ))
590
+ return PTR_ERR (peer );
591
+
592
+ msg = nlmsg_new (rtnl_net_get_size (), GFP_KERNEL );
593
+ if (!msg ) {
594
+ err = - ENOMEM ;
595
+ goto out ;
596
+ }
597
+
598
+ err = rtnl_net_fill (msg , NETLINK_CB (skb ).portid , nlh -> nlmsg_seq , 0 ,
599
+ RTM_GETNSID , net , peer );
600
+ if (err < 0 )
601
+ goto err_out ;
602
+
603
+ err = rtnl_unicast (msg , net , NETLINK_CB (skb ).portid );
604
+ goto out ;
605
+
606
+ err_out :
607
+ nlmsg_free (msg );
608
+ out :
609
+ put_net (peer );
610
+ return err ;
611
+ }
612
+
405
613
static int __init net_ns_init (void )
406
614
{
407
615
struct net_generic * ng ;
@@ -435,6 +643,9 @@ static int __init net_ns_init(void)
435
643
436
644
register_pernet_subsys (& net_ns_ops );
437
645
646
+ rtnl_register (PF_UNSPEC , RTM_NEWNSID , rtnl_net_newid , NULL , NULL );
647
+ rtnl_register (PF_UNSPEC , RTM_GETNSID , rtnl_net_getid , NULL , NULL );
648
+
438
649
return 0 ;
439
650
}
440
651
0 commit comments