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

Commit 9d5a5f65 authored by James Morris's avatar James Morris
Browse files

Merge branch 'smack-for-3.20-rebased' of git://git.gitorious.org/smack-next/kernel into next

parents 743410a0 6d1cff2a
Loading
Loading
Loading
Loading
+12 −0
Original line number Original line Diff line number Diff line
@@ -28,3 +28,15 @@ config SECURITY_SMACK_BRINGUP
	  access rule set once the behavior is well understood.
	  access rule set once the behavior is well understood.
	  This is a superior mechanism to the oft abused
	  This is a superior mechanism to the oft abused
	  "permissive" mode of other systems.
	  "permissive" mode of other systems.
	  If you are unsure how to answer this question, answer N.

config SECURITY_SMACK_NETFILTER
	bool "Packet marking using secmarks for netfilter"
	depends on SECURITY_SMACK
	depends on NETWORK_SECMARK
	depends on NETFILTER
	default n
	help
	  This enables security marking of network packets using
	  Smack labels.
	  If you are unsure how to answer this question, answer N.
+1 −0
Original line number Original line Diff line number Diff line
@@ -5,3 +5,4 @@
obj-$(CONFIG_SECURITY_SMACK) := smack.o
obj-$(CONFIG_SECURITY_SMACK) := smack.o


smack-y := smack_lsm.o smack_access.o smackfs.o
smack-y := smack_lsm.o smack_access.o smackfs.o
smack-$(CONFIG_NETFILTER) += smack_netfilter.o
+11 −0
Original line number Original line Diff line number Diff line
@@ -248,6 +248,7 @@ struct smack_known *smk_find_entry(const char *);
/*
/*
 * Shared data.
 * Shared data.
 */
 */
extern int smack_enabled;
extern int smack_cipso_direct;
extern int smack_cipso_direct;
extern int smack_cipso_mapped;
extern int smack_cipso_mapped;
extern struct smack_known *smack_net_ambient;
extern struct smack_known *smack_net_ambient;
@@ -298,6 +299,16 @@ static inline struct smack_known *smk_of_task(const struct task_smack *tsp)
	return tsp->smk_task;
	return tsp->smk_task;
}
}


static inline struct smack_known *smk_of_task_struct(const struct task_struct *t)
{
	struct smack_known *skp;

	rcu_read_lock();
	skp = smk_of_task(__task_cred(t)->security);
	rcu_read_unlock();
	return skp;
}

/*
/*
 * Present a pointer to the forked smack label entry in an task blob.
 * Present a pointer to the forked smack label entry in an task blob.
 */
 */
+147 −52
Original line number Original line Diff line number Diff line
@@ -43,8 +43,6 @@
#include <linux/binfmts.h>
#include <linux/binfmts.h>
#include "smack.h"
#include "smack.h"


#define task_security(task)	(task_cred_xxx((task), security))

#define TRANS_TRUE	"TRUE"
#define TRANS_TRUE	"TRUE"
#define TRANS_TRUE_SIZE	4
#define TRANS_TRUE_SIZE	4


@@ -52,8 +50,11 @@
#define SMK_RECEIVING	1
#define SMK_RECEIVING	1
#define SMK_SENDING	2
#define SMK_SENDING	2


#if IS_ENABLED(CONFIG_IPV6) && !defined(CONFIG_SECURITY_SMACK_NETFILTER)
LIST_HEAD(smk_ipv6_port_list);
LIST_HEAD(smk_ipv6_port_list);
#endif /* CONFIG_IPV6 && !CONFIG_SECURITY_SMACK_NETFILTER */
static struct kmem_cache *smack_inode_cache;
static struct kmem_cache *smack_inode_cache;
int smack_enabled;


#ifdef CONFIG_SECURITY_SMACK_BRINGUP
#ifdef CONFIG_SECURITY_SMACK_BRINGUP
static void smk_bu_mode(int mode, char *s)
static void smk_bu_mode(int mode, char *s)
@@ -120,7 +121,7 @@ static int smk_bu_current(char *note, struct smack_known *oskp,
static int smk_bu_task(struct task_struct *otp, int mode, int rc)
static int smk_bu_task(struct task_struct *otp, int mode, int rc)
{
{
	struct task_smack *tsp = current_security();
	struct task_smack *tsp = current_security();
	struct task_smack *otsp = task_security(otp);
	struct smack_known *smk_task = smk_of_task_struct(otp);
	char acc[SMK_NUM_ACCESS_TYPE + 1];
	char acc[SMK_NUM_ACCESS_TYPE + 1];


	if (rc <= 0)
	if (rc <= 0)
@@ -128,7 +129,7 @@ static int smk_bu_task(struct task_struct *otp, int mode, int rc)


	smk_bu_mode(mode, acc);
	smk_bu_mode(mode, acc);
	pr_info("Smack Bringup: (%s %s %s) %s to %s\n",
	pr_info("Smack Bringup: (%s %s %s) %s to %s\n",
		tsp->smk_task->smk_known, otsp->smk_task->smk_known, acc,
		tsp->smk_task->smk_known, smk_task->smk_known, acc,
		current->comm, otp->comm);
		current->comm, otp->comm);
	return 0;
	return 0;
}
}
@@ -160,7 +161,7 @@ static int smk_bu_file(struct file *file, int mode, int rc)
{
{
	struct task_smack *tsp = current_security();
	struct task_smack *tsp = current_security();
	struct smack_known *sskp = tsp->smk_task;
	struct smack_known *sskp = tsp->smk_task;
	struct inode *inode = file->f_inode;
	struct inode *inode = file_inode(file);
	char acc[SMK_NUM_ACCESS_TYPE + 1];
	char acc[SMK_NUM_ACCESS_TYPE + 1];


	if (rc <= 0)
	if (rc <= 0)
@@ -168,7 +169,7 @@ static int smk_bu_file(struct file *file, int mode, int rc)


	smk_bu_mode(mode, acc);
	smk_bu_mode(mode, acc);
	pr_info("Smack Bringup: (%s %s %s) file=(%s %ld %pD) %s\n",
	pr_info("Smack Bringup: (%s %s %s) file=(%s %ld %pD) %s\n",
		sskp->smk_known, (char *)file->f_security, acc,
		sskp->smk_known, smk_of_inode(inode)->smk_known, acc,
		inode->i_sb->s_id, inode->i_ino, file,
		inode->i_sb->s_id, inode->i_ino, file,
		current->comm);
		current->comm);
	return 0;
	return 0;
@@ -202,6 +203,7 @@ static int smk_bu_credfile(const struct cred *cred, struct file *file,


/**
/**
 * smk_fetch - Fetch the smack label from a file.
 * smk_fetch - Fetch the smack label from a file.
 * @name: type of the label (attribute)
 * @ip: a pointer to the inode
 * @ip: a pointer to the inode
 * @dp: a pointer to the dentry
 * @dp: a pointer to the dentry
 *
 *
@@ -254,7 +256,9 @@ struct inode_smack *new_inode_smack(struct smack_known *skp)


/**
/**
 * new_task_smack - allocate a task security blob
 * new_task_smack - allocate a task security blob
 * @smack: a pointer to the Smack label to use in the blob
 * @task: a pointer to the Smack label for the running task
 * @forked: a pointer to the Smack label for the forked task
 * @gfp: type of the memory for the allocation
 *
 *
 * Returns the new blob or NULL if there's no memory available
 * Returns the new blob or NULL if there's no memory available
 */
 */
@@ -277,8 +281,9 @@ static struct task_smack *new_task_smack(struct smack_known *task,


/**
/**
 * smk_copy_rules - copy a rule set
 * smk_copy_rules - copy a rule set
 * @nhead - new rules header pointer
 * @nhead: new rules header pointer
 * @ohead - old rules header pointer
 * @ohead: old rules header pointer
 * @gfp: type of the memory for the allocation
 *
 *
 * Returns 0 on success, -ENOMEM on error
 * Returns 0 on success, -ENOMEM on error
 */
 */
@@ -345,7 +350,8 @@ static int smk_ptrace_rule_check(struct task_struct *tracer,
		saip = &ad;
		saip = &ad;
	}
	}


	tsp = task_security(tracer);
	rcu_read_lock();
	tsp = __task_cred(tracer)->security;
	tracer_known = smk_of_task(tsp);
	tracer_known = smk_of_task(tsp);


	if ((mode & PTRACE_MODE_ATTACH) &&
	if ((mode & PTRACE_MODE_ATTACH) &&
@@ -365,11 +371,14 @@ static int smk_ptrace_rule_check(struct task_struct *tracer,
				  tracee_known->smk_known,
				  tracee_known->smk_known,
				  0, rc, saip);
				  0, rc, saip);


		rcu_read_unlock();
		return rc;
		return rc;
	}
	}


	/* In case of rule==SMACK_PTRACE_DEFAULT or mode==PTRACE_MODE_READ */
	/* In case of rule==SMACK_PTRACE_DEFAULT or mode==PTRACE_MODE_READ */
	rc = smk_tskacc(tsp, tracee_known, smk_ptrace_mode(mode), saip);
	rc = smk_tskacc(tsp, tracee_known, smk_ptrace_mode(mode), saip);

	rcu_read_unlock();
	return rc;
	return rc;
}
}


@@ -396,7 +405,7 @@ static int smack_ptrace_access_check(struct task_struct *ctp, unsigned int mode)
	if (rc != 0)
	if (rc != 0)
		return rc;
		return rc;


	skp = smk_of_task(task_security(ctp));
	skp = smk_of_task_struct(ctp);


	rc = smk_ptrace_rule_check(current, skp, mode, __func__);
	rc = smk_ptrace_rule_check(current, skp, mode, __func__);
	return rc;
	return rc;
@@ -796,7 +805,7 @@ static int smack_inode_init_security(struct inode *inode, struct inode *dir,
	if (name)
	if (name)
		*name = XATTR_SMACK_SUFFIX;
		*name = XATTR_SMACK_SUFFIX;


	if (value) {
	if (value && len) {
		rcu_read_lock();
		rcu_read_lock();
		may = smk_access_entry(skp->smk_known, dsp->smk_known,
		may = smk_access_entry(skp->smk_known, dsp->smk_known,
				       &skp->smk_rules);
				       &skp->smk_rules);
@@ -817,10 +826,9 @@ static int smack_inode_init_security(struct inode *inode, struct inode *dir,
		*value = kstrdup(isp->smk_known, GFP_NOFS);
		*value = kstrdup(isp->smk_known, GFP_NOFS);
		if (*value == NULL)
		if (*value == NULL)
			return -ENOMEM;
			return -ENOMEM;
	}


	if (len)
		*len = strlen(isp->smk_known);
		*len = strlen(isp->smk_known);
	}


	return 0;
	return 0;
}
}
@@ -1344,6 +1352,9 @@ static int smack_file_permission(struct file *file, int mask)
 * The security blob for a file is a pointer to the master
 * The security blob for a file is a pointer to the master
 * label list, so no allocation is done.
 * label list, so no allocation is done.
 *
 *
 * f_security is the owner security information. It
 * isn't used on file access checks, it's for send_sigio.
 *
 * Returns 0
 * Returns 0
 */
 */
static int smack_file_alloc_security(struct file *file)
static int smack_file_alloc_security(struct file *file)
@@ -1381,17 +1392,18 @@ static int smack_file_ioctl(struct file *file, unsigned int cmd,
{
{
	int rc = 0;
	int rc = 0;
	struct smk_audit_info ad;
	struct smk_audit_info ad;
	struct inode *inode = file_inode(file);


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


	if (_IOC_DIR(cmd) & _IOC_WRITE) {
	if (_IOC_DIR(cmd) & _IOC_WRITE) {
		rc = smk_curacc(file->f_security, MAY_WRITE, &ad);
		rc = smk_curacc(smk_of_inode(inode), MAY_WRITE, &ad);
		rc = smk_bu_file(file, MAY_WRITE, rc);
		rc = smk_bu_file(file, MAY_WRITE, rc);
	}
	}


	if (rc == 0 && (_IOC_DIR(cmd) & _IOC_READ)) {
	if (rc == 0 && (_IOC_DIR(cmd) & _IOC_READ)) {
		rc = smk_curacc(file->f_security, MAY_READ, &ad);
		rc = smk_curacc(smk_of_inode(inode), MAY_READ, &ad);
		rc = smk_bu_file(file, MAY_READ, rc);
		rc = smk_bu_file(file, MAY_READ, rc);
	}
	}


@@ -1409,10 +1421,11 @@ static int smack_file_lock(struct file *file, unsigned int cmd)
{
{
	struct smk_audit_info ad;
	struct smk_audit_info ad;
	int rc;
	int rc;
	struct inode *inode = file_inode(file);


	smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH);
	smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH);
	smk_ad_setfield_u_fs_path(&ad, file->f_path);
	smk_ad_setfield_u_fs_path(&ad, file->f_path);
	rc = smk_curacc(file->f_security, MAY_LOCK, &ad);
	rc = smk_curacc(smk_of_inode(inode), MAY_LOCK, &ad);
	rc = smk_bu_file(file, MAY_LOCK, rc);
	rc = smk_bu_file(file, MAY_LOCK, rc);
	return rc;
	return rc;
}
}
@@ -1434,7 +1447,7 @@ static int smack_file_fcntl(struct file *file, unsigned int cmd,
{
{
	struct smk_audit_info ad;
	struct smk_audit_info ad;
	int rc = 0;
	int rc = 0;

	struct inode *inode = file_inode(file);


	switch (cmd) {
	switch (cmd) {
	case F_GETLK:
	case F_GETLK:
@@ -1443,14 +1456,14 @@ static int smack_file_fcntl(struct file *file, unsigned int cmd,
	case F_SETLKW:
	case F_SETLKW:
		smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH);
		smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH);
		smk_ad_setfield_u_fs_path(&ad, file->f_path);
		smk_ad_setfield_u_fs_path(&ad, file->f_path);
		rc = smk_curacc(file->f_security, MAY_LOCK, &ad);
		rc = smk_curacc(smk_of_inode(inode), MAY_LOCK, &ad);
		rc = smk_bu_file(file, MAY_LOCK, rc);
		rc = smk_bu_file(file, MAY_LOCK, rc);
		break;
		break;
	case F_SETOWN:
	case F_SETOWN:
	case F_SETSIG:
	case F_SETSIG:
		smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH);
		smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH);
		smk_ad_setfield_u_fs_path(&ad, file->f_path);
		smk_ad_setfield_u_fs_path(&ad, file->f_path);
		rc = smk_curacc(file->f_security, MAY_WRITE, &ad);
		rc = smk_curacc(smk_of_inode(inode), MAY_WRITE, &ad);
		rc = smk_bu_file(file, MAY_WRITE, rc);
		rc = smk_bu_file(file, MAY_WRITE, rc);
		break;
		break;
	default:
	default:
@@ -1568,14 +1581,10 @@ static int smack_mmap_file(struct file *file,
 * smack_file_set_fowner - set the file security blob value
 * smack_file_set_fowner - set the file security blob value
 * @file: object in question
 * @file: object in question
 *
 *
 * Returns 0
 * Further research may be required on this one.
 */
 */
static void smack_file_set_fowner(struct file *file)
static void smack_file_set_fowner(struct file *file)
{
{
	struct smack_known *skp = smk_of_current();
	file->f_security = smk_of_current();

	file->f_security = skp;
}
}


/**
/**
@@ -1627,6 +1636,7 @@ static int smack_file_receive(struct file *file)
	int rc;
	int rc;
	int may = 0;
	int may = 0;
	struct smk_audit_info ad;
	struct smk_audit_info ad;
	struct inode *inode = file_inode(file);


	smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH);
	smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH);
	smk_ad_setfield_u_fs_path(&ad, file->f_path);
	smk_ad_setfield_u_fs_path(&ad, file->f_path);
@@ -1638,7 +1648,7 @@ static int smack_file_receive(struct file *file)
	if (file->f_mode & FMODE_WRITE)
	if (file->f_mode & FMODE_WRITE)
		may |= MAY_WRITE;
		may |= MAY_WRITE;


	rc = smk_curacc(file->f_security, may, &ad);
	rc = smk_curacc(smk_of_inode(inode), may, &ad);
	rc = smk_bu_file(file, may, rc);
	rc = smk_bu_file(file, may, rc);
	return rc;
	return rc;
}
}
@@ -1658,21 +1668,17 @@ static int smack_file_receive(struct file *file)
static int smack_file_open(struct file *file, const struct cred *cred)
static int smack_file_open(struct file *file, const struct cred *cred)
{
{
	struct task_smack *tsp = cred->security;
	struct task_smack *tsp = cred->security;
	struct inode_smack *isp = file_inode(file)->i_security;
	struct inode *inode = file_inode(file);
	struct smk_audit_info ad;
	struct smk_audit_info ad;
	int rc;
	int rc;


	if (smack_privileged(CAP_MAC_OVERRIDE)) {
	if (smack_privileged(CAP_MAC_OVERRIDE))
		file->f_security = isp->smk_inode;
		return 0;
		return 0;
	}


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


	return rc;
	return rc;
}
}
@@ -1826,7 +1832,7 @@ static int smk_curacc_on_task(struct task_struct *p, int access,
				const char *caller)
				const char *caller)
{
{
	struct smk_audit_info ad;
	struct smk_audit_info ad;
	struct smack_known *skp = smk_of_task(task_security(p));
	struct smack_known *skp = smk_of_task_struct(p);
	int rc;
	int rc;


	smk_ad_init(&ad, caller, LSM_AUDIT_DATA_TASK);
	smk_ad_init(&ad, caller, LSM_AUDIT_DATA_TASK);
@@ -1879,7 +1885,7 @@ static int smack_task_getsid(struct task_struct *p)
 */
 */
static void smack_task_getsecid(struct task_struct *p, u32 *secid)
static void smack_task_getsecid(struct task_struct *p, u32 *secid)
{
{
	struct smack_known *skp = smk_of_task(task_security(p));
	struct smack_known *skp = smk_of_task_struct(p);


	*secid = skp->smk_secid;
	*secid = skp->smk_secid;
}
}
@@ -1986,7 +1992,7 @@ static int smack_task_kill(struct task_struct *p, struct siginfo *info,
{
{
	struct smk_audit_info ad;
	struct smk_audit_info ad;
	struct smack_known *skp;
	struct smack_known *skp;
	struct smack_known *tkp = smk_of_task(task_security(p));
	struct smack_known *tkp = smk_of_task_struct(p);
	int rc;
	int rc;


	smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_TASK);
	smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_TASK);
@@ -2040,7 +2046,7 @@ static int smack_task_wait(struct task_struct *p)
static void smack_task_to_inode(struct task_struct *p, struct inode *inode)
static void smack_task_to_inode(struct task_struct *p, struct inode *inode)
{
{
	struct inode_smack *isp = inode->i_security;
	struct inode_smack *isp = inode->i_security;
	struct smack_known *skp = smk_of_task(task_security(p));
	struct smack_known *skp = smk_of_task_struct(p);


	isp->smk_inode = skp;
	isp->smk_inode = skp;
}
}
@@ -2212,6 +2218,7 @@ static int smack_netlabel_send(struct sock *sk, struct sockaddr_in *sap)
	return smack_netlabel(sk, sk_lbl);
	return smack_netlabel(sk, sk_lbl);
}
}


#if IS_ENABLED(CONFIG_IPV6) && !defined(CONFIG_SECURITY_SMACK_NETFILTER)
/**
/**
 * smk_ipv6_port_label - Smack port access table management
 * smk_ipv6_port_label - Smack port access table management
 * @sock: socket
 * @sock: socket
@@ -2361,6 +2368,7 @@ static int smk_ipv6_port_check(struct sock *sk, struct sockaddr_in6 *address,
	rc = smk_bu_note("IPv6 port check", skp, object, MAY_WRITE, rc);
	rc = smk_bu_note("IPv6 port check", skp, object, MAY_WRITE, rc);
	return rc;
	return rc;
}
}
#endif /* CONFIG_IPV6 && !CONFIG_SECURITY_SMACK_NETFILTER */


/**
/**
 * smack_inode_setsecurity - set smack xattrs
 * smack_inode_setsecurity - set smack xattrs
@@ -2421,8 +2429,10 @@ static int smack_inode_setsecurity(struct inode *inode, const char *name,
	} else
	} else
		return -EOPNOTSUPP;
		return -EOPNOTSUPP;


#if IS_ENABLED(CONFIG_IPV6) && !defined(CONFIG_SECURITY_SMACK_NETFILTER)
	if (sock->sk->sk_family == PF_INET6)
	if (sock->sk->sk_family == PF_INET6)
		smk_ipv6_port_label(sock, NULL);
		smk_ipv6_port_label(sock, NULL);
#endif /* CONFIG_IPV6 && !CONFIG_SECURITY_SMACK_NETFILTER */


	return 0;
	return 0;
}
}
@@ -2450,6 +2460,7 @@ static int smack_socket_post_create(struct socket *sock, int family,
	return smack_netlabel(sock->sk, SMACK_CIPSO_SOCKET);
	return smack_netlabel(sock->sk, SMACK_CIPSO_SOCKET);
}
}


#ifndef CONFIG_SECURITY_SMACK_NETFILTER
/**
/**
 * smack_socket_bind - record port binding information.
 * smack_socket_bind - record port binding information.
 * @sock: the socket
 * @sock: the socket
@@ -2463,11 +2474,14 @@ static int smack_socket_post_create(struct socket *sock, int family,
static int smack_socket_bind(struct socket *sock, struct sockaddr *address,
static int smack_socket_bind(struct socket *sock, struct sockaddr *address,
				int addrlen)
				int addrlen)
{
{
#if IS_ENABLED(CONFIG_IPV6)
	if (sock->sk != NULL && sock->sk->sk_family == PF_INET6)
	if (sock->sk != NULL && sock->sk->sk_family == PF_INET6)
		smk_ipv6_port_label(sock, address);
		smk_ipv6_port_label(sock, address);
#endif


	return 0;
	return 0;
}
}
#endif /* !CONFIG_SECURITY_SMACK_NETFILTER */


/**
/**
 * smack_socket_connect - connect access check
 * smack_socket_connect - connect access check
@@ -2496,8 +2510,10 @@ static int smack_socket_connect(struct socket *sock, struct sockaddr *sap,
	case PF_INET6:
	case PF_INET6:
		if (addrlen < sizeof(struct sockaddr_in6))
		if (addrlen < sizeof(struct sockaddr_in6))
			return -EINVAL;
			return -EINVAL;
#if IS_ENABLED(CONFIG_IPV6) && !defined(CONFIG_SECURITY_SMACK_NETFILTER)
		rc = smk_ipv6_port_check(sock->sk, (struct sockaddr_in6 *)sap,
		rc = smk_ipv6_port_check(sock->sk, (struct sockaddr_in6 *)sap,
						SMK_CONNECTING);
						SMK_CONNECTING);
#endif /* CONFIG_IPV6 && !CONFIG_SECURITY_SMACK_NETFILTER */
		break;
		break;
	}
	}
	return rc;
	return rc;
@@ -3033,7 +3049,8 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode)
	 * of the superblock.
	 * of the superblock.
	 */
	 */
	if (opt_dentry->d_parent == opt_dentry) {
	if (opt_dentry->d_parent == opt_dentry) {
		if (sbp->s_magic == CGROUP_SUPER_MAGIC) {
		switch (sbp->s_magic) {
		case CGROUP_SUPER_MAGIC:
			/*
			/*
			 * The cgroup filesystem is never mounted,
			 * The cgroup filesystem is never mounted,
			 * so there's no opportunity to set the mount
			 * so there's no opportunity to set the mount
@@ -3041,8 +3058,19 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode)
			 */
			 */
			sbsp->smk_root = &smack_known_star;
			sbsp->smk_root = &smack_known_star;
			sbsp->smk_default = &smack_known_star;
			sbsp->smk_default = &smack_known_star;
		}
			isp->smk_inode = sbsp->smk_root;
			isp->smk_inode = sbsp->smk_root;
			break;
		case TMPFS_MAGIC:
			/*
			 * What about shmem/tmpfs anonymous files with dentry
			 * obtained from d_alloc_pseudo()?
			 */
			isp->smk_inode = smk_of_current();
			break;
		default:
			isp->smk_inode = sbsp->smk_root;
			break;
		}
		isp->smk_flags |= SMK_INODE_INSTANT;
		isp->smk_flags |= SMK_INODE_INSTANT;
		goto unlockandout;
		goto unlockandout;
	}
	}
@@ -3200,7 +3228,7 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode)
 */
 */
static int smack_getprocattr(struct task_struct *p, char *name, char **value)
static int smack_getprocattr(struct task_struct *p, char *name, char **value)
{
{
	struct smack_known *skp = smk_of_task(task_security(p));
	struct smack_known *skp = smk_of_task_struct(p);
	char *cp;
	char *cp;
	int slen;
	int slen;


@@ -3297,7 +3325,7 @@ static int smack_unix_stream_connect(struct sock *sock,


	if (!smack_privileged(CAP_MAC_OVERRIDE)) {
	if (!smack_privileged(CAP_MAC_OVERRIDE)) {
		skp = ssp->smk_out;
		skp = ssp->smk_out;
		okp = osp->smk_out;
		okp = osp->smk_in;
#ifdef CONFIG_AUDIT
#ifdef CONFIG_AUDIT
		smk_ad_init_net(&ad, __func__, LSM_AUDIT_DATA_NET, &net);
		smk_ad_init_net(&ad, __func__, LSM_AUDIT_DATA_NET, &net);
		smk_ad_setfield_u_net_sk(&ad, other);
		smk_ad_setfield_u_net_sk(&ad, other);
@@ -3305,7 +3333,9 @@ static int smack_unix_stream_connect(struct sock *sock,
		rc = smk_access(skp, okp, MAY_WRITE, &ad);
		rc = smk_access(skp, okp, MAY_WRITE, &ad);
		rc = smk_bu_note("UDS connect", skp, okp, MAY_WRITE, rc);
		rc = smk_bu_note("UDS connect", skp, okp, MAY_WRITE, rc);
		if (rc == 0) {
		if (rc == 0) {
			rc = smk_access(okp, skp, MAY_WRITE, NULL);
			okp = osp->smk_out;
			skp = ssp->smk_in;
			rc = smk_access(okp, skp, MAY_WRITE, &ad);
			rc = smk_bu_note("UDS connect", okp, skp,
			rc = smk_bu_note("UDS connect", okp, skp,
						MAY_WRITE, rc);
						MAY_WRITE, rc);
		}
		}
@@ -3366,7 +3396,9 @@ static int smack_socket_sendmsg(struct socket *sock, struct msghdr *msg,
				int size)
				int size)
{
{
	struct sockaddr_in *sip = (struct sockaddr_in *) msg->msg_name;
	struct sockaddr_in *sip = (struct sockaddr_in *) msg->msg_name;
#if IS_ENABLED(CONFIG_IPV6) && !defined(CONFIG_SECURITY_SMACK_NETFILTER)
	struct sockaddr_in6 *sap = (struct sockaddr_in6 *) msg->msg_name;
	struct sockaddr_in6 *sap = (struct sockaddr_in6 *) msg->msg_name;
#endif /* CONFIG_IPV6 && !CONFIG_SECURITY_SMACK_NETFILTER */
	int rc = 0;
	int rc = 0;


	/*
	/*
@@ -3380,7 +3412,9 @@ static int smack_socket_sendmsg(struct socket *sock, struct msghdr *msg,
		rc = smack_netlabel_send(sock->sk, sip);
		rc = smack_netlabel_send(sock->sk, sip);
		break;
		break;
	case AF_INET6:
	case AF_INET6:
#if IS_ENABLED(CONFIG_IPV6) && !defined(CONFIG_SECURITY_SMACK_NETFILTER)
		rc = smk_ipv6_port_check(sock->sk, sap, SMK_SENDING);
		rc = smk_ipv6_port_check(sock->sk, sap, SMK_SENDING);
#endif /* CONFIG_IPV6 && !CONFIG_SECURITY_SMACK_NETFILTER */
		break;
		break;
	}
	}
	return rc;
	return rc;
@@ -3471,6 +3505,7 @@ static struct smack_known *smack_from_secattr(struct netlbl_lsm_secattr *sap,
	return smack_net_ambient;
	return smack_net_ambient;
}
}


#if IS_ENABLED(CONFIG_IPV6)
static int smk_skb_to_addr_ipv6(struct sk_buff *skb, struct sockaddr_in6 *sip)
static int smk_skb_to_addr_ipv6(struct sk_buff *skb, struct sockaddr_in6 *sip)
{
{
	u8 nexthdr;
	u8 nexthdr;
@@ -3517,6 +3552,7 @@ static int smk_skb_to_addr_ipv6(struct sk_buff *skb, struct sockaddr_in6 *sip)
	}
	}
	return proto;
	return proto;
}
}
#endif /* CONFIG_IPV6 */


/**
/**
 * smack_socket_sock_rcv_skb - Smack packet delivery access check
 * smack_socket_sock_rcv_skb - Smack packet delivery access check
@@ -3529,15 +3565,30 @@ static int smack_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
{
{
	struct netlbl_lsm_secattr secattr;
	struct netlbl_lsm_secattr secattr;
	struct socket_smack *ssp = sk->sk_security;
	struct socket_smack *ssp = sk->sk_security;
	struct smack_known *skp;
	struct smack_known *skp = NULL;
	struct sockaddr_in6 sadd;
	int rc = 0;
	int rc = 0;
	struct smk_audit_info ad;
	struct smk_audit_info ad;
#ifdef CONFIG_AUDIT
#ifdef CONFIG_AUDIT
	struct lsm_network_audit net;
	struct lsm_network_audit net;
#endif
#endif
#if IS_ENABLED(CONFIG_IPV6)
	struct sockaddr_in6 sadd;
	int proto;
#endif /* CONFIG_IPV6 */

	switch (sk->sk_family) {
	switch (sk->sk_family) {
	case PF_INET:
	case PF_INET:
#ifdef CONFIG_SECURITY_SMACK_NETFILTER
		/*
		 * If there is a secmark use it rather than the CIPSO label.
		 * If there is no secmark fall back to CIPSO.
		 * The secmark is assumed to reflect policy better.
		 */
		if (skb && skb->secmark != 0) {
			skp = smack_from_secid(skb->secmark);
			goto access_check;
		}
#endif /* CONFIG_SECURITY_SMACK_NETFILTER */
		/*
		/*
		 * Translate what netlabel gave us.
		 * Translate what netlabel gave us.
		 */
		 */
@@ -3551,6 +3602,9 @@ static int smack_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)


		netlbl_secattr_destroy(&secattr);
		netlbl_secattr_destroy(&secattr);


#ifdef CONFIG_SECURITY_SMACK_NETFILTER
access_check:
#endif
#ifdef CONFIG_AUDIT
#ifdef CONFIG_AUDIT
		smk_ad_init_net(&ad, __func__, LSM_AUDIT_DATA_NET, &net);
		smk_ad_init_net(&ad, __func__, LSM_AUDIT_DATA_NET, &net);
		ad.a.u.net->family = sk->sk_family;
		ad.a.u.net->family = sk->sk_family;
@@ -3569,14 +3623,32 @@ static int smack_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
		if (rc != 0)
		if (rc != 0)
			netlbl_skbuff_err(skb, rc, 0);
			netlbl_skbuff_err(skb, rc, 0);
		break;
		break;
#if IS_ENABLED(CONFIG_IPV6)
	case PF_INET6:
	case PF_INET6:
		rc = smk_skb_to_addr_ipv6(skb, &sadd);
		proto = smk_skb_to_addr_ipv6(skb, &sadd);
		if (rc == IPPROTO_UDP || rc == IPPROTO_TCP)
		if (proto != IPPROTO_UDP && proto != IPPROTO_TCP)
			rc = smk_ipv6_port_check(sk, &sadd, SMK_RECEIVING);
			break;
#ifdef CONFIG_SECURITY_SMACK_NETFILTER
		if (skb && skb->secmark != 0)
			skp = smack_from_secid(skb->secmark);
		else
		else
			rc = 0;
			skp = smack_net_ambient;
#ifdef CONFIG_AUDIT
		smk_ad_init_net(&ad, __func__, LSM_AUDIT_DATA_NET, &net);
		ad.a.u.net->family = sk->sk_family;
		ad.a.u.net->netif = skb->skb_iif;
		ipv6_skb_to_auditdata(skb, &ad.a, NULL);
#endif /* CONFIG_AUDIT */
		rc = smk_access(skp, ssp->smk_in, MAY_WRITE, &ad);
		rc = smk_bu_note("IPv6 delivery", skp, ssp->smk_in,
					MAY_WRITE, rc);
#else /* CONFIG_SECURITY_SMACK_NETFILTER */
		rc = smk_ipv6_port_check(sk, &sadd, SMK_RECEIVING);
#endif /* CONFIG_SECURITY_SMACK_NETFILTER */
		break;
		break;
#endif /* CONFIG_IPV6 */
	}
	}

	return rc;
	return rc;
}
}


@@ -3638,16 +3710,25 @@ static int smack_socket_getpeersec_dgram(struct socket *sock,
	if (skb != NULL) {
	if (skb != NULL) {
		if (skb->protocol == htons(ETH_P_IP))
		if (skb->protocol == htons(ETH_P_IP))
			family = PF_INET;
			family = PF_INET;
#if IS_ENABLED(CONFIG_IPV6)
		else if (skb->protocol == htons(ETH_P_IPV6))
		else if (skb->protocol == htons(ETH_P_IPV6))
			family = PF_INET6;
			family = PF_INET6;
#endif /* CONFIG_IPV6 */
	}
	}
	if (family == PF_UNSPEC && sock != NULL)
	if (family == PF_UNSPEC && sock != NULL)
		family = sock->sk->sk_family;
		family = sock->sk->sk_family;


	if (family == PF_UNIX) {
	switch (family) {
	case PF_UNIX:
		ssp = sock->sk->sk_security;
		ssp = sock->sk->sk_security;
		s = ssp->smk_out->smk_secid;
		s = ssp->smk_out->smk_secid;
	} else if (family == PF_INET || family == PF_INET6) {
		break;
	case PF_INET:
#ifdef CONFIG_SECURITY_SMACK_NETFILTER
		s = skb->secmark;
		if (s != 0)
			break;
#endif
		/*
		/*
		 * Translate what netlabel gave us.
		 * Translate what netlabel gave us.
		 */
		 */
@@ -3660,6 +3741,14 @@ static int smack_socket_getpeersec_dgram(struct socket *sock,
			s = skp->smk_secid;
			s = skp->smk_secid;
		}
		}
		netlbl_secattr_destroy(&secattr);
		netlbl_secattr_destroy(&secattr);
		break;
#if IS_ENABLED(CONFIG_IPV6)
	case PF_INET6:
#ifdef CONFIG_SECURITY_SMACK_NETFILTER
		s = skb->secmark;
#endif /* CONFIG_SECURITY_SMACK_NETFILTER */
		break;
#endif /* CONFIG_IPV6 */
	}
	}
	*secid = s;
	*secid = s;
	if (s == 0)
	if (s == 0)
@@ -3715,6 +3804,7 @@ static int smack_inet_conn_request(struct sock *sk, struct sk_buff *skb,
	struct lsm_network_audit net;
	struct lsm_network_audit net;
#endif
#endif


#if IS_ENABLED(CONFIG_IPV6)
	if (family == PF_INET6) {
	if (family == PF_INET6) {
		/*
		/*
		 * Handle mapped IPv4 packets arriving
		 * Handle mapped IPv4 packets arriving
@@ -3726,6 +3816,7 @@ static int smack_inet_conn_request(struct sock *sk, struct sk_buff *skb,
		else
		else
			return 0;
			return 0;
	}
	}
#endif /* CONFIG_IPV6 */


	netlbl_secattr_init(&secattr);
	netlbl_secattr_init(&secattr);
	rc = netlbl_skbuff_getattr(skb, family, &secattr);
	rc = netlbl_skbuff_getattr(skb, family, &secattr);
@@ -3834,11 +3925,11 @@ static void smack_key_free(struct key *key)
	key->security = NULL;
	key->security = NULL;
}
}


/*
/**
 * smack_key_permission - Smack access on a key
 * smack_key_permission - Smack access on a key
 * @key_ref: gets to the object
 * @key_ref: gets to the object
 * @cred: the credentials to use
 * @cred: the credentials to use
 * @perm: unused
 * @perm: requested key permissions
 *
 *
 * Return 0 if the task has read and write to the object,
 * Return 0 if the task has read and write to the object,
 * an error code otherwise
 * an error code otherwise
@@ -4184,7 +4275,9 @@ struct security_operations smack_ops = {
	.unix_may_send = 		smack_unix_may_send,
	.unix_may_send = 		smack_unix_may_send,


	.socket_post_create = 		smack_socket_post_create,
	.socket_post_create = 		smack_socket_post_create,
#ifndef CONFIG_SECURITY_SMACK_NETFILTER
	.socket_bind =			smack_socket_bind,
	.socket_bind =			smack_socket_bind,
#endif /* CONFIG_SECURITY_SMACK_NETFILTER */
	.socket_connect =		smack_socket_connect,
	.socket_connect =		smack_socket_connect,
	.socket_sendmsg =		smack_socket_sendmsg,
	.socket_sendmsg =		smack_socket_sendmsg,
	.socket_sock_rcv_skb = 		smack_socket_sock_rcv_skb,
	.socket_sock_rcv_skb = 		smack_socket_sock_rcv_skb,
@@ -4265,6 +4358,8 @@ static __init int smack_init(void)
	if (!security_module_enable(&smack_ops))
	if (!security_module_enable(&smack_ops))
		return 0;
		return 0;


	smack_enabled = 1;

	smack_inode_cache = KMEM_CACHE(inode_smack, 0);
	smack_inode_cache = KMEM_CACHE(inode_smack, 0);
	if (!smack_inode_cache)
	if (!smack_inode_cache)
		return -ENOMEM;
		return -ENOMEM;
+96 −0
Original line number Original line Diff line number Diff line
/*
 *  Simplified MAC Kernel (smack) security module
 *
 *  This file contains the Smack netfilter implementation
 *
 *  Author:
 *	Casey Schaufler <casey@schaufler-ca.com>
 *
 *  Copyright (C) 2014 Casey Schaufler <casey@schaufler-ca.com>
 *  Copyright (C) 2014 Intel Corporation.
 *
 *	This program is free software; you can redistribute it and/or modify
 *	it under the terms of the GNU General Public License version 2,
 *	as published by the Free Software Foundation.
 */

#include <linux/netfilter_ipv4.h>
#include <linux/netfilter_ipv6.h>
#include <linux/netdevice.h>
#include "smack.h"

#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)

static unsigned int smack_ipv6_output(const struct nf_hook_ops *ops,
					struct sk_buff *skb,
					const struct net_device *in,
					const struct net_device *out,
					int (*okfn)(struct sk_buff *))
{
	struct socket_smack *ssp;
	struct smack_known *skp;

	if (skb && skb->sk && skb->sk->sk_security) {
		ssp = skb->sk->sk_security;
		skp = ssp->smk_out;
		skb->secmark = skp->smk_secid;
	}

	return NF_ACCEPT;
}
#endif	/* IPV6 */

static unsigned int smack_ipv4_output(const struct nf_hook_ops *ops,
					struct sk_buff *skb,
					const struct net_device *in,
					const struct net_device *out,
					int (*okfn)(struct sk_buff *))
{
	struct socket_smack *ssp;
	struct smack_known *skp;

	if (skb && skb->sk && skb->sk->sk_security) {
		ssp = skb->sk->sk_security;
		skp = ssp->smk_out;
		skb->secmark = skp->smk_secid;
	}

	return NF_ACCEPT;
}

static struct nf_hook_ops smack_nf_ops[] = {
	{
		.hook =		smack_ipv4_output,
		.owner =	THIS_MODULE,
		.pf =		NFPROTO_IPV4,
		.hooknum =	NF_INET_LOCAL_OUT,
		.priority =	NF_IP_PRI_SELINUX_FIRST,
	},
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
	{
		.hook =		smack_ipv6_output,
		.owner =	THIS_MODULE,
		.pf =		NFPROTO_IPV6,
		.hooknum =	NF_INET_LOCAL_OUT,
		.priority =	NF_IP6_PRI_SELINUX_FIRST,
	},
#endif	/* IPV6 */
};

static int __init smack_nf_ip_init(void)
{
	int err;

	if (smack_enabled == 0)
		return 0;

	printk(KERN_DEBUG "Smack: Registering netfilter hooks\n");

	err = nf_register_hooks(smack_nf_ops, ARRAY_SIZE(smack_nf_ops));
	if (err)
		pr_info("Smack: nf_register_hooks: error %d\n", err);

	return 0;
}

__initcall(smack_nf_ip_init);