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

Commit 710584b9 authored by James Morris's avatar James Morris
Browse files

Merge branch 'smack-for-4.11' of git://github.com/cschaufler/smack-next into next

parents c659af78 83a1e53f
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -114,6 +114,7 @@ struct inode_smack {
	struct smack_known	*smk_mmap;	/* label of the mmap domain */
	struct mutex		smk_lock;	/* initialization lock */
	int			smk_flags;	/* smack inode flags */
	struct rcu_head         smk_rcu;	/* for freeing inode_smack */
};

struct task_smack {
@@ -173,6 +174,8 @@ struct smk_port_label {
	unsigned short		smk_port;	/* the port number */
	struct smack_known	*smk_in;	/* inbound label */
	struct smack_known	*smk_out;	/* outgoing label */
	short			smk_sock_type;	/* Socket type */
	short			smk_can_reuse;
};
#endif /* SMACK_IPV6_PORT_LABELING */

+87 −27
Original line number Diff line number Diff line
@@ -52,6 +52,7 @@
#define SMK_SENDING	2

#ifdef SMACK_IPV6_PORT_LABELING
DEFINE_MUTEX(smack_ipv6_lock);
static LIST_HEAD(smk_ipv6_port_list);
#endif
static struct kmem_cache *smack_inode_cache;
@@ -347,8 +348,6 @@ static int smk_copy_rules(struct list_head *nhead, struct list_head *ohead,
	struct smack_rule *orp;
	int rc = 0;

	INIT_LIST_HEAD(nhead);

	list_for_each_entry_rcu(orp, ohead, list) {
		nrp = kzalloc(sizeof(struct smack_rule), gfp);
		if (nrp == NULL) {
@@ -375,8 +374,6 @@ static int smk_copy_relabel(struct list_head *nhead, struct list_head *ohead,
	struct smack_known_list_elem *nklep;
	struct smack_known_list_elem *oklep;

	INIT_LIST_HEAD(nhead);

	list_for_each_entry(oklep, ohead, list) {
		nklep = kzalloc(sizeof(struct smack_known_list_elem), gfp);
		if (nklep == NULL) {
@@ -1009,15 +1006,39 @@ static int smack_inode_alloc_security(struct inode *inode)
}

/**
 * smack_inode_free_security - free an inode blob
 * smack_inode_free_rcu - Free inode_smack blob from cache
 * @head: the rcu_head for getting inode_smack pointer
 *
 *  Call back function called from call_rcu() to free
 *  the i_security blob pointer in inode
 */
static void smack_inode_free_rcu(struct rcu_head *head)
{
	struct inode_smack *issp;

	issp = container_of(head, struct inode_smack, smk_rcu);
	kmem_cache_free(smack_inode_cache, issp);
}

/**
 * smack_inode_free_security - free an inode blob using call_rcu()
 * @inode: the inode with a blob
 *
 * Clears the blob pointer in inode
 * Clears the blob pointer in inode using RCU
 */
static void smack_inode_free_security(struct inode *inode)
{
	kmem_cache_free(smack_inode_cache, inode->i_security);
	inode->i_security = NULL;
	struct inode_smack *issp = inode->i_security;

	/*
	 * The inode may still be referenced in a path walk and
	 * a call to smack_inode_permission() can be made
	 * after smack_inode_free_security() is called.
	 * To avoid race condition free the i_security via RCU
	 * and leave the current inode->i_security pointer intact.
	 * The inode will be freed after the RCU grace period too.
	 */
	call_rcu(&issp->smk_rcu, smack_inode_free_rcu);
}

/**
@@ -1626,6 +1647,9 @@ static int smack_file_ioctl(struct file *file, unsigned int cmd,
	struct smk_audit_info ad;
	struct inode *inode = file_inode(file);

	if (unlikely(IS_PRIVATE(inode)))
		return 0;

	smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH);
	smk_ad_setfield_u_fs_path(&ad, file->f_path);

@@ -1655,6 +1679,9 @@ static int smack_file_lock(struct file *file, unsigned int cmd)
	int rc;
	struct inode *inode = file_inode(file);

	if (unlikely(IS_PRIVATE(inode)))
		return 0;

	smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH);
	smk_ad_setfield_u_fs_path(&ad, file->f_path);
	rc = smk_curacc(smk_of_inode(inode), MAY_LOCK, &ad);
@@ -1681,6 +1708,9 @@ static int smack_file_fcntl(struct file *file, unsigned int cmd,
	int rc = 0;
	struct inode *inode = file_inode(file);

	if (unlikely(IS_PRIVATE(inode)))
		return 0;

	switch (cmd) {
	case F_GETLK:
		break;
@@ -1734,6 +1764,9 @@ static int smack_mmap_file(struct file *file,
	if (file == NULL)
		return 0;

	if (unlikely(IS_PRIVATE(file_inode(file))))
		return 0;

	isp = file_inode(file)->i_security;
	if (isp->smk_mmap == NULL)
		return 0;
@@ -1934,12 +1967,9 @@ static int smack_file_open(struct file *file, const struct cred *cred)
	struct smk_audit_info ad;
	int rc;

	if (smack_privileged(CAP_MAC_OVERRIDE))
		return 0;

	smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH);
	smk_ad_setfield_u_fs_path(&ad, file->f_path);
	rc = smk_access(tsp->smk_task, smk_of_inode(inode), MAY_READ, &ad);
	rc = smk_tskacc(tsp, smk_of_inode(inode), MAY_READ, &ad);
	rc = smk_bu_credfile(cred, file, MAY_READ, rc);

	return rc;
@@ -2353,6 +2383,20 @@ static int smack_sk_alloc_security(struct sock *sk, int family, gfp_t gfp_flags)
 */
static void smack_sk_free_security(struct sock *sk)
{
#ifdef SMACK_IPV6_PORT_LABELING
	struct smk_port_label *spp;

	if (sk->sk_family == PF_INET6) {
		rcu_read_lock();
		list_for_each_entry_rcu(spp, &smk_ipv6_port_list, list) {
			if (spp->smk_sock != sk)
				continue;
			spp->smk_can_reuse = 1;
			break;
		}
		rcu_read_unlock();
	}
#endif
	kfree(sk->sk_security);
}

@@ -2603,17 +2647,20 @@ static void smk_ipv6_port_label(struct socket *sock, struct sockaddr *address)
		 * on the bound socket. Take the changes to the port
		 * as well.
		 */
		list_for_each_entry(spp, &smk_ipv6_port_list, list) {
		rcu_read_lock();
		list_for_each_entry_rcu(spp, &smk_ipv6_port_list, list) {
			if (sk != spp->smk_sock)
				continue;
			spp->smk_in = ssp->smk_in;
			spp->smk_out = ssp->smk_out;
			rcu_read_unlock();
			return;
		}
		/*
		 * A NULL address is only used for updating existing
		 * bound entries. If there isn't one, it's OK.
		 */
		rcu_read_unlock();
		return;
	}

@@ -2629,16 +2676,23 @@ static void smk_ipv6_port_label(struct socket *sock, struct sockaddr *address)
	 * Look for an existing port list entry.
	 * This is an indication that a port is getting reused.
	 */
	list_for_each_entry(spp, &smk_ipv6_port_list, list) {
		if (spp->smk_port != port)
	rcu_read_lock();
	list_for_each_entry_rcu(spp, &smk_ipv6_port_list, list) {
		if (spp->smk_port != port || spp->smk_sock_type != sock->type)
			continue;
		if (spp->smk_can_reuse != 1) {
			rcu_read_unlock();
			return;
		}
		spp->smk_port = port;
		spp->smk_sock = sk;
		spp->smk_in = ssp->smk_in;
		spp->smk_out = ssp->smk_out;
		spp->smk_can_reuse = 0;
		rcu_read_unlock();
		return;
	}

	rcu_read_unlock();
	/*
	 * A new port entry is required.
	 */
@@ -2650,8 +2704,12 @@ static void smk_ipv6_port_label(struct socket *sock, struct sockaddr *address)
	spp->smk_sock = sk;
	spp->smk_in = ssp->smk_in;
	spp->smk_out = ssp->smk_out;
	spp->smk_sock_type = sock->type;
	spp->smk_can_reuse = 0;

	list_add(&spp->list, &smk_ipv6_port_list);
	mutex_lock(&smack_ipv6_lock);
	list_add_rcu(&spp->list, &smk_ipv6_port_list);
	mutex_unlock(&smack_ipv6_lock);
	return;
}

@@ -2702,14 +2760,16 @@ static int smk_ipv6_port_check(struct sock *sk, struct sockaddr_in6 *address,
		return 0;

	port = ntohs(address->sin6_port);
	list_for_each_entry(spp, &smk_ipv6_port_list, list) {
		if (spp->smk_port != port)
	rcu_read_lock();
	list_for_each_entry_rcu(spp, &smk_ipv6_port_list, list) {
		if (spp->smk_port != port || spp->smk_sock_type != sk->sk_type)
			continue;
		object = spp->smk_in;
		if (act == SMK_CONNECTING)
			ssp->smk_packet = spp->smk_out;
		break;
	}
	rcu_read_unlock();

	return smk_ipv6_check(skp, object, address, act);
}
@@ -3438,6 +3498,13 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode)
		case PIPEFS_MAGIC:
			isp->smk_inode = smk_of_current();
			break;
		case SOCKFS_MAGIC:
			/*
			 * Socket access is controlled by the socket
			 * structures associated with the task involved.
			 */
			isp->smk_inode = &smack_known_star;
			break;
		default:
			isp->smk_inode = sbsp->smk_root;
			break;
@@ -3454,19 +3521,12 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode)
	 */
	switch (sbp->s_magic) {
	case SMACK_MAGIC:
	case PIPEFS_MAGIC:
	case SOCKFS_MAGIC:
	case CGROUP_SUPER_MAGIC:
		/*
		 * Casey says that it's a little embarrassing
		 * that the smack file system doesn't do
		 * extended attributes.
		 *
		 * Casey says pipes are easy (?)
		 *
		 * Socket access is controlled by the socket
		 * structures associated with the task involved.
		 *
		 * Cgroupfs is special
		 */
		final = &smack_known_star;
@@ -3849,7 +3909,7 @@ static struct smack_known *smack_from_secattr(struct netlbl_lsm_secattr *sap,
		 * ambient value.
		 */
		rcu_read_lock();
		list_for_each_entry(skp, &smack_known_list, list) {
		list_for_each_entry_rcu(skp, &smack_known_list, list) {
			if (sap->attr.mls.lvl != skp->smk_netlabel.attr.mls.lvl)
				continue;
			/*
+5 −0
Original line number Diff line number Diff line
@@ -67,6 +67,7 @@ enum smk_inos {
/*
 * List locks
 */
static DEFINE_MUTEX(smack_master_list_lock);
static DEFINE_MUTEX(smack_cipso_lock);
static DEFINE_MUTEX(smack_ambient_lock);
static DEFINE_MUTEX(smk_net4addr_lock);
@@ -262,12 +263,16 @@ static int smk_set_access(struct smack_parsed_rule *srp,
		 * it needs to get added for reporting.
		 */
		if (global) {
			mutex_unlock(rule_lock);
			smlp = kzalloc(sizeof(*smlp), GFP_KERNEL);
			if (smlp != NULL) {
				smlp->smk_rule = sp;
				mutex_lock(&smack_master_list_lock);
				list_add_rcu(&smlp->list, &smack_rule_list);
				mutex_unlock(&smack_master_list_lock);
			} else
				rc = -ENOMEM;
			return rc;
		}
	}