From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752010AbbHLRvG (ORCPT ); Wed, 12 Aug 2015 13:51:06 -0400 Received: from mx1.redhat.com ([209.132.183.28]:50129 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751084AbbHLRvE (ORCPT ); Wed, 12 Aug 2015 13:51:04 -0400 Date: Wed, 12 Aug 2015 19:48:47 +0200 From: Oleg Nesterov To: "Eric W. Biederman" Cc: "Kirill A. Shutemov" , Andrew Morton , Kees Cook , David Howells , linux-kernel@vger.kernel.org, Peter Zijlstra , Ingo Molnar , "Kirill A. Shutemov" , Rik van Riel , Vladimir Davydov , Ricky Zhou , Julien Tinnes Subject: Re: [PATCH 1/2] unshare: Unsharing a thread does not require unsharing a vm Message-ID: <20150812174847.GA6703@redhat.com> References: <20150728171500.GA2871@www.outflux.net> <20150728143504.5aa996ba5955522a19c2d5f1@linux-foundation.org> <20150728221111.GA23391@node.dhcp.inet.fi> <20150805172356.GA20490@redhat.com> <87wpx9sjhq.fsf@x220.int.ebiederm.org> <87614tr2jd.fsf@x220.int.ebiederm.org> <20150806130629.GA4728@redhat.com> <20150806134426.GA6843@redhat.com> <871tf9cnbi.fsf_-_@x220.int.ebiederm.org> <87vbclb8op.fsf_-_@x220.int.ebiederm.org> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <87vbclb8op.fsf_-_@x220.int.ebiederm.org> User-Agent: Mutt/1.5.18 (2008-05-17) Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org 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.