diff options
Diffstat (limited to 'security/smack')
| -rw-r--r-- | security/smack/Kconfig | 12 | ||||
| -rw-r--r-- | security/smack/Makefile | 1 | ||||
| -rw-r--r-- | security/smack/smack.h | 11 | ||||
| -rw-r--r-- | security/smack/smack_lsm.c | 199 | ||||
| -rw-r--r-- | security/smack/smack_netfilter.c | 96 | 
5 files changed, 267 insertions, 52 deletions
| diff --git a/security/smack/Kconfig b/security/smack/Kconfig index b065f9789418..271adae81796 100644 --- a/security/smack/Kconfig +++ b/security/smack/Kconfig @@ -28,3 +28,15 @@ config SECURITY_SMACK_BRINGUP  	  access rule set once the behavior is well understood.  	  This is a superior mechanism to the oft abused  	  "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. diff --git a/security/smack/Makefile b/security/smack/Makefile index 67a63aaec827..ee2ebd504541 100644 --- a/security/smack/Makefile +++ b/security/smack/Makefile @@ -5,3 +5,4 @@  obj-$(CONFIG_SECURITY_SMACK) := smack.o  smack-y := smack_lsm.o smack_access.o smackfs.o +smack-$(CONFIG_SECURITY_SMACK_NETFILTER) += smack_netfilter.o diff --git a/security/smack/smack.h b/security/smack/smack.h index b828a379377c..67ccb7b2b89b 100644 --- a/security/smack/smack.h +++ b/security/smack/smack.h @@ -248,6 +248,7 @@ struct smack_known *smk_find_entry(const char *);  /*   * Shared data.   */ +extern int smack_enabled;  extern int smack_cipso_direct;  extern int smack_cipso_mapped;  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;  } +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.   */ diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index f1b17a476e12..a0ccce4e46f8 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c @@ -43,8 +43,6 @@  #include <linux/binfmts.h>  #include "smack.h" -#define task_security(task)	(task_cred_xxx((task), security)) -  #define TRANS_TRUE	"TRUE"  #define TRANS_TRUE_SIZE	4 @@ -52,8 +50,11 @@  #define SMK_RECEIVING	1  #define SMK_SENDING	2 +#if IS_ENABLED(CONFIG_IPV6) && !defined(CONFIG_SECURITY_SMACK_NETFILTER)  LIST_HEAD(smk_ipv6_port_list); +#endif /* CONFIG_IPV6 && !CONFIG_SECURITY_SMACK_NETFILTER */  static struct kmem_cache *smack_inode_cache; +int smack_enabled;  #ifdef CONFIG_SECURITY_SMACK_BRINGUP  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)  {  	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];  	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);  	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);  	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 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];  	if (rc <= 0) @@ -168,7 +169,7 @@ static int smk_bu_file(struct file *file, int mode, int rc)  	smk_bu_mode(mode, acc);  	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,  		current->comm);  	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. + * @name: type of the label (attribute)   * @ip: a pointer to the inode   * @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 - * @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   */ @@ -277,8 +281,9 @@ static struct task_smack *new_task_smack(struct smack_known *task,  /**   * smk_copy_rules - copy a rule set - * @nhead - new rules header pointer - * @ohead - old rules header pointer + * @nhead: new rules header pointer + * @ohead: old rules header pointer + * @gfp: type of the memory for the allocation   *   * Returns 0 on success, -ENOMEM on error   */ @@ -345,7 +350,8 @@ static int smk_ptrace_rule_check(struct task_struct *tracer,  		saip = &ad;  	} -	tsp = task_security(tracer); +	rcu_read_lock(); +	tsp = __task_cred(tracer)->security;  	tracer_known = smk_of_task(tsp);  	if ((mode & PTRACE_MODE_ATTACH) && @@ -365,11 +371,14 @@ static int smk_ptrace_rule_check(struct task_struct *tracer,  				  tracee_known->smk_known,  				  0, rc, saip); +		rcu_read_unlock();  		return rc;  	}  	/* In case of rule==SMACK_PTRACE_DEFAULT or mode==PTRACE_MODE_READ */  	rc = smk_tskacc(tsp, tracee_known, smk_ptrace_mode(mode), saip); + +	rcu_read_unlock();  	return rc;  } @@ -396,7 +405,7 @@ static int smack_ptrace_access_check(struct task_struct *ctp, unsigned int mode)  	if (rc != 0)  		return rc; -	skp = smk_of_task(task_security(ctp)); +	skp = smk_of_task_struct(ctp);  	rc = smk_ptrace_rule_check(current, skp, mode, __func__);  	return rc; @@ -796,7 +805,7 @@ static int smack_inode_init_security(struct inode *inode, struct inode *dir,  	if (name)  		*name = XATTR_SMACK_SUFFIX; -	if (value) { +	if (value && len) {  		rcu_read_lock();  		may = smk_access_entry(skp->smk_known, dsp->smk_known,  				       &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);  		if (*value == NULL)  			return -ENOMEM; -	} -	if (len)  		*len = strlen(isp->smk_known); +	}  	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   * 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   */  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;  	struct smk_audit_info ad; +	struct inode *inode = file_inode(file);  	smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH);  	smk_ad_setfield_u_fs_path(&ad, file->f_path);  	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);  	}  	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);  	} @@ -1409,10 +1421,11 @@ static int smack_file_lock(struct file *file, unsigned int cmd)  {  	struct smk_audit_info ad;  	int rc; +	struct inode *inode = file_inode(file);  	smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_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);  	return rc;  } @@ -1434,7 +1447,7 @@ static int smack_file_fcntl(struct file *file, unsigned int cmd,  {  	struct smk_audit_info ad;  	int rc = 0; - +	struct inode *inode = file_inode(file);  	switch (cmd) {  	case F_GETLK: @@ -1443,14 +1456,14 @@ static int smack_file_fcntl(struct file *file, unsigned int cmd,  	case F_SETLKW:  		smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_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);  		break;  	case F_SETOWN:  	case F_SETSIG:  		smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_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);  		break;  	default: @@ -1568,14 +1581,10 @@ static int smack_mmap_file(struct file *file,   * smack_file_set_fowner - set the file security blob value   * @file: object in question   * - * Returns 0 - * Further research may be required on this one.   */  static void smack_file_set_fowner(struct file *file)  { -	struct smack_known *skp = smk_of_current(); - -	file->f_security = skp; +	file->f_security = smk_of_current();  }  /** @@ -1627,6 +1636,7 @@ static int smack_file_receive(struct file *file)  	int rc;  	int may = 0;  	struct smk_audit_info ad; +	struct inode *inode = file_inode(file);  	smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_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)  		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);  	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)  {  	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;  	int rc; -	if (smack_privileged(CAP_MAC_OVERRIDE)) { -		file->f_security = isp->smk_inode; +	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, 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); -	if (rc == 0) -		file->f_security = isp->smk_inode;  	return rc;  } @@ -1826,7 +1832,7 @@ static int smk_curacc_on_task(struct task_struct *p, int access,  				const char *caller)  {  	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;  	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)  { -	struct smack_known *skp = smk_of_task(task_security(p)); +	struct smack_known *skp = smk_of_task_struct(p);  	*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 smack_known *skp; -	struct smack_known *tkp = smk_of_task(task_security(p)); +	struct smack_known *tkp = smk_of_task_struct(p);  	int rc;  	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)  {  	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;  } @@ -2212,6 +2218,7 @@ static int smack_netlabel_send(struct sock *sk, struct sockaddr_in *sap)  	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   * @sock: socket @@ -2361,6 +2368,7 @@ auditout:  	rc = smk_bu_note("IPv6 port check", skp, object, MAY_WRITE, rc);  	return rc;  } +#endif /* CONFIG_IPV6 && !CONFIG_SECURITY_SMACK_NETFILTER */  /**   * smack_inode_setsecurity - set smack xattrs @@ -2421,8 +2429,10 @@ static int smack_inode_setsecurity(struct inode *inode, const char *name,  	} else  		return -EOPNOTSUPP; +#if IS_ENABLED(CONFIG_IPV6) && !defined(CONFIG_SECURITY_SMACK_NETFILTER)  	if (sock->sk->sk_family == PF_INET6)  		smk_ipv6_port_label(sock, NULL); +#endif /* CONFIG_IPV6 && !CONFIG_SECURITY_SMACK_NETFILTER */  	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);  } +#ifndef CONFIG_SECURITY_SMACK_NETFILTER  /**   * smack_socket_bind - record port binding information.   * @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,  				int addrlen)  { +#if IS_ENABLED(CONFIG_IPV6)  	if (sock->sk != NULL && sock->sk->sk_family == PF_INET6)  		smk_ipv6_port_label(sock, address); +#endif  	return 0;  } +#endif /* !CONFIG_SECURITY_SMACK_NETFILTER */  /**   * smack_socket_connect - connect access check @@ -2496,8 +2510,10 @@ static int smack_socket_connect(struct socket *sock, struct sockaddr *sap,  	case PF_INET6:  		if (addrlen < sizeof(struct sockaddr_in6))  			return -EINVAL; +#if IS_ENABLED(CONFIG_IPV6) && !defined(CONFIG_SECURITY_SMACK_NETFILTER)  		rc = smk_ipv6_port_check(sock->sk, (struct sockaddr_in6 *)sap,  						SMK_CONNECTING); +#endif /* CONFIG_IPV6 && !CONFIG_SECURITY_SMACK_NETFILTER */  		break;  	}  	return rc; @@ -3033,7 +3049,8 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode)  	 * of the superblock.  	 */  	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,  			 * 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_default = &smack_known_star; +			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_inode = sbsp->smk_root;  		isp->smk_flags |= SMK_INODE_INSTANT;  		goto unlockandout;  	} @@ -3200,7 +3228,7 @@ unlockandout:   */  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;  	int slen; @@ -3297,7 +3325,7 @@ static int smack_unix_stream_connect(struct sock *sock,  	if (!smack_privileged(CAP_MAC_OVERRIDE)) {  		skp = ssp->smk_out; -		okp = osp->smk_out; +		okp = osp->smk_in;  #ifdef CONFIG_AUDIT  		smk_ad_init_net(&ad, __func__, LSM_AUDIT_DATA_NET, &net);  		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_bu_note("UDS connect", skp, okp, MAY_WRITE, rc);  		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,  						MAY_WRITE, rc);  		} @@ -3366,7 +3396,9 @@ static int smack_socket_sendmsg(struct socket *sock, struct msghdr *msg,  				int size)  {  	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; +#endif /* CONFIG_IPV6 && !CONFIG_SECURITY_SMACK_NETFILTER */  	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);  		break;  	case AF_INET6: +#if IS_ENABLED(CONFIG_IPV6) && !defined(CONFIG_SECURITY_SMACK_NETFILTER)  		rc = smk_ipv6_port_check(sock->sk, sap, SMK_SENDING); +#endif /* CONFIG_IPV6 && !CONFIG_SECURITY_SMACK_NETFILTER */  		break;  	}  	return rc; @@ -3471,6 +3505,7 @@ static struct smack_known *smack_from_secattr(struct netlbl_lsm_secattr *sap,  	return smack_net_ambient;  } +#if IS_ENABLED(CONFIG_IPV6)  static int smk_skb_to_addr_ipv6(struct sk_buff *skb, struct sockaddr_in6 *sip)  {  	u8 nexthdr; @@ -3517,6 +3552,7 @@ static int smk_skb_to_addr_ipv6(struct sk_buff *skb, struct sockaddr_in6 *sip)  	}  	return proto;  } +#endif /* CONFIG_IPV6 */  /**   * 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 socket_smack *ssp = sk->sk_security; -	struct smack_known *skp; -	struct sockaddr_in6 sadd; +	struct smack_known *skp = NULL;  	int rc = 0;  	struct smk_audit_info ad;  #ifdef CONFIG_AUDIT  	struct lsm_network_audit net;  #endif +#if IS_ENABLED(CONFIG_IPV6) +	struct sockaddr_in6 sadd; +	int proto; +#endif /* CONFIG_IPV6 */ +  	switch (sk->sk_family) {  	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.  		 */ @@ -3551,6 +3602,9 @@ static int smack_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)  		netlbl_secattr_destroy(&secattr); +#ifdef CONFIG_SECURITY_SMACK_NETFILTER +access_check: +#endif  #ifdef CONFIG_AUDIT  		smk_ad_init_net(&ad, __func__, LSM_AUDIT_DATA_NET, &net);  		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)  			netlbl_skbuff_err(skb, rc, 0);  		break; +#if IS_ENABLED(CONFIG_IPV6)  	case PF_INET6: -		rc = smk_skb_to_addr_ipv6(skb, &sadd); -		if (rc == IPPROTO_UDP || rc == IPPROTO_TCP) -			rc = smk_ipv6_port_check(sk, &sadd, SMK_RECEIVING); +		proto = smk_skb_to_addr_ipv6(skb, &sadd); +		if (proto != IPPROTO_UDP && proto != IPPROTO_TCP) +			break; +#ifdef CONFIG_SECURITY_SMACK_NETFILTER +		if (skb && skb->secmark != 0) +			skp = smack_from_secid(skb->secmark);  		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; +#endif /* CONFIG_IPV6 */  	} +  	return rc;  } @@ -3638,16 +3710,25 @@ static int smack_socket_getpeersec_dgram(struct socket *sock,  	if (skb != NULL) {  		if (skb->protocol == htons(ETH_P_IP))  			family = PF_INET; +#if IS_ENABLED(CONFIG_IPV6)  		else if (skb->protocol == htons(ETH_P_IPV6))  			family = PF_INET6; +#endif /* CONFIG_IPV6 */  	}  	if (family == PF_UNSPEC && sock != NULL)  		family = sock->sk->sk_family; -	if (family == PF_UNIX) { +	switch (family) { +	case PF_UNIX:  		ssp = sock->sk->sk_security;  		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.  		 */ @@ -3660,6 +3741,14 @@ static int smack_socket_getpeersec_dgram(struct socket *sock,  			s = skp->smk_secid;  		}  		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;  	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;  #endif +#if IS_ENABLED(CONFIG_IPV6)  	if (family == PF_INET6) {  		/*  		 * Handle mapped IPv4 packets arriving @@ -3726,6 +3816,7 @@ static int smack_inet_conn_request(struct sock *sk, struct sk_buff *skb,  		else  			return 0;  	} +#endif /* CONFIG_IPV6 */  	netlbl_secattr_init(&secattr);  	rc = netlbl_skbuff_getattr(skb, family, &secattr); @@ -3834,11 +3925,11 @@ static void smack_key_free(struct key *key)  	key->security = NULL;  } -/* +/**   * smack_key_permission - Smack access on a key   * @key_ref: gets to the object   * @cred: the credentials to use - * @perm: unused + * @perm: requested key permissions   *   * Return 0 if the task has read and write to the object,   * an error code otherwise @@ -4184,7 +4275,9 @@ struct security_operations smack_ops = {  	.unix_may_send = 		smack_unix_may_send,  	.socket_post_create = 		smack_socket_post_create, +#ifndef CONFIG_SECURITY_SMACK_NETFILTER  	.socket_bind =			smack_socket_bind, +#endif /* CONFIG_SECURITY_SMACK_NETFILTER */  	.socket_connect =		smack_socket_connect,  	.socket_sendmsg =		smack_socket_sendmsg,  	.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))  		return 0; +	smack_enabled = 1; +  	smack_inode_cache = KMEM_CACHE(inode_smack, 0);  	if (!smack_inode_cache)  		return -ENOMEM; diff --git a/security/smack/smack_netfilter.c b/security/smack/smack_netfilter.c new file mode 100644 index 000000000000..c952632afb0d --- /dev/null +++ b/security/smack/smack_netfilter.c @@ -0,0 +1,96 @@ +/* + *  Simplified MAC Kernel (smack) security module + * + *  This file contains the Smack netfilter implementation + * + *  Author: + *	Casey Schaufler <[email protected]> + * + *  Copyright (C) 2014 Casey Schaufler <[email protected]> + *  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); |