kern/64573: mmap with PROT_NONE, but still could be read
gordon
hddai at 163.net
Mon Mar 22 08:00:36 PST 2004
>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:
More information about the freebsd-bugs
mailing list