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