|
@@ -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,
|