Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c312feb2 authored by Eric Paris's avatar Eric Paris Committed by Linus Torvalds
Browse files

[PATCH] SELinux: decouple fscontext/context mount options



Remove the conflict between fscontext and context mount options.  If
context= is specified without fscontext it will operate just as before, if
both are specified we will use mount point labeling and all inodes will get
the label specified by context=.  The superblock will be labeled with the
label of fscontext=, thus affecting operations which check the superblock
security context, such as associate permissions.

Signed-off-by: default avatarEric Paris <eparis@parisplace.org>
Acked-by: default avatarStephen Smalley <sds@tycho.nsa.gov>
Signed-off-by: default avatarJames Morris <jmorris@namei.org>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 2ed6e34f
Loading
Loading
Loading
Loading
+54 −15
Original line number Diff line number Diff line
@@ -246,6 +246,7 @@ static int superblock_alloc_security(struct super_block *sb)
	sbsec->sb = sb;
	sbsec->sid = SECINITSID_UNLABELED;
	sbsec->def_sid = SECINITSID_FILE;
	sbsec->mntpoint_sid = SECINITSID_UNLABELED;
	sb->s_security = sbsec;

	return 0;
@@ -329,9 +330,26 @@ static match_table_t tokens = {

#define SEL_MOUNT_FAIL_MSG "SELinux:  duplicate or incompatible mount options\n"

static int may_context_mount_sb_relabel(u32 sid,
			struct superblock_security_struct *sbsec,
			struct task_security_struct *tsec)
{
	int rc;

	rc = avc_has_perm(tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM,
			  FILESYSTEM__RELABELFROM, NULL);
	if (rc)
		return rc;

	rc = avc_has_perm(tsec->sid, sid, SECCLASS_FILESYSTEM,
			  FILESYSTEM__RELABELTO, NULL);
	return rc;
}

static int try_context_mount(struct super_block *sb, void *data)
{
	char *context = NULL, *defcontext = NULL;
	char *fscontext = NULL;
	const char *name;
	u32 sid;
	int alloc = 0, rc = 0, seen = 0;
@@ -374,7 +392,7 @@ static int try_context_mount(struct super_block *sb, void *data)

			switch (token) {
			case Opt_context:
				if (seen) {
				if (seen & (Opt_context|Opt_defcontext)) {
					rc = -EINVAL;
					printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
					goto out_free;
@@ -390,13 +408,13 @@ static int try_context_mount(struct super_block *sb, void *data)
				break;

			case Opt_fscontext:
				if (seen & (Opt_context|Opt_fscontext)) {
				if (seen & Opt_fscontext) {
					rc = -EINVAL;
					printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
					goto out_free;
				}
				context = match_strdup(&args[0]);
				if (!context) {
				fscontext = match_strdup(&args[0]);
				if (!fscontext) {
					rc = -ENOMEM;
					goto out_free;
				}
@@ -441,28 +459,45 @@ static int try_context_mount(struct super_block *sb, void *data)
	if (!seen)
		goto out;

	if (context) {
		rc = security_context_to_sid(context, strlen(context), &sid);
	/* sets the context of the superblock for the fs being mounted. */
	if (fscontext) {
		rc = security_context_to_sid(fscontext, strlen(fscontext), &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);
			       fscontext, sb->s_id, name, rc);
			goto out_free;
		}

		rc = avc_has_perm(tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM,
		                  FILESYSTEM__RELABELFROM, NULL);
		rc = may_context_mount_sb_relabel(sid, sbsec, tsec);
		if (rc)
			goto out_free;

		rc = avc_has_perm(tsec->sid, sid, SECCLASS_FILESYSTEM,
		                  FILESYSTEM__RELABELTO, NULL);
		sbsec->sid = sid;
	}

	/*
	 * Switch to using mount point labeling behavior.
	 * sets the label used on all file below the mountpoint, and will set
	 * the superblock context if not already set.
	 */
	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 = may_context_mount_sb_relabel(sid, sbsec, tsec);
		if (rc)
			goto out_free;

		if (!fscontext)
			sbsec->sid = sid;
		sbsec->mntpoint_sid = sid;

		if (seen & Opt_context)
		sbsec->behavior = SECURITY_FS_USE_MNTPOINT;
	}

@@ -495,6 +530,7 @@ static int try_context_mount(struct super_block *sb, void *data)
	if (alloc) {
		kfree(context);
		kfree(defcontext);
		kfree(fscontext);
	}
out:
	return rc;
@@ -876,8 +912,11 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent
			goto out;
		isec->sid = sid;
		break;
	case SECURITY_FS_USE_MNTPOINT:
		isec->sid = sbsec->mntpoint_sid;
		break;
	default:
		/* Default to the fs SID. */
		/* Default to the fs superblock SID. */
		isec->sid = sbsec->sid;

		if (sbsec->proc) {
+2 −1
Original line number Diff line number Diff line
@@ -57,8 +57,9 @@ struct file_security_struct {
struct superblock_security_struct {
	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 sid;			/* SID of file system superblock */
	u32 def_sid;			/* default SID for labeling */
	u32 mntpoint_sid;		/* SECURITY_FS_USE_MNTPOINT context for files */
	unsigned int behavior;          /* labeling behavior */
	unsigned char initialized;      /* initialization flag */
	unsigned char proc;             /* proc fs */