Skip to content

Commit bcf58e7

Browse files
committed
userns: Make create_new_namespaces take a user_ns parameter
Modify create_new_namespaces to explicitly take a user namespace parameter, instead of implicitly through the task_struct. This allows an implementation of unshare(CLONE_NEWUSER) where the new user namespace is not stored onto the current task_struct until after all of the namespaces are created. Acked-by: Serge Hallyn <[email protected]> Signed-off-by: "Eric W. Biederman" <[email protected]>
1 parent 142e1d1 commit bcf58e7

File tree

5 files changed

+28
-26
lines changed

5 files changed

+28
-26
lines changed

include/linux/ipc_namespace.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,8 @@ static inline int mq_init_ns(struct ipc_namespace *ns) { return 0; }
133133

134134
#if defined(CONFIG_IPC_NS)
135135
extern struct ipc_namespace *copy_ipcs(unsigned long flags,
136-
struct task_struct *tsk);
136+
struct user_namespace *user_ns, struct ipc_namespace *ns);
137+
137138
static inline struct ipc_namespace *get_ipc_ns(struct ipc_namespace *ns)
138139
{
139140
if (ns)
@@ -144,12 +145,12 @@ static inline struct ipc_namespace *get_ipc_ns(struct ipc_namespace *ns)
144145
extern void put_ipc_ns(struct ipc_namespace *ns);
145146
#else
146147
static inline struct ipc_namespace *copy_ipcs(unsigned long flags,
147-
struct task_struct *tsk)
148+
struct user_namespace *user_ns, struct ipc_namespace *ns)
148149
{
149150
if (flags & CLONE_NEWIPC)
150151
return ERR_PTR(-EINVAL);
151152

152-
return tsk->nsproxy->ipc_ns;
153+
return ns;
153154
}
154155

155156
static inline struct ipc_namespace *get_ipc_ns(struct ipc_namespace *ns)

include/linux/utsname.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ static inline void get_uts_ns(struct uts_namespace *ns)
3333
}
3434

3535
extern struct uts_namespace *copy_utsname(unsigned long flags,
36-
struct task_struct *tsk);
36+
struct user_namespace *user_ns, struct uts_namespace *old_ns);
3737
extern void free_uts_ns(struct kref *kref);
3838

3939
static inline void put_uts_ns(struct uts_namespace *ns)
@@ -50,12 +50,12 @@ static inline void put_uts_ns(struct uts_namespace *ns)
5050
}
5151

5252
static inline struct uts_namespace *copy_utsname(unsigned long flags,
53-
struct task_struct *tsk)
53+
struct user_namespace *user_ns, struct uts_namespace *old_ns)
5454
{
5555
if (flags & CLONE_NEWUTS)
5656
return ERR_PTR(-EINVAL);
5757

58-
return tsk->nsproxy->uts_ns;
58+
return old_ns;
5959
}
6060
#endif
6161

ipc/namespace.c

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616

1717
#include "util.h"
1818

19-
static struct ipc_namespace *create_ipc_ns(struct task_struct *tsk,
19+
static struct ipc_namespace *create_ipc_ns(struct user_namespace *user_ns,
2020
struct ipc_namespace *old_ns)
2121
{
2222
struct ipc_namespace *ns;
@@ -46,19 +46,17 @@ static struct ipc_namespace *create_ipc_ns(struct task_struct *tsk,
4646
ipcns_notify(IPCNS_CREATED);
4747
register_ipcns_notifier(ns);
4848

49-
ns->user_ns = get_user_ns(task_cred_xxx(tsk, user_ns));
49+
ns->user_ns = get_user_ns(user_ns);
5050

5151
return ns;
5252
}
5353

5454
struct ipc_namespace *copy_ipcs(unsigned long flags,
55-
struct task_struct *tsk)
55+
struct user_namespace *user_ns, struct ipc_namespace *ns)
5656
{
57-
struct ipc_namespace *ns = tsk->nsproxy->ipc_ns;
58-
5957
if (!(flags & CLONE_NEWIPC))
6058
return get_ipc_ns(ns);
61-
return create_ipc_ns(tsk, ns);
59+
return create_ipc_ns(user_ns, ns);
6260
}
6361

6462
/*

kernel/nsproxy.c

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,8 @@ static inline struct nsproxy *create_nsproxy(void)
5757
* leave it to the caller to do proper locking and attach it to task.
5858
*/
5959
static struct nsproxy *create_new_namespaces(unsigned long flags,
60-
struct task_struct *tsk, struct fs_struct *new_fs)
60+
struct task_struct *tsk, struct user_namespace *user_ns,
61+
struct fs_struct *new_fs)
6162
{
6263
struct nsproxy *new_nsp;
6364
int err;
@@ -66,31 +67,31 @@ static struct nsproxy *create_new_namespaces(unsigned long flags,
6667
if (!new_nsp)
6768
return ERR_PTR(-ENOMEM);
6869

69-
new_nsp->mnt_ns = copy_mnt_ns(flags, tsk->nsproxy->mnt_ns, task_cred_xxx(tsk, user_ns), new_fs);
70+
new_nsp->mnt_ns = copy_mnt_ns(flags, tsk->nsproxy->mnt_ns, user_ns, new_fs);
7071
if (IS_ERR(new_nsp->mnt_ns)) {
7172
err = PTR_ERR(new_nsp->mnt_ns);
7273
goto out_ns;
7374
}
7475

75-
new_nsp->uts_ns = copy_utsname(flags, tsk);
76+
new_nsp->uts_ns = copy_utsname(flags, user_ns, tsk->nsproxy->uts_ns);
7677
if (IS_ERR(new_nsp->uts_ns)) {
7778
err = PTR_ERR(new_nsp->uts_ns);
7879
goto out_uts;
7980
}
8081

81-
new_nsp->ipc_ns = copy_ipcs(flags, tsk);
82+
new_nsp->ipc_ns = copy_ipcs(flags, user_ns, tsk->nsproxy->ipc_ns);
8283
if (IS_ERR(new_nsp->ipc_ns)) {
8384
err = PTR_ERR(new_nsp->ipc_ns);
8485
goto out_ipc;
8586
}
8687

87-
new_nsp->pid_ns = copy_pid_ns(flags, task_cred_xxx(tsk, user_ns), tsk->nsproxy->pid_ns);
88+
new_nsp->pid_ns = copy_pid_ns(flags, user_ns, tsk->nsproxy->pid_ns);
8889
if (IS_ERR(new_nsp->pid_ns)) {
8990
err = PTR_ERR(new_nsp->pid_ns);
9091
goto out_pid;
9192
}
9293

93-
new_nsp->net_ns = copy_net_ns(flags, task_cred_xxx(tsk, user_ns), tsk->nsproxy->net_ns);
94+
new_nsp->net_ns = copy_net_ns(flags, user_ns, tsk->nsproxy->net_ns);
9495
if (IS_ERR(new_nsp->net_ns)) {
9596
err = PTR_ERR(new_nsp->net_ns);
9697
goto out_net;
@@ -152,7 +153,8 @@ int copy_namespaces(unsigned long flags, struct task_struct *tsk)
152153
goto out;
153154
}
154155

155-
new_ns = create_new_namespaces(flags, tsk, tsk->fs);
156+
new_ns = create_new_namespaces(flags, tsk,
157+
task_cred_xxx(tsk, user_ns), tsk->fs);
156158
if (IS_ERR(new_ns)) {
157159
err = PTR_ERR(new_ns);
158160
goto out;
@@ -186,6 +188,7 @@ void free_nsproxy(struct nsproxy *ns)
186188
int unshare_nsproxy_namespaces(unsigned long unshare_flags,
187189
struct nsproxy **new_nsp, struct fs_struct *new_fs)
188190
{
191+
struct user_namespace *user_ns;
189192
int err = 0;
190193

191194
if (!(unshare_flags & (CLONE_NEWNS | CLONE_NEWUTS | CLONE_NEWIPC |
@@ -195,7 +198,8 @@ int unshare_nsproxy_namespaces(unsigned long unshare_flags,
195198
if (!nsown_capable(CAP_SYS_ADMIN))
196199
return -EPERM;
197200

198-
*new_nsp = create_new_namespaces(unshare_flags, current,
201+
user_ns = current_user_ns();
202+
*new_nsp = create_new_namespaces(unshare_flags, current, user_ns,
199203
new_fs ? new_fs : current->fs);
200204
if (IS_ERR(*new_nsp)) {
201205
err = PTR_ERR(*new_nsp);
@@ -252,7 +256,7 @@ SYSCALL_DEFINE2(setns, int, fd, int, nstype)
252256
if (nstype && (ops->type != nstype))
253257
goto out;
254258

255-
new_nsproxy = create_new_namespaces(0, tsk, tsk->fs);
259+
new_nsproxy = create_new_namespaces(0, tsk, current_user_ns(), tsk->fs);
256260
if (IS_ERR(new_nsproxy)) {
257261
err = PTR_ERR(new_nsproxy);
258262
goto out;

kernel/utsname.c

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ static struct uts_namespace *create_uts_ns(void)
3232
* @old_ns: namespace to clone
3333
* Return NULL on error (failure to kmalloc), new ns otherwise
3434
*/
35-
static struct uts_namespace *clone_uts_ns(struct task_struct *tsk,
35+
static struct uts_namespace *clone_uts_ns(struct user_namespace *user_ns,
3636
struct uts_namespace *old_ns)
3737
{
3838
struct uts_namespace *ns;
@@ -43,7 +43,7 @@ static struct uts_namespace *clone_uts_ns(struct task_struct *tsk,
4343

4444
down_read(&uts_sem);
4545
memcpy(&ns->name, &old_ns->name, sizeof(ns->name));
46-
ns->user_ns = get_user_ns(task_cred_xxx(tsk, user_ns));
46+
ns->user_ns = get_user_ns(user_ns);
4747
up_read(&uts_sem);
4848
return ns;
4949
}
@@ -55,9 +55,8 @@ static struct uts_namespace *clone_uts_ns(struct task_struct *tsk,
5555
* versa.
5656
*/
5757
struct uts_namespace *copy_utsname(unsigned long flags,
58-
struct task_struct *tsk)
58+
struct user_namespace *user_ns, struct uts_namespace *old_ns)
5959
{
60-
struct uts_namespace *old_ns = tsk->nsproxy->uts_ns;
6160
struct uts_namespace *new_ns;
6261

6362
BUG_ON(!old_ns);
@@ -66,7 +65,7 @@ struct uts_namespace *copy_utsname(unsigned long flags,
6665
if (!(flags & CLONE_NEWUTS))
6766
return old_ns;
6867

69-
new_ns = clone_uts_ns(tsk, old_ns);
68+
new_ns = clone_uts_ns(user_ns, old_ns);
7069

7170
put_uts_ns(old_ns);
7271
return new_ns;

0 commit comments

Comments
 (0)