DF-3053 / df3053b.c
/* DF-3053 hammer version - nfsm_mbuftouio ignores copyout fault. * A: read(fd, region, 4096); B: flips mprotect NONE<->RW continuously. * BUG hit = read returns 4096 while region still 0x5A (fault swallowed). * userland accesses to the region are guarded with sigsetjmp/SIGSEGV. */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <errno.h> #include <fcntl.h> #include <unistd.h> #include <pthread.h> #include <setjmp.h> #include <signal.h> #include <sys/mman.h> static char *region; static volatile int stop=0, in_guard=0; static sigjmp_buf jb; static long bug_hits=0, ok_reads=0, fault_reads=0, total=0, guard_faults=0; static void segv(int sig){ (void)sig; if(in_guard){ in_guard=0; siglongjmp(jb,1);} _exit(99); } static void *flipper(void*a){ while(!stop){ mprotect(region,8192,PROT_NONE); mprotect(region,8192,PROT_READ|PROT_WRITE); } return NULL; } #define GUARDED(stmt) do{ if(sigsetjmp(jb,1)==0){ in_guard=1; stmt; in_guard=0; } else { guard_faults++; mprotect(region,8192,PROT_READ|PROT_WRITE); } } while(0) int main(int argc,char**argv){ pthread_t t; int iters=argc>2?atoi(argv[2]):20000; struct sigaction sa; memset(&sa,0,sizeof sa); sa.sa_handler=segv; sigaction(SIGSEGV,&sa,NULL); if(argc<2){fprintf(stderr,"usage: df3053b file [iters]\n");return 2;} int fd=open(argv[1],O_RDONLY); if(fd<0){perror("open");return 1;} region=mmap(NULL,8192,PROT_READ|PROT_WRITE,MAP_ANON|MAP_PRIVATE,-1,0); if(region==MAP_FAILED){perror("mmap");return 1;} pthread_create(&t,NULL,flipper,NULL); for(int i=0;i<iters;i++){ GUARDED({ mprotect(region,8192,PROT_READ|PROT_WRITE); memset(region,0x5A,4096); }); errno=0; ssize_t r=read(fd,region,4096); total++; int stale=1; GUARDED({ mprotect(region,8192,PROT_READ|PROT_WRITE); for(int q=0;q<4096;q++) if(region[q]!=(char)0x5A){stale=0;break;} }); if(r==4096 && stale) bug_hits++; else if(r==4096) ok_reads++; else fault_reads++; } stop=1; pthread_join(t,NULL); printf("total=%ld bug_full_success_stale=%ld delivered_ok=%ld fault_reported=%ld guard_faults=%ld\n", total,bug_hits,ok_reads,fault_reads,guard_faults); return 0; } |