Subject: kern/5834: shmdt(2) deallocates wrong region of pages with UVM.
To: None <gnats-bugs@gnats.netbsd.org>
From: None <yasufu-i@is.aist-nara.ac.jp>
List: netbsd-bugs
Date: 07/25/1998 05:24:38
>Number: 5834
>Category: kern
>Synopsis: shmdt(2) deallocates wrong region of pages with UVM.
>Confidential: no
>Severity: serious
>Priority: high
>Responsible: kern-bug-people (Kernel Bug People)
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Fri Jul 24 13:35:01 1998
>Last-Modified:
>Originator: ITOH Yasufumi
>Organization:
Nara Institute of Science and Technology, Nara, Japan
>Release: 1.3F (July 24, 1998)
>Environment:
System: NetBSD libble.my.domain 1.3F NetBSD 1.3F (LIBBLE) #1: Sat Jul 25 03:56:40 JST 1998 itohy@libble.my.domain:/usr/src/sys/arch/alpha/compile/LIBBLE alpha
>Description:
shmdt(2) frees unexpected mapping with the UVM kernel option.
The starting address is correct, but the size is wong,
and the succeeding pages are also unmapped.
I noticed this on Alpha, since it deallocates vast space
including the stack segment(!) and the process receives
SIGSEGV at the next stack operation.
>How-To-Repeat:
Try this on NetBSD/alpha with UVM & SYSVSHM option.
The program gets SIGSEGV after shmdt(),
since the stack does not exist any longer.
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdio.h>
int
main()
{
int id;
void *addr;
int status = 1;
void *volatile foo; /* forced on stack */
if ((id = shmget(IPC_PRIVATE, 16384, IPC_CREAT|0600)) == -1) {
perror("shmget");
return 1;
}
addr = shmat(id, 0, 0);
if (addr == (void *) -1) {
perror("shmat");
goto out;
}
foo = &foo; /* try write stack */
printf("id: %d, addr: %p, foo: %p\n", id, addr, foo);
if (shmdt(addr)) {
perror("shmdt");
goto out;
}
foo = NULL; /* touch stack -- SEGV here */
status = 0; /* all success */
out: if (shmctl(id, IPC_RMID, NULL))
perror("shmctl(IPC_RMID)");
return status;
}
>Fix:
Apply this patch to sys/kern.
diff -uF^[a-zA-Z_][a-z A-Z0-9_]*(.*[^;]$ sys/kern/sysv_shm.c.orig sys/kern/sysv_shm.c
--- sys/kern/sysv_shm.c.orig Fri May 8 20:20:45 1998
+++ sys/kern/sysv_shm.c Sat Jul 25 03:56:13 1998
@@ -163,8 +163,7 @@ shm_delete_mapping(vm, shmmap_s)
shmseg = &shmsegs[segnum];
size = (shmseg->shm_segsz + CLOFSET) & ~CLOFSET;
#ifdef UVM
- result = uvm_deallocate(&vm->vm_map,
- shmmap_s->va, shmmap_s->va + size);
+ result = uvm_deallocate(&vm->vm_map, shmmap_s->va, size);
#else
result = vm_map_remove(&vm->vm_map,
shmmap_s->va, shmmap_s->va + size);
>Audit-Trail:
>Unformatted: