DragonFlyBSD Kernel Audit
DF-0931 / small_eFault.c
← back to finding ↓ download raw
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/mman.h>
#include <sys/stat.h>
int main(int argc, char **argv){
    if(argc!=2){fprintf(stderr,"usage: %s <file>\n",argv[0]);return 1;}
    long pagesz = sysconf(_SC_PAGESIZE);
    /* map 1 page, write 100 bytes starting 50 bytes before page end.
     * copyin copies 50 bytes, then EFAULTs on the next page (unmapped). */
    char *buf = mmap(NULL, pagesz, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
    memset(buf, 'X', pagesz);
    char *start = buf + pagesz - 50;  /* 50 valid bytes, then unmapped */
    int fd = open(argv[1], O_WRONLY);
    if(fd<0){perror("open");return 1;}
    ssize_t r = write(fd, start, 100);  /* 100 bytes, only 50 valid */
    fprintf(stderr, "write(%d, start, 100) = %zd errno=%d (%s)\n", fd, r, errno, strerror(errno));
    close(fd);
    struct stat st;
    if(stat(argv[1],&st)==0)
        fprintf(stderr, "mode=%o ISUID=%s\n", st.st_mode&07777,
            (st.st_mode&S_ISUID)?"PRESERVED":"cleared");
    return 0;
}