diff options
| -rw-r--r-- | fs/overlayfs/copy_up.c | 22 | ||||
| -rw-r--r-- | fs/overlayfs/dir.c | 10 | ||||
| -rw-r--r-- | include/linux/lsm_hooks.h | 36 | ||||
| -rw-r--r-- | include/linux/security.h | 24 | ||||
| -rw-r--r-- | security/lsm_audit.c | 4 | ||||
| -rw-r--r-- | security/security.c | 27 | ||||
| -rw-r--r-- | security/selinux/Kconfig | 38 | ||||
| -rw-r--r-- | security/selinux/hooks.c | 90 | ||||
| -rw-r--r-- | security/selinux/include/security.h | 4 | ||||
| -rw-r--r-- | security/selinux/ss/conditional.c | 2 | ||||
| -rw-r--r-- | security/selinux/ss/ebitmap.c | 3 | ||||
| -rw-r--r-- | security/selinux/ss/policydb.c | 12 | ||||
| -rw-r--r-- | security/smack/smack_netfilter.c | 4 | 
13 files changed, 211 insertions, 65 deletions
diff --git a/fs/overlayfs/copy_up.c b/fs/overlayfs/copy_up.c index 54e5d6681786..cd65f12b3464 100644 --- a/fs/overlayfs/copy_up.c +++ b/fs/overlayfs/copy_up.c @@ -103,6 +103,13 @@ retry:  			goto retry;  		} +		error = security_inode_copy_up_xattr(name); +		if (error < 0 && error != -EOPNOTSUPP) +			break; +		if (error == 1) { +			error = 0; +			continue; /* Discard */ +		}  		error = vfs_setxattr(new, name, value, size, 0);  		if (error)  			break; @@ -246,6 +253,8 @@ static int ovl_copy_up_locked(struct dentry *workdir, struct dentry *upperdir,  	struct dentry *upper = NULL;  	umode_t mode = stat->mode;  	int err; +	const struct cred *old_creds = NULL; +	struct cred *new_creds = NULL;  	newdentry = ovl_lookup_temp(workdir, dentry);  	err = PTR_ERR(newdentry); @@ -258,10 +267,23 @@ static int ovl_copy_up_locked(struct dentry *workdir, struct dentry *upperdir,  	if (IS_ERR(upper))  		goto out1; +	err = security_inode_copy_up(dentry, &new_creds); +	if (err < 0) +		goto out2; + +	if (new_creds) +		old_creds = override_creds(new_creds); +  	/* Can't properly set mode on creation because of the umask */  	stat->mode &= S_IFMT;  	err = ovl_create_real(wdir, newdentry, stat, link, NULL, true);  	stat->mode = mode; + +	if (new_creds) { +		revert_creds(old_creds); +		put_cred(new_creds); +	} +  	if (err)  		goto out2; diff --git a/fs/overlayfs/dir.c b/fs/overlayfs/dir.c index 12bcd07b9e32..a155e52db9fe 100644 --- a/fs/overlayfs/dir.c +++ b/fs/overlayfs/dir.c @@ -435,6 +435,15 @@ static int ovl_create_or_link(struct dentry *dentry, struct inode *inode,  	if (override_cred) {  		override_cred->fsuid = inode->i_uid;  		override_cred->fsgid = inode->i_gid; +		if (!hardlink) { +			err = security_dentry_create_files_as(dentry, +					stat->mode, &dentry->d_name, old_cred, +					override_cred); +			if (err) { +				put_cred(override_cred); +				goto out_revert_creds; +			} +		}  		put_cred(override_creds(override_cred));  		put_cred(override_cred); @@ -445,6 +454,7 @@ static int ovl_create_or_link(struct dentry *dentry, struct inode *inode,  			err = ovl_create_over_whiteout(dentry, inode, stat,  							link, hardlink);  	} +out_revert_creds:  	revert_creds(old_cred);  	if (!err) {  		struct inode *realinode = d_inode(ovl_dentry_upper(dentry)); diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h index dc56ae3a68cd..558adfa5c8a8 100644 --- a/include/linux/lsm_hooks.h +++ b/include/linux/lsm_hooks.h @@ -151,6 +151,16 @@   *	@name name of the last path component used to create file   *	@ctx pointer to place the pointer to the resulting context in.   *	@ctxlen point to place the length of the resulting context. + * @dentry_create_files_as: + *	Compute a context for a dentry as the inode is not yet available + *	and set that context in passed in creds so that new files are + *	created using that context. Context is calculated using the + *	passed in creds and not the creds of the caller. + *	@dentry dentry to use in calculating the context. + *	@mode mode used to determine resource type. + *	@name name of the last path component used to create file + *	@old creds which should be used for context calculation + *	@new creds to modify   *   *   * Security hooks for inode operations. @@ -401,6 +411,23 @@   *	@inode contains a pointer to the inode.   *	@secid contains a pointer to the location where result will be saved.   *	In case of failure, @secid will be set to zero. + * @inode_copy_up: + *	A file is about to be copied up from lower layer to upper layer of + *	overlay filesystem. Security module can prepare a set of new creds + *	and modify as need be and return new creds. Caller will switch to + *	new creds temporarily to create new file and release newly allocated + *	creds. + *	@src indicates the union dentry of file that is being copied up. + *	@new pointer to pointer to return newly allocated creds. + *	Returns 0 on success or a negative error code on error. + * @inode_copy_up_xattr: + *	Filter the xattrs being copied up when a unioned file is copied + *	up from a lower layer to the union/overlay layer. + *	@name indicates the name of the xattr. + *	Returns 0 to accept the xattr, 1 to discard the xattr, -EOPNOTSUPP if + *	security module does not know about attribute or a negative error code + *	to abort the copy up. Note that the caller is responsible for reading + *	and writing the xattrs as this hook is merely a filter.   *   * Security hooks for file operations   * @@ -1358,6 +1385,10 @@ union security_list_options {  	int (*dentry_init_security)(struct dentry *dentry, int mode,  					const struct qstr *name, void **ctx,  					u32 *ctxlen); +	int (*dentry_create_files_as)(struct dentry *dentry, int mode, +					struct qstr *name, +					const struct cred *old, +					struct cred *new);  #ifdef CONFIG_SECURITY_PATH @@ -1425,6 +1456,8 @@ union security_list_options {  	int (*inode_listsecurity)(struct inode *inode, char *buffer,  					size_t buffer_size);  	void (*inode_getsecid)(struct inode *inode, u32 *secid); +	int (*inode_copy_up)(struct dentry *src, struct cred **new); +	int (*inode_copy_up_xattr)(const char *name);  	int (*file_permission)(struct file *file, int mask);  	int (*file_alloc_security)(struct file *file); @@ -1655,6 +1688,7 @@ struct security_hook_heads {  	struct list_head sb_clone_mnt_opts;  	struct list_head sb_parse_opts_str;  	struct list_head dentry_init_security; +	struct list_head dentry_create_files_as;  #ifdef CONFIG_SECURITY_PATH  	struct list_head path_unlink;  	struct list_head path_mkdir; @@ -1695,6 +1729,8 @@ struct security_hook_heads {  	struct list_head inode_setsecurity;  	struct list_head inode_listsecurity;  	struct list_head inode_getsecid; +	struct list_head inode_copy_up; +	struct list_head inode_copy_up_xattr;  	struct list_head file_permission;  	struct list_head file_alloc_security;  	struct list_head file_free_security; diff --git a/include/linux/security.h b/include/linux/security.h index 4c7412943b81..c2125e9093e8 100644 --- a/include/linux/security.h +++ b/include/linux/security.h @@ -242,6 +242,10 @@ int security_sb_parse_opts_str(char *options, struct security_mnt_opts *opts);  int security_dentry_init_security(struct dentry *dentry, int mode,  					const struct qstr *name, void **ctx,  					u32 *ctxlen); +int security_dentry_create_files_as(struct dentry *dentry, int mode, +					struct qstr *name, +					const struct cred *old, +					struct cred *new);  int security_inode_alloc(struct inode *inode);  void security_inode_free(struct inode *inode); @@ -282,6 +286,8 @@ int security_inode_getsecurity(struct inode *inode, const char *name, void **buf  int security_inode_setsecurity(struct inode *inode, const char *name, const void *value, size_t size, int flags);  int security_inode_listsecurity(struct inode *inode, char *buffer, size_t buffer_size);  void security_inode_getsecid(struct inode *inode, u32 *secid); +int security_inode_copy_up(struct dentry *src, struct cred **new); +int security_inode_copy_up_xattr(const char *name);  int security_file_permission(struct file *file, int mask);  int security_file_alloc(struct file *file);  void security_file_free(struct file *file); @@ -597,6 +603,14 @@ static inline int security_dentry_init_security(struct dentry *dentry,  	return -EOPNOTSUPP;  } +static inline int security_dentry_create_files_as(struct dentry *dentry, +						  int mode, struct qstr *name, +						  const struct cred *old, +						  struct cred *new) +{ +	return 0; +} +  static inline int security_inode_init_security(struct inode *inode,  						struct inode *dir, @@ -757,6 +771,16 @@ static inline void security_inode_getsecid(struct inode *inode, u32 *secid)  	*secid = 0;  } +static inline int security_inode_copy_up(struct dentry *src, struct cred **new) +{ +	return 0; +} + +static inline int security_inode_copy_up_xattr(const char *name) +{ +	return -EOPNOTSUPP; +} +  static inline int security_file_permission(struct file *file, int mask)  {  	return 0; diff --git a/security/lsm_audit.c b/security/lsm_audit.c index cccbf3068cdc..9bf851884800 100644 --- a/security/lsm_audit.c +++ b/security/lsm_audit.c @@ -99,7 +99,7 @@ int ipv4_skb_to_auditdata(struct sk_buff *skb,  	}  	return ret;  } -#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) +#if IS_ENABLED(CONFIG_IPV6)  /**   * ipv6_skb_to_auditdata : fill auditdata from skb   * @skb : the skb @@ -257,7 +257,7 @@ static void dump_common_audit_data(struct audit_buffer *ab,  			audit_log_format(ab, " ino=%lu", inode->i_ino);  		} -		audit_log_format(ab, " ioctlcmd=%hx", a->u.op->cmd); +		audit_log_format(ab, " ioctlcmd=0x%hx", a->u.op->cmd);  		break;  	}  	case LSM_AUDIT_DATA_DENTRY: { diff --git a/security/security.c b/security/security.c index 4838e7fefa1f..f825304f04a7 100644 --- a/security/security.c +++ b/security/security.c @@ -364,6 +364,15 @@ int security_dentry_init_security(struct dentry *dentry, int mode,  }  EXPORT_SYMBOL(security_dentry_init_security); +int security_dentry_create_files_as(struct dentry *dentry, int mode, +				    struct qstr *name, +				    const struct cred *old, struct cred *new) +{ +	return call_int_hook(dentry_create_files_as, 0, dentry, mode, +				name, old, new); +} +EXPORT_SYMBOL(security_dentry_create_files_as); +  int security_inode_init_security(struct inode *inode, struct inode *dir,  				 const struct qstr *qstr,  				 const initxattrs initxattrs, void *fs_data) @@ -748,6 +757,18 @@ void security_inode_getsecid(struct inode *inode, u32 *secid)  	call_void_hook(inode_getsecid, inode, secid);  } +int security_inode_copy_up(struct dentry *src, struct cred **new) +{ +	return call_int_hook(inode_copy_up, 0, src, new); +} +EXPORT_SYMBOL(security_inode_copy_up); + +int security_inode_copy_up_xattr(const char *name) +{ +	return call_int_hook(inode_copy_up_xattr, -EOPNOTSUPP, name); +} +EXPORT_SYMBOL(security_inode_copy_up_xattr); +  int security_file_permission(struct file *file, int mask)  {  	int ret; @@ -1623,6 +1644,8 @@ struct security_hook_heads security_hook_heads = {  		LIST_HEAD_INIT(security_hook_heads.sb_parse_opts_str),  	.dentry_init_security =  		LIST_HEAD_INIT(security_hook_heads.dentry_init_security), +	.dentry_create_files_as = +		LIST_HEAD_INIT(security_hook_heads.dentry_create_files_as),  #ifdef CONFIG_SECURITY_PATH  	.path_unlink =	LIST_HEAD_INIT(security_hook_heads.path_unlink),  	.path_mkdir =	LIST_HEAD_INIT(security_hook_heads.path_mkdir), @@ -1684,6 +1707,10 @@ struct security_hook_heads security_hook_heads = {  		LIST_HEAD_INIT(security_hook_heads.inode_listsecurity),  	.inode_getsecid =  		LIST_HEAD_INIT(security_hook_heads.inode_getsecid), +	.inode_copy_up = +		LIST_HEAD_INIT(security_hook_heads.inode_copy_up), +	.inode_copy_up_xattr = +		LIST_HEAD_INIT(security_hook_heads.inode_copy_up_xattr),  	.file_permission =  		LIST_HEAD_INIT(security_hook_heads.file_permission),  	.file_alloc_security = diff --git a/security/selinux/Kconfig b/security/selinux/Kconfig index 8691e92f27e5..ea7e3efbe0f7 100644 --- a/security/selinux/Kconfig +++ b/security/selinux/Kconfig @@ -93,41 +93,3 @@ config SECURITY_SELINUX_CHECKREQPROT_VALUE  	  via /selinux/checkreqprot if authorized by policy.  	  If you are unsure how to answer this question, answer 0. - -config SECURITY_SELINUX_POLICYDB_VERSION_MAX -	bool "NSA SELinux maximum supported policy format version" -	depends on SECURITY_SELINUX -	default n -	help -	  This option enables the maximum policy format version supported -	  by SELinux to be set to a particular value.  This value is reported -	  to userspace via /selinux/policyvers and used at policy load time. -	  It can be adjusted downward to support legacy userland (init) that -	  does not correctly handle kernels that support newer policy versions. - -	  Examples: -	  For the Fedora Core 3 or 4 Linux distributions, enable this option -	  and set the value via the next option. For Fedora Core 5 and later, -	  do not enable this option. - -	  If you are unsure how to answer this question, answer N. - -config SECURITY_SELINUX_POLICYDB_VERSION_MAX_VALUE -	int "NSA SELinux maximum supported policy format version value" -	depends on SECURITY_SELINUX_POLICYDB_VERSION_MAX -	range 15 23 -	default 19 -	help -	  This option sets the value for the maximum policy format version -	  supported by SELinux. - -	  Examples: -	  For Fedora Core 3, use 18. -	  For Fedora Core 4, use 19. - -	  If you are unsure how to answer this question, look for the -	  policy format version supported by your policy toolchain, by -	  running 'checkpolicy -V'. Or look at what policy you have -	  installed under /etc/selinux/$SELINUXTYPE/policy, where -	  SELINUXTYPE is defined in your /etc/selinux/config. - diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 13185a6c266a..e15e56081c0c 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -1808,13 +1808,13 @@ out:  /*   * Determine the label for an inode that might be unioned.   */ -static int selinux_determine_inode_label(struct inode *dir, -					 const struct qstr *name, -					 u16 tclass, -					 u32 *_new_isid) +static int +selinux_determine_inode_label(const struct task_security_struct *tsec, +				 struct inode *dir, +				 const struct qstr *name, u16 tclass, +				 u32 *_new_isid)  {  	const struct superblock_security_struct *sbsec = dir->i_sb->s_security; -	const struct task_security_struct *tsec = current_security();  	if ((sbsec->flags & SE_SBINITIALIZED) &&  	    (sbsec->behavior == SECURITY_FS_USE_MNTPOINT)) { @@ -1857,8 +1857,8 @@ static int may_create(struct inode *dir,  	if (rc)  		return rc; -	rc = selinux_determine_inode_label(dir, &dentry->d_name, tclass, -					   &newsid); +	rc = selinux_determine_inode_label(current_security(), dir, +					   &dentry->d_name, tclass, &newsid);  	if (rc)  		return rc; @@ -2838,7 +2838,8 @@ static int selinux_dentry_init_security(struct dentry *dentry, int mode,  	u32 newsid;  	int rc; -	rc = selinux_determine_inode_label(d_inode(dentry->d_parent), name, +	rc = selinux_determine_inode_label(current_security(), +					   d_inode(dentry->d_parent), name,  					   inode_mode_to_security_class(mode),  					   &newsid);  	if (rc) @@ -2847,6 +2848,27 @@ static int selinux_dentry_init_security(struct dentry *dentry, int mode,  	return security_sid_to_context(newsid, (char **)ctx, ctxlen);  } +static int selinux_dentry_create_files_as(struct dentry *dentry, int mode, +					  struct qstr *name, +					  const struct cred *old, +					  struct cred *new) +{ +	u32 newsid; +	int rc; +	struct task_security_struct *tsec; + +	rc = selinux_determine_inode_label(old->security, +					   d_inode(dentry->d_parent), name, +					   inode_mode_to_security_class(mode), +					   &newsid); +	if (rc) +		return rc; + +	tsec = new->security; +	tsec->create_sid = newsid; +	return 0; +} +  static int selinux_inode_init_security(struct inode *inode, struct inode *dir,  				       const struct qstr *qstr,  				       const char **name, @@ -2863,7 +2885,7 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir,  	sid = tsec->sid;  	newsid = tsec->create_sid; -	rc = selinux_determine_inode_label( +	rc = selinux_determine_inode_label(current_security(),  		dir, qstr,  		inode_mode_to_security_class(inode->i_mode),  		&newsid); @@ -3293,6 +3315,41 @@ static void selinux_inode_getsecid(struct inode *inode, u32 *secid)  	*secid = isec->sid;  } +static int selinux_inode_copy_up(struct dentry *src, struct cred **new) +{ +	u32 sid; +	struct task_security_struct *tsec; +	struct cred *new_creds = *new; + +	if (new_creds == NULL) { +		new_creds = prepare_creds(); +		if (!new_creds) +			return -ENOMEM; +	} + +	tsec = new_creds->security; +	/* Get label from overlay inode and set it in create_sid */ +	selinux_inode_getsecid(d_inode(src), &sid); +	tsec->create_sid = sid; +	*new = new_creds; +	return 0; +} + +static int selinux_inode_copy_up_xattr(const char *name) +{ +	/* The copy_up hook above sets the initial context on an inode, but we +	 * don't then want to overwrite it by blindly copying all the lower +	 * xattrs up.  Instead, we have to filter out SELinux-related xattrs. +	 */ +	if (strcmp(name, XATTR_NAME_SELINUX) == 0) +		return 1; /* Discard */ +	/* +	 * Any other attribute apart from SELINUX is not claimed, supported +	 * by selinux. +	 */ +	return -EOPNOTSUPP; +} +  /* file security operations */  static int selinux_revalidate_file_permission(struct file *file, int mask) @@ -3984,7 +4041,7 @@ out:  	return ret;  } -#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) +#if IS_ENABLED(CONFIG_IPV6)  /* Returns error only if unable to parse addresses */  static int selinux_parse_skb_ipv6(struct sk_buff *skb, @@ -4075,7 +4132,7 @@ static int selinux_parse_skb(struct sk_buff *skb, struct common_audit_data *ad,  				       &ad->u.net->v4info.daddr);  		goto okay; -#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) +#if IS_ENABLED(CONFIG_IPV6)  	case PF_INET6:  		ret = selinux_parse_skb_ipv6(skb, ad, proto);  		if (ret) @@ -5029,7 +5086,7 @@ static unsigned int selinux_ipv4_forward(void *priv,  	return selinux_ip_forward(skb, state->in, PF_INET);  } -#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) +#if IS_ENABLED(CONFIG_IPV6)  static unsigned int selinux_ipv6_forward(void *priv,  					 struct sk_buff *skb,  					 const struct nf_hook_state *state) @@ -5087,7 +5144,7 @@ static unsigned int selinux_ipv4_output(void *priv,  	return selinux_ip_output(skb, PF_INET);  } -#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) +#if IS_ENABLED(CONFIG_IPV6)  static unsigned int selinux_ipv6_output(void *priv,  					struct sk_buff *skb,  					const struct nf_hook_state *state) @@ -5273,7 +5330,7 @@ static unsigned int selinux_ipv4_postroute(void *priv,  	return selinux_ip_postroute(skb, state->out, PF_INET);  } -#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) +#if IS_ENABLED(CONFIG_IPV6)  static unsigned int selinux_ipv6_postroute(void *priv,  					   struct sk_buff *skb,  					   const struct nf_hook_state *state) @@ -6062,6 +6119,7 @@ static struct security_hook_list selinux_hooks[] = {  	LSM_HOOK_INIT(sb_parse_opts_str, selinux_parse_opts_str),  	LSM_HOOK_INIT(dentry_init_security, selinux_dentry_init_security), +	LSM_HOOK_INIT(dentry_create_files_as, selinux_dentry_create_files_as),  	LSM_HOOK_INIT(inode_alloc_security, selinux_inode_alloc_security),  	LSM_HOOK_INIT(inode_free_security, selinux_inode_free_security), @@ -6088,6 +6146,8 @@ static struct security_hook_list selinux_hooks[] = {  	LSM_HOOK_INIT(inode_setsecurity, selinux_inode_setsecurity),  	LSM_HOOK_INIT(inode_listsecurity, selinux_inode_listsecurity),  	LSM_HOOK_INIT(inode_getsecid, selinux_inode_getsecid), +	LSM_HOOK_INIT(inode_copy_up, selinux_inode_copy_up), +	LSM_HOOK_INIT(inode_copy_up_xattr, selinux_inode_copy_up_xattr),  	LSM_HOOK_INIT(file_permission, selinux_file_permission),  	LSM_HOOK_INIT(file_alloc_security, selinux_file_alloc_security), @@ -6317,7 +6377,7 @@ static struct nf_hook_ops selinux_nf_ops[] = {  		.hooknum =	NF_INET_LOCAL_OUT,  		.priority =	NF_IP_PRI_SELINUX_FIRST,  	}, -#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) +#if IS_ENABLED(CONFIG_IPV6)  	{  		.hook =		selinux_ipv6_postroute,  		.pf =		NFPROTO_IPV6, diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h index 38feb55d531a..308a286c6cbe 100644 --- a/security/selinux/include/security.h +++ b/security/selinux/include/security.h @@ -39,11 +39,7 @@  /* Range of policy versions we understand*/  #define POLICYDB_VERSION_MIN   POLICYDB_VERSION_BASE -#ifdef CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX -#define POLICYDB_VERSION_MAX	CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX_VALUE -#else  #define POLICYDB_VERSION_MAX	POLICYDB_VERSION_XPERMS_IOCTL -#endif  /* Mask for just the mount related flags */  #define SE_MNTMASK	0x0f diff --git a/security/selinux/ss/conditional.c b/security/selinux/ss/conditional.c index 456e1a9bcfde..34afeadd9e73 100644 --- a/security/selinux/ss/conditional.c +++ b/security/selinux/ss/conditional.c @@ -242,6 +242,8 @@ int cond_read_bool(struct policydb *p, struct hashtab *h, void *fp)  		goto err;  	len = le32_to_cpu(buf[2]); +	if (((len == 0) || (len == (u32)-1))) +		goto err;  	rc = -ENOMEM;  	key = kmalloc(len + 1, GFP_KERNEL); diff --git a/security/selinux/ss/ebitmap.c b/security/selinux/ss/ebitmap.c index 894b6cdc11c5..7d10e5d418bb 100644 --- a/security/selinux/ss/ebitmap.c +++ b/security/selinux/ss/ebitmap.c @@ -374,6 +374,9 @@ int ebitmap_read(struct ebitmap *e, void *fp)  		goto ok;  	} +	if (e->highbit && !count) +		goto bad; +  	for (i = 0; i < count; i++) {  		rc = next_entry(&startbit, fp, sizeof(u32));  		if (rc < 0) { diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c index 992a31530825..ace683838d80 100644 --- a/security/selinux/ss/policydb.c +++ b/security/selinux/ss/policydb.c @@ -541,21 +541,21 @@ static int policydb_index(struct policydb *p)  	rc = -ENOMEM;  	p->class_val_to_struct = -		kmalloc(p->p_classes.nprim * sizeof(*(p->class_val_to_struct)), +		kzalloc(p->p_classes.nprim * sizeof(*(p->class_val_to_struct)),  			GFP_KERNEL);  	if (!p->class_val_to_struct)  		goto out;  	rc = -ENOMEM;  	p->role_val_to_struct = -		kmalloc(p->p_roles.nprim * sizeof(*(p->role_val_to_struct)), +		kzalloc(p->p_roles.nprim * sizeof(*(p->role_val_to_struct)),  			GFP_KERNEL);  	if (!p->role_val_to_struct)  		goto out;  	rc = -ENOMEM;  	p->user_val_to_struct = -		kmalloc(p->p_users.nprim * sizeof(*(p->user_val_to_struct)), +		kzalloc(p->p_users.nprim * sizeof(*(p->user_val_to_struct)),  			GFP_KERNEL);  	if (!p->user_val_to_struct)  		goto out; @@ -964,7 +964,7 @@ int policydb_context_isvalid(struct policydb *p, struct context *c)  		 * Role must be authorized for the type.  		 */  		role = p->role_val_to_struct[c->role - 1]; -		if (!ebitmap_get_bit(&role->types, c->type - 1)) +		if (!role || !ebitmap_get_bit(&role->types, c->type - 1))  			/* role may not be associated with type */  			return 0; @@ -1094,6 +1094,9 @@ static int str_read(char **strp, gfp_t flags, void *fp, u32 len)  	int rc;  	char *str; +	if ((len == 0) || (len == (u32)-1)) +		return -EINVAL; +  	str = kmalloc(len + 1, flags);  	if (!str)  		return -ENOMEM; @@ -2414,6 +2417,7 @@ int policydb_read(struct policydb *p, void *fp)  		} else  			tr->tclass = p->process_class; +		rc = -EINVAL;  		if (!policydb_role_isvalid(p, tr->role) ||  		    !policydb_type_isvalid(p, tr->type) ||  		    !policydb_class_isvalid(p, tr->tclass) || diff --git a/security/smack/smack_netfilter.c b/security/smack/smack_netfilter.c index aa6bf1b22ec5..205b785fb400 100644 --- a/security/smack/smack_netfilter.c +++ b/security/smack/smack_netfilter.c @@ -20,7 +20,7 @@  #include <net/inet_sock.h>  #include "smack.h" -#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) +#if IS_ENABLED(CONFIG_IPV6)  static unsigned int smack_ipv6_output(void *priv,  					struct sk_buff *skb, @@ -64,7 +64,7 @@ static struct nf_hook_ops smack_nf_ops[] = {  		.hooknum =	NF_INET_LOCAL_OUT,  		.priority =	NF_IP_PRI_SELINUX_FIRST,  	}, -#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) +#if IS_ENABLED(CONFIG_IPV6)  	{  		.hook =		smack_ipv6_output,  		.pf =		NFPROTO_IPV6,  | 
