Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 22 Mar 2004 08:00:02 -0800 (PST)
From:      gordon <hddai@163.net>
To:        freebsd-gnats-submit@FreeBSD.org
Subject:   kern/64573: mmap with PROT_NONE, but still could be read
Message-ID:  <200403221600.i2MG02NC074827@www.freebsd.org>
Resent-Message-ID: <200403221600.i2MG0ZcM039855@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help

>Number:         64573
>Category:       kern
>Synopsis:       mmap with PROT_NONE, but still could be read
>Confidential:   no
>Severity:       critical
>Priority:       high
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Mon Mar 22 08:00:35 PST 2004
>Closed-Date:
>Last-Modified:
>Originator:     gordon
>Release:        FreeBSD current 5.2
>Organization:
PDL
>Environment:
FreeBSD i386      
>Description:
I have ported a test program for LSB test suites to test the compatibility of mmap system call. As to Open Group Technical Standard System Interfaces and Headers, Issue 5, when mmap with PROT_NONE, the  mapped pages should not be allowed to access. But as the program shows, the mapped page could still be read. Can anyone tell me how to solve this problem?
#include <stdio.h>
#include <unistd.h>
#include <setjmp.h>
#include <signal.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>

static int vsrt_mmap_setup(void);
static void vsrt_mmapsig_fn(int);
static void vsrt_invalid_sig_fn(int);
static int vsrt_signal(int , void (*handler)(int));
static int vsrt_open_file(char* s, int flag, mode_t mode, int npages);
typedef struct {
		char	name[10];
		int	signal;
		int	flags;
	} vsrt_siglst;
static vsrt_siglst	vsrt_signals[] = {
		{ "SIGFPE",	SIGFPE,		0 },
		{ "SIGILL",	SIGILL,		0 },
	};
#define	VSRT_NUM_SIGNALS	(sizeof(vsrt_signals) / sizeof(vsrt_siglst))
#define VSRT_PROT_ALL	(mode_t)(S_IRWXU|S_IRWXG|S_IRWXO)
static char* test_file = "./dhd";
static int vsrt_got_sigsegv = 0;
static int vsrt_got_sigbus = 0;
static int vsrt_got_sig = 0;
static int vsrt_setjmp_called = 0;
static unsigned long vsrt_pgsz, vsrt_ipgsz;
static sigjmp_buf vsrt_env;	
static struct sigaction Sigaction;

main()
{
	int	fd, err;
	pid_t	pid;
	int *addr;
	volatile int i;
	
	if (vsrt_mmap_setup() == -1){
		printf("Setup error!\n");
		return;
	}
	fd = vsrt_open_file(test_file, O_RDWR, VSRT_PROT_ALL, 2);
	if (fd == -1){
		printf("Error in open file\n");
		return;
	}
	if ((addr = (int *)mmap(0, vsrt_pgsz, PROT_NONE, MAP_SHARED, fd, (off_t)vsrt_pgsz)) == (int *) (-1)) {
		err = errno;
		printf("mmap failed, errno = %d \n", err);
		(void)close(fd);
		(void)unlink(test_file);
		return;
	}

	
	if ((pid = fork()) == 0){
		vsrt_setjmp_called = 1;

		if(sigsetjmp(vsrt_env,1) ==0)
			i = *addr;

		if (!(vsrt_got_sigsegv || vsrt_got_sigbus)) {
			printf("Mapped page could be accessed\n");
			exit(1);
		}
		else printf("Mapped page could not be accessed\n");
		exit (0);
	}
	else if (pid == -1){
		printf("fork failed\n");
		exit(0);
	}
	else	wait((int *)0);	
	close(fd);
	munmap((void*) addr, (size_t)vsrt_pgsz);
	unlink(test_file);
} 

int vsrt_mmap_setup(void) {
	int	i;
	
	if ((vsrt_pgsz = sysconf(_SC_PAGESIZE)) == -1) {
		printf("Error to get pagesize\n");
		return -1;
	}
	vsrt_ipgsz = vsrt_pgsz/sizeof(int);
	vsrt_got_sigsegv = vsrt_got_sigbus = vsrt_got_sig = 0;
	for (i = 0; i < VSRT_NUM_SIGNALS; i++) {
		if (vsrt_signal(vsrt_signals[i].signal, &vsrt_invalid_sig_fn) == -1)  return -1;
	}
	if (vsrt_signal(SIGSEGV, vsrt_mmapsig_fn) == -1) return -1;
	if (vsrt_signal(SIGBUS, vsrt_mmapsig_fn) == -1)	return -1;
	return 0;
}

int vsrt_signal(int sig, void (*handler)(int))
{
	int	rval;
	rval = sigemptyset(&(Sigaction.sa_mask));
	if (rval == -1) {
		printf("Error to sigemptyset\n");
		return -1;
	}
	Sigaction.sa_handler = handler;
	Sigaction.sa_flags = 0;
	rval = sigaction(sig,&Sigaction,(struct sigaction *)NULL);
	if (rval == -1) {
		printf("Error in sigaction\n");
		return -1;
	}
	return 0;
}

static void vsrt_invalid_sig_fn(int s)
{
	int i;
	for (i = 0; i < VSRT_NUM_SIGNALS; i++) {
		if (s == vsrt_signals[i].signal) {
			printf("Invalid signal: %d(%s) received\n", s, vsrt_signals[i].name);
			return;
		}
	}
}

static void vsrt_mmapsig_fn(int s)
{
	if (s == SIGSEGV)	vsrt_got_sigsegv++;
	else if (s == SIGBUS) vsrt_got_sigbus++;
	vsrt_got_sig++;
	if (vsrt_setjmp_called) {
		vsrt_setjmp_called = 0;
		siglongjmp(vsrt_env, 1);
	}
}

int vsrt_open_file(char* s, int flag, mode_t mode, int npages)
{
	int fd, *buf, i, j;
	unlink(s);
	if ((fd = open(s, (O_RDWR|O_CREAT|O_TRUNC), (mode_t)(S_IRWXU|S_IRWXG|S_IRWXO))) == -1) {
		printf("open() failed, errno = %d \n", errno);
		return -1;
	}
	if ((buf = (int *)malloc(sizeof(int) * vsrt_ipgsz * npages)) == NULL) {
		printf("malloc() failed, errno = %d \n", errno);
		return -1;
	}
	for (j = 0; j < vsrt_ipgsz*npages; j += sizeof(buf)/sizeof(buf[0])) {
		for (i = 0; i < sizeof(buf)/sizeof(buf[0]); i++)	buf[i] = i + j;
		if (write(fd, (void*)buf, sizeof(buf)) != sizeof(buf)) {
			printf("write() failed, errno = %d \n", errno );
			return -1;
		}
	}
	(void)close(fd);
	if (chmod(s, mode) == -1) {
		printf("chmod() failed, errno = %d \n", errno);
		return -1;
	}
	if ((fd = open(s, flag)) == -1) {
		printf("open() failed, errno = %d \n", errno);
		return -1;
	}
	return (fd);
}
     
>How-To-Repeat:
The ported program is attached in the Full Description part.      
>Fix:
      
>Release-Note:
>Audit-Trail:
>Unformatted:



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200403221600.i2MG02NC074827>