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

Commit 6f799c97 authored by James Morris's avatar James Morris
Browse files

Merge branch 'master' of git://git.infradead.org/users/pcmoore/selinux into ra-next

parents eb8948a0 42d64e1a
Loading
Loading
Loading
Loading
+18 −8
Original line number Diff line number Diff line
@@ -1052,17 +1052,25 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
 * @xfrm_policy_delete_security:
 *	@ctx contains the xfrm_sec_ctx.
 *	Authorize deletion of xp->security.
 * @xfrm_state_alloc_security:
 * @xfrm_state_alloc:
 *	@x contains the xfrm_state being added to the Security Association
 *	Database by the XFRM system.
 *	@sec_ctx contains the security context information being provided by
 *	the user-level SA generation program (e.g., setkey or racoon).
 *	@secid contains the secid from which to take the mls portion of the context.
 *	Allocate a security structure to the x->security field; the security
 *	field is initialized to NULL when the xfrm_state is allocated. Set the
 *	context to correspond to either sec_ctx or polsec, with the mls portion
 *	taken from secid in the latter case.
 *	Return 0 if operation was successful (memory to allocate, legal context).
 *	context to correspond to sec_ctx. Return 0 if operation was successful
 *	(memory to allocate, legal context).
 * @xfrm_state_alloc_acquire:
 *	@x contains the xfrm_state being added to the Security Association
 *	Database by the XFRM system.
 *	@polsec contains the policy's security context.
 *	@secid contains the secid from which to take the mls portion of the
 *	context.
 *	Allocate a security structure to the x->security field; the security
 *	field is initialized to NULL when the xfrm_state is allocated. Set the
 *	context to correspond to secid. Return 0 if operation was successful
 *	(memory to allocate, legal context).
 * @xfrm_state_free_security:
 *	@x contains the xfrm_state.
 *	Deallocate x->security.
@@ -1679,8 +1687,10 @@ struct security_operations {
	int (*xfrm_policy_clone_security) (struct xfrm_sec_ctx *old_ctx, struct xfrm_sec_ctx **new_ctx);
	void (*xfrm_policy_free_security) (struct xfrm_sec_ctx *ctx);
	int (*xfrm_policy_delete_security) (struct xfrm_sec_ctx *ctx);
	int (*xfrm_state_alloc_security) (struct xfrm_state *x,
		struct xfrm_user_sec_ctx *sec_ctx,
	int (*xfrm_state_alloc) (struct xfrm_state *x,
				 struct xfrm_user_sec_ctx *sec_ctx);
	int (*xfrm_state_alloc_acquire) (struct xfrm_state *x,
					 struct xfrm_sec_ctx *polsec,
					 u32 secid);
	void (*xfrm_state_free_security) (struct xfrm_state *x);
	int (*xfrm_state_delete_security) (struct xfrm_state *x);
+11 −4
Original line number Diff line number Diff line
@@ -777,8 +777,14 @@ static int cap_xfrm_policy_delete_security(struct xfrm_sec_ctx *ctx)
	return 0;
}

static int cap_xfrm_state_alloc_security(struct xfrm_state *x,
					 struct xfrm_user_sec_ctx *sec_ctx,
static int cap_xfrm_state_alloc(struct xfrm_state *x,
				struct xfrm_user_sec_ctx *sec_ctx)
{
	return 0;
}

static int cap_xfrm_state_alloc_acquire(struct xfrm_state *x,
					struct xfrm_sec_ctx *polsec,
					u32 secid)
{
	return 0;
@@ -1101,7 +1107,8 @@ void __init security_fixup_ops(struct security_operations *ops)
	set_to_cap_if_null(ops, xfrm_policy_clone_security);
	set_to_cap_if_null(ops, xfrm_policy_free_security);
	set_to_cap_if_null(ops, xfrm_policy_delete_security);
	set_to_cap_if_null(ops, xfrm_state_alloc_security);
	set_to_cap_if_null(ops, xfrm_state_alloc);
	set_to_cap_if_null(ops, xfrm_state_alloc_acquire);
	set_to_cap_if_null(ops, xfrm_state_free_security);
	set_to_cap_if_null(ops, xfrm_state_delete_security);
	set_to_cap_if_null(ops, xfrm_policy_lookup);
+4 −9
Original line number Diff line number Diff line
@@ -1340,22 +1340,17 @@ int security_xfrm_policy_delete(struct xfrm_sec_ctx *ctx)
	return security_ops->xfrm_policy_delete_security(ctx);
}

int security_xfrm_state_alloc(struct xfrm_state *x, struct xfrm_user_sec_ctx *sec_ctx)
int security_xfrm_state_alloc(struct xfrm_state *x,
			      struct xfrm_user_sec_ctx *sec_ctx)
{
	return security_ops->xfrm_state_alloc_security(x, sec_ctx, 0);
	return security_ops->xfrm_state_alloc(x, sec_ctx);
}
EXPORT_SYMBOL(security_xfrm_state_alloc);

int security_xfrm_state_alloc_acquire(struct xfrm_state *x,
				      struct xfrm_sec_ctx *polsec, u32 secid)
{
	if (!polsec)
		return 0;
	/*
	 * We want the context to be taken from secid which is usually
	 * from the sock.
	 */
	return security_ops->xfrm_state_alloc_security(x, NULL, secid);
	return security_ops->xfrm_state_alloc_acquire(x, polsec, secid);
}

int security_xfrm_state_delete(struct xfrm_state *x)
+94 −52
Original line number Diff line number Diff line
@@ -95,7 +95,9 @@
#include "audit.h"
#include "avc_ss.h"

#define NUM_SEL_MNT_OPTS 5
#define SB_TYPE_FMT "%s%s%s"
#define SB_SUBTYPE(sb) (sb->s_subtype && sb->s_subtype[0])
#define SB_TYPE_ARGS(sb) sb->s_type->name, SB_SUBTYPE(sb) ? "." : "", SB_SUBTYPE(sb) ? sb->s_subtype : ""

extern struct security_operations *security_ops;

@@ -139,12 +141,28 @@ static struct kmem_cache *sel_inode_cache;
 * This function checks the SECMARK reference counter to see if any SECMARK
 * targets are currently configured, if the reference counter is greater than
 * zero SECMARK is considered to be enabled.  Returns true (1) if SECMARK is
 * enabled, false (0) if SECMARK is disabled.
 * enabled, false (0) if SECMARK is disabled.  If the always_check_network
 * policy capability is enabled, SECMARK is always considered enabled.
 *
 */
static int selinux_secmark_enabled(void)
{
	return (atomic_read(&selinux_secmark_refcount) > 0);
	return (selinux_policycap_alwaysnetwork || atomic_read(&selinux_secmark_refcount));
}

/**
 * selinux_peerlbl_enabled - Check to see if peer labeling is currently enabled
 *
 * Description:
 * This function checks if NetLabel or labeled IPSEC is enabled.  Returns true
 * (1) if any are enabled or false (0) if neither are enabled.  If the
 * always_check_network policy capability is enabled, peer labeling
 * is always considered enabled.
 *
 */
static int selinux_peerlbl_enabled(void)
{
	return (selinux_policycap_alwaysnetwork || netlbl_enabled() || selinux_xfrm_enabled());
}

/*
@@ -309,8 +327,11 @@ enum {
	Opt_defcontext = 3,
	Opt_rootcontext = 4,
	Opt_labelsupport = 5,
	Opt_nextmntopt = 6,
};

#define NUM_SEL_MNT_OPTS	(Opt_nextmntopt - 1)

static const match_table_t tokens = {
	{Opt_context, CONTEXT_STR "%s"},
	{Opt_fscontext, FSCONTEXT_STR "%s"},
@@ -355,6 +376,29 @@ static int may_context_mount_inode_relabel(u32 sid,
	return rc;
}

static int selinux_is_sblabel_mnt(struct super_block *sb)
{
	struct superblock_security_struct *sbsec = sb->s_security;

	if (sbsec->behavior == SECURITY_FS_USE_XATTR ||
	    sbsec->behavior == SECURITY_FS_USE_TRANS ||
	    sbsec->behavior == SECURITY_FS_USE_TASK)
		return 1;

	/* Special handling for sysfs. Is genfs but also has setxattr handler*/
	if (strncmp(sb->s_type->name, "sysfs", sizeof("sysfs")) == 0)
		return 1;

	/*
	 * Special handling for rootfs. Is genfs but supports
	 * setting SELinux context on in-core inodes.
	 */
	if (strncmp(sb->s_type->name, "rootfs", sizeof("rootfs")) == 0)
		return 1;

	return 0;
}

static int sb_finish_set_opts(struct super_block *sb)
{
	struct superblock_security_struct *sbsec = sb->s_security;
@@ -369,8 +413,8 @@ static int sb_finish_set_opts(struct super_block *sb)
		   the first boot of the SELinux kernel before we have
		   assigned xattr values to the filesystem. */
		if (!root_inode->i_op->getxattr) {
			printk(KERN_WARNING "SELinux: (dev %s, type %s) has no "
			       "xattr support\n", sb->s_id, sb->s_type->name);
			printk(KERN_WARNING "SELinux: (dev %s, type "SB_TYPE_FMT") has no "
			       "xattr support\n", sb->s_id, SB_TYPE_ARGS(sb));
			rc = -EOPNOTSUPP;
			goto out;
		}
@@ -378,35 +422,27 @@ static int sb_finish_set_opts(struct super_block *sb)
		if (rc < 0 && rc != -ENODATA) {
			if (rc == -EOPNOTSUPP)
				printk(KERN_WARNING "SELinux: (dev %s, type "
				       "%s) has no security xattr handler\n",
				       sb->s_id, sb->s_type->name);
				       SB_TYPE_FMT") has no security xattr handler\n",
				       sb->s_id, SB_TYPE_ARGS(sb));
			else
				printk(KERN_WARNING "SELinux: (dev %s, type "
				       "%s) getxattr errno %d\n", sb->s_id,
				       sb->s_type->name, -rc);
				       SB_TYPE_FMT") getxattr errno %d\n", sb->s_id,
				       SB_TYPE_ARGS(sb), -rc);
			goto out;
		}
	}

	sbsec->flags |= (SE_SBINITIALIZED | SE_SBLABELSUPP);

	if (sbsec->behavior > ARRAY_SIZE(labeling_behaviors))
		printk(KERN_ERR "SELinux: initialized (dev %s, type %s), unknown behavior\n",
		       sb->s_id, sb->s_type->name);
		printk(KERN_ERR "SELinux: initialized (dev %s, type "SB_TYPE_FMT"), unknown behavior\n",
		       sb->s_id, SB_TYPE_ARGS(sb));
	else
		printk(KERN_DEBUG "SELinux: initialized (dev %s, type %s), %s\n",
		       sb->s_id, sb->s_type->name,
		printk(KERN_DEBUG "SELinux: initialized (dev %s, type "SB_TYPE_FMT"), %s\n",
		       sb->s_id, SB_TYPE_ARGS(sb),
		       labeling_behaviors[sbsec->behavior-1]);

	if (sbsec->behavior == SECURITY_FS_USE_GENFS ||
	    sbsec->behavior == SECURITY_FS_USE_MNTPOINT ||
	    sbsec->behavior == SECURITY_FS_USE_NONE ||
	    sbsec->behavior > ARRAY_SIZE(labeling_behaviors))
		sbsec->flags &= ~SE_SBLABELSUPP;

	/* Special handling for sysfs. Is genfs but also has setxattr handler*/
	if (strncmp(sb->s_type->name, "sysfs", sizeof("sysfs")) == 0)
		sbsec->flags |= SE_SBLABELSUPP;
	sbsec->flags |= SE_SBINITIALIZED;
	if (selinux_is_sblabel_mnt(sb))
		sbsec->flags |= SBLABEL_MNT;

	/* Initialize the root inode. */
	rc = inode_doinit_with_dentry(root_inode, root);
@@ -460,15 +496,18 @@ static int selinux_get_mnt_opts(const struct super_block *sb,
	if (!ss_initialized)
		return -EINVAL;

	/* make sure we always check enough bits to cover the mask */
	BUILD_BUG_ON(SE_MNTMASK >= (1 << NUM_SEL_MNT_OPTS));

	tmp = sbsec->flags & SE_MNTMASK;
	/* count the number of mount options for this sb */
	for (i = 0; i < 8; i++) {
	for (i = 0; i < NUM_SEL_MNT_OPTS; i++) {
		if (tmp & 0x01)
			opts->num_mnt_opts++;
		tmp >>= 1;
	}
	/* Check if the Label support flag is set */
	if (sbsec->flags & SE_SBLABELSUPP)
	if (sbsec->flags & SBLABEL_MNT)
		opts->num_mnt_opts++;

	opts->mnt_opts = kcalloc(opts->num_mnt_opts, sizeof(char *), GFP_ATOMIC);
@@ -515,9 +554,9 @@ static int selinux_get_mnt_opts(const struct super_block *sb,
		opts->mnt_opts[i] = context;
		opts->mnt_opts_flags[i++] = ROOTCONTEXT_MNT;
	}
	if (sbsec->flags & SE_SBLABELSUPP) {
	if (sbsec->flags & SBLABEL_MNT) {
		opts->mnt_opts[i] = NULL;
		opts->mnt_opts_flags[i++] = SE_SBLABELSUPP;
		opts->mnt_opts_flags[i++] = SBLABEL_MNT;
	}

	BUG_ON(i != opts->num_mnt_opts);
@@ -561,7 +600,6 @@ static int selinux_set_mnt_opts(struct super_block *sb,
	const struct cred *cred = current_cred();
	int rc = 0, i;
	struct superblock_security_struct *sbsec = sb->s_security;
	const char *name = sb->s_type->name;
	struct inode *inode = sbsec->sb->s_root->d_inode;
	struct inode_security_struct *root_isec = inode->i_security;
	u32 fscontext_sid = 0, context_sid = 0, rootcontext_sid = 0;
@@ -614,14 +652,14 @@ static int selinux_set_mnt_opts(struct super_block *sb,
	for (i = 0; i < num_opts; i++) {
		u32 sid;

		if (flags[i] == SE_SBLABELSUPP)
		if (flags[i] == SBLABEL_MNT)
			continue;
		rc = security_context_to_sid(mount_options[i],
					     strlen(mount_options[i]), &sid);
		if (rc) {
			printk(KERN_WARNING "SELinux: security_context_to_sid"
			       "(%s) failed for (dev %s, type %s) errno=%d\n",
			       mount_options[i], sb->s_id, name, rc);
			       "(%s) failed for (dev %s, type "SB_TYPE_FMT") errno=%d\n",
			       mount_options[i], sb->s_id, SB_TYPE_ARGS(sb), rc);
			goto out;
		}
		switch (flags[i]) {
@@ -685,9 +723,7 @@ static int selinux_set_mnt_opts(struct super_block *sb,
		 * Determine the labeling behavior to use for this
		 * filesystem type.
		 */
		rc = security_fs_use((sbsec->flags & SE_SBPROC) ?
					"proc" : sb->s_type->name,
					&sbsec->behavior, &sbsec->sid);
		rc = security_fs_use(sb);
		if (rc) {
			printk(KERN_WARNING
				"%s: security_fs_use(%s) returned %d\n",
@@ -770,7 +806,8 @@ static int selinux_set_mnt_opts(struct super_block *sb,
out_double_mount:
	rc = -EINVAL;
	printk(KERN_WARNING "SELinux: mount invalid.  Same superblock, different "
	       "security settings for (dev %s, type %s)\n", sb->s_id, name);
	       "security settings for (dev %s, type "SB_TYPE_FMT")\n", sb->s_id,
	       SB_TYPE_ARGS(sb));
	goto out;
}

@@ -1037,7 +1074,7 @@ static void selinux_write_opts(struct seq_file *m,
		case DEFCONTEXT_MNT:
			prefix = DEFCONTEXT_STR;
			break;
		case SE_SBLABELSUPP:
		case SBLABEL_MNT:
			seq_putc(m, ',');
			seq_puts(m, LABELSUPP_STR);
			continue;
@@ -1650,7 +1687,7 @@ static int may_create(struct inode *dir,
	if (rc)
		return rc;

	if (!newsid || !(sbsec->flags & SE_SBLABELSUPP)) {
	if (!newsid || !(sbsec->flags & SBLABEL_MNT)) {
		rc = security_transition_sid(sid, dsec->sid, tclass,
					     &dentry->d_name, &newsid);
		if (rc)
@@ -2438,14 +2475,14 @@ static int selinux_sb_remount(struct super_block *sb, void *data)
		u32 sid;
		size_t len;

		if (flags[i] == SE_SBLABELSUPP)
		if (flags[i] == SBLABEL_MNT)
			continue;
		len = strlen(mount_options[i]);
		rc = security_context_to_sid(mount_options[i], len, &sid);
		if (rc) {
			printk(KERN_WARNING "SELinux: security_context_to_sid"
			       "(%s) failed for (dev %s, type %s) errno=%d\n",
			       mount_options[i], sb->s_id, sb->s_type->name, rc);
			       "(%s) failed for (dev %s, type "SB_TYPE_FMT") errno=%d\n",
			       mount_options[i], sb->s_id, SB_TYPE_ARGS(sb), rc);
			goto out_free_opts;
		}
		rc = -EINVAL;
@@ -2483,8 +2520,8 @@ static int selinux_sb_remount(struct super_block *sb, void *data)
	return rc;
out_bad_option:
	printk(KERN_WARNING "SELinux: unable to change security options "
	       "during remount (dev %s, type=%s)\n", sb->s_id,
	       sb->s_type->name);
	       "during remount (dev %s, type "SB_TYPE_FMT")\n", sb->s_id,
	       SB_TYPE_ARGS(sb));
	goto out_free_opts;
}

@@ -2607,7 +2644,7 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
	if ((sbsec->flags & SE_SBINITIALIZED) &&
	    (sbsec->behavior == SECURITY_FS_USE_MNTPOINT))
		newsid = sbsec->mntpoint_sid;
	else if (!newsid || !(sbsec->flags & SE_SBLABELSUPP)) {
	else if (!newsid || !(sbsec->flags & SBLABEL_MNT)) {
		rc = security_transition_sid(sid, dsec->sid,
					     inode_mode_to_security_class(inode->i_mode),
					     qstr, &newsid);
@@ -2629,7 +2666,7 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
		isec->initialized = 1;
	}

	if (!ss_initialized || !(sbsec->flags & SE_SBLABELSUPP))
	if (!ss_initialized || !(sbsec->flags & SBLABEL_MNT))
		return -EOPNOTSUPP;

	if (name)
@@ -2831,7 +2868,7 @@ static int selinux_inode_setxattr(struct dentry *dentry, const char *name,
		return selinux_inode_setotherxattr(dentry, name);

	sbsec = inode->i_sb->s_security;
	if (!(sbsec->flags & SE_SBLABELSUPP))
	if (!(sbsec->flags & SBLABEL_MNT))
		return -EOPNOTSUPP;

	if (!inode_owner_or_capable(inode))
@@ -3792,8 +3829,12 @@ static int selinux_skb_peerlbl_sid(struct sk_buff *skb, u16 family, u32 *sid)
	u32 nlbl_sid;
	u32 nlbl_type;

	selinux_skb_xfrm_sid(skb, &xfrm_sid);
	selinux_netlbl_skbuff_getsid(skb, family, &nlbl_type, &nlbl_sid);
	err = selinux_skb_xfrm_sid(skb, &xfrm_sid);
	if (unlikely(err))
		return -EACCES;
	err = selinux_netlbl_skbuff_getsid(skb, family, &nlbl_type, &nlbl_sid);
	if (unlikely(err))
		return -EACCES;

	err = security_net_peersid_resolve(nlbl_sid, nlbl_type, xfrm_sid, sid);
	if (unlikely(err)) {
@@ -4247,7 +4288,7 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
		return selinux_sock_rcv_skb_compat(sk, skb, family);

	secmark_active = selinux_secmark_enabled();
	peerlbl_active = netlbl_enabled() || selinux_xfrm_enabled();
	peerlbl_active = selinux_peerlbl_enabled();
	if (!secmark_active && !peerlbl_active)
		return 0;

@@ -4629,7 +4670,7 @@ static unsigned int selinux_ip_forward(struct sk_buff *skb, int ifindex,

	secmark_active = selinux_secmark_enabled();
	netlbl_active = netlbl_enabled();
	peerlbl_active = netlbl_active || selinux_xfrm_enabled();
	peerlbl_active = selinux_peerlbl_enabled();
	if (!secmark_active && !peerlbl_active)
		return NF_ACCEPT;

@@ -4781,7 +4822,7 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex,
		return NF_ACCEPT;
#endif
	secmark_active = selinux_secmark_enabled();
	peerlbl_active = netlbl_enabled() || selinux_xfrm_enabled();
	peerlbl_active = selinux_peerlbl_enabled();
	if (!secmark_active && !peerlbl_active)
		return NF_ACCEPT;

@@ -5785,7 +5826,8 @@ static struct security_operations selinux_ops = {
	.xfrm_policy_clone_security =	selinux_xfrm_policy_clone,
	.xfrm_policy_free_security =	selinux_xfrm_policy_free,
	.xfrm_policy_delete_security =	selinux_xfrm_policy_delete,
	.xfrm_state_alloc_security =	selinux_xfrm_state_alloc,
	.xfrm_state_alloc =		selinux_xfrm_state_alloc,
	.xfrm_state_alloc_acquire =	selinux_xfrm_state_alloc_acquire,
	.xfrm_state_free_security =	selinux_xfrm_state_free,
	.xfrm_state_delete_security =	selinux_xfrm_state_delete,
	.xfrm_policy_lookup =		selinux_xfrm_policy_lookup,
+2 −2
Original line number Diff line number Diff line
@@ -58,8 +58,8 @@ struct superblock_security_struct {
	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 flags;		/* which mount options were specified */
	unsigned short behavior;	/* labeling behavior */
	unsigned short flags;		/* which mount options were specified */
	struct mutex lock;
	struct list_head isec_head;
	spinlock_t isec_lock;
Loading