Skip to content

Commit a878c02

Browse files
committed
Merge branch 'proc-per-ns'
Dmitry Torokhov says: ==================== Make /proc per net namespace objects belong to container Currently [almost] all /proc objects belong to the global root, even if data belongs to a given namespace within a container and (at least for sysctls) we work around permssions checks to allow container's root to access the data. This series changes ownership of net namespace /proc objects (/proc/net/self/* and /proc/sys/net/*) to be container's root and not global root when there exists mapping for container's root in user namespace. This helps when running Android CTS in a container, but I think it makes sense regardless. Changes from V1: - added fix for crash when !CONFIG_NET_NS (new patch #1) - addressed Eric'c comments for error handling style in patch #3 and added his Ack - adjusted patch #2 to use the same style of erro handling - sent out as series instead of separate patches ==================== Signed-off-by: David S. Miller <[email protected]>
2 parents d16d9d2 + e79c6a4 commit a878c02

File tree

6 files changed

+61
-13
lines changed

6 files changed

+61
-13
lines changed

fs/proc/generic.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -390,6 +390,8 @@ static struct proc_dir_entry *__proc_create(struct proc_dir_entry **parent,
390390
atomic_set(&ent->count, 1);
391391
spin_lock_init(&ent->pde_unload_lock);
392392
INIT_LIST_HEAD(&ent->pde_openers);
393+
proc_set_user(ent, (*parent)->uid, (*parent)->gid);
394+
393395
out:
394396
return ent;
395397
}

fs/proc/proc_net.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include <linux/bitops.h>
2222
#include <linux/mount.h>
2323
#include <linux/nsproxy.h>
24+
#include <linux/uidgid.h>
2425
#include <net/net_namespace.h>
2526
#include <linux/seq_file.h>
2627

@@ -185,6 +186,8 @@ const struct file_operations proc_net_operations = {
185186
static __net_init int proc_net_ns_init(struct net *net)
186187
{
187188
struct proc_dir_entry *netd, *net_statd;
189+
kuid_t uid;
190+
kgid_t gid;
188191
int err;
189192

190193
err = -ENOMEM;
@@ -199,6 +202,16 @@ static __net_init int proc_net_ns_init(struct net *net)
199202
netd->parent = &proc_root;
200203
memcpy(netd->name, "net", 4);
201204

205+
uid = make_kuid(net->user_ns, 0);
206+
if (!uid_valid(uid))
207+
uid = netd->uid;
208+
209+
gid = make_kgid(net->user_ns, 0);
210+
if (!gid_valid(gid))
211+
gid = netd->gid;
212+
213+
proc_set_user(netd, uid, gid);
214+
202215
err = -EEXIST;
203216
net_statd = proc_net_mkdir(net, "stat", netd);
204217
if (!net_statd)

fs/proc/proc_sysctl.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -430,6 +430,7 @@ static int sysctl_perm(struct ctl_table_header *head, struct ctl_table *table, i
430430
static struct inode *proc_sys_make_inode(struct super_block *sb,
431431
struct ctl_table_header *head, struct ctl_table *table)
432432
{
433+
struct ctl_table_root *root = head->root;
433434
struct inode *inode;
434435
struct proc_inode *ei;
435436

@@ -457,6 +458,10 @@ static struct inode *proc_sys_make_inode(struct super_block *sb,
457458
if (is_empty_dir(head))
458459
make_empty_dir_inode(inode);
459460
}
461+
462+
if (root->set_ownership)
463+
root->set_ownership(head, table, &inode->i_uid, &inode->i_gid);
464+
460465
out:
461466
return inode;
462467
}

include/linux/sysctl.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include <linux/rcupdate.h>
2626
#include <linux/wait.h>
2727
#include <linux/rbtree.h>
28+
#include <linux/uidgid.h>
2829
#include <uapi/linux/sysctl.h>
2930

3031
/* For the /proc/sys support */
@@ -157,6 +158,9 @@ struct ctl_table_root {
157158
struct ctl_table_set default_set;
158159
struct ctl_table_set *(*lookup)(struct ctl_table_root *root,
159160
struct nsproxy *namespaces);
161+
void (*set_ownership)(struct ctl_table_header *head,
162+
struct ctl_table *table,
163+
kuid_t *uid, kgid_t *gid);
160164
int (*permissions)(struct ctl_table_header *head, struct ctl_table *table);
161165
};
162166

net/core/net_namespace.c

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ struct net init_net = {
3737
};
3838
EXPORT_SYMBOL(init_net);
3939

40+
static bool init_net_initialized;
41+
4042
#define INITIAL_NET_GEN_PTRS 13 /* +1 for len +2 for rcu_head */
4143

4244
static unsigned int max_gen_ptrs = INITIAL_NET_GEN_PTRS;
@@ -750,6 +752,8 @@ static int __init net_ns_init(void)
750752
if (setup_net(&init_net, &init_user_ns))
751753
panic("Could not setup the initial network namespace");
752754

755+
init_net_initialized = true;
756+
753757
rtnl_lock();
754758
list_add_tail_rcu(&init_net.list, &net_namespace_list);
755759
rtnl_unlock();
@@ -811,15 +815,24 @@ static void __unregister_pernet_operations(struct pernet_operations *ops)
811815
static int __register_pernet_operations(struct list_head *list,
812816
struct pernet_operations *ops)
813817
{
818+
if (!init_net_initialized) {
819+
list_add_tail(&ops->list, list);
820+
return 0;
821+
}
822+
814823
return ops_init(ops, &init_net);
815824
}
816825

817826
static void __unregister_pernet_operations(struct pernet_operations *ops)
818827
{
819-
LIST_HEAD(net_exit_list);
820-
list_add(&init_net.exit_list, &net_exit_list);
821-
ops_exit_list(ops, &net_exit_list);
822-
ops_free_list(ops, &net_exit_list);
828+
if (!init_net_initialized) {
829+
list_del(&ops->list);
830+
} else {
831+
LIST_HEAD(net_exit_list);
832+
list_add(&init_net.exit_list, &net_exit_list);
833+
ops_exit_list(ops, &net_exit_list);
834+
ops_free_list(ops, &net_exit_list);
835+
}
823836
}
824837

825838
#endif /* CONFIG_NET_NS */

net/sysctl_net.c

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -42,26 +42,37 @@ static int net_ctl_permissions(struct ctl_table_header *head,
4242
struct ctl_table *table)
4343
{
4444
struct net *net = container_of(head->set, struct net, sysctls);
45-
kuid_t root_uid = make_kuid(net->user_ns, 0);
46-
kgid_t root_gid = make_kgid(net->user_ns, 0);
4745

4846
/* Allow network administrator to have same access as root. */
49-
if (ns_capable_noaudit(net->user_ns, CAP_NET_ADMIN) ||
50-
uid_eq(root_uid, current_euid())) {
47+
if (ns_capable(net->user_ns, CAP_NET_ADMIN)) {
5148
int mode = (table->mode >> 6) & 7;
5249
return (mode << 6) | (mode << 3) | mode;
5350
}
54-
/* Allow netns root group to have the same access as the root group */
55-
if (in_egroup_p(root_gid)) {
56-
int mode = (table->mode >> 3) & 7;
57-
return (mode << 3) | mode;
58-
}
51+
5952
return table->mode;
6053
}
6154

55+
static void net_ctl_set_ownership(struct ctl_table_header *head,
56+
struct ctl_table *table,
57+
kuid_t *uid, kgid_t *gid)
58+
{
59+
struct net *net = container_of(head->set, struct net, sysctls);
60+
kuid_t ns_root_uid;
61+
kgid_t ns_root_gid;
62+
63+
ns_root_uid = make_kuid(net->user_ns, 0);
64+
if (uid_valid(ns_root_uid))
65+
*uid = ns_root_uid;
66+
67+
ns_root_gid = make_kgid(net->user_ns, 0);
68+
if (gid_valid(ns_root_gid))
69+
*gid = ns_root_gid;
70+
}
71+
6272
static struct ctl_table_root net_sysctl_root = {
6373
.lookup = net_ctl_header_lookup,
6474
.permissions = net_ctl_permissions,
75+
.set_ownership = net_ctl_set_ownership,
6576
};
6677

6778
static int __net_init sysctl_net_init(struct net *net)

0 commit comments

Comments
 (0)