Hello all.

mprotect(2) says: "If len is 0, then action will be taken on the page
that contains addr". The reality says it's not so:

$ cat ~/cvs/mprotect_test.c

#include <sys/types.h>
#include <sys/param.h>
#include <sys/mman.h>

#include <stdio.h>
#include <unistd.h>

void
mymemset(char *p, int c, size_t len) {
        size_t  i;
        char    cc;

        cc = (char)(c & 0xFF);
        for (i = 0; i < len; i++) {
                fputc('.', stderr);
                p[i] = cc;
        }
}

int
main(int argc, char **argv) {
        long     pgsz;
        char    *p;

        pgsz = sysconf(_SC_PAGESIZE);
        if ((p = (char*)mmap(NULL, pgsz * 3, PROT_NONE, MAP_ANON, -1, 0)) == 
NULL)
                err(1, "mmap");
        if (mprotect(p + pgsz, 0, PROT_READ|PROT_WRITE) == -1)
                err(1, mprotect);
        fputs("writing to page 1: ", stderr);
        mymemset(p + pgsz, 0xCC, pgsz);
        fputs("OK\nwriting to page 0: ", stderr);
        mymemset(p, 0xCC, pgsz);
        fputs("OK (WTF?!)\nwriting to page 2: ", stderr);
        mymemset(p + (pgsz * 2), 0xCC, pgsz);
        fputs("OK (WTF?!)\n", stderr);

        return 1;
}
$ cc -O0 -ggdb -o mprotect_test mprotect_test.c
$ ./mprotect_test
writing to page 1: .Segmentation fault (core dumped)
$

I checked the SUS, and it is not clear: "The mprotect() function shall
change the access protections to be that specified by prot for those
whole pages containing any part of the address space of the process
starting at address addr and continuing for len bytes."

So either sys_mprotect(), uvm_map_protect() or man page is not correct.
As I'm totally newbie in UVM, please, do not bite me for the patch
proposed below. At least, very much. :)

-- 
  Best wishes,
    Vadim Zhukov

A: Because it messes up the order in which people normally read text.
Q: Why is top-posting such a bad thing?
A: Top-posting.
Q: What is the most annoying thing in e-mail?


@@ -778,6 +778,8 @@ sys_mprotect(struct proc *p, void *v, re
        
        if ((prot & VM_PROT_ALL) != prot)
                return (EINVAL);
+       if (size == 0)
+               size = PAGE_SIZE;
 
        /*
         * align the address to a page boundary, and adjust the size accordingly

Reply via email to