[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20150812174847.GA6703@redhat.com>
Date: Wed, 12 Aug 2015 19:48:47 +0200
From: Oleg Nesterov <oleg@...hat.com>
To: "Eric W. Biederman" <ebiederm@...ssion.com>
Cc: "Kirill A. Shutemov" <kirill@...temov.name>,
Andrew Morton <akpm@...ux-foundation.org>,
Kees Cook <keescook@...omium.org>,
David Howells <dhowells@...hat.com>,
linux-kernel@...r.kernel.org,
Peter Zijlstra <peterz@...radead.org>,
Ingo Molnar <mingo@...nel.org>,
"Kirill A. Shutemov" <kirill.shutemov@...ux.intel.com>,
Rik van Riel <riel@...hat.com>,
Vladimir Davydov <vdavydov@...allels.com>,
Ricky Zhou <rickyz@...omium.org>,
Julien Tinnes <jln@...gle.com>
Subject: Re: [PATCH 1/2] unshare: Unsharing a thread does not require
unsharing a vm
On 08/11, Eric W. Biederman wrote:
>
> --- a/kernel/fork.c
> +++ b/kernel/fork.c
> @@ -1866,13 +1866,17 @@ static int check_unshare_flags(unsigned long unshare_flags)
> CLONE_NEWUSER|CLONE_NEWPID))
> return -EINVAL;
> /*
> - * Not implemented, but pretend it works if there is nothing to
> - * unshare. Note that unsharing CLONE_THREAD or CLONE_SIGHAND
> - * needs to unshare vm.
> + * Not implemented, but pretend it works if there is nothing
> + * to unshare. Note that unsharing the address space or the
> + * signal handlers also need to unshare the signal queues (aka
> + * CLONE_THREAD).
> */
> if (unshare_flags & (CLONE_THREAD | CLONE_SIGHAND | CLONE_VM)) {
> - /* FIXME: get_task_mm() increments ->mm_users */
> - if (atomic_read(¤t->mm->mm_users) > 1)
> + if (!thread_group_empty(current))
> + return -EINVAL;
> + }
> + if (unshare_flags & CLONE_VM) {
> + if (!current_is_single_threaded())
> return -EINVAL;
> }
OK, but then you can remove "| CLONE_VM" from the previous check...
> @@ -1941,16 +1945,16 @@ SYSCALL_DEFINE1(unshare, unsigned long, unshare_flags)
> if (unshare_flags & CLONE_NEWUSER)
> unshare_flags |= CLONE_THREAD | CLONE_FS;
> /*
> - * If unsharing a thread from a thread group, must also unshare vm.
> - */
> - if (unshare_flags & CLONE_THREAD)
> - unshare_flags |= CLONE_VM;
OK,
> /*
> + * If unsharing a signal handlers, must also unshare the signal queues.
> + */
> + if (unshare_flags & CLONE_SIGHAND)
> + unshare_flags |= CLONE_THREAD;
This looks unnecessary, check_unshare_flags() checks "THREAD | SIGHAND".
And to me the comment looks misleading although I won't argue.
And in fact this doesn't look exactly right, or I am totally confused.
Shouldn't we do
if (unshare_flags & CLONE_SIGHAND)
unshare_flags |= CLONE_VM;
? Or change check_unshare_flags()...
Otherwise suppose that a single threaded process does clone(VM | SIGHAND)
and (say) child does sys_unshare(SIGHAND). This will wrongly succeed afaics.
Oleg.
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Powered by blists - more mailing lists