Commit 9bfb23fc4a481650e60d22dbe84c0fd5a9d49bba

Authored by Oleg Nesterov
Committed by Linus Torvalds
1 parent 4d51985e48

sys_unshare: remove the dead CLONE_THREAD/SIGHAND/VM code

Cleanup: kill the dead code which does nothing but complicates the code
and confuses the reader.

sys_unshare(CLONE_THREAD/SIGHAND/VM) is not really implemented, and I
doubt very much it will ever work.  At least, nobody even tried since the
original 99d1419d96d7df9cfa56 ("unshare system call -v5: system call
handler function") was applied more than 4 years ago.

And the code is not consistent.  unshare_thread() always fails
unconditionally, while unshare_sighand() and unshare_vm() pretend to work
if there is nothing to unshare.

Remove unshare_thread(), unshare_sighand(), unshare_vm() helpers and
related variables and add a simple CLONE_THREAD | CLONE_SIGHAND| CLONE_VM
check into check_unshare_flags().

Also, move the "CLONE_NEWNS needs CLONE_FS" check from
check_unshare_flags() to sys_unshare().  This looks more consistent and
matches the similar do_sysvsem check in sys_unshare().

Note: with or without this patch "atomic_read(mm->mm_users) > 1" can give
a false positive due to get_task_mm().

Signed-off-by: Oleg Nesterov <oleg@redhat.com>
Acked-by: Roland McGrath <roland@redhat.com>
Cc: Janak Desai <janak@us.ibm.com>
Cc: Daniel Lezcano <daniel.lezcano@free.fr>
Cc: "Eric W. Biederman" <ebiederm@xmission.com>
Cc: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com>
Cc: Alexey Dobriyan <adobriyan@gmail.com>
Acked-by: Serge Hallyn <serge.hallyn@canonical.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

Showing 1 changed file with 25 additions and 98 deletions Side-by-side Diff

... ... @@ -1519,39 +1519,25 @@
1519 1519 }
1520 1520  
1521 1521 /*
1522   - * Check constraints on flags passed to the unshare system call and
1523   - * force unsharing of additional process context as appropriate.
  1522 + * Check constraints on flags passed to the unshare system call.
1524 1523 */
1525   -static void check_unshare_flags(unsigned long *flags_ptr)
  1524 +static int check_unshare_flags(unsigned long unshare_flags)
1526 1525 {
  1526 + if (unshare_flags & ~(CLONE_THREAD|CLONE_FS|CLONE_NEWNS|CLONE_SIGHAND|
  1527 + CLONE_VM|CLONE_FILES|CLONE_SYSVSEM|
  1528 + CLONE_NEWUTS|CLONE_NEWIPC|CLONE_NEWNET))
  1529 + return -EINVAL;
1527 1530 /*
1528   - * If unsharing a thread from a thread group, must also
1529   - * unshare vm.
  1531 + * Not implemented, but pretend it works if there is nothing to
  1532 + * unshare. Note that unsharing CLONE_THREAD or CLONE_SIGHAND
  1533 + * needs to unshare vm.
1530 1534 */
1531   - if (*flags_ptr & CLONE_THREAD)
1532   - *flags_ptr |= CLONE_VM;
  1535 + if (unshare_flags & (CLONE_THREAD | CLONE_SIGHAND | CLONE_VM)) {
  1536 + /* FIXME: get_task_mm() increments ->mm_users */
  1537 + if (atomic_read(&current->mm->mm_users) > 1)
  1538 + return -EINVAL;
  1539 + }
1533 1540  
1534   - /*
1535   - * If unsharing vm, must also unshare signal handlers.
1536   - */
1537   - if (*flags_ptr & CLONE_VM)
1538   - *flags_ptr |= CLONE_SIGHAND;
1539   -
1540   - /*
1541   - * If unsharing namespace, must also unshare filesystem information.
1542   - */
1543   - if (*flags_ptr & CLONE_NEWNS)
1544   - *flags_ptr |= CLONE_FS;
1545   -}
1546   -
1547   -/*
1548   - * Unsharing of tasks created with CLONE_THREAD is not supported yet
1549   - */
1550   -static int unshare_thread(unsigned long unshare_flags)
1551   -{
1552   - if (unshare_flags & CLONE_THREAD)
1553   - return -EINVAL;
1554   -
1555 1541 return 0;
1556 1542 }
1557 1543  
... ... @@ -1577,34 +1563,6 @@
1577 1563 }
1578 1564  
1579 1565 /*
1580   - * Unsharing of sighand is not supported yet
1581   - */
1582   -static int unshare_sighand(unsigned long unshare_flags, struct sighand_struct **new_sighp)
1583   -{
1584   - struct sighand_struct *sigh = current->sighand;
1585   -
1586   - if ((unshare_flags & CLONE_SIGHAND) && atomic_read(&sigh->count) > 1)
1587   - return -EINVAL;
1588   - else
1589   - return 0;
1590   -}
1591   -
1592   -/*
1593   - * Unshare vm if it is being shared
1594   - */
1595   -static int unshare_vm(unsigned long unshare_flags, struct mm_struct **new_mmp)
1596   -{
1597   - struct mm_struct *mm = current->mm;
1598   -
1599   - if ((unshare_flags & CLONE_VM) &&
1600   - (mm && atomic_read(&mm->mm_users) > 1)) {
1601   - return -EINVAL;
1602   - }
1603   -
1604   - return 0;
1605   -}
1606   -
1607   -/*
1608 1566 * Unshare file descriptor table if it is being shared
1609 1567 */
1610 1568 static int unshare_fd(unsigned long unshare_flags, struct files_struct **new_fdp)
1611 1569  
1612 1570  
1613 1571  
1614 1572  
1615 1573  
1616 1574  
1617 1575  
1618 1576  
... ... @@ -1632,45 +1590,37 @@
1632 1590 */
1633 1591 SYSCALL_DEFINE1(unshare, unsigned long, unshare_flags)
1634 1592 {
1635   - int err = 0;
1636 1593 struct fs_struct *fs, *new_fs = NULL;
1637   - struct sighand_struct *new_sigh = NULL;
1638   - struct mm_struct *mm, *new_mm = NULL, *active_mm = NULL;
1639 1594 struct files_struct *fd, *new_fd = NULL;
1640 1595 struct nsproxy *new_nsproxy = NULL;
1641 1596 int do_sysvsem = 0;
  1597 + int err;
1642 1598  
1643   - check_unshare_flags(&unshare_flags);
1644   -
1645   - /* Return -EINVAL for all unsupported flags */
1646   - err = -EINVAL;
1647   - if (unshare_flags & ~(CLONE_THREAD|CLONE_FS|CLONE_NEWNS|CLONE_SIGHAND|
1648   - CLONE_VM|CLONE_FILES|CLONE_SYSVSEM|
1649   - CLONE_NEWUTS|CLONE_NEWIPC|CLONE_NEWNET))
  1599 + err = check_unshare_flags(unshare_flags);
  1600 + if (err)
1650 1601 goto bad_unshare_out;
1651 1602  
1652 1603 /*
  1604 + * If unsharing namespace, must also unshare filesystem information.
  1605 + */
  1606 + if (unshare_flags & CLONE_NEWNS)
  1607 + unshare_flags |= CLONE_FS;
  1608 + /*
1653 1609 * CLONE_NEWIPC must also detach from the undolist: after switching
1654 1610 * to a new ipc namespace, the semaphore arrays from the old
1655 1611 * namespace are unreachable.
1656 1612 */
1657 1613 if (unshare_flags & (CLONE_NEWIPC|CLONE_SYSVSEM))
1658 1614 do_sysvsem = 1;
1659   - if ((err = unshare_thread(unshare_flags)))
1660   - goto bad_unshare_out;
1661 1615 if ((err = unshare_fs(unshare_flags, &new_fs)))
1662   - goto bad_unshare_cleanup_thread;
1663   - if ((err = unshare_sighand(unshare_flags, &new_sigh)))
1664   - goto bad_unshare_cleanup_fs;
1665   - if ((err = unshare_vm(unshare_flags, &new_mm)))
1666   - goto bad_unshare_cleanup_sigh;
  1616 + goto bad_unshare_out;
1667 1617 if ((err = unshare_fd(unshare_flags, &new_fd)))
1668   - goto bad_unshare_cleanup_vm;
  1618 + goto bad_unshare_cleanup_fs;
1669 1619 if ((err = unshare_nsproxy_namespaces(unshare_flags, &new_nsproxy,
1670 1620 new_fs)))
1671 1621 goto bad_unshare_cleanup_fd;
1672 1622  
1673   - if (new_fs || new_mm || new_fd || do_sysvsem || new_nsproxy) {
  1623 + if (new_fs || new_fd || do_sysvsem || new_nsproxy) {
1674 1624 if (do_sysvsem) {
1675 1625 /*
1676 1626 * CLONE_SYSVSEM is equivalent to sys_exit().
... ... @@ -1696,19 +1646,6 @@
1696 1646 spin_unlock(&fs->lock);
1697 1647 }
1698 1648  
1699   - if (new_mm) {
1700   - mm = current->mm;
1701   - active_mm = current->active_mm;
1702   - current->mm = new_mm;
1703   - current->active_mm = new_mm;
1704   - if (current->signal->oom_score_adj == OOM_SCORE_ADJ_MIN) {
1705   - atomic_dec(&mm->oom_disable_count);
1706   - atomic_inc(&new_mm->oom_disable_count);
1707   - }
1708   - activate_mm(active_mm, new_mm);
1709   - new_mm = mm;
1710   - }
1711   -
1712 1649 if (new_fd) {
1713 1650 fd = current->files;
1714 1651 current->files = new_fd;
1715 1652  
... ... @@ -1725,20 +1662,10 @@
1725 1662 if (new_fd)
1726 1663 put_files_struct(new_fd);
1727 1664  
1728   -bad_unshare_cleanup_vm:
1729   - if (new_mm)
1730   - mmput(new_mm);
1731   -
1732   -bad_unshare_cleanup_sigh:
1733   - if (new_sigh)
1734   - if (atomic_dec_and_test(&new_sigh->count))
1735   - kmem_cache_free(sighand_cachep, new_sigh);
1736   -
1737 1665 bad_unshare_cleanup_fs:
1738 1666 if (new_fs)
1739 1667 free_fs_struct(new_fs);
1740 1668  
1741   -bad_unshare_cleanup_thread:
1742 1669 bad_unshare_out:
1743 1670 return err;
1744 1671 }