mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH] (3/3) SELinux context mount support - SELinux changes.
       [not found] <Xine.LNX.4.44.0402040949010.4796@thoron.boston.redhat.com>
@ 2004-02-04 15:33 ` James Morris
  2004-02-05 10:17   ` Valdis.Kletnieks
  0 siblings, 1 reply; 4+ messages in thread
From: James Morris @ 2004-02-04 15:33 UTC (permalink / raw)
  To: Andrew Morton, Alexander Viro
  Cc: Stephen Smalley, linux-kernel, selinux, Chris Wright

This patch implements context mount support within SELinux.

Three new mount options are provided:

context=%s
  Label the entire filesystem with the specified security context during
  mount and change the labeling behavior to 'mountpoint labeling'.  The 
  /proc/self/attr/fscreate attribute will be ignored for file creation on 
  the filesystem, although policy-specified transitions will still work 
  normally.  This also sets the aggregate filesystem security context.

fscontext=%s
  Set the label of the aggregate filesystem to the specified security 
  context, so that SELinux policy controls over the filesystem itself may 
  be reinstated.  Only works for filesystems without EA labeling support, 
  and is not valid if 'context' has been specified.

defcontext=%s
  Set the default security context for files created in this filesystem to 
  the specified security context (as opposed to the current global default).
  Only works for filesystems without EA labeling support, and is not 
  valid if 'context' has been specified.

To set the context or fscontext options, the security policy must specify
appropriate permissions for the filesystem relabelfrom and filesystem
relabelto controls.  For the defcontext option, the filesystem relablefrom
and filesystem assoicate controls are invoked.

The security mount options are parsed out and stripped from the normal 
mount option data so that no normal filesystems need to be aware of them.  

Filesystems with binary mount option data (e.g. NFS, SMBFS, AFS, Coda) 
need to be handled as special cases: only NFS is supprted at this stage 
per the previous patch.


 security/selinux/hooks.c            |  315 +++++++++++++++++++++++++++++++++---
 security/selinux/include/objsec.h   |    1 
 security/selinux/include/security.h |   12 -
 3 files changed, 303 insertions(+), 25 deletions(-)

diff -urN -X dontdiff linux-2.6.2.p/security/selinux/hooks.c linux-2.6.2.w/security/selinux/hooks.c
--- linux-2.6.2.p/security/selinux/hooks.c	2004-02-04 08:39:07.000000000 -0500
+++ linux-2.6.2.w/security/selinux/hooks.c	2004-02-04 09:08:51.914484008 -0500
@@ -56,6 +56,8 @@
 #include <linux/quota.h>
 #include <linux/un.h>		/* for Unix socket types */
 #include <net/af_unix.h>	/* for Unix socket types */
+#include <linux/parser.h>
+#include <linux/nfs_mount.h>
 
 #include "avc.h"
 #include "objsec.h"
@@ -223,6 +225,7 @@
 	sbsec->magic = SELINUX_MAGIC;
 	sbsec->sb = sb;
 	sbsec->sid = SECINITSID_UNLABELED;
+	sbsec->def_sid = SECINITSID_FILE;
 	sb->s_security = sbsec;
 
 	return 0;
@@ -283,12 +286,13 @@
 
 /* The file system's label must be initialized prior to use. */
 
-static char *labeling_behaviors[5] = {
+static char *labeling_behaviors[6] = {
 	"uses xattr",
 	"uses transition SIDs",
 	"uses task SIDs",
 	"uses genfs_contexts",
-	"not configured for labeling"
+	"not configured for labeling",
+	"uses mountpoint labeling",
 };
 
 static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dentry);
@@ -298,7 +302,200 @@
 	return inode_doinit_with_dentry(inode, NULL);
 }
 
-static int superblock_doinit(struct super_block *sb)
+enum {
+	Opt_context = 1,
+	Opt_fscontext = 2,
+	Opt_defcontext = 4,
+};
+
+static match_table_t tokens = {
+	{Opt_context, "context=%s"},
+	{Opt_fscontext, "fscontext=%s"},
+	{Opt_defcontext, "defcontext=%s"},
+};
+
+#define SEL_MOUNT_FAIL_MSG "SELinux:  duplicate or incompatible mount options\n"
+
+static int try_context_mount(struct super_block *sb, void *data)
+{
+	char *context = NULL, *defcontext = NULL;
+	const char *name;
+	u32 sid;
+	int alloc = 0, rc = 0, seen = 0;
+	struct task_security_struct *tsec = current->security;
+	struct superblock_security_struct *sbsec = sb->s_security;
+
+	if (!data)
+		goto out;
+	
+	name = sb->s_type->name;
+	
+	/* Ignore these fileystems with binary mount option data. */
+	if (!strcmp(name, "coda") ||
+	    !strcmp(name, "afs") || !strcmp(name, "smbfs"))
+		goto out;
+
+	/* NFS we understand. */
+	if (!strcmp(name, "nfs")) {
+		struct nfs_mount_data *d = data;
+		
+		if (d->version <  NFS_MOUNT_VERSION)
+			goto out;
+			
+		if (d->context[0]) {
+			context = d->context;
+			seen |= Opt_context;
+		}
+
+	/* Standard string-based options. */
+	} else {
+		char *p, *options = data;
+		
+		while ((p = strsep(&options, ",")) != NULL) {
+			int token;
+			substring_t args[MAX_OPT_ARGS];
+			
+			if (!*p)
+				continue;
+
+			token = match_token(p, tokens, args);
+
+			switch (token) {
+			case Opt_context:
+				if (seen) {
+					rc = -EINVAL;
+					printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
+					goto out_free;
+				}
+				context = match_strdup(&args[0]);
+				if (!context) {
+					rc = -ENOMEM;
+					goto out_free;
+				}
+				if (!alloc)
+					alloc = 1;
+				seen |= Opt_context;
+				break;
+			
+			case Opt_fscontext:
+				if (sbsec->behavior != SECURITY_FS_USE_XATTR) {
+					rc = -EINVAL;
+					printk(KERN_WARNING "SELinux:  "
+					       "fscontext option is invalid for"
+					       " this filesystem type\n");
+					goto out_free;
+				}
+				if (seen & (Opt_context|Opt_fscontext)) {
+					rc = -EINVAL;
+					printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
+					goto out_free;
+				}
+				context = match_strdup(&args[0]);
+				if (!context) {
+					rc = -ENOMEM;
+					goto out_free;
+				}
+				if (!alloc)
+					alloc = 1;
+				seen |= Opt_fscontext;
+				break;
+
+			case Opt_defcontext:
+				if (sbsec->behavior != SECURITY_FS_USE_XATTR) {
+					rc = -EINVAL;
+					printk(KERN_WARNING "SELinux:  "
+					       "defcontext option is invalid "
+					       "for this filesystem type\n");
+					goto out_free;
+				}
+				if (seen & (Opt_context|Opt_defcontext)) {
+					rc = -EINVAL;
+					printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
+					goto out_free;
+				}
+				defcontext = match_strdup(&args[0]);
+				if (!defcontext) {
+					rc = -ENOMEM;
+					goto out_free;
+				}
+				if (!alloc)
+					alloc = 1;
+				seen |= Opt_defcontext;
+				break;
+
+			default:
+				rc = -EINVAL;
+				printk(KERN_WARNING "SELinux:  unknown mount "
+				       "option\n");
+				goto out_free;
+			
+			}
+		}
+	}
+	
+	if (!seen)
+		goto out;
+
+	if (context) {
+		rc = security_context_to_sid(context, strlen(context), &sid);
+		if (rc) {
+			printk(KERN_WARNING "SELinux: security_context_to_sid"
+			       "(%s) failed for (dev %s, type %s) errno=%d\n",
+			       context, sb->s_id, name, rc);
+			goto out_free;
+		}
+		
+		rc = avc_has_perm(tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM,
+		                  FILESYSTEM__RELABELFROM, NULL, NULL);
+		if (rc)
+			goto out_free;
+			
+		rc = avc_has_perm(tsec->sid, sid, SECCLASS_FILESYSTEM,
+		                  FILESYSTEM__RELABELTO, NULL, NULL);
+		if (rc)
+			goto out_free;
+			
+		sbsec->sid = sid;
+		
+		if (seen & Opt_context)
+			sbsec->behavior = SECURITY_FS_USE_MNTPOINT;
+	}
+
+	if (defcontext) {
+		rc = security_context_to_sid(defcontext, strlen(defcontext), &sid);
+		if (rc) {
+			printk(KERN_WARNING "SELinux: security_context_to_sid"
+			       "(%s) failed for (dev %s, type %s) errno=%d\n",
+			       defcontext, sb->s_id, name, rc);
+			goto out_free;
+		}
+
+		if (sid == sbsec->def_sid)
+			goto out_free;
+		
+		rc = avc_has_perm(tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM,
+				  FILESYSTEM__RELABELFROM, NULL, NULL);
+		if (rc)
+			goto out_free;
+			
+		rc = avc_has_perm(sid, sbsec->sid, SECCLASS_FILESYSTEM,
+				  FILESYSTEM__ASSOCIATE, NULL, NULL); 
+		if (rc)
+			goto out_free;
+
+		sbsec->def_sid = sid;
+	}
+
+out_free:
+	if (alloc) {
+		kfree(context);
+		kfree(defcontext);
+	}
+out:
+	return rc;
+}
+
+static int superblock_doinit(struct super_block *sb, void *data)
 {
 	struct superblock_security_struct *sbsec = sb->s_security;
 	struct dentry *root = sb->s_root;
@@ -328,6 +525,10 @@
 		goto out;
 	}
 
+	rc = try_context_mount(sb, data);
+	if (rc)
+		goto out;
+
 	if (sbsec->behavior == SECURITY_FS_USE_XATTR) {
 		/* Make sure that the xattr handler exists and that no
 		   error other than -ENODATA is returned by getxattr on
@@ -530,7 +731,7 @@
 	switch (sbsec->behavior) {
 	case SECURITY_FS_USE_XATTR:
 		if (!inode->i_op->getxattr) {
-			isec->sid = SECINITSID_FILE;
+			isec->sid = sbsec->def_sid;
 			break;
 		}
 
@@ -589,7 +790,7 @@
 				goto out;
 			}
 			/* Map ENODATA to the default file SID */
-			sid = SECINITSID_FILE;
+			sid = sbsec->def_sid;
 			rc = 0;
 		} else {
 			rc = security_context_to_sid(context, rc, &sid);
@@ -829,6 +1030,7 @@
 
 	tsec = current->security;
 	dsec = dir->i_security;
+	sbsec = dir->i_sb->s_security;
 
 	AVC_AUDIT_DATA_INIT(&ad, FS);
 	ad.u.fs.dentry = dentry;
@@ -839,7 +1041,7 @@
 	if (rc)
 		return rc;
 
-	if (tsec->create_sid) {
+	if (tsec->create_sid && sbsec->behavior != SECURITY_FS_USE_MNTPOINT) {
 		newsid = tsec->create_sid;
 	} else {
 		rc = security_transition_sid(tsec->sid, dsec->sid, tclass,
@@ -852,8 +1054,6 @@
 	if (rc)
 		return rc;
 
-	sbsec = dir->i_sb->s_security;
-
 	return avc_has_perm(newsid, sbsec->sid,
 			    SECCLASS_FILESYSTEM,
 			    FILESYSTEM__ASSOCIATE, NULL, &ad);
@@ -1061,6 +1261,7 @@
 
 	tsec = current->security;
 	dsec = dir->i_security;
+	sbsec = dir->i_sb->s_security;
 
 	inode = dentry->d_inode;
 	if (!inode) {
@@ -1072,7 +1273,7 @@
 		return 0;
 	}
 
-	if (tsec->create_sid) {
+	if (tsec->create_sid && sbsec->behavior != SECURITY_FS_USE_MNTPOINT) {
 		newsid = tsec->create_sid;
 	} else {
 		rc = security_transition_sid(tsec->sid, dsec->sid,
@@ -1095,10 +1296,6 @@
 		return rc;
 	}
 
-	sbsec = dir->i_sb->s_security;
-	if (!sbsec)
-		return 0;
-
 	if (sbsec->behavior == SECURITY_FS_USE_XATTR &&
 	    inode->i_op->setxattr) {
 		/* Use extended attributes. */
@@ -1660,12 +1857,83 @@
 	superblock_free_security(sb);
 }
 
-static int selinux_sb_kern_mount(struct super_block *sb)
+static inline int match_prefix(char *prefix, int plen, char *option, int olen)
+{
+	if (plen > olen)
+		return 0;
+
+	return !memcmp(prefix, option, plen);
+}
+
+static inline int selinux_option(char *option, int len)
+{
+	return (match_prefix("context=", sizeof("context=")-1, option, len) ||
+	        match_prefix("fscontext=", sizeof("fscontext=")-1, option, len) ||
+	        match_prefix("defcontext=", sizeof("defcontext=")-1, option, len));
+}
+
+static inline void take_option(char **to, char *from, int *first, int len)
+{
+	if (!*first) {
+		**to = ',';
+		*to += 1;
+	}
+	else
+		*first = 0;
+	memcpy(*to, from, len);
+	*to += len;
+}
+
+static int selinux_sb_copy_data(const char *fstype, void *orig, void *copy)
+{
+	int fnosec, fsec, rc = 0;
+	char *in_save, *in_curr, *in_end;
+	char *sec_curr, *nosec_save, *nosec;
+
+	in_curr = orig;
+	sec_curr = copy;
+
+	/* Binary mount data: just copy */
+	if (!strcmp(fstype, "nfs") || !strcmp(fstype, "coda") ||
+	    !strcmp(fstype, "smbfs") || !strcmp(fstype, "afs")) {
+		copy_page(sec_curr, in_curr);
+		goto out;
+	}
+
+	nosec = (char *)get_zeroed_page(GFP_KERNEL);
+	if (!nosec) {
+		rc = -ENOMEM;
+		goto out;
+	}
+
+	nosec_save = nosec;
+	fnosec = fsec = 1;
+	in_save = in_end = orig;
+
+	do {
+		if (*in_end == ',' || *in_end == '\0') {
+			int len = in_end - in_curr;
+			
+			if (selinux_option(in_curr, len))
+				take_option(&sec_curr, in_curr, &fsec, len);
+			else
+				take_option(&nosec, in_curr, &fnosec, len);
+
+			in_curr = in_end + 1;
+		}
+	} while (*in_end++);
+	
+	copy_page(in_save, nosec_save);
+out:
+	return rc;
+}
+
+static int selinux_sb_kern_mount(struct super_block *sb, void *data)
 {
 	struct avc_audit_data ad;
 	int rc;
 
-	rc = superblock_doinit(sb);
+	rc = superblock_doinit(sb, data);
 	if (rc)
 		return rc;
 
@@ -1857,6 +2125,10 @@
 		return dentry_has_perm(current, NULL, dentry, FILE__SETATTR);
 	}
 
+	sbsec = inode->i_sb->s_security;
+	if (sbsec->behavior == SECURITY_FS_USE_MNTPOINT)
+		return -ENOTSUPP;
+
 	AVC_AUDIT_DATA_INIT(&ad,FS);
 	ad.u.fs.dentry = dentry;
 
@@ -1875,10 +2147,6 @@
 	if (rc)
 		return rc;
 
-	sbsec = inode->i_sb->s_security;
-	if (!sbsec)
-		return 0;
-
 	return avc_has_perm(newsid,
 			    sbsec->sid,
 			    SECCLASS_FILESYSTEM,
@@ -1913,6 +2181,12 @@
 
 static int selinux_inode_getxattr (struct dentry *dentry, char *name)
 {
+	struct inode *inode = dentry->d_inode;
+	struct superblock_security_struct *sbsec = inode->i_sb->s_security;
+	
+	if (sbsec->behavior == SECURITY_FS_USE_MNTPOINT)
+		return -ENOTSUPP;
+
 	return dentry_has_perm(current, NULL, dentry, FILE__GETATTR);
 }
 
@@ -3555,6 +3829,7 @@
 
 	.sb_alloc_security =		selinux_sb_alloc_security,
 	.sb_free_security =		selinux_sb_free_security,
+	.sb_copy_data =			selinux_sb_copy_data,
 	.sb_kern_mount =	        selinux_sb_kern_mount,
 	.sb_statfs =			selinux_sb_statfs,
 	.sb_mount =			selinux_mount,
@@ -3731,7 +4006,7 @@
 		spin_unlock(&sb_security_lock);
 		down_read(&sb->s_umount);
 		if (sb->s_root)
-			superblock_doinit(sb);
+			superblock_doinit(sb, NULL);
 		drop_super(sb);
 		spin_lock(&sb_security_lock);
 		list_del_init(&sbsec->list);
diff -urN -X dontdiff linux-2.6.2.p/security/selinux/include/objsec.h linux-2.6.2.w/security/selinux/include/objsec.h
--- linux-2.6.2.p/security/selinux/include/objsec.h	2004-02-04 08:39:07.000000000 -0500
+++ linux-2.6.2.w/security/selinux/include/objsec.h	2004-02-04 09:08:51.915483856 -0500
@@ -63,6 +63,7 @@
 	struct super_block *sb;         /* back pointer to sb object */
 	struct list_head list;          /* list of superblock_security_struct */
 	u32 sid;              /* SID of file system */
+	u32 def_sid;			/* default SID for labeling */
 	unsigned int behavior;          /* labeling behavior */
 	unsigned char initialized;      /* initialization flag */
 	unsigned char proc;             /* proc fs */
diff -urN -X dontdiff linux-2.6.2.p/security/selinux/include/security.h linux-2.6.2.w/security/selinux/include/security.h
--- linux-2.6.2.p/security/selinux/include/security.h	2003-10-28 10:59:50.000000000 -0500
+++ linux-2.6.2.w/security/selinux/include/security.h	2004-02-04 09:08:51.916483704 -0500
@@ -62,11 +62,13 @@
 int security_node_sid(u16 domain, void *addr, u32 addrlen,
 	u32 *out_sid);
 
-#define SECURITY_FS_USE_XATTR 1 /* use xattr */
-#define SECURITY_FS_USE_TRANS 2 /* use transition SIDs, e.g. devpts/tmpfs */
-#define SECURITY_FS_USE_TASK  3 /* use task SIDs, e.g. pipefs/sockfs */
-#define SECURITY_FS_USE_GENFS 4 /* use the genfs support */
-#define SECURITY_FS_USE_NONE  5 /* no labeling support */
+#define SECURITY_FS_USE_XATTR		1 /* use xattr */
+#define SECURITY_FS_USE_TRANS		2 /* use transition SIDs, e.g. devpts/tmpfs */
+#define SECURITY_FS_USE_TASK		3 /* use task SIDs, e.g. pipefs/sockfs */
+#define SECURITY_FS_USE_GENFS		4 /* use the genfs support */
+#define SECURITY_FS_USE_NONE		5 /* no labeling support */
+#define SECURITY_FS_USE_MNTPOINT	6 /* use mountpoint labeling */
+
 int security_fs_use(const char *fstype, unsigned int *behavior,
 	u32 *sid);
 





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

* Re: [PATCH] (3/3) SELinux context mount support - SELinux changes.
  2004-02-04 15:33 ` [PATCH] (3/3) SELinux context mount support - SELinux changes James Morris
@ 2004-02-05 10:17   ` Valdis.Kletnieks
  2004-02-05 10:40     ` Andrew Morton
  0 siblings, 1 reply; 4+ messages in thread
From: Valdis.Kletnieks @ 2004-02-05 10:17 UTC (permalink / raw)
  To: James Morris
  Cc: Andrew Morton, Alexander Viro, Stephen Smalley, linux-kernel,
	selinux, Chris Wright

[-- Attachment #1: Type: text/plain, Size: 1084 bytes --]

On Wed, 04 Feb 2004 10:33:12 EST, James Morris said:
> This patch implements context mount support within SELinux.
> 
> Three new mount options are provided:

<30 lines of summary information elided>

> Filesystems with binary mount option data (e.g. NFS, SMBFS, AFS, Coda) 
> need to be handled as special cases: only NFS is supprted at this stage 
> per the previous patch.

First I kept these patches around.

Then I saw that Andrew picked them up for 2.6.2-mm1, so I didn't need
to keep them.

Then I saw I had to either keep them, extract the summary info and keep that,
hope that I could find it while searching the LKML archives when I need it,
reverse engineer the code (how many times would I end up reading the code
if I got stuck by the relabelfrom/relabelto stuff?), or otherwise get lucky.

This isn't the first time that we've had patches go by with nice explanitory
text that doesn't make it into the kernel tree.  Does anybody have a good
idea on what we can/should do about these?  Even just dropping them into
one big Documentation/hints file might be good enough.


[-- Attachment #2: Type: application/pgp-signature, Size: 226 bytes --]

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

* Re: [PATCH] (3/3) SELinux context mount support - SELinux changes.
  2004-02-05 10:17   ` Valdis.Kletnieks
@ 2004-02-05 10:40     ` Andrew Morton
  2004-02-05 11:19       ` Valdis.Kletnieks
  0 siblings, 1 reply; 4+ messages in thread
From: Andrew Morton @ 2004-02-05 10:40 UTC (permalink / raw)
  To: Valdis.Kletnieks; +Cc: jmorris, aviro, sds, linux-kernel, selinux, chrisw

Valdis.Kletnieks@vt.edu wrote:
>
> This isn't the first time that we've had patches go by with nice explanitory
>  text that doesn't make it into the kernel tree.  Does anybody have a good
>  idea on what we can/should do about these?  Even just dropping them into
>  one big Documentation/hints file might be good enough.
> 

All that text is lovingly shovelled into the changelogs.  They're damn hard
to get at via the bk web interface but with `bk revtool' it's a snap.  Go
to a line in a .c file, double-click on it, see the diffview and the full
changelog.


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

* Re: [PATCH] (3/3) SELinux context mount support - SELinux changes.
  2004-02-05 10:40     ` Andrew Morton
@ 2004-02-05 11:19       ` Valdis.Kletnieks
  0 siblings, 0 replies; 4+ messages in thread
From: Valdis.Kletnieks @ 2004-02-05 11:19 UTC (permalink / raw)
  To: Andrew Morton; +Cc: jmorris, aviro, sds, linux-kernel, selinux, chrisw

[-- Attachment #1: Type: text/plain, Size: 556 bytes --]

On Thu, 05 Feb 2004 02:40:16 PST, Andrew Morton said:

> All that text is lovingly shovelled into the changelogs.  They're damn hard
> to get at via the bk web interface but with `bk revtool' it's a snap.  Go
> to a line in a .c file, double-click on it, see the diffview and the full
> changelog.

Wow.. So you go to line 300 or so of drivers/block/as-iosched.c and
a doubleclick pulls up Documentation/as-iosched.txt? Coooool ;)

% which bk
/usr/bin/which: no bk in (/home/valdis/bin:/usr/local/bin:/usr/bin/X11:/bin:/usr/bin:/usr/sbin:/sbin)

Damn. :)


[-- Attachment #2: Type: application/pgp-signature, Size: 226 bytes --]

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

end of thread, other threads:[~2004-02-05 14:44 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <Xine.LNX.4.44.0402040949010.4796@thoron.boston.redhat.com>
2004-02-04 15:33 ` [PATCH] (3/3) SELinux context mount support - SELinux changes James Morris
2004-02-05 10:17   ` Valdis.Kletnieks
2004-02-05 10:40     ` Andrew Morton
2004-02-05 11:19       ` Valdis.Kletnieks

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®