Commit 741a295130606143edbf9fc740f633dbc1e6225f

Authored by JANAK DESAI
Committed by Linus Torvalds
1 parent 99d1419d96

[PATCH] unshare system call -v5: unshare namespace

If the namespace structure is being shared, allocate a new one and copy
information from the current, shared, structure.

Signed-off-by: Janak Desai <janak@us.ibm.com>
Cc: Al Viro <viro@ftp.linux.org.uk>
Cc: Christoph Hellwig <hch@lst.de>
Cc: Michael Kerrisk <mtk-manpages@gmx.net>
Cc: Andi Kleen <ak@muc.de>
Cc: Paul Mackerras <paulus@samba.org>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>

Showing 3 changed files with 48 additions and 26 deletions Side-by-side Diff

... ... @@ -1325,27 +1325,17 @@
1325 1325 return retval;
1326 1326 }
1327 1327  
1328   -int copy_namespace(int flags, struct task_struct *tsk)
  1328 +/*
  1329 + * Allocate a new namespace structure and populate it with contents
  1330 + * copied from the namespace of the passed in task structure.
  1331 + */
  1332 +struct namespace *dup_namespace(struct task_struct *tsk, struct fs_struct *fs)
1329 1333 {
1330 1334 struct namespace *namespace = tsk->namespace;
1331 1335 struct namespace *new_ns;
1332 1336 struct vfsmount *rootmnt = NULL, *pwdmnt = NULL, *altrootmnt = NULL;
1333   - struct fs_struct *fs = tsk->fs;
1334 1337 struct vfsmount *p, *q;
1335 1338  
1336   - if (!namespace)
1337   - return 0;
1338   -
1339   - get_namespace(namespace);
1340   -
1341   - if (!(flags & CLONE_NEWNS))
1342   - return 0;
1343   -
1344   - if (!capable(CAP_SYS_ADMIN)) {
1345   - put_namespace(namespace);
1346   - return -EPERM;
1347   - }
1348   -
1349 1339 new_ns = kmalloc(sizeof(struct namespace), GFP_KERNEL);
1350 1340 if (!new_ns)
1351 1341 goto out;
... ... @@ -1396,8 +1386,6 @@
1396 1386 }
1397 1387 up_write(&namespace_sem);
1398 1388  
1399   - tsk->namespace = new_ns;
1400   -
1401 1389 if (rootmnt)
1402 1390 mntput(rootmnt);
1403 1391 if (pwdmnt)
1404 1392  
1405 1393  
... ... @@ -1405,12 +1393,40 @@
1405 1393 if (altrootmnt)
1406 1394 mntput(altrootmnt);
1407 1395  
1408   - put_namespace(namespace);
1409   - return 0;
  1396 +out:
  1397 + return new_ns;
  1398 +}
1410 1399  
  1400 +int copy_namespace(int flags, struct task_struct *tsk)
  1401 +{
  1402 + struct namespace *namespace = tsk->namespace;
  1403 + struct namespace *new_ns;
  1404 + int err = 0;
  1405 +
  1406 + if (!namespace)
  1407 + return 0;
  1408 +
  1409 + get_namespace(namespace);
  1410 +
  1411 + if (!(flags & CLONE_NEWNS))
  1412 + return 0;
  1413 +
  1414 + if (!capable(CAP_SYS_ADMIN)) {
  1415 + err = -EPERM;
  1416 + goto out;
  1417 + }
  1418 +
  1419 + new_ns = dup_namespace(tsk, tsk->fs);
  1420 + if (!new_ns) {
  1421 + err = -ENOMEM;
  1422 + goto out;
  1423 + }
  1424 +
  1425 + tsk->namespace = new_ns;
  1426 +
1411 1427 out:
1412 1428 put_namespace(namespace);
1413   - return -ENOMEM;
  1429 + return err;
1414 1430 }
1415 1431  
1416 1432 asmlinkage long sys_mount(char __user * dev_name, char __user * dir_name,
include/linux/namespace.h
... ... @@ -15,6 +15,7 @@
15 15  
16 16 extern int copy_namespace(int, struct task_struct *);
17 17 extern void __put_namespace(struct namespace *namespace);
  18 +extern struct namespace *dup_namespace(struct task_struct *, struct fs_struct *);
18 19  
19 20 static inline void put_namespace(struct namespace *namespace)
20 21 {
... ... @@ -1388,17 +1388,22 @@
1388 1388 }
1389 1389  
1390 1390 /*
1391   - * Unsharing of namespace for tasks created without CLONE_NEWNS is not
1392   - * supported yet
  1391 + * Unshare the namespace structure if it is being shared
1393 1392 */
1394   -static int unshare_namespace(unsigned long unshare_flags, struct namespace **new_nsp)
  1393 +static int unshare_namespace(unsigned long unshare_flags, struct namespace **new_nsp, struct fs_struct *new_fs)
1395 1394 {
1396 1395 struct namespace *ns = current->namespace;
1397 1396  
1398 1397 if ((unshare_flags & CLONE_NEWNS) &&
1399   - (ns && atomic_read(&ns->count) > 1))
1400   - return -EINVAL;
  1398 + (ns && atomic_read(&ns->count) > 1)) {
  1399 + if (!capable(CAP_SYS_ADMIN))
  1400 + return -EPERM;
1401 1401  
  1402 + *new_nsp = dup_namespace(current, new_fs ? new_fs : current->fs);
  1403 + if (!*new_nsp)
  1404 + return -ENOMEM;
  1405 + }
  1406 +
1402 1407 return 0;
1403 1408 }
1404 1409  
... ... @@ -1482,7 +1487,7 @@
1482 1487 goto bad_unshare_out;
1483 1488 if ((err = unshare_fs(unshare_flags, &new_fs)))
1484 1489 goto bad_unshare_cleanup_thread;
1485   - if ((err = unshare_namespace(unshare_flags, &new_ns)))
  1490 + if ((err = unshare_namespace(unshare_flags, &new_ns, new_fs)))
1486 1491 goto bad_unshare_cleanup_fs;
1487 1492 if ((err = unshare_sighand(unshare_flags, &new_sigh)))
1488 1493 goto bad_unshare_cleanup_ns;