Commit 9edff4ab1f8d82675277a04e359d0ed8bf14a7b7
Committed by
Linus Torvalds
1 parent
44f564a4bf
Exists in
master
and in
7 other branches
ipc: sysvsem: implement sys_unshare(CLONE_SYSVSEM)
sys_unshare(CLONE_NEWIPC) doesn't handle the undo lists properly, this can cause a kernel memory corruption. CLONE_NEWIPC must detach from the existing undo lists. Fix, part 1: add support for sys_unshare(CLONE_SYSVSEM) The original reason to not support it was the potential (inevitable?) confusion due to the fact that sys_unshare(CLONE_SYSVSEM) has the inverse meaning of clone(CLONE_SYSVSEM). Our two most reasonable options then appear to be (1) fully support CLONE_SYSVSEM, or (2) continue to refuse explicit CLONE_SYSVSEM, but always do it anyway on unshare(CLONE_SYSVSEM). This patch does (1). Changelog: Apr 16: SEH: switch to Manfred's alternative patch which removes the unshare_semundo() function which always refused CLONE_SYSVSEM. Signed-off-by: Manfred Spraul <manfred@colorfullife.com> Signed-off-by: Serge E. Hallyn <serue@us.ibm.com> Acked-by: "Eric W. Biederman" <ebiederm@xmission.com> Cc: Pavel Emelyanov <xemul@openvz.org> Cc: Michael Kerrisk <mtk.manpages@googlemail.com> Cc: Pierre Peiffer <peifferp@gmail.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Showing 2 changed files with 12 additions and 18 deletions Side-by-side Diff
ipc/sem.c
kernel/fork.c
... | ... | @@ -1669,18 +1669,6 @@ |
1669 | 1669 | } |
1670 | 1670 | |
1671 | 1671 | /* |
1672 | - * Unsharing of semundo for tasks created with CLONE_SYSVSEM is not | |
1673 | - * supported yet | |
1674 | - */ | |
1675 | -static int unshare_semundo(unsigned long unshare_flags, struct sem_undo_list **new_ulistp) | |
1676 | -{ | |
1677 | - if (unshare_flags & CLONE_SYSVSEM) | |
1678 | - return -EINVAL; | |
1679 | - | |
1680 | - return 0; | |
1681 | -} | |
1682 | - | |
1683 | -/* | |
1684 | 1672 | * unshare allows a process to 'unshare' part of the process |
1685 | 1673 | * context which was originally shared using clone. copy_* |
1686 | 1674 | * functions used by do_fork() cannot be used here directly |
1687 | 1675 | |
... | ... | @@ -1695,8 +1683,8 @@ |
1695 | 1683 | struct sighand_struct *new_sigh = NULL; |
1696 | 1684 | struct mm_struct *mm, *new_mm = NULL, *active_mm = NULL; |
1697 | 1685 | struct files_struct *fd, *new_fd = NULL; |
1698 | - struct sem_undo_list *new_ulist = NULL; | |
1699 | 1686 | struct nsproxy *new_nsproxy = NULL; |
1687 | + int do_sysvsem = 0; | |
1700 | 1688 | |
1701 | 1689 | check_unshare_flags(&unshare_flags); |
1702 | 1690 | |
... | ... | @@ -1708,6 +1696,8 @@ |
1708 | 1696 | CLONE_NEWNET)) |
1709 | 1697 | goto bad_unshare_out; |
1710 | 1698 | |
1699 | + if (unshare_flags & CLONE_SYSVSEM) | |
1700 | + do_sysvsem = 1; | |
1711 | 1701 | if ((err = unshare_thread(unshare_flags))) |
1712 | 1702 | goto bad_unshare_out; |
1713 | 1703 | if ((err = unshare_fs(unshare_flags, &new_fs))) |
1714 | 1704 | |
1715 | 1705 | |
... | ... | @@ -1718,13 +1708,17 @@ |
1718 | 1708 | goto bad_unshare_cleanup_sigh; |
1719 | 1709 | if ((err = unshare_fd(unshare_flags, &new_fd))) |
1720 | 1710 | goto bad_unshare_cleanup_vm; |
1721 | - if ((err = unshare_semundo(unshare_flags, &new_ulist))) | |
1722 | - goto bad_unshare_cleanup_fd; | |
1723 | 1711 | if ((err = unshare_nsproxy_namespaces(unshare_flags, &new_nsproxy, |
1724 | 1712 | new_fs))) |
1725 | - goto bad_unshare_cleanup_semundo; | |
1713 | + goto bad_unshare_cleanup_fd; | |
1726 | 1714 | |
1727 | - if (new_fs || new_mm || new_fd || new_ulist || new_nsproxy) { | |
1715 | + if (new_fs || new_mm || new_fd || do_sysvsem || new_nsproxy) { | |
1716 | + if (do_sysvsem) { | |
1717 | + /* | |
1718 | + * CLONE_SYSVSEM is equivalent to sys_exit(). | |
1719 | + */ | |
1720 | + exit_sem(current); | |
1721 | + } | |
1728 | 1722 | |
1729 | 1723 | if (new_nsproxy) { |
1730 | 1724 | switch_task_namespaces(current, new_nsproxy); |
... | ... | @@ -1760,7 +1754,6 @@ |
1760 | 1754 | if (new_nsproxy) |
1761 | 1755 | put_nsproxy(new_nsproxy); |
1762 | 1756 | |
1763 | -bad_unshare_cleanup_semundo: | |
1764 | 1757 | bad_unshare_cleanup_fd: |
1765 | 1758 | if (new_fd) |
1766 | 1759 | put_files_struct(new_fd); |