Skip to content

Commit 49f4d8b

Browse files
committed
pidns: Capture the user namespace and filter ns_last_pid
- Capture the the user namespace that creates the pid namespace - Use that user namespace to test if it is ok to write to /proc/sys/kernel/ns_last_pid. Zhao Hongjiang <[email protected]> noticed I was missing a put_user_ns in when destroying a pid_ns. I have foloded his patch into this one so that bisects will work properly. Acked-by: Serge Hallyn <[email protected]> Signed-off-by: "Eric W. Biederman" <[email protected]>
1 parent ae06c7c commit 49f4d8b

File tree

4 files changed

+19
-9
lines changed

4 files changed

+19
-9
lines changed

include/linux/pid_namespace.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ struct pid_namespace {
3131
#ifdef CONFIG_BSD_PROCESS_ACCT
3232
struct bsd_acct_struct *bacct;
3333
#endif
34+
struct user_namespace *user_ns;
3435
kgid_t pid_gid;
3536
int hide_pid;
3637
int reboot; /* group exit code if this pidns was rebooted */
@@ -46,7 +47,8 @@ static inline struct pid_namespace *get_pid_ns(struct pid_namespace *ns)
4647
return ns;
4748
}
4849

49-
extern struct pid_namespace *copy_pid_ns(unsigned long flags, struct pid_namespace *ns);
50+
extern struct pid_namespace *copy_pid_ns(unsigned long flags,
51+
struct user_namespace *user_ns, struct pid_namespace *ns);
5052
extern void zap_pid_ns_processes(struct pid_namespace *pid_ns);
5153
extern int reboot_pid_ns(struct pid_namespace *pid_ns, int cmd);
5254
extern void put_pid_ns(struct pid_namespace *ns);
@@ -59,8 +61,8 @@ static inline struct pid_namespace *get_pid_ns(struct pid_namespace *ns)
5961
return ns;
6062
}
6163

62-
static inline struct pid_namespace *
63-
copy_pid_ns(unsigned long flags, struct pid_namespace *ns)
64+
static inline struct pid_namespace *copy_pid_ns(unsigned long flags,
65+
struct user_namespace *user_ns, struct pid_namespace *ns)
6466
{
6567
if (flags & CLONE_NEWPID)
6668
ns = ERR_PTR(-EINVAL);

kernel/nsproxy.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ static struct nsproxy *create_new_namespaces(unsigned long flags,
8484
goto out_ipc;
8585
}
8686

87-
new_nsp->pid_ns = copy_pid_ns(flags, task_active_pid_ns(tsk));
87+
new_nsp->pid_ns = copy_pid_ns(flags, task_cred_xxx(tsk, user_ns), task_active_pid_ns(tsk));
8888
if (IS_ERR(new_nsp->pid_ns)) {
8989
err = PTR_ERR(new_nsp->pid_ns);
9090
goto out_pid;

kernel/pid.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ struct pid_namespace init_pid_ns = {
7878
.last_pid = 0,
7979
.level = 0,
8080
.child_reaper = &init_task,
81+
.user_ns = &init_user_ns,
8182
};
8283
EXPORT_SYMBOL_GPL(init_pid_ns);
8384

kernel/pid_namespace.c

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
#include <linux/pid.h>
1212
#include <linux/pid_namespace.h>
13+
#include <linux/user_namespace.h>
1314
#include <linux/syscalls.h>
1415
#include <linux/err.h>
1516
#include <linux/acct.h>
@@ -74,7 +75,8 @@ static struct kmem_cache *create_pid_cachep(int nr_ids)
7475
/* MAX_PID_NS_LEVEL is needed for limiting size of 'struct pid' */
7576
#define MAX_PID_NS_LEVEL 32
7677

77-
static struct pid_namespace *create_pid_namespace(struct pid_namespace *parent_pid_ns)
78+
static struct pid_namespace *create_pid_namespace(struct user_namespace *user_ns,
79+
struct pid_namespace *parent_pid_ns)
7880
{
7981
struct pid_namespace *ns;
8082
unsigned int level = parent_pid_ns->level + 1;
@@ -102,6 +104,7 @@ static struct pid_namespace *create_pid_namespace(struct pid_namespace *parent_p
102104
kref_init(&ns->kref);
103105
ns->level = level;
104106
ns->parent = get_pid_ns(parent_pid_ns);
107+
ns->user_ns = get_user_ns(user_ns);
105108

106109
set_bit(0, ns->pidmap[0].page);
107110
atomic_set(&ns->pidmap[0].nr_free, BITS_PER_PAGE - 1);
@@ -117,6 +120,7 @@ static struct pid_namespace *create_pid_namespace(struct pid_namespace *parent_p
117120

118121
out_put_parent_pid_ns:
119122
put_pid_ns(parent_pid_ns);
123+
put_user_ns(user_ns);
120124
out_free_map:
121125
kfree(ns->pidmap[0].page);
122126
out_free:
@@ -131,16 +135,18 @@ static void destroy_pid_namespace(struct pid_namespace *ns)
131135

132136
for (i = 0; i < PIDMAP_ENTRIES; i++)
133137
kfree(ns->pidmap[i].page);
138+
put_user_ns(ns->user_ns);
134139
kmem_cache_free(pid_ns_cachep, ns);
135140
}
136141

137-
struct pid_namespace *copy_pid_ns(unsigned long flags, struct pid_namespace *old_ns)
142+
struct pid_namespace *copy_pid_ns(unsigned long flags,
143+
struct user_namespace *user_ns, struct pid_namespace *old_ns)
138144
{
139145
if (!(flags & CLONE_NEWPID))
140146
return get_pid_ns(old_ns);
141147
if (flags & (CLONE_THREAD|CLONE_PARENT))
142148
return ERR_PTR(-EINVAL);
143-
return create_pid_namespace(old_ns);
149+
return create_pid_namespace(user_ns, old_ns);
144150
}
145151

146152
static void free_pid_ns(struct kref *kref)
@@ -239,9 +245,10 @@ void zap_pid_ns_processes(struct pid_namespace *pid_ns)
239245
static int pid_ns_ctl_handler(struct ctl_table *table, int write,
240246
void __user *buffer, size_t *lenp, loff_t *ppos)
241247
{
248+
struct pid_namespace *pid_ns = task_active_pid_ns(current);
242249
struct ctl_table tmp = *table;
243250

244-
if (write && !capable(CAP_SYS_ADMIN))
251+
if (write && !ns_capable(pid_ns->user_ns, CAP_SYS_ADMIN))
245252
return -EPERM;
246253

247254
/*
@@ -250,7 +257,7 @@ static int pid_ns_ctl_handler(struct ctl_table *table, int write,
250257
* it should synchronize its usage with external means.
251258
*/
252259

253-
tmp.data = &current->nsproxy->pid_ns->last_pid;
260+
tmp.data = &pid_ns->last_pid;
254261
return proc_dointvec_minmax(&tmp, write, buffer, lenp, ppos);
255262
}
256263

0 commit comments

Comments
 (0)