kern/138880: [linux] munmap segfaults after linux_mmap2 stresstest

Alexander Best alexbestms at math.uni-muenster.de
Wed Sep 16 15:00:15 UTC 2009


>Number:         138880
>Category:       kern
>Synopsis:       [linux] munmap segfaults after linux_mmap2 stresstest
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    freebsd-bugs
>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:
>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 at 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 at ltp.cvs.sourceforge.net:/cvsroot/ltp login
cvs -z3 -d:pserver:anonymous at 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 at us.ibm.com */
/* 06/30/2001	Port to Linux	nsharoff at 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:
>Unformatted:


More information about the freebsd-bugs mailing list