diff --git a/ipc/sem.c b/ipc/sem.c index 0b45a4d..35841bd 100644 --- a/ipc/sem.c +++ b/ipc/sem.c @@ -1298,6 +1298,7 @@ void exit_sem(struct task_struct *tsk) undo_list = tsk->sysvsem.undo_list; if (!undo_list) return; + tsk->sysvsem.undo_list = NULL; if (!atomic_dec_and_test(&undo_list->refcnt)) return; diff --git a/kernel/fork.c b/kernel/fork.c index 9c042f9..a3f3abb 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -1733,6 +1733,18 @@ asmlinkage long sys_unshare(unsigned long unshare_flags) if (new_fs || new_mm || new_fd || new_ulist || new_nsproxy) { if (new_nsproxy) { + if ((current->nsproxy == NULL && new_nsproxy != NULL) || + (current->nsproxy != NULL && new_nsproxy == NULL) || + (current->nsproxy != NULL && new_nsproxy != NULL && current->nsproxy->ipc_ns != new_nsproxy->ipc_ns)) { + /* switching the IPC namespace is considered equivalent to sys_exit() wrt. + * to outstanding SEM_UNDO undos: After switching to the new IPC namespace, + * the semaphore arrays from the old namespace are not accessible anymore. + * + * Additionally, an implicit sys_unshare(CLONE_SYSVSEM) is performed. + */ + exit_sem(current); + } + switch_task_namespaces(current, new_nsproxy); new_nsproxy = NULL; }