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>