| Summary: | Bug in VM page protection handling. | ||||||
|---|---|---|---|---|---|---|---|
| Product: | Base System | Reporter: | Pawel Jakub Dawidek <nick> | ||||
| Component: | kern | Assignee: | freebsd-bugs (Nobody) <bugs> | ||||
| Status: | Closed FIXED | ||||||
| Severity: | Affects Only Me | CC: | alc | ||||
| Priority: | Normal | ||||||
| Version: | Unspecified | ||||||
| Hardware: | Any | ||||||
| OS: | Any | ||||||
| Attachments: |
|
||||||
State Changed From-To: open->closed As alc@ said it is not a bug. Adding to audit trail, from misfiled PR kern/54420: Date: Sat, 12 Jul 2003 15:36:27 -0500 From: "Alan L. Cox" <alc@imimic.com> Message-Id: <3F10714B.44FAD294@imimic.com> References: <20030712201112.87A7E3ABB53@milla.ask33.net> Never mind the comment about the breakage. That is not correct. Regards, Alan |
There is a problem in setting page protection in function vm_map_protect(). When we set for example max_protection to VM_PROT_READ and after that we will try do change max_protection to VM_PROT_ALL there is no chance to do that, because of bogus check. This 'if' doesn't check if we set max_protection or just protection and denieds all increasing max_protection tries. Problem doesn't affect FreeBSD directly, because such situation never occurs, but for 3rd-party kernel modules this could be importent. For example, for my module - cerb - where I need to do operations on VM pages, it is very important and this bug provoke 'Bus error's in some situations. Fix: This patch fix this. How-To-Repeat: This sample kernel module shows the problem. It is for FreeBSD 4.x, but simlar could be prepared for 5.x. #include <sys/param.h> #include <sys/proc.h> #include <sys/kernel.h> #include <sys/module.h> #include <sys/systm.h> #include <sys/lock.h> #include <vm/vm.h> #include <vm/pmap.h> #include <vm/vm_map.h> static int mod(struct module *module, int cmd, void *arg) { vm_map_t map = &curproc->p_vmspace->vm_map; vm_offset_t start, end; int error = 0; switch (cmd) { case MOD_LOAD: end = start = (vm_offset_t)curproc->p_vmspace->vm_daddr + ctob(curproc->p_vmspace->vm_dsize); start--; error = vm_map_protect(map, start, end, VM_PROT_READ, TRUE); printf("ERROR1: %d\n", error); error = vm_map_protect(map, start, end, VM_PROT_ALL, TRUE); /* Here should be 2 which means KERN_PROTECTION_FAILURE. */ printf("ERROR2: %d\n", error); error = 0; printf("testmod loaded.\n"); break; case MOD_UNLOAD: printf("testmod unloaded.\n"); break; default: error = EINVAL; break; } return (error); } static moduledata_t testmod_mod = { "testmod", mod, NULL }; DECLARE_MODULE(testmod, testmod_mod, SI_SUB_DRIVERS, SI_ORDER_MIDDLE);