diff options
Diffstat (limited to 'security-selinux-overlayfs-support.patch')
-rw-r--r-- | security-selinux-overlayfs-support.patch | 931 |
1 files changed, 931 insertions, 0 deletions
diff --git a/security-selinux-overlayfs-support.patch b/security-selinux-overlayfs-support.patch new file mode 100644 index 000000000..7149e4566 --- /dev/null +++ b/security-selinux-overlayfs-support.patch @@ -0,0 +1,931 @@ +From 1a93a6eac32a2853177f10e274b9b761b42356eb Mon Sep 17 00:00:00 2001 +From: Javier Martinez Canillas <javier@osg.samsung.com> +Date: Mon, 8 Aug 2016 13:08:25 -0400 +Subject: [PATCH 01/10] security: Use IS_ENABLED() instead of checking for + built-in or module + +The IS_ENABLED() macro checks if a Kconfig symbol has been enabled +either built-in or as a module, use that macro instead of open coding +the same. + +Signed-off-by: Javier Martinez Canillas <javier@osg.samsung.com> +Acked-by: Casey Schaufler <casey@schaufler-ca.com> +Signed-off-by: Paul Moore <paul@paul-moore.com> +--- + security/lsm_audit.c | 2 +- + security/selinux/hooks.c | 12 ++++++------ + security/smack/smack_netfilter.c | 4 ++-- + 3 files changed, 9 insertions(+), 9 deletions(-) + +diff --git a/security/lsm_audit.c b/security/lsm_audit.c +index cccbf30..5369036 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 +diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c +index 13185a6..880f953 100644 +--- a/security/selinux/hooks.c ++++ b/security/selinux/hooks.c +@@ -3984,7 +3984,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 +4075,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 +5029,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 +5087,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 +5273,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) +@@ -6317,7 +6317,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/smack/smack_netfilter.c b/security/smack/smack_netfilter.c +index aa6bf1b..205b785 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, +-- +2.7.4 + +From 8b31f456c72e53ee97474a538bcd91bfb1b93fb7 Mon Sep 17 00:00:00 2001 +From: William Roberts <william.c.roberts@intel.com> +Date: Mon, 8 Aug 2016 13:08:34 -0400 +Subject: [PATCH 02/10] selinux: print leading 0x on ioctlcmd audits + +ioctlcmd is currently printing hex numbers, but their is no leading +0x. Thus things like ioctlcmd=1234 are misleading, as the base is +not evident. + +Correct this by adding 0x as a prefix, so ioctlcmd=1234 becomes +ioctlcmd=0x1234. + +Signed-off-by: William Roberts <william.c.roberts@intel.com> +Signed-off-by: Paul Moore <paul@paul-moore.com> +--- + security/lsm_audit.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/security/lsm_audit.c b/security/lsm_audit.c +index 5369036..9bf8518 100644 +--- a/security/lsm_audit.c ++++ b/security/lsm_audit.c +@@ -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: { +-- +2.7.4 + +From d8ad8b49618410ddeafd78465b63a6cedd6c9484 Mon Sep 17 00:00:00 2001 +From: Vivek Goyal <vgoyal@redhat.com> +Date: Wed, 13 Jul 2016 11:13:56 -0400 +Subject: [PATCH 03/10] security, overlayfs: provide copy up security hook for + unioned files + +Provide a security hook to label new file correctly when a file is copied +up from lower layer to upper layer of a overlay/union mount. + +This hook can prepare a new set of creds which are suitable for new file +creation during copy up. Caller will use new creds to create file and then +revert back to old creds and release new creds. + +Signed-off-by: Vivek Goyal <vgoyal@redhat.com> +Acked-by: Stephen Smalley <sds@tycho.nsa.gov> +[PM: whitespace cleanup to appease checkpatch.pl] +Signed-off-by: Paul Moore <paul@paul-moore.com> +--- + fs/overlayfs/copy_up.c | 15 +++++++++++++++ + include/linux/lsm_hooks.h | 11 +++++++++++ + include/linux/security.h | 6 ++++++ + security/security.c | 8 ++++++++ + 4 files changed, 40 insertions(+) + +diff --git a/fs/overlayfs/copy_up.c b/fs/overlayfs/copy_up.c +index 54e5d66..c297b1f 100644 +--- a/fs/overlayfs/copy_up.c ++++ b/fs/overlayfs/copy_up.c +@@ -246,6 +246,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 +260,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/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h +index 101bf19..cb69fc8 100644 +--- a/include/linux/lsm_hooks.h ++++ b/include/linux/lsm_hooks.h +@@ -401,6 +401,15 @@ + * @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. + * + * Security hooks for file operations + * +@@ -1425,6 +1434,7 @@ 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 (*file_permission)(struct file *file, int mask); + int (*file_alloc_security)(struct file *file); +@@ -1696,6 +1706,7 @@ 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 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 7831cd5..c5b0ccd 100644 +--- a/include/linux/security.h ++++ b/include/linux/security.h +@@ -282,6 +282,7 @@ 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_file_permission(struct file *file, int mask); + int security_file_alloc(struct file *file); + void security_file_free(struct file *file); +@@ -758,6 +759,11 @@ 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_file_permission(struct file *file, int mask) + { + return 0; +diff --git a/security/security.c b/security/security.c +index 4838e7f..f2a7f27 100644 +--- a/security/security.c ++++ b/security/security.c +@@ -748,6 +748,12 @@ 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_file_permission(struct file *file, int mask) + { + int ret; +@@ -1684,6 +1690,8 @@ 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), + .file_permission = + LIST_HEAD_INIT(security_hook_heads.file_permission), + .file_alloc_security = +-- +2.7.4 + +From 56909eb3f559103196ecbf2c08c923e0804980fb Mon Sep 17 00:00:00 2001 +From: Vivek Goyal <vgoyal@redhat.com> +Date: Wed, 13 Jul 2016 10:44:48 -0400 +Subject: [PATCH 04/10] selinux: Implementation for inode_copy_up() hook + +A file is being copied up for overlay file system. Prepare a new set of +creds and set create_sid appropriately so that new file is created with +appropriate label. + +Overlay inode has right label for both context and non-context mount +cases. In case of non-context mount, overlay inode will have the label +of lower file and in case of context mount, overlay inode will have +the label from context= mount option. + +Signed-off-by: Vivek Goyal <vgoyal@redhat.com> +Acked-by: Stephen Smalley <sds@tycho.nsa.gov> +Signed-off-by: Paul Moore <paul@paul-moore.com> +--- + security/selinux/hooks.c | 21 +++++++++++++++++++++ + 1 file changed, 21 insertions(+) + +diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c +index 880f953..40597ed 100644 +--- a/security/selinux/hooks.c ++++ b/security/selinux/hooks.c +@@ -3293,6 +3293,26 @@ 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; ++} ++ + /* file security operations */ + + static int selinux_revalidate_file_permission(struct file *file, int mask) +@@ -6088,6 +6108,7 @@ 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(file_permission, selinux_file_permission), + LSM_HOOK_INIT(file_alloc_security, selinux_file_alloc_security), +-- +2.7.4 + +From 121ab822ef21914adac2fa3730efeeb8fd762473 Mon Sep 17 00:00:00 2001 +From: Vivek Goyal <vgoyal@redhat.com> +Date: Wed, 13 Jul 2016 10:44:49 -0400 +Subject: [PATCH 05/10] security,overlayfs: Provide security hook for copy up + of xattrs for overlay file + +Provide a security hook which is called when xattrs of a file are being +copied up. This hook is called once for each xattr and LSM can return +0 if the security module wants the xattr to be copied up, 1 if the +security module wants the xattr to be discarded on the copy, -EOPNOTSUPP +if the security module does not handle/manage the xattr, or a -errno +upon an error. + +Signed-off-by: David Howells <dhowells@redhat.com> +Signed-off-by: Vivek Goyal <vgoyal@redhat.com> +Acked-by: Stephen Smalley <sds@tycho.nsa.gov> +[PM: whitespace cleanup for checkpatch.pl] +Signed-off-by: Paul Moore <paul@paul-moore.com> +--- + fs/overlayfs/copy_up.c | 7 +++++++ + include/linux/lsm_hooks.h | 10 ++++++++++ + include/linux/security.h | 6 ++++++ + security/security.c | 8 ++++++++ + 4 files changed, 31 insertions(+) + +diff --git a/fs/overlayfs/copy_up.c b/fs/overlayfs/copy_up.c +index c297b1f..cd65f12 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; +diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h +index cb69fc8..5797122 100644 +--- a/include/linux/lsm_hooks.h ++++ b/include/linux/lsm_hooks.h +@@ -410,6 +410,14 @@ + * @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 + * +@@ -1435,6 +1443,7 @@ union security_list_options { + 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); +@@ -1707,6 +1716,7 @@ struct security_hook_heads { + 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 c5b0ccd..536fafd 100644 +--- a/include/linux/security.h ++++ b/include/linux/security.h +@@ -283,6 +283,7 @@ int security_inode_setsecurity(struct inode *inode, const char *name, const void + 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); +@@ -764,6 +765,11 @@ 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/security.c b/security/security.c +index f2a7f27..a9e2bb9 100644 +--- a/security/security.c ++++ b/security/security.c +@@ -754,6 +754,12 @@ int security_inode_copy_up(struct dentry *src, struct cred **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; +@@ -1692,6 +1698,8 @@ struct security_hook_heads security_hook_heads = { + 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 = +-- +2.7.4 + +From 19472b69d639d58415866bf127d5f9005038c105 Mon Sep 17 00:00:00 2001 +From: Vivek Goyal <vgoyal@redhat.com> +Date: Wed, 13 Jul 2016 10:44:50 -0400 +Subject: [PATCH 06/10] selinux: Implementation for inode_copy_up_xattr() hook + +When a file is copied up in overlay, we have already created file on +upper/ with right label and there is no need to copy up selinux +label/xattr from lower file to upper file. In fact in case of context +mount, we don't want to copy up label as newly created file got its label +from context= option. + +Signed-off-by: Vivek Goyal <vgoyal@redhat.com> +Acked-by: Stephen Smalley <sds@tycho.nsa.gov> +Signed-off-by: Paul Moore <paul@paul-moore.com> +--- + security/selinux/hooks.c | 16 ++++++++++++++++ + 1 file changed, 16 insertions(+) + +diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c +index 40597ed..a2d5108 100644 +--- a/security/selinux/hooks.c ++++ b/security/selinux/hooks.c +@@ -3313,6 +3313,21 @@ static int selinux_inode_copy_up(struct dentry *src, struct cred **new) + 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) +@@ -6109,6 +6124,7 @@ static struct security_hook_list selinux_hooks[] = { + 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), +-- +2.7.4 + +From c957f6df52c509ccfbb96659fd1a0f7812de333f Mon Sep 17 00:00:00 2001 +From: Vivek Goyal <vgoyal@redhat.com> +Date: Wed, 13 Jul 2016 10:44:51 -0400 +Subject: [PATCH 07/10] selinux: Pass security pointer to + determine_inode_label() + +Right now selinux_determine_inode_label() works on security pointer of +current task. Soon I need this to work on a security pointer retrieved +from a set of creds. So start passing in a pointer and caller can +decide where to fetch security pointer from. + +Signed-off-by: Vivek Goyal <vgoyal@redhat.com> +Acked-by: Stephen Smalley <sds@tycho.nsa.gov> +Signed-off-by: Paul Moore <paul@paul-moore.com> +--- + security/selinux/hooks.c | 19 ++++++++++--------- + 1 file changed, 10 insertions(+), 9 deletions(-) + +diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c +index a2d5108..f9d398b 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) +@@ -2863,7 +2864,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); +-- +2.7.4 + +From 2602625b7e46576b00db619ac788c508ba3bcb2c Mon Sep 17 00:00:00 2001 +From: Vivek Goyal <vgoyal@redhat.com> +Date: Wed, 13 Jul 2016 10:44:52 -0400 +Subject: [PATCH 08/10] security, overlayfs: Provide hook to correctly label + newly created files + +During a new file creation we need to make sure new file is created with the +right label. New file is created in upper/ so effectively file should get +label as if task had created file in upper/. + +We switched to mounter's creds for actual file creation. Also if there is a +whiteout present, then file will be created in work/ dir first and then +renamed in upper. In none of the cases file will be labeled as we want it to +be. + +This patch introduces a new hook dentry_create_files_as(), which determines +the label/context dentry will get if it had been created by task in upper +and modify passed set of creds appropriately. Caller makes use of these new +creds for file creation. + +Signed-off-by: Vivek Goyal <vgoyal@redhat.com> +Acked-by: Stephen Smalley <sds@tycho.nsa.gov> +[PM: fix whitespace issues found with checkpatch.pl] +[PM: changes to use stat->mode in ovl_create_or_link()] +Signed-off-by: Paul Moore <paul@paul-moore.com> +--- + fs/overlayfs/dir.c | 10 ++++++++++ + include/linux/lsm_hooks.h | 15 +++++++++++++++ + include/linux/security.h | 12 ++++++++++++ + security/security.c | 11 +++++++++++ + 4 files changed, 48 insertions(+) + +diff --git a/fs/overlayfs/dir.c b/fs/overlayfs/dir.c +index 12bcd07..a155e52 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 5797122..f2af2af 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. +@@ -1375,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 +@@ -1675,6 +1689,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; +diff --git a/include/linux/security.h b/include/linux/security.h +index 536fafd..a6c6d5d 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); +@@ -600,6 +604,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, +diff --git a/security/security.c b/security/security.c +index a9e2bb9..f825304 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) +@@ -1635,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), +-- +2.7.4 + +From a518b0a5b0d7f3397e065acb956bca9635aa892d Mon Sep 17 00:00:00 2001 +From: Vivek Goyal <vgoyal@redhat.com> +Date: Wed, 13 Jul 2016 10:44:53 -0400 +Subject: [PATCH 09/10] selinux: Implement dentry_create_files_as() hook + +Calculate what would be the label of newly created file and set that +secid in the passed creds. + +Context of the task which is actually creating file is retrieved from +set of creds passed in. (old->security). + +Signed-off-by: Vivek Goyal <vgoyal@redhat.com> +Acked-by: Stephen Smalley <sds@tycho.nsa.gov> +Signed-off-by: Paul Moore <paul@paul-moore.com> +--- + security/selinux/hooks.c | 22 ++++++++++++++++++++++ + 1 file changed, 22 insertions(+) + +diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c +index f9d398b..e15e560 100644 +--- a/security/selinux/hooks.c ++++ b/security/selinux/hooks.c +@@ -2848,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, +@@ -6098,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), +-- +2.7.4 + +From 348a0db9e69e4c214bf5d7677f17cb99cdc47db0 Mon Sep 17 00:00:00 2001 +From: William Roberts <william.c.roberts@intel.com> +Date: Mon, 15 Aug 2016 12:42:12 -0700 +Subject: [PATCH 10/10] selinux: drop SECURITY_SELINUX_POLICYDB_VERSION_MAX + +Remove the SECURITY_SELINUX_POLICYDB_VERSION_MAX Kconfig option + +Per: https://github.com/SELinuxProject/selinux/wiki/Kernel-Todo + +This was only needed on Fedora 3 and 4 and just causes issues now, +so drop it. + +The MAX and MIN should just be whatever the kernel can support. + +Signed-off-by: William Roberts <william.c.roberts@intel.com> +Signed-off-by: Paul Moore <paul@paul-moore.com> +--- + security/selinux/Kconfig | 38 ------------------------------------- + security/selinux/include/security.h | 4 ---- + 2 files changed, 42 deletions(-) + +diff --git a/security/selinux/Kconfig b/security/selinux/Kconfig +index 8691e92..ea7e3ef 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/include/security.h b/security/selinux/include/security.h +index 38feb55..308a286 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 +-- +2.7.4 + |