diff options
Diffstat (limited to 'security')
-rw-r--r-- | security/dummy.c | 7 | ||||
-rw-r--r-- | security/selinux/hooks.c | 59 | ||||
-rw-r--r-- | security/selinux/include/objsec.h | 1 |
3 files changed, 67 insertions, 0 deletions
diff --git a/security/dummy.c b/security/dummy.c index 6ff88758647..e8a00fa8046 100644 --- a/security/dummy.c +++ b/security/dummy.c @@ -258,6 +258,12 @@ static void dummy_inode_free_security (struct inode *inode) return; } +static int dummy_inode_init_security (struct inode *inode, struct inode *dir, + char **name, void **value, size_t *len) +{ + return -EOPNOTSUPP; +} + static int dummy_inode_create (struct inode *inode, struct dentry *dentry, int mask) { @@ -886,6 +892,7 @@ void security_fixup_ops (struct security_operations *ops) set_to_dummy_if_null(ops, sb_post_pivotroot); set_to_dummy_if_null(ops, inode_alloc_security); set_to_dummy_if_null(ops, inode_free_security); + set_to_dummy_if_null(ops, inode_init_security); set_to_dummy_if_null(ops, inode_create); set_to_dummy_if_null(ops, inode_post_create); set_to_dummy_if_null(ops, inode_link); diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 8641f8894b4..63701fe0e1a 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -1274,6 +1274,7 @@ static int post_create(struct inode *dir, struct inode *inode; struct inode_security_struct *dsec; struct superblock_security_struct *sbsec; + struct inode_security_struct *isec; u32 newsid; char *context; unsigned int len; @@ -1293,6 +1294,11 @@ static int post_create(struct inode *dir, return 0; } + isec = inode->i_security; + + if (isec->security_attr_init) + return 0; + if (tsec->create_sid && sbsec->behavior != SECURITY_FS_USE_MNTPOINT) { newsid = tsec->create_sid; } else { @@ -2018,6 +2024,58 @@ static void selinux_inode_free_security(struct inode *inode) inode_free_security(inode); } +static int selinux_inode_init_security(struct inode *inode, struct inode *dir, + char **name, void **value, + size_t *len) +{ + struct task_security_struct *tsec; + struct inode_security_struct *dsec; + struct superblock_security_struct *sbsec; + struct inode_security_struct *isec; + u32 newsid; + int rc; + char *namep, *context; + + tsec = current->security; + dsec = dir->i_security; + sbsec = dir->i_sb->s_security; + isec = inode->i_security; + + if (tsec->create_sid && sbsec->behavior != SECURITY_FS_USE_MNTPOINT) { + newsid = tsec->create_sid; + } else { + rc = security_transition_sid(tsec->sid, dsec->sid, + inode_mode_to_security_class(inode->i_mode), + &newsid); + if (rc) { + printk(KERN_WARNING "%s: " + "security_transition_sid failed, rc=%d (dev=%s " + "ino=%ld)\n", + __FUNCTION__, + -rc, inode->i_sb->s_id, inode->i_ino); + return rc; + } + } + + inode_security_set_sid(inode, newsid); + + namep = kstrdup(XATTR_SELINUX_SUFFIX, GFP_KERNEL); + if (!namep) + return -ENOMEM; + *name = namep; + + rc = security_sid_to_context(newsid, &context, len); + if (rc) { + kfree(namep); + return rc; + } + *value = context; + + isec->security_attr_init = 1; + + return 0; +} + static int selinux_inode_create(struct inode *dir, struct dentry *dentry, int mask) { return may_create(dir, dentry, SECCLASS_FILE); @@ -4298,6 +4356,7 @@ static struct security_operations selinux_ops = { .inode_alloc_security = selinux_inode_alloc_security, .inode_free_security = selinux_inode_free_security, + .inode_init_security = selinux_inode_init_security, .inode_create = selinux_inode_create, .inode_post_create = selinux_inode_post_create, .inode_link = selinux_inode_link, diff --git a/security/selinux/include/objsec.h b/security/selinux/include/objsec.h index 887937c8134..c515bc0b58a 100644 --- a/security/selinux/include/objsec.h +++ b/security/selinux/include/objsec.h @@ -46,6 +46,7 @@ struct inode_security_struct { unsigned char initialized; /* initialization flag */ struct semaphore sem; unsigned char inherit; /* inherit SID from parent entry */ + unsigned char security_attr_init; /* security attributes init flag */ }; struct file_security_struct { |