/* * check_access -- check access to mapped memory */ static void check_access(char *addr, size_t len, int prot) { volatile int i; /* arrange to catch SEGV */ struct sigaction v; sigemptyset(&v.sa_mask); v.sa_flags = 0; v.sa_handler = signal_handler; SIGACTION(SIGSEGV, &v, NULL); char pat[PAGE_SIZE]; char buf[PAGE_SIZE]; for (i = 0; i < len / PAGE_SIZE; i++) { /* check read access */ if (!ut_sigsetjmp(Jmp)) { memcpy(buf, addr + PAGE_SIZE * i, PAGE_SIZE); if ((prot & PROT_READ) == 0) UT_FATAL("memory can be read"); } else { if (prot & PROT_READ) UT_FATAL("memory cannot be read"); } } /* fill up mapped region with new pattern */ memset(pat, 0xA5, PAGE_SIZE); for (i = 0; i < len / PAGE_SIZE; i++) { if (!ut_sigsetjmp(Jmp)) { memcpy(addr + PAGE_SIZE * i, pat, PAGE_SIZE); if ((prot & PROT_WRITE) == 0) UT_FATAL("memory can be written"); } else { if (prot & PROT_WRITE) UT_FATAL("memory cannot be written"); } } }
/* * do_check -- check the mapping */ static void do_check(int fd, void *addr, size_t mlen) { /* arrange to catch SEGV */ struct sigaction v; sigemptyset(&v.sa_mask); v.sa_flags = 0; v.sa_handler = signal_handler; SIGACTION(SIGSEGV, &v, NULL); char pat[CHECK_BYTES]; char buf[CHECK_BYTES]; /* write some pattern to the file */ memset(pat, 0x5A, CHECK_BYTES); WRITE(fd, pat, CHECK_BYTES); if (memcmp(pat, addr, CHECK_BYTES)) UT_OUT("first %d bytes do not match", CHECK_BYTES); /* fill up mapped region with new pattern */ memset(pat, 0xA5, CHECK_BYTES); memcpy(addr, pat, CHECK_BYTES); UT_ASSERTeq(pmem_msync(addr, CHECK_BYTES), 0); UT_ASSERTeq(pmem_unmap(addr, mlen), 0); if (!ut_sigsetjmp(Jmp)) { /* same memcpy from above should now fail */ memcpy(addr, pat, CHECK_BYTES); } else { UT_OUT("unmap successful"); } LSEEK(fd, (os_off_t)0, SEEK_SET); if (READ(fd, buf, CHECK_BYTES) == CHECK_BYTES) { if (memcmp(pat, buf, CHECK_BYTES)) UT_OUT("first %d bytes do not match", CHECK_BYTES); } }
/* * check_mapping -- check access to memory mapped file */ static void check_mapping(int fd, char *addr, size_t len, int prot, int flags, off_t offset) { volatile int i; /* arrange to catch SEGV */ struct sigaction v; sigemptyset(&v.sa_mask); v.sa_flags = 0; v.sa_handler = signal_handler; SIGACTION(SIGSEGV, &v, NULL); char pat[PAGE_SIZE] = { 0 }; char buf[PAGE_SIZE]; if ((flags & CHECK_RO) == 0 && fd != -1) { /* write some pattern to the file */ memset(pat, 0x5A, PAGE_SIZE); for (i = 0; i < len / PAGE_SIZE; i++) { LSEEK(fd, offset + PAGE_SIZE * i, SEEK_SET); WRITE(fd, pat, PAGE_SIZE); LSEEK(fd, offset + PAGE_SIZE * i, SEEK_SET); if (READ(fd, buf, PAGE_SIZE) == PAGE_SIZE) { if (memcmp(pat, buf, PAGE_SIZE)) UT_FATAL("first %d bytes do not match", PAGE_SIZE); } } } check_access(addr, len, prot); munmap(addr, len); /* same memcpy from above should now fail */ for (i = 0; i < len / PAGE_SIZE; i++) { if (!ut_sigsetjmp(Jmp)) { memcpy(addr + PAGE_SIZE * i, pat, PAGE_SIZE); UT_FATAL("unmap failed"); } } if (fd != -1) { /* expected pattern */ if ((flags & (CHECK_PRIV | CHECK_RO)) != 0 || (prot & PROT_WRITE) == 0) memset(pat, 0x5A, PAGE_SIZE); else memset(pat, 0xA5, PAGE_SIZE); for (i = 0; i < len / PAGE_SIZE; i++) { LSEEK(fd, offset + PAGE_SIZE * i, SEEK_SET); if (READ(fd, buf, PAGE_SIZE) == PAGE_SIZE) { if (memcmp(pat, buf, PAGE_SIZE)) UT_FATAL("first %d bytes do not match", PAGE_SIZE); } } } }