From nobody@FreeBSD.org  Wed Sep 16 14:53:11 2009
Return-Path: <nobody@FreeBSD.org>
Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34])
	by hub.freebsd.org (Postfix) with ESMTP id DC1A61065679
	for <freebsd-gnats-submit@FreeBSD.org>; Wed, 16 Sep 2009 14:53:11 +0000 (UTC)
	(envelope-from nobody@FreeBSD.org)
Received: from www.freebsd.org (www.freebsd.org [IPv6:2001:4f8:fff6::21])
	by mx1.freebsd.org (Postfix) with ESMTP id C9E958FC1C
	for <freebsd-gnats-submit@FreeBSD.org>; Wed, 16 Sep 2009 14:53:11 +0000 (UTC)
Received: from www.freebsd.org (localhost [127.0.0.1])
	by www.freebsd.org (8.14.3/8.14.3) with ESMTP id n8GErBA5005238
	for <freebsd-gnats-submit@FreeBSD.org>; Wed, 16 Sep 2009 14:53:11 GMT
	(envelope-from nobody@www.freebsd.org)
Received: (from nobody@localhost)
	by www.freebsd.org (8.14.3/8.14.3/Submit) id n8GErBLu005236;
	Wed, 16 Sep 2009 14:53:11 GMT
	(envelope-from nobody)
Message-Id: <200909161453.n8GErBLu005236@www.freebsd.org>
Date: Wed, 16 Sep 2009 14:53:11 GMT
From: Alexander Best <alexbestms@math.uni-muenster.de>
To: freebsd-gnats-submit@FreeBSD.org
Subject: [linux] munmap segfaults after linux_mmap2 stresstest
X-Send-Pr-Version: www-3.1
X-GNATS-Notify:

>Number:         138880
>Category:       kern
>Synopsis:       [linux] munmap segfaults after linux_mmap2 stresstest
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    freebsd-emulation
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Wed Sep 16 15:00:14 UTC 2009
>Closed-Date:    
>Last-Modified:  Tue Nov  3 16:10:02 UTC 2009
>Originator:     Alexander Best
>Release:        9.0-CURRENT
>Organization:
>Environment:
FreeBSD otaku 9.0-CURRENT FreeBSD 9.0-CURRENT #0 r197234: Wed Sep 16 01:10:00 CEST 2009     root@otaku:/usr/obj/usr/src/sys/ARUNDEL  i386
>Description:
the linux test project (ltp) is a set of small scripts and binaries to test if an environment meets all the criteria necessary to be 100% compatible with linux.

testcases/kernel/mem/mmapstress/mmapstress08 performs a mmap2 stress test. the source has been attached. upon munmap a segfault gets triggered.

if munmap gets called by a linux app the args are directly passed to the freebsd version of munmap. either the problem lies in the freebsd munmap function or the linux and freebsd of munmap behave differently. this would require a new linux_munmap function to map a linux munmap call appropriately to freebsd's munmap function.

here's a snipped truss output:

linux_mmap2(0x3bc00000,0x1000,0x3,0x22,0x0,0x6)  = 1002438656 (0x3bc00000)
linux_mmap2(0x3c000000,0x1000,0x3,0x22,0x0,0x6)  = 1006632960 (0x3c000000)
linux_mmap2(0x3c400000,0x1000,0x3,0x22,0x0,0x6)  = 1010827264 (0x3c400000)
linux_mmap2(0x3c800000,0x1000,0x3,0x22,0x0,0x6)  = 1015021568 (0x3c800000)
linux_mmap2(0x3cc00000,0x1000,0x3,0x22,0x0,0x6)  = 1019215872 (0x3cc00000)
linux_mmap2(0x3d000000,0x1000,0x3,0x22,0x0,0x6)  = 1023410176 (0x3d000000)
linux_mmap2(0x3d400000,0x1000,0x3,0x22,0x0,0x6)  = 1027604480 (0x3d400000)
linux_mmap2(0x3d800000,0x1000,0x3,0x22,0x0,0x6)  = 1031798784 (0x3d800000)
linux_mmap2(0x3dc00000,0x1000,0x3,0x22,0x0,0x6)  = 1035993088 (0x3dc00000)
linux_mmap2(0x3e000000,0x1000,0x3,0x22,0x0,0x6)  = 1040187392 (0x3e000000)
linux_mmap2(0x3e400000,0x1000,0x3,0x22,0x0,0x6)  = 1044381696 (0x3e400000)
linux_mmap2(0x3e800000,0x1000,0x3,0x22,0x0,0x6)  = 1048576000 (0x3e800000)
linux_mmap2(0x3ec00000,0x1000,0x3,0x22,0x0,0x6)  = 1052770304 (0x3ec00000)
linux_mmap2(0x3f000000,0x1000,0x3,0x22,0x0,0x6)  = 1056964608 (0x3f000000)
linux_mmap2(0x3f400000,0x1000,0x3,0x22,0x0,0x6)  = 1061158912 (0x3f400000)
linux_mmap2(0x3f800000,0x1000,0x3,0x22,0x0,0x6)  = 1065353216 (0x3f800000)
linux_mmap2(0x3fc00000,0x1000,0x3,0x22,0x0,0x6)  = 1069547520 (0x3fc00000)
munmap(0x8050000,939196416)                      = 0 (0x0)
SIGNAL 11 (SIGSEGV)
process exit, rval = 0

cheers.
alex
>How-To-Repeat:
cd /usr/ports/emulators/linux_dist-gentoo-stage3 && make install
cd /usr/local/gentoo-stage3
cvs -d:pserver:anonymous@ltp.cvs.sourceforge.net:/cvsroot/ltp login
cvs -z3 -d:pserver:anonymous@ltp.cvs.sourceforge.net:/cvsroot/ltp co ltp
chroot /usr/local/gentoo-stage3 bash
cd ltp && ./configure && make all install
cd testcases/kernel/mem/mmapstress
./mmapstress08
>Fix:


Patch attached with submission follows:

/* 01/02/2003	Port to LTP	avenkat@us.ibm.com */
/* 06/30/2001	Port to Linux	nsharoff@us.ibm.com */
/*
 *   Copyright (c) International Business Machines  Corp., 2003
 *
 *   This program is free software;  you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation; either version 2 of the License, or
 *   (at your option) any later version.
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY;  without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
 *   the GNU General Public License for more details.
 *
 *   You should have received a copy of the GNU General Public License
 *   along with this program;  if not, write to the Free Software
 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 */

/* as_anon_get:
 *	This program tests the kernel primitive as_anon_get by using up lots of
 *	level 2 page tables causing the kernel to switch to large blocks of
 *	anonymous backing store allocation.  This is done by allocating pages 4
 *	megs apart since each pt handles 1024 pages of 4096 bytes each.  Each
 *	page thus requires another page table.  The pages are then unmapped to
 *	switch back to small swap space allocations.
 */
#include <sys/types.h>
#include <sys/mman.h>
#include <unistd.h>
#include <errno.h>
#include <stdio.h>
/*****	LTP Port	*****/
#include "test.h"
#include "usctest.h"
#define FAILED 0
#define PASSED 1

int local_flag = PASSED;
char *TCID = "mmapstress08";
FILE *temp;
int TST_TOTAL = 1;
extern int Tst_count;

#if defined(__i386__) || defined(__x86_64__)
int anyfail();
void ok_exit();
/*****  **      **      *****/



#define NPTEPG		(1024)
/*#define GRAN_NUMBER	(1<<2)*/

#define GRAN_NUMBER	(1<<8)
	/* == 256 @ 4MB per mmap(2), we span a total of 1 GB */


extern time_t	time(time_t *);
extern char	*ctime(const time_t *);
extern long	sysconf(int name);

#define ERROR(M) (void)fprintf(stderr, "%s: errno = %d: " M "\n", argv[0], \
			errno)

/*ARGSUSED*/
int
main(int argc, char *argv[])
{
	caddr_t mmapaddr, munmap_begin;
	long pagesize = sysconf(_SC_PAGE_SIZE);
	int i;
	time_t t;

	(void)time(&t);
	//(void)printf("%s: Started %s", argv[0], ctime(&t));
	if (sbrk(pagesize - ((u_long)sbrk(0)%(u_long)pagesize))==(char *)-1) {
		ERROR("couldn't round up brk to a page boundary");
                local_flag = FAILED;
                anyfail();
	}
	/* The brk is now at the begining of a page. */

	if ((munmap_begin = mmapaddr = (caddr_t)sbrk(0)) == (caddr_t)-1) {
		ERROR("couldn't find top of brk");
                local_flag = FAILED;
                anyfail();
	}
	mmapaddr = 0;
	/* burn level 2 ptes by spacing mmaps 4Meg apart */
	/* This should switch to large anonymous swap space granularity */
	for (i = 0; i < GRAN_NUMBER; i++) {
		if (mmap(mmapaddr, pagesize, PROT_READ|PROT_WRITE,
			MAP_ANONYMOUS|MAP_PRIVATE, 0, 0)==(caddr_t)-1)
		{
			ERROR("mmap failed");
                	local_flag = FAILED;
                	anyfail();
		}
		mmapaddr += NPTEPG*pagesize;
	}
	/* Free bizillion level2 ptes to switch to small granularity */
	if (munmap(munmap_begin, (size_t)(mmapaddr-munmap_begin))) {
		ERROR("munmap failed");
                local_flag = FAILED;
                anyfail();
	}
	(void)time(&t);
	//(void)printf("%s: Finished %s", argv[0], ctime(&t));
	ok_exit();
	return 0;
}


/*****  LTP Port        *****/
void ok_exit()
{
        tst_resm(TPASS, "Test passed\n");
	tst_exit();
}


int anyfail()
{
  tst_resm(TFAIL, "Test failed\n");
  tst_exit();
  return 0;
}

#else /* defined(__i386__) || defined(__x86_64__) */
int
main (void)
{
  tst_resm (TCONF, "Test is only applicable for IA-32 and x86-64.");
  tst_exit ();
}
#endif
/*****  **      **      *****/



>Release-Note:
>Audit-Trail:
Responsible-Changed-From-To: freebsd-bugs->freebsd-emulation 
Responsible-Changed-By: linimon 
Responsible-Changed-When: Wed Sep 16 21:54:34 UTC 2009 
Responsible-Changed-Why:  
Over to maintainer(s). 

http://www.freebsd.org/cgi/query-pr.cgi?pr=138880 

From: Alexander Best <alexbestms@math.uni-muenster.de>
To: <bug-followup@FreeBSD.org>
Cc:  
Subject: Re: kern/138880: [linux] munmap segfaults after linux_mmap2
 stresstest
Date: Tue, 03 Nov 2009 17:01:23 +0100 (CET)

 here's a linux_kdump which might show more details than truss:
 
   1478 mmapstress08 CALL  linux_mmap2(0x3e800000,0x1000,0x3,0x22,0,0)
   1478 mmapstress08 RET   linux_mmap2 1048576000/0x3e800000
   1478 mmapstress08 CALL  linux_mmap2(0x3ec00000,0x1000,0x3,0x22,0,0)
   1478 mmapstress08 RET   linux_mmap2 1052770304/0x3ec00000
   1478 mmapstress08 CALL  linux_mmap2(0x3f000000,0x1000,0x3,0x22,0,0)
   1478 mmapstress08 RET   linux_mmap2 1056964608/0x3f000000
   1478 mmapstress08 CALL  linux_mmap2(0x3f400000,0x1000,0x3,0x22,0,0)
   1478 mmapstress08 RET   linux_mmap2 1061158912/0x3f400000
   1478 mmapstress08 CALL  linux_mmap2(0x3f800000,0x1000,0x3,0x22,0,0)
   1478 mmapstress08 RET   linux_mmap2 1065353216/0x3f800000
   1478 mmapstress08 CALL  linux_mmap2(0x3fc00000,0x1000,0x3,0x22,0,0)
   1478 mmapstress08 RET   linux_mmap2 1069547520/0x3fc00000
   1478 mmapstress08 CALL  munmap(0x8050000,0x37fb0000)
   1478 mmapstress08 RET   munmap 0
   1478 mmapstress08 PSIG  SIGSEGV SIG_DFL
   1478 mmapstress08 NAMI  "mmapstress08.core"
 
 alex
>Unformatted:
