From owner-freebsd-current@freebsd.org Wed Dec 16 13:33:22 2015 Return-Path: Delivered-To: freebsd-current@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 1A2B1A49351 for ; Wed, 16 Dec 2015 13:33:22 +0000 (UTC) (envelope-from kostikbel@gmail.com) Received: from kib.kiev.ua (kib.kiev.ua [IPv6:2001:470:d5e7:1::1]) (using TLSv1 with cipher DHE-RSA-CAMELLIA256-SHA (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 971011A0F for ; Wed, 16 Dec 2015 13:33:21 +0000 (UTC) (envelope-from kostikbel@gmail.com) Received: from tom.home (kostik@localhost [127.0.0.1]) by kib.kiev.ua (8.15.2/8.15.2) with ESMTPS id tBGCA0tj052873 (version=TLSv1 cipher=DHE-RSA-CAMELLIA256-SHA bits=256 verify=NO); Wed, 16 Dec 2015 14:10:00 +0200 (EET) (envelope-from kostikbel@gmail.com) DKIM-Filter: OpenDKIM Filter v2.10.3 kib.kiev.ua tBGCA0tj052873 Received: (from kostik@localhost) by tom.home (8.15.2/8.15.2/Submit) id tBGCA0E0052872; Wed, 16 Dec 2015 14:10:00 +0200 (EET) (envelope-from kostikbel@gmail.com) X-Authentication-Warning: tom.home: kostik set sender to kostikbel@gmail.com using -f Date: Wed, 16 Dec 2015 14:10:00 +0200 From: Konstantin Belousov To: FreeBSD Current Subject: Re: fork_findpid() - Fatal trap 12: page fault while in kernel mode Message-ID: <20151216121000.GV3625@kib.kiev.ua> References: <20151215174238.2d7cc3bb@fabiankeil.de> <20151216104227.GS3625@kib.kiev.ua> <20151216122116.09e1b27d@fabiankeil.de> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20151216122116.09e1b27d@fabiankeil.de> User-Agent: Mutt/1.5.24 (2015-08-30) X-Spam-Status: No, score=-2.0 required=5.0 tests=ALL_TRUSTED,BAYES_00, DKIM_ADSP_CUSTOM_MED,FREEMAIL_FROM,NML_ADSP_CUSTOM_MED autolearn=no autolearn_force=no version=3.4.1 X-Spam-Checker-Version: SpamAssassin 3.4.1 (2015-04-28) on tom.home X-BeenThere: freebsd-current@freebsd.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: Discussions about the use of FreeBSD-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 16 Dec 2015 13:33:22 -0000 On Wed, Dec 16, 2015 at 12:21:16PM +0100, Fabian Keil wrote: > Konstantin Belousov wrote: > > It is the values of *p and *(p->p_pgrp) that are needed, from the frame 8. > > Unfortunately it's not available and apparently I removed the attempts > to get it from the previous output. > allproc is available and the first one matches lastpid and has an invalid > p_pgrp, but due to trypid being optimized out as well, it's not obvious > (to me) that it's the right process. p_suspcount = 0, p_xthread = 0xfffff801162819a0, p_boundary_count = 0, p_pendingcnt = 0, p_itimers = 0x0, p_procdesc = 0x0, p_treeflag = 0, p_magic = 3203398350, p_osrel = 1100090, > p_comm = 0xfffff800304df3c4 "privoxy", p_pgrp = 0x618b0080, > I've changed p's declaration to static so hopefully its value will > be available the next time the panic occurs, but it may take a while > until that happens. >From the state of the process you provided, it is a new (zigote) of the forking process, which was already linked into allproc list. Also, it seems that bzero part of the forking procedure was finished, but bcopy was not yet. The p_pgrp cannot be a pointer, it is not yet initialized. There, we have at least one issue, since zigote is linked before the p_pgrp is initialized, and the proctree/allproc locks are dropped. As result, fork_findpid() accesses memory with undefined content. It seems that the least morbid solution is to slightly extend the scope of the allproc lock in do_fork(), to prevent fork_findpid() from working while we did not finished copying data from old to new process. diff --git a/sys/kern/kern_fork.c b/sys/kern/kern_fork.c index 1b556be..ae04c9f 100644 --- a/sys/kern/kern_fork.c +++ b/sys/kern/kern_fork.c @@ -396,13 +396,12 @@ do_fork(struct thread *td, int flags, struct proc *p2, struct thread *td2, PROC_LOCK(p2); PROC_LOCK(p1); - sx_xunlock(&allproc_lock); - bcopy(&p1->p_startcopy, &p2->p_startcopy, __rangeof(struct proc, p_startcopy, p_endcopy)); pargs_hold(p2->p_args); PROC_UNLOCK(p1); + sx_xunlock(&allproc_lock); bzero(&p2->p_startzero, __rangeof(struct proc, p_startzero, p_endzero));