|
@@ -1668,18 +1668,6 @@ static int unshare_fd(unsigned long unshare_flags, struct files_struct **new_fdp
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-/*
|
|
|
- * Unsharing of semundo for tasks created with CLONE_SYSVSEM is not
|
|
|
- * supported yet
|
|
|
- */
|
|
|
-static int unshare_semundo(unsigned long unshare_flags, struct sem_undo_list **new_ulistp)
|
|
|
-{
|
|
|
- if (unshare_flags & CLONE_SYSVSEM)
|
|
|
- return -EINVAL;
|
|
|
-
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
/*
|
|
|
* unshare allows a process to 'unshare' part of the process
|
|
|
* context which was originally shared using clone. copy_*
|
|
@@ -1695,8 +1683,8 @@ asmlinkage long sys_unshare(unsigned long unshare_flags)
|
|
|
struct sighand_struct *new_sigh = NULL;
|
|
|
struct mm_struct *mm, *new_mm = NULL, *active_mm = NULL;
|
|
|
struct files_struct *fd, *new_fd = NULL;
|
|
|
- struct sem_undo_list *new_ulist = NULL;
|
|
|
struct nsproxy *new_nsproxy = NULL;
|
|
|
+ int do_sysvsem = 0;
|
|
|
|
|
|
check_unshare_flags(&unshare_flags);
|
|
|
|
|
@@ -1708,6 +1696,8 @@ asmlinkage long sys_unshare(unsigned long unshare_flags)
|
|
|
CLONE_NEWNET))
|
|
|
goto bad_unshare_out;
|
|
|
|
|
|
+ if (unshare_flags & CLONE_SYSVSEM)
|
|
|
+ do_sysvsem = 1;
|
|
|
if ((err = unshare_thread(unshare_flags)))
|
|
|
goto bad_unshare_out;
|
|
|
if ((err = unshare_fs(unshare_flags, &new_fs)))
|
|
@@ -1718,13 +1708,17 @@ asmlinkage long sys_unshare(unsigned long unshare_flags)
|
|
|
goto bad_unshare_cleanup_sigh;
|
|
|
if ((err = unshare_fd(unshare_flags, &new_fd)))
|
|
|
goto bad_unshare_cleanup_vm;
|
|
|
- if ((err = unshare_semundo(unshare_flags, &new_ulist)))
|
|
|
- goto bad_unshare_cleanup_fd;
|
|
|
if ((err = unshare_nsproxy_namespaces(unshare_flags, &new_nsproxy,
|
|
|
new_fs)))
|
|
|
- goto bad_unshare_cleanup_semundo;
|
|
|
+ goto bad_unshare_cleanup_fd;
|
|
|
|
|
|
- if (new_fs || new_mm || new_fd || new_ulist || new_nsproxy) {
|
|
|
+ if (new_fs || new_mm || new_fd || do_sysvsem || new_nsproxy) {
|
|
|
+ if (do_sysvsem) {
|
|
|
+ /*
|
|
|
+ * CLONE_SYSVSEM is equivalent to sys_exit().
|
|
|
+ */
|
|
|
+ exit_sem(current);
|
|
|
+ }
|
|
|
|
|
|
if (new_nsproxy) {
|
|
|
switch_task_namespaces(current, new_nsproxy);
|
|
@@ -1760,7 +1754,6 @@ asmlinkage long sys_unshare(unsigned long unshare_flags)
|
|
|
if (new_nsproxy)
|
|
|
put_nsproxy(new_nsproxy);
|
|
|
|
|
|
-bad_unshare_cleanup_semundo:
|
|
|
bad_unshare_cleanup_fd:
|
|
|
if (new_fd)
|
|
|
put_files_struct(new_fd);
|