[LWN Logo]

Date:         Wed, 15 Sep 1999 01:57:57 +0200
From: Henrik Nordstrom <hno@HEM.PASSAGEN.SE>
Subject:      Re: KKIS19990914.004b: ShareDream - shared memory - ipc
To: BUGTRAQ@SECURITYFOCUS.COM

This is a multi-part message in MIME format.

--------------33C58AFA3CE85E0572267A4
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

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).

I am assuming others have made similar patches and tools before, but no
effective limit on shared memory exists in base Linux-2.2.12.

--
Henrik Nordstrom


Robert 'Shadow' Paj1k wrote:

[snip]
>  Raport title        : Shared Memory DoS - IPC vulnerability (Linux
>                        abuse as example)
>  Problem found by    : Robert Pajak (shadow@security.kki.pl),
>                        probably other ppl found that first - one of them is
>                        lcamtuf, Solar Designer is probably other...
[snip]
> This is due to fact that shared memory segments can exist without
> beeing bind with processes. To protect you should diable this
> operations, or use Solar Designer's stack patch with limits set,
> etc...
[snip]

--------------33C58AFA3CE85E0572267A4
Content-Type: text/plain; charset=us-ascii; name="ipc_limit.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline; filename="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

--------------33C58AFA3CE85E0572267A4
Content-Type: text/plain; charset=us-ascii; name="free_shmem.c"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline; filename="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;
}

--------------33C58AFA3CE85E0572267A4--