All of lore.kernel.org
 help / color / mirror / Atom feed
* segmentation fault in /tmp
@ 2002-07-21  2:26 Ed Street
  2002-07-26 14:48 ` [patch] " Stephen Smalley
  0 siblings, 1 reply; 2+ messages in thread
From: Ed Street @ 2002-07-21  2:26 UTC (permalink / raw)
  To: 'Selinux'

Hello,

This is a base install woody 3.0 with a promise controller card
(hardware mirror).  I have /var and /tmp broken off into separate
partitions, 10 gigs each. (40g barracuda drives)  

When /tmp is umounted at any time it produces a Segmentation fault.
(umount /tmp from either console or shutdown/poweroff/halt/reboot
scripts)  Under a non-selinux kernel this behavior is not displayed.

I have avc_enforcing set to permissive using the default policy.  This
is on a clean install after the lsm deb's and the kernel went on, also
Make -C  realabel was ran before reboot.  

This is the message that I get, so far I have been unable to produce any
core files from this.

Unable to handle kernel NULL pointer dereference at virtual address
00000098 printing eip:
*pde = 00000000
Oops: 0000
CPU: 0
EIP: 0010:[<c016017f>] Not tainted
EFLAGS: 00010212
Eax: cf5c0420	ebx: cefad970	ecx: ce71befc	edx: 00000000
Esi: cebad970	edi: c0000000	ebp: ceb8a380	esp: ce71becc
Ds: 0018	es: 0018	ss: 0018
Process umount (pid: 249, stackpage=ce71b000)

Stack: 
ce71a000 c01ae769 cebad970 ce71defc 00000004 ce71bef4 cebadc00 ceb8a380
Cebadc00 c0439f20 0001fd10 00000000 00000000 c01b5584 ceb9a380 ce71a000
Ceb8a380 c014e882 ceb8a280 cf5c0420 ceb8a380 cebad800 cfff8da0 c014b79d

Call Trace: [<c01ae769>} {<c01b5584>] [<c014e882>] [<c014b79d>]
[<c01ad882>]
[<c01ae49d>] [<c01b4010>] [<c0150b82>] [<c0150cae>] [<c0127562>]
[<c0150cd4>]

[<c0107023>]

Code: 8b 82 98 00 00 00 f6 40 2b 10 75 0f f6 82 0c 01 00 00 01 75
 Segmentation fault

Ed


--
You have received this message because you are subscribed to the selinux list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

^ permalink raw reply	[flat|nested] 2+ messages in thread

* [patch] Re: segmentation fault in /tmp
  2002-07-21  2:26 segmentation fault in /tmp Ed Street
@ 2002-07-26 14:48 ` Stephen Smalley
  0 siblings, 0 replies; 2+ messages in thread
From: Stephen Smalley @ 2002-07-26 14:48 UTC (permalink / raw)
  To: Ed Street; +Cc: 'Selinux'

[-- Attachment #1: Type: TEXT/PLAIN, Size: 1159 bytes --]


On Sat, 20 Jul 2002, Ed Street wrote:

> This is a base install woody 3.0 with a promise controller card
> (hardware mirror).  I have /var and /tmp broken off into separate
> partitions, 10 gigs each. (40g barracuda drives)
>
> When /tmp is umounted at any time it produces a Segmentation fault.
> (umount /tmp from either console or shutdown/poweroff/halt/reboot
> scripts)  Under a non-selinux kernel this behavior is not displayed.
<snip>

The attached patch (also committed to the sourceforge CVS) fixes several
bugs in the PSID mapping code related to safely closing the PSID mapping
files and freeing the in-memory data structures for an unmount.  To apply,
save this patch to ~/psid.patch, cd lsm-2.4, and patch -p1 < ~/psid.patch.
Then, rebuild your kernel.

As a side note, Ed ran into this particular bug because his init scripts
were removing everything from /tmp on every boot, including the persistent
label mapping files since /tmp was a separate filesystem.  Naturally, this
would have been denied if the system was in enforcing mode.  It is
obviously not a good idea to remove these files.

--
Stephen D. Smalley, NAI Labs
ssmalley@nai.com



[-- Attachment #2: Type: TEXT/PLAIN, Size: 10951 bytes --]

Index: lsm-2.4/security/selinux/hooks.c
===================================================================
RCS file: /cvsroot/selinux/nsa/lsm-2.4/security/selinux/hooks.c,v
retrieving revision 1.14
diff -u -r1.14 hooks.c
--- lsm-2.4/security/selinux/hooks.c	12 Jul 2002 15:14:26 -0000	1.14
+++ lsm-2.4/security/selinux/hooks.c	26 Jul 2002 14:27:07 -0000
@@ -372,7 +372,7 @@
 	if (!sbsec || sbsec->magic != SELINUX_MAGIC) 
 		return; 
 
-	if (sbsec->uses_psids && sbsec->psidtab)
+	if (sbsec->uses_psids)
 		psid_release(sb);
 
 	sb->s_security = NULL;
@@ -2160,7 +2160,7 @@
 
 	if (reinit_psids) {
 		sbsec = sb->s_security;
-		if (sbsec->uses_psids && sbsec->psidtab) {
+		if (sbsec->uses_psids) {
 			psid_release(sb);
 			rc = psid_init(sb);
 			if (rc < 0) {
@@ -2211,7 +2211,7 @@
 		return;
 	sbsec = sb->s_security;
 
-	if (sbsec->uses_psids && sbsec->psidtab) {
+	if (sbsec->uses_psids) {
 		psid_release(sb);
 		rc = psid_init(sb);
 		if (rc < 0) {
@@ -2392,14 +2392,13 @@
 {
 	struct super_block *sb = inode->i_sb; 
 	if (sb) {
-		struct superblock_security_struct *sbsec;
-		int rc;
+		struct superblock_security_struct *sbsec = sb->s_security;
 
-		rc = superblock_precondition(sb);
-		if (rc <= 0)
+		if (!sbsec || sbsec->magic != SELINUX_MAGIC || 
+		    !sbsec->initialized)
 			return;
-		sbsec = sb->s_security;
-		if (sbsec && sbsec->uses_psids)
+
+		if (sbsec->uses_psids)
 			clear_psid(inode);
 	}
 }
Index: lsm-2.4/security/selinux/psid.c
===================================================================
RCS file: /cvsroot/selinux/nsa/lsm-2.4/security/selinux/psid.c,v
retrieving revision 1.2
diff -u -r1.2 psid.c
--- lsm-2.4/security/selinux/psid.c	24 Jun 2002 13:25:11 -0000	1.2
+++ lsm-2.4/security/selinux/psid.c	26 Jul 2002 14:27:07 -0000
@@ -122,11 +122,13 @@
 	s_index_t raw_sindex;		 /* PSID 0 */
 	spinlock_t lock;
 	struct semaphore sem;
+	unsigned int count;
 };
 typedef struct psidtab psidtab_t;
 
 #define PSIDTAB_HASH(psid) (psid & (PSIDTAB_SLOTS - 1))
 
+static spinlock_t psidtab_lock = SPIN_LOCK_UNLOCKED;
 
 /*
  * Two PSIDs are reserved:  PSID 0
@@ -152,11 +154,11 @@
 	memset(t, 0, sizeof(psidtab_t));
 	t->lock = SPIN_LOCK_UNLOCKED;
 	init_MUTEX(&t->sem);
+	t->count = 1;
 	*tp = t;
 	return 0;
 }
 
-
 /* 
  * Release the PSID mapping files and
  * free the memory used by the PSID cache.
@@ -166,7 +168,6 @@
 	psidtab_node_t     *cur, *tmp;
 	int             hvalue, i;
 
-
 	for (i = 0; i < PSEC_NFILES; i++) {
 		if (t->files[i].f_dentry) {
 			dput(t->files[i].f_dentry);
@@ -185,6 +186,45 @@
 	kfree(t);
 }
 
+static inline psidtab_t *psidtab_get(struct superblock_security_struct *sbsec)
+{
+	psidtab_t *t;
+
+	spin_lock(&psidtab_lock);
+	t = sbsec->psidtab;
+	if (!t || !t->count) {
+		spin_unlock(&psidtab_lock);
+		return NULL;
+	}
+	t->count++;
+	spin_unlock(&psidtab_lock);
+
+	return t;
+}
+
+static inline void psidtab_put(struct superblock_security_struct *sbsec,
+			       psidtab_t *t)
+{
+	spin_lock(&psidtab_lock);
+	if (!t || !t->count) {
+		if (t)
+			printk("psidtab_put:  zero count\n");
+		spin_unlock(&psidtab_lock);
+		return;
+	}
+	t->count--;
+	if (t->count) {
+		spin_unlock(&psidtab_lock);
+		return;
+	}
+	if (sbsec->psidtab == t) {
+		printk("psidtab_put:  psidtab not already cleared.\n");
+		sbsec->psidtab = NULL;
+	}
+	spin_unlock(&psidtab_lock);
+
+	psidtab_destroy(t);
+}
 
 /*
  * Insert an entry for the pair (`psid', `sid') in the PSID cache.
@@ -614,8 +654,8 @@
 		
 		rc = security_context_to_sid(cbuf, rc, &sid);
 		if (rc) {
-			printk("psidfiles_init:  error %d in obtaining SID for context %s (psid %d).\n", 
-			       -rc, cbuf, t->next_psid);
+			printk("psidfiles_init:  invalid context %s (psid %d).\n", 
+			       cbuf, t->next_psid);
 #if 0
 			if ((sb->s_flags & MS_RDONLY) == 0) {
 				rc = write_abs(&t->index_fp, 
@@ -708,6 +748,7 @@
 	dput(file);
 	dput(dir);
 bad:	
+	inode_security_set_sid(sb->s_root->d_inode, SECINITSID_UNLABELED);
 	printk("psidfiles_init:  initialization failed, error %d\n", -rc);
 	return rc;
 }
@@ -722,14 +763,18 @@
 int psid_init(struct super_block *sb)
 {
 	struct superblock_security_struct *sbsec = sb->s_security;
-	psidtab_t *t = sbsec->psidtab;
+	psidtab_t *t = psidtab_get(sbsec);
 	mm_segment_t old_fs;
 	int rc;
 
 
 	if (t) {
-		printk("psid_init:  already initialized this super block\n");
-		return -EACCES;
+		/* PSID mapping is already initialized. 
+		   This can occur from umount_busy if umount_close 
+		   was not called, i.e. this is not the last instance
+		   and it is busy. Not an error. */
+		psidtab_put(sbsec, t);
+		return 0;
 	}
 
 	DPRINTF("psid_init:  creating psidtab\n");
@@ -744,7 +789,6 @@
 	set_fs(old_fs);
 	if (rc)	{
 		psidtab_destroy(t);
-		sbsec->psidtab = 0;
 		return rc;
 	}
 	if (t->initialized)
@@ -764,10 +808,9 @@
 int psid_remount(struct super_block *sb)
 {
 	struct superblock_security_struct *sbsec = sb->s_security;
-	psidtab_t *t = sbsec->psidtab;
+	psidtab_t *t = psidtab_get(sbsec);
 	mm_segment_t old_fs;
 	int i, rc;
-	
 
 	if (!t) {
 		printk("psid_remount:  uninitialized super block\n");
@@ -780,8 +823,7 @@
 		rc = psidfiles_init(sb, t);
 		set_fs(old_fs);
 		if (rc)	{
-			psidtab_destroy(t);
-			sbsec->psidtab = 0;
+			psidtab_put(sbsec, t);
 			panic("VFS:  psid_remount failed (rc=%d)", rc);
 			return rc;
 		}
@@ -807,6 +849,8 @@
 	if (t->initialized)
 		psidtab_hash_eval(t, "remount");
 
+	psidtab_put(sbsec, t);
+
 	return 0;
 }
 
@@ -818,18 +862,35 @@
 void psid_release(struct super_block *sb)
 {
 	struct superblock_security_struct *sbsec = sb->s_security;
-	if (!sbsec->psidtab) {
-		printk("psid_release:  uninitialized super block\n");
+	psidtab_t *t = psidtab_get(sbsec);
+
+	if (!t) {
+		/* PSID mapping was already released (or never initialized). 
+		   This can occur from superblock_free_security, since 
+		   the PSID mapping is typically released by umount_close.
+		   Not an error. */
 		return;
 	}
 
 	DPRINTF("psid_release:  destroying psidtab\n");
 
-	if (sbsec->psidtab->initialized)
+	if (t->initialized)
 		psidtab_hash_eval(sb->s_security, "release");
 
-	psidtab_destroy(sbsec->psidtab);
-	sbsec->psidtab = 0;
+	/* Forcibly clear sbsec->psidtab, rather than 
+	   merely waiting for the final psidtab_put. 
+	   This ensures that a subsequent psid_init will 
+	   be able to succeed, e.g. for umount_busy or post_pivotroot. 
+	   Take the semaphore to synchronize with in-progress writes. */
+	down(&t->sem);
+	sbsec->psidtab = NULL;
+	up(&t->sem);
+
+	/* Put twice, once for the get above and once to drop
+	   the reference saved in sbsec.  Only transient references
+	   will remain for in-progress PSID functions. */
+	psidtab_put(sbsec, t);
+	psidtab_put(sbsec, t);
 }
 
 
@@ -842,14 +903,13 @@
 	struct super_block *sb = inode->i_sb;
 	struct superblock_security_struct *sbsec = sb->s_security;
 	struct inode_security_struct *isec;
-	psidtab_t *t = sbsec->psidtab;
+	psidtab_t *t = psidtab_get(sbsec);
 	psid_t psid, raw_psid;
 	security_id_t sid;
 	mm_segment_t old_fs;
 	int rc;
 
 	if (!t) {
-		printk("psid_to_sid:  ino %ld -> unlabeled\n", inode->i_ino);
 		*out_sid = SECINITSID_UNLABELED;
 		return 0;
 	}
@@ -857,6 +917,7 @@
 	if (!t->initialized) {
 		isec = sb->s_root->d_inode->i_security;
 		*out_sid = isec->sid;
+		psidtab_put(sbsec, t);
 		return 0;
 	}
 
@@ -868,6 +929,7 @@
 		printk("psid_to_sid:  unable to read inodes for %ld, using unlabeled\n", 
 		       inode->i_ino);
 		*out_sid = SECINITSID_UNLABELED;
+		psidtab_put(sbsec, t);
 		return 0;
 	}
 	if (rc == 0)
@@ -880,14 +942,14 @@
 		DPRINTF("psid_to_sid:  no SID for psid %d\n", psid);
 		sid = psidtab_search_psid(t, 0);
 		if (!sid) {
-			printk("psid_to_sid:  psid %d -> unlabeled\n", psid);
 			inode_security_set_sid(inode, SECINITSID_UNLABELED);
+			psidtab_put(sbsec, t);
 			return 0;
 		}
 	}
 
 	*out_sid = sid;
-
+	psidtab_put(sbsec, t);
 	return 0;
 }
 
@@ -905,19 +967,26 @@
 {
 	struct super_block *sb = inode->i_sb;
 	struct superblock_security_struct *sbsec = sb->s_security;
-	psidtab_t *t = sbsec->psidtab;
+	psidtab_t *t = psidtab_get(sbsec);
 	psid_t          psid, raw_psid;
 	int rc = 0;
 	mm_segment_t old_fs;
 
 	if (!t || !t->initialized) {
+		psidtab_put(sbsec, t);
 		return 0;
 	}
 
 	psid = psidtab_search_sid(t, sid, 0);
 	if (!psid) {
+		psidtab_put(sbsec, t);
 		down(&t->sem);
 		/* Rescan now that we hold the semaphore */
+		t = psidtab_get(sbsec);
+		if (!t || !t->initialized) {
+			rc = -EACCES;
+			goto up_out;
+		}
 		psid = psidtab_search_sid(t, sid, 0);
 		if (psid) 
 			goto up_out;
@@ -935,8 +1004,10 @@
 		up(&t->sem);
 	}
 
-	if (rc)
+	if (rc) {
+		psidtab_put(sbsec, t);
 		return rc;
+	}
 
 	raw_psid = cpu_to_le32(psid);
 
@@ -945,8 +1016,11 @@
 	rc = write_abs(&t->inodes_fp, (char*)&raw_psid, sizeof(psid_t), 
 		       inode->i_ino * sizeof(psid_t));
 	set_fs(old_fs);
-	if (rc < 0) 
+	if (rc < 0) {
+		psidtab_put(sbsec, t);
 		return rc;
+	}
+	psidtab_put(sbsec, t);
 	return 0;
 }
 
@@ -954,12 +1028,13 @@
 {
 	struct super_block *sb = inode->i_sb;
 	struct superblock_security_struct *sbsec = sb->s_security;
-	psidtab_t *t = sbsec->psidtab;
+	psidtab_t *t = psidtab_get(sbsec);
 	psid_t          raw_psid;
 	int rc;
 	mm_segment_t old_fs;
 
 	if (!t || !t->initialized) {
+		psidtab_put(sbsec, t);
 		return 0;
 	}
 
@@ -970,8 +1045,11 @@
 	rc = write_abs(&t->inodes_fp, (char*)&raw_psid, sizeof(psid_t), 
 		       inode->i_ino * sizeof(psid_t));
 	set_fs(old_fs);
-	if (rc < 0) 
+	if (rc < 0) {
+		psidtab_put(sbsec, t);
 		return rc;
+	}
+	psidtab_put(sbsec, t);
 	return 0;
 }
 
@@ -1080,36 +1158,43 @@
 		 security_id_t f_sid)
 {
 	struct superblock_security_struct *sbsec = sb->s_security;
-	psidtab_t *t = sbsec->psidtab;
+	psidtab_t *t = psidtab_get(sbsec);
 	mm_segment_t old_fs;
 	int rc = 0;
 
 
 	if (sb->s_flags & MS_RDONLY) {
 		DPRINTF("psid_chsidfs:  file system is read-only\n");
+		psidtab_put(sbsec, t);
 		return -EACCES;
 	}
 
 	if (!t || !t->initialized) {
-		printk("psid_chsidfs:  uninitialized super block\n");
+		psidtab_put(sbsec, t);
 		return -EACCES;
 	}	
 
-	old_fs = get_fs();
-	set_fs(KERNEL_DS);
 
+	psidtab_put(sbsec, t);
 	down(&t->sem);
+	t = psidtab_get(sbsec);
+	if (!t || !t->initialized) {
+		rc = -EACCES;
+		goto out;
+	}
 
+	old_fs = get_fs();
+	set_fs(KERNEL_DS);
 	if (fs_sid) {
 		rc = chpsid(t, FS_PSID, fs_sid);
 	}
 	if (f_sid && !rc) {
 		rc = chpsid(t, FILE_PSID, f_sid);
 	}
-
-	up(&t->sem);
-
 	set_fs(old_fs);
 
+out:
+	up(&t->sem);
+	psidtab_put(sbsec, t);
 	return rc;
 }

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2002-07-26 14:49 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2002-07-21  2:26 segmentation fault in /tmp Ed Street
2002-07-26 14:48 ` [patch] " Stephen Smalley

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.