Re: OT: howto remove SHM that was attached by shmat

Marc-Christian Petersen <[email protected]> Sat, 17 Apr 2004 18:38:49 +0200
Newsgroups gmane.linux.wolk.devel
Organization Linux-Systeme GmbH
Message-ID <200404171838.49229@WOLK>
On Saturday 17 April 2004 17:58, Marc-Christian Petersen wrote:

Hi again,

> > Attached a patch ontop of 2.4.20-WOLK4.14s. Patch untested yet. Compiles
> > at least. This stuff is also in 2.2-secure for ages. And now I ask myself
> > why I didn't merge that into 2.4-WOLK earlier. I'll forward port it to
> > 2.6-WOLK in the next minutes ...

> ok, that patch is bogus. Attached one actually works :)

ok, attached one ontop of 2.6.5-wolk3.0-rc2 with grsecurity addon applied.

Care to test this one? :) Anyone?

ciao, Marc
grsecurity-2.0+-harden-shm-from-openwall-v2.patch (text/x-diff, 3.4 KB)
--- old/grsecurity/Kconfig	2004-04-17 00:36:42.000000000 +0200
+++ new/grsecrutiy/Kconfig	2004-04-17 18:22:58.000000000 +0200
@@ -821,6 +821,25 @@ config GRKERNSEC_TPE_GID
 	  on the sysctl option for more information.  If the sysctl option is
 	  enabled, a sysctl option with name "tpe_gid" is created.
 
+config GRKERNSEC_HARDEN_SHM
+	bool "Destroy shared memory segments not in use"
+	depends on SYSVIPC
+	default n
+	help
+	  Linux lets you set resource limits, including on how much memory one
+	  process can consume, via setrlimit(2). Unfortunately, shared memory
+	  segments are allowed to exist without association with any process,
+	  and thus might not be counted against any resource limits. This option
+	  automatically destroys shared memory segments when their attach count
+	  becomes zero after a detach or a process termination. It will also
+	  destroy segments that were created, but never attached to, on exit from
+	  the process. (In case you're curious, the only use left for IPC_RMID is
+	  to immediately destroy an unattached segment.) Of course, this breaks
+	  the way things are defined, so some applications might stop working.
+	  Note that this feature will do you no good unless you also configure
+	  your resource limits (in particular, RLIMIT_AS and RLIMIT_NPROC). Most
+	  systems don't need this.
+
 endmenu
 
 menu "Network Protections"
--- old/kernel/exit.c	2004-04-17 00:25:09.000000000 +0200
+++ new/kernel/exit.c	2004-04-17 18:09:16.000000000 +0200
@@ -34,6 +34,9 @@
 #include <asm/mmu_context.h>
 
 extern void sem_exit (void);
+#ifdef CONFIG_GRKERNSEC_HARDEN_SHM
+extern void exit_shm (void);
+#endif
 extern struct task_struct *child_reaper;
 
 int getrusage(struct task_struct *, int, struct rusage *);
@@ -827,6 +830,9 @@ asmlinkage NORET_TYPE void do_exit(long 
 	__exit_mm(tsk);
 
 	exit_sem(tsk);
+#ifdef CONFIG_GRKERNSEC_HARDEN_SHM
+	exit_shm();
+#endif
 	__exit_files(tsk);
 	__exit_fs(tsk);
 	exit_namespace(tsk);
--- old/ipc/shm.c	2004-04-17 00:25:09.000000000 +0200
+++ new/ipc/shm.c	2004-04-17 18:11:55.000000000 +0200
@@ -148,14 +148,41 @@ static void shm_close (struct vm_area_st
 	shp->shm_lprid = current->tgid;
 	shp->shm_dtim = get_seconds();
 	shp->shm_nattch--;
+#ifdef CONFIG_GRKERNSEC_HARDEN_SHM
+	if(shp->shm_nattch == 0) {
+		shp->shm_flags |= SHM_DEST;
+		shm_destroy (shp);
+	}
+#else
 	if(shp->shm_nattch == 0 &&
 	   shp->shm_flags & SHM_DEST)
 		shm_destroy (shp);
+#endif
 	else
 		shm_unlock(shp);
 	up (&shm_ids.sem);
 }
 
+#ifdef CONFIG_GRKERNSEC_HARDEN_SHM
+void exit_shm (void)
+{
+	int i;
+	struct shmid_kernel *shp;
+
+	for (i = 0; i <= shm_ids.max_id; i++) {
+		shp = shm_get(i);
+		if (!shp) continue;
+
+		if (shp->shm_cprid != current->pid) continue;
+
+		if (shp->shm_nattch <= 0) {
+			shp->shm_flags |= SHM_DEST;
+			shm_destroy (shp);
+		}
+	}
+}
+#endif
+
 static int shm_mmap(struct file * file, struct vm_area_struct * vma)
 {
 	file_accessed(file);
--- old/include/linux/sem.h	2004-04-16 23:51:29.000000000 +0200
+++ new/include/linux/sem.h	2004-04-17 18:20:52.000000000 +0200
@@ -138,6 +138,7 @@ struct sysv_sem {
 
 extern int copy_semundo(unsigned long clone_flags, struct task_struct *tsk);
 extern void exit_sem(struct task_struct *tsk);
+extern void exit_shm(void);
 
 #else
 static inline int copy_semundo(unsigned long clone_flags, struct task_struct *tsk)
@@ -149,6 +150,12 @@ static inline void exit_sem(struct task_
 {
 	return;
 }
+
+static inline void exit_shm(void)
+{
+	return;
+}
+
 #endif
 
 #endif /* __KERNEL__ */