Discussion:
[PATCH v16 0/4] LSM: Generalize existing module stacking
Casey Schaufler
2014-08-08 19:23:23 UTC
Permalink
Subject: [PATCH v15 0/3] LSM: Generalize existing module stacking

There are currently two different mechanisms used to
stack security modules. The capability module is set
up as the "default" module. The other modules that
replace it call the functions it contains directly.
The Yama module is stacked using ifdefs in the security
infrastructure.

This patch set changes the existing module stacking so that
all stacking gets done the same way. There is no
"default" module, instead there is a list of modules
for each hook. The capability module is now on the
list first. If Yama stacking is configured, that is
added to the list next. Finally, if another module is
configured it gets added to the lists. The capability
calls duplicated within existing LSMs have been
removed. Not all capability calls in other modules can
be treated this way, and the individual cases are
noted.

The fourth patch is motivated by a discussion I had
with Linus about LSM performance. We can get significant
performance improvement if we put the LSM inode data
into the inode rather than maintaining a pointer to
data that is allocated and freed separately. Rather
than having an i_security entry there is now a structure
for each LSM that needs one, i_selinux and i_smack for
the time being.

The downside is that there are more LSM configuration
ifdefs in header files. There are tricks that could
be used to reduce them, but they really make the code
ugly. Uglier than the ifdefs, by quite a margin. If you
configure LSMs that you're not using, the structures
get slightly bigger. That is more than offset by the
performance improvement gained by the inode change.

Signed-off-by: Casey Schaufler <***@schaufler-ca.com>

---

fs/nfs/inode.c | 14 +-
include/linux/fs.h | 13 +-
include/linux/security.h | 17 +-
include/linux/selinux.h | 13 +
include/linux/smack.h | 38 +
security/Makefile | 2 +-
security/apparmor/domain.c | 4 +-
security/apparmor/lsm.c | 20 +-
security/capability.c | 1131 ------------------------------
security/commoncap.c | 34 +
security/security.c | 1592 +++++++++++++++++++++++++++++++++++-------
security/selinux/hooks.c | 184 ++---
security/selinux/selinuxfs.c | 8 +-
security/smack/smack.h | 22 +-
security/smack/smack_lsm.c | 103 +--
security/tomoyo/tomoyo.c | 6 -
security/yama/yama_lsm.c | 36 +-
17 files changed, 1571 insertions(+), 1666 deletions(-)

--
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
the body of a message to ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Casey Schaufler
2014-08-08 20:00:16 UTC
Permalink
Subject: [PATCH v16 1/4] LSM: Macroize security hooks

The security hooks are called by accessing the relevant
entry in the security_ops structure. Placing the calls into
a macro does nothing to the performance (it should generate
identical code) and sets the stage for a more sophisticated
calling scheme.

Signed-off-by: Casey Schaufler <***@schaufler-ca.com>

---
security/security.c | 428 +++++++++++++++++++++++++++------------------------
1 file changed, 227 insertions(+), 201 deletions(-)

diff --git a/security/security.c b/security/security.c
index 31614e9..b8c14d0 100644
--- a/security/security.c
+++ b/security/security.c
@@ -129,10 +129,22 @@ int __init register_security(struct security_operations *ops)
return -EAGAIN;

security_ops = ops;
-
return 0;
}

+/*
+ * Hook operation macros.
+ *
+ * call_void_hook:
+ * This is a hook that does not return a value.
+ *
+ * call_int_hook:
+ * This is a hook that returns a value.
+ */
+
+#define call_void_hook(FUNC, ...) security_ops->FUNC(__VA_ARGS__)
+#define call_int_hook(FUNC, ...) security_ops->FUNC(__VA_ARGS__)
+
/* Security operations */

int security_ptrace_access_check(struct task_struct *child, unsigned int mode)
@@ -143,7 +155,7 @@ int security_ptrace_access_check(struct task_struct *child, unsigned int mode)
if (rc)
return rc;
#endif
- return security_ops->ptrace_access_check(child, mode);
+ return call_int_hook(ptrace_access_check, child, mode);
}

int security_ptrace_traceme(struct task_struct *parent)
@@ -154,7 +166,7 @@ int security_ptrace_traceme(struct task_struct *parent)
if (rc)
return rc;
#endif
- return security_ops->ptrace_traceme(parent);
+ return call_int_hook(ptrace_traceme, parent);
}

int security_capget(struct task_struct *target,
@@ -162,7 +174,7 @@ int security_capget(struct task_struct *target,
kernel_cap_t *inheritable,
kernel_cap_t *permitted)
{
- return security_ops->capget(target, effective, inheritable, permitted);
+ return call_int_hook(capget, target, effective, inheritable, permitted);
}

int security_capset(struct cred *new, const struct cred *old,
@@ -170,57 +182,61 @@ int security_capset(struct cred *new, const struct cred *old,
const kernel_cap_t *inheritable,
const kernel_cap_t *permitted)
{
- return security_ops->capset(new, old,
+ return call_int_hook(capset, new, old,
effective, inheritable, permitted);
}

int security_capable(const struct cred *cred, struct user_namespace *ns,
int cap)
{
- return security_ops->capable(cred, ns, cap, SECURITY_CAP_AUDIT);
+ return call_int_hook(capable, cred, ns, cap, SECURITY_CAP_AUDIT);
}

+/*
+ * This is special because there is no capable_noaudit
+ * the the hooks list
+ */
int security_capable_noaudit(const struct cred *cred, struct user_namespace *ns,
int cap)
{
- return security_ops->capable(cred, ns, cap, SECURITY_CAP_NOAUDIT);
+ return call_int_hook(capable, cred, ns, cap, SECURITY_CAP_NOAUDIT);
}

int security_quotactl(int cmds, int type, int id, struct super_block *sb)
{
- return security_ops->quotactl(cmds, type, id, sb);
+ return call_int_hook(quotactl, cmds, type, id, sb);
}

int security_quota_on(struct dentry *dentry)
{
- return security_ops->quota_on(dentry);
+ return call_int_hook(quota_on, dentry);
}

int security_syslog(int type)
{
- return security_ops->syslog(type);
+ return call_int_hook(syslog, type);
}

int security_settime(const struct timespec *ts, const struct timezone *tz)
{
- return security_ops->settime(ts, tz);
+ return call_int_hook(settime, ts, tz);
}

int security_vm_enough_memory_mm(struct mm_struct *mm, long pages)
{
- return security_ops->vm_enough_memory(mm, pages);
+ return call_int_hook(vm_enough_memory, mm, pages);
}

int security_bprm_set_creds(struct linux_binprm *bprm)
{
- return security_ops->bprm_set_creds(bprm);
+ return call_int_hook(bprm_set_creds, bprm);
}

int security_bprm_check(struct linux_binprm *bprm)
{
int ret;

- ret = security_ops->bprm_check_security(bprm);
+ ret = call_int_hook(bprm_check_security, bprm);
if (ret)
return ret;
return ima_bprm_check(bprm);
@@ -228,69 +244,69 @@ int security_bprm_check(struct linux_binprm *bprm)

void security_bprm_committing_creds(struct linux_binprm *bprm)
{
- security_ops->bprm_committing_creds(bprm);
+ call_void_hook(bprm_committing_creds, bprm);
}

void security_bprm_committed_creds(struct linux_binprm *bprm)
{
- security_ops->bprm_committed_creds(bprm);
+ call_void_hook(bprm_committed_creds, bprm);
}

int security_bprm_secureexec(struct linux_binprm *bprm)
{
- return security_ops->bprm_secureexec(bprm);
+ return call_int_hook(bprm_secureexec, bprm);
}

int security_sb_alloc(struct super_block *sb)
{
- return security_ops->sb_alloc_security(sb);
+ return call_int_hook(sb_alloc_security, sb);
}

void security_sb_free(struct super_block *sb)
{
- security_ops->sb_free_security(sb);
+ call_void_hook(sb_free_security, sb);
}

int security_sb_copy_data(char *orig, char *copy)
{
- return security_ops->sb_copy_data(orig, copy);
+ return call_int_hook(sb_copy_data, orig, copy);
}
EXPORT_SYMBOL(security_sb_copy_data);

int security_sb_remount(struct super_block *sb, void *data)
{
- return security_ops->sb_remount(sb, data);
+ return call_int_hook(sb_remount, sb, data);
}

int security_sb_kern_mount(struct super_block *sb, int flags, void *data)
{
- return security_ops->sb_kern_mount(sb, flags, data);
+ return call_int_hook(sb_kern_mount, sb, flags, data);
}

int security_sb_show_options(struct seq_file *m, struct super_block *sb)
{
- return security_ops->sb_show_options(m, sb);
+ return call_int_hook(sb_show_options, m, sb);
}

int security_sb_statfs(struct dentry *dentry)
{
- return security_ops->sb_statfs(dentry);
+ return call_int_hook(sb_statfs, dentry);
}

int security_sb_mount(const char *dev_name, struct path *path,
const char *type, unsigned long flags, void *data)
{
- return security_ops->sb_mount(dev_name, path, type, flags, data);
+ return call_int_hook(sb_mount, dev_name, path, type, flags, data);
}

int security_sb_umount(struct vfsmount *mnt, int flags)
{
- return security_ops->sb_umount(mnt, flags);
+ return call_int_hook(sb_umount, mnt, flags);
}

int security_sb_pivotroot(struct path *old_path, struct path *new_path)
{
- return security_ops->sb_pivotroot(old_path, new_path);
+ return call_int_hook(sb_pivotroot, old_path, new_path);
}

int security_sb_set_mnt_opts(struct super_block *sb,
@@ -298,7 +314,7 @@ int security_sb_set_mnt_opts(struct super_block *sb,
unsigned long kern_flags,
unsigned long *set_kern_flags)
{
- return security_ops->sb_set_mnt_opts(sb, opts, kern_flags,
+ return call_int_hook(sb_set_mnt_opts, sb, opts, kern_flags,
set_kern_flags);
}
EXPORT_SYMBOL(security_sb_set_mnt_opts);
@@ -306,33 +322,33 @@ EXPORT_SYMBOL(security_sb_set_mnt_opts);
int security_sb_clone_mnt_opts(const struct super_block *oldsb,
struct super_block *newsb)
{
- return security_ops->sb_clone_mnt_opts(oldsb, newsb);
+ return call_int_hook(sb_clone_mnt_opts, oldsb, newsb);
}
EXPORT_SYMBOL(security_sb_clone_mnt_opts);

int security_sb_parse_opts_str(char *options, struct security_mnt_opts *opts)
{
- return security_ops->sb_parse_opts_str(options, opts);
+ return call_int_hook(sb_parse_opts_str, options, opts);
}
EXPORT_SYMBOL(security_sb_parse_opts_str);

int security_inode_alloc(struct inode *inode)
{
inode->i_security = NULL;
- return security_ops->inode_alloc_security(inode);
+ return call_int_hook(inode_alloc_security, inode);
}

void security_inode_free(struct inode *inode)
{
integrity_inode_free(inode);
- security_ops->inode_free_security(inode);
+ call_void_hook(inode_free_security, inode);
}

int security_dentry_init_security(struct dentry *dentry, int mode,
struct qstr *name, void **ctx,
u32 *ctxlen)
{
- return security_ops->dentry_init_security(dentry, mode, name,
+ return call_int_hook(dentry_init_security, dentry, mode, name,
ctx, ctxlen);
}
EXPORT_SYMBOL(security_dentry_init_security);
@@ -349,11 +365,11 @@ int security_inode_init_security(struct inode *inode, struct inode *dir,
return 0;

if (!initxattrs)
- return security_ops->inode_init_security(inode, dir, qstr,
+ return call_int_hook(inode_init_security, inode, dir, qstr,
NULL, NULL, NULL);
memset(new_xattrs, 0, sizeof(new_xattrs));
lsm_xattr = new_xattrs;
- ret = security_ops->inode_init_security(inode, dir, qstr,
+ ret = call_int_hook(inode_init_security, inode, dir, qstr,
&lsm_xattr->name,
&lsm_xattr->value,
&lsm_xattr->value_len);
@@ -372,14 +388,18 @@ out:
}
EXPORT_SYMBOL(security_inode_init_security);

+/*
+ * Shares a hook with inode_init_security
+ */
int security_old_inode_init_security(struct inode *inode, struct inode *dir,
const struct qstr *qstr, const char **name,
void **value, size_t *len)
{
if (unlikely(IS_PRIVATE(inode)))
return -EOPNOTSUPP;
- return security_ops->inode_init_security(inode, dir, qstr, name, value,
- len);
+
+ return call_int_hook(inode_init_security, inode, dir, qstr, name,
+ value, len);
}
EXPORT_SYMBOL(security_old_inode_init_security);

@@ -389,7 +409,7 @@ int security_path_mknod(struct path *dir, struct dentry *dentry, umode_t mode,
{
if (unlikely(IS_PRIVATE(dir->dentry->d_inode)))
return 0;
- return security_ops->path_mknod(dir, dentry, mode, dev);
+ return call_int_hook(path_mknod, dir, dentry, mode, dev);
}
EXPORT_SYMBOL(security_path_mknod);

@@ -397,7 +417,7 @@ int security_path_mkdir(struct path *dir, struct dentry *dentry, umode_t mode)
{
if (unlikely(IS_PRIVATE(dir->dentry->d_inode)))
return 0;
- return security_ops->path_mkdir(dir, dentry, mode);
+ return call_int_hook(path_mkdir, dir, dentry, mode);
}
EXPORT_SYMBOL(security_path_mkdir);

@@ -405,14 +425,14 @@ int security_path_rmdir(struct path *dir, struct dentry *dentry)
{
if (unlikely(IS_PRIVATE(dir->dentry->d_inode)))
return 0;
- return security_ops->path_rmdir(dir, dentry);
+ return call_int_hook(path_rmdir, dir, dentry);
}

int security_path_unlink(struct path *dir, struct dentry *dentry)
{
if (unlikely(IS_PRIVATE(dir->dentry->d_inode)))
return 0;
- return security_ops->path_unlink(dir, dentry);
+ return call_int_hook(path_unlink, dir, dentry);
}
EXPORT_SYMBOL(security_path_unlink);

@@ -421,7 +441,7 @@ int security_path_symlink(struct path *dir, struct dentry *dentry,
{
if (unlikely(IS_PRIVATE(dir->dentry->d_inode)))
return 0;
- return security_ops->path_symlink(dir, dentry, old_name);
+ return call_int_hook(path_symlink, dir, dentry, old_name);
}

int security_path_link(struct dentry *old_dentry, struct path *new_dir,
@@ -429,7 +449,7 @@ int security_path_link(struct dentry *old_dentry, struct path *new_dir,
{
if (unlikely(IS_PRIVATE(old_dentry->d_inode)))
return 0;
- return security_ops->path_link(old_dentry, new_dir, new_dentry);
+ return call_int_hook(path_link, old_dentry, new_dir, new_dentry);
}

int security_path_rename(struct path *old_dir, struct dentry *old_dentry,
@@ -441,13 +461,13 @@ int security_path_rename(struct path *old_dir, struct dentry *old_dentry,
return 0;

if (flags & RENAME_EXCHANGE) {
- int err = security_ops->path_rename(new_dir, new_dentry,
+ int err = call_int_hook(path_rename, new_dir, new_dentry,
old_dir, old_dentry);
if (err)
return err;
}

- return security_ops->path_rename(old_dir, old_dentry, new_dir,
+ return call_int_hook(path_rename, old_dir, old_dentry, new_dir,
new_dentry);
}
EXPORT_SYMBOL(security_path_rename);
@@ -456,26 +476,26 @@ int security_path_truncate(struct path *path)
{
if (unlikely(IS_PRIVATE(path->dentry->d_inode)))
return 0;
- return security_ops->path_truncate(path);
+ return call_int_hook(path_truncate, path);
}

int security_path_chmod(struct path *path, umode_t mode)
{
if (unlikely(IS_PRIVATE(path->dentry->d_inode)))
return 0;
- return security_ops->path_chmod(path, mode);
+ return call_int_hook(path_chmod, path, mode);
}

int security_path_chown(struct path *path, kuid_t uid, kgid_t gid)
{
if (unlikely(IS_PRIVATE(path->dentry->d_inode)))
return 0;
- return security_ops->path_chown(path, uid, gid);
+ return call_int_hook(path_chown, path, uid, gid);
}

int security_path_chroot(struct path *path)
{
- return security_ops->path_chroot(path);
+ return call_int_hook(path_chroot, path);
}
#endif

@@ -483,7 +503,7 @@ int security_inode_create(struct inode *dir, struct dentry *dentry, umode_t mode
{
if (unlikely(IS_PRIVATE(dir)))
return 0;
- return security_ops->inode_create(dir, dentry, mode);
+ return call_int_hook(inode_create, dir, dentry, mode);
}
EXPORT_SYMBOL_GPL(security_inode_create);

@@ -492,14 +512,14 @@ int security_inode_link(struct dentry *old_dentry, struct inode *dir,
{
if (unlikely(IS_PRIVATE(old_dentry->d_inode)))
return 0;
- return security_ops->inode_link(old_dentry, dir, new_dentry);
+ return call_int_hook(inode_link, old_dentry, dir, new_dentry);
}

int security_inode_unlink(struct inode *dir, struct dentry *dentry)
{
if (unlikely(IS_PRIVATE(dentry->d_inode)))
return 0;
- return security_ops->inode_unlink(dir, dentry);
+ return call_int_hook(inode_unlink, dir, dentry);
}

int security_inode_symlink(struct inode *dir, struct dentry *dentry,
@@ -507,14 +527,14 @@ int security_inode_symlink(struct inode *dir, struct dentry *dentry,
{
if (unlikely(IS_PRIVATE(dir)))
return 0;
- return security_ops->inode_symlink(dir, dentry, old_name);
+ return call_int_hook(inode_symlink, dir, dentry, old_name);
}

int security_inode_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
{
if (unlikely(IS_PRIVATE(dir)))
return 0;
- return security_ops->inode_mkdir(dir, dentry, mode);
+ return call_int_hook(inode_mkdir, dir, dentry, mode);
}
EXPORT_SYMBOL_GPL(security_inode_mkdir);

@@ -522,14 +542,14 @@ int security_inode_rmdir(struct inode *dir, struct dentry *dentry)
{
if (unlikely(IS_PRIVATE(dentry->d_inode)))
return 0;
- return security_ops->inode_rmdir(dir, dentry);
+ return call_int_hook(inode_rmdir, dir, dentry);
}

int security_inode_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t dev)
{
if (unlikely(IS_PRIVATE(dir)))
return 0;
- return security_ops->inode_mknod(dir, dentry, mode, dev);
+ return call_int_hook(inode_mknod, dir, dentry, mode, dev);
}

int security_inode_rename(struct inode *old_dir, struct dentry *old_dentry,
@@ -541,13 +561,13 @@ int security_inode_rename(struct inode *old_dir, struct dentry *old_dentry,
return 0;

if (flags & RENAME_EXCHANGE) {
- int err = security_ops->inode_rename(new_dir, new_dentry,
+ int err = call_int_hook(inode_rename, old_dir, old_dentry,
old_dir, old_dentry);
if (err)
return err;
}

- return security_ops->inode_rename(old_dir, old_dentry,
+ return call_int_hook(inode_rename, old_dir, old_dentry,
new_dir, new_dentry);
}

@@ -555,21 +575,21 @@ int security_inode_readlink(struct dentry *dentry)
{
if (unlikely(IS_PRIVATE(dentry->d_inode)))
return 0;
- return security_ops->inode_readlink(dentry);
+ return call_int_hook(inode_readlink, dentry);
}

int security_inode_follow_link(struct dentry *dentry, struct nameidata *nd)
{
if (unlikely(IS_PRIVATE(dentry->d_inode)))
return 0;
- return security_ops->inode_follow_link(dentry, nd);
+ return call_int_hook(inode_follow_link, dentry, nd);
}

int security_inode_permission(struct inode *inode, int mask)
{
if (unlikely(IS_PRIVATE(inode)))
return 0;
- return security_ops->inode_permission(inode, mask);
+ return call_int_hook(inode_permission, inode, mask);
}

int security_inode_setattr(struct dentry *dentry, struct iattr *attr)
@@ -578,7 +598,7 @@ int security_inode_setattr(struct dentry *dentry, struct iattr *attr)

if (unlikely(IS_PRIVATE(dentry->d_inode)))
return 0;
- ret = security_ops->inode_setattr(dentry, attr);
+ ret = call_int_hook(inode_setattr, dentry, attr);
if (ret)
return ret;
return evm_inode_setattr(dentry, attr);
@@ -589,7 +609,7 @@ int security_inode_getattr(struct vfsmount *mnt, struct dentry *dentry)
{
if (unlikely(IS_PRIVATE(dentry->d_inode)))
return 0;
- return security_ops->inode_getattr(mnt, dentry);
+ return call_int_hook(inode_getattr, mnt, dentry);
}

int security_inode_setxattr(struct dentry *dentry, const char *name,
@@ -599,7 +619,8 @@ int security_inode_setxattr(struct dentry *dentry, const char *name,

if (unlikely(IS_PRIVATE(dentry->d_inode)))
return 0;
- ret = security_ops->inode_setxattr(dentry, name, value, size, flags);
+ ret = call_int_hook(inode_setxattr, dentry, name, value, size, flags);
+
if (ret)
return ret;
ret = ima_inode_setxattr(dentry, name, value, size);
@@ -613,7 +634,7 @@ void security_inode_post_setxattr(struct dentry *dentry, const char *name,
{
if (unlikely(IS_PRIVATE(dentry->d_inode)))
return;
- security_ops->inode_post_setxattr(dentry, name, value, size, flags);
+ call_void_hook(inode_post_setxattr, dentry, name, value, size, flags);
evm_inode_post_setxattr(dentry, name, value, size);
}

@@ -621,14 +642,14 @@ int security_inode_getxattr(struct dentry *dentry, const char *name)
{
if (unlikely(IS_PRIVATE(dentry->d_inode)))
return 0;
- return security_ops->inode_getxattr(dentry, name);
+ return call_int_hook(inode_getxattr, dentry, name);
}

int security_inode_listxattr(struct dentry *dentry)
{
if (unlikely(IS_PRIVATE(dentry->d_inode)))
return 0;
- return security_ops->inode_listxattr(dentry);
+ return call_int_hook(inode_listxattr, dentry);
}

int security_inode_removexattr(struct dentry *dentry, const char *name)
@@ -637,7 +658,7 @@ int security_inode_removexattr(struct dentry *dentry, const char *name)

if (unlikely(IS_PRIVATE(dentry->d_inode)))
return 0;
- ret = security_ops->inode_removexattr(dentry, name);
+ ret = call_int_hook(inode_removexattr, dentry, name);
if (ret)
return ret;
ret = ima_inode_removexattr(dentry, name);
@@ -648,46 +669,47 @@ int security_inode_removexattr(struct dentry *dentry, const char *name)

int security_inode_need_killpriv(struct dentry *dentry)
{
- return security_ops->inode_need_killpriv(dentry);
+ return call_int_hook(inode_need_killpriv, dentry);
}

int security_inode_killpriv(struct dentry *dentry)
{
- return security_ops->inode_killpriv(dentry);
+ return call_int_hook(inode_killpriv, dentry);
}

int security_inode_getsecurity(const struct inode *inode, const char *name, void **buffer, bool alloc)
{
if (unlikely(IS_PRIVATE(inode)))
return -EOPNOTSUPP;
- return security_ops->inode_getsecurity(inode, name, buffer, alloc);
+ return call_int_hook(inode_getsecurity, inode, name, buffer, alloc);
}

int security_inode_setsecurity(struct inode *inode, const char *name, const void *value, size_t size, int flags)
{
if (unlikely(IS_PRIVATE(inode)))
return -EOPNOTSUPP;
- return security_ops->inode_setsecurity(inode, name, value, size, flags);
+ return call_int_hook(inode_setsecurity, inode, name, value, size,
+ flags);
}

int security_inode_listsecurity(struct inode *inode, char *buffer, size_t buffer_size)
{
if (unlikely(IS_PRIVATE(inode)))
return 0;
- return security_ops->inode_listsecurity(inode, buffer, buffer_size);
+ return call_int_hook(inode_listsecurity, inode, buffer, buffer_size);
}
EXPORT_SYMBOL(security_inode_listsecurity);

void security_inode_getsecid(const struct inode *inode, u32 *secid)
{
- security_ops->inode_getsecid(inode, secid);
+ call_void_hook(inode_getsecid, inode, secid);
}

int security_file_permission(struct file *file, int mask)
{
int ret;

- ret = security_ops->file_permission(file, mask);
+ ret = call_int_hook(file_permission, file, mask);
if (ret)
return ret;

@@ -696,17 +718,17 @@ int security_file_permission(struct file *file, int mask)

int security_file_alloc(struct file *file)
{
- return security_ops->file_alloc_security(file);
+ return call_int_hook(file_alloc_security, file);
}

void security_file_free(struct file *file)
{
- security_ops->file_free_security(file);
+ call_void_hook(file_free_security, file);
}

int security_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
- return security_ops->file_ioctl(file, cmd, arg);
+ return call_int_hook(file_ioctl, file, cmd, arg);
}

static inline unsigned long mmap_prot(struct file *file, unsigned long prot)
@@ -747,7 +769,7 @@ int security_mmap_file(struct file *file, unsigned long prot,
unsigned long flags)
{
int ret;
- ret = security_ops->mmap_file(file, prot,
+ ret = call_int_hook(mmap_file, file, prot,
mmap_prot(file, prot), flags);
if (ret)
return ret;
@@ -756,46 +778,46 @@ int security_mmap_file(struct file *file, unsigned long prot,

int security_mmap_addr(unsigned long addr)
{
- return security_ops->mmap_addr(addr);
+ return call_int_hook(mmap_addr, addr);
}

int security_file_mprotect(struct vm_area_struct *vma, unsigned long reqprot,
unsigned long prot)
{
- return security_ops->file_mprotect(vma, reqprot, prot);
+ return call_int_hook(file_mprotect, vma, reqprot, prot);
}

int security_file_lock(struct file *file, unsigned int cmd)
{
- return security_ops->file_lock(file, cmd);
+ return call_int_hook(file_lock, file, cmd);
}

int security_file_fcntl(struct file *file, unsigned int cmd, unsigned long arg)
{
- return security_ops->file_fcntl(file, cmd, arg);
+ return call_int_hook(file_fcntl, file, cmd, arg);
}

int security_file_set_fowner(struct file *file)
{
- return security_ops->file_set_fowner(file);
+ return call_int_hook(file_set_fowner, file);
}

int security_file_send_sigiotask(struct task_struct *tsk,
struct fown_struct *fown, int sig)
{
- return security_ops->file_send_sigiotask(tsk, fown, sig);
+ return call_int_hook(file_send_sigiotask, tsk, fown, sig);
}

int security_file_receive(struct file *file)
{
- return security_ops->file_receive(file);
+ return call_int_hook(file_receive, file);
}

int security_file_open(struct file *file, const struct cred *cred)
{
int ret;

- ret = security_ops->file_open(file, cred);
+ ret = call_int_hook(file_open, file, cred);
if (ret)
return ret;

@@ -804,7 +826,7 @@ int security_file_open(struct file *file, const struct cred *cred)

int security_task_create(unsigned long clone_flags)
{
- return security_ops->task_create(clone_flags);
+ return call_int_hook(task_create, clone_flags);
}

void security_task_free(struct task_struct *task)
@@ -812,49 +834,49 @@ void security_task_free(struct task_struct *task)
#ifdef CONFIG_SECURITY_YAMA_STACKED
yama_task_free(task);
#endif
- security_ops->task_free(task);
+ call_void_hook(task_free, task);
}

int security_cred_alloc_blank(struct cred *cred, gfp_t gfp)
{
- return security_ops->cred_alloc_blank(cred, gfp);
+ return call_int_hook(cred_alloc_blank, cred, gfp);
}

void security_cred_free(struct cred *cred)
{
- security_ops->cred_free(cred);
+ call_void_hook(cred_free, cred);
}

int security_prepare_creds(struct cred *new, const struct cred *old, gfp_t gfp)
{
- return security_ops->cred_prepare(new, old, gfp);
+ return call_int_hook(cred_prepare, new, old, gfp);
}

void security_transfer_creds(struct cred *new, const struct cred *old)
{
- security_ops->cred_transfer(new, old);
+ call_void_hook(cred_transfer, new, old);
}

int security_kernel_act_as(struct cred *new, u32 secid)
{
- return security_ops->kernel_act_as(new, secid);
+ return call_int_hook(kernel_act_as, new, secid);
}

int security_kernel_create_files_as(struct cred *new, struct inode *inode)
{
- return security_ops->kernel_create_files_as(new, inode);
+ return call_int_hook(kernel_create_files_as, new, inode);
}

int security_kernel_module_request(char *kmod_name)
{
- return security_ops->kernel_module_request(kmod_name);
+ return call_int_hook(kernel_module_request, kmod_name);
}

int security_kernel_module_from_file(struct file *file)
{
int ret;

- ret = security_ops->kernel_module_from_file(file);
+ ret = call_int_hook(kernel_module_from_file, file);
if (ret)
return ret;
return ima_module_check(file);
@@ -863,75 +885,75 @@ int security_kernel_module_from_file(struct file *file)
int security_task_fix_setuid(struct cred *new, const struct cred *old,
int flags)
{
- return security_ops->task_fix_setuid(new, old, flags);
+ return call_int_hook(task_fix_setuid, new, old, flags);
}

int security_task_setpgid(struct task_struct *p, pid_t pgid)
{
- return security_ops->task_setpgid(p, pgid);
+ return call_int_hook(task_setpgid, p, pgid);
}

int security_task_getpgid(struct task_struct *p)
{
- return security_ops->task_getpgid(p);
+ return call_int_hook(task_getpgid, p);
}

int security_task_getsid(struct task_struct *p)
{
- return security_ops->task_getsid(p);
+ return call_int_hook(task_getsid, p);
}

void security_task_getsecid(struct task_struct *p, u32 *secid)
{
- security_ops->task_getsecid(p, secid);
+ call_void_hook(task_getsecid, p, secid);
}
EXPORT_SYMBOL(security_task_getsecid);

int security_task_setnice(struct task_struct *p, int nice)
{
- return security_ops->task_setnice(p, nice);
+ return call_int_hook(task_setnice, p, nice);
}

int security_task_setioprio(struct task_struct *p, int ioprio)
{
- return security_ops->task_setioprio(p, ioprio);
+ return call_int_hook(task_setioprio, p, ioprio);
}

int security_task_getioprio(struct task_struct *p)
{
- return security_ops->task_getioprio(p);
+ return call_int_hook(task_getioprio, p);
}

int security_task_setrlimit(struct task_struct *p, unsigned int resource,
struct rlimit *new_rlim)
{
- return security_ops->task_setrlimit(p, resource, new_rlim);
+ return call_int_hook(task_setrlimit, p, resource, new_rlim);
}

int security_task_setscheduler(struct task_struct *p)
{
- return security_ops->task_setscheduler(p);
+ return call_int_hook(task_setscheduler, p);
}

int security_task_getscheduler(struct task_struct *p)
{
- return security_ops->task_getscheduler(p);
+ return call_int_hook(task_getscheduler, p);
}

int security_task_movememory(struct task_struct *p)
{
- return security_ops->task_movememory(p);
+ return call_int_hook(task_movememory, p);
}

int security_task_kill(struct task_struct *p, struct siginfo *info,
int sig, u32 secid)
{
- return security_ops->task_kill(p, info, sig, secid);
+ return call_int_hook(task_kill, p, info, sig, secid);
}

int security_task_wait(struct task_struct *p)
{
- return security_ops->task_wait(p);
+ return call_int_hook(task_wait, p);
}

int security_task_prctl(int option, unsigned long arg2, unsigned long arg3,
@@ -943,179 +965,179 @@ int security_task_prctl(int option, unsigned long arg2, unsigned long arg3,
if (rc != -ENOSYS)
return rc;
#endif
- return security_ops->task_prctl(option, arg2, arg3, arg4, arg5);
+ return call_int_hook(task_prctl, option, arg2, arg3, arg4, arg5);
}

void security_task_to_inode(struct task_struct *p, struct inode *inode)
{
- security_ops->task_to_inode(p, inode);
+ call_void_hook(task_to_inode, p, inode);
}

int security_ipc_permission(struct kern_ipc_perm *ipcp, short flag)
{
- return security_ops->ipc_permission(ipcp, flag);
+ return call_int_hook(ipc_permission, ipcp, flag);
}

void security_ipc_getsecid(struct kern_ipc_perm *ipcp, u32 *secid)
{
- security_ops->ipc_getsecid(ipcp, secid);
+ call_void_hook(ipc_getsecid, ipcp, secid);
}

int security_msg_msg_alloc(struct msg_msg *msg)
{
- return security_ops->msg_msg_alloc_security(msg);
+ return call_int_hook(msg_msg_alloc_security, msg);
}

void security_msg_msg_free(struct msg_msg *msg)
{
- security_ops->msg_msg_free_security(msg);
+ call_void_hook(msg_msg_free_security, msg);
}

int security_msg_queue_alloc(struct msg_queue *msq)
{
- return security_ops->msg_queue_alloc_security(msq);
+ return call_int_hook(msg_queue_alloc_security, msq);
}

void security_msg_queue_free(struct msg_queue *msq)
{
- security_ops->msg_queue_free_security(msq);
+ call_void_hook(msg_queue_free_security, msq);
}

int security_msg_queue_associate(struct msg_queue *msq, int msqflg)
{
- return security_ops->msg_queue_associate(msq, msqflg);
+ return call_int_hook(msg_queue_associate, msq, msqflg);
}

int security_msg_queue_msgctl(struct msg_queue *msq, int cmd)
{
- return security_ops->msg_queue_msgctl(msq, cmd);
+ return call_int_hook(msg_queue_msgctl, msq, cmd);
}

int security_msg_queue_msgsnd(struct msg_queue *msq,
struct msg_msg *msg, int msqflg)
{
- return security_ops->msg_queue_msgsnd(msq, msg, msqflg);
+ return call_int_hook(msg_queue_msgsnd, msq, msg, msqflg);
}

int security_msg_queue_msgrcv(struct msg_queue *msq, struct msg_msg *msg,
struct task_struct *target, long type, int mode)
{
- return security_ops->msg_queue_msgrcv(msq, msg, target, type, mode);
+ return call_int_hook(msg_queue_msgrcv, msq, msg, target, type, mode);
}

int security_shm_alloc(struct shmid_kernel *shp)
{
- return security_ops->shm_alloc_security(shp);
+ return call_int_hook(shm_alloc_security, shp);
}

void security_shm_free(struct shmid_kernel *shp)
{
- security_ops->shm_free_security(shp);
+ call_void_hook(shm_free_security, shp);
}

int security_shm_associate(struct shmid_kernel *shp, int shmflg)
{
- return security_ops->shm_associate(shp, shmflg);
+ return call_int_hook(shm_associate, shp, shmflg);
}

int security_shm_shmctl(struct shmid_kernel *shp, int cmd)
{
- return security_ops->shm_shmctl(shp, cmd);
+ return call_int_hook(shm_shmctl, shp, cmd);
}

int security_shm_shmat(struct shmid_kernel *shp, char __user *shmaddr, int shmflg)
{
- return security_ops->shm_shmat(shp, shmaddr, shmflg);
+ return call_int_hook(shm_shmat, shp, shmaddr, shmflg);
}

int security_sem_alloc(struct sem_array *sma)
{
- return security_ops->sem_alloc_security(sma);
+ return call_int_hook(sem_alloc_security, sma);
}

void security_sem_free(struct sem_array *sma)
{
- security_ops->sem_free_security(sma);
+ call_void_hook(sem_free_security, sma);
}

int security_sem_associate(struct sem_array *sma, int semflg)
{
- return security_ops->sem_associate(sma, semflg);
+ return call_int_hook(sem_associate, sma, semflg);
}

int security_sem_semctl(struct sem_array *sma, int cmd)
{
- return security_ops->sem_semctl(sma, cmd);
+ return call_int_hook(sem_semctl, sma, cmd);
}

int security_sem_semop(struct sem_array *sma, struct sembuf *sops,
unsigned nsops, int alter)
{
- return security_ops->sem_semop(sma, sops, nsops, alter);
+ return call_int_hook(sem_semop, sma, sops, nsops, alter);
}

void security_d_instantiate(struct dentry *dentry, struct inode *inode)
{
if (unlikely(inode && IS_PRIVATE(inode)))
return;
- security_ops->d_instantiate(dentry, inode);
+ call_void_hook(d_instantiate, dentry, inode);
}
EXPORT_SYMBOL(security_d_instantiate);

int security_getprocattr(struct task_struct *p, char *name, char **value)
{
- return security_ops->getprocattr(p, name, value);
+ return call_int_hook(getprocattr, p, name, value);
}

int security_setprocattr(struct task_struct *p, char *name, void *value, size_t size)
{
- return security_ops->setprocattr(p, name, value, size);
+ return call_int_hook(setprocattr, p, name, value, size);
}

int security_netlink_send(struct sock *sk, struct sk_buff *skb)
{
- return security_ops->netlink_send(sk, skb);
+ return call_int_hook(netlink_send, sk, skb);
}

int security_ismaclabel(const char *name)
{
- return security_ops->ismaclabel(name);
+ return call_int_hook(ismaclabel, name);
}
EXPORT_SYMBOL(security_ismaclabel);

int security_secid_to_secctx(u32 secid, char **secdata, u32 *seclen)
{
- return security_ops->secid_to_secctx(secid, secdata, seclen);
+ return call_int_hook(secid_to_secctx, secid, secdata, seclen);
}
EXPORT_SYMBOL(security_secid_to_secctx);

int security_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid)
{
- return security_ops->secctx_to_secid(secdata, seclen, secid);
+ return call_int_hook(secctx_to_secid, secdata, seclen, secid);
}
EXPORT_SYMBOL(security_secctx_to_secid);

void security_release_secctx(char *secdata, u32 seclen)
{
- security_ops->release_secctx(secdata, seclen);
+ call_void_hook(release_secctx, secdata, seclen);
}
EXPORT_SYMBOL(security_release_secctx);

int security_inode_notifysecctx(struct inode *inode, void *ctx, u32 ctxlen)
{
- return security_ops->inode_notifysecctx(inode, ctx, ctxlen);
+ return call_int_hook(inode_notifysecctx, inode, ctx, ctxlen);
}
EXPORT_SYMBOL(security_inode_notifysecctx);

int security_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen)
{
- return security_ops->inode_setsecctx(dentry, ctx, ctxlen);
+ return call_int_hook(inode_setsecctx, dentry, ctx, ctxlen);
}
EXPORT_SYMBOL(security_inode_setsecctx);

int security_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen)
{
- return security_ops->inode_getsecctx(inode, ctx, ctxlen);
+ return call_int_hook(inode_getsecctx, inode, ctx, ctxlen);
}
EXPORT_SYMBOL(security_inode_getsecctx);

@@ -1123,212 +1145,213 @@ EXPORT_SYMBOL(security_inode_getsecctx);

int security_unix_stream_connect(struct sock *sock, struct sock *other, struct sock *newsk)
{
- return security_ops->unix_stream_connect(sock, other, newsk);
+ return call_int_hook(unix_stream_connect, sock, other, newsk);
}
EXPORT_SYMBOL(security_unix_stream_connect);

int security_unix_may_send(struct socket *sock, struct socket *other)
{
- return security_ops->unix_may_send(sock, other);
+ return call_int_hook(unix_may_send, sock, other);
}
EXPORT_SYMBOL(security_unix_may_send);

int security_socket_create(int family, int type, int protocol, int kern)
{
- return security_ops->socket_create(family, type, protocol, kern);
+ return call_int_hook(socket_create, family, type, protocol, kern);
}

int security_socket_post_create(struct socket *sock, int family,
int type, int protocol, int kern)
{
- return security_ops->socket_post_create(sock, family, type,
+ return call_int_hook(socket_post_create, sock, family, type,
protocol, kern);
}

int security_socket_bind(struct socket *sock, struct sockaddr *address, int addrlen)
{
- return security_ops->socket_bind(sock, address, addrlen);
+ return call_int_hook(socket_bind, sock, address, addrlen);
}

int security_socket_connect(struct socket *sock, struct sockaddr *address, int addrlen)
{
- return security_ops->socket_connect(sock, address, addrlen);
+ return call_int_hook(socket_connect, sock, address, addrlen);
}

int security_socket_listen(struct socket *sock, int backlog)
{
- return security_ops->socket_listen(sock, backlog);
+ return call_int_hook(socket_listen, sock, backlog);
}

int security_socket_accept(struct socket *sock, struct socket *newsock)
{
- return security_ops->socket_accept(sock, newsock);
+ return call_int_hook(socket_accept, sock, newsock);
}

int security_socket_sendmsg(struct socket *sock, struct msghdr *msg, int size)
{
- return security_ops->socket_sendmsg(sock, msg, size);
+ return call_int_hook(socket_sendmsg, sock, msg, size);
}

int security_socket_recvmsg(struct socket *sock, struct msghdr *msg,
int size, int flags)
{
- return security_ops->socket_recvmsg(sock, msg, size, flags);
+ return call_int_hook(socket_recvmsg, sock, msg, size, flags);
}

int security_socket_getsockname(struct socket *sock)
{
- return security_ops->socket_getsockname(sock);
+ return call_int_hook(socket_getsockname, sock);
}

int security_socket_getpeername(struct socket *sock)
{
- return security_ops->socket_getpeername(sock);
+ return call_int_hook(socket_getpeername, sock);
}

int security_socket_getsockopt(struct socket *sock, int level, int optname)
{
- return security_ops->socket_getsockopt(sock, level, optname);
+ return call_int_hook(socket_getsockopt, sock, level, optname);
}

int security_socket_setsockopt(struct socket *sock, int level, int optname)
{
- return security_ops->socket_setsockopt(sock, level, optname);
+ return call_int_hook(socket_setsockopt, sock, level, optname);
}

int security_socket_shutdown(struct socket *sock, int how)
{
- return security_ops->socket_shutdown(sock, how);
+ return call_int_hook(socket_shutdown, sock, how);
}

int security_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
{
- return security_ops->socket_sock_rcv_skb(sk, skb);
+ return call_int_hook(socket_sock_rcv_skb, sk, skb);
}
EXPORT_SYMBOL(security_sock_rcv_skb);

int security_socket_getpeersec_stream(struct socket *sock, char __user *optval,
int __user *optlen, unsigned len)
{
- return security_ops->socket_getpeersec_stream(sock, optval, optlen, len);
+ return call_int_hook(socket_getpeersec_stream, sock, optval, optlen,
+ len);
}

int security_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *skb, u32 *secid)
{
- return security_ops->socket_getpeersec_dgram(sock, skb, secid);
+ return call_int_hook(socket_getpeersec_dgram, sock, skb, secid);
}
EXPORT_SYMBOL(security_socket_getpeersec_dgram);

int security_sk_alloc(struct sock *sk, int family, gfp_t priority)
{
- return security_ops->sk_alloc_security(sk, family, priority);
+ return call_int_hook(sk_alloc_security, sk, family, priority);
}

void security_sk_free(struct sock *sk)
{
- security_ops->sk_free_security(sk);
+ call_void_hook(sk_free_security, sk);
}

void security_sk_clone(const struct sock *sk, struct sock *newsk)
{
- security_ops->sk_clone_security(sk, newsk);
+ call_void_hook(sk_clone_security, sk, newsk);
}
EXPORT_SYMBOL(security_sk_clone);

void security_sk_classify_flow(struct sock *sk, struct flowi *fl)
{
- security_ops->sk_getsecid(sk, &fl->flowi_secid);
+ call_void_hook(sk_getsecid, sk, &fl->flowi_secid);
}
EXPORT_SYMBOL(security_sk_classify_flow);

void security_req_classify_flow(const struct request_sock *req, struct flowi *fl)
{
- security_ops->req_classify_flow(req, fl);
+ call_void_hook(req_classify_flow, req, fl);
}
EXPORT_SYMBOL(security_req_classify_flow);

void security_sock_graft(struct sock *sk, struct socket *parent)
{
- security_ops->sock_graft(sk, parent);
+ call_void_hook(sock_graft, sk, parent);
}
EXPORT_SYMBOL(security_sock_graft);

int security_inet_conn_request(struct sock *sk,
struct sk_buff *skb, struct request_sock *req)
{
- return security_ops->inet_conn_request(sk, skb, req);
+ return call_int_hook(inet_conn_request, sk, skb, req);
}
EXPORT_SYMBOL(security_inet_conn_request);

void security_inet_csk_clone(struct sock *newsk,
const struct request_sock *req)
{
- security_ops->inet_csk_clone(newsk, req);
+ call_void_hook(inet_csk_clone, newsk, req);
}

void security_inet_conn_established(struct sock *sk,
struct sk_buff *skb)
{
- security_ops->inet_conn_established(sk, skb);
+ call_void_hook(inet_conn_established, sk, skb);
}

int security_secmark_relabel_packet(u32 secid)
{
- return security_ops->secmark_relabel_packet(secid);
+ return call_int_hook(secmark_relabel_packet, secid);
}
EXPORT_SYMBOL(security_secmark_relabel_packet);

void security_secmark_refcount_inc(void)
{
- security_ops->secmark_refcount_inc();
+ call_void_hook(secmark_refcount_inc);
}
EXPORT_SYMBOL(security_secmark_refcount_inc);

void security_secmark_refcount_dec(void)
{
- security_ops->secmark_refcount_dec();
+ call_void_hook(secmark_refcount_dec);
}
EXPORT_SYMBOL(security_secmark_refcount_dec);

int security_tun_dev_alloc_security(void **security)
{
- return security_ops->tun_dev_alloc_security(security);
+ return call_int_hook(tun_dev_alloc_security, security);
}
EXPORT_SYMBOL(security_tun_dev_alloc_security);

void security_tun_dev_free_security(void *security)
{
- security_ops->tun_dev_free_security(security);
+ call_void_hook(tun_dev_free_security, security);
}
EXPORT_SYMBOL(security_tun_dev_free_security);

int security_tun_dev_create(void)
{
- return security_ops->tun_dev_create();
+ return call_int_hook(tun_dev_create);
}
EXPORT_SYMBOL(security_tun_dev_create);

int security_tun_dev_attach_queue(void *security)
{
- return security_ops->tun_dev_attach_queue(security);
+ return call_int_hook(tun_dev_attach_queue, security);
}
EXPORT_SYMBOL(security_tun_dev_attach_queue);

int security_tun_dev_attach(struct sock *sk, void *security)
{
- return security_ops->tun_dev_attach(sk, security);
+ return call_int_hook(tun_dev_attach, sk, security);
}
EXPORT_SYMBOL(security_tun_dev_attach);

int security_tun_dev_open(void *security)
{
- return security_ops->tun_dev_open(security);
+ return call_int_hook(tun_dev_open, security);
}
EXPORT_SYMBOL(security_tun_dev_open);

void security_skb_owned_by(struct sk_buff *skb, struct sock *sk)
{
- security_ops->skb_owned_by(skb, sk);
+ call_void_hook(skb_owned_by, skb, sk);
}

#endif /* CONFIG_SECURITY_NETWORK */
@@ -1339,71 +1362,74 @@ int security_xfrm_policy_alloc(struct xfrm_sec_ctx **ctxp,
struct xfrm_user_sec_ctx *sec_ctx,
gfp_t gfp)
{
- return security_ops->xfrm_policy_alloc_security(ctxp, sec_ctx, gfp);
+ return call_int_hook(xfrm_policy_alloc_security, ctxp, sec_ctx, gfp);
}
EXPORT_SYMBOL(security_xfrm_policy_alloc);

int security_xfrm_policy_clone(struct xfrm_sec_ctx *old_ctx,
struct xfrm_sec_ctx **new_ctxp)
{
- return security_ops->xfrm_policy_clone_security(old_ctx, new_ctxp);
+ return call_int_hook(xfrm_policy_clone_security, old_ctx, new_ctxp);
}

void security_xfrm_policy_free(struct xfrm_sec_ctx *ctx)
{
- security_ops->xfrm_policy_free_security(ctx);
+ call_void_hook(xfrm_policy_free_security, ctx);
}
EXPORT_SYMBOL(security_xfrm_policy_free);

int security_xfrm_policy_delete(struct xfrm_sec_ctx *ctx)
{
- return security_ops->xfrm_policy_delete_security(ctx);
+ return call_int_hook(xfrm_policy_delete_security, ctx);
}

int security_xfrm_state_alloc(struct xfrm_state *x,
struct xfrm_user_sec_ctx *sec_ctx)
{
- return security_ops->xfrm_state_alloc(x, sec_ctx);
+ return call_int_hook(xfrm_state_alloc, x, sec_ctx);
}
EXPORT_SYMBOL(security_xfrm_state_alloc);

int security_xfrm_state_alloc_acquire(struct xfrm_state *x,
struct xfrm_sec_ctx *polsec, u32 secid)
{
- return security_ops->xfrm_state_alloc_acquire(x, polsec, secid);
+ return call_int_hook(xfrm_state_alloc_acquire, x, polsec, secid);
}

int security_xfrm_state_delete(struct xfrm_state *x)
{
- return security_ops->xfrm_state_delete_security(x);
+ return call_int_hook(xfrm_state_delete_security, x);
}
EXPORT_SYMBOL(security_xfrm_state_delete);

void security_xfrm_state_free(struct xfrm_state *x)
{
- security_ops->xfrm_state_free_security(x);
+ call_void_hook(xfrm_state_free_security, x);
}

int security_xfrm_policy_lookup(struct xfrm_sec_ctx *ctx, u32 fl_secid, u8 dir)
{
- return security_ops->xfrm_policy_lookup(ctx, fl_secid, dir);
+ return call_int_hook(xfrm_policy_lookup, ctx, fl_secid, dir);
}

int security_xfrm_state_pol_flow_match(struct xfrm_state *x,
struct xfrm_policy *xp,
const struct flowi *fl)
{
- return security_ops->xfrm_state_pol_flow_match(x, xp, fl);
+ return call_int_hook(xfrm_state_pol_flow_match, x, xp, fl);
}

int security_xfrm_decode_session(struct sk_buff *skb, u32 *secid)
{
- return security_ops->xfrm_decode_session(skb, secid, 1);
+ return call_int_hook(xfrm_decode_session, skb, secid, 1);
}

+/*
+ * Special case with no hook for skb_classify_flow
+ */
void security_skb_classify_flow(struct sk_buff *skb, struct flowi *fl)
{
- int rc = security_ops->xfrm_decode_session(skb, &fl->flowi_secid, 0);
+ int rc = call_int_hook(xfrm_decode_session, skb, &fl->flowi_secid, 0);

BUG_ON(rc);
}
@@ -1416,23 +1442,23 @@ EXPORT_SYMBOL(security_skb_classify_flow);
int security_key_alloc(struct key *key, const struct cred *cred,
unsigned long flags)
{
- return security_ops->key_alloc(key, cred, flags);
+ return call_int_hook(key_alloc, key, cred, flags);
}

void security_key_free(struct key *key)
{
- security_ops->key_free(key);
+ call_void_hook(key_free, key);
}

int security_key_permission(key_ref_t key_ref,
const struct cred *cred, unsigned perm)
{
- return security_ops->key_permission(key_ref, cred, perm);
+ return call_int_hook(key_permission, key_ref, cred, perm);
}

int security_key_getsecurity(struct key *key, char **_buffer)
{
- return security_ops->key_getsecurity(key, _buffer);
+ return call_int_hook(key_getsecurity, key, _buffer);
}

#endif /* CONFIG_KEYS */
@@ -1441,23 +1467,23 @@ int security_key_getsecurity(struct key *key, char **_buffer)

int security_audit_rule_init(u32 field, u32 op, char *rulestr, void **lsmrule)
{
- return security_ops->audit_rule_init(field, op, rulestr, lsmrule);
+ return call_int_hook(audit_rule_init, field, op, rulestr, lsmrule);
}

int security_audit_rule_known(struct audit_krule *krule)
{
- return security_ops->audit_rule_known(krule);
+ return call_int_hook(audit_rule_known, krule);
}

void security_audit_rule_free(void *lsmrule)
{
- security_ops->audit_rule_free(lsmrule);
+ call_void_hook(audit_rule_free, lsmrule);
}

int security_audit_rule_match(u32 secid, u32 field, u32 op, void *lsmrule,
struct audit_context *actx)
{
- return security_ops->audit_rule_match(secid, field, op, lsmrule, actx);
+ return call_int_hook(audit_rule_match, secid, field, op, lsmrule, actx);
}

#endif /* CONFIG_AUDIT */

--
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
the body of a message to ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Kees Cook
2014-08-14 18:42:14 UTC
Permalink
Post by Casey Schaufler
Subject: [PATCH v16 1/4] LSM: Macroize security hooks
The security hooks are called by accessing the relevant
entry in the security_ops structure. Placing the calls into
a macro does nothing to the performance (it should generate
identical code) and sets the stage for a more sophisticated
calling scheme.
Easy to review patch! :)

Reviewed-by: Kees Cook <***@chromium.org>

-Kees
--
Kees Cook
Chrome OS Security
--
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
the body of a message to ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Casey Schaufler
2014-08-08 20:00:28 UTC
Permalink
Subject: [PATCH v16 2/4] LSM: Refactor existing LSM stacking

The existing code stacks up to three security modules.
If there is only one module it is the capability module.
If a module is specified the capability code is explicitly
called within the specified module. If Yama stacking is
configured the yama hooks are called and then the specified
module. The capability check is made twice in the yama
stacking case.

This patch adds a list for each of the LSM hooks. The capability
hooks that are non-trivial are put on the list first. If Yama
stacking is configured the yama hooks are added to the list.
If a module is configured it gets added next. Each entry in the
list is called in order:

(capability[ yama][ {selinux|smack|tomoyo|apparmor}])

Exit is on first failure (bail on fail) which matches the
existing behavior. The explict calls to the capability module
are removed where they would duplicate the stacked call.

Signed-off-by: Casey Schaufler <***@schaufler-ca.com>

---
include/linux/security.h | 6 +-
security/Makefile | 2 +-
security/apparmor/domain.c | 4 +-
security/apparmor/lsm.c | 20 +-
security/commoncap.c | 34 ++
security/security.c | 1185 +++++++++++++++++++++++++++++++++++++++++---
security/selinux/hooks.c | 48 +-
security/smack/smack_lsm.c | 35 +-
security/tomoyo/tomoyo.c | 6 -
security/yama/yama_lsm.c | 36 +-
10 files changed, 1187 insertions(+), 189 deletions(-)

diff --git a/include/linux/security.h b/include/linux/security.h
index 9c6b972..29076d6 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -101,6 +101,8 @@ extern int cap_task_setioprio(struct task_struct *p, int ioprio);
extern int cap_task_setnice(struct task_struct *p, int nice);
extern int cap_vm_enough_memory(struct mm_struct *mm, long pages);

+extern struct security_operations capability_ops;
+
struct msghdr;
struct sk_buff;
struct sock;
@@ -116,7 +118,9 @@ struct seq_file;

extern int cap_netlink_send(struct sock *sk, struct sk_buff *skb);

-void reset_security_ops(void);
+#ifdef CONFIG_SECURITY_SELINUX_DISABLE
+void security_module_disable(struct security_operations *);
+#endif

#ifdef CONFIG_MMU
extern unsigned long mmap_min_addr;
diff --git a/security/Makefile b/security/Makefile
index 05f1c93..c9bfbc8 100644
--- a/security/Makefile
+++ b/security/Makefile
@@ -14,7 +14,7 @@ obj-y += commoncap.o
obj-$(CONFIG_MMU) += min_addr.o

# Object file lists
-obj-$(CONFIG_SECURITY) += security.o capability.o
+obj-$(CONFIG_SECURITY) += security.o
obj-$(CONFIG_SECURITYFS) += inode.o
obj-$(CONFIG_SECURITY_SELINUX) += selinux/
obj-$(CONFIG_SECURITY_SMACK) += smack/
diff --git a/security/apparmor/domain.c b/security/apparmor/domain.c
index 452567d..38aefc0 100644
--- a/security/apparmor/domain.c
+++ b/security/apparmor/domain.c
@@ -347,9 +347,7 @@ int apparmor_bprm_set_creds(struct linux_binprm *bprm)
file_inode(bprm->file)->i_mode
};
const char *name = NULL, *target = NULL, *info = NULL;
- int error = cap_bprm_set_creds(bprm);
- if (error)
- return error;
+ int error = 0;

if (bprm->cred_prepared)
return 0;
diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c
index 9981000..e29c92d 100644
--- a/security/apparmor/lsm.c
+++ b/security/apparmor/lsm.c
@@ -96,19 +96,11 @@ static void apparmor_cred_transfer(struct cred *new, const struct cred *old)
static int apparmor_ptrace_access_check(struct task_struct *child,
unsigned int mode)
{
- int error = cap_ptrace_access_check(child, mode);
- if (error)
- return error;
-
return aa_ptrace(current, child, mode);
}

static int apparmor_ptrace_traceme(struct task_struct *parent)
{
- int error = cap_ptrace_traceme(parent);
- if (error)
- return error;
-
return aa_ptrace(parent, current, PTRACE_MODE_ATTACH);
}

@@ -140,13 +132,11 @@ static int apparmor_capable(const struct cred *cred, struct user_namespace *ns,
int cap, int audit)
{
struct aa_profile *profile;
- /* cap_capable returns 0 on success, else -EPERM */
- int error = cap_capable(cred, ns, cap, audit);
- if (!error) {
- profile = aa_cred_profile(cred);
- if (!unconfined(profile))
- error = aa_capable(profile, cap, audit);
- }
+ int error = 0;
+
+ profile = aa_cred_profile(cred);
+ if (!unconfined(profile))
+ error = aa_capable(profile, cap, audit);
return error;
}

diff --git a/security/commoncap.c b/security/commoncap.c
index b9d613e..1cfc27c 100644
--- a/security/commoncap.c
+++ b/security/commoncap.c
@@ -994,3 +994,37 @@ int cap_mmap_file(struct file *file, unsigned long reqprot,
{
return 0;
}
+
+#ifdef CONFIG_SECURITY
+
+struct security_operations capability_ops = {
+ .name = "capability",
+ .capable = cap_capable,
+ .settime = cap_settime,
+ .ptrace_access_check = cap_ptrace_access_check,
+ .ptrace_traceme = cap_ptrace_traceme,
+ .capget = cap_capget,
+ .capset = cap_capset,
+ .bprm_set_creds = cap_bprm_set_creds,
+ /*
+ * Not stacked in the usual way.
+ * .bprm_secureexec = cap_bprm_secureexec,
+ * .inode_setxattr = cap_inode_setxattr,
+ * .inode_removexattr = cap_inode_removexattr,
+ */
+ .inode_need_killpriv = cap_inode_need_killpriv,
+ .inode_killpriv = cap_inode_killpriv,
+ /*
+ * Not stacked in the usual way.
+ * .mmap_addr = cap_mmap_addr,
+ */
+ .mmap_file = cap_mmap_file,
+ .task_fix_setuid = cap_task_fix_setuid,
+ .task_prctl = cap_task_prctl,
+ .task_setscheduler = cap_task_setscheduler,
+ .task_setioprio = cap_task_setioprio,
+ .task_setnice = cap_task_setnice,
+ .vm_enough_memory = cap_vm_enough_memory,
+};
+
+#endif /* CONFIG_SECURITY */
diff --git a/security/security.c b/security/security.c
index b8c14d0..cf26b62 100644
--- a/security/security.c
+++ b/security/security.c
@@ -25,28 +25,20 @@
#include <linux/mount.h>
#include <linux/personality.h>
#include <linux/backing-dev.h>
+#include <linux/list.h>
#include <net/flow.h>

+struct security_hook_list {
+ struct list_head shl_head;
+ struct security_operations *shl_ops;
+};
+
#define MAX_LSM_EVM_XATTR 2

/* Boot-time LSM user choice */
static __initdata char chosen_lsm[SECURITY_NAME_MAX + 1] =
CONFIG_DEFAULT_SECURITY;

-static struct security_operations *security_ops;
-static struct security_operations default_security_ops = {
- .name = "default",
-};
-
-static inline int __init verify(struct security_operations *ops)
-{
- /* verify the security_operations structure exists */
- if (!ops)
- return -EINVAL;
- security_fixup_ops(ops);
- return 0;
-}
-
static void __init do_security_initcalls(void)
{
initcall_t *call;
@@ -57,6 +49,11 @@ static void __init do_security_initcalls(void)
}
}

+static int __init security_enlist_ops(struct security_operations *sop);
+
+#ifdef CONFIG_SECURITY_YAMA_STACKED
+extern struct security_operations yama_ops;
+#endif
/**
* security_init - initializes the security framework
*
@@ -64,20 +61,30 @@ static void __init do_security_initcalls(void)
*/
int __init security_init(void)
{
+ int rc;
+
printk(KERN_INFO "Security Framework initialized\n");

- security_fixup_ops(&default_security_ops);
- security_ops = &default_security_ops;
+ /*
+ * Always load the capability module.
+ */
+ rc = security_enlist_ops(&capability_ops);
+ if (rc)
+ return rc;
+#ifdef CONFIG_SECURITY_YAMA_STACKED
+ rc = security_enlist_ops(&yama_ops);
+ if (rc)
+ return rc;
+#endif
+ /*
+ * Load the chosen module if there is one.
+ * This will also find yama if it is stacking
+ */
do_security_initcalls();

return 0;
}

-void reset_security_ops(void)
-{
- security_ops = &default_security_ops;
-}
-
/* Save user chosen LSM */
static int __init choose_lsm(char *str)
{
@@ -119,56 +126,115 @@ int __init security_module_enable(struct security_operations *ops)
*/
int __init register_security(struct security_operations *ops)
{
- if (verify(ops)) {
+ /*
+ * Verify the security_operations structure exists
+ */
+ if (!ops) {
printk(KERN_DEBUG "%s could not verify "
"security_operations structure.\n", __func__);
return -EINVAL;
}

- if (security_ops != &default_security_ops)
- return -EAGAIN;
-
- security_ops = ops;
- return 0;
+ return security_enlist_ops(ops);
}

/*
- * Hook operation macros.
+ * Hook list operation macros.
*
* call_void_hook:
* This is a hook that does not return a value.
*
* call_int_hook:
* This is a hook that returns a value.
+ * Stop on the first failure.
*/

-#define call_void_hook(FUNC, ...) security_ops->FUNC(__VA_ARGS__)
-#define call_int_hook(FUNC, ...) security_ops->FUNC(__VA_ARGS__)
+#ifdef CONFIG_SECURITY_SELINUX_DISABLE
+
+#define call_void_hook(FUNC, ...) \
+ do { \
+ struct security_hook_list *P; \
+ \
+ if (hooks_##FUNC.next == NULL) \
+ break; \
+ if (list_empty(&hooks_##FUNC)) \
+ break; \
+ \
+ list_for_each_entry(P, &hooks_##FUNC, shl_head) { \
+ if (P->shl_ops == NULL) \
+ continue; \
+ P->shl_ops->FUNC(__VA_ARGS__); \
+ } \
+ } while (0) \
+
+#define call_int_hook(FUNC, ...) ({ \
+ int RC = 0; \
+ do { \
+ struct security_hook_list *P; \
+ \
+ if (hooks_##FUNC.next == NULL) \
+ break; \
+ if (list_empty(&hooks_##FUNC)) \
+ break; \
+ \
+ list_for_each_entry(P, &hooks_##FUNC, shl_head) { \
+ if (P->shl_ops == NULL) \
+ continue; \
+ RC = P->shl_ops->FUNC(__VA_ARGS__); \
+ if (RC != 0) \
+ break; \
+ } \
+ } while (0); \
+ RC; \
+}) \
+
+#else /* CONFIG_SECURITY_SELINUX_DISABLE */
+
+#define call_void_hook(FUNC, ...) \
+ do { \
+ struct security_hook_list *P; \
+ \
+ if (list_empty(&hooks_##FUNC)) \
+ break; \
+ \
+ list_for_each_entry(P, &hooks_##FUNC, shl_head) \
+ P->shl_ops->FUNC(__VA_ARGS__); \
+ } while (0) \
+
+#define call_int_hook(FUNC, ...) ({ \
+ int RC = 0; \
+ do { \
+ struct security_hook_list *P; \
+ \
+ if (list_empty(&hooks_##FUNC)) \
+ break; \
+ \
+ list_for_each_entry(P, &hooks_##FUNC, shl_head) { \
+ RC = P->shl_ops->FUNC(__VA_ARGS__); \
+ if (RC != 0) \
+ break; \
+ } \
+ } while (0); \
+ RC; \
+}) \
+
+#endif /* CONFIG_SECURITY_SELINUX_DISABLE */

/* Security operations */

+static struct list_head hooks_ptrace_access_check;
int security_ptrace_access_check(struct task_struct *child, unsigned int mode)
{
-#ifdef CONFIG_SECURITY_YAMA_STACKED
- int rc;
- rc = yama_ptrace_access_check(child, mode);
- if (rc)
- return rc;
-#endif
return call_int_hook(ptrace_access_check, child, mode);
}

+static struct list_head hooks_ptrace_traceme;
int security_ptrace_traceme(struct task_struct *parent)
{
-#ifdef CONFIG_SECURITY_YAMA_STACKED
- int rc;
- rc = yama_ptrace_traceme(parent);
- if (rc)
- return rc;
-#endif
return call_int_hook(ptrace_traceme, parent);
}

+static struct list_head hooks_capget;
int security_capget(struct task_struct *target,
kernel_cap_t *effective,
kernel_cap_t *inheritable,
@@ -177,6 +243,7 @@ int security_capget(struct task_struct *target,
return call_int_hook(capget, target, effective, inheritable, permitted);
}

+static struct list_head hooks_capset;
int security_capset(struct cred *new, const struct cred *old,
const kernel_cap_t *effective,
const kernel_cap_t *inheritable,
@@ -186,6 +253,7 @@ int security_capset(struct cred *new, const struct cred *old,
effective, inheritable, permitted);
}

+static struct list_head hooks_capable;
int security_capable(const struct cred *cred, struct user_namespace *ns,
int cap)
{
@@ -202,36 +270,43 @@ int security_capable_noaudit(const struct cred *cred, struct user_namespace *ns,
return call_int_hook(capable, cred, ns, cap, SECURITY_CAP_NOAUDIT);
}

+static struct list_head hooks_quotactl;
int security_quotactl(int cmds, int type, int id, struct super_block *sb)
{
return call_int_hook(quotactl, cmds, type, id, sb);
}

+static struct list_head hooks_quota_on;
int security_quota_on(struct dentry *dentry)
{
return call_int_hook(quota_on, dentry);
}

+static struct list_head hooks_syslog;
int security_syslog(int type)
{
return call_int_hook(syslog, type);
}

+static struct list_head hooks_settime;
int security_settime(const struct timespec *ts, const struct timezone *tz)
{
return call_int_hook(settime, ts, tz);
}

+static struct list_head hooks_vm_enough_memory;
int security_vm_enough_memory_mm(struct mm_struct *mm, long pages)
{
return call_int_hook(vm_enough_memory, mm, pages);
}

+static struct list_head hooks_bprm_set_creds;
int security_bprm_set_creds(struct linux_binprm *bprm)
{
return call_int_hook(bprm_set_creds, bprm);
}

+static struct list_head hooks_bprm_check_security;
int security_bprm_check(struct linux_binprm *bprm)
{
int ret;
@@ -242,83 +317,110 @@ int security_bprm_check(struct linux_binprm *bprm)
return ima_bprm_check(bprm);
}

+static struct list_head hooks_bprm_committing_creds;
void security_bprm_committing_creds(struct linux_binprm *bprm)
{
call_void_hook(bprm_committing_creds, bprm);
}

+static struct list_head hooks_bprm_committed_creds;
void security_bprm_committed_creds(struct linux_binprm *bprm)
{
call_void_hook(bprm_committed_creds, bprm);
}

+static struct list_head hooks_bprm_secureexec;
int security_bprm_secureexec(struct linux_binprm *bprm)
{
+ /*
+ * SELinux and Smack integrate the cap call,
+ * so assume that all LSMs supplying this call do so.
+ */
+ if (list_empty(&hooks_bprm_secureexec))
+ return cap_bprm_secureexec(bprm);
+
return call_int_hook(bprm_secureexec, bprm);
}

+static struct list_head hooks_sb_alloc_security;
int security_sb_alloc(struct super_block *sb)
{
return call_int_hook(sb_alloc_security, sb);
}

+static struct list_head hooks_sb_free_security;
void security_sb_free(struct super_block *sb)
{
call_void_hook(sb_free_security, sb);
}

+static struct list_head hooks_sb_copy_data;
int security_sb_copy_data(char *orig, char *copy)
{
return call_int_hook(sb_copy_data, orig, copy);
}
EXPORT_SYMBOL(security_sb_copy_data);

+static struct list_head hooks_sb_remount;
int security_sb_remount(struct super_block *sb, void *data)
{
return call_int_hook(sb_remount, sb, data);
}

+static struct list_head hooks_sb_kern_mount;
int security_sb_kern_mount(struct super_block *sb, int flags, void *data)
{
return call_int_hook(sb_kern_mount, sb, flags, data);
}

+static struct list_head hooks_sb_show_options;
int security_sb_show_options(struct seq_file *m, struct super_block *sb)
{
return call_int_hook(sb_show_options, m, sb);
}

+static struct list_head hooks_sb_statfs;
int security_sb_statfs(struct dentry *dentry)
{
return call_int_hook(sb_statfs, dentry);
}

+static struct list_head hooks_sb_mount;
int security_sb_mount(const char *dev_name, struct path *path,
const char *type, unsigned long flags, void *data)
{
return call_int_hook(sb_mount, dev_name, path, type, flags, data);
}

+static struct list_head hooks_sb_umount;
int security_sb_umount(struct vfsmount *mnt, int flags)
{
return call_int_hook(sb_umount, mnt, flags);
}

+static struct list_head hooks_sb_pivotroot;
int security_sb_pivotroot(struct path *old_path, struct path *new_path)
{
return call_int_hook(sb_pivotroot, old_path, new_path);
}

+static struct list_head hooks_sb_set_mnt_opts;
int security_sb_set_mnt_opts(struct super_block *sb,
struct security_mnt_opts *opts,
unsigned long kern_flags,
unsigned long *set_kern_flags)
{
+ if (list_empty(&hooks_sb_set_mnt_opts)) {
+ if (unlikely(opts->num_mnt_opts))
+ return -EOPNOTSUPP;
+ }
+
return call_int_hook(sb_set_mnt_opts, sb, opts, kern_flags,
set_kern_flags);
}
EXPORT_SYMBOL(security_sb_set_mnt_opts);

+static struct list_head hooks_sb_clone_mnt_opts;
int security_sb_clone_mnt_opts(const struct super_block *oldsb,
struct super_block *newsb)
{
@@ -326,33 +428,40 @@ int security_sb_clone_mnt_opts(const struct super_block *oldsb,
}
EXPORT_SYMBOL(security_sb_clone_mnt_opts);

+static struct list_head hooks_sb_parse_opts_str;
int security_sb_parse_opts_str(char *options, struct security_mnt_opts *opts)
{
return call_int_hook(sb_parse_opts_str, options, opts);
}
EXPORT_SYMBOL(security_sb_parse_opts_str);

+static struct list_head hooks_inode_alloc_security;
int security_inode_alloc(struct inode *inode)
{
inode->i_security = NULL;
return call_int_hook(inode_alloc_security, inode);
}

+static struct list_head hooks_inode_free_security;
void security_inode_free(struct inode *inode)
{
integrity_inode_free(inode);
call_void_hook(inode_free_security, inode);
}

+static struct list_head hooks_dentry_init_security;
int security_dentry_init_security(struct dentry *dentry, int mode,
struct qstr *name, void **ctx,
u32 *ctxlen)
{
+ if (list_empty(&hooks_dentry_init_security))
+ return -EOPNOTSUPP;
return call_int_hook(dentry_init_security, dentry, mode, name,
ctx, ctxlen);
}
EXPORT_SYMBOL(security_dentry_init_security);

+static struct list_head hooks_inode_init_security;
int security_inode_init_security(struct inode *inode, struct inode *dir,
const struct qstr *qstr,
const initxattrs initxattrs, void *fs_data)
@@ -364,11 +473,15 @@ int security_inode_init_security(struct inode *inode, struct inode *dir,
if (unlikely(IS_PRIVATE(inode)))
return 0;

+ if (list_empty(&hooks_inode_init_security))
+ return 0;
+
if (!initxattrs)
return call_int_hook(inode_init_security, inode, dir, qstr,
NULL, NULL, NULL);
memset(new_xattrs, 0, sizeof(new_xattrs));
lsm_xattr = new_xattrs;
+
ret = call_int_hook(inode_init_security, inode, dir, qstr,
&lsm_xattr->name,
&lsm_xattr->value,
@@ -397,6 +510,8 @@ int security_old_inode_init_security(struct inode *inode, struct inode *dir,
{
if (unlikely(IS_PRIVATE(inode)))
return -EOPNOTSUPP;
+ if (list_empty(&hooks_inode_init_security))
+ return 0;

return call_int_hook(inode_init_security, inode, dir, qstr, name,
value, len);
@@ -404,6 +519,7 @@ int security_old_inode_init_security(struct inode *inode, struct inode *dir,
EXPORT_SYMBOL(security_old_inode_init_security);

#ifdef CONFIG_SECURITY_PATH
+static struct list_head hooks_path_mknod;
int security_path_mknod(struct path *dir, struct dentry *dentry, umode_t mode,
unsigned int dev)
{
@@ -413,6 +529,7 @@ int security_path_mknod(struct path *dir, struct dentry *dentry, umode_t mode,
}
EXPORT_SYMBOL(security_path_mknod);

+static struct list_head hooks_path_mkdir;
int security_path_mkdir(struct path *dir, struct dentry *dentry, umode_t mode)
{
if (unlikely(IS_PRIVATE(dir->dentry->d_inode)))
@@ -421,6 +538,7 @@ int security_path_mkdir(struct path *dir, struct dentry *dentry, umode_t mode)
}
EXPORT_SYMBOL(security_path_mkdir);

+static struct list_head hooks_path_rmdir;
int security_path_rmdir(struct path *dir, struct dentry *dentry)
{
if (unlikely(IS_PRIVATE(dir->dentry->d_inode)))
@@ -428,6 +546,7 @@ int security_path_rmdir(struct path *dir, struct dentry *dentry)
return call_int_hook(path_rmdir, dir, dentry);
}

+static struct list_head hooks_path_unlink;
int security_path_unlink(struct path *dir, struct dentry *dentry)
{
if (unlikely(IS_PRIVATE(dir->dentry->d_inode)))
@@ -436,6 +555,7 @@ int security_path_unlink(struct path *dir, struct dentry *dentry)
}
EXPORT_SYMBOL(security_path_unlink);

+static struct list_head hooks_path_symlink;
int security_path_symlink(struct path *dir, struct dentry *dentry,
const char *old_name)
{
@@ -444,6 +564,7 @@ int security_path_symlink(struct path *dir, struct dentry *dentry,
return call_int_hook(path_symlink, dir, dentry, old_name);
}

+static struct list_head hooks_path_link;
int security_path_link(struct dentry *old_dentry, struct path *new_dir,
struct dentry *new_dentry)
{
@@ -452,6 +573,7 @@ int security_path_link(struct dentry *old_dentry, struct path *new_dir,
return call_int_hook(path_link, old_dentry, new_dir, new_dentry);
}

+static struct list_head hooks_path_rename;
int security_path_rename(struct path *old_dir, struct dentry *old_dentry,
struct path *new_dir, struct dentry *new_dentry,
unsigned int flags)
@@ -472,6 +594,7 @@ int security_path_rename(struct path *old_dir, struct dentry *old_dentry,
}
EXPORT_SYMBOL(security_path_rename);

+static struct list_head hooks_path_truncate;
int security_path_truncate(struct path *path)
{
if (unlikely(IS_PRIVATE(path->dentry->d_inode)))
@@ -479,6 +602,7 @@ int security_path_truncate(struct path *path)
return call_int_hook(path_truncate, path);
}

+static struct list_head hooks_path_chmod;
int security_path_chmod(struct path *path, umode_t mode)
{
if (unlikely(IS_PRIVATE(path->dentry->d_inode)))
@@ -486,6 +610,7 @@ int security_path_chmod(struct path *path, umode_t mode)
return call_int_hook(path_chmod, path, mode);
}

+static struct list_head hooks_path_chown;
int security_path_chown(struct path *path, kuid_t uid, kgid_t gid)
{
if (unlikely(IS_PRIVATE(path->dentry->d_inode)))
@@ -493,12 +618,14 @@ int security_path_chown(struct path *path, kuid_t uid, kgid_t gid)
return call_int_hook(path_chown, path, uid, gid);
}

+static struct list_head hooks_path_chroot;
int security_path_chroot(struct path *path)
{
return call_int_hook(path_chroot, path);
}
#endif

+static struct list_head hooks_inode_create;
int security_inode_create(struct inode *dir, struct dentry *dentry, umode_t mode)
{
if (unlikely(IS_PRIVATE(dir)))
@@ -507,6 +634,7 @@ int security_inode_create(struct inode *dir, struct dentry *dentry, umode_t mode
}
EXPORT_SYMBOL_GPL(security_inode_create);

+static struct list_head hooks_inode_link;
int security_inode_link(struct dentry *old_dentry, struct inode *dir,
struct dentry *new_dentry)
{
@@ -515,6 +643,7 @@ int security_inode_link(struct dentry *old_dentry, struct inode *dir,
return call_int_hook(inode_link, old_dentry, dir, new_dentry);
}

+static struct list_head hooks_inode_unlink;
int security_inode_unlink(struct inode *dir, struct dentry *dentry)
{
if (unlikely(IS_PRIVATE(dentry->d_inode)))
@@ -522,6 +651,7 @@ int security_inode_unlink(struct inode *dir, struct dentry *dentry)
return call_int_hook(inode_unlink, dir, dentry);
}

+static struct list_head hooks_inode_symlink;
int security_inode_symlink(struct inode *dir, struct dentry *dentry,
const char *old_name)
{
@@ -530,6 +660,7 @@ int security_inode_symlink(struct inode *dir, struct dentry *dentry,
return call_int_hook(inode_symlink, dir, dentry, old_name);
}

+static struct list_head hooks_inode_mkdir;
int security_inode_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
{
if (unlikely(IS_PRIVATE(dir)))
@@ -538,6 +669,7 @@ int security_inode_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
}
EXPORT_SYMBOL_GPL(security_inode_mkdir);

+static struct list_head hooks_inode_rmdir;
int security_inode_rmdir(struct inode *dir, struct dentry *dentry)
{
if (unlikely(IS_PRIVATE(dentry->d_inode)))
@@ -545,6 +677,7 @@ int security_inode_rmdir(struct inode *dir, struct dentry *dentry)
return call_int_hook(inode_rmdir, dir, dentry);
}

+static struct list_head hooks_inode_mknod;
int security_inode_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t dev)
{
if (unlikely(IS_PRIVATE(dir)))
@@ -552,6 +685,7 @@ int security_inode_mknod(struct inode *dir, struct dentry *dentry, umode_t mode,
return call_int_hook(inode_mknod, dir, dentry, mode, dev);
}

+static struct list_head hooks_inode_rename;
int security_inode_rename(struct inode *old_dir, struct dentry *old_dentry,
struct inode *new_dir, struct dentry *new_dentry,
unsigned int flags)
@@ -571,6 +705,7 @@ int security_inode_rename(struct inode *old_dir, struct dentry *old_dentry,
new_dir, new_dentry);
}

+static struct list_head hooks_inode_readlink;
int security_inode_readlink(struct dentry *dentry)
{
if (unlikely(IS_PRIVATE(dentry->d_inode)))
@@ -578,6 +713,7 @@ int security_inode_readlink(struct dentry *dentry)
return call_int_hook(inode_readlink, dentry);
}

+static struct list_head hooks_inode_follow_link;
int security_inode_follow_link(struct dentry *dentry, struct nameidata *nd)
{
if (unlikely(IS_PRIVATE(dentry->d_inode)))
@@ -585,6 +721,7 @@ int security_inode_follow_link(struct dentry *dentry, struct nameidata *nd)
return call_int_hook(inode_follow_link, dentry, nd);
}

+static struct list_head hooks_inode_permission;
int security_inode_permission(struct inode *inode, int mask)
{
if (unlikely(IS_PRIVATE(inode)))
@@ -592,6 +729,7 @@ int security_inode_permission(struct inode *inode, int mask)
return call_int_hook(inode_permission, inode, mask);
}

+static struct list_head hooks_inode_setattr;
int security_inode_setattr(struct dentry *dentry, struct iattr *attr)
{
int ret;
@@ -605,6 +743,7 @@ int security_inode_setattr(struct dentry *dentry, struct iattr *attr)
}
EXPORT_SYMBOL_GPL(security_inode_setattr);

+static struct list_head hooks_inode_getattr;
int security_inode_getattr(struct vfsmount *mnt, struct dentry *dentry)
{
if (unlikely(IS_PRIVATE(dentry->d_inode)))
@@ -612,6 +751,7 @@ int security_inode_getattr(struct vfsmount *mnt, struct dentry *dentry)
return call_int_hook(inode_getattr, mnt, dentry);
}

+static struct list_head hooks_inode_setxattr;
int security_inode_setxattr(struct dentry *dentry, const char *name,
const void *value, size_t size, int flags)
{
@@ -619,7 +759,15 @@ int security_inode_setxattr(struct dentry *dentry, const char *name,

if (unlikely(IS_PRIVATE(dentry->d_inode)))
return 0;
- ret = call_int_hook(inode_setxattr, dentry, name, value, size, flags);
+ /*
+ * SELinux and Smack integrate the cap call,
+ * so assume that all LSMs supplying this call do so.
+ */
+ if (list_empty(&hooks_inode_setxattr))
+ ret = cap_inode_setxattr(dentry, name, value, size, flags);
+ else
+ ret = call_int_hook(inode_setxattr, dentry, name, value,
+ size, flags);

if (ret)
return ret;
@@ -629,6 +777,7 @@ int security_inode_setxattr(struct dentry *dentry, const char *name,
return evm_inode_setxattr(dentry, name, value, size);
}

+static struct list_head hooks_inode_post_setxattr;
void security_inode_post_setxattr(struct dentry *dentry, const char *name,
const void *value, size_t size, int flags)
{
@@ -638,6 +787,7 @@ void security_inode_post_setxattr(struct dentry *dentry, const char *name,
evm_inode_post_setxattr(dentry, name, value, size);
}

+static struct list_head hooks_inode_getxattr;
int security_inode_getxattr(struct dentry *dentry, const char *name)
{
if (unlikely(IS_PRIVATE(dentry->d_inode)))
@@ -645,6 +795,7 @@ int security_inode_getxattr(struct dentry *dentry, const char *name)
return call_int_hook(inode_getxattr, dentry, name);
}

+static struct list_head hooks_inode_listxattr;
int security_inode_listxattr(struct dentry *dentry)
{
if (unlikely(IS_PRIVATE(dentry->d_inode)))
@@ -652,13 +803,19 @@ int security_inode_listxattr(struct dentry *dentry)
return call_int_hook(inode_listxattr, dentry);
}

+static struct list_head hooks_inode_removexattr;
int security_inode_removexattr(struct dentry *dentry, const char *name)
{
int ret;

if (unlikely(IS_PRIVATE(dentry->d_inode)))
return 0;
- ret = call_int_hook(inode_removexattr, dentry, name);
+
+ if (list_empty(&hooks_inode_removexattr))
+ ret = cap_inode_removexattr(dentry, name);
+ else
+ ret = call_int_hook(inode_removexattr, dentry, name);
+
if (ret)
return ret;
ret = ima_inode_removexattr(dentry, name);
@@ -667,31 +824,40 @@ int security_inode_removexattr(struct dentry *dentry, const char *name)
return evm_inode_removexattr(dentry, name);
}

+static struct list_head hooks_inode_need_killpriv;
int security_inode_need_killpriv(struct dentry *dentry)
{
return call_int_hook(inode_need_killpriv, dentry);
}

+static struct list_head hooks_inode_killpriv;
int security_inode_killpriv(struct dentry *dentry)
{
return call_int_hook(inode_killpriv, dentry);
}

+static struct list_head hooks_inode_getsecurity;
int security_inode_getsecurity(const struct inode *inode, const char *name, void **buffer, bool alloc)
{
if (unlikely(IS_PRIVATE(inode)))
return -EOPNOTSUPP;
+ if (list_empty(&hooks_inode_getsecurity))
+ return -EOPNOTSUPP;
return call_int_hook(inode_getsecurity, inode, name, buffer, alloc);
}

+static struct list_head hooks_inode_setsecurity;
int security_inode_setsecurity(struct inode *inode, const char *name, const void *value, size_t size, int flags)
{
if (unlikely(IS_PRIVATE(inode)))
return -EOPNOTSUPP;
+ if (list_empty(&hooks_inode_setsecurity))
+ return -EOPNOTSUPP;
return call_int_hook(inode_setsecurity, inode, name, value, size,
flags);
}

+static struct list_head hooks_inode_listsecurity;
int security_inode_listsecurity(struct inode *inode, char *buffer, size_t buffer_size)
{
if (unlikely(IS_PRIVATE(inode)))
@@ -700,11 +866,16 @@ int security_inode_listsecurity(struct inode *inode, char *buffer, size_t buffer
}
EXPORT_SYMBOL(security_inode_listsecurity);

+static struct list_head hooks_inode_getsecid;
void security_inode_getsecid(const struct inode *inode, u32 *secid)
{
- call_void_hook(inode_getsecid, inode, secid);
+ if (list_empty(&hooks_inode_getsecid))
+ *secid = 0;
+ else
+ call_void_hook(inode_getsecid, inode, secid);
}

+static struct list_head hooks_file_permission;
int security_file_permission(struct file *file, int mask)
{
int ret;
@@ -716,16 +887,19 @@ int security_file_permission(struct file *file, int mask)
return fsnotify_perm(file, mask);
}

+static struct list_head hooks_file_alloc_security;
int security_file_alloc(struct file *file)
{
return call_int_hook(file_alloc_security, file);
}

+static struct list_head hooks_file_free_security;
void security_file_free(struct file *file)
{
call_void_hook(file_free_security, file);
}

+static struct list_head hooks_file_ioctl;
int security_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
return call_int_hook(file_ioctl, file, cmd, arg);
@@ -765,6 +939,7 @@ static inline unsigned long mmap_prot(struct file *file, unsigned long prot)
return prot;
}

+static struct list_head hooks_mmap_file;
int security_mmap_file(struct file *file, unsigned long prot,
unsigned long flags)
{
@@ -776,43 +951,51 @@ int security_mmap_file(struct file *file, unsigned long prot,
return ima_file_mmap(file, prot);
}

+static struct list_head hooks_mmap_addr;
int security_mmap_addr(unsigned long addr)
{
return call_int_hook(mmap_addr, addr);
}

+static struct list_head hooks_file_mprotect;
int security_file_mprotect(struct vm_area_struct *vma, unsigned long reqprot,
unsigned long prot)
{
return call_int_hook(file_mprotect, vma, reqprot, prot);
}

+static struct list_head hooks_file_lock;
int security_file_lock(struct file *file, unsigned int cmd)
{
return call_int_hook(file_lock, file, cmd);
}

+static struct list_head hooks_file_fcntl;
int security_file_fcntl(struct file *file, unsigned int cmd, unsigned long arg)
{
return call_int_hook(file_fcntl, file, cmd, arg);
}

+static struct list_head hooks_file_set_fowner;
int security_file_set_fowner(struct file *file)
{
return call_int_hook(file_set_fowner, file);
}

+static struct list_head hooks_file_send_sigiotask;
int security_file_send_sigiotask(struct task_struct *tsk,
struct fown_struct *fown, int sig)
{
return call_int_hook(file_send_sigiotask, tsk, fown, sig);
}

+static struct list_head hooks_file_receive;
int security_file_receive(struct file *file)
{
return call_int_hook(file_receive, file);
}

+static struct list_head hooks_file_open;
int security_file_open(struct file *file, const struct cred *cred)
{
int ret;
@@ -824,54 +1007,61 @@ int security_file_open(struct file *file, const struct cred *cred)
return fsnotify_perm(file, MAY_OPEN);
}

+static struct list_head hooks_task_create;
int security_task_create(unsigned long clone_flags)
{
return call_int_hook(task_create, clone_flags);
}

+static struct list_head hooks_task_free;
void security_task_free(struct task_struct *task)
{
-#ifdef CONFIG_SECURITY_YAMA_STACKED
- yama_task_free(task);
-#endif
call_void_hook(task_free, task);
}

+static struct list_head hooks_cred_alloc_blank;
int security_cred_alloc_blank(struct cred *cred, gfp_t gfp)
{
return call_int_hook(cred_alloc_blank, cred, gfp);
}

+static struct list_head hooks_cred_free;
void security_cred_free(struct cred *cred)
{
call_void_hook(cred_free, cred);
}

+static struct list_head hooks_cred_prepare;
int security_prepare_creds(struct cred *new, const struct cred *old, gfp_t gfp)
{
return call_int_hook(cred_prepare, new, old, gfp);
}

+static struct list_head hooks_cred_transfer;
void security_transfer_creds(struct cred *new, const struct cred *old)
{
call_void_hook(cred_transfer, new, old);
}

+static struct list_head hooks_kernel_act_as;
int security_kernel_act_as(struct cred *new, u32 secid)
{
return call_int_hook(kernel_act_as, new, secid);
}

+static struct list_head hooks_kernel_create_files_as;
int security_kernel_create_files_as(struct cred *new, struct inode *inode)
{
return call_int_hook(kernel_create_files_as, new, inode);
}

+static struct list_head hooks_kernel_module_request;
int security_kernel_module_request(char *kmod_name)
{
return call_int_hook(kernel_module_request, kmod_name);
}

+static struct list_head hooks_kernel_module_from_file;
int security_kernel_module_from_file(struct file *file)
{
int ret;
@@ -882,200 +1072,257 @@ int security_kernel_module_from_file(struct file *file)
return ima_module_check(file);
}

+static struct list_head hooks_task_fix_setuid;
int security_task_fix_setuid(struct cred *new, const struct cred *old,
int flags)
{
return call_int_hook(task_fix_setuid, new, old, flags);
}

+static struct list_head hooks_task_setpgid;
int security_task_setpgid(struct task_struct *p, pid_t pgid)
{
return call_int_hook(task_setpgid, p, pgid);
}

+static struct list_head hooks_task_getpgid;
int security_task_getpgid(struct task_struct *p)
{
return call_int_hook(task_getpgid, p);
}

+static struct list_head hooks_task_getsid;
int security_task_getsid(struct task_struct *p)
{
return call_int_hook(task_getsid, p);
}

+static struct list_head hooks_task_getsecid;
void security_task_getsecid(struct task_struct *p, u32 *secid)
{
- call_void_hook(task_getsecid, p, secid);
+ if (list_empty(&hooks_task_getsecid))
+ *secid = 0;
+ else
+ call_void_hook(task_getsecid, p, secid);
}
EXPORT_SYMBOL(security_task_getsecid);

+static struct list_head hooks_task_setnice;
int security_task_setnice(struct task_struct *p, int nice)
{
return call_int_hook(task_setnice, p, nice);
}

+static struct list_head hooks_task_setioprio;
int security_task_setioprio(struct task_struct *p, int ioprio)
{
return call_int_hook(task_setioprio, p, ioprio);
}

+static struct list_head hooks_task_getioprio;
int security_task_getioprio(struct task_struct *p)
{
return call_int_hook(task_getioprio, p);
}

+static struct list_head hooks_task_setrlimit;
int security_task_setrlimit(struct task_struct *p, unsigned int resource,
struct rlimit *new_rlim)
{
return call_int_hook(task_setrlimit, p, resource, new_rlim);
}

+static struct list_head hooks_task_setscheduler;
int security_task_setscheduler(struct task_struct *p)
{
return call_int_hook(task_setscheduler, p);
}

+static struct list_head hooks_task_getscheduler;
int security_task_getscheduler(struct task_struct *p)
{
return call_int_hook(task_getscheduler, p);
}

+static struct list_head hooks_task_movememory;
int security_task_movememory(struct task_struct *p)
{
return call_int_hook(task_movememory, p);
}

+static struct list_head hooks_task_kill;
int security_task_kill(struct task_struct *p, struct siginfo *info,
int sig, u32 secid)
{
return call_int_hook(task_kill, p, info, sig, secid);
}

+static struct list_head hooks_task_wait;
int security_task_wait(struct task_struct *p)
{
return call_int_hook(task_wait, p);
}

+static struct list_head hooks_task_prctl;
int security_task_prctl(int option, unsigned long arg2, unsigned long arg3,
unsigned long arg4, unsigned long arg5)
{
-#ifdef CONFIG_SECURITY_YAMA_STACKED
- int rc;
- rc = yama_task_prctl(option, arg2, arg3, arg4, arg5);
- if (rc != -ENOSYS)
- return rc;
+ int thisrc;
+ int rc = -ENOSYS;
+ struct security_hook_list *shp;
+
+ if (list_empty(&hooks_task_prctl))
+ return -ENOSYS;
+
+ list_for_each_entry(shp, &hooks_task_prctl, shl_head) {
+#ifdef CONFIG_SECURITY_SELINUX_DISABLE
+ if (shp->shl_ops == NULL)
+ continue;
#endif
- return call_int_hook(task_prctl, option, arg2, arg3, arg4, arg5);
+ thisrc = shp->shl_ops->task_prctl(option, arg2, arg3,
+ arg4, arg5);
+ if (thisrc != -ENOSYS) {
+ rc = thisrc;
+ if (thisrc != 0)
+ break;
+ }
+ }
+ return rc;
}

+static struct list_head hooks_task_to_inode;
void security_task_to_inode(struct task_struct *p, struct inode *inode)
{
call_void_hook(task_to_inode, p, inode);
}

+static struct list_head hooks_ipc_permission;
int security_ipc_permission(struct kern_ipc_perm *ipcp, short flag)
{
return call_int_hook(ipc_permission, ipcp, flag);
}

+static struct list_head hooks_ipc_getsecid;
void security_ipc_getsecid(struct kern_ipc_perm *ipcp, u32 *secid)
{
- call_void_hook(ipc_getsecid, ipcp, secid);
+ if (list_empty(&hooks_ipc_getsecid))
+ *secid = 0;
+ else
+ call_void_hook(ipc_getsecid, ipcp, secid);
}

+static struct list_head hooks_msg_msg_alloc_security;
int security_msg_msg_alloc(struct msg_msg *msg)
{
return call_int_hook(msg_msg_alloc_security, msg);
}

+static struct list_head hooks_msg_msg_free_security;
void security_msg_msg_free(struct msg_msg *msg)
{
call_void_hook(msg_msg_free_security, msg);
}

+static struct list_head hooks_msg_queue_alloc_security;
int security_msg_queue_alloc(struct msg_queue *msq)
{
return call_int_hook(msg_queue_alloc_security, msq);
}

+static struct list_head hooks_msg_queue_free_security;
void security_msg_queue_free(struct msg_queue *msq)
{
call_void_hook(msg_queue_free_security, msq);
}

+static struct list_head hooks_msg_queue_associate;
int security_msg_queue_associate(struct msg_queue *msq, int msqflg)
{
return call_int_hook(msg_queue_associate, msq, msqflg);
}

+static struct list_head hooks_msg_queue_msgctl;
int security_msg_queue_msgctl(struct msg_queue *msq, int cmd)
{
return call_int_hook(msg_queue_msgctl, msq, cmd);
}

+static struct list_head hooks_msg_queue_msgsnd;
int security_msg_queue_msgsnd(struct msg_queue *msq,
struct msg_msg *msg, int msqflg)
{
return call_int_hook(msg_queue_msgsnd, msq, msg, msqflg);
}

+static struct list_head hooks_msg_queue_msgrcv;
int security_msg_queue_msgrcv(struct msg_queue *msq, struct msg_msg *msg,
struct task_struct *target, long type, int mode)
{
return call_int_hook(msg_queue_msgrcv, msq, msg, target, type, mode);
}

+static struct list_head hooks_shm_alloc_security;
int security_shm_alloc(struct shmid_kernel *shp)
{
return call_int_hook(shm_alloc_security, shp);
}

+static struct list_head hooks_shm_free_security;
void security_shm_free(struct shmid_kernel *shp)
{
call_void_hook(shm_free_security, shp);
}

+static struct list_head hooks_shm_associate;
int security_shm_associate(struct shmid_kernel *shp, int shmflg)
{
return call_int_hook(shm_associate, shp, shmflg);
}

+static struct list_head hooks_shm_shmctl;
int security_shm_shmctl(struct shmid_kernel *shp, int cmd)
{
return call_int_hook(shm_shmctl, shp, cmd);
}

+static struct list_head hooks_shm_shmat;
int security_shm_shmat(struct shmid_kernel *shp, char __user *shmaddr, int shmflg)
{
return call_int_hook(shm_shmat, shp, shmaddr, shmflg);
}

+static struct list_head hooks_sem_alloc_security;
int security_sem_alloc(struct sem_array *sma)
{
return call_int_hook(sem_alloc_security, sma);
}

+static struct list_head hooks_sem_free_security;
void security_sem_free(struct sem_array *sma)
{
call_void_hook(sem_free_security, sma);
}

+static struct list_head hooks_sem_associate;
int security_sem_associate(struct sem_array *sma, int semflg)
{
return call_int_hook(sem_associate, sma, semflg);
}

+static struct list_head hooks_sem_semctl;
int security_sem_semctl(struct sem_array *sma, int cmd)
{
return call_int_hook(sem_semctl, sma, cmd);
}

+static struct list_head hooks_sem_semop;
int security_sem_semop(struct sem_array *sma, struct sembuf *sops,
unsigned nsops, int alter)
{
return call_int_hook(sem_semop, sma, sops, nsops, alter);
}

+static struct list_head hooks_d_instantiate;
void security_d_instantiate(struct dentry *dentry, struct inode *inode)
{
if (unlikely(inode && IS_PRIVATE(inode)))
@@ -1084,82 +1331,108 @@ void security_d_instantiate(struct dentry *dentry, struct inode *inode)
}
EXPORT_SYMBOL(security_d_instantiate);

+static struct list_head hooks_getprocattr;
int security_getprocattr(struct task_struct *p, char *name, char **value)
{
+ if (list_empty(&hooks_getprocattr))
+ return -EINVAL;
return call_int_hook(getprocattr, p, name, value);
}

+static struct list_head hooks_setprocattr;
int security_setprocattr(struct task_struct *p, char *name, void *value, size_t size)
{
+ if (list_empty(&hooks_setprocattr))
+ return -EINVAL;
return call_int_hook(setprocattr, p, name, value, size);
}

+static struct list_head hooks_netlink_send;
int security_netlink_send(struct sock *sk, struct sk_buff *skb)
{
return call_int_hook(netlink_send, sk, skb);
}

+static struct list_head hooks_ismaclabel;
int security_ismaclabel(const char *name)
{
return call_int_hook(ismaclabel, name);
}
EXPORT_SYMBOL(security_ismaclabel);

+static struct list_head hooks_secid_to_secctx;
int security_secid_to_secctx(u32 secid, char **secdata, u32 *seclen)
{
+ if (list_empty(&hooks_secid_to_secctx))
+ return -EOPNOTSUPP;
return call_int_hook(secid_to_secctx, secid, secdata, seclen);
}
EXPORT_SYMBOL(security_secid_to_secctx);

+static struct list_head hooks_secctx_to_secid;
int security_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid)
{
+ if (list_empty(&hooks_secctx_to_secid)) {
+ *secid = 0;
+ return 0;
+ }
return call_int_hook(secctx_to_secid, secdata, seclen, secid);
}
EXPORT_SYMBOL(security_secctx_to_secid);

+static struct list_head hooks_release_secctx;
void security_release_secctx(char *secdata, u32 seclen)
{
call_void_hook(release_secctx, secdata, seclen);
}
EXPORT_SYMBOL(security_release_secctx);

+static struct list_head hooks_inode_notifysecctx;
int security_inode_notifysecctx(struct inode *inode, void *ctx, u32 ctxlen)
{
return call_int_hook(inode_notifysecctx, inode, ctx, ctxlen);
}
EXPORT_SYMBOL(security_inode_notifysecctx);

+static struct list_head hooks_inode_setsecctx;
int security_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen)
{
return call_int_hook(inode_setsecctx, dentry, ctx, ctxlen);
}
EXPORT_SYMBOL(security_inode_setsecctx);

+static struct list_head hooks_inode_getsecctx;
int security_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen)
{
+ if (list_empty(&hooks_inode_getsecctx))
+ return -EOPNOTSUPP;
return call_int_hook(inode_getsecctx, inode, ctx, ctxlen);
}
EXPORT_SYMBOL(security_inode_getsecctx);

#ifdef CONFIG_SECURITY_NETWORK

+static struct list_head hooks_unix_stream_connect;
int security_unix_stream_connect(struct sock *sock, struct sock *other, struct sock *newsk)
{
return call_int_hook(unix_stream_connect, sock, other, newsk);
}
EXPORT_SYMBOL(security_unix_stream_connect);

+static struct list_head hooks_unix_may_send;
int security_unix_may_send(struct socket *sock, struct socket *other)
{
return call_int_hook(unix_may_send, sock, other);
}
EXPORT_SYMBOL(security_unix_may_send);

+static struct list_head hooks_socket_create;
int security_socket_create(int family, int type, int protocol, int kern)
{
return call_int_hook(socket_create, family, type, protocol, kern);
}

+static struct list_head hooks_socket_post_create;
int security_socket_post_create(struct socket *sock, int family,
int type, int protocol, int kern)
{
@@ -1167,115 +1440,140 @@ int security_socket_post_create(struct socket *sock, int family,
protocol, kern);
}

+static struct list_head hooks_socket_bind;
int security_socket_bind(struct socket *sock, struct sockaddr *address, int addrlen)
{
return call_int_hook(socket_bind, sock, address, addrlen);
}

+static struct list_head hooks_socket_connect;
int security_socket_connect(struct socket *sock, struct sockaddr *address, int addrlen)
{
return call_int_hook(socket_connect, sock, address, addrlen);
}

+static struct list_head hooks_socket_listen;
int security_socket_listen(struct socket *sock, int backlog)
{
return call_int_hook(socket_listen, sock, backlog);
}

+static struct list_head hooks_socket_accept;
int security_socket_accept(struct socket *sock, struct socket *newsock)
{
return call_int_hook(socket_accept, sock, newsock);
}

+static struct list_head hooks_socket_sendmsg;
int security_socket_sendmsg(struct socket *sock, struct msghdr *msg, int size)
{
return call_int_hook(socket_sendmsg, sock, msg, size);
}

+static struct list_head hooks_socket_recvmsg;
int security_socket_recvmsg(struct socket *sock, struct msghdr *msg,
int size, int flags)
{
return call_int_hook(socket_recvmsg, sock, msg, size, flags);
}

+static struct list_head hooks_socket_getsockname;
int security_socket_getsockname(struct socket *sock)
{
return call_int_hook(socket_getsockname, sock);
}

+static struct list_head hooks_socket_getpeername;
int security_socket_getpeername(struct socket *sock)
{
return call_int_hook(socket_getpeername, sock);
}

+static struct list_head hooks_socket_getsockopt;
int security_socket_getsockopt(struct socket *sock, int level, int optname)
{
return call_int_hook(socket_getsockopt, sock, level, optname);
}

+static struct list_head hooks_socket_setsockopt;
int security_socket_setsockopt(struct socket *sock, int level, int optname)
{
return call_int_hook(socket_setsockopt, sock, level, optname);
}

+static struct list_head hooks_socket_shutdown;
int security_socket_shutdown(struct socket *sock, int how)
{
return call_int_hook(socket_shutdown, sock, how);
}

+static struct list_head hooks_socket_sock_rcv_skb;
int security_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
{
return call_int_hook(socket_sock_rcv_skb, sk, skb);
}
EXPORT_SYMBOL(security_sock_rcv_skb);

+static struct list_head hooks_socket_getpeersec_stream;
int security_socket_getpeersec_stream(struct socket *sock, char __user *optval,
int __user *optlen, unsigned len)
{
+ if (list_empty(&hooks_socket_getpeersec_stream))
+ return -ENOPROTOOPT;
return call_int_hook(socket_getpeersec_stream, sock, optval, optlen,
len);
}

+static struct list_head hooks_socket_getpeersec_dgram;
int security_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *skb, u32 *secid)
{
+ if (list_empty(&hooks_socket_getpeersec_dgram))
+ return -ENOPROTOOPT;
return call_int_hook(socket_getpeersec_dgram, sock, skb, secid);
}
EXPORT_SYMBOL(security_socket_getpeersec_dgram);

+static struct list_head hooks_sk_alloc_security;
int security_sk_alloc(struct sock *sk, int family, gfp_t priority)
{
return call_int_hook(sk_alloc_security, sk, family, priority);
}

+static struct list_head hooks_sk_free_security;
void security_sk_free(struct sock *sk)
{
call_void_hook(sk_free_security, sk);
}

+static struct list_head hooks_sk_clone_security;
void security_sk_clone(const struct sock *sk, struct sock *newsk)
{
call_void_hook(sk_clone_security, sk, newsk);
}
EXPORT_SYMBOL(security_sk_clone);

+static struct list_head hooks_sk_getsecid;
void security_sk_classify_flow(struct sock *sk, struct flowi *fl)
{
call_void_hook(sk_getsecid, sk, &fl->flowi_secid);
}
EXPORT_SYMBOL(security_sk_classify_flow);

+static struct list_head hooks_req_classify_flow;
void security_req_classify_flow(const struct request_sock *req, struct flowi *fl)
{
call_void_hook(req_classify_flow, req, fl);
}
EXPORT_SYMBOL(security_req_classify_flow);

+static struct list_head hooks_sock_graft;
void security_sock_graft(struct sock *sk, struct socket *parent)
{
call_void_hook(sock_graft, sk, parent);
}
EXPORT_SYMBOL(security_sock_graft);

+static struct list_head hooks_inet_conn_request;
int security_inet_conn_request(struct sock *sk,
struct sk_buff *skb, struct request_sock *req)
{
@@ -1283,72 +1581,84 @@ int security_inet_conn_request(struct sock *sk,
}
EXPORT_SYMBOL(security_inet_conn_request);

+static struct list_head hooks_inet_csk_clone;
void security_inet_csk_clone(struct sock *newsk,
const struct request_sock *req)
{
call_void_hook(inet_csk_clone, newsk, req);
}

+static struct list_head hooks_inet_conn_established;
void security_inet_conn_established(struct sock *sk,
struct sk_buff *skb)
{
call_void_hook(inet_conn_established, sk, skb);
}

+static struct list_head hooks_secmark_relabel_packet;
int security_secmark_relabel_packet(u32 secid)
{
return call_int_hook(secmark_relabel_packet, secid);
}
EXPORT_SYMBOL(security_secmark_relabel_packet);

+static struct list_head hooks_secmark_refcount_inc;
void security_secmark_refcount_inc(void)
{
call_void_hook(secmark_refcount_inc);
}
EXPORT_SYMBOL(security_secmark_refcount_inc);

+static struct list_head hooks_secmark_refcount_dec;
void security_secmark_refcount_dec(void)
{
call_void_hook(secmark_refcount_dec);
}
EXPORT_SYMBOL(security_secmark_refcount_dec);

+static struct list_head hooks_tun_dev_alloc_security;
int security_tun_dev_alloc_security(void **security)
{
return call_int_hook(tun_dev_alloc_security, security);
}
EXPORT_SYMBOL(security_tun_dev_alloc_security);

+static struct list_head hooks_tun_dev_free_security;
void security_tun_dev_free_security(void *security)
{
call_void_hook(tun_dev_free_security, security);
}
EXPORT_SYMBOL(security_tun_dev_free_security);

+static struct list_head hooks_tun_dev_create;
int security_tun_dev_create(void)
{
return call_int_hook(tun_dev_create);
}
EXPORT_SYMBOL(security_tun_dev_create);

+static struct list_head hooks_tun_dev_attach_queue;
int security_tun_dev_attach_queue(void *security)
{
return call_int_hook(tun_dev_attach_queue, security);
}
EXPORT_SYMBOL(security_tun_dev_attach_queue);

+static struct list_head hooks_tun_dev_attach;
int security_tun_dev_attach(struct sock *sk, void *security)
{
return call_int_hook(tun_dev_attach, sk, security);
}
EXPORT_SYMBOL(security_tun_dev_attach);

+static struct list_head hooks_tun_dev_open;
int security_tun_dev_open(void *security)
{
return call_int_hook(tun_dev_open, security);
}
EXPORT_SYMBOL(security_tun_dev_open);

+static struct list_head hooks_skb_owned_by;
void security_skb_owned_by(struct sk_buff *skb, struct sock *sk)
{
call_void_hook(skb_owned_by, skb, sk);
@@ -1358,6 +1668,7 @@ void security_skb_owned_by(struct sk_buff *skb, struct sock *sk)

#ifdef CONFIG_SECURITY_NETWORK_XFRM

+static struct list_head hooks_xfrm_policy_alloc_security;
int security_xfrm_policy_alloc(struct xfrm_sec_ctx **ctxp,
struct xfrm_user_sec_ctx *sec_ctx,
gfp_t gfp)
@@ -1366,23 +1677,27 @@ int security_xfrm_policy_alloc(struct xfrm_sec_ctx **ctxp,
}
EXPORT_SYMBOL(security_xfrm_policy_alloc);

+static struct list_head hooks_xfrm_policy_clone_security;
int security_xfrm_policy_clone(struct xfrm_sec_ctx *old_ctx,
struct xfrm_sec_ctx **new_ctxp)
{
return call_int_hook(xfrm_policy_clone_security, old_ctx, new_ctxp);
}

+static struct list_head hooks_xfrm_policy_free_security;
void security_xfrm_policy_free(struct xfrm_sec_ctx *ctx)
{
call_void_hook(xfrm_policy_free_security, ctx);
}
EXPORT_SYMBOL(security_xfrm_policy_free);

+static struct list_head hooks_xfrm_policy_delete_security;
int security_xfrm_policy_delete(struct xfrm_sec_ctx *ctx)
{
return call_int_hook(xfrm_policy_delete_security, ctx);
}

+static struct list_head hooks_xfrm_state_alloc;
int security_xfrm_state_alloc(struct xfrm_state *x,
struct xfrm_user_sec_ctx *sec_ctx)
{
@@ -1390,35 +1705,43 @@ int security_xfrm_state_alloc(struct xfrm_state *x,
}
EXPORT_SYMBOL(security_xfrm_state_alloc);

+static struct list_head hooks_xfrm_state_alloc_acquire;
int security_xfrm_state_alloc_acquire(struct xfrm_state *x,
struct xfrm_sec_ctx *polsec, u32 secid)
{
return call_int_hook(xfrm_state_alloc_acquire, x, polsec, secid);
}

+static struct list_head hooks_xfrm_state_delete_security;
int security_xfrm_state_delete(struct xfrm_state *x)
{
return call_int_hook(xfrm_state_delete_security, x);
}
EXPORT_SYMBOL(security_xfrm_state_delete);

+static struct list_head hooks_xfrm_state_free_security;
void security_xfrm_state_free(struct xfrm_state *x)
{
call_void_hook(xfrm_state_free_security, x);
}

+static struct list_head hooks_xfrm_policy_lookup;
int security_xfrm_policy_lookup(struct xfrm_sec_ctx *ctx, u32 fl_secid, u8 dir)
{
return call_int_hook(xfrm_policy_lookup, ctx, fl_secid, dir);
}

+static struct list_head hooks_xfrm_state_pol_flow_match;
int security_xfrm_state_pol_flow_match(struct xfrm_state *x,
struct xfrm_policy *xp,
const struct flowi *fl)
{
+ if (list_empty(&hooks_xfrm_state_pol_flow_match))
+ return 1;
return call_int_hook(xfrm_state_pol_flow_match, x, xp, fl);
}

+static struct list_head hooks_xfrm_decode_session;
int security_xfrm_decode_session(struct sk_buff *skb, u32 *secid)
{
return call_int_hook(xfrm_decode_session, skb, secid, 1);
@@ -1429,7 +1752,9 @@ int security_xfrm_decode_session(struct sk_buff *skb, u32 *secid)
*/
void security_skb_classify_flow(struct sk_buff *skb, struct flowi *fl)
{
- int rc = call_int_hook(xfrm_decode_session, skb, &fl->flowi_secid, 0);
+ int rc;
+
+ rc = call_int_hook(xfrm_decode_session, skb, &fl->flowi_secid, 0);

BUG_ON(rc);
}
@@ -1439,25 +1764,33 @@ EXPORT_SYMBOL(security_skb_classify_flow);

#ifdef CONFIG_KEYS

+static struct list_head hooks_key_alloc;
int security_key_alloc(struct key *key, const struct cred *cred,
unsigned long flags)
{
return call_int_hook(key_alloc, key, cred, flags);
}

+static struct list_head hooks_key_free;
void security_key_free(struct key *key)
{
call_void_hook(key_free, key);
}

+static struct list_head hooks_key_permission;
int security_key_permission(key_ref_t key_ref,
const struct cred *cred, unsigned perm)
{
return call_int_hook(key_permission, key_ref, cred, perm);
}

+static struct list_head hooks_key_getsecurity;
int security_key_getsecurity(struct key *key, char **_buffer)
{
+ if (list_empty(&hooks_key_getsecurity)) {
+ *_buffer = NULL;
+ return 0;
+ }
return call_int_hook(key_getsecurity, key, _buffer);
}

@@ -1465,21 +1798,25 @@ int security_key_getsecurity(struct key *key, char **_buffer)

#ifdef CONFIG_AUDIT

+static struct list_head hooks_audit_rule_init;
int security_audit_rule_init(u32 field, u32 op, char *rulestr, void **lsmrule)
{
return call_int_hook(audit_rule_init, field, op, rulestr, lsmrule);
}

+static struct list_head hooks_audit_rule_known;
int security_audit_rule_known(struct audit_krule *krule)
{
return call_int_hook(audit_rule_known, krule);
}

+static struct list_head hooks_audit_rule_free;
void security_audit_rule_free(void *lsmrule)
{
call_void_hook(audit_rule_free, lsmrule);
}

+static struct list_head hooks_audit_rule_match;
int security_audit_rule_match(u32 secid, u32 field, u32 op, void *lsmrule,
struct audit_context *actx)
{
@@ -1487,3 +1824,737 @@ int security_audit_rule_match(u32 secid, u32 field, u32 op, void *lsmrule,
}

#endif /* CONFIG_AUDIT */
+
+static int __init add_hook_to_list(struct list_head *hooklist,
+ void *interesting,
+ struct security_operations *sop)
+{
+ struct security_hook_list *new;
+ struct security_hook_list *shp;
+
+ if (hooklist->next == NULL)
+ INIT_LIST_HEAD(hooklist);
+
+ if (interesting == NULL)
+ return 0;
+
+ new = kzalloc(sizeof(*new), GFP_KERNEL);
+ if (new == NULL)
+ return -ENOMEM;
+
+ INIT_LIST_HEAD(&new->shl_head);
+ new->shl_ops = sop;
+
+ shp = list_last_entry(hooklist, struct security_hook_list, shl_head);
+ list_add_rcu(&new->shl_head, &shp->shl_head);
+
+ return 0;
+}
+
+static int __init security_enlist_ops(struct security_operations *sop)
+{
+ printk(KERN_INFO "Security operations for %s initialized\n", sop->name);
+
+ if (add_hook_to_list(&hooks_ptrace_access_check,
+ sop->ptrace_access_check, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_ptrace_traceme, sop->ptrace_traceme, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_capget, sop->capget, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_capset, sop->capset, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_capable, sop->capable, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_quotactl, sop->quotactl, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_quota_on, sop->quota_on, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_syslog, sop->syslog, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_settime, sop->settime, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_vm_enough_memory,
+ sop->vm_enough_memory, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_bprm_set_creds, sop->bprm_set_creds, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_bprm_committing_creds,
+ sop->bprm_committing_creds, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_bprm_committed_creds,
+ sop->bprm_committed_creds, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_bprm_check_security,
+ sop->bprm_check_security, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_bprm_secureexec, sop->bprm_secureexec, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_sb_alloc_security,
+ sop->sb_alloc_security, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_sb_free_security,
+ sop->sb_free_security, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_sb_copy_data, sop->sb_copy_data, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_sb_remount, sop->sb_remount, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_sb_kern_mount, sop->sb_kern_mount, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_sb_show_options, sop->sb_show_options, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_sb_statfs, sop->sb_statfs, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_sb_mount, sop->sb_mount, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_sb_umount, sop->sb_umount, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_sb_pivotroot, sop->sb_pivotroot, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_sb_set_mnt_opts, sop->sb_set_mnt_opts, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_sb_clone_mnt_opts,
+ sop->sb_clone_mnt_opts, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_sb_parse_opts_str,
+ sop->sb_parse_opts_str, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_dentry_init_security,
+ sop->dentry_init_security, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_inode_alloc_security,
+ sop->inode_alloc_security, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_inode_free_security,
+ sop->inode_free_security, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_inode_init_security,
+ sop->inode_init_security, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_inode_create, sop->inode_create, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_inode_link, sop->inode_link, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_inode_unlink, sop->inode_unlink, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_inode_symlink, sop->inode_symlink, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_inode_mkdir, sop->inode_mkdir, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_inode_rmdir, sop->inode_rmdir, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_inode_mknod, sop->inode_mknod, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_inode_rename, sop->inode_rename, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_inode_readlink, sop->inode_readlink, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_inode_follow_link,
+ sop->inode_follow_link, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_inode_permission,
+ sop->inode_permission, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_inode_setattr, sop->inode_setattr, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_inode_getattr, sop->inode_getattr, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_inode_setxattr, sop->inode_setxattr, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_inode_post_setxattr,
+ sop->inode_post_setxattr, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_inode_getxattr, sop->inode_getxattr, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_inode_listxattr, sop->inode_listxattr, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_inode_removexattr,
+ sop->inode_removexattr, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_inode_need_killpriv,
+ sop->inode_need_killpriv, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_inode_killpriv, sop->inode_killpriv, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_inode_getsecurity,
+ sop->inode_getsecurity, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_inode_setsecurity,
+ sop->inode_setsecurity, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_inode_listsecurity,
+ sop->inode_listsecurity, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_inode_getsecid,
+ sop->inode_getsecid, sop))
+ return -ENOMEM;
+#ifdef CONFIG_SECURITY_PATH
+ if (add_hook_to_list(&hooks_path_mknod, sop->path_mknod, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_path_mkdir, sop->path_mkdir, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_path_rmdir, sop->path_rmdir, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_path_unlink, sop->path_unlink, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_path_symlink, sop->path_symlink, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_path_link, sop->path_link, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_path_rename, sop->path_rename, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_path_truncate, sop->path_truncate, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_path_chmod, sop->path_chmod, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_path_chown, sop->path_chown, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_path_chroot, sop->path_chroot, sop))
+ return -ENOMEM;
+#endif
+ if (add_hook_to_list(&hooks_file_permission, sop->file_permission, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_file_alloc_security,
+ sop->file_alloc_security, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_file_free_security,
+ sop->file_free_security, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_file_ioctl, sop->file_ioctl, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_mmap_addr, sop->mmap_addr, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_mmap_file, sop->mmap_file, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_file_mprotect, sop->file_mprotect, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_file_lock, sop->file_lock, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_file_fcntl, sop->file_fcntl, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_file_set_fowner, sop->file_set_fowner, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_file_send_sigiotask,
+ sop->file_send_sigiotask, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_file_receive, sop->file_receive, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_file_open, sop->file_open, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_task_create, sop->task_create, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_task_free, sop->task_free, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_cred_alloc_blank,
+ sop->cred_alloc_blank, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_cred_free, sop->cred_free, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_cred_prepare, sop->cred_prepare, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_cred_transfer, sop->cred_transfer, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_kernel_act_as, sop->kernel_act_as, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_kernel_create_files_as,
+ sop->kernel_create_files_as, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_kernel_module_request,
+ sop->kernel_module_request, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_kernel_module_from_file,
+ sop->kernel_module_from_file, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_task_fix_setuid, sop->task_fix_setuid, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_task_setpgid, sop->task_setpgid, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_task_getpgid, sop->task_getpgid, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_task_getsid, sop->task_getsid, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_task_getsecid, sop->task_getsecid, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_task_setnice, sop->task_setnice, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_task_setioprio, sop->task_setioprio, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_task_getioprio, sop->task_getioprio, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_task_setrlimit, sop->task_setrlimit, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_task_setscheduler,
+ sop->task_setscheduler, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_task_getscheduler,
+ sop->task_getscheduler, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_task_movememory, sop->task_movememory, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_task_wait, sop->task_wait, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_task_kill, sop->task_kill, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_task_prctl, sop->task_prctl, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_task_to_inode, sop->task_to_inode, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_ipc_permission, sop->ipc_permission, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_ipc_getsecid, sop->ipc_getsecid, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_msg_msg_alloc_security,
+ sop->msg_msg_alloc_security, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_msg_msg_free_security,
+ sop->msg_msg_free_security, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_msg_queue_alloc_security,
+ sop->msg_queue_alloc_security, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_msg_queue_free_security,
+ sop->msg_queue_free_security, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_msg_queue_associate,
+ sop->msg_queue_associate, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_msg_queue_msgctl,
+ sop->msg_queue_msgctl, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_msg_queue_msgsnd,
+ sop->msg_queue_msgsnd, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_msg_queue_msgrcv,
+ sop->msg_queue_msgrcv, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_shm_alloc_security,
+ sop->shm_alloc_security, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_shm_free_security,
+ sop->shm_free_security, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_shm_associate, sop->shm_associate, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_shm_shmctl, sop->shm_shmctl, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_shm_shmat, sop->shm_shmat, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_sem_alloc_security,
+ sop->sem_alloc_security, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_sem_free_security,
+ sop->sem_free_security, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_sem_associate, sop->sem_associate, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_sem_semctl, sop->sem_semctl, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_sem_semop, sop->sem_semop, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_netlink_send, sop->netlink_send, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_d_instantiate, sop->d_instantiate, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_getprocattr, sop->getprocattr, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_setprocattr, sop->setprocattr, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_ismaclabel, sop->ismaclabel, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_secid_to_secctx, sop->secid_to_secctx, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_secctx_to_secid, sop->secctx_to_secid, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_release_secctx, sop->release_secctx, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_inode_notifysecctx,
+ sop->inode_notifysecctx, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_inode_setsecctx, sop->inode_setsecctx, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_inode_getsecctx, sop->inode_getsecctx, sop))
+ return -ENOMEM;
+#ifdef CONFIG_SECURITY_NETWORK
+ if (add_hook_to_list(&hooks_unix_stream_connect,
+ sop->unix_stream_connect, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_unix_may_send, sop->unix_may_send, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_socket_create, sop->socket_create, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_socket_post_create,
+ sop->socket_post_create, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_socket_bind, sop->socket_bind, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_socket_connect, sop->socket_connect, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_socket_listen, sop->socket_listen, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_socket_accept, sop->socket_accept, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_socket_sendmsg, sop->socket_sendmsg, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_socket_recvmsg, sop->socket_recvmsg, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_socket_getsockname,
+ sop->socket_getsockname, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_socket_getpeername,
+ sop->socket_getpeername, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_socket_setsockopt,
+ sop->socket_setsockopt, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_socket_getsockopt,
+ sop->socket_getsockopt, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_socket_shutdown, sop->socket_shutdown, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_socket_sock_rcv_skb,
+ sop->socket_sock_rcv_skb, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_socket_getpeersec_stream,
+ sop->socket_getpeersec_stream, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_socket_getpeersec_dgram,
+ sop->socket_getpeersec_dgram, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_sk_alloc_security,
+ sop->sk_alloc_security, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_sk_free_security,
+ sop->sk_free_security, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_sk_clone_security,
+ sop->sk_clone_security, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_sk_getsecid, sop->sk_getsecid, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_sock_graft, sop->sock_graft, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_inet_conn_request,
+ sop->inet_conn_request, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_inet_csk_clone, sop->inet_csk_clone, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_inet_conn_established,
+ sop->inet_conn_established, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_secmark_relabel_packet,
+ sop->secmark_relabel_packet, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_secmark_refcount_inc,
+ sop->secmark_refcount_inc, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_secmark_refcount_dec,
+ sop->secmark_refcount_dec, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_req_classify_flow,
+ sop->req_classify_flow, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_tun_dev_alloc_security,
+ sop->tun_dev_alloc_security, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_tun_dev_free_security,
+ sop->tun_dev_free_security, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_tun_dev_create, sop->tun_dev_create, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_tun_dev_open, sop->tun_dev_open, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_tun_dev_attach_queue,
+ sop->tun_dev_attach_queue, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_tun_dev_attach, sop->tun_dev_attach, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_skb_owned_by, sop->skb_owned_by, sop))
+ return -ENOMEM;
+#endif /* CONFIG_SECURITY_NETWORK */
+#ifdef CONFIG_SECURITY_NETWORK_XFRM
+ if (add_hook_to_list(&hooks_xfrm_policy_alloc_security,
+ sop->xfrm_policy_alloc_security, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_xfrm_policy_clone_security,
+ sop->xfrm_policy_clone_security, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_xfrm_policy_free_security,
+ sop->xfrm_policy_free_security, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_xfrm_policy_delete_security,
+ sop->xfrm_policy_delete_security, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_xfrm_state_alloc,
+ sop->xfrm_state_alloc, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_xfrm_state_alloc_acquire,
+ sop->xfrm_state_alloc_acquire, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_xfrm_state_free_security,
+ sop->xfrm_state_free_security, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_xfrm_state_delete_security,
+ sop->xfrm_state_delete_security, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_xfrm_policy_lookup,
+ sop->xfrm_policy_lookup, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_xfrm_state_pol_flow_match,
+ sop->xfrm_state_pol_flow_match, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_xfrm_decode_session,
+ sop->xfrm_decode_session, sop))
+ return -ENOMEM;
+#endif /* CONFIG_SECURITY_NETWORK_XFRM */
+#ifdef CONFIG_KEYS
+ if (add_hook_to_list(&hooks_key_alloc, sop->key_alloc, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_key_free, sop->key_free, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_key_permission, sop->key_permission, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_key_getsecurity, sop->key_getsecurity, sop))
+ return -ENOMEM;
+#endif /* CONFIG_KEYS */
+#ifdef CONFIG_AUDIT
+ if (add_hook_to_list(&hooks_audit_rule_init, sop->audit_rule_init, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_audit_rule_known, sop->audit_rule_known,
+ sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_audit_rule_match, sop->audit_rule_match,
+ sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_audit_rule_free, sop->audit_rule_free, sop))
+ return -ENOMEM;
+#endif
+ return 0;
+}
+
+#ifdef CONFIG_SECURITY_SELINUX_DISABLE
+static void clear_hook_entry(struct list_head *head,
+ struct security_operations *sop)
+{
+ struct security_hook_list *shp;
+
+ if (head->next == NULL)
+ return;
+ if (list_empty(head))
+ return;
+
+ list_for_each_entry(shp, head, shl_head)
+ if (shp->shl_ops == sop) {
+ shp->shl_ops = NULL;
+ return;
+ }
+}
+
+void security_module_disable(struct security_operations *sop)
+{
+ printk(KERN_INFO "Security operations for %s disabled.\n", sop->name);
+ clear_hook_entry(&hooks_ptrace_access_check, sop);
+ clear_hook_entry(&hooks_ptrace_traceme, sop);
+ clear_hook_entry(&hooks_capget, sop);
+ clear_hook_entry(&hooks_capset, sop);
+ clear_hook_entry(&hooks_capable, sop);
+ clear_hook_entry(&hooks_quotactl, sop);
+ clear_hook_entry(&hooks_quota_on, sop);
+ clear_hook_entry(&hooks_syslog, sop);
+ clear_hook_entry(&hooks_settime, sop);
+ clear_hook_entry(&hooks_vm_enough_memory, sop);
+ clear_hook_entry(&hooks_bprm_set_creds, sop);
+ clear_hook_entry(&hooks_bprm_committing_creds, sop);
+ clear_hook_entry(&hooks_bprm_committed_creds, sop);
+ clear_hook_entry(&hooks_bprm_check_security, sop);
+ clear_hook_entry(&hooks_bprm_secureexec, sop);
+ clear_hook_entry(&hooks_sb_alloc_security, sop);
+ clear_hook_entry(&hooks_sb_free_security, sop);
+ clear_hook_entry(&hooks_sb_copy_data, sop);
+ clear_hook_entry(&hooks_sb_remount, sop);
+ clear_hook_entry(&hooks_sb_kern_mount, sop);
+ clear_hook_entry(&hooks_sb_show_options, sop);
+ clear_hook_entry(&hooks_sb_statfs, sop);
+ clear_hook_entry(&hooks_sb_mount, sop);
+ clear_hook_entry(&hooks_sb_umount, sop);
+ clear_hook_entry(&hooks_sb_pivotroot, sop);
+ clear_hook_entry(&hooks_sb_set_mnt_opts, sop);
+ clear_hook_entry(&hooks_sb_clone_mnt_opts, sop);
+ clear_hook_entry(&hooks_sb_parse_opts_str, sop);
+ clear_hook_entry(&hooks_dentry_init_security, sop);
+ clear_hook_entry(&hooks_inode_alloc_security, sop);
+ clear_hook_entry(&hooks_inode_free_security, sop);
+ clear_hook_entry(&hooks_inode_init_security, sop);
+ clear_hook_entry(&hooks_inode_create, sop);
+ clear_hook_entry(&hooks_inode_link, sop);
+ clear_hook_entry(&hooks_inode_unlink, sop);
+ clear_hook_entry(&hooks_inode_symlink, sop);
+ clear_hook_entry(&hooks_inode_mkdir, sop);
+ clear_hook_entry(&hooks_inode_rmdir, sop);
+ clear_hook_entry(&hooks_inode_mknod, sop);
+ clear_hook_entry(&hooks_inode_rename, sop);
+ clear_hook_entry(&hooks_inode_readlink, sop);
+ clear_hook_entry(&hooks_inode_follow_link, sop);
+ clear_hook_entry(&hooks_inode_permission, sop);
+ clear_hook_entry(&hooks_inode_setattr, sop);
+ clear_hook_entry(&hooks_inode_getattr, sop);
+ clear_hook_entry(&hooks_inode_setxattr, sop);
+ clear_hook_entry(&hooks_inode_post_setxattr, sop);
+ clear_hook_entry(&hooks_inode_getxattr, sop);
+ clear_hook_entry(&hooks_inode_listxattr, sop);
+ clear_hook_entry(&hooks_inode_removexattr, sop);
+ clear_hook_entry(&hooks_inode_need_killpriv, sop);
+ clear_hook_entry(&hooks_inode_killpriv, sop);
+ clear_hook_entry(&hooks_inode_getsecurity, sop);
+ clear_hook_entry(&hooks_inode_setsecurity, sop);
+ clear_hook_entry(&hooks_inode_listsecurity, sop);
+ clear_hook_entry(&hooks_inode_getsecid, sop);
+#ifdef CONFIG_SECURITY_PATH
+ clear_hook_entry(&hooks_path_mknod, sop);
+ clear_hook_entry(&hooks_path_mkdir, sop);
+ clear_hook_entry(&hooks_path_rmdir, sop);
+ clear_hook_entry(&hooks_path_unlink, sop);
+ clear_hook_entry(&hooks_path_symlink, sop);
+ clear_hook_entry(&hooks_path_link, sop);
+ clear_hook_entry(&hooks_path_rename, sop);
+ clear_hook_entry(&hooks_path_truncate, sop);
+ clear_hook_entry(&hooks_path_chmod, sop);
+ clear_hook_entry(&hooks_path_chown, sop);
+ clear_hook_entry(&hooks_path_chroot, sop);
+#endif
+ clear_hook_entry(&hooks_file_permission, sop);
+ clear_hook_entry(&hooks_file_alloc_security, sop);
+ clear_hook_entry(&hooks_file_free_security, sop);
+ clear_hook_entry(&hooks_file_ioctl, sop);
+ clear_hook_entry(&hooks_mmap_addr, sop);
+ clear_hook_entry(&hooks_mmap_file, sop);
+ clear_hook_entry(&hooks_file_mprotect, sop);
+ clear_hook_entry(&hooks_file_lock, sop);
+ clear_hook_entry(&hooks_file_fcntl, sop);
+ clear_hook_entry(&hooks_file_set_fowner, sop);
+ clear_hook_entry(&hooks_file_send_sigiotask, sop);
+ clear_hook_entry(&hooks_file_receive, sop);
+ clear_hook_entry(&hooks_file_open, sop);
+ clear_hook_entry(&hooks_task_create, sop);
+ clear_hook_entry(&hooks_task_free, sop);
+ clear_hook_entry(&hooks_cred_alloc_blank, sop);
+ clear_hook_entry(&hooks_cred_free, sop);
+ clear_hook_entry(&hooks_cred_prepare, sop);
+ clear_hook_entry(&hooks_cred_transfer, sop);
+ clear_hook_entry(&hooks_kernel_act_as, sop);
+ clear_hook_entry(&hooks_kernel_create_files_as, sop);
+ clear_hook_entry(&hooks_kernel_module_request, sop);
+ clear_hook_entry(&hooks_kernel_module_from_file, sop);
+ clear_hook_entry(&hooks_task_fix_setuid, sop);
+ clear_hook_entry(&hooks_task_setpgid, sop);
+ clear_hook_entry(&hooks_task_getpgid, sop);
+ clear_hook_entry(&hooks_task_getsid, sop);
+ clear_hook_entry(&hooks_task_getsecid, sop);
+ clear_hook_entry(&hooks_task_setnice, sop);
+ clear_hook_entry(&hooks_task_setioprio, sop);
+ clear_hook_entry(&hooks_task_getioprio, sop);
+ clear_hook_entry(&hooks_task_setrlimit, sop);
+ clear_hook_entry(&hooks_task_setscheduler, sop);
+ clear_hook_entry(&hooks_task_getscheduler, sop);
+ clear_hook_entry(&hooks_task_movememory, sop);
+ clear_hook_entry(&hooks_task_wait, sop);
+ clear_hook_entry(&hooks_task_kill, sop);
+ clear_hook_entry(&hooks_task_prctl, sop);
+ clear_hook_entry(&hooks_task_to_inode, sop);
+ clear_hook_entry(&hooks_ipc_permission, sop);
+ clear_hook_entry(&hooks_ipc_getsecid, sop);
+ clear_hook_entry(&hooks_msg_msg_alloc_security, sop);
+ clear_hook_entry(&hooks_msg_msg_free_security, sop);
+ clear_hook_entry(&hooks_msg_queue_alloc_security, sop);
+ clear_hook_entry(&hooks_msg_queue_free_security, sop);
+ clear_hook_entry(&hooks_msg_queue_associate, sop);
+ clear_hook_entry(&hooks_msg_queue_msgctl, sop);
+ clear_hook_entry(&hooks_msg_queue_msgsnd, sop);
+ clear_hook_entry(&hooks_msg_queue_msgrcv, sop);
+ clear_hook_entry(&hooks_shm_alloc_security, sop);
+ clear_hook_entry(&hooks_shm_free_security, sop);
+ clear_hook_entry(&hooks_shm_associate, sop);
+ clear_hook_entry(&hooks_shm_shmctl, sop);
+ clear_hook_entry(&hooks_shm_shmat, sop);
+ clear_hook_entry(&hooks_sem_alloc_security, sop);
+ clear_hook_entry(&hooks_sem_free_security, sop);
+ clear_hook_entry(&hooks_sem_associate, sop);
+ clear_hook_entry(&hooks_sem_semctl, sop);
+ clear_hook_entry(&hooks_sem_semop, sop);
+ clear_hook_entry(&hooks_netlink_send, sop);
+ clear_hook_entry(&hooks_d_instantiate, sop);
+ clear_hook_entry(&hooks_getprocattr, sop);
+ clear_hook_entry(&hooks_setprocattr, sop);
+ clear_hook_entry(&hooks_ismaclabel, sop);
+ clear_hook_entry(&hooks_secid_to_secctx, sop);
+ clear_hook_entry(&hooks_secctx_to_secid, sop);
+ clear_hook_entry(&hooks_release_secctx, sop);
+ clear_hook_entry(&hooks_inode_notifysecctx, sop);
+ clear_hook_entry(&hooks_inode_setsecctx, sop);
+ clear_hook_entry(&hooks_inode_getsecctx, sop);
+#ifdef CONFIG_SECURITY_NETWORK
+ clear_hook_entry(&hooks_unix_stream_connect, sop);
+ clear_hook_entry(&hooks_unix_may_send, sop);
+ clear_hook_entry(&hooks_socket_create, sop);
+ clear_hook_entry(&hooks_socket_post_create, sop);
+ clear_hook_entry(&hooks_socket_bind, sop);
+ clear_hook_entry(&hooks_socket_connect, sop);
+ clear_hook_entry(&hooks_socket_listen, sop);
+ clear_hook_entry(&hooks_socket_accept, sop);
+ clear_hook_entry(&hooks_socket_sendmsg, sop);
+ clear_hook_entry(&hooks_socket_recvmsg, sop);
+ clear_hook_entry(&hooks_socket_getsockname, sop);
+ clear_hook_entry(&hooks_socket_getpeername, sop);
+ clear_hook_entry(&hooks_socket_setsockopt, sop);
+ clear_hook_entry(&hooks_socket_getsockopt, sop);
+ clear_hook_entry(&hooks_socket_shutdown, sop);
+ clear_hook_entry(&hooks_socket_sock_rcv_skb, sop);
+ clear_hook_entry(&hooks_socket_getpeersec_stream, sop);
+ clear_hook_entry(&hooks_socket_getpeersec_dgram, sop);
+ clear_hook_entry(&hooks_sk_alloc_security, sop);
+ clear_hook_entry(&hooks_sk_free_security, sop);
+ clear_hook_entry(&hooks_sk_clone_security, sop);
+ clear_hook_entry(&hooks_sk_getsecid, sop);
+ clear_hook_entry(&hooks_sock_graft, sop);
+ clear_hook_entry(&hooks_inet_conn_request, sop);
+ clear_hook_entry(&hooks_inet_csk_clone, sop);
+ clear_hook_entry(&hooks_inet_conn_established, sop);
+ clear_hook_entry(&hooks_secmark_relabel_packet, sop);
+ clear_hook_entry(&hooks_secmark_refcount_inc, sop);
+ clear_hook_entry(&hooks_secmark_refcount_dec, sop);
+ clear_hook_entry(&hooks_req_classify_flow, sop);
+ clear_hook_entry(&hooks_tun_dev_alloc_security, sop);
+ clear_hook_entry(&hooks_tun_dev_free_security, sop);
+ clear_hook_entry(&hooks_tun_dev_create, sop);
+ clear_hook_entry(&hooks_tun_dev_open, sop);
+ clear_hook_entry(&hooks_tun_dev_attach_queue, sop);
+ clear_hook_entry(&hooks_tun_dev_attach, sop);
+ clear_hook_entry(&hooks_skb_owned_by, sop);
+#endif /* CONFIG_SECURITY_NETWORK */
+#ifdef CONFIG_SECURITY_NETWORK_XFRM
+ clear_hook_entry(&hooks_xfrm_policy_alloc_security, sop);
+ clear_hook_entry(&hooks_xfrm_policy_clone_security, sop);
+ clear_hook_entry(&hooks_xfrm_policy_free_security, sop);
+ clear_hook_entry(&hooks_xfrm_policy_delete_security, sop);
+ clear_hook_entry(&hooks_xfrm_state_alloc, sop);
+ clear_hook_entry(&hooks_xfrm_state_alloc_acquire, sop);
+ clear_hook_entry(&hooks_xfrm_state_free_security, sop);
+ clear_hook_entry(&hooks_xfrm_state_delete_security, sop);
+ clear_hook_entry(&hooks_xfrm_policy_lookup, sop);
+ clear_hook_entry(&hooks_xfrm_state_pol_flow_match, sop);
+ clear_hook_entry(&hooks_xfrm_decode_session, sop);
+#endif /* CONFIG_SECURITY_NETWORK_XFRM */
+#ifdef CONFIG_KEYS
+ clear_hook_entry(&hooks_key_alloc, sop);
+ clear_hook_entry(&hooks_key_free, sop);
+ clear_hook_entry(&hooks_key_permission, sop);
+ clear_hook_entry(&hooks_key_getsecurity, sop);
+#endif /* CONFIG_KEYS */
+#ifdef CONFIG_AUDIT
+ clear_hook_entry(&hooks_audit_rule_init, sop);
+ clear_hook_entry(&hooks_audit_rule_known, sop);
+ clear_hook_entry(&hooks_audit_rule_match, sop);
+ clear_hook_entry(&hooks_audit_rule_free, sop);
+#endif
+}
+#endif /* CONFIG_SECURITY_SELINUX_DISABLE */
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 83d06db..4b8852c 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -1927,12 +1927,6 @@ static inline u32 open_file_to_av(struct file *file)
static int selinux_ptrace_access_check(struct task_struct *child,
unsigned int mode)
{
- int rc;
-
- rc = cap_ptrace_access_check(child, mode);
- if (rc)
- return rc;
-
if (mode & PTRACE_MODE_READ) {
u32 sid = current_sid();
u32 csid = task_sid(child);
@@ -1944,12 +1938,6 @@ static int selinux_ptrace_access_check(struct task_struct *child,

static int selinux_ptrace_traceme(struct task_struct *parent)
{
- int rc;
-
- rc = cap_ptrace_traceme(parent);
- if (rc)
- return rc;
-
return task_has_perm(parent, current, PROCESS__PTRACE);
}

@@ -1993,12 +1981,6 @@ static int selinux_capset(struct cred *new, const struct cred *old,
static int selinux_capable(const struct cred *cred, struct user_namespace *ns,
int cap, int audit)
{
- int rc;
-
- rc = cap_capable(cred, ns, cap, audit);
- if (rc)
- return rc;
-
return cred_has_capability(cred, cap, audit);
}

@@ -2095,10 +2077,6 @@ static int selinux_bprm_set_creds(struct linux_binprm *bprm)
struct inode *inode = file_inode(bprm->file);
int rc;

- rc = cap_bprm_set_creds(bprm);
- if (rc)
- return rc;
-
/* SELinux context only depends on initial program or script and not
* the script interpreter */
if (bprm->cred_prepared)
@@ -3549,23 +3527,11 @@ static void selinux_task_getsecid(struct task_struct *p, u32 *secid)

static int selinux_task_setnice(struct task_struct *p, int nice)
{
- int rc;
-
- rc = cap_task_setnice(p, nice);
- if (rc)
- return rc;
-
return current_has_perm(p, PROCESS__SETSCHED);
}

static int selinux_task_setioprio(struct task_struct *p, int ioprio)
{
- int rc;
-
- rc = cap_task_setioprio(p, ioprio);
- if (rc)
- return rc;
-
return current_has_perm(p, PROCESS__SETSCHED);
}

@@ -3591,12 +3557,6 @@ static int selinux_task_setrlimit(struct task_struct *p, unsigned int resource,

static int selinux_task_setscheduler(struct task_struct *p)
{
- int rc;
-
- rc = cap_task_setscheduler(p);
- if (rc)
- return rc;
-
return current_has_perm(p, PROCESS__SETSCHED);
}

@@ -5018,12 +4978,6 @@ static unsigned int selinux_ipv6_postroute(const struct nf_hook_ops *ops,

static int selinux_netlink_send(struct sock *sk, struct sk_buff *skb)
{
- int err;
-
- err = cap_netlink_send(sk, skb);
- if (err)
- return err;
-
return selinux_nlmsg_perm(sk, skb);
}

@@ -6131,7 +6085,7 @@ int selinux_disable(void)
selinux_disabled = 1;
selinux_enabled = 0;

- reset_security_ops();
+ security_module_disable(&selinux_ops);

/* Try to destroy the avc node cache */
avc_disable();
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index f2c3080..4b071b3 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -244,10 +244,6 @@ static int smack_ptrace_access_check(struct task_struct *ctp, unsigned int mode)
int rc;
struct smack_known *skp;

- rc = cap_ptrace_access_check(ctp, mode);
- if (rc != 0)
- return rc;
-
skp = smk_of_task(task_security(ctp));

rc = smk_ptrace_rule_check(current, skp->smk_known, mode, __func__);
@@ -267,10 +263,6 @@ static int smack_ptrace_traceme(struct task_struct *ptp)
int rc;
struct smack_known *skp;

- rc = cap_ptrace_traceme(ptp);
- if (rc != 0)
- return rc;
-
skp = smk_of_task(current_security());

rc = smk_ptrace_rule_check(ptp, skp->smk_known,
@@ -525,12 +517,9 @@ static int smack_bprm_set_creds(struct linux_binprm *bprm)
struct inode *inode = file_inode(bprm->file);
struct task_smack *bsp = bprm->cred->security;
struct inode_smack *isp;
+ struct task_struct *tracer;
int rc;

- rc = cap_bprm_set_creds(bprm);
- if (rc != 0)
- return rc;
-
if (bprm->cred_prepared)
return 0;

@@ -539,7 +528,6 @@ static int smack_bprm_set_creds(struct linux_binprm *bprm)
return 0;

if (bprm->unsafe & (LSM_UNSAFE_PTRACE | LSM_UNSAFE_PTRACE_CAP)) {
- struct task_struct *tracer;
rc = 0;

rcu_read_lock();
@@ -1703,12 +1691,7 @@ static void smack_task_getsecid(struct task_struct *p, u32 *secid)
*/
static int smack_task_setnice(struct task_struct *p, int nice)
{
- int rc;
-
- rc = cap_task_setnice(p, nice);
- if (rc == 0)
- rc = smk_curacc_on_task(p, MAY_WRITE, __func__);
- return rc;
+ return smk_curacc_on_task(p, MAY_WRITE, __func__);
}

/**
@@ -1720,12 +1703,7 @@ static int smack_task_setnice(struct task_struct *p, int nice)
*/
static int smack_task_setioprio(struct task_struct *p, int ioprio)
{
- int rc;
-
- rc = cap_task_setioprio(p, ioprio);
- if (rc == 0)
- rc = smk_curacc_on_task(p, MAY_WRITE, __func__);
- return rc;
+ return smk_curacc_on_task(p, MAY_WRITE, __func__);
}

/**
@@ -1749,12 +1727,7 @@ static int smack_task_getioprio(struct task_struct *p)
*/
static int smack_task_setscheduler(struct task_struct *p)
{
- int rc;
-
- rc = cap_task_setscheduler(p);
- if (rc == 0)
- rc = smk_curacc_on_task(p, MAY_WRITE, __func__);
- return rc;
+ return smk_curacc_on_task(p, MAY_WRITE, __func__);
}

/**
diff --git a/security/tomoyo/tomoyo.c b/security/tomoyo/tomoyo.c
index f0b756e..92d2230 100644
--- a/security/tomoyo/tomoyo.c
+++ b/security/tomoyo/tomoyo.c
@@ -72,12 +72,6 @@ static void tomoyo_cred_free(struct cred *cred)
*/
static int tomoyo_bprm_set_creds(struct linux_binprm *bprm)
{
- int rc;
-
- rc = cap_bprm_set_creds(bprm);
- if (rc)
- return rc;
-
/*
* Do only if this function is called for the first time of an execve
* operation.
diff --git a/security/yama/yama_lsm.c b/security/yama/yama_lsm.c
index 13c88fbc..7974a23 100644
--- a/security/yama/yama_lsm.c
+++ b/security/yama/yama_lsm.c
@@ -154,13 +154,9 @@ void yama_task_free(struct task_struct *task)
int yama_task_prctl(int option, unsigned long arg2, unsigned long arg3,
unsigned long arg4, unsigned long arg5)
{
- int rc;
+ int rc = 0;
struct task_struct *myself = current;

- rc = cap_task_prctl(option, arg2, arg3, arg4, arg5);
- if (rc != -ENOSYS)
- return rc;
-
switch (option) {
case PR_SET_PTRACER:
/* Since a thread can call prctl(), find the group leader
@@ -284,13 +280,6 @@ int yama_ptrace_access_check(struct task_struct *child,
{
int rc;

- /* If standard caps disallows it, so does Yama. We should
- * only tighten restrictions further.
- */
- rc = cap_ptrace_access_check(child, mode);
- if (rc)
- return rc;
-
/* require ptrace target be a child of ptracer on attach */
if (mode == PTRACE_MODE_ATTACH) {
switch (ptrace_scope) {
@@ -335,14 +324,7 @@ int yama_ptrace_access_check(struct task_struct *child,
*/
int yama_ptrace_traceme(struct task_struct *parent)
{
- int rc;
-
- /* If standard caps disallows it, so does Yama. We should
- * only tighten restrictions further.
- */
- rc = cap_ptrace_traceme(parent);
- if (rc)
- return rc;
+ int rc = 0;

/* Only disallow PTRACE_TRACEME on more aggressive settings. */
switch (ptrace_scope) {
@@ -364,8 +346,7 @@ int yama_ptrace_traceme(struct task_struct *parent)
return rc;
}

-#ifndef CONFIG_SECURITY_YAMA_STACKED
-static struct security_operations yama_ops = {
+struct security_operations yama_ops = {
.name = "yama",

.ptrace_access_check = yama_ptrace_access_check,
@@ -373,7 +354,6 @@ static struct security_operations yama_ops = {
.task_prctl = yama_task_prctl,
.task_free = yama_task_free,
};
-#endif

#ifdef CONFIG_SYSCTL
static int yama_dointvec_minmax(struct ctl_table *table, int write,
@@ -421,17 +401,17 @@ static struct ctl_table yama_sysctl_table[] = {
static __init int yama_init(void)
{
#ifndef CONFIG_SECURITY_YAMA_STACKED
+ /*
+ * If yama is being stacked this is already taken care of.
+ */
if (!security_module_enable(&yama_ops))
return 0;
-#endif
-
- printk(KERN_INFO "Yama: becoming mindful.\n");
-
-#ifndef CONFIG_SECURITY_YAMA_STACKED
if (register_security(&yama_ops))
panic("Yama: kernel registration failed.\n");
#endif

+ printk(KERN_INFO "Yama: becoming mindful.\n");
+
#ifdef CONFIG_SYSCTL
if (!register_sysctl_paths(yama_sysctl_path, yama_sysctl_table))
panic("Yama: sysctl registration failed.\n");

--
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
the body of a message to ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Stephen Smalley
2014-08-11 20:36:10 UTC
Permalink
Post by Casey Schaufler
Subject: [PATCH v16 2/4] LSM: Refactor existing LSM stacking
The existing code stacks up to three security modules.
If there is only one module it is the capability module.
If a module is specified the capability code is explicitly
called within the specified module. If Yama stacking is
configured the yama hooks are called and then the specified
module. The capability check is made twice in the yama
stacking case.
This patch adds a list for each of the LSM hooks. The capability
hooks that are non-trivial are put on the list first. If Yama
stacking is configured the yama hooks are added to the list.
If a module is configured it gets added next. Each entry in the
(capability[ yama][ {selinux|smack|tomoyo|apparmor}])
Exit is on first failure (bail on fail) which matches the
existing behavior. The explict calls to the capability module
are removed where they would duplicate the stacked call.
diff --git a/security/commoncap.c b/security/commoncap.c
index b9d613e..1cfc27c 100644
--- a/security/commoncap.c
+++ b/security/commoncap.c
@@ -994,3 +994,37 @@ int cap_mmap_file(struct file *file, unsigned long reqprot,
{
return 0;
}
+
+#ifdef CONFIG_SECURITY
+
+struct security_operations capability_ops = {
+ .name = "capability",
+ .capable = cap_capable,
+ .settime = cap_settime,
+ .ptrace_access_check = cap_ptrace_access_check,
+ .ptrace_traceme = cap_ptrace_traceme,
+ .capget = cap_capget,
+ .capset = cap_capset,
+ .bprm_set_creds = cap_bprm_set_creds,
+ /*
+ * Not stacked in the usual way.
+ * .bprm_secureexec = cap_bprm_secureexec,
Still don't see why you can't do this one in the usual way.
Order doesn't matter.
Just change selinux_bprm_secureexec() to return !!atsecure.
Post by Casey Schaufler
+ * .inode_setxattr = cap_inode_setxattr,
+ * .inode_removexattr = cap_inode_removexattr,
+ */
+ .inode_need_killpriv = cap_inode_need_killpriv,
+ .inode_killpriv = cap_inode_killpriv,
+ /*
+ * Not stacked in the usual way.
+ * .mmap_addr = cap_mmap_addr,
+ */
Ditto; current selinux_mmap_addr() calls cap_mmap_addr() first.
Post by Casey Schaufler
+ .mmap_file = cap_mmap_file,
+ .task_fix_setuid = cap_task_fix_setuid,
+ .task_prctl = cap_task_prctl,
+ .task_setscheduler = cap_task_setscheduler,
+ .task_setioprio = cap_task_setioprio,
+ .task_setnice = cap_task_setnice,
+ .vm_enough_memory = cap_vm_enough_memory,
Still don't think this one can be handled in the usual way since the
__vm_enough_memory() call will perform double accounting.
--
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
the body of a message to ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Stephen Smalley
2014-08-12 14:15:10 UTC
Permalink
Post by Casey Schaufler
Subject: [PATCH v16 2/4] LSM: Refactor existing LSM stacking
The existing code stacks up to three security modules.
If there is only one module it is the capability module.
If a module is specified the capability code is explicitly
called within the specified module. If Yama stacking is
configured the yama hooks are called and then the specified
module. The capability check is made twice in the yama
stacking case.
This patch adds a list for each of the LSM hooks. The capability
hooks that are non-trivial are put on the list first. If Yama
stacking is configured the yama hooks are added to the list.
If a module is configured it gets added next. Each entry in the
(capability[ yama][ {selinux|smack|tomoyo|apparmor}])
Exit is on first failure (bail on fail) which matches the
existing behavior. The explict calls to the capability module
are removed where they would duplicate the stacked call.
---
include/linux/security.h | 6 +-
security/Makefile | 2 +-
security/apparmor/domain.c | 4 +-
security/apparmor/lsm.c | 20 +-
security/commoncap.c | 34 ++
security/security.c | 1185 +++++++++++++++++++++++++++++++++++++++++---
security/selinux/hooks.c | 48 +-
security/smack/smack_lsm.c | 35 +-
security/tomoyo/tomoyo.c | 6 -
security/yama/yama_lsm.c | 36 +-
10 files changed, 1187 insertions(+), 189 deletions(-)
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 83d06db..4b8852c 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -1993,12 +1981,6 @@ static int selinux_capset(struct cred *new, const struct cred *old,
static int selinux_capable(const struct cred *cred, struct user_namespace *ns,
int cap, int audit)
{
- int rc;
-
- rc = cap_capable(cred, ns, cap, audit);
- if (rc)
- return rc;
-
return cred_has_capability(cred, cap, audit);
}
When you make this change, you need to also update all internal calls to
selinux_capable() within SELinux to instead call security_capable() in
order to preserve applying both the standard capability check and the
SELinux check. Examples include selinux_vm_enough_memory(), which
cannot be stacked in the usual way due to the accounting performed by
__vm_enough_memory(), and selinux_inode_getsecurity().

--
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
the body of a message to ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Stephen Smalley
2014-08-12 14:18:50 UTC
Permalink
Post by Stephen Smalley
Post by Casey Schaufler
Subject: [PATCH v16 2/4] LSM: Refactor existing LSM stacking
The existing code stacks up to three security modules.
If there is only one module it is the capability module.
If a module is specified the capability code is explicitly
called within the specified module. If Yama stacking is
configured the yama hooks are called and then the specified
module. The capability check is made twice in the yama
stacking case.
This patch adds a list for each of the LSM hooks. The capability
hooks that are non-trivial are put on the list first. If Yama
stacking is configured the yama hooks are added to the list.
If a module is configured it gets added next. Each entry in the
(capability[ yama][ {selinux|smack|tomoyo|apparmor}])
Exit is on first failure (bail on fail) which matches the
existing behavior. The explict calls to the capability module
are removed where they would duplicate the stacked call.
---
include/linux/security.h | 6 +-
security/Makefile | 2 +-
security/apparmor/domain.c | 4 +-
security/apparmor/lsm.c | 20 +-
security/commoncap.c | 34 ++
security/security.c | 1185 +++++++++++++++++++++++++++++++++++++++++---
security/selinux/hooks.c | 48 +-
security/smack/smack_lsm.c | 35 +-
security/tomoyo/tomoyo.c | 6 -
security/yama/yama_lsm.c | 36 +-
10 files changed, 1187 insertions(+), 189 deletions(-)
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 83d06db..4b8852c 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -1993,12 +1981,6 @@ static int selinux_capset(struct cred *new, const struct cred *old,
static int selinux_capable(const struct cred *cred, struct user_namespace *ns,
int cap, int audit)
{
- int rc;
-
- rc = cap_capable(cred, ns, cap, audit);
- if (rc)
- return rc;
-
return cred_has_capability(cred, cap, audit);
}
When you make this change, you need to also update all internal calls to
selinux_capable() within SELinux to instead call security_capable() in
order to preserve applying both the standard capability check and the
SELinux check. Examples include selinux_vm_enough_memory(), which
cannot be stacked in the usual way due to the accounting performed by
__vm_enough_memory(), and selinux_inode_getsecurity().
Sorry, that should be security_capable_noaudit().


--
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
the body of a message to ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Kees Cook
2014-08-14 19:04:06 UTC
Permalink
Post by Casey Schaufler
Subject: [PATCH v16 2/4] LSM: Refactor existing LSM stacking
The existing code stacks up to three security modules.
If there is only one module it is the capability module.
If a module is specified the capability code is explicitly
called within the specified module. If Yama stacking is
configured the yama hooks are called and then the specified
module. The capability check is made twice in the yama
stacking case.
Is it worth clarifying that it's not the cap_* call, but the
is_capable call that gets repeated for Yama?
Post by Casey Schaufler
This patch adds a list for each of the LSM hooks. The capability
hooks that are non-trivial are put on the list first. If Yama
stacking is configured the yama hooks are added to the list.
If a module is configured it gets added next. Each entry in the
(capability[ yama][ {selinux|smack|tomoyo|apparmor}])
Is this realy an "|" operation? Aren't they all just processed in order?
Post by Casey Schaufler
Exit is on first failure (bail on fail) which matches the
existing behavior. The explict calls to the capability module
are removed where they would duplicate the stacked call.
---
include/linux/security.h | 6 +-
security/Makefile | 2 +-
security/apparmor/domain.c | 4 +-
security/apparmor/lsm.c | 20 +-
security/commoncap.c | 34 ++
security/security.c | 1185 +++++++++++++++++++++++++++++++++++++++++---
security/selinux/hooks.c | 48 +-
security/smack/smack_lsm.c | 35 +-
security/tomoyo/tomoyo.c | 6 -
security/yama/yama_lsm.c | 36 +-
10 files changed, 1187 insertions(+), 189 deletions(-)
diff --git a/include/linux/security.h b/include/linux/security.h
index 9c6b972..29076d6 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -101,6 +101,8 @@ extern int cap_task_setioprio(struct task_struct *p, int ioprio);
extern int cap_task_setnice(struct task_struct *p, int nice);
extern int cap_vm_enough_memory(struct mm_struct *mm, long pages);
+extern struct security_operations capability_ops;
+
struct msghdr;
struct sk_buff;
struct sock;
@@ -116,7 +118,9 @@ struct seq_file;
extern int cap_netlink_send(struct sock *sk, struct sk_buff *skb);
-void reset_security_ops(void);
+#ifdef CONFIG_SECURITY_SELINUX_DISABLE
+void security_module_disable(struct security_operations *);
+#endif
#ifdef CONFIG_MMU
extern unsigned long mmap_min_addr;
diff --git a/security/Makefile b/security/Makefile
index 05f1c93..c9bfbc8 100644
--- a/security/Makefile
+++ b/security/Makefile
@@ -14,7 +14,7 @@ obj-y += commoncap.o
obj-$(CONFIG_MMU) += min_addr.o
# Object file lists
-obj-$(CONFIG_SECURITY) += security.o capability.o
+obj-$(CONFIG_SECURITY) += security.o
obj-$(CONFIG_SECURITYFS) += inode.o
obj-$(CONFIG_SECURITY_SELINUX) += selinux/
obj-$(CONFIG_SECURITY_SMACK) += smack/
diff --git a/security/apparmor/domain.c b/security/apparmor/domain.c
index 452567d..38aefc0 100644
--- a/security/apparmor/domain.c
+++ b/security/apparmor/domain.c
@@ -347,9 +347,7 @@ int apparmor_bprm_set_creds(struct linux_binprm *bprm)
file_inode(bprm->file)->i_mode
};
const char *name = NULL, *target = NULL, *info = NULL;
- int error = cap_bprm_set_creds(bprm);
- if (error)
- return error;
+ int error = 0;
if (bprm->cred_prepared)
return 0;
diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c
index 9981000..e29c92d 100644
--- a/security/apparmor/lsm.c
+++ b/security/apparmor/lsm.c
@@ -96,19 +96,11 @@ static void apparmor_cred_transfer(struct cred *new, const struct cred *old)
static int apparmor_ptrace_access_check(struct task_struct *child,
unsigned int mode)
{
- int error = cap_ptrace_access_check(child, mode);
- if (error)
- return error;
-
return aa_ptrace(current, child, mode);
}
static int apparmor_ptrace_traceme(struct task_struct *parent)
{
- int error = cap_ptrace_traceme(parent);
- if (error)
- return error;
-
return aa_ptrace(parent, current, PTRACE_MODE_ATTACH);
}
@@ -140,13 +132,11 @@ static int apparmor_capable(const struct cred *cred, struct user_namespace *ns,
int cap, int audit)
{
struct aa_profile *profile;
- /* cap_capable returns 0 on success, else -EPERM */
- int error = cap_capable(cred, ns, cap, audit);
- if (!error) {
- profile = aa_cred_profile(cred);
- if (!unconfined(profile))
- error = aa_capable(profile, cap, audit);
- }
+ int error = 0;
+
+ profile = aa_cred_profile(cred);
+ if (!unconfined(profile))
+ error = aa_capable(profile, cap, audit);
return error;
}
diff --git a/security/commoncap.c b/security/commoncap.c
index b9d613e..1cfc27c 100644
--- a/security/commoncap.c
+++ b/security/commoncap.c
@@ -994,3 +994,37 @@ int cap_mmap_file(struct file *file, unsigned long reqprot,
{
return 0;
}
+
+#ifdef CONFIG_SECURITY
+
+struct security_operations capability_ops = {
+ .name = "capability",
+ .capable = cap_capable,
+ .settime = cap_settime,
+ .ptrace_access_check = cap_ptrace_access_check,
+ .ptrace_traceme = cap_ptrace_traceme,
+ .capget = cap_capget,
+ .capset = cap_capset,
+ .bprm_set_creds = cap_bprm_set_creds,
+ /*
+ * Not stacked in the usual way.
+ * .bprm_secureexec = cap_bprm_secureexec,
+ * .inode_setxattr = cap_inode_setxattr,
+ * .inode_removexattr = cap_inode_removexattr,
+ */
+ .inode_need_killpriv = cap_inode_need_killpriv,
+ .inode_killpriv = cap_inode_killpriv,
+ /*
+ * Not stacked in the usual way.
+ * .mmap_addr = cap_mmap_addr,
+ */
+ .mmap_file = cap_mmap_file,
+ .task_fix_setuid = cap_task_fix_setuid,
+ .task_prctl = cap_task_prctl,
+ .task_setscheduler = cap_task_setscheduler,
+ .task_setioprio = cap_task_setioprio,
+ .task_setnice = cap_task_setnice,
+ .vm_enough_memory = cap_vm_enough_memory,
+};
It may be worth calling out in include/linux/security.h the operations
that aren't stacked in the "usual" way, and how an LSM should handle
it.
Post by Casey Schaufler
+
+#endif /* CONFIG_SECURITY */
diff --git a/security/security.c b/security/security.c
index b8c14d0..cf26b62 100644
--- a/security/security.c
+++ b/security/security.c
@@ -25,28 +25,20 @@
#include <linux/mount.h>
#include <linux/personality.h>
#include <linux/backing-dev.h>
+#include <linux/list.h>
#include <net/flow.h>
+struct security_hook_list {
+ struct list_head shl_head;
+ struct security_operations *shl_ops;
+};
+
#define MAX_LSM_EVM_XATTR 2
/* Boot-time LSM user choice */
static __initdata char chosen_lsm[SECURITY_NAME_MAX + 1] =
CONFIG_DEFAULT_SECURITY;
-static struct security_operations *security_ops;
-static struct security_operations default_security_ops = {
- .name = "default",
-};
-
-static inline int __init verify(struct security_operations *ops)
-{
- /* verify the security_operations structure exists */
- if (!ops)
- return -EINVAL;
- security_fixup_ops(ops);
- return 0;
-}
-
static void __init do_security_initcalls(void)
{
initcall_t *call;
@@ -57,6 +49,11 @@ static void __init do_security_initcalls(void)
}
}
+static int __init security_enlist_ops(struct security_operations *sop);
+
+#ifdef CONFIG_SECURITY_YAMA_STACKED
+extern struct security_operations yama_ops;
+#endif
/**
* security_init - initializes the security framework
*
@@ -64,20 +61,30 @@ static void __init do_security_initcalls(void)
*/
int __init security_init(void)
{
+ int rc;
+
printk(KERN_INFO "Security Framework initialized\n");
- security_fixup_ops(&default_security_ops);
- security_ops = &default_security_ops;
+ /*
+ * Always load the capability module.
+ */
+ rc = security_enlist_ops(&capability_ops);
+ if (rc)
+ return rc;
+#ifdef CONFIG_SECURITY_YAMA_STACKED
+ rc = security_enlist_ops(&yama_ops);
+ if (rc)
+ return rc;
+#endif
It seems like a follow-on patch after the i_security mux is done would
add the logic for "chosen_lsm" to be a list? And then the build
default would be "everything built in" and
CONFIG_SECURITY_YAMA_STACKED would go away, yes?

Or is the intent for minor stacked LSMs to just get initialized in
security_init, or to not call security_enabled() during their own
init? Yama could do this now, actually to remove
CONFIG_SECURITY_YAMA_STACKED.
Post by Casey Schaufler
+ /*
+ * Load the chosen module if there is one.
+ * This will also find yama if it is stacking
+ */
do_security_initcalls();
Is this comment left-over? Yama stack is handled above.
Post by Casey Schaufler
return 0;
}
[...snip...]
Post by Casey Schaufler
+
+static int __init security_enlist_ops(struct security_operations *sop)
+{
+ printk(KERN_INFO "Security operations for %s initialized\n", sop->name);
Should this be at the end, instead? It's past tense, and failures
should be reported via the individual LSM.
Post by Casey Schaufler
+
+ if (add_hook_to_list(&hooks_ptrace_access_check,
+ sop->ptrace_access_check, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_ptrace_traceme, sop->ptrace_traceme, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_capget, sop->capget, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_capset, sop->capset, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_capable, sop->capable, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_quotactl, sop->quotactl, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_quota_on, sop->quota_on, sop))
+ return -ENOMEM;
+ if (add_hook_to_list(&hooks_syslog, sop->syslog, sop))
+ return -ENOMEM;
[...snip...]
Post by Casey Schaufler
diff --git a/security/yama/yama_lsm.c b/security/yama/yama_lsm.c
index 13c88fbc..7974a23 100644
--- a/security/yama/yama_lsm.c
+++ b/security/yama/yama_lsm.c
@@ -154,13 +154,9 @@ void yama_task_free(struct task_struct *task)
int yama_task_prctl(int option, unsigned long arg2, unsigned long arg3,
unsigned long arg4, unsigned long arg5)
{
- int rc;
+ int rc = 0;
struct task_struct *myself = current;
- rc = cap_task_prctl(option, arg2, arg3, arg4, arg5);
- if (rc != -ENOSYS)
- return rc;
-
switch (option) {
/* Since a thread can call prctl(), find the group leader
@@ -284,13 +280,6 @@ int yama_ptrace_access_check(struct task_struct *child,
{
int rc;
- /* If standard caps disallows it, so does Yama. We should
- * only tighten restrictions further.
- */
- rc = cap_ptrace_access_check(child, mode);
- if (rc)
- return rc;
-
/* require ptrace target be a child of ptracer on attach */
if (mode == PTRACE_MODE_ATTACH) {
switch (ptrace_scope) {
@@ -335,14 +324,7 @@ int yama_ptrace_access_check(struct task_struct *child,
*/
int yama_ptrace_traceme(struct task_struct *parent)
{
- int rc;
-
- /* If standard caps disallows it, so does Yama. We should
- * only tighten restrictions further.
- */
- rc = cap_ptrace_traceme(parent);
- if (rc)
- return rc;
+ int rc = 0;
/* Only disallow PTRACE_TRACEME on more aggressive settings. */
switch (ptrace_scope) {
@@ -364,8 +346,7 @@ int yama_ptrace_traceme(struct task_struct *parent)
return rc;
}
-#ifndef CONFIG_SECURITY_YAMA_STACKED
-static struct security_operations yama_ops = {
+struct security_operations yama_ops = {
.name = "yama",
.ptrace_access_check = yama_ptrace_access_check,
@@ -373,7 +354,6 @@ static struct security_operations yama_ops = {
.task_prctl = yama_task_prctl,
.task_free = yama_task_free,
};
-#endif
#ifdef CONFIG_SYSCTL
static int yama_dointvec_minmax(struct ctl_table *table, int write,
@@ -421,17 +401,17 @@ static struct ctl_table yama_sysctl_table[] = {
static __init int yama_init(void)
{
#ifndef CONFIG_SECURITY_YAMA_STACKED
+ /*
+ * If yama is being stacked this is already taken care of.
+ */
if (!security_module_enable(&yama_ops))
return 0;
-#endif
-
- printk(KERN_INFO "Yama: becoming mindful.\n");
-
-#ifndef CONFIG_SECURITY_YAMA_STACKED
if (register_security(&yama_ops))
panic("Yama: kernel registration failed.\n");
#endif
+ printk(KERN_INFO "Yama: becoming mindful.\n");
+
#ifdef CONFIG_SYSCTL
if (!register_sysctl_paths(yama_sysctl_path, yama_sysctl_table))
panic("Yama: sysctl registration failed.\n");
For example, the CONFIG_SECURITY_YAMA_STACKED special cases could be
dropped and Yama's yama_init() could be:

static __init int yama_init(void)
{
/* Does not call security_module_enable() so it always stacks. */
printk(KERN_INFO "Yama: becoming mindful.\n");

if (register_security(&yama_ops))
panic("Yama: kernel registration failed.\n");

#ifdef CONFIG_SYSCTL
if (!register_sysctl_paths(yama_sysctl_path, yama_sysctl_table))
panic("Yama: sysctl registration failed.\n");
....

But perhaps explicit ordering in security_init is better?

Thanks!

-Kees
--
Kees Cook
Chrome OS Security
--
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
the body of a message to ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Tetsuo Handa
2014-08-23 11:45:05 UTC
Permalink
Comments from thread-safety point of view for runtime-unregistration.
Post by Casey Schaufler
-#define call_void_hook(FUNC, ...) security_ops->FUNC(__VA_ARGS__)
-#define call_int_hook(FUNC, ...) security_ops->FUNC(__VA_ARGS__)
+#ifdef CONFIG_SECURITY_SELINUX_DISABLE
+
+#define call_void_hook(FUNC, ...) \
+ do { \
+ struct security_hook_list *P; \
+ \
+ if (hooks_##FUNC.next == NULL) \
+ break; \
Why not to kill this check by changing from

static struct list_head hooks_xxx;

to

static LIST_HEAD(hooks_xxx);

?
Post by Casey Schaufler
+ if (list_empty(&hooks_##FUNC)) \
+ break; \
Is this check needed?
I think that list_for_each_entry() is a no-op if list_empty() is true.
Post by Casey Schaufler
+ \
+ list_for_each_entry(P, &hooks_##FUNC, shl_head) { \
+ if (P->shl_ops == NULL) \
+ continue; \
There is NULL pointer dereference race window because clear_hook_entry() can
set P->shl_ops to NULL after current thread passed this check. You need to
save P->shl_ops into a local temporary variable in case clear_hook_entry()
is called.
Post by Casey Schaufler
+ P->shl_ops->FUNC(__VA_ARGS__); \
+ } \
+ } while (0) \
+
+#define call_int_hook(FUNC, ...) ({ \
+ int RC = 0; \
+ do { \
+ struct security_hook_list *P; \
+ \
+ if (hooks_##FUNC.next == NULL) \
+ break; \
+ if (list_empty(&hooks_##FUNC)) \
+ break; \
+ \
+ list_for_each_entry(P, &hooks_##FUNC, shl_head) { \
+ if (P->shl_ops == NULL) \
+ continue; \
Ditto for this macro.
Post by Casey Schaufler
+ RC = P->shl_ops->FUNC(__VA_ARGS__); \
+ if (RC != 0) \
+ break; \
+ } \
+ } while (0); \
+ RC; \
+}) \
+
+#else /* CONFIG_SECURITY_SELINUX_DISABLE */
@@ -619,7 +759,15 @@ int security_inode_setxattr(struct dentry *dentry, const char *name,
if (unlikely(IS_PRIVATE(dentry->d_inode)))
return 0;
- ret = call_int_hook(inode_setxattr, dentry, name, value, size, flags);
+ /*
+ * SELinux and Smack integrate the cap call,
+ * so assume that all LSMs supplying this call do so.
+ */
+ if (list_empty(&hooks_inode_setxattr))
+ ret = cap_inode_setxattr(dentry, name, value, size, flags);
+ else
+ ret = call_int_hook(inode_setxattr, dentry, name, value,
+ size, flags);
Is this race-free when clear_hook_entry() is called after current thread
passed list_empty(&hooks_inode_setxattr) check?
Post by Casey Schaufler
if (ret)
return ret;
+static struct list_head hooks_inode_getsecurity;
int security_inode_getsecurity(const struct inode *inode, const char *name, void **buffer, bool alloc)
{
if (unlikely(IS_PRIVATE(inode)))
return -EOPNOTSUPP;
+ if (list_empty(&hooks_inode_getsecurity))
+ return -EOPNOTSUPP;
return call_int_hook(inode_getsecurity, inode, name, buffer, alloc);
}
call_int_hook() must return -EOPNOTSUPP rather than 0 when clear_hook_entry()
is called after current thread passed list_empty(&hooks_inode_getsecurity)
check. What about passing default return value (which would be either 0 or
-EOPNOTSUPP) to call_int_hook() ?
Post by Casey Schaufler
@@ -700,11 +866,16 @@ int security_inode_listsecurity(struct inode *inode, char *buffer, size_t buffer
}
EXPORT_SYMBOL(security_inode_listsecurity);
+static struct list_head hooks_inode_getsecid;
void security_inode_getsecid(const struct inode *inode, u32 *secid)
{
- call_void_hook(inode_getsecid, inode, secid);
+ if (list_empty(&hooks_inode_getsecid))
+ *secid = 0;
+ else
+ call_void_hook(inode_getsecid, inode, secid);
}
Maybe we want to unconditionally do

*secid = 0;

before list_empty(&hooks_inode_getsecid) check in case clear_hook_entry() is
called.
--
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
the body of a message to ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Tetsuo Handa
2014-09-07 06:56:01 UTC
Permalink
Post by Tetsuo Handa
Comments from thread-safety point of view for runtime-unregistration.
Here is an only compile tested patch which reflected some of my comments.

security/security.c | 1324 +++++++++++++------------------------------------------------
1 file changed, 301 insertions(+), 1023 deletions(-)

diff --git a/security/security.c b/security/security.c
index 678b905..86d49a5 100644
--- a/security/security.c
+++ b/security/security.c
@@ -28,6 +28,214 @@
#include <linux/list.h>
#include <net/flow.h>

+enum lsm_hooks_index {
+ lsm_ptrace_access_check,
+ lsm_ptrace_traceme,
+ lsm_capget,
+ lsm_capset,
+ lsm_capable,
+ lsm_quotactl,
+ lsm_quota_on,
+ lsm_syslog,
+ lsm_settime,
+ lsm_vm_enough_memory,
+ lsm_bprm_set_creds,
+ lsm_bprm_check_security,
+ lsm_bprm_secureexec,
+ lsm_bprm_committing_creds,
+ lsm_bprm_committed_creds,
+ lsm_sb_alloc_security,
+ lsm_sb_free_security,
+ lsm_sb_copy_data,
+ lsm_sb_remount,
+ lsm_sb_kern_mount,
+ lsm_sb_show_options,
+ lsm_sb_statfs,
+ lsm_sb_mount,
+ lsm_sb_umount,
+ lsm_sb_pivotroot,
+ lsm_sb_set_mnt_opts,
+ lsm_sb_clone_mnt_opts,
+ lsm_sb_parse_opts_str,
+ lsm_dentry_init_security,
+#ifdef CONFIG_SECURITY_PATH
+ lsm_path_unlink,
+ lsm_path_mkdir,
+ lsm_path_rmdir,
+ lsm_path_mknod,
+ lsm_path_truncate,
+ lsm_path_symlink,
+ lsm_path_link,
+ lsm_path_rename,
+ lsm_path_chmod,
+ lsm_path_chown,
+ lsm_path_chroot,
+#endif
+ lsm_inode_alloc_security,
+ lsm_inode_free_security,
+ lsm_inode_init_security,
+ lsm_inode_create,
+ lsm_inode_link,
+ lsm_inode_unlink,
+ lsm_inode_symlink,
+ lsm_inode_mkdir,
+ lsm_inode_rmdir,
+ lsm_inode_mknod,
+ lsm_inode_rename,
+ lsm_inode_readlink,
+ lsm_inode_follow_link,
+ lsm_inode_permission,
+ lsm_inode_setattr,
+ lsm_inode_getattr,
+ lsm_inode_setxattr,
+ lsm_inode_post_setxattr,
+ lsm_inode_getxattr,
+ lsm_inode_listxattr,
+ lsm_inode_removexattr,
+ lsm_inode_need_killpriv,
+ lsm_inode_killpriv,
+ lsm_inode_getsecurity,
+ lsm_inode_setsecurity,
+ lsm_inode_listsecurity,
+ lsm_inode_getsecid,
+ lsm_file_permission,
+ lsm_file_alloc_security,
+ lsm_file_free_security,
+ lsm_file_ioctl,
+ lsm_mmap_addr,
+ lsm_mmap_file,
+ lsm_file_mprotect,
+ lsm_file_lock,
+ lsm_file_fcntl,
+ lsm_file_set_fowner,
+ lsm_file_send_sigiotask,
+ lsm_file_receive,
+ lsm_file_open,
+ lsm_task_create,
+ lsm_task_free,
+ lsm_cred_alloc_blank,
+ lsm_cred_free,
+ lsm_cred_prepare,
+ lsm_cred_transfer,
+ lsm_kernel_act_as,
+ lsm_kernel_create_files_as,
+ lsm_kernel_module_request,
+ lsm_kernel_module_from_file,
+ lsm_task_fix_setuid,
+ lsm_task_setpgid,
+ lsm_task_getpgid,
+ lsm_task_getsid,
+ lsm_task_getsecid,
+ lsm_task_setnice,
+ lsm_task_setioprio,
+ lsm_task_getioprio,
+ lsm_task_setrlimit,
+ lsm_task_setscheduler,
+ lsm_task_getscheduler,
+ lsm_task_movememory,
+ lsm_task_kill,
+ lsm_task_wait,
+ lsm_task_prctl,
+ lsm_task_to_inode,
+ lsm_ipc_permission,
+ lsm_ipc_getsecid,
+ lsm_msg_msg_alloc_security,
+ lsm_msg_msg_free_security,
+ lsm_msg_queue_alloc_security,
+ lsm_msg_queue_free_security,
+ lsm_msg_queue_associate,
+ lsm_msg_queue_msgctl,
+ lsm_msg_queue_msgsnd,
+ lsm_msg_queue_msgrcv,
+ lsm_shm_alloc_security,
+ lsm_shm_free_security,
+ lsm_shm_associate,
+ lsm_shm_shmctl,
+ lsm_shm_shmat,
+ lsm_sem_alloc_security,
+ lsm_sem_free_security,
+ lsm_sem_associate,
+ lsm_sem_semctl,
+ lsm_sem_semop,
+ lsm_netlink_send,
+ lsm_d_instantiate,
+ lsm_getprocattr,
+ lsm_setprocattr,
+ lsm_ismaclabel,
+ lsm_secid_to_secctx,
+ lsm_secctx_to_secid,
+ lsm_release_secctx,
+ lsm_inode_notifysecctx,
+ lsm_inode_setsecctx,
+ lsm_inode_getsecctx,
+#ifdef CONFIG_SECURITY_NETWORK
+ lsm_unix_stream_connect,
+ lsm_unix_may_send,
+ lsm_socket_create,
+ lsm_socket_post_create,
+ lsm_socket_bind,
+ lsm_socket_connect,
+ lsm_socket_listen,
+ lsm_socket_accept,
+ lsm_socket_sendmsg,
+ lsm_socket_recvmsg,
+ lsm_socket_getsockname,
+ lsm_socket_getpeername,
+ lsm_socket_getsockopt,
+ lsm_socket_setsockopt,
+ lsm_socket_shutdown,
+ lsm_socket_sock_rcv_skb,
+ lsm_socket_getpeersec_stream,
+ lsm_socket_getpeersec_dgram,
+ lsm_sk_alloc_security,
+ lsm_sk_free_security,
+ lsm_sk_clone_security,
+ lsm_sk_getsecid,
+ lsm_sock_graft,
+ lsm_inet_conn_request,
+ lsm_inet_csk_clone,
+ lsm_inet_conn_established,
+ lsm_secmark_relabel_packet,
+ lsm_secmark_refcount_inc,
+ lsm_secmark_refcount_dec,
+ lsm_req_classify_flow,
+ lsm_tun_dev_alloc_security,
+ lsm_tun_dev_free_security,
+ lsm_tun_dev_create,
+ lsm_tun_dev_attach_queue,
+ lsm_tun_dev_attach,
+ lsm_tun_dev_open,
+ lsm_skb_owned_by,
+#endif/* CONFIG_SECURITY_NETWORK */
+#ifdef CONFIG_SECURITY_NETWORK_XFRM
+ lsm_xfrm_policy_alloc_security,
+ lsm_xfrm_policy_clone_security,
+ lsm_xfrm_policy_free_security,
+ lsm_xfrm_policy_delete_security,
+ lsm_xfrm_state_alloc,
+ lsm_xfrm_state_alloc_acquire,
+ lsm_xfrm_state_free_security,
+ lsm_xfrm_state_delete_security,
+ lsm_xfrm_policy_lookup,
+ lsm_xfrm_state_pol_flow_match,
+ lsm_xfrm_decode_session,
+#endif/* CONFIG_SECURITY_NETWORK_XFRM */
+#ifdef CONFIG_KEYS
+ lsm_key_alloc,
+ lsm_key_free,
+ lsm_key_permission,
+ lsm_key_getsecurity,
+#endif/* CONFIG_KEYS */
+#ifdef CONFIG_AUDIT
+ lsm_audit_rule_init,
+ lsm_audit_rule_known,
+ lsm_audit_rule_match,
+ lsm_audit_rule_free,
+#endif /* CONFIG_AUDIT */
+ max_lsm_hooks
+};
+static struct list_head lsm_hooks[max_lsm_hooks];
+
struct security_hook_list {
struct list_head shl_head;
struct security_operations *shl_ops;
@@ -62,6 +270,10 @@ extern struct security_operations yama_ops;
int __init security_init(void)
{
int rc;
+ enum lsm_hooks_index i;
+
+ for (i = 0; i < max_lsm_hooks; i++)
+ INIT_LIST_HEAD(&lsm_hooks[i]);

printk(KERN_INFO "Security Framework initialized\n");

@@ -144,97 +356,63 @@ int __init register_security(struct security_operations *ops)
* call_void_hook:
* This is a hook that does not return a value.
*
+ * call_int_hook_default:
+ * This is a hook that returns a value.
+ * Stop on the first failure.
+ *
* call_int_hook:
* This is a hook that returns a value.
* Stop on the first failure.
*/

-#ifdef CONFIG_SECURITY_SELINUX_DISABLE
-
#define call_void_hook(FUNC, ...) \
do { \
struct security_hook_list *P; \
\
- if (hooks_##FUNC.next == NULL) \
- break; \
- if (list_empty(&hooks_##FUNC)) \
- break; \
- \
- list_for_each_entry(P, &hooks_##FUNC, shl_head) { \
- if (P->shl_ops == NULL) \
- continue; \
+ list_for_each_entry(P, &lsm_hooks[lsm_##FUNC], shl_head)\
P->shl_ops->FUNC(__VA_ARGS__); \
- } \
- } while (0) \
+ } while (0)

-#define call_int_hook(FUNC, ...) ({ \
- int RC = 0; \
+#define call_int_hook_default(rc, FUNC, ...) ({ \
+ int RC = rc; \
do { \
struct security_hook_list *P; \
\
- if (hooks_##FUNC.next == NULL) \
- break; \
- if (list_empty(&hooks_##FUNC)) \
- break; \
- \
- list_for_each_entry(P, &hooks_##FUNC, shl_head) { \
- if (P->shl_ops == NULL) \
- continue; \
+ list_for_each_entry(P, &lsm_hooks[lsm_##FUNC], shl_head) { \
RC = P->shl_ops->FUNC(__VA_ARGS__); \
if (RC != 0) \
break; \
} \
} while (0); \
RC; \
-}) \
-
-#else /* CONFIG_SECURITY_SELINUX_DISABLE */
-
-#define call_void_hook(FUNC, ...) \
- do { \
- struct security_hook_list *P; \
- \
- if (list_empty(&hooks_##FUNC)) \
- break; \
- \
- list_for_each_entry(P, &hooks_##FUNC, shl_head) \
- P->shl_ops->FUNC(__VA_ARGS__); \
- } while (0) \
+})

#define call_int_hook(FUNC, ...) ({ \
int RC = 0; \
do { \
struct security_hook_list *P; \
\
- if (list_empty(&hooks_##FUNC)) \
- break; \
- \
- list_for_each_entry(P, &hooks_##FUNC, shl_head) { \
+ list_for_each_entry(P, &lsm_hooks[lsm_##FUNC], shl_head) { \
RC = P->shl_ops->FUNC(__VA_ARGS__); \
if (RC != 0) \
break; \
} \
} while (0); \
RC; \
-}) \
-
-#endif /* CONFIG_SECURITY_SELINUX_DISABLE */
+})

/* Security operations */

-static struct list_head hooks_ptrace_access_check;
int security_ptrace_access_check(struct task_struct *child, unsigned int mode)
{
return call_int_hook(ptrace_access_check, child, mode);
}

-static struct list_head hooks_ptrace_traceme;
int security_ptrace_traceme(struct task_struct *parent)
{
return call_int_hook(ptrace_traceme, parent);
}

-static struct list_head hooks_capget;
int security_capget(struct task_struct *target,
kernel_cap_t *effective,
kernel_cap_t *inheritable,
@@ -243,7 +421,6 @@ int security_capget(struct task_struct *target,
return call_int_hook(capget, target, effective, inheritable, permitted);
}

-static struct list_head hooks_capset;
int security_capset(struct cred *new, const struct cred *old,
const kernel_cap_t *effective,
const kernel_cap_t *inheritable,
@@ -253,7 +430,6 @@ int security_capset(struct cred *new, const struct cred *old,
effective, inheritable, permitted);
}

-static struct list_head hooks_capable;
int security_capable(const struct cred *cred, struct user_namespace *ns,
int cap)
{
@@ -270,43 +446,36 @@ int security_capable_noaudit(const struct cred *cred, struct user_namespace *ns,
return call_int_hook(capable, cred, ns, cap, SECURITY_CAP_NOAUDIT);
}

-static struct list_head hooks_quotactl;
int security_quotactl(int cmds, int type, int id, struct super_block *sb)
{
return call_int_hook(quotactl, cmds, type, id, sb);
}

-static struct list_head hooks_quota_on;
int security_quota_on(struct dentry *dentry)
{
return call_int_hook(quota_on, dentry);
}

-static struct list_head hooks_syslog;
int security_syslog(int type)
{
return call_int_hook(syslog, type);
}

-static struct list_head hooks_settime;
int security_settime(const struct timespec *ts, const struct timezone *tz)
{
return call_int_hook(settime, ts, tz);
}

-static struct list_head hooks_vm_enough_memory;
int security_vm_enough_memory_mm(struct mm_struct *mm, long pages)
{
return call_int_hook(vm_enough_memory, mm, pages);
}

-static struct list_head hooks_bprm_set_creds;
int security_bprm_set_creds(struct linux_binprm *bprm)
{
return call_int_hook(bprm_set_creds, bprm);
}

-static struct list_head hooks_bprm_check_security;
int security_bprm_check(struct linux_binprm *bprm)
{
int ret;
@@ -317,100 +486,86 @@ int security_bprm_check(struct linux_binprm *bprm)
return ima_bprm_check(bprm);
}

-static struct list_head hooks_bprm_committing_creds;
void security_bprm_committing_creds(struct linux_binprm *bprm)
{
call_void_hook(bprm_committing_creds, bprm);
}

-static struct list_head hooks_bprm_committed_creds;
void security_bprm_committed_creds(struct linux_binprm *bprm)
{
call_void_hook(bprm_committed_creds, bprm);
}

-static struct list_head hooks_bprm_secureexec;
int security_bprm_secureexec(struct linux_binprm *bprm)
{
/*
* SELinux and Smack integrate the cap call,
* so assume that all LSMs supplying this call do so.
*/
- if (list_empty(&hooks_bprm_secureexec))
+ if (list_empty(&lsm_hooks[lsm_bprm_secureexec]))
return cap_bprm_secureexec(bprm);

return call_int_hook(bprm_secureexec, bprm);
}

-static struct list_head hooks_sb_alloc_security;
int security_sb_alloc(struct super_block *sb)
{
return call_int_hook(sb_alloc_security, sb);
}

-static struct list_head hooks_sb_free_security;
void security_sb_free(struct super_block *sb)
{
call_void_hook(sb_free_security, sb);
}

-static struct list_head hooks_sb_copy_data;
int security_sb_copy_data(char *orig, char *copy)
{
return call_int_hook(sb_copy_data, orig, copy);
}
EXPORT_SYMBOL(security_sb_copy_data);

-static struct list_head hooks_sb_remount;
int security_sb_remount(struct super_block *sb, void *data)
{
return call_int_hook(sb_remount, sb, data);
}

-static struct list_head hooks_sb_kern_mount;
int security_sb_kern_mount(struct super_block *sb, int flags, void *data)
{
return call_int_hook(sb_kern_mount, sb, flags, data);
}

-static struct list_head hooks_sb_show_options;
int security_sb_show_options(struct seq_file *m, struct super_block *sb)
{
return call_int_hook(sb_show_options, m, sb);
}

-static struct list_head hooks_sb_statfs;
int security_sb_statfs(struct dentry *dentry)
{
return call_int_hook(sb_statfs, dentry);
}

-static struct list_head hooks_sb_mount;
int security_sb_mount(const char *dev_name, struct path *path,
const char *type, unsigned long flags, void *data)
{
return call_int_hook(sb_mount, dev_name, path, type, flags, data);
}

-static struct list_head hooks_sb_umount;
int security_sb_umount(struct vfsmount *mnt, int flags)
{
return call_int_hook(sb_umount, mnt, flags);
}

-static struct list_head hooks_sb_pivotroot;
int security_sb_pivotroot(struct path *old_path, struct path *new_path)
{
return call_int_hook(sb_pivotroot, old_path, new_path);
}

-static struct list_head hooks_sb_set_mnt_opts;
int security_sb_set_mnt_opts(struct super_block *sb,
struct security_mnt_opts *opts,
unsigned long kern_flags,
unsigned long *set_kern_flags)
{
- if (list_empty(&hooks_sb_set_mnt_opts)) {
+ if (list_empty(&lsm_hooks[lsm_sb_set_mnt_opts])) {
if (unlikely(opts->num_mnt_opts))
return -EOPNOTSUPP;
}
@@ -420,7 +575,6 @@ int security_sb_set_mnt_opts(struct super_block *sb,
}
EXPORT_SYMBOL(security_sb_set_mnt_opts);

-static struct list_head hooks_sb_clone_mnt_opts;
int security_sb_clone_mnt_opts(const struct super_block *oldsb,
struct super_block *newsb)
{
@@ -428,39 +582,32 @@ int security_sb_clone_mnt_opts(const struct super_block *oldsb,
}
EXPORT_SYMBOL(security_sb_clone_mnt_opts);

-static struct list_head hooks_sb_parse_opts_str;
int security_sb_parse_opts_str(char *options, struct security_mnt_opts *opts)
{
return call_int_hook(sb_parse_opts_str, options, opts);
}
EXPORT_SYMBOL(security_sb_parse_opts_str);

-static struct list_head hooks_inode_alloc_security;
int security_inode_alloc(struct inode *inode)
{
return call_int_hook(inode_alloc_security, inode);
}

-static struct list_head hooks_inode_free_security;
void security_inode_free(struct inode *inode)
{
integrity_inode_free(inode);
call_void_hook(inode_free_security, inode);
}

-static struct list_head hooks_dentry_init_security;
int security_dentry_init_security(struct dentry *dentry, int mode,
struct qstr *name, void **ctx,
u32 *ctxlen)
{
- if (list_empty(&hooks_dentry_init_security))
- return -EOPNOTSUPP;
- return call_int_hook(dentry_init_security, dentry, mode, name,
- ctx, ctxlen);
+ return call_int_hook_default(-EOPNOTSUPP, dentry_init_security, dentry,
+ mode, name, ctx, ctxlen);
}
EXPORT_SYMBOL(security_dentry_init_security);

-static struct list_head hooks_inode_init_security;
int security_inode_init_security(struct inode *inode, struct inode *dir,
const struct qstr *qstr,
const initxattrs initxattrs, void *fs_data)
@@ -472,7 +619,7 @@ int security_inode_init_security(struct inode *inode, struct inode *dir,
if (unlikely(IS_PRIVATE(inode)))
return 0;

- if (list_empty(&hooks_inode_init_security))
+ if (list_empty(&lsm_hooks[lsm_inode_init_security]))
return 0;

if (!initxattrs)
@@ -509,7 +656,7 @@ int security_old_inode_init_security(struct inode *inode, struct inode *dir,
{
if (unlikely(IS_PRIVATE(inode)))
return -EOPNOTSUPP;
- if (list_empty(&hooks_inode_init_security))
+ if (list_empty(&lsm_hooks[lsm_inode_init_security]))
return 0;

return call_int_hook(inode_init_security, inode, dir, qstr, name,
@@ -518,7 +665,6 @@ int security_old_inode_init_security(struct inode *inode, struct inode *dir,
EXPORT_SYMBOL(security_old_inode_init_security);

#ifdef CONFIG_SECURITY_PATH
-static struct list_head hooks_path_mknod;
int security_path_mknod(struct path *dir, struct dentry *dentry, umode_t mode,
unsigned int dev)
{
@@ -528,7 +674,6 @@ int security_path_mknod(struct path *dir, struct dentry *dentry, umode_t mode,
}
EXPORT_SYMBOL(security_path_mknod);

-static struct list_head hooks_path_mkdir;
int security_path_mkdir(struct path *dir, struct dentry *dentry, umode_t mode)
{
if (unlikely(IS_PRIVATE(dir->dentry->d_inode)))
@@ -537,7 +682,6 @@ int security_path_mkdir(struct path *dir, struct dentry *dentry, umode_t mode)
}
EXPORT_SYMBOL(security_path_mkdir);

-static struct list_head hooks_path_rmdir;
int security_path_rmdir(struct path *dir, struct dentry *dentry)
{
if (unlikely(IS_PRIVATE(dir->dentry->d_inode)))
@@ -545,7 +689,6 @@ int security_path_rmdir(struct path *dir, struct dentry *dentry)
return call_int_hook(path_rmdir, dir, dentry);
}

-static struct list_head hooks_path_unlink;
int security_path_unlink(struct path *dir, struct dentry *dentry)
{
if (unlikely(IS_PRIVATE(dir->dentry->d_inode)))
@@ -554,7 +697,6 @@ int security_path_unlink(struct path *dir, struct dentry *dentry)
}
EXPORT_SYMBOL(security_path_unlink);

-static struct list_head hooks_path_symlink;
int security_path_symlink(struct path *dir, struct dentry *dentry,
const char *old_name)
{
@@ -563,7 +705,6 @@ int security_path_symlink(struct path *dir, struct dentry *dentry,
return call_int_hook(path_symlink, dir, dentry, old_name);
}

-static struct list_head hooks_path_link;
int security_path_link(struct dentry *old_dentry, struct path *new_dir,
struct dentry *new_dentry)
{
@@ -572,7 +713,6 @@ int security_path_link(struct dentry *old_dentry, struct path *new_dir,
return call_int_hook(path_link, old_dentry, new_dir, new_dentry);
}

-static struct list_head hooks_path_rename;
int security_path_rename(struct path *old_dir, struct dentry *old_dentry,
struct path *new_dir, struct dentry *new_dentry,
unsigned int flags)
@@ -593,7 +733,6 @@ int security_path_rename(struct path *old_dir, struct dentry *old_dentry,
}
EXPORT_SYMBOL(security_path_rename);

-static struct list_head hooks_path_truncate;
int security_path_truncate(struct path *path)
{
if (unlikely(IS_PRIVATE(path->dentry->d_inode)))
@@ -601,7 +740,6 @@ int security_path_truncate(struct path *path)
return call_int_hook(path_truncate, path);
}

-static struct list_head hooks_path_chmod;
int security_path_chmod(struct path *path, umode_t mode)
{
if (unlikely(IS_PRIVATE(path->dentry->d_inode)))
@@ -609,7 +747,6 @@ int security_path_chmod(struct path *path, umode_t mode)
return call_int_hook(path_chmod, path, mode);
}

-static struct list_head hooks_path_chown;
int security_path_chown(struct path *path, kuid_t uid, kgid_t gid)
{
if (unlikely(IS_PRIVATE(path->dentry->d_inode)))
@@ -617,14 +754,12 @@ int security_path_chown(struct path *path, kuid_t uid, kgid_t gid)
return call_int_hook(path_chown, path, uid, gid);
}

-static struct list_head hooks_path_chroot;
int security_path_chroot(struct path *path)
{
return call_int_hook(path_chroot, path);
}
#endif

-static struct list_head hooks_inode_create;
int security_inode_create(struct inode *dir, struct dentry *dentry, umode_t mode)
{
if (unlikely(IS_PRIVATE(dir)))
@@ -633,7 +768,6 @@ int security_inode_create(struct inode *dir, struct dentry *dentry, umode_t mode
}
EXPORT_SYMBOL_GPL(security_inode_create);

-static struct list_head hooks_inode_link;
int security_inode_link(struct dentry *old_dentry, struct inode *dir,
struct dentry *new_dentry)
{
@@ -642,7 +776,6 @@ int security_inode_link(struct dentry *old_dentry, struct inode *dir,
return call_int_hook(inode_link, old_dentry, dir, new_dentry);
}

-static struct list_head hooks_inode_unlink;
int security_inode_unlink(struct inode *dir, struct dentry *dentry)
{
if (unlikely(IS_PRIVATE(dentry->d_inode)))
@@ -650,7 +783,6 @@ int security_inode_unlink(struct inode *dir, struct dentry *dentry)
return call_int_hook(inode_unlink, dir, dentry);
}

-static struct list_head hooks_inode_symlink;
int security_inode_symlink(struct inode *dir, struct dentry *dentry,
const char *old_name)
{
@@ -659,7 +791,6 @@ int security_inode_symlink(struct inode *dir, struct dentry *dentry,
return call_int_hook(inode_symlink, dir, dentry, old_name);
}

-static struct list_head hooks_inode_mkdir;
int security_inode_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
{
if (unlikely(IS_PRIVATE(dir)))
@@ -668,7 +799,6 @@ int security_inode_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
}
EXPORT_SYMBOL_GPL(security_inode_mkdir);

-static struct list_head hooks_inode_rmdir;
int security_inode_rmdir(struct inode *dir, struct dentry *dentry)
{
if (unlikely(IS_PRIVATE(dentry->d_inode)))
@@ -676,7 +806,6 @@ int security_inode_rmdir(struct inode *dir, struct dentry *dentry)
return call_int_hook(inode_rmdir, dir, dentry);
}

-static struct list_head hooks_inode_mknod;
int security_inode_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t dev)
{
if (unlikely(IS_PRIVATE(dir)))
@@ -684,7 +813,6 @@ int security_inode_mknod(struct inode *dir, struct dentry *dentry, umode_t mode,
return call_int_hook(inode_mknod, dir, dentry, mode, dev);
}

-static struct list_head hooks_inode_rename;
int security_inode_rename(struct inode *old_dir, struct dentry *old_dentry,
struct inode *new_dir, struct dentry *new_dentry,
unsigned int flags)
@@ -704,7 +832,6 @@ int security_inode_rename(struct inode *old_dir, struct dentry *old_dentry,
new_dir, new_dentry);
}

-static struct list_head hooks_inode_readlink;
int security_inode_readlink(struct dentry *dentry)
{
if (unlikely(IS_PRIVATE(dentry->d_inode)))
@@ -712,7 +839,6 @@ int security_inode_readlink(struct dentry *dentry)
return call_int_hook(inode_readlink, dentry);
}

-static struct list_head hooks_inode_follow_link;
int security_inode_follow_link(struct dentry *dentry, struct nameidata *nd)
{
if (unlikely(IS_PRIVATE(dentry->d_inode)))
@@ -720,7 +846,6 @@ int security_inode_follow_link(struct dentry *dentry, struct nameidata *nd)
return call_int_hook(inode_follow_link, dentry, nd);
}

-static struct list_head hooks_inode_permission;
int security_inode_permission(struct inode *inode, int mask)
{
if (unlikely(IS_PRIVATE(inode)))
@@ -728,7 +853,6 @@ int security_inode_permission(struct inode *inode, int mask)
return call_int_hook(inode_permission, inode, mask);
}

-static struct list_head hooks_inode_setattr;
int security_inode_setattr(struct dentry *dentry, struct iattr *attr)
{
int ret;
@@ -742,7 +866,6 @@ int security_inode_setattr(struct dentry *dentry, struct iattr *attr)
}
EXPORT_SYMBOL_GPL(security_inode_setattr);

-static struct list_head hooks_inode_getattr;
int security_inode_getattr(struct vfsmount *mnt, struct dentry *dentry)
{
if (unlikely(IS_PRIVATE(dentry->d_inode)))
@@ -750,7 +873,6 @@ int security_inode_getattr(struct vfsmount *mnt, struct dentry *dentry)
return call_int_hook(inode_getattr, mnt, dentry);
}

-static struct list_head hooks_inode_setxattr;
int security_inode_setxattr(struct dentry *dentry, const char *name,
const void *value, size_t size, int flags)
{
@@ -762,7 +884,7 @@ int security_inode_setxattr(struct dentry *dentry, const char *name,
* SELinux and Smack integrate the cap call,
* so assume that all LSMs supplying this call do so.
*/
- if (list_empty(&hooks_inode_setxattr))
+ if (list_empty(&lsm_hooks[lsm_inode_setxattr]))
ret = cap_inode_setxattr(dentry, name, value, size, flags);
else
ret = call_int_hook(inode_setxattr, dentry, name, value,
@@ -776,7 +898,6 @@ int security_inode_setxattr(struct dentry *dentry, const char *name,
return evm_inode_setxattr(dentry, name, value, size);
}

-static struct list_head hooks_inode_post_setxattr;
void security_inode_post_setxattr(struct dentry *dentry, const char *name,
const void *value, size_t size, int flags)
{
@@ -786,7 +907,6 @@ void security_inode_post_setxattr(struct dentry *dentry, const char *name,
evm_inode_post_setxattr(dentry, name, value, size);
}

-static struct list_head hooks_inode_getxattr;
int security_inode_getxattr(struct dentry *dentry, const char *name)
{
if (unlikely(IS_PRIVATE(dentry->d_inode)))
@@ -794,7 +914,6 @@ int security_inode_getxattr(struct dentry *dentry, const char *name)
return call_int_hook(inode_getxattr, dentry, name);
}

-static struct list_head hooks_inode_listxattr;
int security_inode_listxattr(struct dentry *dentry)
{
if (unlikely(IS_PRIVATE(dentry->d_inode)))
@@ -802,7 +921,6 @@ int security_inode_listxattr(struct dentry *dentry)
return call_int_hook(inode_listxattr, dentry);
}

-static struct list_head hooks_inode_removexattr;
int security_inode_removexattr(struct dentry *dentry, const char *name)
{
int ret;
@@ -810,7 +928,7 @@ int security_inode_removexattr(struct dentry *dentry, const char *name)
if (unlikely(IS_PRIVATE(dentry->d_inode)))
return 0;

- if (list_empty(&hooks_inode_removexattr))
+ if (list_empty(&lsm_hooks[lsm_inode_removexattr]))
ret = cap_inode_removexattr(dentry, name);
else
ret = call_int_hook(inode_removexattr, dentry, name);
@@ -823,40 +941,32 @@ int security_inode_removexattr(struct dentry *dentry, const char *name)
return evm_inode_removexattr(dentry, name);
}

-static struct list_head hooks_inode_need_killpriv;
int security_inode_need_killpriv(struct dentry *dentry)
{
return call_int_hook(inode_need_killpriv, dentry);
}

-static struct list_head hooks_inode_killpriv;
int security_inode_killpriv(struct dentry *dentry)
{
return call_int_hook(inode_killpriv, dentry);
}

-static struct list_head hooks_inode_getsecurity;
int security_inode_getsecurity(const struct inode *inode, const char *name, void **buffer, bool alloc)
{
if (unlikely(IS_PRIVATE(inode)))
return -EOPNOTSUPP;
- if (list_empty(&hooks_inode_getsecurity))
- return -EOPNOTSUPP;
- return call_int_hook(inode_getsecurity, inode, name, buffer, alloc);
+ return call_int_hook_default(-EOPNOTSUPP, inode_getsecurity, inode,
+ name, buffer, alloc);
}

-static struct list_head hooks_inode_setsecurity;
int security_inode_setsecurity(struct inode *inode, const char *name, const void *value, size_t size, int flags)
{
if (unlikely(IS_PRIVATE(inode)))
return -EOPNOTSUPP;
- if (list_empty(&hooks_inode_setsecurity))
- return -EOPNOTSUPP;
- return call_int_hook(inode_setsecurity, inode, name, value, size,
- flags);
+ return call_int_hook_default(-EOPNOTSUPP, inode_setsecurity, inode,
+ name, value, size, flags);
}

-static struct list_head hooks_inode_listsecurity;
int security_inode_listsecurity(struct inode *inode, char *buffer, size_t buffer_size)
{
if (unlikely(IS_PRIVATE(inode)))
@@ -865,16 +975,12 @@ int security_inode_listsecurity(struct inode *inode, char *buffer, size_t buffer
}
EXPORT_SYMBOL(security_inode_listsecurity);

-static struct list_head hooks_inode_getsecid;
void security_inode_getsecid(const struct inode *inode, u32 *secid)
{
- if (list_empty(&hooks_inode_getsecid))
- *secid = 0;
- else
- call_void_hook(inode_getsecid, inode, secid);
+ *secid = 0;
+ call_void_hook(inode_getsecid, inode, secid);
}

-static struct list_head hooks_file_permission;
int security_file_permission(struct file *file, int mask)
{
int ret;
@@ -886,19 +992,16 @@ int security_file_permission(struct file *file, int mask)
return fsnotify_perm(file, mask);
}

-static struct list_head hooks_file_alloc_security;
int security_file_alloc(struct file *file)
{
return call_int_hook(file_alloc_security, file);
}

-static struct list_head hooks_file_free_security;
void security_file_free(struct file *file)
{
call_void_hook(file_free_security, file);
}

-static struct list_head hooks_file_ioctl;
int security_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
return call_int_hook(file_ioctl, file, cmd, arg);
@@ -938,7 +1041,6 @@ static inline unsigned long mmap_prot(struct file *file, unsigned long prot)
return prot;
}

-static struct list_head hooks_mmap_file;
int security_mmap_file(struct file *file, unsigned long prot,
unsigned long flags)
{
@@ -950,51 +1052,43 @@ int security_mmap_file(struct file *file, unsigned long prot,
return ima_file_mmap(file, prot);
}

-static struct list_head hooks_mmap_addr;
int security_mmap_addr(unsigned long addr)
{
return call_int_hook(mmap_addr, addr);
}

-static struct list_head hooks_file_mprotect;
int security_file_mprotect(struct vm_area_struct *vma, unsigned long reqprot,
unsigned long prot)
{
return call_int_hook(file_mprotect, vma, reqprot, prot);
}

-static struct list_head hooks_file_lock;
int security_file_lock(struct file *file, unsigned int cmd)
{
return call_int_hook(file_lock, file, cmd);
}

-static struct list_head hooks_file_fcntl;
int security_file_fcntl(struct file *file, unsigned int cmd, unsigned long arg)
{
return call_int_hook(file_fcntl, file, cmd, arg);
}

-static struct list_head hooks_file_set_fowner;
int security_file_set_fowner(struct file *file)
{
return call_int_hook(file_set_fowner, file);
}

-static struct list_head hooks_file_send_sigiotask;
int security_file_send_sigiotask(struct task_struct *tsk,
struct fown_struct *fown, int sig)
{
return call_int_hook(file_send_sigiotask, tsk, fown, sig);
}

-static struct list_head hooks_file_receive;
int security_file_receive(struct file *file)
{
return call_int_hook(file_receive, file);
}

-static struct list_head hooks_file_open;
int security_file_open(struct file *file, const struct cred *cred)
{
int ret;
@@ -1006,61 +1100,51 @@ int security_file_open(struct file *file, const struct cred *cred)
return fsnotify_perm(file, MAY_OPEN);
}

-static struct list_head hooks_task_create;
int security_task_create(unsigned long clone_flags)
{
return call_int_hook(task_create, clone_flags);
}

-static struct list_head hooks_task_free;
void security_task_free(struct task_struct *task)
{
call_void_hook(task_free, task);
}

-static struct list_head hooks_cred_alloc_blank;
int security_cred_alloc_blank(struct cred *cred, gfp_t gfp)
{
return call_int_hook(cred_alloc_blank, cred, gfp);
}

-static struct list_head hooks_cred_free;
void security_cred_free(struct cred *cred)
{
call_void_hook(cred_free, cred);
}

-static struct list_head hooks_cred_prepare;
int security_prepare_creds(struct cred *new, const struct cred *old, gfp_t gfp)
{
return call_int_hook(cred_prepare, new, old, gfp);
}

-static struct list_head hooks_cred_transfer;
void security_transfer_creds(struct cred *new, const struct cred *old)
{
call_void_hook(cred_transfer, new, old);
}

-static struct list_head hooks_kernel_act_as;
int security_kernel_act_as(struct cred *new, u32 secid)
{
return call_int_hook(kernel_act_as, new, secid);
}

-static struct list_head hooks_kernel_create_files_as;
int security_kernel_create_files_as(struct cred *new, struct inode *inode)
{
return call_int_hook(kernel_create_files_as, new, inode);
}

-static struct list_head hooks_kernel_module_request;
int security_kernel_module_request(char *kmod_name)
{
return call_int_hook(kernel_module_request, kmod_name);
}

-static struct list_head hooks_kernel_module_from_file;
int security_kernel_module_from_file(struct file *file)
{
int ret;
@@ -1071,98 +1155,81 @@ int security_kernel_module_from_file(struct file *file)
return ima_module_check(file);
}

-static struct list_head hooks_task_fix_setuid;
int security_task_fix_setuid(struct cred *new, const struct cred *old,
int flags)
{
return call_int_hook(task_fix_setuid, new, old, flags);
}

-static struct list_head hooks_task_setpgid;
int security_task_setpgid(struct task_struct *p, pid_t pgid)
{
return call_int_hook(task_setpgid, p, pgid);
}

-static struct list_head hooks_task_getpgid;
int security_task_getpgid(struct task_struct *p)
{
return call_int_hook(task_getpgid, p);
}

-static struct list_head hooks_task_getsid;
int security_task_getsid(struct task_struct *p)
{
return call_int_hook(task_getsid, p);
}

-static struct list_head hooks_task_getsecid;
void security_task_getsecid(struct task_struct *p, u32 *secid)
{
- if (list_empty(&hooks_task_getsecid))
- *secid = 0;
- else
- call_void_hook(task_getsecid, p, secid);
+ *secid = 0;
+ call_void_hook(task_getsecid, p, secid);
}
EXPORT_SYMBOL(security_task_getsecid);

-static struct list_head hooks_task_setnice;
int security_task_setnice(struct task_struct *p, int nice)
{
return call_int_hook(task_setnice, p, nice);
}

-static struct list_head hooks_task_setioprio;
int security_task_setioprio(struct task_struct *p, int ioprio)
{
return call_int_hook(task_setioprio, p, ioprio);
}

-static struct list_head hooks_task_getioprio;
int security_task_getioprio(struct task_struct *p)
{
return call_int_hook(task_getioprio, p);
}

-static struct list_head hooks_task_setrlimit;
int security_task_setrlimit(struct task_struct *p, unsigned int resource,
struct rlimit *new_rlim)
{
return call_int_hook(task_setrlimit, p, resource, new_rlim);
}

-static struct list_head hooks_task_setscheduler;
int security_task_setscheduler(struct task_struct *p)
{
return call_int_hook(task_setscheduler, p);
}

-static struct list_head hooks_task_getscheduler;
int security_task_getscheduler(struct task_struct *p)
{
return call_int_hook(task_getscheduler, p);
}

-static struct list_head hooks_task_movememory;
int security_task_movememory(struct task_struct *p)
{
return call_int_hook(task_movememory, p);
}

-static struct list_head hooks_task_kill;
int security_task_kill(struct task_struct *p, struct siginfo *info,
int sig, u32 secid)
{
return call_int_hook(task_kill, p, info, sig, secid);
}

-static struct list_head hooks_task_wait;
int security_task_wait(struct task_struct *p)
{
return call_int_hook(task_wait, p);
}

-static struct list_head hooks_task_prctl;
int security_task_prctl(int option, unsigned long arg2, unsigned long arg3,
unsigned long arg4, unsigned long arg5)
{
@@ -1170,16 +1237,11 @@ int security_task_prctl(int option, unsigned long arg2, unsigned long arg3,
int rc = -ENOSYS;
struct security_hook_list *shp;

- if (list_empty(&hooks_task_prctl))
+ if (list_empty(&lsm_hooks[lsm_task_prctl]))
return -ENOSYS;

- list_for_each_entry(shp, &hooks_task_prctl, shl_head) {
-#ifdef CONFIG_SECURITY_SELINUX_DISABLE
- if (shp->shl_ops == NULL)
- continue;
-#endif
- thisrc = shp->shl_ops->task_prctl(option, arg2, arg3,
- arg4, arg5);
+ list_for_each_entry(shp, &lsm_hooks[lsm_task_prctl], shl_head) {
+ thisrc = shp->shl_ops->task_prctl(option, arg2, arg3, arg4, arg5);
if (thisrc != -ENOSYS) {
rc = thisrc;
if (thisrc != 0)
@@ -1189,139 +1251,115 @@ int security_task_prctl(int option, unsigned long arg2, unsigned long arg3,
return rc;
}

-static struct list_head hooks_task_to_inode;
void security_task_to_inode(struct task_struct *p, struct inode *inode)
{
call_void_hook(task_to_inode, p, inode);
}

-static struct list_head hooks_ipc_permission;
int security_ipc_permission(struct kern_ipc_perm *ipcp, short flag)
{
return call_int_hook(ipc_permission, ipcp, flag);
}

-static struct list_head hooks_ipc_getsecid;
void security_ipc_getsecid(struct kern_ipc_perm *ipcp, u32 *secid)
{
- if (list_empty(&hooks_ipc_getsecid))
- *secid = 0;
- else
- call_void_hook(ipc_getsecid, ipcp, secid);
+ *secid = 0;
+ call_void_hook(ipc_getsecid, ipcp, secid);
}

-static struct list_head hooks_msg_msg_alloc_security;
int security_msg_msg_alloc(struct msg_msg *msg)
{
return call_int_hook(msg_msg_alloc_security, msg);
}

-static struct list_head hooks_msg_msg_free_security;
void security_msg_msg_free(struct msg_msg *msg)
{
call_void_hook(msg_msg_free_security, msg);
}

-static struct list_head hooks_msg_queue_alloc_security;
int security_msg_queue_alloc(struct msg_queue *msq)
{
return call_int_hook(msg_queue_alloc_security, msq);
}

-static struct list_head hooks_msg_queue_free_security;
void security_msg_queue_free(struct msg_queue *msq)
{
call_void_hook(msg_queue_free_security, msq);
}

-static struct list_head hooks_msg_queue_associate;
int security_msg_queue_associate(struct msg_queue *msq, int msqflg)
{
return call_int_hook(msg_queue_associate, msq, msqflg);
}

-static struct list_head hooks_msg_queue_msgctl;
int security_msg_queue_msgctl(struct msg_queue *msq, int cmd)
{
return call_int_hook(msg_queue_msgctl, msq, cmd);
}

-static struct list_head hooks_msg_queue_msgsnd;
int security_msg_queue_msgsnd(struct msg_queue *msq,
struct msg_msg *msg, int msqflg)
{
return call_int_hook(msg_queue_msgsnd, msq, msg, msqflg);
}

-static struct list_head hooks_msg_queue_msgrcv;
int security_msg_queue_msgrcv(struct msg_queue *msq, struct msg_msg *msg,
struct task_struct *target, long type, int mode)
{
return call_int_hook(msg_queue_msgrcv, msq, msg, target, type, mode);
}

-static struct list_head hooks_shm_alloc_security;
int security_shm_alloc(struct shmid_kernel *shp)
{
return call_int_hook(shm_alloc_security, shp);
}

-static struct list_head hooks_shm_free_security;
void security_shm_free(struct shmid_kernel *shp)
{
call_void_hook(shm_free_security, shp);
}

-static struct list_head hooks_shm_associate;
int security_shm_associate(struct shmid_kernel *shp, int shmflg)
{
return call_int_hook(shm_associate, shp, shmflg);
}

-static struct list_head hooks_shm_shmctl;
int security_shm_shmctl(struct shmid_kernel *shp, int cmd)
{
return call_int_hook(shm_shmctl, shp, cmd);
}

-static struct list_head hooks_shm_shmat;
int security_shm_shmat(struct shmid_kernel *shp, char __user *shmaddr, int shmflg)
{
return call_int_hook(shm_shmat, shp, shmaddr, shmflg);
}

-static struct list_head hooks_sem_alloc_security;
int security_sem_alloc(struct sem_array *sma)
{
return call_int_hook(sem_alloc_security, sma);
}

-static struct list_head hooks_sem_free_security;
void security_sem_free(struct sem_array *sma)
{
call_void_hook(sem_free_security, sma);
}

-static struct list_head hooks_sem_associate;
int security_sem_associate(struct sem_array *sma, int semflg)
{
return call_int_hook(sem_associate, sma, semflg);
}

-static struct list_head hooks_sem_semctl;
int security_sem_semctl(struct sem_array *sma, int cmd)
{
return call_int_hook(sem_semctl, sma, cmd);
}

-static struct list_head hooks_sem_semop;
int security_sem_semop(struct sem_array *sma, struct sembuf *sops,
unsigned nsops, int alter)
{
return call_int_hook(sem_semop, sma, sops, nsops, alter);
}

-static struct list_head hooks_d_instantiate;
void security_d_instantiate(struct dentry *dentry, struct inode *inode)
{
if (unlikely(inode && IS_PRIVATE(inode)))
@@ -1330,108 +1368,86 @@ void security_d_instantiate(struct dentry *dentry, struct inode *inode)
}
EXPORT_SYMBOL(security_d_instantiate);

-static struct list_head hooks_getprocattr;
int security_getprocattr(struct task_struct *p, char *name, char **value)
{
- if (list_empty(&hooks_getprocattr))
- return -EINVAL;
- return call_int_hook(getprocattr, p, name, value);
+ return call_int_hook_default(-EINVAL, getprocattr, p, name, value);
}

-static struct list_head hooks_setprocattr;
int security_setprocattr(struct task_struct *p, char *name, void *value, size_t size)
{
- if (list_empty(&hooks_setprocattr))
- return -EINVAL;
- return call_int_hook(setprocattr, p, name, value, size);
+ return call_int_hook_default(-EINVAL, setprocattr, p, name, value,
+ size);
}

-static struct list_head hooks_netlink_send;
int security_netlink_send(struct sock *sk, struct sk_buff *skb)
{
return call_int_hook(netlink_send, sk, skb);
}

-static struct list_head hooks_ismaclabel;
int security_ismaclabel(const char *name)
{
return call_int_hook(ismaclabel, name);
}
EXPORT_SYMBOL(security_ismaclabel);

-static struct list_head hooks_secid_to_secctx;
int security_secid_to_secctx(u32 secid, char **secdata, u32 *seclen)
{
- if (list_empty(&hooks_secid_to_secctx))
- return -EOPNOTSUPP;
- return call_int_hook(secid_to_secctx, secid, secdata, seclen);
+ return call_int_hook_default(-EOPNOTSUPP, secid_to_secctx, secid,
+ secdata, seclen);
}
EXPORT_SYMBOL(security_secid_to_secctx);

-static struct list_head hooks_secctx_to_secid;
int security_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid)
{
- if (list_empty(&hooks_secctx_to_secid)) {
- *secid = 0;
- return 0;
- }
+ *secid = 0;
return call_int_hook(secctx_to_secid, secdata, seclen, secid);
}
EXPORT_SYMBOL(security_secctx_to_secid);

-static struct list_head hooks_release_secctx;
void security_release_secctx(char *secdata, u32 seclen)
{
call_void_hook(release_secctx, secdata, seclen);
}
EXPORT_SYMBOL(security_release_secctx);

-static struct list_head hooks_inode_notifysecctx;
int security_inode_notifysecctx(struct inode *inode, void *ctx, u32 ctxlen)
{
return call_int_hook(inode_notifysecctx, inode, ctx, ctxlen);
}
EXPORT_SYMBOL(security_inode_notifysecctx);

-static struct list_head hooks_inode_setsecctx;
int security_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen)
{
return call_int_hook(inode_setsecctx, dentry, ctx, ctxlen);
}
EXPORT_SYMBOL(security_inode_setsecctx);

-static struct list_head hooks_inode_getsecctx;
int security_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen)
{
- if (list_empty(&hooks_inode_getsecctx))
- return -EOPNOTSUPP;
- return call_int_hook(inode_getsecctx, inode, ctx, ctxlen);
+ return call_int_hook_default(-EOPNOTSUPP, inode_getsecctx, inode, ctx,
+ ctxlen);
}
EXPORT_SYMBOL(security_inode_getsecctx);

#ifdef CONFIG_SECURITY_NETWORK

-static struct list_head hooks_unix_stream_connect;
int security_unix_stream_connect(struct sock *sock, struct sock *other, struct sock *newsk)
{
return call_int_hook(unix_stream_connect, sock, other, newsk);
}
EXPORT_SYMBOL(security_unix_stream_connect);

-static struct list_head hooks_unix_may_send;
int security_unix_may_send(struct socket *sock, struct socket *other)
{
return call_int_hook(unix_may_send, sock, other);
}
EXPORT_SYMBOL(security_unix_may_send);

-static struct list_head hooks_socket_create;
int security_socket_create(int family, int type, int protocol, int kern)
{
return call_int_hook(socket_create, family, type, protocol, kern);
}

-static struct list_head hooks_socket_post_create;
int security_socket_post_create(struct socket *sock, int family,
int type, int protocol, int kern)
{
@@ -1439,140 +1455,116 @@ int security_socket_post_create(struct socket *sock, int family,
protocol, kern);
}

-static struct list_head hooks_socket_bind;
int security_socket_bind(struct socket *sock, struct sockaddr *address, int addrlen)
{
return call_int_hook(socket_bind, sock, address, addrlen);
}

-static struct list_head hooks_socket_connect;
int security_socket_connect(struct socket *sock, struct sockaddr *address, int addrlen)
{
return call_int_hook(socket_connect, sock, address, addrlen);
}

-static struct list_head hooks_socket_listen;
int security_socket_listen(struct socket *sock, int backlog)
{
return call_int_hook(socket_listen, sock, backlog);
}

-static struct list_head hooks_socket_accept;
int security_socket_accept(struct socket *sock, struct socket *newsock)
{
return call_int_hook(socket_accept, sock, newsock);
}

-static struct list_head hooks_socket_sendmsg;
int security_socket_sendmsg(struct socket *sock, struct msghdr *msg, int size)
{
return call_int_hook(socket_sendmsg, sock, msg, size);
}

-static struct list_head hooks_socket_recvmsg;
int security_socket_recvmsg(struct socket *sock, struct msghdr *msg,
int size, int flags)
{
return call_int_hook(socket_recvmsg, sock, msg, size, flags);
}

-static struct list_head hooks_socket_getsockname;
int security_socket_getsockname(struct socket *sock)
{
return call_int_hook(socket_getsockname, sock);
}

-static struct list_head hooks_socket_getpeername;
int security_socket_getpeername(struct socket *sock)
{
return call_int_hook(socket_getpeername, sock);
}

-static struct list_head hooks_socket_getsockopt;
int security_socket_getsockopt(struct socket *sock, int level, int optname)
{
return call_int_hook(socket_getsockopt, sock, level, optname);
}

-static struct list_head hooks_socket_setsockopt;
int security_socket_setsockopt(struct socket *sock, int level, int optname)
{
return call_int_hook(socket_setsockopt, sock, level, optname);
}

-static struct list_head hooks_socket_shutdown;
int security_socket_shutdown(struct socket *sock, int how)
{
return call_int_hook(socket_shutdown, sock, how);
}

-static struct list_head hooks_socket_sock_rcv_skb;
int security_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
{
return call_int_hook(socket_sock_rcv_skb, sk, skb);
}
EXPORT_SYMBOL(security_sock_rcv_skb);

-static struct list_head hooks_socket_getpeersec_stream;
int security_socket_getpeersec_stream(struct socket *sock, char __user *optval,
int __user *optlen, unsigned len)
{
- if (list_empty(&hooks_socket_getpeersec_stream))
- return -ENOPROTOOPT;
- return call_int_hook(socket_getpeersec_stream, sock, optval, optlen,
- len);
+ return call_int_hook_default(-ENOPROTOOPT, socket_getpeersec_stream,
+ sock, optval, optlen, len);
}

-static struct list_head hooks_socket_getpeersec_dgram;
int security_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *skb, u32 *secid)
{
- if (list_empty(&hooks_socket_getpeersec_dgram))
- return -ENOPROTOOPT;
- return call_int_hook(socket_getpeersec_dgram, sock, skb, secid);
+ return call_int_hook_default(-ENOPROTOOPT, socket_getpeersec_dgram,
+ sock, skb, secid);
}
EXPORT_SYMBOL(security_socket_getpeersec_dgram);

-static struct list_head hooks_sk_alloc_security;
int security_sk_alloc(struct sock *sk, int family, gfp_t priority)
{
return call_int_hook(sk_alloc_security, sk, family, priority);
}

-static struct list_head hooks_sk_free_security;
void security_sk_free(struct sock *sk)
{
call_void_hook(sk_free_security, sk);
}

-static struct list_head hooks_sk_clone_security;
void security_sk_clone(const struct sock *sk, struct sock *newsk)
{
call_void_hook(sk_clone_security, sk, newsk);
}
EXPORT_SYMBOL(security_sk_clone);

-static struct list_head hooks_sk_getsecid;
void security_sk_classify_flow(struct sock *sk, struct flowi *fl)
{
call_void_hook(sk_getsecid, sk, &fl->flowi_secid);
}
EXPORT_SYMBOL(security_sk_classify_flow);

-static struct list_head hooks_req_classify_flow;
void security_req_classify_flow(const struct request_sock *req, struct flowi *fl)
{
call_void_hook(req_classify_flow, req, fl);
}
EXPORT_SYMBOL(security_req_classify_flow);

-static struct list_head hooks_sock_graft;
void security_sock_graft(struct sock *sk, struct socket *parent)
{
call_void_hook(sock_graft, sk, parent);
}
EXPORT_SYMBOL(security_sock_graft);

-static struct list_head hooks_inet_conn_request;
int security_inet_conn_request(struct sock *sk,
struct sk_buff *skb, struct request_sock *req)
{
@@ -1580,84 +1572,72 @@ int security_inet_conn_request(struct sock *sk,
}
EXPORT_SYMBOL(security_inet_conn_request);

-static struct list_head hooks_inet_csk_clone;
void security_inet_csk_clone(struct sock *newsk,
const struct request_sock *req)
{
call_void_hook(inet_csk_clone, newsk, req);
}

-static struct list_head hooks_inet_conn_established;
void security_inet_conn_established(struct sock *sk,
struct sk_buff *skb)
{
call_void_hook(inet_conn_established, sk, skb);
}

-static struct list_head hooks_secmark_relabel_packet;
int security_secmark_relabel_packet(u32 secid)
{
return call_int_hook(secmark_relabel_packet, secid);
}
EXPORT_SYMBOL(security_secmark_relabel_packet);

-static struct list_head hooks_secmark_refcount_inc;
void security_secmark_refcount_inc(void)
{
call_void_hook(secmark_refcount_inc);
}
EXPORT_SYMBOL(security_secmark_refcount_inc);

-static struct list_head hooks_secmark_refcount_dec;
void security_secmark_refcount_dec(void)
{
call_void_hook(secmark_refcount_dec);
}
EXPORT_SYMBOL(security_secmark_refcount_dec);

-static struct list_head hooks_tun_dev_alloc_security;
int security_tun_dev_alloc_security(void **security)
{
return call_int_hook(tun_dev_alloc_security, security);
}
EXPORT_SYMBOL(security_tun_dev_alloc_security);

-static struct list_head hooks_tun_dev_free_security;
void security_tun_dev_free_security(void *security)
{
call_void_hook(tun_dev_free_security, security);
}
EXPORT_SYMBOL(security_tun_dev_free_security);

-static struct list_head hooks_tun_dev_create;
int security_tun_dev_create(void)
{
return call_int_hook(tun_dev_create);
}
EXPORT_SYMBOL(security_tun_dev_create);

-static struct list_head hooks_tun_dev_attach_queue;
int security_tun_dev_attach_queue(void *security)
{
return call_int_hook(tun_dev_attach_queue, security);
}
EXPORT_SYMBOL(security_tun_dev_attach_queue);

-static struct list_head hooks_tun_dev_attach;
int security_tun_dev_attach(struct sock *sk, void *security)
{
return call_int_hook(tun_dev_attach, sk, security);
}
EXPORT_SYMBOL(security_tun_dev_attach);

-static struct list_head hooks_tun_dev_open;
int security_tun_dev_open(void *security)
{
return call_int_hook(tun_dev_open, security);
}
EXPORT_SYMBOL(security_tun_dev_open);

-static struct list_head hooks_skb_owned_by;
void security_skb_owned_by(struct sk_buff *skb, struct sock *sk)
{
call_void_hook(skb_owned_by, skb, sk);
@@ -1667,7 +1647,6 @@ void security_skb_owned_by(struct sk_buff *skb, struct sock *sk)

#ifdef CONFIG_SECURITY_NETWORK_XFRM

-static struct list_head hooks_xfrm_policy_alloc_security;
int security_xfrm_policy_alloc(struct xfrm_sec_ctx **ctxp,
struct xfrm_user_sec_ctx *sec_ctx,
gfp_t gfp)
@@ -1676,27 +1655,23 @@ int security_xfrm_policy_alloc(struct xfrm_sec_ctx **ctxp,
}
EXPORT_SYMBOL(security_xfrm_policy_alloc);

-static struct list_head hooks_xfrm_policy_clone_security;
int security_xfrm_policy_clone(struct xfrm_sec_ctx *old_ctx,
struct xfrm_sec_ctx **new_ctxp)
{
return call_int_hook(xfrm_policy_clone_security, old_ctx, new_ctxp);
}

-static struct list_head hooks_xfrm_policy_free_security;
void security_xfrm_policy_free(struct xfrm_sec_ctx *ctx)
{
call_void_hook(xfrm_policy_free_security, ctx);
}
EXPORT_SYMBOL(security_xfrm_policy_free);

-static struct list_head hooks_xfrm_policy_delete_security;
int security_xfrm_policy_delete(struct xfrm_sec_ctx *ctx)
{
return call_int_hook(xfrm_policy_delete_security, ctx);
}

-static struct list_head hooks_xfrm_state_alloc;
int security_xfrm_state_alloc(struct xfrm_state *x,
struct xfrm_user_sec_ctx *sec_ctx)
{
@@ -1704,43 +1679,35 @@ int security_xfrm_state_alloc(struct xfrm_state *x,
}
EXPORT_SYMBOL(security_xfrm_state_alloc);

-static struct list_head hooks_xfrm_state_alloc_acquire;
int security_xfrm_state_alloc_acquire(struct xfrm_state *x,
struct xfrm_sec_ctx *polsec, u32 secid)
{
return call_int_hook(xfrm_state_alloc_acquire, x, polsec, secid);
}

-static struct list_head hooks_xfrm_state_delete_security;
int security_xfrm_state_delete(struct xfrm_state *x)
{
return call_int_hook(xfrm_state_delete_security, x);
}
EXPORT_SYMBOL(security_xfrm_state_delete);

-static struct list_head hooks_xfrm_state_free_security;
void security_xfrm_state_free(struct xfrm_state *x)
{
call_void_hook(xfrm_state_free_security, x);
}

-static struct list_head hooks_xfrm_policy_lookup;
int security_xfrm_policy_lookup(struct xfrm_sec_ctx *ctx, u32 fl_secid, u8 dir)
{
return call_int_hook(xfrm_policy_lookup, ctx, fl_secid, dir);
}

-static struct list_head hooks_xfrm_state_pol_flow_match;
int security_xfrm_state_pol_flow_match(struct xfrm_state *x,
struct xfrm_policy *xp,
const struct flowi *fl)
{
- if (list_empty(&hooks_xfrm_state_pol_flow_match))
- return 1;
- return call_int_hook(xfrm_state_pol_flow_match, x, xp, fl);
+ return call_int_hook_default(1, xfrm_state_pol_flow_match, x, xp, fl);
}

-static struct list_head hooks_xfrm_decode_session;
int security_xfrm_decode_session(struct sk_buff *skb, u32 *secid)
{
return call_int_hook(xfrm_decode_session, skb, secid, 1);
@@ -1763,33 +1730,26 @@ EXPORT_SYMBOL(security_skb_classify_flow);

#ifdef CONFIG_KEYS

-static struct list_head hooks_key_alloc;
int security_key_alloc(struct key *key, const struct cred *cred,
unsigned long flags)
{
return call_int_hook(key_alloc, key, cred, flags);
}

-static struct list_head hooks_key_free;
void security_key_free(struct key *key)
{
call_void_hook(key_free, key);
}

-static struct list_head hooks_key_permission;
int security_key_permission(key_ref_t key_ref,
const struct cred *cred, unsigned perm)
{
return call_int_hook(key_permission, key_ref, cred, perm);
}

-static struct list_head hooks_key_getsecurity;
int security_key_getsecurity(struct key *key, char **_buffer)
{
- if (list_empty(&hooks_key_getsecurity)) {
- *_buffer = NULL;
- return 0;
- }
+ *_buffer = NULL;
return call_int_hook(key_getsecurity, key, _buffer);
}

@@ -1797,25 +1757,21 @@ int security_key_getsecurity(struct key *key, char **_buffer)

#ifdef CONFIG_AUDIT

-static struct list_head hooks_audit_rule_init;
int security_audit_rule_init(u32 field, u32 op, char *rulestr, void **lsmrule)
{
return call_int_hook(audit_rule_init, field, op, rulestr, lsmrule);
}

-static struct list_head hooks_audit_rule_known;
int security_audit_rule_known(struct audit_krule *krule)
{
return call_int_hook(audit_rule_known, krule);
}

-static struct list_head hooks_audit_rule_free;
void security_audit_rule_free(void *lsmrule)
{
call_void_hook(audit_rule_free, lsmrule);
}

-static struct list_head hooks_audit_rule_match;
int security_audit_rule_match(u32 secid, u32 field, u32 op, void *lsmrule,
struct audit_context *actx)
{
@@ -1824,736 +1780,58 @@ int security_audit_rule_match(u32 secid, u32 field, u32 op, void *lsmrule,

#endif /* CONFIG_AUDIT */

-static int __init add_hook_to_list(struct list_head *hooklist,
- void *interesting,
- struct security_operations *sop)
-{
- struct security_hook_list *new;
- struct security_hook_list *shp;
-
- if (hooklist->next == NULL)
- INIT_LIST_HEAD(hooklist);
-
- if (interesting == NULL)
- return 0;
-
- new = kzalloc(sizeof(*new), GFP_KERNEL);
- if (new == NULL)
- return -ENOMEM;
-
- INIT_LIST_HEAD(&new->shl_head);
- new->shl_ops = sop;
-
- shp = list_last_entry(hooklist, struct security_hook_list, shl_head);
- list_add_rcu(&new->shl_head, &shp->shl_head);
-
- return 0;
-}
-
static int __init security_enlist_ops(struct security_operations *sop)
{
- printk(KERN_INFO "Security operations for %s initialized\n", sop->name);
-
- if (add_hook_to_list(&hooks_ptrace_access_check,
- sop->ptrace_access_check, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_ptrace_traceme, sop->ptrace_traceme, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_capget, sop->capget, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_capset, sop->capset, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_capable, sop->capable, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_quotactl, sop->quotactl, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_quota_on, sop->quota_on, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_syslog, sop->syslog, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_settime, sop->settime, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_vm_enough_memory,
- sop->vm_enough_memory, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_bprm_set_creds, sop->bprm_set_creds, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_bprm_committing_creds,
- sop->bprm_committing_creds, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_bprm_committed_creds,
- sop->bprm_committed_creds, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_bprm_check_security,
- sop->bprm_check_security, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_bprm_secureexec, sop->bprm_secureexec, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_sb_alloc_security,
- sop->sb_alloc_security, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_sb_free_security,
- sop->sb_free_security, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_sb_copy_data, sop->sb_copy_data, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_sb_remount, sop->sb_remount, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_sb_kern_mount, sop->sb_kern_mount, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_sb_show_options, sop->sb_show_options, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_sb_statfs, sop->sb_statfs, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_sb_mount, sop->sb_mount, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_sb_umount, sop->sb_umount, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_sb_pivotroot, sop->sb_pivotroot, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_sb_set_mnt_opts, sop->sb_set_mnt_opts, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_sb_clone_mnt_opts,
- sop->sb_clone_mnt_opts, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_sb_parse_opts_str,
- sop->sb_parse_opts_str, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_dentry_init_security,
- sop->dentry_init_security, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_inode_alloc_security,
- sop->inode_alloc_security, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_inode_free_security,
- sop->inode_free_security, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_inode_init_security,
- sop->inode_init_security, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_inode_create, sop->inode_create, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_inode_link, sop->inode_link, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_inode_unlink, sop->inode_unlink, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_inode_symlink, sop->inode_symlink, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_inode_mkdir, sop->inode_mkdir, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_inode_rmdir, sop->inode_rmdir, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_inode_mknod, sop->inode_mknod, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_inode_rename, sop->inode_rename, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_inode_readlink, sop->inode_readlink, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_inode_follow_link,
- sop->inode_follow_link, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_inode_permission,
- sop->inode_permission, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_inode_setattr, sop->inode_setattr, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_inode_getattr, sop->inode_getattr, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_inode_setxattr, sop->inode_setxattr, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_inode_post_setxattr,
- sop->inode_post_setxattr, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_inode_getxattr, sop->inode_getxattr, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_inode_listxattr, sop->inode_listxattr, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_inode_removexattr,
- sop->inode_removexattr, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_inode_need_killpriv,
- sop->inode_need_killpriv, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_inode_killpriv, sop->inode_killpriv, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_inode_getsecurity,
- sop->inode_getsecurity, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_inode_setsecurity,
- sop->inode_setsecurity, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_inode_listsecurity,
- sop->inode_listsecurity, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_inode_getsecid,
- sop->inode_getsecid, sop))
- return -ENOMEM;
-#ifdef CONFIG_SECURITY_PATH
- if (add_hook_to_list(&hooks_path_mknod, sop->path_mknod, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_path_mkdir, sop->path_mkdir, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_path_rmdir, sop->path_rmdir, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_path_unlink, sop->path_unlink, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_path_symlink, sop->path_symlink, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_path_link, sop->path_link, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_path_rename, sop->path_rename, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_path_truncate, sop->path_truncate, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_path_chmod, sop->path_chmod, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_path_chown, sop->path_chown, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_path_chroot, sop->path_chroot, sop))
- return -ENOMEM;
-#endif
- if (add_hook_to_list(&hooks_file_permission, sop->file_permission, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_file_alloc_security,
- sop->file_alloc_security, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_file_free_security,
- sop->file_free_security, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_file_ioctl, sop->file_ioctl, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_mmap_addr, sop->mmap_addr, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_mmap_file, sop->mmap_file, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_file_mprotect, sop->file_mprotect, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_file_lock, sop->file_lock, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_file_fcntl, sop->file_fcntl, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_file_set_fowner, sop->file_set_fowner, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_file_send_sigiotask,
- sop->file_send_sigiotask, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_file_receive, sop->file_receive, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_file_open, sop->file_open, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_task_create, sop->task_create, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_task_free, sop->task_free, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_cred_alloc_blank,
- sop->cred_alloc_blank, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_cred_free, sop->cred_free, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_cred_prepare, sop->cred_prepare, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_cred_transfer, sop->cred_transfer, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_kernel_act_as, sop->kernel_act_as, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_kernel_create_files_as,
- sop->kernel_create_files_as, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_kernel_module_request,
- sop->kernel_module_request, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_kernel_module_from_file,
- sop->kernel_module_from_file, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_task_fix_setuid, sop->task_fix_setuid, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_task_setpgid, sop->task_setpgid, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_task_getpgid, sop->task_getpgid, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_task_getsid, sop->task_getsid, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_task_getsecid, sop->task_getsecid, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_task_setnice, sop->task_setnice, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_task_setioprio, sop->task_setioprio, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_task_getioprio, sop->task_getioprio, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_task_setrlimit, sop->task_setrlimit, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_task_setscheduler,
- sop->task_setscheduler, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_task_getscheduler,
- sop->task_getscheduler, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_task_movememory, sop->task_movememory, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_task_wait, sop->task_wait, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_task_kill, sop->task_kill, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_task_prctl, sop->task_prctl, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_task_to_inode, sop->task_to_inode, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_ipc_permission, sop->ipc_permission, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_ipc_getsecid, sop->ipc_getsecid, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_msg_msg_alloc_security,
- sop->msg_msg_alloc_security, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_msg_msg_free_security,
- sop->msg_msg_free_security, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_msg_queue_alloc_security,
- sop->msg_queue_alloc_security, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_msg_queue_free_security,
- sop->msg_queue_free_security, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_msg_queue_associate,
- sop->msg_queue_associate, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_msg_queue_msgctl,
- sop->msg_queue_msgctl, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_msg_queue_msgsnd,
- sop->msg_queue_msgsnd, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_msg_queue_msgrcv,
- sop->msg_queue_msgrcv, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_shm_alloc_security,
- sop->shm_alloc_security, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_shm_free_security,
- sop->shm_free_security, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_shm_associate, sop->shm_associate, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_shm_shmctl, sop->shm_shmctl, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_shm_shmat, sop->shm_shmat, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_sem_alloc_security,
- sop->sem_alloc_security, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_sem_free_security,
- sop->sem_free_security, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_sem_associate, sop->sem_associate, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_sem_semctl, sop->sem_semctl, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_sem_semop, sop->sem_semop, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_netlink_send, sop->netlink_send, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_d_instantiate, sop->d_instantiate, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_getprocattr, sop->getprocattr, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_setprocattr, sop->setprocattr, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_ismaclabel, sop->ismaclabel, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_secid_to_secctx, sop->secid_to_secctx, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_secctx_to_secid, sop->secctx_to_secid, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_release_secctx, sop->release_secctx, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_inode_notifysecctx,
- sop->inode_notifysecctx, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_inode_setsecctx, sop->inode_setsecctx, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_inode_getsecctx, sop->inode_getsecctx, sop))
- return -ENOMEM;
-#ifdef CONFIG_SECURITY_NETWORK
- if (add_hook_to_list(&hooks_unix_stream_connect,
- sop->unix_stream_connect, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_unix_may_send, sop->unix_may_send, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_socket_create, sop->socket_create, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_socket_post_create,
- sop->socket_post_create, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_socket_bind, sop->socket_bind, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_socket_connect, sop->socket_connect, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_socket_listen, sop->socket_listen, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_socket_accept, sop->socket_accept, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_socket_sendmsg, sop->socket_sendmsg, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_socket_recvmsg, sop->socket_recvmsg, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_socket_getsockname,
- sop->socket_getsockname, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_socket_getpeername,
- sop->socket_getpeername, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_socket_setsockopt,
- sop->socket_setsockopt, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_socket_getsockopt,
- sop->socket_getsockopt, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_socket_shutdown, sop->socket_shutdown, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_socket_sock_rcv_skb,
- sop->socket_sock_rcv_skb, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_socket_getpeersec_stream,
- sop->socket_getpeersec_stream, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_socket_getpeersec_dgram,
- sop->socket_getpeersec_dgram, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_sk_alloc_security,
- sop->sk_alloc_security, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_sk_free_security,
- sop->sk_free_security, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_sk_clone_security,
- sop->sk_clone_security, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_sk_getsecid, sop->sk_getsecid, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_sock_graft, sop->sock_graft, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_inet_conn_request,
- sop->inet_conn_request, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_inet_csk_clone, sop->inet_csk_clone, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_inet_conn_established,
- sop->inet_conn_established, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_secmark_relabel_packet,
- sop->secmark_relabel_packet, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_secmark_refcount_inc,
- sop->secmark_refcount_inc, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_secmark_refcount_dec,
- sop->secmark_refcount_dec, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_req_classify_flow,
- sop->req_classify_flow, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_tun_dev_alloc_security,
- sop->tun_dev_alloc_security, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_tun_dev_free_security,
- sop->tun_dev_free_security, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_tun_dev_create, sop->tun_dev_create, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_tun_dev_open, sop->tun_dev_open, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_tun_dev_attach_queue,
- sop->tun_dev_attach_queue, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_tun_dev_attach, sop->tun_dev_attach, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_skb_owned_by, sop->skb_owned_by, sop))
- return -ENOMEM;
-#endif /* CONFIG_SECURITY_NETWORK */
-#ifdef CONFIG_SECURITY_NETWORK_XFRM
- if (add_hook_to_list(&hooks_xfrm_policy_alloc_security,
- sop->xfrm_policy_alloc_security, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_xfrm_policy_clone_security,
- sop->xfrm_policy_clone_security, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_xfrm_policy_free_security,
- sop->xfrm_policy_free_security, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_xfrm_policy_delete_security,
- sop->xfrm_policy_delete_security, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_xfrm_state_alloc,
- sop->xfrm_state_alloc, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_xfrm_state_alloc_acquire,
- sop->xfrm_state_alloc_acquire, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_xfrm_state_free_security,
- sop->xfrm_state_free_security, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_xfrm_state_delete_security,
- sop->xfrm_state_delete_security, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_xfrm_policy_lookup,
- sop->xfrm_policy_lookup, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_xfrm_state_pol_flow_match,
- sop->xfrm_state_pol_flow_match, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_xfrm_decode_session,
- sop->xfrm_decode_session, sop))
- return -ENOMEM;
-#endif /* CONFIG_SECURITY_NETWORK_XFRM */
-#ifdef CONFIG_KEYS
- if (add_hook_to_list(&hooks_key_alloc, sop->key_alloc, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_key_free, sop->key_free, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_key_permission, sop->key_permission, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_key_getsecurity, sop->key_getsecurity, sop))
- return -ENOMEM;
-#endif /* CONFIG_KEYS */
-#ifdef CONFIG_AUDIT
- if (add_hook_to_list(&hooks_audit_rule_init, sop->audit_rule_init, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_audit_rule_known, sop->audit_rule_known,
- sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_audit_rule_match, sop->audit_rule_match,
- sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_audit_rule_free, sop->audit_rule_free, sop))
+ enum lsm_hooks_index i;
+ int count = 0;
+ struct security_hook_list **new;
+ /*
+ * Optimization by assuming that "enum lsm_hooks_index" indicates
+ * ordering of callback pointers in "struct security_operations" and
+ * ptrace_access_check is the first callback.
+ *
+ * If you change "struct security_operations", you must also change
+ * "enum lsm_hooks_index" accordingly.
+ */
+ void **hooks = (void **) &sop->ptrace_access_check;
+
+ /* How many callbacks are defined? */
+ for (i = 0; i < max_lsm_hooks; i++)
+ if (hooks[i])
+ count++;
+ /* Allocate memory for registering callbacks. */
+ new = kzalloc(sizeof(struct security_hook_list) * count, GFP_KERNEL);
+ if (!new) {
+ printk(KERN_INFO "Failed to initialize security operations for %s\n",
+ sop->name);
return -ENOMEM;
-#endif
+ }
+ /* Assign only defined callbacks. */
+ count = 0;
+ for (i = 0; i < max_lsm_hooks; i++) {
+ if (!hooks[i])
+ continue;
+ new[count]->shl_ops = sop;
+ list_add_tail_rcu(&new[count]->shl_head, &lsm_hooks[i]);
+ count++;
+ }
+ printk(KERN_INFO "Security operations for %s initialized\n", sop->name);
return 0;
}

#ifdef CONFIG_SECURITY_SELINUX_DISABLE
-static void clear_hook_entry(struct list_head *head,
- struct security_operations *sop)
+void security_module_disable(struct security_operations *sop)
{
+ enum lsm_hooks_index i;
struct security_hook_list *shp;

- if (head->next == NULL)
- return;
- if (list_empty(head))
- return;
-
- list_for_each_entry(shp, head, shl_head)
- if (shp->shl_ops == sop) {
- shp->shl_ops = NULL;
- return;
- }
-}
-
-void security_module_disable(struct security_operations *sop)
-{
+ /* Unassign defined callbacks. */
+ for (i = 0; i < max_lsm_hooks; i++)
+ list_for_each_entry(shp, &lsm_hooks[i], shl_head)
+ if (shp->shl_ops == sop) {
+ list_del_rcu(&shp->shl_head);
+ break;
+ }
printk(KERN_INFO "Security operations for %s disabled.\n", sop->name);
- clear_hook_entry(&hooks_ptrace_access_check, sop);
- clear_hook_entry(&hooks_ptrace_traceme, sop);
- clear_hook_entry(&hooks_capget, sop);
- clear_hook_entry(&hooks_capset, sop);
- clear_hook_entry(&hooks_capable, sop);
- clear_hook_entry(&hooks_quotactl, sop);
- clear_hook_entry(&hooks_quota_on, sop);
- clear_hook_entry(&hooks_syslog, sop);
- clear_hook_entry(&hooks_settime, sop);
- clear_hook_entry(&hooks_vm_enough_memory, sop);
- clear_hook_entry(&hooks_bprm_set_creds, sop);
- clear_hook_entry(&hooks_bprm_committing_creds, sop);
- clear_hook_entry(&hooks_bprm_committed_creds, sop);
- clear_hook_entry(&hooks_bprm_check_security, sop);
- clear_hook_entry(&hooks_bprm_secureexec, sop);
- clear_hook_entry(&hooks_sb_alloc_security, sop);
- clear_hook_entry(&hooks_sb_free_security, sop);
- clear_hook_entry(&hooks_sb_copy_data, sop);
- clear_hook_entry(&hooks_sb_remount, sop);
- clear_hook_entry(&hooks_sb_kern_mount, sop);
- clear_hook_entry(&hooks_sb_show_options, sop);
- clear_hook_entry(&hooks_sb_statfs, sop);
- clear_hook_entry(&hooks_sb_mount, sop);
- clear_hook_entry(&hooks_sb_umount, sop);
- clear_hook_entry(&hooks_sb_pivotroot, sop);
- clear_hook_entry(&hooks_sb_set_mnt_opts, sop);
- clear_hook_entry(&hooks_sb_clone_mnt_opts, sop);
- clear_hook_entry(&hooks_sb_parse_opts_str, sop);
- clear_hook_entry(&hooks_dentry_init_security, sop);
- clear_hook_entry(&hooks_inode_alloc_security, sop);
- clear_hook_entry(&hooks_inode_free_security, sop);
- clear_hook_entry(&hooks_inode_init_security, sop);
- clear_hook_entry(&hooks_inode_create, sop);
- clear_hook_entry(&hooks_inode_link, sop);
- clear_hook_entry(&hooks_inode_unlink, sop);
- clear_hook_entry(&hooks_inode_symlink, sop);
- clear_hook_entry(&hooks_inode_mkdir, sop);
- clear_hook_entry(&hooks_inode_rmdir, sop);
- clear_hook_entry(&hooks_inode_mknod, sop);
- clear_hook_entry(&hooks_inode_rename, sop);
- clear_hook_entry(&hooks_inode_readlink, sop);
- clear_hook_entry(&hooks_inode_follow_link, sop);
- clear_hook_entry(&hooks_inode_permission, sop);
- clear_hook_entry(&hooks_inode_setattr, sop);
- clear_hook_entry(&hooks_inode_getattr, sop);
- clear_hook_entry(&hooks_inode_setxattr, sop);
- clear_hook_entry(&hooks_inode_post_setxattr, sop);
- clear_hook_entry(&hooks_inode_getxattr, sop);
- clear_hook_entry(&hooks_inode_listxattr, sop);
- clear_hook_entry(&hooks_inode_removexattr, sop);
- clear_hook_entry(&hooks_inode_need_killpriv, sop);
- clear_hook_entry(&hooks_inode_killpriv, sop);
- clear_hook_entry(&hooks_inode_getsecurity, sop);
- clear_hook_entry(&hooks_inode_setsecurity, sop);
- clear_hook_entry(&hooks_inode_listsecurity, sop);
- clear_hook_entry(&hooks_inode_getsecid, sop);
-#ifdef CONFIG_SECURITY_PATH
- clear_hook_entry(&hooks_path_mknod, sop);
- clear_hook_entry(&hooks_path_mkdir, sop);
- clear_hook_entry(&hooks_path_rmdir, sop);
- clear_hook_entry(&hooks_path_unlink, sop);
- clear_hook_entry(&hooks_path_symlink, sop);
- clear_hook_entry(&hooks_path_link, sop);
- clear_hook_entry(&hooks_path_rename, sop);
- clear_hook_entry(&hooks_path_truncate, sop);
- clear_hook_entry(&hooks_path_chmod, sop);
- clear_hook_entry(&hooks_path_chown, sop);
- clear_hook_entry(&hooks_path_chroot, sop);
-#endif
- clear_hook_entry(&hooks_file_permission, sop);
- clear_hook_entry(&hooks_file_alloc_security, sop);
- clear_hook_entry(&hooks_file_free_security, sop);
- clear_hook_entry(&hooks_file_ioctl, sop);
- clear_hook_entry(&hooks_mmap_addr, sop);
- clear_hook_entry(&hooks_mmap_file, sop);
- clear_hook_entry(&hooks_file_mprotect, sop);
- clear_hook_entry(&hooks_file_lock, sop);
- clear_hook_entry(&hooks_file_fcntl, sop);
- clear_hook_entry(&hooks_file_set_fowner, sop);
- clear_hook_entry(&hooks_file_send_sigiotask, sop);
- clear_hook_entry(&hooks_file_receive, sop);
- clear_hook_entry(&hooks_file_open, sop);
- clear_hook_entry(&hooks_task_create, sop);
- clear_hook_entry(&hooks_task_free, sop);
- clear_hook_entry(&hooks_cred_alloc_blank, sop);
- clear_hook_entry(&hooks_cred_free, sop);
- clear_hook_entry(&hooks_cred_prepare, sop);
- clear_hook_entry(&hooks_cred_transfer, sop);
- clear_hook_entry(&hooks_kernel_act_as, sop);
- clear_hook_entry(&hooks_kernel_create_files_as, sop);
- clear_hook_entry(&hooks_kernel_module_request, sop);
- clear_hook_entry(&hooks_kernel_module_from_file, sop);
- clear_hook_entry(&hooks_task_fix_setuid, sop);
- clear_hook_entry(&hooks_task_setpgid, sop);
- clear_hook_entry(&hooks_task_getpgid, sop);
- clear_hook_entry(&hooks_task_getsid, sop);
- clear_hook_entry(&hooks_task_getsecid, sop);
- clear_hook_entry(&hooks_task_setnice, sop);
- clear_hook_entry(&hooks_task_setioprio, sop);
- clear_hook_entry(&hooks_task_getioprio, sop);
- clear_hook_entry(&hooks_task_setrlimit, sop);
- clear_hook_entry(&hooks_task_setscheduler, sop);
- clear_hook_entry(&hooks_task_getscheduler, sop);
- clear_hook_entry(&hooks_task_movememory, sop);
- clear_hook_entry(&hooks_task_wait, sop);
- clear_hook_entry(&hooks_task_kill, sop);
- clear_hook_entry(&hooks_task_prctl, sop);
- clear_hook_entry(&hooks_task_to_inode, sop);
- clear_hook_entry(&hooks_ipc_permission, sop);
- clear_hook_entry(&hooks_ipc_getsecid, sop);
- clear_hook_entry(&hooks_msg_msg_alloc_security, sop);
- clear_hook_entry(&hooks_msg_msg_free_security, sop);
- clear_hook_entry(&hooks_msg_queue_alloc_security, sop);
- clear_hook_entry(&hooks_msg_queue_free_security, sop);
- clear_hook_entry(&hooks_msg_queue_associate, sop);
- clear_hook_entry(&hooks_msg_queue_msgctl, sop);
- clear_hook_entry(&hooks_msg_queue_msgsnd, sop);
- clear_hook_entry(&hooks_msg_queue_msgrcv, sop);
- clear_hook_entry(&hooks_shm_alloc_security, sop);
- clear_hook_entry(&hooks_shm_free_security, sop);
- clear_hook_entry(&hooks_shm_associate, sop);
- clear_hook_entry(&hooks_shm_shmctl, sop);
- clear_hook_entry(&hooks_shm_shmat, sop);
- clear_hook_entry(&hooks_sem_alloc_security, sop);
- clear_hook_entry(&hooks_sem_free_security, sop);
- clear_hook_entry(&hooks_sem_associate, sop);
- clear_hook_entry(&hooks_sem_semctl, sop);
- clear_hook_entry(&hooks_sem_semop, sop);
- clear_hook_entry(&hooks_netlink_send, sop);
- clear_hook_entry(&hooks_d_instantiate, sop);
- clear_hook_entry(&hooks_getprocattr, sop);
- clear_hook_entry(&hooks_setprocattr, sop);
- clear_hook_entry(&hooks_ismaclabel, sop);
- clear_hook_entry(&hooks_secid_to_secctx, sop);
- clear_hook_entry(&hooks_secctx_to_secid, sop);
- clear_hook_entry(&hooks_release_secctx, sop);
- clear_hook_entry(&hooks_inode_notifysecctx, sop);
- clear_hook_entry(&hooks_inode_setsecctx, sop);
- clear_hook_entry(&hooks_inode_getsecctx, sop);
-#ifdef CONFIG_SECURITY_NETWORK
- clear_hook_entry(&hooks_unix_stream_connect, sop);
- clear_hook_entry(&hooks_unix_may_send, sop);
- clear_hook_entry(&hooks_socket_create, sop);
- clear_hook_entry(&hooks_socket_post_create, sop);
- clear_hook_entry(&hooks_socket_bind, sop);
- clear_hook_entry(&hooks_socket_connect, sop);
- clear_hook_entry(&hooks_socket_listen, sop);
- clear_hook_entry(&hooks_socket_accept, sop);
- clear_hook_entry(&hooks_socket_sendmsg, sop);
- clear_hook_entry(&hooks_socket_recvmsg, sop);
- clear_hook_entry(&hooks_socket_getsockname, sop);
- clear_hook_entry(&hooks_socket_getpeername, sop);
- clear_hook_entry(&hooks_socket_setsockopt, sop);
- clear_hook_entry(&hooks_socket_getsockopt, sop);
- clear_hook_entry(&hooks_socket_shutdown, sop);
- clear_hook_entry(&hooks_socket_sock_rcv_skb, sop);
- clear_hook_entry(&hooks_socket_getpeersec_stream, sop);
- clear_hook_entry(&hooks_socket_getpeersec_dgram, sop);
- clear_hook_entry(&hooks_sk_alloc_security, sop);
- clear_hook_entry(&hooks_sk_free_security, sop);
- clear_hook_entry(&hooks_sk_clone_security, sop);
- clear_hook_entry(&hooks_sk_getsecid, sop);
- clear_hook_entry(&hooks_sock_graft, sop);
- clear_hook_entry(&hooks_inet_conn_request, sop);
- clear_hook_entry(&hooks_inet_csk_clone, sop);
- clear_hook_entry(&hooks_inet_conn_established, sop);
- clear_hook_entry(&hooks_secmark_relabel_packet, sop);
- clear_hook_entry(&hooks_secmark_refcount_inc, sop);
- clear_hook_entry(&hooks_secmark_refcount_dec, sop);
- clear_hook_entry(&hooks_req_classify_flow, sop);
- clear_hook_entry(&hooks_tun_dev_alloc_security, sop);
- clear_hook_entry(&hooks_tun_dev_free_security, sop);
- clear_hook_entry(&hooks_tun_dev_create, sop);
- clear_hook_entry(&hooks_tun_dev_open, sop);
- clear_hook_entry(&hooks_tun_dev_attach_queue, sop);
- clear_hook_entry(&hooks_tun_dev_attach, sop);
- clear_hook_entry(&hooks_skb_owned_by, sop);
-#endif /* CONFIG_SECURITY_NETWORK */
-#ifdef CONFIG_SECURITY_NETWORK_XFRM
- clear_hook_entry(&hooks_xfrm_policy_alloc_security, sop);
- clear_hook_entry(&hooks_xfrm_policy_clone_security, sop);
- clear_hook_entry(&hooks_xfrm_policy_free_security, sop);
- clear_hook_entry(&hooks_xfrm_policy_delete_security, sop);
- clear_hook_entry(&hooks_xfrm_state_alloc, sop);
- clear_hook_entry(&hooks_xfrm_state_alloc_acquire, sop);
- clear_hook_entry(&hooks_xfrm_state_free_security, sop);
- clear_hook_entry(&hooks_xfrm_state_delete_security, sop);
- clear_hook_entry(&hooks_xfrm_policy_lookup, sop);
- clear_hook_entry(&hooks_xfrm_state_pol_flow_match, sop);
- clear_hook_entry(&hooks_xfrm_decode_session, sop);
-#endif /* CONFIG_SECURITY_NETWORK_XFRM */
-#ifdef CONFIG_KEYS
- clear_hook_entry(&hooks_key_alloc, sop);
- clear_hook_entry(&hooks_key_free, sop);
- clear_hook_entry(&hooks_key_permission, sop);
- clear_hook_entry(&hooks_key_getsecurity, sop);
-#endif /* CONFIG_KEYS */
-#ifdef CONFIG_AUDIT
- clear_hook_entry(&hooks_audit_rule_init, sop);
- clear_hook_entry(&hooks_audit_rule_known, sop);
- clear_hook_entry(&hooks_audit_rule_match, sop);
- clear_hook_entry(&hooks_audit_rule_free, sop);
-#endif
}
#endif /* CONFIG_SECURITY_SELINUX_DISABLE */
--
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
the body of a message to ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Casey Schaufler
2014-09-07 15:49:51 UTC
Permalink
I'm on holiday and won't be able to reply until after September 15th. I
don't like the array of lists. I prefer the variable per hook because
when we actually get around to stacking some hooks may need a no list,
or a different kind of list.
Post by Tetsuo Handa
Post by Tetsuo Handa
Comments from thread-safety point of view for runtime-unregistration.
Here is an only compile tested patch which reflected some of my comments.
security/security.c | 1324 +++++++++++++------------------------------------------------
1 file changed, 301 insertions(+), 1023 deletions(-)
diff --git a/security/security.c b/security/security.c
index 678b905..86d49a5 100644
--- a/security/security.c
+++ b/security/security.c
@@ -28,6 +28,214 @@
#include <linux/list.h>
#include <net/flow.h>
+enum lsm_hooks_index {
+ lsm_ptrace_access_check,
+ lsm_ptrace_traceme,
+ lsm_capget,
+ lsm_capset,
+ lsm_capable,
+ lsm_quotactl,
+ lsm_quota_on,
+ lsm_syslog,
+ lsm_settime,
+ lsm_vm_enough_memory,
+ lsm_bprm_set_creds,
+ lsm_bprm_check_security,
+ lsm_bprm_secureexec,
+ lsm_bprm_committing_creds,
+ lsm_bprm_committed_creds,
+ lsm_sb_alloc_security,
+ lsm_sb_free_security,
+ lsm_sb_copy_data,
+ lsm_sb_remount,
+ lsm_sb_kern_mount,
+ lsm_sb_show_options,
+ lsm_sb_statfs,
+ lsm_sb_mount,
+ lsm_sb_umount,
+ lsm_sb_pivotroot,
+ lsm_sb_set_mnt_opts,
+ lsm_sb_clone_mnt_opts,
+ lsm_sb_parse_opts_str,
+ lsm_dentry_init_security,
+#ifdef CONFIG_SECURITY_PATH
+ lsm_path_unlink,
+ lsm_path_mkdir,
+ lsm_path_rmdir,
+ lsm_path_mknod,
+ lsm_path_truncate,
+ lsm_path_symlink,
+ lsm_path_link,
+ lsm_path_rename,
+ lsm_path_chmod,
+ lsm_path_chown,
+ lsm_path_chroot,
+#endif
+ lsm_inode_alloc_security,
+ lsm_inode_free_security,
+ lsm_inode_init_security,
+ lsm_inode_create,
+ lsm_inode_link,
+ lsm_inode_unlink,
+ lsm_inode_symlink,
+ lsm_inode_mkdir,
+ lsm_inode_rmdir,
+ lsm_inode_mknod,
+ lsm_inode_rename,
+ lsm_inode_readlink,
+ lsm_inode_follow_link,
+ lsm_inode_permission,
+ lsm_inode_setattr,
+ lsm_inode_getattr,
+ lsm_inode_setxattr,
+ lsm_inode_post_setxattr,
+ lsm_inode_getxattr,
+ lsm_inode_listxattr,
+ lsm_inode_removexattr,
+ lsm_inode_need_killpriv,
+ lsm_inode_killpriv,
+ lsm_inode_getsecurity,
+ lsm_inode_setsecurity,
+ lsm_inode_listsecurity,
+ lsm_inode_getsecid,
+ lsm_file_permission,
+ lsm_file_alloc_security,
+ lsm_file_free_security,
+ lsm_file_ioctl,
+ lsm_mmap_addr,
+ lsm_mmap_file,
+ lsm_file_mprotect,
+ lsm_file_lock,
+ lsm_file_fcntl,
+ lsm_file_set_fowner,
+ lsm_file_send_sigiotask,
+ lsm_file_receive,
+ lsm_file_open,
+ lsm_task_create,
+ lsm_task_free,
+ lsm_cred_alloc_blank,
+ lsm_cred_free,
+ lsm_cred_prepare,
+ lsm_cred_transfer,
+ lsm_kernel_act_as,
+ lsm_kernel_create_files_as,
+ lsm_kernel_module_request,
+ lsm_kernel_module_from_file,
+ lsm_task_fix_setuid,
+ lsm_task_setpgid,
+ lsm_task_getpgid,
+ lsm_task_getsid,
+ lsm_task_getsecid,
+ lsm_task_setnice,
+ lsm_task_setioprio,
+ lsm_task_getioprio,
+ lsm_task_setrlimit,
+ lsm_task_setscheduler,
+ lsm_task_getscheduler,
+ lsm_task_movememory,
+ lsm_task_kill,
+ lsm_task_wait,
+ lsm_task_prctl,
+ lsm_task_to_inode,
+ lsm_ipc_permission,
+ lsm_ipc_getsecid,
+ lsm_msg_msg_alloc_security,
+ lsm_msg_msg_free_security,
+ lsm_msg_queue_alloc_security,
+ lsm_msg_queue_free_security,
+ lsm_msg_queue_associate,
+ lsm_msg_queue_msgctl,
+ lsm_msg_queue_msgsnd,
+ lsm_msg_queue_msgrcv,
+ lsm_shm_alloc_security,
+ lsm_shm_free_security,
+ lsm_shm_associate,
+ lsm_shm_shmctl,
+ lsm_shm_shmat,
+ lsm_sem_alloc_security,
+ lsm_sem_free_security,
+ lsm_sem_associate,
+ lsm_sem_semctl,
+ lsm_sem_semop,
+ lsm_netlink_send,
+ lsm_d_instantiate,
+ lsm_getprocattr,
+ lsm_setprocattr,
+ lsm_ismaclabel,
+ lsm_secid_to_secctx,
+ lsm_secctx_to_secid,
+ lsm_release_secctx,
+ lsm_inode_notifysecctx,
+ lsm_inode_setsecctx,
+ lsm_inode_getsecctx,
+#ifdef CONFIG_SECURITY_NETWORK
+ lsm_unix_stream_connect,
+ lsm_unix_may_send,
+ lsm_socket_create,
+ lsm_socket_post_create,
+ lsm_socket_bind,
+ lsm_socket_connect,
+ lsm_socket_listen,
+ lsm_socket_accept,
+ lsm_socket_sendmsg,
+ lsm_socket_recvmsg,
+ lsm_socket_getsockname,
+ lsm_socket_getpeername,
+ lsm_socket_getsockopt,
+ lsm_socket_setsockopt,
+ lsm_socket_shutdown,
+ lsm_socket_sock_rcv_skb,
+ lsm_socket_getpeersec_stream,
+ lsm_socket_getpeersec_dgram,
+ lsm_sk_alloc_security,
+ lsm_sk_free_security,
+ lsm_sk_clone_security,
+ lsm_sk_getsecid,
+ lsm_sock_graft,
+ lsm_inet_conn_request,
+ lsm_inet_csk_clone,
+ lsm_inet_conn_established,
+ lsm_secmark_relabel_packet,
+ lsm_secmark_refcount_inc,
+ lsm_secmark_refcount_dec,
+ lsm_req_classify_flow,
+ lsm_tun_dev_alloc_security,
+ lsm_tun_dev_free_security,
+ lsm_tun_dev_create,
+ lsm_tun_dev_attach_queue,
+ lsm_tun_dev_attach,
+ lsm_tun_dev_open,
+ lsm_skb_owned_by,
+#endif/* CONFIG_SECURITY_NETWORK */
+#ifdef CONFIG_SECURITY_NETWORK_XFRM
+ lsm_xfrm_policy_alloc_security,
+ lsm_xfrm_policy_clone_security,
+ lsm_xfrm_policy_free_security,
+ lsm_xfrm_policy_delete_security,
+ lsm_xfrm_state_alloc,
+ lsm_xfrm_state_alloc_acquire,
+ lsm_xfrm_state_free_security,
+ lsm_xfrm_state_delete_security,
+ lsm_xfrm_policy_lookup,
+ lsm_xfrm_state_pol_flow_match,
+ lsm_xfrm_decode_session,
+#endif/* CONFIG_SECURITY_NETWORK_XFRM */
+#ifdef CONFIG_KEYS
+ lsm_key_alloc,
+ lsm_key_free,
+ lsm_key_permission,
+ lsm_key_getsecurity,
+#endif/* CONFIG_KEYS */
+#ifdef CONFIG_AUDIT
+ lsm_audit_rule_init,
+ lsm_audit_rule_known,
+ lsm_audit_rule_match,
+ lsm_audit_rule_free,
+#endif /* CONFIG_AUDIT */
+ max_lsm_hooks
+};
+static struct list_head lsm_hooks[max_lsm_hooks];
+
struct security_hook_list {
struct list_head shl_head;
struct security_operations *shl_ops;
@@ -62,6 +270,10 @@ extern struct security_operations yama_ops;
int __init security_init(void)
{
int rc;
+ enum lsm_hooks_index i;
+
+ for (i = 0; i < max_lsm_hooks; i++)
+ INIT_LIST_HEAD(&lsm_hooks[i]);
printk(KERN_INFO "Security Framework initialized\n");
@@ -144,97 +356,63 @@ int __init register_security(struct security_operations *ops)
* This is a hook that does not return a value.
*
+ * This is a hook that returns a value.
+ * Stop on the first failure.
+ *
* This is a hook that returns a value.
* Stop on the first failure.
*/
-#ifdef CONFIG_SECURITY_SELINUX_DISABLE
-
#define call_void_hook(FUNC, ...) \
do { \
struct security_hook_list *P; \
\
- if (hooks_##FUNC.next == NULL) \
- break; \
- if (list_empty(&hooks_##FUNC)) \
- break; \
- \
- list_for_each_entry(P, &hooks_##FUNC, shl_head) { \
- if (P->shl_ops == NULL) \
- continue; \
+ list_for_each_entry(P, &lsm_hooks[lsm_##FUNC], shl_head)\
P->shl_ops->FUNC(__VA_ARGS__); \
- } \
- } while (0) \
+ } while (0)
-#define call_int_hook(FUNC, ...) ({ \
- int RC = 0; \
+#define call_int_hook_default(rc, FUNC, ...) ({ \
+ int RC = rc; \
do { \
struct security_hook_list *P; \
\
- if (hooks_##FUNC.next == NULL) \
- break; \
- if (list_empty(&hooks_##FUNC)) \
- break; \
- \
- list_for_each_entry(P, &hooks_##FUNC, shl_head) { \
- if (P->shl_ops == NULL) \
- continue; \
+ list_for_each_entry(P, &lsm_hooks[lsm_##FUNC], shl_head) { \
RC = P->shl_ops->FUNC(__VA_ARGS__); \
if (RC != 0) \
break; \
} \
} while (0); \
RC; \
-}) \
-
-#else /* CONFIG_SECURITY_SELINUX_DISABLE */
-
-#define call_void_hook(FUNC, ...) \
- do { \
- struct security_hook_list *P; \
- \
- if (list_empty(&hooks_##FUNC)) \
- break; \
- \
- list_for_each_entry(P, &hooks_##FUNC, shl_head) \
- P->shl_ops->FUNC(__VA_ARGS__); \
- } while (0) \
+})
#define call_int_hook(FUNC, ...) ({ \
int RC = 0; \
do { \
struct security_hook_list *P; \
\
- if (list_empty(&hooks_##FUNC)) \
- break; \
- \
- list_for_each_entry(P, &hooks_##FUNC, shl_head) { \
+ list_for_each_entry(P, &lsm_hooks[lsm_##FUNC], shl_head) { \
RC = P->shl_ops->FUNC(__VA_ARGS__); \
if (RC != 0) \
break; \
} \
} while (0); \
RC; \
-}) \
-
-#endif /* CONFIG_SECURITY_SELINUX_DISABLE */
+})
/* Security operations */
-static struct list_head hooks_ptrace_access_check;
int security_ptrace_access_check(struct task_struct *child, unsigned int mode)
{
return call_int_hook(ptrace_access_check, child, mode);
}
-static struct list_head hooks_ptrace_traceme;
int security_ptrace_traceme(struct task_struct *parent)
{
return call_int_hook(ptrace_traceme, parent);
}
-static struct list_head hooks_capget;
int security_capget(struct task_struct *target,
kernel_cap_t *effective,
kernel_cap_t *inheritable,
@@ -243,7 +421,6 @@ int security_capget(struct task_struct *target,
return call_int_hook(capget, target, effective, inheritable, permitted);
}
-static struct list_head hooks_capset;
int security_capset(struct cred *new, const struct cred *old,
const kernel_cap_t *effective,
const kernel_cap_t *inheritable,
@@ -253,7 +430,6 @@ int security_capset(struct cred *new, const struct cred *old,
effective, inheritable, permitted);
}
-static struct list_head hooks_capable;
int security_capable(const struct cred *cred, struct user_namespace *ns,
int cap)
{
@@ -270,43 +446,36 @@ int security_capable_noaudit(const struct cred *cred, struct user_namespace *ns,
return call_int_hook(capable, cred, ns, cap, SECURITY_CAP_NOAUDIT);
}
-static struct list_head hooks_quotactl;
int security_quotactl(int cmds, int type, int id, struct super_block *sb)
{
return call_int_hook(quotactl, cmds, type, id, sb);
}
-static struct list_head hooks_quota_on;
int security_quota_on(struct dentry *dentry)
{
return call_int_hook(quota_on, dentry);
}
-static struct list_head hooks_syslog;
int security_syslog(int type)
{
return call_int_hook(syslog, type);
}
-static struct list_head hooks_settime;
int security_settime(const struct timespec *ts, const struct timezone *tz)
{
return call_int_hook(settime, ts, tz);
}
-static struct list_head hooks_vm_enough_memory;
int security_vm_enough_memory_mm(struct mm_struct *mm, long pages)
{
return call_int_hook(vm_enough_memory, mm, pages);
}
-static struct list_head hooks_bprm_set_creds;
int security_bprm_set_creds(struct linux_binprm *bprm)
{
return call_int_hook(bprm_set_creds, bprm);
}
-static struct list_head hooks_bprm_check_security;
int security_bprm_check(struct linux_binprm *bprm)
{
int ret;
@@ -317,100 +486,86 @@ int security_bprm_check(struct linux_binprm *bprm)
return ima_bprm_check(bprm);
}
-static struct list_head hooks_bprm_committing_creds;
void security_bprm_committing_creds(struct linux_binprm *bprm)
{
call_void_hook(bprm_committing_creds, bprm);
}
-static struct list_head hooks_bprm_committed_creds;
void security_bprm_committed_creds(struct linux_binprm *bprm)
{
call_void_hook(bprm_committed_creds, bprm);
}
-static struct list_head hooks_bprm_secureexec;
int security_bprm_secureexec(struct linux_binprm *bprm)
{
/*
* SELinux and Smack integrate the cap call,
* so assume that all LSMs supplying this call do so.
*/
- if (list_empty(&hooks_bprm_secureexec))
+ if (list_empty(&lsm_hooks[lsm_bprm_secureexec]))
return cap_bprm_secureexec(bprm);
return call_int_hook(bprm_secureexec, bprm);
}
-static struct list_head hooks_sb_alloc_security;
int security_sb_alloc(struct super_block *sb)
{
return call_int_hook(sb_alloc_security, sb);
}
-static struct list_head hooks_sb_free_security;
void security_sb_free(struct super_block *sb)
{
call_void_hook(sb_free_security, sb);
}
-static struct list_head hooks_sb_copy_data;
int security_sb_copy_data(char *orig, char *copy)
{
return call_int_hook(sb_copy_data, orig, copy);
}
EXPORT_SYMBOL(security_sb_copy_data);
-static struct list_head hooks_sb_remount;
int security_sb_remount(struct super_block *sb, void *data)
{
return call_int_hook(sb_remount, sb, data);
}
-static struct list_head hooks_sb_kern_mount;
int security_sb_kern_mount(struct super_block *sb, int flags, void *data)
{
return call_int_hook(sb_kern_mount, sb, flags, data);
}
-static struct list_head hooks_sb_show_options;
int security_sb_show_options(struct seq_file *m, struct super_block *sb)
{
return call_int_hook(sb_show_options, m, sb);
}
-static struct list_head hooks_sb_statfs;
int security_sb_statfs(struct dentry *dentry)
{
return call_int_hook(sb_statfs, dentry);
}
-static struct list_head hooks_sb_mount;
int security_sb_mount(const char *dev_name, struct path *path,
const char *type, unsigned long flags, void *data)
{
return call_int_hook(sb_mount, dev_name, path, type, flags, data);
}
-static struct list_head hooks_sb_umount;
int security_sb_umount(struct vfsmount *mnt, int flags)
{
return call_int_hook(sb_umount, mnt, flags);
}
-static struct list_head hooks_sb_pivotroot;
int security_sb_pivotroot(struct path *old_path, struct path *new_path)
{
return call_int_hook(sb_pivotroot, old_path, new_path);
}
-static struct list_head hooks_sb_set_mnt_opts;
int security_sb_set_mnt_opts(struct super_block *sb,
struct security_mnt_opts *opts,
unsigned long kern_flags,
unsigned long *set_kern_flags)
{
- if (list_empty(&hooks_sb_set_mnt_opts)) {
+ if (list_empty(&lsm_hooks[lsm_sb_set_mnt_opts])) {
if (unlikely(opts->num_mnt_opts))
return -EOPNOTSUPP;
}
@@ -420,7 +575,6 @@ int security_sb_set_mnt_opts(struct super_block *sb,
}
EXPORT_SYMBOL(security_sb_set_mnt_opts);
-static struct list_head hooks_sb_clone_mnt_opts;
int security_sb_clone_mnt_opts(const struct super_block *oldsb,
struct super_block *newsb)
{
@@ -428,39 +582,32 @@ int security_sb_clone_mnt_opts(const struct super_block *oldsb,
}
EXPORT_SYMBOL(security_sb_clone_mnt_opts);
-static struct list_head hooks_sb_parse_opts_str;
int security_sb_parse_opts_str(char *options, struct security_mnt_opts *opts)
{
return call_int_hook(sb_parse_opts_str, options, opts);
}
EXPORT_SYMBOL(security_sb_parse_opts_str);
-static struct list_head hooks_inode_alloc_security;
int security_inode_alloc(struct inode *inode)
{
return call_int_hook(inode_alloc_security, inode);
}
-static struct list_head hooks_inode_free_security;
void security_inode_free(struct inode *inode)
{
integrity_inode_free(inode);
call_void_hook(inode_free_security, inode);
}
-static struct list_head hooks_dentry_init_security;
int security_dentry_init_security(struct dentry *dentry, int mode,
struct qstr *name, void **ctx,
u32 *ctxlen)
{
- if (list_empty(&hooks_dentry_init_security))
- return -EOPNOTSUPP;
- return call_int_hook(dentry_init_security, dentry, mode, name,
- ctx, ctxlen);
+ return call_int_hook_default(-EOPNOTSUPP, dentry_init_security, dentry,
+ mode, name, ctx, ctxlen);
}
EXPORT_SYMBOL(security_dentry_init_security);
-static struct list_head hooks_inode_init_security;
int security_inode_init_security(struct inode *inode, struct inode *dir,
const struct qstr *qstr,
const initxattrs initxattrs, void *fs_data)
@@ -472,7 +619,7 @@ int security_inode_init_security(struct inode *inode, struct inode *dir,
if (unlikely(IS_PRIVATE(inode)))
return 0;
- if (list_empty(&hooks_inode_init_security))
+ if (list_empty(&lsm_hooks[lsm_inode_init_security]))
return 0;
if (!initxattrs)
@@ -509,7 +656,7 @@ int security_old_inode_init_security(struct inode *inode, struct inode *dir,
{
if (unlikely(IS_PRIVATE(inode)))
return -EOPNOTSUPP;
- if (list_empty(&hooks_inode_init_security))
+ if (list_empty(&lsm_hooks[lsm_inode_init_security]))
return 0;
return call_int_hook(inode_init_security, inode, dir, qstr, name,
@@ -518,7 +665,6 @@ int security_old_inode_init_security(struct inode *inode, struct inode *dir,
EXPORT_SYMBOL(security_old_inode_init_security);
#ifdef CONFIG_SECURITY_PATH
-static struct list_head hooks_path_mknod;
int security_path_mknod(struct path *dir, struct dentry *dentry, umode_t mode,
unsigned int dev)
{
@@ -528,7 +674,6 @@ int security_path_mknod(struct path *dir, struct dentry *dentry, umode_t mode,
}
EXPORT_SYMBOL(security_path_mknod);
-static struct list_head hooks_path_mkdir;
int security_path_mkdir(struct path *dir, struct dentry *dentry, umode_t mode)
{
if (unlikely(IS_PRIVATE(dir->dentry->d_inode)))
@@ -537,7 +682,6 @@ int security_path_mkdir(struct path *dir, struct dentry *dentry, umode_t mode)
}
EXPORT_SYMBOL(security_path_mkdir);
-static struct list_head hooks_path_rmdir;
int security_path_rmdir(struct path *dir, struct dentry *dentry)
{
if (unlikely(IS_PRIVATE(dir->dentry->d_inode)))
@@ -545,7 +689,6 @@ int security_path_rmdir(struct path *dir, struct dentry *dentry)
return call_int_hook(path_rmdir, dir, dentry);
}
-static struct list_head hooks_path_unlink;
int security_path_unlink(struct path *dir, struct dentry *dentry)
{
if (unlikely(IS_PRIVATE(dir->dentry->d_inode)))
@@ -554,7 +697,6 @@ int security_path_unlink(struct path *dir, struct dentry *dentry)
}
EXPORT_SYMBOL(security_path_unlink);
-static struct list_head hooks_path_symlink;
int security_path_symlink(struct path *dir, struct dentry *dentry,
const char *old_name)
{
@@ -563,7 +705,6 @@ int security_path_symlink(struct path *dir, struct dentry *dentry,
return call_int_hook(path_symlink, dir, dentry, old_name);
}
-static struct list_head hooks_path_link;
int security_path_link(struct dentry *old_dentry, struct path *new_dir,
struct dentry *new_dentry)
{
@@ -572,7 +713,6 @@ int security_path_link(struct dentry *old_dentry, struct path *new_dir,
return call_int_hook(path_link, old_dentry, new_dir, new_dentry);
}
-static struct list_head hooks_path_rename;
int security_path_rename(struct path *old_dir, struct dentry *old_dentry,
struct path *new_dir, struct dentry *new_dentry,
unsigned int flags)
@@ -593,7 +733,6 @@ int security_path_rename(struct path *old_dir, struct dentry *old_dentry,
}
EXPORT_SYMBOL(security_path_rename);
-static struct list_head hooks_path_truncate;
int security_path_truncate(struct path *path)
{
if (unlikely(IS_PRIVATE(path->dentry->d_inode)))
@@ -601,7 +740,6 @@ int security_path_truncate(struct path *path)
return call_int_hook(path_truncate, path);
}
-static struct list_head hooks_path_chmod;
int security_path_chmod(struct path *path, umode_t mode)
{
if (unlikely(IS_PRIVATE(path->dentry->d_inode)))
@@ -609,7 +747,6 @@ int security_path_chmod(struct path *path, umode_t mode)
return call_int_hook(path_chmod, path, mode);
}
-static struct list_head hooks_path_chown;
int security_path_chown(struct path *path, kuid_t uid, kgid_t gid)
{
if (unlikely(IS_PRIVATE(path->dentry->d_inode)))
@@ -617,14 +754,12 @@ int security_path_chown(struct path *path, kuid_t uid, kgid_t gid)
return call_int_hook(path_chown, path, uid, gid);
}
-static struct list_head hooks_path_chroot;
int security_path_chroot(struct path *path)
{
return call_int_hook(path_chroot, path);
}
#endif
-static struct list_head hooks_inode_create;
int security_inode_create(struct inode *dir, struct dentry *dentry, umode_t mode)
{
if (unlikely(IS_PRIVATE(dir)))
@@ -633,7 +768,6 @@ int security_inode_create(struct inode *dir, struct dentry *dentry, umode_t mode
}
EXPORT_SYMBOL_GPL(security_inode_create);
-static struct list_head hooks_inode_link;
int security_inode_link(struct dentry *old_dentry, struct inode *dir,
struct dentry *new_dentry)
{
@@ -642,7 +776,6 @@ int security_inode_link(struct dentry *old_dentry, struct inode *dir,
return call_int_hook(inode_link, old_dentry, dir, new_dentry);
}
-static struct list_head hooks_inode_unlink;
int security_inode_unlink(struct inode *dir, struct dentry *dentry)
{
if (unlikely(IS_PRIVATE(dentry->d_inode)))
@@ -650,7 +783,6 @@ int security_inode_unlink(struct inode *dir, struct dentry *dentry)
return call_int_hook(inode_unlink, dir, dentry);
}
-static struct list_head hooks_inode_symlink;
int security_inode_symlink(struct inode *dir, struct dentry *dentry,
const char *old_name)
{
@@ -659,7 +791,6 @@ int security_inode_symlink(struct inode *dir, struct dentry *dentry,
return call_int_hook(inode_symlink, dir, dentry, old_name);
}
-static struct list_head hooks_inode_mkdir;
int security_inode_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
{
if (unlikely(IS_PRIVATE(dir)))
@@ -668,7 +799,6 @@ int security_inode_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
}
EXPORT_SYMBOL_GPL(security_inode_mkdir);
-static struct list_head hooks_inode_rmdir;
int security_inode_rmdir(struct inode *dir, struct dentry *dentry)
{
if (unlikely(IS_PRIVATE(dentry->d_inode)))
@@ -676,7 +806,6 @@ int security_inode_rmdir(struct inode *dir, struct dentry *dentry)
return call_int_hook(inode_rmdir, dir, dentry);
}
-static struct list_head hooks_inode_mknod;
int security_inode_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t dev)
{
if (unlikely(IS_PRIVATE(dir)))
@@ -684,7 +813,6 @@ int security_inode_mknod(struct inode *dir, struct dentry *dentry, umode_t mode,
return call_int_hook(inode_mknod, dir, dentry, mode, dev);
}
-static struct list_head hooks_inode_rename;
int security_inode_rename(struct inode *old_dir, struct dentry *old_dentry,
struct inode *new_dir, struct dentry *new_dentry,
unsigned int flags)
@@ -704,7 +832,6 @@ int security_inode_rename(struct inode *old_dir, struct dentry *old_dentry,
new_dir, new_dentry);
}
-static struct list_head hooks_inode_readlink;
int security_inode_readlink(struct dentry *dentry)
{
if (unlikely(IS_PRIVATE(dentry->d_inode)))
@@ -712,7 +839,6 @@ int security_inode_readlink(struct dentry *dentry)
return call_int_hook(inode_readlink, dentry);
}
-static struct list_head hooks_inode_follow_link;
int security_inode_follow_link(struct dentry *dentry, struct nameidata *nd)
{
if (unlikely(IS_PRIVATE(dentry->d_inode)))
@@ -720,7 +846,6 @@ int security_inode_follow_link(struct dentry *dentry, struct nameidata *nd)
return call_int_hook(inode_follow_link, dentry, nd);
}
-static struct list_head hooks_inode_permission;
int security_inode_permission(struct inode *inode, int mask)
{
if (unlikely(IS_PRIVATE(inode)))
@@ -728,7 +853,6 @@ int security_inode_permission(struct inode *inode, int mask)
return call_int_hook(inode_permission, inode, mask);
}
-static struct list_head hooks_inode_setattr;
int security_inode_setattr(struct dentry *dentry, struct iattr *attr)
{
int ret;
@@ -742,7 +866,6 @@ int security_inode_setattr(struct dentry *dentry, struct iattr *attr)
}
EXPORT_SYMBOL_GPL(security_inode_setattr);
-static struct list_head hooks_inode_getattr;
int security_inode_getattr(struct vfsmount *mnt, struct dentry *dentry)
{
if (unlikely(IS_PRIVATE(dentry->d_inode)))
@@ -750,7 +873,6 @@ int security_inode_getattr(struct vfsmount *mnt, struct dentry *dentry)
return call_int_hook(inode_getattr, mnt, dentry);
}
-static struct list_head hooks_inode_setxattr;
int security_inode_setxattr(struct dentry *dentry, const char *name,
const void *value, size_t size, int flags)
{
@@ -762,7 +884,7 @@ int security_inode_setxattr(struct dentry *dentry, const char *name,
* SELinux and Smack integrate the cap call,
* so assume that all LSMs supplying this call do so.
*/
- if (list_empty(&hooks_inode_setxattr))
+ if (list_empty(&lsm_hooks[lsm_inode_setxattr]))
ret = cap_inode_setxattr(dentry, name, value, size, flags);
else
ret = call_int_hook(inode_setxattr, dentry, name, value,
@@ -776,7 +898,6 @@ int security_inode_setxattr(struct dentry *dentry, const char *name,
return evm_inode_setxattr(dentry, name, value, size);
}
-static struct list_head hooks_inode_post_setxattr;
void security_inode_post_setxattr(struct dentry *dentry, const char *name,
const void *value, size_t size, int flags)
{
@@ -786,7 +907,6 @@ void security_inode_post_setxattr(struct dentry *dentry, const char *name,
evm_inode_post_setxattr(dentry, name, value, size);
}
-static struct list_head hooks_inode_getxattr;
int security_inode_getxattr(struct dentry *dentry, const char *name)
{
if (unlikely(IS_PRIVATE(dentry->d_inode)))
@@ -794,7 +914,6 @@ int security_inode_getxattr(struct dentry *dentry, const char *name)
return call_int_hook(inode_getxattr, dentry, name);
}
-static struct list_head hooks_inode_listxattr;
int security_inode_listxattr(struct dentry *dentry)
{
if (unlikely(IS_PRIVATE(dentry->d_inode)))
@@ -802,7 +921,6 @@ int security_inode_listxattr(struct dentry *dentry)
return call_int_hook(inode_listxattr, dentry);
}
-static struct list_head hooks_inode_removexattr;
int security_inode_removexattr(struct dentry *dentry, const char *name)
{
int ret;
@@ -810,7 +928,7 @@ int security_inode_removexattr(struct dentry *dentry, const char *name)
if (unlikely(IS_PRIVATE(dentry->d_inode)))
return 0;
- if (list_empty(&hooks_inode_removexattr))
+ if (list_empty(&lsm_hooks[lsm_inode_removexattr]))
ret = cap_inode_removexattr(dentry, name);
else
ret = call_int_hook(inode_removexattr, dentry, name);
@@ -823,40 +941,32 @@ int security_inode_removexattr(struct dentry *dentry, const char *name)
return evm_inode_removexattr(dentry, name);
}
-static struct list_head hooks_inode_need_killpriv;
int security_inode_need_killpriv(struct dentry *dentry)
{
return call_int_hook(inode_need_killpriv, dentry);
}
-static struct list_head hooks_inode_killpriv;
int security_inode_killpriv(struct dentry *dentry)
{
return call_int_hook(inode_killpriv, dentry);
}
-static struct list_head hooks_inode_getsecurity;
int security_inode_getsecurity(const struct inode *inode, const char *name, void **buffer, bool alloc)
{
if (unlikely(IS_PRIVATE(inode)))
return -EOPNOTSUPP;
- if (list_empty(&hooks_inode_getsecurity))
- return -EOPNOTSUPP;
- return call_int_hook(inode_getsecurity, inode, name, buffer, alloc);
+ return call_int_hook_default(-EOPNOTSUPP, inode_getsecurity, inode,
+ name, buffer, alloc);
}
-static struct list_head hooks_inode_setsecurity;
int security_inode_setsecurity(struct inode *inode, const char *name, const void *value, size_t size, int flags)
{
if (unlikely(IS_PRIVATE(inode)))
return -EOPNOTSUPP;
- if (list_empty(&hooks_inode_setsecurity))
- return -EOPNOTSUPP;
- return call_int_hook(inode_setsecurity, inode, name, value, size,
- flags);
+ return call_int_hook_default(-EOPNOTSUPP, inode_setsecurity, inode,
+ name, value, size, flags);
}
-static struct list_head hooks_inode_listsecurity;
int security_inode_listsecurity(struct inode *inode, char *buffer, size_t buffer_size)
{
if (unlikely(IS_PRIVATE(inode)))
@@ -865,16 +975,12 @@ int security_inode_listsecurity(struct inode *inode, char *buffer, size_t buffer
}
EXPORT_SYMBOL(security_inode_listsecurity);
-static struct list_head hooks_inode_getsecid;
void security_inode_getsecid(const struct inode *inode, u32 *secid)
{
- if (list_empty(&hooks_inode_getsecid))
- *secid = 0;
- else
- call_void_hook(inode_getsecid, inode, secid);
+ *secid = 0;
+ call_void_hook(inode_getsecid, inode, secid);
}
-static struct list_head hooks_file_permission;
int security_file_permission(struct file *file, int mask)
{
int ret;
@@ -886,19 +992,16 @@ int security_file_permission(struct file *file, int mask)
return fsnotify_perm(file, mask);
}
-static struct list_head hooks_file_alloc_security;
int security_file_alloc(struct file *file)
{
return call_int_hook(file_alloc_security, file);
}
-static struct list_head hooks_file_free_security;
void security_file_free(struct file *file)
{
call_void_hook(file_free_security, file);
}
-static struct list_head hooks_file_ioctl;
int security_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
return call_int_hook(file_ioctl, file, cmd, arg);
@@ -938,7 +1041,6 @@ static inline unsigned long mmap_prot(struct file *file, unsigned long prot)
return prot;
}
-static struct list_head hooks_mmap_file;
int security_mmap_file(struct file *file, unsigned long prot,
unsigned long flags)
{
@@ -950,51 +1052,43 @@ int security_mmap_file(struct file *file, unsigned long prot,
return ima_file_mmap(file, prot);
}
-static struct list_head hooks_mmap_addr;
int security_mmap_addr(unsigned long addr)
{
return call_int_hook(mmap_addr, addr);
}
-static struct list_head hooks_file_mprotect;
int security_file_mprotect(struct vm_area_struct *vma, unsigned long reqprot,
unsigned long prot)
{
return call_int_hook(file_mprotect, vma, reqprot, prot);
}
-static struct list_head hooks_file_lock;
int security_file_lock(struct file *file, unsigned int cmd)
{
return call_int_hook(file_lock, file, cmd);
}
-static struct list_head hooks_file_fcntl;
int security_file_fcntl(struct file *file, unsigned int cmd, unsigned long arg)
{
return call_int_hook(file_fcntl, file, cmd, arg);
}
-static struct list_head hooks_file_set_fowner;
int security_file_set_fowner(struct file *file)
{
return call_int_hook(file_set_fowner, file);
}
-static struct list_head hooks_file_send_sigiotask;
int security_file_send_sigiotask(struct task_struct *tsk,
struct fown_struct *fown, int sig)
{
return call_int_hook(file_send_sigiotask, tsk, fown, sig);
}
-static struct list_head hooks_file_receive;
int security_file_receive(struct file *file)
{
return call_int_hook(file_receive, file);
}
-static struct list_head hooks_file_open;
int security_file_open(struct file *file, const struct cred *cred)
{
int ret;
@@ -1006,61 +1100,51 @@ int security_file_open(struct file *file, const struct cred *cred)
return fsnotify_perm(file, MAY_OPEN);
}
-static struct list_head hooks_task_create;
int security_task_create(unsigned long clone_flags)
{
return call_int_hook(task_create, clone_flags);
}
-static struct list_head hooks_task_free;
void security_task_free(struct task_struct *task)
{
call_void_hook(task_free, task);
}
-static struct list_head hooks_cred_alloc_blank;
int security_cred_alloc_blank(struct cred *cred, gfp_t gfp)
{
return call_int_hook(cred_alloc_blank, cred, gfp);
}
-static struct list_head hooks_cred_free;
void security_cred_free(struct cred *cred)
{
call_void_hook(cred_free, cred);
}
-static struct list_head hooks_cred_prepare;
int security_prepare_creds(struct cred *new, const struct cred *old, gfp_t gfp)
{
return call_int_hook(cred_prepare, new, old, gfp);
}
-static struct list_head hooks_cred_transfer;
void security_transfer_creds(struct cred *new, const struct cred *old)
{
call_void_hook(cred_transfer, new, old);
}
-static struct list_head hooks_kernel_act_as;
int security_kernel_act_as(struct cred *new, u32 secid)
{
return call_int_hook(kernel_act_as, new, secid);
}
-static struct list_head hooks_kernel_create_files_as;
int security_kernel_create_files_as(struct cred *new, struct inode *inode)
{
return call_int_hook(kernel_create_files_as, new, inode);
}
-static struct list_head hooks_kernel_module_request;
int security_kernel_module_request(char *kmod_name)
{
return call_int_hook(kernel_module_request, kmod_name);
}
-static struct list_head hooks_kernel_module_from_file;
int security_kernel_module_from_file(struct file *file)
{
int ret;
@@ -1071,98 +1155,81 @@ int security_kernel_module_from_file(struct file *file)
return ima_module_check(file);
}
-static struct list_head hooks_task_fix_setuid;
int security_task_fix_setuid(struct cred *new, const struct cred *old,
int flags)
{
return call_int_hook(task_fix_setuid, new, old, flags);
}
-static struct list_head hooks_task_setpgid;
int security_task_setpgid(struct task_struct *p, pid_t pgid)
{
return call_int_hook(task_setpgid, p, pgid);
}
-static struct list_head hooks_task_getpgid;
int security_task_getpgid(struct task_struct *p)
{
return call_int_hook(task_getpgid, p);
}
-static struct list_head hooks_task_getsid;
int security_task_getsid(struct task_struct *p)
{
return call_int_hook(task_getsid, p);
}
-static struct list_head hooks_task_getsecid;
void security_task_getsecid(struct task_struct *p, u32 *secid)
{
- if (list_empty(&hooks_task_getsecid))
- *secid = 0;
- else
- call_void_hook(task_getsecid, p, secid);
+ *secid = 0;
+ call_void_hook(task_getsecid, p, secid);
}
EXPORT_SYMBOL(security_task_getsecid);
-static struct list_head hooks_task_setnice;
int security_task_setnice(struct task_struct *p, int nice)
{
return call_int_hook(task_setnice, p, nice);
}
-static struct list_head hooks_task_setioprio;
int security_task_setioprio(struct task_struct *p, int ioprio)
{
return call_int_hook(task_setioprio, p, ioprio);
}
-static struct list_head hooks_task_getioprio;
int security_task_getioprio(struct task_struct *p)
{
return call_int_hook(task_getioprio, p);
}
-static struct list_head hooks_task_setrlimit;
int security_task_setrlimit(struct task_struct *p, unsigned int resource,
struct rlimit *new_rlim)
{
return call_int_hook(task_setrlimit, p, resource, new_rlim);
}
-static struct list_head hooks_task_setscheduler;
int security_task_setscheduler(struct task_struct *p)
{
return call_int_hook(task_setscheduler, p);
}
-static struct list_head hooks_task_getscheduler;
int security_task_getscheduler(struct task_struct *p)
{
return call_int_hook(task_getscheduler, p);
}
-static struct list_head hooks_task_movememory;
int security_task_movememory(struct task_struct *p)
{
return call_int_hook(task_movememory, p);
}
-static struct list_head hooks_task_kill;
int security_task_kill(struct task_struct *p, struct siginfo *info,
int sig, u32 secid)
{
return call_int_hook(task_kill, p, info, sig, secid);
}
-static struct list_head hooks_task_wait;
int security_task_wait(struct task_struct *p)
{
return call_int_hook(task_wait, p);
}
-static struct list_head hooks_task_prctl;
int security_task_prctl(int option, unsigned long arg2, unsigned long arg3,
unsigned long arg4, unsigned long arg5)
{
@@ -1170,16 +1237,11 @@ int security_task_prctl(int option, unsigned long arg2, unsigned long arg3,
int rc = -ENOSYS;
struct security_hook_list *shp;
- if (list_empty(&hooks_task_prctl))
+ if (list_empty(&lsm_hooks[lsm_task_prctl]))
return -ENOSYS;
- list_for_each_entry(shp, &hooks_task_prctl, shl_head) {
-#ifdef CONFIG_SECURITY_SELINUX_DISABLE
- if (shp->shl_ops == NULL)
- continue;
-#endif
- thisrc = shp->shl_ops->task_prctl(option, arg2, arg3,
- arg4, arg5);
+ list_for_each_entry(shp, &lsm_hooks[lsm_task_prctl], shl_head) {
+ thisrc = shp->shl_ops->task_prctl(option, arg2, arg3, arg4, arg5);
if (thisrc != -ENOSYS) {
rc = thisrc;
if (thisrc != 0)
@@ -1189,139 +1251,115 @@ int security_task_prctl(int option, unsigned long arg2, unsigned long arg3,
return rc;
}
-static struct list_head hooks_task_to_inode;
void security_task_to_inode(struct task_struct *p, struct inode *inode)
{
call_void_hook(task_to_inode, p, inode);
}
-static struct list_head hooks_ipc_permission;
int security_ipc_permission(struct kern_ipc_perm *ipcp, short flag)
{
return call_int_hook(ipc_permission, ipcp, flag);
}
-static struct list_head hooks_ipc_getsecid;
void security_ipc_getsecid(struct kern_ipc_perm *ipcp, u32 *secid)
{
- if (list_empty(&hooks_ipc_getsecid))
- *secid = 0;
- else
- call_void_hook(ipc_getsecid, ipcp, secid);
+ *secid = 0;
+ call_void_hook(ipc_getsecid, ipcp, secid);
}
-static struct list_head hooks_msg_msg_alloc_security;
int security_msg_msg_alloc(struct msg_msg *msg)
{
return call_int_hook(msg_msg_alloc_security, msg);
}
-static struct list_head hooks_msg_msg_free_security;
void security_msg_msg_free(struct msg_msg *msg)
{
call_void_hook(msg_msg_free_security, msg);
}
-static struct list_head hooks_msg_queue_alloc_security;
int security_msg_queue_alloc(struct msg_queue *msq)
{
return call_int_hook(msg_queue_alloc_security, msq);
}
-static struct list_head hooks_msg_queue_free_security;
void security_msg_queue_free(struct msg_queue *msq)
{
call_void_hook(msg_queue_free_security, msq);
}
-static struct list_head hooks_msg_queue_associate;
int security_msg_queue_associate(struct msg_queue *msq, int msqflg)
{
return call_int_hook(msg_queue_associate, msq, msqflg);
}
-static struct list_head hooks_msg_queue_msgctl;
int security_msg_queue_msgctl(struct msg_queue *msq, int cmd)
{
return call_int_hook(msg_queue_msgctl, msq, cmd);
}
-static struct list_head hooks_msg_queue_msgsnd;
int security_msg_queue_msgsnd(struct msg_queue *msq,
struct msg_msg *msg, int msqflg)
{
return call_int_hook(msg_queue_msgsnd, msq, msg, msqflg);
}
-static struct list_head hooks_msg_queue_msgrcv;
int security_msg_queue_msgrcv(struct msg_queue *msq, struct msg_msg *msg,
struct task_struct *target, long type, int mode)
{
return call_int_hook(msg_queue_msgrcv, msq, msg, target, type, mode);
}
-static struct list_head hooks_shm_alloc_security;
int security_shm_alloc(struct shmid_kernel *shp)
{
return call_int_hook(shm_alloc_security, shp);
}
-static struct list_head hooks_shm_free_security;
void security_shm_free(struct shmid_kernel *shp)
{
call_void_hook(shm_free_security, shp);
}
-static struct list_head hooks_shm_associate;
int security_shm_associate(struct shmid_kernel *shp, int shmflg)
{
return call_int_hook(shm_associate, shp, shmflg);
}
-static struct list_head hooks_shm_shmctl;
int security_shm_shmctl(struct shmid_kernel *shp, int cmd)
{
return call_int_hook(shm_shmctl, shp, cmd);
}
-static struct list_head hooks_shm_shmat;
int security_shm_shmat(struct shmid_kernel *shp, char __user *shmaddr, int shmflg)
{
return call_int_hook(shm_shmat, shp, shmaddr, shmflg);
}
-static struct list_head hooks_sem_alloc_security;
int security_sem_alloc(struct sem_array *sma)
{
return call_int_hook(sem_alloc_security, sma);
}
-static struct list_head hooks_sem_free_security;
void security_sem_free(struct sem_array *sma)
{
call_void_hook(sem_free_security, sma);
}
-static struct list_head hooks_sem_associate;
int security_sem_associate(struct sem_array *sma, int semflg)
{
return call_int_hook(sem_associate, sma, semflg);
}
-static struct list_head hooks_sem_semctl;
int security_sem_semctl(struct sem_array *sma, int cmd)
{
return call_int_hook(sem_semctl, sma, cmd);
}
-static struct list_head hooks_sem_semop;
int security_sem_semop(struct sem_array *sma, struct sembuf *sops,
unsigned nsops, int alter)
{
return call_int_hook(sem_semop, sma, sops, nsops, alter);
}
-static struct list_head hooks_d_instantiate;
void security_d_instantiate(struct dentry *dentry, struct inode *inode)
{
if (unlikely(inode && IS_PRIVATE(inode)))
@@ -1330,108 +1368,86 @@ void security_d_instantiate(struct dentry *dentry, struct inode *inode)
}
EXPORT_SYMBOL(security_d_instantiate);
-static struct list_head hooks_getprocattr;
int security_getprocattr(struct task_struct *p, char *name, char **value)
{
- if (list_empty(&hooks_getprocattr))
- return -EINVAL;
- return call_int_hook(getprocattr, p, name, value);
+ return call_int_hook_default(-EINVAL, getprocattr, p, name, value);
}
-static struct list_head hooks_setprocattr;
int security_setprocattr(struct task_struct *p, char *name, void *value, size_t size)
{
- if (list_empty(&hooks_setprocattr))
- return -EINVAL;
- return call_int_hook(setprocattr, p, name, value, size);
+ return call_int_hook_default(-EINVAL, setprocattr, p, name, value,
+ size);
}
-static struct list_head hooks_netlink_send;
int security_netlink_send(struct sock *sk, struct sk_buff *skb)
{
return call_int_hook(netlink_send, sk, skb);
}
-static struct list_head hooks_ismaclabel;
int security_ismaclabel(const char *name)
{
return call_int_hook(ismaclabel, name);
}
EXPORT_SYMBOL(security_ismaclabel);
-static struct list_head hooks_secid_to_secctx;
int security_secid_to_secctx(u32 secid, char **secdata, u32 *seclen)
{
- if (list_empty(&hooks_secid_to_secctx))
- return -EOPNOTSUPP;
- return call_int_hook(secid_to_secctx, secid, secdata, seclen);
+ return call_int_hook_default(-EOPNOTSUPP, secid_to_secctx, secid,
+ secdata, seclen);
}
EXPORT_SYMBOL(security_secid_to_secctx);
-static struct list_head hooks_secctx_to_secid;
int security_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid)
{
- if (list_empty(&hooks_secctx_to_secid)) {
- *secid = 0;
- return 0;
- }
+ *secid = 0;
return call_int_hook(secctx_to_secid, secdata, seclen, secid);
}
EXPORT_SYMBOL(security_secctx_to_secid);
-static struct list_head hooks_release_secctx;
void security_release_secctx(char *secdata, u32 seclen)
{
call_void_hook(release_secctx, secdata, seclen);
}
EXPORT_SYMBOL(security_release_secctx);
-static struct list_head hooks_inode_notifysecctx;
int security_inode_notifysecctx(struct inode *inode, void *ctx, u32 ctxlen)
{
return call_int_hook(inode_notifysecctx, inode, ctx, ctxlen);
}
EXPORT_SYMBOL(security_inode_notifysecctx);
-static struct list_head hooks_inode_setsecctx;
int security_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen)
{
return call_int_hook(inode_setsecctx, dentry, ctx, ctxlen);
}
EXPORT_SYMBOL(security_inode_setsecctx);
-static struct list_head hooks_inode_getsecctx;
int security_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen)
{
- if (list_empty(&hooks_inode_getsecctx))
- return -EOPNOTSUPP;
- return call_int_hook(inode_getsecctx, inode, ctx, ctxlen);
+ return call_int_hook_default(-EOPNOTSUPP, inode_getsecctx, inode, ctx,
+ ctxlen);
}
EXPORT_SYMBOL(security_inode_getsecctx);
#ifdef CONFIG_SECURITY_NETWORK
-static struct list_head hooks_unix_stream_connect;
int security_unix_stream_connect(struct sock *sock, struct sock *other, struct sock *newsk)
{
return call_int_hook(unix_stream_connect, sock, other, newsk);
}
EXPORT_SYMBOL(security_unix_stream_connect);
-static struct list_head hooks_unix_may_send;
int security_unix_may_send(struct socket *sock, struct socket *other)
{
return call_int_hook(unix_may_send, sock, other);
}
EXPORT_SYMBOL(security_unix_may_send);
-static struct list_head hooks_socket_create;
int security_socket_create(int family, int type, int protocol, int kern)
{
return call_int_hook(socket_create, family, type, protocol, kern);
}
-static struct list_head hooks_socket_post_create;
int security_socket_post_create(struct socket *sock, int family,
int type, int protocol, int kern)
{
@@ -1439,140 +1455,116 @@ int security_socket_post_create(struct socket *sock, int family,
protocol, kern);
}
-static struct list_head hooks_socket_bind;
int security_socket_bind(struct socket *sock, struct sockaddr *address, int addrlen)
{
return call_int_hook(socket_bind, sock, address, addrlen);
}
-static struct list_head hooks_socket_connect;
int security_socket_connect(struct socket *sock, struct sockaddr *address, int addrlen)
{
return call_int_hook(socket_connect, sock, address, addrlen);
}
-static struct list_head hooks_socket_listen;
int security_socket_listen(struct socket *sock, int backlog)
{
return call_int_hook(socket_listen, sock, backlog);
}
-static struct list_head hooks_socket_accept;
int security_socket_accept(struct socket *sock, struct socket *newsock)
{
return call_int_hook(socket_accept, sock, newsock);
}
-static struct list_head hooks_socket_sendmsg;
int security_socket_sendmsg(struct socket *sock, struct msghdr *msg, int size)
{
return call_int_hook(socket_sendmsg, sock, msg, size);
}
-static struct list_head hooks_socket_recvmsg;
int security_socket_recvmsg(struct socket *sock, struct msghdr *msg,
int size, int flags)
{
return call_int_hook(socket_recvmsg, sock, msg, size, flags);
}
-static struct list_head hooks_socket_getsockname;
int security_socket_getsockname(struct socket *sock)
{
return call_int_hook(socket_getsockname, sock);
}
-static struct list_head hooks_socket_getpeername;
int security_socket_getpeername(struct socket *sock)
{
return call_int_hook(socket_getpeername, sock);
}
-static struct list_head hooks_socket_getsockopt;
int security_socket_getsockopt(struct socket *sock, int level, int optname)
{
return call_int_hook(socket_getsockopt, sock, level, optname);
}
-static struct list_head hooks_socket_setsockopt;
int security_socket_setsockopt(struct socket *sock, int level, int optname)
{
return call_int_hook(socket_setsockopt, sock, level, optname);
}
-static struct list_head hooks_socket_shutdown;
int security_socket_shutdown(struct socket *sock, int how)
{
return call_int_hook(socket_shutdown, sock, how);
}
-static struct list_head hooks_socket_sock_rcv_skb;
int security_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
{
return call_int_hook(socket_sock_rcv_skb, sk, skb);
}
EXPORT_SYMBOL(security_sock_rcv_skb);
-static struct list_head hooks_socket_getpeersec_stream;
int security_socket_getpeersec_stream(struct socket *sock, char __user *optval,
int __user *optlen, unsigned len)
{
- if (list_empty(&hooks_socket_getpeersec_stream))
- return -ENOPROTOOPT;
- return call_int_hook(socket_getpeersec_stream, sock, optval, optlen,
- len);
+ return call_int_hook_default(-ENOPROTOOPT, socket_getpeersec_stream,
+ sock, optval, optlen, len);
}
-static struct list_head hooks_socket_getpeersec_dgram;
int security_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *skb, u32 *secid)
{
- if (list_empty(&hooks_socket_getpeersec_dgram))
- return -ENOPROTOOPT;
- return call_int_hook(socket_getpeersec_dgram, sock, skb, secid);
+ return call_int_hook_default(-ENOPROTOOPT, socket_getpeersec_dgram,
+ sock, skb, secid);
}
EXPORT_SYMBOL(security_socket_getpeersec_dgram);
-static struct list_head hooks_sk_alloc_security;
int security_sk_alloc(struct sock *sk, int family, gfp_t priority)
{
return call_int_hook(sk_alloc_security, sk, family, priority);
}
-static struct list_head hooks_sk_free_security;
void security_sk_free(struct sock *sk)
{
call_void_hook(sk_free_security, sk);
}
-static struct list_head hooks_sk_clone_security;
void security_sk_clone(const struct sock *sk, struct sock *newsk)
{
call_void_hook(sk_clone_security, sk, newsk);
}
EXPORT_SYMBOL(security_sk_clone);
-static struct list_head hooks_sk_getsecid;
void security_sk_classify_flow(struct sock *sk, struct flowi *fl)
{
call_void_hook(sk_getsecid, sk, &fl->flowi_secid);
}
EXPORT_SYMBOL(security_sk_classify_flow);
-static struct list_head hooks_req_classify_flow;
void security_req_classify_flow(const struct request_sock *req, struct flowi *fl)
{
call_void_hook(req_classify_flow, req, fl);
}
EXPORT_SYMBOL(security_req_classify_flow);
-static struct list_head hooks_sock_graft;
void security_sock_graft(struct sock *sk, struct socket *parent)
{
call_void_hook(sock_graft, sk, parent);
}
EXPORT_SYMBOL(security_sock_graft);
-static struct list_head hooks_inet_conn_request;
int security_inet_conn_request(struct sock *sk,
struct sk_buff *skb, struct request_sock *req)
{
@@ -1580,84 +1572,72 @@ int security_inet_conn_request(struct sock *sk,
}
EXPORT_SYMBOL(security_inet_conn_request);
-static struct list_head hooks_inet_csk_clone;
void security_inet_csk_clone(struct sock *newsk,
const struct request_sock *req)
{
call_void_hook(inet_csk_clone, newsk, req);
}
-static struct list_head hooks_inet_conn_established;
void security_inet_conn_established(struct sock *sk,
struct sk_buff *skb)
{
call_void_hook(inet_conn_established, sk, skb);
}
-static struct list_head hooks_secmark_relabel_packet;
int security_secmark_relabel_packet(u32 secid)
{
return call_int_hook(secmark_relabel_packet, secid);
}
EXPORT_SYMBOL(security_secmark_relabel_packet);
-static struct list_head hooks_secmark_refcount_inc;
void security_secmark_refcount_inc(void)
{
call_void_hook(secmark_refcount_inc);
}
EXPORT_SYMBOL(security_secmark_refcount_inc);
-static struct list_head hooks_secmark_refcount_dec;
void security_secmark_refcount_dec(void)
{
call_void_hook(secmark_refcount_dec);
}
EXPORT_SYMBOL(security_secmark_refcount_dec);
-static struct list_head hooks_tun_dev_alloc_security;
int security_tun_dev_alloc_security(void **security)
{
return call_int_hook(tun_dev_alloc_security, security);
}
EXPORT_SYMBOL(security_tun_dev_alloc_security);
-static struct list_head hooks_tun_dev_free_security;
void security_tun_dev_free_security(void *security)
{
call_void_hook(tun_dev_free_security, security);
}
EXPORT_SYMBOL(security_tun_dev_free_security);
-static struct list_head hooks_tun_dev_create;
int security_tun_dev_create(void)
{
return call_int_hook(tun_dev_create);
}
EXPORT_SYMBOL(security_tun_dev_create);
-static struct list_head hooks_tun_dev_attach_queue;
int security_tun_dev_attach_queue(void *security)
{
return call_int_hook(tun_dev_attach_queue, security);
}
EXPORT_SYMBOL(security_tun_dev_attach_queue);
-static struct list_head hooks_tun_dev_attach;
int security_tun_dev_attach(struct sock *sk, void *security)
{
return call_int_hook(tun_dev_attach, sk, security);
}
EXPORT_SYMBOL(security_tun_dev_attach);
-static struct list_head hooks_tun_dev_open;
int security_tun_dev_open(void *security)
{
return call_int_hook(tun_dev_open, security);
}
EXPORT_SYMBOL(security_tun_dev_open);
-static struct list_head hooks_skb_owned_by;
void security_skb_owned_by(struct sk_buff *skb, struct sock *sk)
{
call_void_hook(skb_owned_by, skb, sk);
@@ -1667,7 +1647,6 @@ void security_skb_owned_by(struct sk_buff *skb, struct sock *sk)
#ifdef CONFIG_SECURITY_NETWORK_XFRM
-static struct list_head hooks_xfrm_policy_alloc_security;
int security_xfrm_policy_alloc(struct xfrm_sec_ctx **ctxp,
struct xfrm_user_sec_ctx *sec_ctx,
gfp_t gfp)
@@ -1676,27 +1655,23 @@ int security_xfrm_policy_alloc(struct xfrm_sec_ctx **ctxp,
}
EXPORT_SYMBOL(security_xfrm_policy_alloc);
-static struct list_head hooks_xfrm_policy_clone_security;
int security_xfrm_policy_clone(struct xfrm_sec_ctx *old_ctx,
struct xfrm_sec_ctx **new_ctxp)
{
return call_int_hook(xfrm_policy_clone_security, old_ctx, new_ctxp);
}
-static struct list_head hooks_xfrm_policy_free_security;
void security_xfrm_policy_free(struct xfrm_sec_ctx *ctx)
{
call_void_hook(xfrm_policy_free_security, ctx);
}
EXPORT_SYMBOL(security_xfrm_policy_free);
-static struct list_head hooks_xfrm_policy_delete_security;
int security_xfrm_policy_delete(struct xfrm_sec_ctx *ctx)
{
return call_int_hook(xfrm_policy_delete_security, ctx);
}
-static struct list_head hooks_xfrm_state_alloc;
int security_xfrm_state_alloc(struct xfrm_state *x,
struct xfrm_user_sec_ctx *sec_ctx)
{
@@ -1704,43 +1679,35 @@ int security_xfrm_state_alloc(struct xfrm_state *x,
}
EXPORT_SYMBOL(security_xfrm_state_alloc);
-static struct list_head hooks_xfrm_state_alloc_acquire;
int security_xfrm_state_alloc_acquire(struct xfrm_state *x,
struct xfrm_sec_ctx *polsec, u32 secid)
{
return call_int_hook(xfrm_state_alloc_acquire, x, polsec, secid);
}
-static struct list_head hooks_xfrm_state_delete_security;
int security_xfrm_state_delete(struct xfrm_state *x)
{
return call_int_hook(xfrm_state_delete_security, x);
}
EXPORT_SYMBOL(security_xfrm_state_delete);
-static struct list_head hooks_xfrm_state_free_security;
void security_xfrm_state_free(struct xfrm_state *x)
{
call_void_hook(xfrm_state_free_security, x);
}
-static struct list_head hooks_xfrm_policy_lookup;
int security_xfrm_policy_lookup(struct xfrm_sec_ctx *ctx, u32 fl_secid, u8 dir)
{
return call_int_hook(xfrm_policy_lookup, ctx, fl_secid, dir);
}
-static struct list_head hooks_xfrm_state_pol_flow_match;
int security_xfrm_state_pol_flow_match(struct xfrm_state *x,
struct xfrm_policy *xp,
const struct flowi *fl)
{
- if (list_empty(&hooks_xfrm_state_pol_flow_match))
- return 1;
- return call_int_hook(xfrm_state_pol_flow_match, x, xp, fl);
+ return call_int_hook_default(1, xfrm_state_pol_flow_match, x, xp, fl);
}
-static struct list_head hooks_xfrm_decode_session;
int security_xfrm_decode_session(struct sk_buff *skb, u32 *secid)
{
return call_int_hook(xfrm_decode_session, skb, secid, 1);
@@ -1763,33 +1730,26 @@ EXPORT_SYMBOL(security_skb_classify_flow);
#ifdef CONFIG_KEYS
-static struct list_head hooks_key_alloc;
int security_key_alloc(struct key *key, const struct cred *cred,
unsigned long flags)
{
return call_int_hook(key_alloc, key, cred, flags);
}
-static struct list_head hooks_key_free;
void security_key_free(struct key *key)
{
call_void_hook(key_free, key);
}
-static struct list_head hooks_key_permission;
int security_key_permission(key_ref_t key_ref,
const struct cred *cred, unsigned perm)
{
return call_int_hook(key_permission, key_ref, cred, perm);
}
-static struct list_head hooks_key_getsecurity;
int security_key_getsecurity(struct key *key, char **_buffer)
{
- if (list_empty(&hooks_key_getsecurity)) {
- *_buffer = NULL;
- return 0;
- }
+ *_buffer = NULL;
return call_int_hook(key_getsecurity, key, _buffer);
}
@@ -1797,25 +1757,21 @@ int security_key_getsecurity(struct key *key, char **_buffer)
#ifdef CONFIG_AUDIT
-static struct list_head hooks_audit_rule_init;
int security_audit_rule_init(u32 field, u32 op, char *rulestr, void **lsmrule)
{
return call_int_hook(audit_rule_init, field, op, rulestr, lsmrule);
}
-static struct list_head hooks_audit_rule_known;
int security_audit_rule_known(struct audit_krule *krule)
{
return call_int_hook(audit_rule_known, krule);
}
-static struct list_head hooks_audit_rule_free;
void security_audit_rule_free(void *lsmrule)
{
call_void_hook(audit_rule_free, lsmrule);
}
-static struct list_head hooks_audit_rule_match;
int security_audit_rule_match(u32 secid, u32 field, u32 op, void *lsmrule,
struct audit_context *actx)
{
@@ -1824,736 +1780,58 @@ int security_audit_rule_match(u32 secid, u32 field, u32 op, void *lsmrule,
#endif /* CONFIG_AUDIT */
-static int __init add_hook_to_list(struct list_head *hooklist,
- void *interesting,
- struct security_operations *sop)
-{
- struct security_hook_list *new;
- struct security_hook_list *shp;
-
- if (hooklist->next == NULL)
- INIT_LIST_HEAD(hooklist);
-
- if (interesting == NULL)
- return 0;
-
- new = kzalloc(sizeof(*new), GFP_KERNEL);
- if (new == NULL)
- return -ENOMEM;
-
- INIT_LIST_HEAD(&new->shl_head);
- new->shl_ops = sop;
-
- shp = list_last_entry(hooklist, struct security_hook_list, shl_head);
- list_add_rcu(&new->shl_head, &shp->shl_head);
-
- return 0;
-}
-
static int __init security_enlist_ops(struct security_operations *sop)
{
- printk(KERN_INFO "Security operations for %s initialized\n", sop->name);
-
- if (add_hook_to_list(&hooks_ptrace_access_check,
- sop->ptrace_access_check, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_ptrace_traceme, sop->ptrace_traceme, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_capget, sop->capget, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_capset, sop->capset, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_capable, sop->capable, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_quotactl, sop->quotactl, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_quota_on, sop->quota_on, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_syslog, sop->syslog, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_settime, sop->settime, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_vm_enough_memory,
- sop->vm_enough_memory, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_bprm_set_creds, sop->bprm_set_creds, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_bprm_committing_creds,
- sop->bprm_committing_creds, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_bprm_committed_creds,
- sop->bprm_committed_creds, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_bprm_check_security,
- sop->bprm_check_security, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_bprm_secureexec, sop->bprm_secureexec, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_sb_alloc_security,
- sop->sb_alloc_security, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_sb_free_security,
- sop->sb_free_security, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_sb_copy_data, sop->sb_copy_data, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_sb_remount, sop->sb_remount, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_sb_kern_mount, sop->sb_kern_mount, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_sb_show_options, sop->sb_show_options, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_sb_statfs, sop->sb_statfs, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_sb_mount, sop->sb_mount, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_sb_umount, sop->sb_umount, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_sb_pivotroot, sop->sb_pivotroot, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_sb_set_mnt_opts, sop->sb_set_mnt_opts, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_sb_clone_mnt_opts,
- sop->sb_clone_mnt_opts, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_sb_parse_opts_str,
- sop->sb_parse_opts_str, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_dentry_init_security,
- sop->dentry_init_security, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_inode_alloc_security,
- sop->inode_alloc_security, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_inode_free_security,
- sop->inode_free_security, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_inode_init_security,
- sop->inode_init_security, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_inode_create, sop->inode_create, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_inode_link, sop->inode_link, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_inode_unlink, sop->inode_unlink, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_inode_symlink, sop->inode_symlink, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_inode_mkdir, sop->inode_mkdir, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_inode_rmdir, sop->inode_rmdir, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_inode_mknod, sop->inode_mknod, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_inode_rename, sop->inode_rename, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_inode_readlink, sop->inode_readlink, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_inode_follow_link,
- sop->inode_follow_link, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_inode_permission,
- sop->inode_permission, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_inode_setattr, sop->inode_setattr, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_inode_getattr, sop->inode_getattr, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_inode_setxattr, sop->inode_setxattr, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_inode_post_setxattr,
- sop->inode_post_setxattr, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_inode_getxattr, sop->inode_getxattr, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_inode_listxattr, sop->inode_listxattr, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_inode_removexattr,
- sop->inode_removexattr, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_inode_need_killpriv,
- sop->inode_need_killpriv, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_inode_killpriv, sop->inode_killpriv, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_inode_getsecurity,
- sop->inode_getsecurity, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_inode_setsecurity,
- sop->inode_setsecurity, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_inode_listsecurity,
- sop->inode_listsecurity, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_inode_getsecid,
- sop->inode_getsecid, sop))
- return -ENOMEM;
-#ifdef CONFIG_SECURITY_PATH
- if (add_hook_to_list(&hooks_path_mknod, sop->path_mknod, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_path_mkdir, sop->path_mkdir, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_path_rmdir, sop->path_rmdir, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_path_unlink, sop->path_unlink, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_path_symlink, sop->path_symlink, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_path_link, sop->path_link, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_path_rename, sop->path_rename, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_path_truncate, sop->path_truncate, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_path_chmod, sop->path_chmod, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_path_chown, sop->path_chown, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_path_chroot, sop->path_chroot, sop))
- return -ENOMEM;
-#endif
- if (add_hook_to_list(&hooks_file_permission, sop->file_permission, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_file_alloc_security,
- sop->file_alloc_security, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_file_free_security,
- sop->file_free_security, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_file_ioctl, sop->file_ioctl, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_mmap_addr, sop->mmap_addr, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_mmap_file, sop->mmap_file, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_file_mprotect, sop->file_mprotect, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_file_lock, sop->file_lock, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_file_fcntl, sop->file_fcntl, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_file_set_fowner, sop->file_set_fowner, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_file_send_sigiotask,
- sop->file_send_sigiotask, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_file_receive, sop->file_receive, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_file_open, sop->file_open, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_task_create, sop->task_create, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_task_free, sop->task_free, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_cred_alloc_blank,
- sop->cred_alloc_blank, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_cred_free, sop->cred_free, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_cred_prepare, sop->cred_prepare, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_cred_transfer, sop->cred_transfer, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_kernel_act_as, sop->kernel_act_as, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_kernel_create_files_as,
- sop->kernel_create_files_as, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_kernel_module_request,
- sop->kernel_module_request, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_kernel_module_from_file,
- sop->kernel_module_from_file, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_task_fix_setuid, sop->task_fix_setuid, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_task_setpgid, sop->task_setpgid, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_task_getpgid, sop->task_getpgid, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_task_getsid, sop->task_getsid, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_task_getsecid, sop->task_getsecid, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_task_setnice, sop->task_setnice, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_task_setioprio, sop->task_setioprio, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_task_getioprio, sop->task_getioprio, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_task_setrlimit, sop->task_setrlimit, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_task_setscheduler,
- sop->task_setscheduler, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_task_getscheduler,
- sop->task_getscheduler, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_task_movememory, sop->task_movememory, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_task_wait, sop->task_wait, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_task_kill, sop->task_kill, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_task_prctl, sop->task_prctl, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_task_to_inode, sop->task_to_inode, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_ipc_permission, sop->ipc_permission, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_ipc_getsecid, sop->ipc_getsecid, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_msg_msg_alloc_security,
- sop->msg_msg_alloc_security, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_msg_msg_free_security,
- sop->msg_msg_free_security, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_msg_queue_alloc_security,
- sop->msg_queue_alloc_security, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_msg_queue_free_security,
- sop->msg_queue_free_security, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_msg_queue_associate,
- sop->msg_queue_associate, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_msg_queue_msgctl,
- sop->msg_queue_msgctl, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_msg_queue_msgsnd,
- sop->msg_queue_msgsnd, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_msg_queue_msgrcv,
- sop->msg_queue_msgrcv, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_shm_alloc_security,
- sop->shm_alloc_security, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_shm_free_security,
- sop->shm_free_security, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_shm_associate, sop->shm_associate, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_shm_shmctl, sop->shm_shmctl, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_shm_shmat, sop->shm_shmat, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_sem_alloc_security,
- sop->sem_alloc_security, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_sem_free_security,
- sop->sem_free_security, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_sem_associate, sop->sem_associate, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_sem_semctl, sop->sem_semctl, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_sem_semop, sop->sem_semop, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_netlink_send, sop->netlink_send, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_d_instantiate, sop->d_instantiate, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_getprocattr, sop->getprocattr, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_setprocattr, sop->setprocattr, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_ismaclabel, sop->ismaclabel, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_secid_to_secctx, sop->secid_to_secctx, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_secctx_to_secid, sop->secctx_to_secid, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_release_secctx, sop->release_secctx, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_inode_notifysecctx,
- sop->inode_notifysecctx, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_inode_setsecctx, sop->inode_setsecctx, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_inode_getsecctx, sop->inode_getsecctx, sop))
- return -ENOMEM;
-#ifdef CONFIG_SECURITY_NETWORK
- if (add_hook_to_list(&hooks_unix_stream_connect,
- sop->unix_stream_connect, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_unix_may_send, sop->unix_may_send, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_socket_create, sop->socket_create, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_socket_post_create,
- sop->socket_post_create, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_socket_bind, sop->socket_bind, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_socket_connect, sop->socket_connect, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_socket_listen, sop->socket_listen, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_socket_accept, sop->socket_accept, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_socket_sendmsg, sop->socket_sendmsg, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_socket_recvmsg, sop->socket_recvmsg, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_socket_getsockname,
- sop->socket_getsockname, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_socket_getpeername,
- sop->socket_getpeername, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_socket_setsockopt,
- sop->socket_setsockopt, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_socket_getsockopt,
- sop->socket_getsockopt, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_socket_shutdown, sop->socket_shutdown, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_socket_sock_rcv_skb,
- sop->socket_sock_rcv_skb, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_socket_getpeersec_stream,
- sop->socket_getpeersec_stream, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_socket_getpeersec_dgram,
- sop->socket_getpeersec_dgram, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_sk_alloc_security,
- sop->sk_alloc_security, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_sk_free_security,
- sop->sk_free_security, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_sk_clone_security,
- sop->sk_clone_security, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_sk_getsecid, sop->sk_getsecid, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_sock_graft, sop->sock_graft, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_inet_conn_request,
- sop->inet_conn_request, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_inet_csk_clone, sop->inet_csk_clone, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_inet_conn_established,
- sop->inet_conn_established, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_secmark_relabel_packet,
- sop->secmark_relabel_packet, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_secmark_refcount_inc,
- sop->secmark_refcount_inc, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_secmark_refcount_dec,
- sop->secmark_refcount_dec, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_req_classify_flow,
- sop->req_classify_flow, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_tun_dev_alloc_security,
- sop->tun_dev_alloc_security, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_tun_dev_free_security,
- sop->tun_dev_free_security, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_tun_dev_create, sop->tun_dev_create, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_tun_dev_open, sop->tun_dev_open, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_tun_dev_attach_queue,
- sop->tun_dev_attach_queue, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_tun_dev_attach, sop->tun_dev_attach, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_skb_owned_by, sop->skb_owned_by, sop))
- return -ENOMEM;
-#endif /* CONFIG_SECURITY_NETWORK */
-#ifdef CONFIG_SECURITY_NETWORK_XFRM
- if (add_hook_to_list(&hooks_xfrm_policy_alloc_security,
- sop->xfrm_policy_alloc_security, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_xfrm_policy_clone_security,
- sop->xfrm_policy_clone_security, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_xfrm_policy_free_security,
- sop->xfrm_policy_free_security, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_xfrm_policy_delete_security,
- sop->xfrm_policy_delete_security, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_xfrm_state_alloc,
- sop->xfrm_state_alloc, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_xfrm_state_alloc_acquire,
- sop->xfrm_state_alloc_acquire, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_xfrm_state_free_security,
- sop->xfrm_state_free_security, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_xfrm_state_delete_security,
- sop->xfrm_state_delete_security, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_xfrm_policy_lookup,
- sop->xfrm_policy_lookup, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_xfrm_state_pol_flow_match,
- sop->xfrm_state_pol_flow_match, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_xfrm_decode_session,
- sop->xfrm_decode_session, sop))
- return -ENOMEM;
-#endif /* CONFIG_SECURITY_NETWORK_XFRM */
-#ifdef CONFIG_KEYS
- if (add_hook_to_list(&hooks_key_alloc, sop->key_alloc, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_key_free, sop->key_free, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_key_permission, sop->key_permission, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_key_getsecurity, sop->key_getsecurity, sop))
- return -ENOMEM;
-#endif /* CONFIG_KEYS */
-#ifdef CONFIG_AUDIT
- if (add_hook_to_list(&hooks_audit_rule_init, sop->audit_rule_init, sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_audit_rule_known, sop->audit_rule_known,
- sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_audit_rule_match, sop->audit_rule_match,
- sop))
- return -ENOMEM;
- if (add_hook_to_list(&hooks_audit_rule_free, sop->audit_rule_free, sop))
+ enum lsm_hooks_index i;
+ int count = 0;
+ struct security_hook_list **new;
+ /*
+ * Optimization by assuming that "enum lsm_hooks_index" indicates
+ * ordering of callback pointers in "struct security_operations" and
+ * ptrace_access_check is the first callback.
+ *
+ * If you change "struct security_operations", you must also change
+ * "enum lsm_hooks_index" accordingly.
+ */
+ void **hooks = (void **) &sop->ptrace_access_check;
+
+ /* How many callbacks are defined? */
+ for (i = 0; i < max_lsm_hooks; i++)
+ if (hooks[i])
+ count++;
+ /* Allocate memory for registering callbacks. */
+ new = kzalloc(sizeof(struct security_hook_list) * count, GFP_KERNEL);
+ if (!new) {
+ printk(KERN_INFO "Failed to initialize security operations for %s\n",
+ sop->name);
return -ENOMEM;
-#endif
+ }
+ /* Assign only defined callbacks. */
+ count = 0;
+ for (i = 0; i < max_lsm_hooks; i++) {
+ if (!hooks[i])
+ continue;
+ new[count]->shl_ops = sop;
+ list_add_tail_rcu(&new[count]->shl_head, &lsm_hooks[i]);
+ count++;
+ }
+ printk(KERN_INFO "Security operations for %s initialized\n", sop->name);
return 0;
}
#ifdef CONFIG_SECURITY_SELINUX_DISABLE
-static void clear_hook_entry(struct list_head *head,
- struct security_operations *sop)
+void security_module_disable(struct security_operations *sop)
{
+ enum lsm_hooks_index i;
struct security_hook_list *shp;
- if (head->next == NULL)
- return;
- if (list_empty(head))
- return;
-
- list_for_each_entry(shp, head, shl_head)
- if (shp->shl_ops == sop) {
- shp->shl_ops = NULL;
- return;
- }
-}
-
-void security_module_disable(struct security_operations *sop)
-{
+ /* Unassign defined callbacks. */
+ for (i = 0; i < max_lsm_hooks; i++)
+ list_for_each_entry(shp, &lsm_hooks[i], shl_head)
+ if (shp->shl_ops == sop) {
+ list_del_rcu(&shp->shl_head);
+ break;
+ }
printk(KERN_INFO "Security operations for %s disabled.\n", sop->name);
- clear_hook_entry(&hooks_ptrace_access_check, sop);
- clear_hook_entry(&hooks_ptrace_traceme, sop);
- clear_hook_entry(&hooks_capget, sop);
- clear_hook_entry(&hooks_capset, sop);
- clear_hook_entry(&hooks_capable, sop);
- clear_hook_entry(&hooks_quotactl, sop);
- clear_hook_entry(&hooks_quota_on, sop);
- clear_hook_entry(&hooks_syslog, sop);
- clear_hook_entry(&hooks_settime, sop);
- clear_hook_entry(&hooks_vm_enough_memory, sop);
- clear_hook_entry(&hooks_bprm_set_creds, sop);
- clear_hook_entry(&hooks_bprm_committing_creds, sop);
- clear_hook_entry(&hooks_bprm_committed_creds, sop);
- clear_hook_entry(&hooks_bprm_check_security, sop);
- clear_hook_entry(&hooks_bprm_secureexec, sop);
- clear_hook_entry(&hooks_sb_alloc_security, sop);
- clear_hook_entry(&hooks_sb_free_security, sop);
- clear_hook_entry(&hooks_sb_copy_data, sop);
- clear_hook_entry(&hooks_sb_remount, sop);
- clear_hook_entry(&hooks_sb_kern_mount, sop);
- clear_hook_entry(&hooks_sb_show_options, sop);
- clear_hook_entry(&hooks_sb_statfs, sop);
- clear_hook_entry(&hooks_sb_mount, sop);
- clear_hook_entry(&hooks_sb_umount, sop);
- clear_hook_entry(&hooks_sb_pivotroot, sop);
- clear_hook_entry(&hooks_sb_set_mnt_opts, sop);
- clear_hook_entry(&hooks_sb_clone_mnt_opts, sop);
- clear_hook_entry(&hooks_sb_parse_opts_str, sop);
- clear_hook_entry(&hooks_dentry_init_security, sop);
- clear_hook_entry(&hooks_inode_alloc_security, sop);
- clear_hook_entry(&hooks_inode_free_security, sop);
- clear_hook_entry(&hooks_inode_init_security, sop);
- clear_hook_entry(&hooks_inode_create, sop);
- clear_hook_entry(&hooks_inode_link, sop);
- clear_hook_entry(&hooks_inode_unlink, sop);
- clear_hook_entry(&hooks_inode_symlink, sop);
- clear_hook_entry(&hooks_inode_mkdir, sop);
- clear_hook_entry(&hooks_inode_rmdir, sop);
- clear_hook_entry(&hooks_inode_mknod, sop);
- clear_hook_entry(&hooks_inode_rename, sop);
- clear_hook_entry(&hooks_inode_readlink, sop);
- clear_hook_entry(&hooks_inode_follow_link, sop);
- clear_hook_entry(&hooks_inode_permission, sop);
- clear_hook_entry(&hooks_inode_setattr, sop);
- clear_hook_entry(&hooks_inode_getattr, sop);
- clear_hook_entry(&hooks_inode_setxattr, sop);
- clear_hook_entry(&hooks_inode_post_setxattr, sop);
- clear_hook_entry(&hooks_inode_getxattr, sop);
- clear_hook_entry(&hooks_inode_listxattr, sop);
- clear_hook_entry(&hooks_inode_removexattr, sop);
- clear_hook_entry(&hooks_inode_need_killpriv, sop);
- clear_hook_entry(&hooks_inode_killpriv, sop);
- clear_hook_entry(&hooks_inode_getsecurity, sop);
- clear_hook_entry(&hooks_inode_setsecurity, sop);
- clear_hook_entry(&hooks_inode_listsecurity, sop);
- clear_hook_entry(&hooks_inode_getsecid, sop);
-#ifdef CONFIG_SECURITY_PATH
- clear_hook_entry(&hooks_path_mknod, sop);
- clear_hook_entry(&hooks_path_mkdir, sop);
- clear_hook_entry(&hooks_path_rmdir, sop);
- clear_hook_entry(&hooks_path_unlink, sop);
- clear_hook_entry(&hooks_path_symlink, sop);
- clear_hook_entry(&hooks_path_link, sop);
- clear_hook_entry(&hooks_path_rename, sop);
- clear_hook_entry(&hooks_path_truncate, sop);
- clear_hook_entry(&hooks_path_chmod, sop);
- clear_hook_entry(&hooks_path_chown, sop);
- clear_hook_entry(&hooks_path_chroot, sop);
-#endif
- clear_hook_entry(&hooks_file_permission, sop);
- clear_hook_entry(&hooks_file_alloc_security, sop);
- clear_hook_entry(&hooks_file_free_security, sop);
- clear_hook_entry(&hooks_file_ioctl, sop);
- clear_hook_entry(&hooks_mmap_addr, sop);
- clear_hook_entry(&hooks_mmap_file, sop);
- clear_hook_entry(&hooks_file_mprotect, sop);
- clear_hook_entry(&hooks_file_lock, sop);
- clear_hook_entry(&hooks_file_fcntl, sop);
- clear_hook_entry(&hooks_file_set_fowner, sop);
- clear_hook_entry(&hooks_file_send_sigiotask, sop);
- clear_hook_entry(&hooks_file_receive, sop);
- clear_hook_entry(&hooks_file_open, sop);
- clear_hook_entry(&hooks_task_create, sop);
- clear_hook_entry(&hooks_task_free, sop);
- clear_hook_entry(&hooks_cred_alloc_blank, sop);
- clear_hook_entry(&hooks_cred_free, sop);
- clear_hook_entry(&hooks_cred_prepare, sop);
- clear_hook_entry(&hooks_cred_transfer, sop);
- clear_hook_entry(&hooks_kernel_act_as, sop);
- clear_hook_entry(&hooks_kernel_create_files_as, sop);
- clear_hook_entry(&hooks_kernel_module_request, sop);
- clear_hook_entry(&hooks_kernel_module_from_file, sop);
- clear_hook_entry(&hooks_task_fix_setuid, sop);
- clear_hook_entry(&hooks_task_setpgid, sop);
- clear_hook_entry(&hooks_task_getpgid, sop);
- clear_hook_entry(&hooks_task_getsid, sop);
- clear_hook_entry(&hooks_task_getsecid, sop);
- clear_hook_entry(&hooks_task_setnice, sop);
- clear_hook_entry(&hooks_task_setioprio, sop);
- clear_hook_entry(&hooks_task_getioprio, sop);
- clear_hook_entry(&hooks_task_setrlimit, sop);
- clear_hook_entry(&hooks_task_setscheduler, sop);
- clear_hook_entry(&hooks_task_getscheduler, sop);
- clear_hook_entry(&hooks_task_movememory, sop);
- clear_hook_entry(&hooks_task_wait, sop);
- clear_hook_entry(&hooks_task_kill, sop);
- clear_hook_entry(&hooks_task_prctl, sop);
- clear_hook_entry(&hooks_task_to_inode, sop);
- clear_hook_entry(&hooks_ipc_permission, sop);
- clear_hook_entry(&hooks_ipc_getsecid, sop);
- clear_hook_entry(&hooks_msg_msg_alloc_security, sop);
- clear_hook_entry(&hooks_msg_msg_free_security, sop);
- clear_hook_entry(&hooks_msg_queue_alloc_security, sop);
- clear_hook_entry(&hooks_msg_queue_free_security, sop);
- clear_hook_entry(&hooks_msg_queue_associate, sop);
- clear_hook_entry(&hooks_msg_queue_msgctl, sop);
- clear_hook_entry(&hooks_msg_queue_msgsnd, sop);
- clear_hook_entry(&hooks_msg_queue_msgrcv, sop);
- clear_hook_entry(&hooks_shm_alloc_security, sop);
- clear_hook_entry(&hooks_shm_free_security, sop);
- clear_hook_entry(&hooks_shm_associate, sop);
- clear_hook_entry(&hooks_shm_shmctl, sop);
- clear_hook_entry(&hooks_shm_shmat, sop);
- clear_hook_entry(&hooks_sem_alloc_security, sop);
- clear_hook_entry(&hooks_sem_free_security, sop);
- clear_hook_entry(&hooks_sem_associate, sop);
- clear_hook_entry(&hooks_sem_semctl, sop);
- clear_hook_entry(&hooks_sem_semop, sop);
- clear_hook_entry(&hooks_netlink_send, sop);
- clear_hook_entry(&hooks_d_instantiate, sop);
- clear_hook_entry(&hooks_getprocattr, sop);
- clear_hook_entry(&hooks_setprocattr, sop);
- clear_hook_entry(&hooks_ismaclabel, sop);
- clear_hook_entry(&hooks_secid_to_secctx, sop);
- clear_hook_entry(&hooks_secctx_to_secid, sop);
- clear_hook_entry(&hooks_release_secctx, sop);
- clear_hook_entry(&hooks_inode_notifysecctx, sop);
- clear_hook_entry(&hooks_inode_setsecctx, sop);
- clear_hook_entry(&hooks_inode_getsecctx, sop);
-#ifdef CONFIG_SECURITY_NETWORK
- clear_hook_entry(&hooks_unix_stream_connect, sop);
- clear_hook_entry(&hooks_unix_may_send, sop);
- clear_hook_entry(&hooks_socket_create, sop);
- clear_hook_entry(&hooks_socket_post_create, sop);
- clear_hook_entry(&hooks_socket_bind, sop);
- clear_hook_entry(&hooks_socket_connect, sop);
- clear_hook_entry(&hooks_socket_listen, sop);
- clear_hook_entry(&hooks_socket_accept, sop);
- clear_hook_entry(&hooks_socket_sendmsg, sop);
- clear_hook_entry(&hooks_socket_recvmsg, sop);
- clear_hook_entry(&hooks_socket_getsockname, sop);
- clear_hook_entry(&hooks_socket_getpeername, sop);
- clear_hook_entry(&hooks_socket_setsockopt, sop);
- clear_hook_entry(&hooks_socket_getsockopt, sop);
- clear_hook_entry(&hooks_socket_shutdown, sop);
- clear_hook_entry(&hooks_socket_sock_rcv_skb, sop);
- clear_hook_entry(&hooks_socket_getpeersec_stream, sop);
- clear_hook_entry(&hooks_socket_getpeersec_dgram, sop);
- clear_hook_entry(&hooks_sk_alloc_security, sop);
- clear_hook_entry(&hooks_sk_free_security, sop);
- clear_hook_entry(&hooks_sk_clone_security, sop);
- clear_hook_entry(&hooks_sk_getsecid, sop);
- clear_hook_entry(&hooks_sock_graft, sop);
- clear_hook_entry(&hooks_inet_conn_request, sop);
- clear_hook_entry(&hooks_inet_csk_clone, sop);
- clear_hook_entry(&hooks_inet_conn_established, sop);
- clear_hook_entry(&hooks_secmark_relabel_packet, sop);
- clear_hook_entry(&hooks_secmark_refcount_inc, sop);
- clear_hook_entry(&hooks_secmark_refcount_dec, sop);
- clear_hook_entry(&hooks_req_classify_flow, sop);
- clear_hook_entry(&hooks_tun_dev_alloc_security, sop);
- clear_hook_entry(&hooks_tun_dev_free_security, sop);
- clear_hook_entry(&hooks_tun_dev_create, sop);
- clear_hook_entry(&hooks_tun_dev_open, sop);
- clear_hook_entry(&hooks_tun_dev_attach_queue, sop);
- clear_hook_entry(&hooks_tun_dev_attach, sop);
- clear_hook_entry(&hooks_skb_owned_by, sop);
-#endif /* CONFIG_SECURITY_NETWORK */
-#ifdef CONFIG_SECURITY_NETWORK_XFRM
- clear_hook_entry(&hooks_xfrm_policy_alloc_security, sop);
- clear_hook_entry(&hooks_xfrm_policy_clone_security, sop);
- clear_hook_entry(&hooks_xfrm_policy_free_security, sop);
- clear_hook_entry(&hooks_xfrm_policy_delete_security, sop);
- clear_hook_entry(&hooks_xfrm_state_alloc, sop);
- clear_hook_entry(&hooks_xfrm_state_alloc_acquire, sop);
- clear_hook_entry(&hooks_xfrm_state_free_security, sop);
- clear_hook_entry(&hooks_xfrm_state_delete_security, sop);
- clear_hook_entry(&hooks_xfrm_policy_lookup, sop);
- clear_hook_entry(&hooks_xfrm_state_pol_flow_match, sop);
- clear_hook_entry(&hooks_xfrm_decode_session, sop);
-#endif /* CONFIG_SECURITY_NETWORK_XFRM */
-#ifdef CONFIG_KEYS
- clear_hook_entry(&hooks_key_alloc, sop);
- clear_hook_entry(&hooks_key_free, sop);
- clear_hook_entry(&hooks_key_permission, sop);
- clear_hook_entry(&hooks_key_getsecurity, sop);
-#endif /* CONFIG_KEYS */
-#ifdef CONFIG_AUDIT
- clear_hook_entry(&hooks_audit_rule_init, sop);
- clear_hook_entry(&hooks_audit_rule_known, sop);
- clear_hook_entry(&hooks_audit_rule_match, sop);
- clear_hook_entry(&hooks_audit_rule_free, sop);
-#endif
}
#endif /* CONFIG_SECURITY_SELINUX_DISABLE */
--
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
the body of a message to ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Tetsuo Handa
2014-10-22 13:44:42 UTC
Permalink
Post by Casey Schaufler
I'm on holiday and won't be able to reply until after September 15th. I
don't like the array of lists. I prefer the variable per hook because
when we actually get around to stacking some hooks may need a no list,
or a different kind of list.
In the future versions some hooks might not require their corresponding
list, but I was not able to find code in v17 where use of the array of
lists breaks something. What is wrong with leaving potentially unused
few list elements declared and initialized as empty?
Post by Casey Schaufler
Post by Tetsuo Handa
Post by Tetsuo Handa
Comments from thread-safety point of view for runtime-unregistration.
Here is an only compile tested patch which reflected some of my comments.
security/security.c | 1324 +++++++++++++------------------------------------------------
1 file changed, 301 insertions(+), 1023 deletions(-)
--
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
the body of a message to ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Casey Schaufler
2014-10-23 21:19:00 UTC
Permalink
Post by Tetsuo Handa
Post by Casey Schaufler
I'm on holiday and won't be able to reply until after September 15th. I
don't like the array of lists. I prefer the variable per hook because
when we actually get around to stacking some hooks may need a no list,
or a different kind of list.
In the future versions some hooks might not require their corresponding
list, but I was not able to find code in v17 where use of the array of
lists breaks something. What is wrong with leaving potentially unused
few list elements declared and initialized as empty?
There is nothing wrong with the array of lists approach, but I
think the individual variables result in code that is easier to
work with. The array makes the disabling code simpler, but it
adds a bit more complexity that you have to understand if you
are going to work on hooks. I did v16 in the array style, and
I never cottoned to the parallel enum for each hook. There is
probably a clever way to get the index from the security_ops
structure, but that is more clever than is needed. Unless there
is a performance reason, I'd prefer to stick with the individual
list variables.
Post by Tetsuo Handa
Post by Casey Schaufler
Post by Tetsuo Handa
Post by Tetsuo Handa
Comments from thread-safety point of view for runtime-unregistration.
Here is an only compile tested patch which reflected some of my comments.
security/security.c | 1324 +++++++++++++------------------------------------------------
1 file changed, 301 insertions(+), 1023 deletions(-)
--
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
More majordomo info at http://vger.kernel.org/majordomo-info.html
--
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
the body of a message to ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Casey Schaufler
2014-08-08 20:00:36 UTC
Permalink
Subject: [PATCH v16 3/4] LSM: Remove the unnecessary security/capability.c

As nothing in security/capabiliy.c is used any longer the
file can be safely removed. This isn't done in the 2/4 patch
because it makes the patch file too large for mail lists.

Signed-off-by: Casey Schaufler <***@schaufler-ca.com>

---
security/capability.c | 1131 -------------------------------------------------
1 file changed, 1131 deletions(-)

diff --git a/security/capability.c b/security/capability.c
deleted file mode 100644
index e76373d..0000000
--- a/security/capability.c
+++ /dev/null
@@ -1,1131 +0,0 @@
-/*
- * Capabilities Linux Security Module
- *
- * This is the default security module in case no other module is loaded.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- */
-
-#include <linux/security.h>
-
-static int cap_syslog(int type)
-{
- return 0;
-}
-
-static int cap_quotactl(int cmds, int type, int id, struct super_block *sb)
-{
- return 0;
-}
-
-static int cap_quota_on(struct dentry *dentry)
-{
- return 0;
-}
-
-static int cap_bprm_check_security(struct linux_binprm *bprm)
-{
- return 0;
-}
-
-static void cap_bprm_committing_creds(struct linux_binprm *bprm)
-{
-}
-
-static void cap_bprm_committed_creds(struct linux_binprm *bprm)
-{
-}
-
-static int cap_sb_alloc_security(struct super_block *sb)
-{
- return 0;
-}
-
-static void cap_sb_free_security(struct super_block *sb)
-{
-}
-
-static int cap_sb_copy_data(char *orig, char *copy)
-{
- return 0;
-}
-
-static int cap_sb_remount(struct super_block *sb, void *data)
-{
- return 0;
-}
-
-static int cap_sb_kern_mount(struct super_block *sb, int flags, void *data)
-{
- return 0;
-}
-
-static int cap_sb_show_options(struct seq_file *m, struct super_block *sb)
-{
- return 0;
-}
-
-static int cap_sb_statfs(struct dentry *dentry)
-{
- return 0;
-}
-
-static int cap_sb_mount(const char *dev_name, struct path *path,
- const char *type, unsigned long flags, void *data)
-{
- return 0;
-}
-
-static int cap_sb_umount(struct vfsmount *mnt, int flags)
-{
- return 0;
-}
-
-static int cap_sb_pivotroot(struct path *old_path, struct path *new_path)
-{
- return 0;
-}
-
-static int cap_sb_set_mnt_opts(struct super_block *sb,
- struct security_mnt_opts *opts,
- unsigned long kern_flags,
- unsigned long *set_kern_flags)
-
-{
- if (unlikely(opts->num_mnt_opts))
- return -EOPNOTSUPP;
- return 0;
-}
-
-static int cap_sb_clone_mnt_opts(const struct super_block *oldsb,
- struct super_block *newsb)
-{
- return 0;
-}
-
-static int cap_sb_parse_opts_str(char *options, struct security_mnt_opts *opts)
-{
- return 0;
-}
-
-static int cap_dentry_init_security(struct dentry *dentry, int mode,
- struct qstr *name, void **ctx,
- u32 *ctxlen)
-{
- return -EOPNOTSUPP;
-}
-
-static int cap_inode_alloc_security(struct inode *inode)
-{
- return 0;
-}
-
-static void cap_inode_free_security(struct inode *inode)
-{
-}
-
-static int cap_inode_init_security(struct inode *inode, struct inode *dir,
- const struct qstr *qstr, const char **name,
- void **value, size_t *len)
-{
- return -EOPNOTSUPP;
-}
-
-static int cap_inode_create(struct inode *inode, struct dentry *dentry,
- umode_t mask)
-{
- return 0;
-}
-
-static int cap_inode_link(struct dentry *old_dentry, struct inode *inode,
- struct dentry *new_dentry)
-{
- return 0;
-}
-
-static int cap_inode_unlink(struct inode *inode, struct dentry *dentry)
-{
- return 0;
-}
-
-static int cap_inode_symlink(struct inode *inode, struct dentry *dentry,
- const char *name)
-{
- return 0;
-}
-
-static int cap_inode_mkdir(struct inode *inode, struct dentry *dentry,
- umode_t mask)
-{
- return 0;
-}
-
-static int cap_inode_rmdir(struct inode *inode, struct dentry *dentry)
-{
- return 0;
-}
-
-static int cap_inode_mknod(struct inode *inode, struct dentry *dentry,
- umode_t mode, dev_t dev)
-{
- return 0;
-}
-
-static int cap_inode_rename(struct inode *old_inode, struct dentry *old_dentry,
- struct inode *new_inode, struct dentry *new_dentry)
-{
- return 0;
-}
-
-static int cap_inode_readlink(struct dentry *dentry)
-{
- return 0;
-}
-
-static int cap_inode_follow_link(struct dentry *dentry,
- struct nameidata *nameidata)
-{
- return 0;
-}
-
-static int cap_inode_permission(struct inode *inode, int mask)
-{
- return 0;
-}
-
-static int cap_inode_setattr(struct dentry *dentry, struct iattr *iattr)
-{
- return 0;
-}
-
-static int cap_inode_getattr(struct vfsmount *mnt, struct dentry *dentry)
-{
- return 0;
-}
-
-static void cap_inode_post_setxattr(struct dentry *dentry, const char *name,
- const void *value, size_t size, int flags)
-{
-}
-
-static int cap_inode_getxattr(struct dentry *dentry, const char *name)
-{
- return 0;
-}
-
-static int cap_inode_listxattr(struct dentry *dentry)
-{
- return 0;
-}
-
-static int cap_inode_getsecurity(const struct inode *inode, const char *name,
- void **buffer, bool alloc)
-{
- return -EOPNOTSUPP;
-}
-
-static int cap_inode_setsecurity(struct inode *inode, const char *name,
- const void *value, size_t size, int flags)
-{
- return -EOPNOTSUPP;
-}
-
-static int cap_inode_listsecurity(struct inode *inode, char *buffer,
- size_t buffer_size)
-{
- return 0;
-}
-
-static void cap_inode_getsecid(const struct inode *inode, u32 *secid)
-{
- *secid = 0;
-}
-
-#ifdef CONFIG_SECURITY_PATH
-static int cap_path_mknod(struct path *dir, struct dentry *dentry, umode_t mode,
- unsigned int dev)
-{
- return 0;
-}
-
-static int cap_path_mkdir(struct path *dir, struct dentry *dentry, umode_t mode)
-{
- return 0;
-}
-
-static int cap_path_rmdir(struct path *dir, struct dentry *dentry)
-{
- return 0;
-}
-
-static int cap_path_unlink(struct path *dir, struct dentry *dentry)
-{
- return 0;
-}
-
-static int cap_path_symlink(struct path *dir, struct dentry *dentry,
- const char *old_name)
-{
- return 0;
-}
-
-static int cap_path_link(struct dentry *old_dentry, struct path *new_dir,
- struct dentry *new_dentry)
-{
- return 0;
-}
-
-static int cap_path_rename(struct path *old_path, struct dentry *old_dentry,
- struct path *new_path, struct dentry *new_dentry)
-{
- return 0;
-}
-
-static int cap_path_truncate(struct path *path)
-{
- return 0;
-}
-
-static int cap_path_chmod(struct path *path, umode_t mode)
-{
- return 0;
-}
-
-static int cap_path_chown(struct path *path, kuid_t uid, kgid_t gid)
-{
- return 0;
-}
-
-static int cap_path_chroot(struct path *root)
-{
- return 0;
-}
-#endif
-
-static int cap_file_permission(struct file *file, int mask)
-{
- return 0;
-}
-
-static int cap_file_alloc_security(struct file *file)
-{
- return 0;
-}
-
-static void cap_file_free_security(struct file *file)
-{
-}
-
-static int cap_file_ioctl(struct file *file, unsigned int command,
- unsigned long arg)
-{
- return 0;
-}
-
-static int cap_file_mprotect(struct vm_area_struct *vma, unsigned long reqprot,
- unsigned long prot)
-{
- return 0;
-}
-
-static int cap_file_lock(struct file *file, unsigned int cmd)
-{
- return 0;
-}
-
-static int cap_file_fcntl(struct file *file, unsigned int cmd,
- unsigned long arg)
-{
- return 0;
-}
-
-static int cap_file_set_fowner(struct file *file)
-{
- return 0;
-}
-
-static int cap_file_send_sigiotask(struct task_struct *tsk,
- struct fown_struct *fown, int sig)
-{
- return 0;
-}
-
-static int cap_file_receive(struct file *file)
-{
- return 0;
-}
-
-static int cap_file_open(struct file *file, const struct cred *cred)
-{
- return 0;
-}
-
-static int cap_task_create(unsigned long clone_flags)
-{
- return 0;
-}
-
-static void cap_task_free(struct task_struct *task)
-{
-}
-
-static int cap_cred_alloc_blank(struct cred *cred, gfp_t gfp)
-{
- return 0;
-}
-
-static void cap_cred_free(struct cred *cred)
-{
-}
-
-static int cap_cred_prepare(struct cred *new, const struct cred *old, gfp_t gfp)
-{
- return 0;
-}
-
-static void cap_cred_transfer(struct cred *new, const struct cred *old)
-{
-}
-
-static int cap_kernel_act_as(struct cred *new, u32 secid)
-{
- return 0;
-}
-
-static int cap_kernel_create_files_as(struct cred *new, struct inode *inode)
-{
- return 0;
-}
-
-static int cap_kernel_module_request(char *kmod_name)
-{
- return 0;
-}
-
-static int cap_kernel_module_from_file(struct file *file)
-{
- return 0;
-}
-
-static int cap_task_setpgid(struct task_struct *p, pid_t pgid)
-{
- return 0;
-}
-
-static int cap_task_getpgid(struct task_struct *p)
-{
- return 0;
-}
-
-static int cap_task_getsid(struct task_struct *p)
-{
- return 0;
-}
-
-static void cap_task_getsecid(struct task_struct *p, u32 *secid)
-{
- *secid = 0;
-}
-
-static int cap_task_getioprio(struct task_struct *p)
-{
- return 0;
-}
-
-static int cap_task_setrlimit(struct task_struct *p, unsigned int resource,
- struct rlimit *new_rlim)
-{
- return 0;
-}
-
-static int cap_task_getscheduler(struct task_struct *p)
-{
- return 0;
-}
-
-static int cap_task_movememory(struct task_struct *p)
-{
- return 0;
-}
-
-static int cap_task_wait(struct task_struct *p)
-{
- return 0;
-}
-
-static int cap_task_kill(struct task_struct *p, struct siginfo *info,
- int sig, u32 secid)
-{
- return 0;
-}
-
-static void cap_task_to_inode(struct task_struct *p, struct inode *inode)
-{
-}
-
-static int cap_ipc_permission(struct kern_ipc_perm *ipcp, short flag)
-{
- return 0;
-}
-
-static void cap_ipc_getsecid(struct kern_ipc_perm *ipcp, u32 *secid)
-{
- *secid = 0;
-}
-
-static int cap_msg_msg_alloc_security(struct msg_msg *msg)
-{
- return 0;
-}
-
-static void cap_msg_msg_free_security(struct msg_msg *msg)
-{
-}
-
-static int cap_msg_queue_alloc_security(struct msg_queue *msq)
-{
- return 0;
-}
-
-static void cap_msg_queue_free_security(struct msg_queue *msq)
-{
-}
-
-static int cap_msg_queue_associate(struct msg_queue *msq, int msqflg)
-{
- return 0;
-}
-
-static int cap_msg_queue_msgctl(struct msg_queue *msq, int cmd)
-{
- return 0;
-}
-
-static int cap_msg_queue_msgsnd(struct msg_queue *msq, struct msg_msg *msg,
- int msgflg)
-{
- return 0;
-}
-
-static int cap_msg_queue_msgrcv(struct msg_queue *msq, struct msg_msg *msg,
- struct task_struct *target, long type, int mode)
-{
- return 0;
-}
-
-static int cap_shm_alloc_security(struct shmid_kernel *shp)
-{
- return 0;
-}
-
-static void cap_shm_free_security(struct shmid_kernel *shp)
-{
-}
-
-static int cap_shm_associate(struct shmid_kernel *shp, int shmflg)
-{
- return 0;
-}
-
-static int cap_shm_shmctl(struct shmid_kernel *shp, int cmd)
-{
- return 0;
-}
-
-static int cap_shm_shmat(struct shmid_kernel *shp, char __user *shmaddr,
- int shmflg)
-{
- return 0;
-}
-
-static int cap_sem_alloc_security(struct sem_array *sma)
-{
- return 0;
-}
-
-static void cap_sem_free_security(struct sem_array *sma)
-{
-}
-
-static int cap_sem_associate(struct sem_array *sma, int semflg)
-{
- return 0;
-}
-
-static int cap_sem_semctl(struct sem_array *sma, int cmd)
-{
- return 0;
-}
-
-static int cap_sem_semop(struct sem_array *sma, struct sembuf *sops,
- unsigned nsops, int alter)
-{
- return 0;
-}
-
-#ifdef CONFIG_SECURITY_NETWORK
-static int cap_unix_stream_connect(struct sock *sock, struct sock *other,
- struct sock *newsk)
-{
- return 0;
-}
-
-static int cap_unix_may_send(struct socket *sock, struct socket *other)
-{
- return 0;
-}
-
-static int cap_socket_create(int family, int type, int protocol, int kern)
-{
- return 0;
-}
-
-static int cap_socket_post_create(struct socket *sock, int family, int type,
- int protocol, int kern)
-{
- return 0;
-}
-
-static int cap_socket_bind(struct socket *sock, struct sockaddr *address,
- int addrlen)
-{
- return 0;
-}
-
-static int cap_socket_connect(struct socket *sock, struct sockaddr *address,
- int addrlen)
-{
- return 0;
-}
-
-static int cap_socket_listen(struct socket *sock, int backlog)
-{
- return 0;
-}
-
-static int cap_socket_accept(struct socket *sock, struct socket *newsock)
-{
- return 0;
-}
-
-static int cap_socket_sendmsg(struct socket *sock, struct msghdr *msg, int size)
-{
- return 0;
-}
-
-static int cap_socket_recvmsg(struct socket *sock, struct msghdr *msg,
- int size, int flags)
-{
- return 0;
-}
-
-static int cap_socket_getsockname(struct socket *sock)
-{
- return 0;
-}
-
-static int cap_socket_getpeername(struct socket *sock)
-{
- return 0;
-}
-
-static int cap_socket_setsockopt(struct socket *sock, int level, int optname)
-{
- return 0;
-}
-
-static int cap_socket_getsockopt(struct socket *sock, int level, int optname)
-{
- return 0;
-}
-
-static int cap_socket_shutdown(struct socket *sock, int how)
-{
- return 0;
-}
-
-static int cap_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
-{
- return 0;
-}
-
-static int cap_socket_getpeersec_stream(struct socket *sock,
- char __user *optval,
- int __user *optlen, unsigned len)
-{
- return -ENOPROTOOPT;
-}
-
-static int cap_socket_getpeersec_dgram(struct socket *sock,
- struct sk_buff *skb, u32 *secid)
-{
- return -ENOPROTOOPT;
-}
-
-static int cap_sk_alloc_security(struct sock *sk, int family, gfp_t priority)
-{
- return 0;
-}
-
-static void cap_sk_free_security(struct sock *sk)
-{
-}
-
-static void cap_sk_clone_security(const struct sock *sk, struct sock *newsk)
-{
-}
-
-static void cap_sk_getsecid(struct sock *sk, u32 *secid)
-{
-}
-
-static void cap_sock_graft(struct sock *sk, struct socket *parent)
-{
-}
-
-static int cap_inet_conn_request(struct sock *sk, struct sk_buff *skb,
- struct request_sock *req)
-{
- return 0;
-}
-
-static void cap_inet_csk_clone(struct sock *newsk,
- const struct request_sock *req)
-{
-}
-
-static void cap_inet_conn_established(struct sock *sk, struct sk_buff *skb)
-{
-}
-
-static int cap_secmark_relabel_packet(u32 secid)
-{
- return 0;
-}
-
-static void cap_secmark_refcount_inc(void)
-{
-}
-
-static void cap_secmark_refcount_dec(void)
-{
-}
-
-static void cap_req_classify_flow(const struct request_sock *req,
- struct flowi *fl)
-{
-}
-
-static int cap_tun_dev_alloc_security(void **security)
-{
- return 0;
-}
-
-static void cap_tun_dev_free_security(void *security)
-{
-}
-
-static int cap_tun_dev_create(void)
-{
- return 0;
-}
-
-static int cap_tun_dev_attach_queue(void *security)
-{
- return 0;
-}
-
-static int cap_tun_dev_attach(struct sock *sk, void *security)
-{
- return 0;
-}
-
-static int cap_tun_dev_open(void *security)
-{
- return 0;
-}
-
-static void cap_skb_owned_by(struct sk_buff *skb, struct sock *sk)
-{
-}
-
-#endif /* CONFIG_SECURITY_NETWORK */
-
-#ifdef CONFIG_SECURITY_NETWORK_XFRM
-static int cap_xfrm_policy_alloc_security(struct xfrm_sec_ctx **ctxp,
- struct xfrm_user_sec_ctx *sec_ctx,
- gfp_t gfp)
-{
- return 0;
-}
-
-static int cap_xfrm_policy_clone_security(struct xfrm_sec_ctx *old_ctx,
- struct xfrm_sec_ctx **new_ctxp)
-{
- return 0;
-}
-
-static void cap_xfrm_policy_free_security(struct xfrm_sec_ctx *ctx)
-{
-}
-
-static int cap_xfrm_policy_delete_security(struct xfrm_sec_ctx *ctx)
-{
- return 0;
-}
-
-static int cap_xfrm_state_alloc(struct xfrm_state *x,
- struct xfrm_user_sec_ctx *sec_ctx)
-{
- return 0;
-}
-
-static int cap_xfrm_state_alloc_acquire(struct xfrm_state *x,
- struct xfrm_sec_ctx *polsec,
- u32 secid)
-{
- return 0;
-}
-
-static void cap_xfrm_state_free_security(struct xfrm_state *x)
-{
-}
-
-static int cap_xfrm_state_delete_security(struct xfrm_state *x)
-{
- return 0;
-}
-
-static int cap_xfrm_policy_lookup(struct xfrm_sec_ctx *ctx, u32 sk_sid, u8 dir)
-{
- return 0;
-}
-
-static int cap_xfrm_state_pol_flow_match(struct xfrm_state *x,
- struct xfrm_policy *xp,
- const struct flowi *fl)
-{
- return 1;
-}
-
-static int cap_xfrm_decode_session(struct sk_buff *skb, u32 *fl, int ckall)
-{
- return 0;
-}
-
-#endif /* CONFIG_SECURITY_NETWORK_XFRM */
-static void cap_d_instantiate(struct dentry *dentry, struct inode *inode)
-{
-}
-
-static int cap_getprocattr(struct task_struct *p, char *name, char **value)
-{
- return -EINVAL;
-}
-
-static int cap_setprocattr(struct task_struct *p, char *name, void *value,
- size_t size)
-{
- return -EINVAL;
-}
-
-static int cap_ismaclabel(const char *name)
-{
- return 0;
-}
-
-static int cap_secid_to_secctx(u32 secid, char **secdata, u32 *seclen)
-{
- return -EOPNOTSUPP;
-}
-
-static int cap_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid)
-{
- *secid = 0;
- return 0;
-}
-
-static void cap_release_secctx(char *secdata, u32 seclen)
-{
-}
-
-static int cap_inode_notifysecctx(struct inode *inode, void *ctx, u32 ctxlen)
-{
- return 0;
-}
-
-static int cap_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen)
-{
- return 0;
-}
-
-static int cap_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen)
-{
- return -EOPNOTSUPP;
-}
-#ifdef CONFIG_KEYS
-static int cap_key_alloc(struct key *key, const struct cred *cred,
- unsigned long flags)
-{
- return 0;
-}
-
-static void cap_key_free(struct key *key)
-{
-}
-
-static int cap_key_permission(key_ref_t key_ref, const struct cred *cred,
- unsigned perm)
-{
- return 0;
-}
-
-static int cap_key_getsecurity(struct key *key, char **_buffer)
-{
- *_buffer = NULL;
- return 0;
-}
-
-#endif /* CONFIG_KEYS */
-
-#ifdef CONFIG_AUDIT
-static int cap_audit_rule_init(u32 field, u32 op, char *rulestr, void **lsmrule)
-{
- return 0;
-}
-
-static int cap_audit_rule_known(struct audit_krule *krule)
-{
- return 0;
-}
-
-static int cap_audit_rule_match(u32 secid, u32 field, u32 op, void *lsmrule,
- struct audit_context *actx)
-{
- return 0;
-}
-
-static void cap_audit_rule_free(void *lsmrule)
-{
-}
-#endif /* CONFIG_AUDIT */
-
-#define set_to_cap_if_null(ops, function) \
- do { \
- if (!ops->function) { \
- ops->function = cap_##function; \
- pr_debug("Had to override the " #function \
- " security operation with the default.\n");\
- } \
- } while (0)
-
-void __init security_fixup_ops(struct security_operations *ops)
-{
- set_to_cap_if_null(ops, ptrace_access_check);
- set_to_cap_if_null(ops, ptrace_traceme);
- set_to_cap_if_null(ops, capget);
- set_to_cap_if_null(ops, capset);
- set_to_cap_if_null(ops, capable);
- set_to_cap_if_null(ops, quotactl);
- set_to_cap_if_null(ops, quota_on);
- set_to_cap_if_null(ops, syslog);
- set_to_cap_if_null(ops, settime);
- set_to_cap_if_null(ops, vm_enough_memory);
- set_to_cap_if_null(ops, bprm_set_creds);
- set_to_cap_if_null(ops, bprm_committing_creds);
- set_to_cap_if_null(ops, bprm_committed_creds);
- set_to_cap_if_null(ops, bprm_check_security);
- set_to_cap_if_null(ops, bprm_secureexec);
- set_to_cap_if_null(ops, sb_alloc_security);
- set_to_cap_if_null(ops, sb_free_security);
- set_to_cap_if_null(ops, sb_copy_data);
- set_to_cap_if_null(ops, sb_remount);
- set_to_cap_if_null(ops, sb_kern_mount);
- set_to_cap_if_null(ops, sb_show_options);
- set_to_cap_if_null(ops, sb_statfs);
- set_to_cap_if_null(ops, sb_mount);
- set_to_cap_if_null(ops, sb_umount);
- set_to_cap_if_null(ops, sb_pivotroot);
- set_to_cap_if_null(ops, sb_set_mnt_opts);
- set_to_cap_if_null(ops, sb_clone_mnt_opts);
- set_to_cap_if_null(ops, sb_parse_opts_str);
- set_to_cap_if_null(ops, dentry_init_security);
- set_to_cap_if_null(ops, inode_alloc_security);
- set_to_cap_if_null(ops, inode_free_security);
- set_to_cap_if_null(ops, inode_init_security);
- set_to_cap_if_null(ops, inode_create);
- set_to_cap_if_null(ops, inode_link);
- set_to_cap_if_null(ops, inode_unlink);
- set_to_cap_if_null(ops, inode_symlink);
- set_to_cap_if_null(ops, inode_mkdir);
- set_to_cap_if_null(ops, inode_rmdir);
- set_to_cap_if_null(ops, inode_mknod);
- set_to_cap_if_null(ops, inode_rename);
- set_to_cap_if_null(ops, inode_readlink);
- set_to_cap_if_null(ops, inode_follow_link);
- set_to_cap_if_null(ops, inode_permission);
- set_to_cap_if_null(ops, inode_setattr);
- set_to_cap_if_null(ops, inode_getattr);
- set_to_cap_if_null(ops, inode_setxattr);
- set_to_cap_if_null(ops, inode_post_setxattr);
- set_to_cap_if_null(ops, inode_getxattr);
- set_to_cap_if_null(ops, inode_listxattr);
- set_to_cap_if_null(ops, inode_removexattr);
- set_to_cap_if_null(ops, inode_need_killpriv);
- set_to_cap_if_null(ops, inode_killpriv);
- set_to_cap_if_null(ops, inode_getsecurity);
- set_to_cap_if_null(ops, inode_setsecurity);
- set_to_cap_if_null(ops, inode_listsecurity);
- set_to_cap_if_null(ops, inode_getsecid);
-#ifdef CONFIG_SECURITY_PATH
- set_to_cap_if_null(ops, path_mknod);
- set_to_cap_if_null(ops, path_mkdir);
- set_to_cap_if_null(ops, path_rmdir);
- set_to_cap_if_null(ops, path_unlink);
- set_to_cap_if_null(ops, path_symlink);
- set_to_cap_if_null(ops, path_link);
- set_to_cap_if_null(ops, path_rename);
- set_to_cap_if_null(ops, path_truncate);
- set_to_cap_if_null(ops, path_chmod);
- set_to_cap_if_null(ops, path_chown);
- set_to_cap_if_null(ops, path_chroot);
-#endif
- set_to_cap_if_null(ops, file_permission);
- set_to_cap_if_null(ops, file_alloc_security);
- set_to_cap_if_null(ops, file_free_security);
- set_to_cap_if_null(ops, file_ioctl);
- set_to_cap_if_null(ops, mmap_addr);
- set_to_cap_if_null(ops, mmap_file);
- set_to_cap_if_null(ops, file_mprotect);
- set_to_cap_if_null(ops, file_lock);
- set_to_cap_if_null(ops, file_fcntl);
- set_to_cap_if_null(ops, file_set_fowner);
- set_to_cap_if_null(ops, file_send_sigiotask);
- set_to_cap_if_null(ops, file_receive);
- set_to_cap_if_null(ops, file_open);
- set_to_cap_if_null(ops, task_create);
- set_to_cap_if_null(ops, task_free);
- set_to_cap_if_null(ops, cred_alloc_blank);
- set_to_cap_if_null(ops, cred_free);
- set_to_cap_if_null(ops, cred_prepare);
- set_to_cap_if_null(ops, cred_transfer);
- set_to_cap_if_null(ops, kernel_act_as);
- set_to_cap_if_null(ops, kernel_create_files_as);
- set_to_cap_if_null(ops, kernel_module_request);
- set_to_cap_if_null(ops, kernel_module_from_file);
- set_to_cap_if_null(ops, task_fix_setuid);
- set_to_cap_if_null(ops, task_setpgid);
- set_to_cap_if_null(ops, task_getpgid);
- set_to_cap_if_null(ops, task_getsid);
- set_to_cap_if_null(ops, task_getsecid);
- set_to_cap_if_null(ops, task_setnice);
- set_to_cap_if_null(ops, task_setioprio);
- set_to_cap_if_null(ops, task_getioprio);
- set_to_cap_if_null(ops, task_setrlimit);
- set_to_cap_if_null(ops, task_setscheduler);
- set_to_cap_if_null(ops, task_getscheduler);
- set_to_cap_if_null(ops, task_movememory);
- set_to_cap_if_null(ops, task_wait);
- set_to_cap_if_null(ops, task_kill);
- set_to_cap_if_null(ops, task_prctl);
- set_to_cap_if_null(ops, task_to_inode);
- set_to_cap_if_null(ops, ipc_permission);
- set_to_cap_if_null(ops, ipc_getsecid);
- set_to_cap_if_null(ops, msg_msg_alloc_security);
- set_to_cap_if_null(ops, msg_msg_free_security);
- set_to_cap_if_null(ops, msg_queue_alloc_security);
- set_to_cap_if_null(ops, msg_queue_free_security);
- set_to_cap_if_null(ops, msg_queue_associate);
- set_to_cap_if_null(ops, msg_queue_msgctl);
- set_to_cap_if_null(ops, msg_queue_msgsnd);
- set_to_cap_if_null(ops, msg_queue_msgrcv);
- set_to_cap_if_null(ops, shm_alloc_security);
- set_to_cap_if_null(ops, shm_free_security);
- set_to_cap_if_null(ops, shm_associate);
- set_to_cap_if_null(ops, shm_shmctl);
- set_to_cap_if_null(ops, shm_shmat);
- set_to_cap_if_null(ops, sem_alloc_security);
- set_to_cap_if_null(ops, sem_free_security);
- set_to_cap_if_null(ops, sem_associate);
- set_to_cap_if_null(ops, sem_semctl);
- set_to_cap_if_null(ops, sem_semop);
- set_to_cap_if_null(ops, netlink_send);
- set_to_cap_if_null(ops, d_instantiate);
- set_to_cap_if_null(ops, getprocattr);
- set_to_cap_if_null(ops, setprocattr);
- set_to_cap_if_null(ops, ismaclabel);
- set_to_cap_if_null(ops, secid_to_secctx);
- set_to_cap_if_null(ops, secctx_to_secid);
- set_to_cap_if_null(ops, release_secctx);
- set_to_cap_if_null(ops, inode_notifysecctx);
- set_to_cap_if_null(ops, inode_setsecctx);
- set_to_cap_if_null(ops, inode_getsecctx);
-#ifdef CONFIG_SECURITY_NETWORK
- set_to_cap_if_null(ops, unix_stream_connect);
- set_to_cap_if_null(ops, unix_may_send);
- set_to_cap_if_null(ops, socket_create);
- set_to_cap_if_null(ops, socket_post_create);
- set_to_cap_if_null(ops, socket_bind);
- set_to_cap_if_null(ops, socket_connect);
- set_to_cap_if_null(ops, socket_listen);
- set_to_cap_if_null(ops, socket_accept);
- set_to_cap_if_null(ops, socket_sendmsg);
- set_to_cap_if_null(ops, socket_recvmsg);
- set_to_cap_if_null(ops, socket_getsockname);
- set_to_cap_if_null(ops, socket_getpeername);
- set_to_cap_if_null(ops, socket_setsockopt);
- set_to_cap_if_null(ops, socket_getsockopt);
- set_to_cap_if_null(ops, socket_shutdown);
- set_to_cap_if_null(ops, socket_sock_rcv_skb);
- set_to_cap_if_null(ops, socket_getpeersec_stream);
- set_to_cap_if_null(ops, socket_getpeersec_dgram);
- set_to_cap_if_null(ops, sk_alloc_security);
- set_to_cap_if_null(ops, sk_free_security);
- set_to_cap_if_null(ops, sk_clone_security);
- set_to_cap_if_null(ops, sk_getsecid);
- set_to_cap_if_null(ops, sock_graft);
- set_to_cap_if_null(ops, inet_conn_request);
- set_to_cap_if_null(ops, inet_csk_clone);
- set_to_cap_if_null(ops, inet_conn_established);
- set_to_cap_if_null(ops, secmark_relabel_packet);
- set_to_cap_if_null(ops, secmark_refcount_inc);
- set_to_cap_if_null(ops, secmark_refcount_dec);
- set_to_cap_if_null(ops, req_classify_flow);
- set_to_cap_if_null(ops, tun_dev_alloc_security);
- set_to_cap_if_null(ops, tun_dev_free_security);
- set_to_cap_if_null(ops, tun_dev_create);
- set_to_cap_if_null(ops, tun_dev_open);
- set_to_cap_if_null(ops, tun_dev_attach_queue);
- set_to_cap_if_null(ops, tun_dev_attach);
- set_to_cap_if_null(ops, skb_owned_by);
-#endif /* CONFIG_SECURITY_NETWORK */
-#ifdef CONFIG_SECURITY_NETWORK_XFRM
- set_to_cap_if_null(ops, xfrm_policy_alloc_security);
- set_to_cap_if_null(ops, xfrm_policy_clone_security);
- set_to_cap_if_null(ops, xfrm_policy_free_security);
- set_to_cap_if_null(ops, xfrm_policy_delete_security);
- set_to_cap_if_null(ops, xfrm_state_alloc);
- set_to_cap_if_null(ops, xfrm_state_alloc_acquire);
- set_to_cap_if_null(ops, xfrm_state_free_security);
- set_to_cap_if_null(ops, xfrm_state_delete_security);
- set_to_cap_if_null(ops, xfrm_policy_lookup);
- set_to_cap_if_null(ops, xfrm_state_pol_flow_match);
- set_to_cap_if_null(ops, xfrm_decode_session);
-#endif /* CONFIG_SECURITY_NETWORK_XFRM */
-#ifdef CONFIG_KEYS
- set_to_cap_if_null(ops, key_alloc);
- set_to_cap_if_null(ops, key_free);
- set_to_cap_if_null(ops, key_permission);
- set_to_cap_if_null(ops, key_getsecurity);
-#endif /* CONFIG_KEYS */
-#ifdef CONFIG_AUDIT
- set_to_cap_if_null(ops, audit_rule_init);
- set_to_cap_if_null(ops, audit_rule_known);
- set_to_cap_if_null(ops, audit_rule_match);
- set_to_cap_if_null(ops, audit_rule_free);
-#endif
-}

--
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
the body of a message to ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Kees Cook
2014-08-14 19:05:31 UTC
Permalink
Post by Casey Schaufler
Subject: [PATCH v16 3/4] LSM: Remove the unnecessary security/capability.c
As nothing in security/capabiliy.c is used any longer the
file can be safely removed. This isn't done in the 2/4 patch
because it makes the patch file too large for mail lists.
---
security/capability.c | 1131 -------------------------------------------------
1 file changed, 1131 deletions(-)
Another easy review. :)

Reviewed-by: Kees Cook <***@chromium.org>

-Kees
--
Kees Cook
Chrome OS Security
--
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
the body of a message to ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Casey Schaufler
2014-08-08 20:00:41 UTC
Permalink
Subject: [PATCH v16 4/4] LSM: Stop allocating inode->i_security

Both security modules (SELinux and Smack) that use inode security
data do so for all inodes. Every inode allocation results in a
subsequent security blob allocation as well. Access checks
have to use a level of indirection, impacting performance.

Instead of allocating the security module data separately, include
it in the inode. This makes the inode bigger, but the memory was
going to be allocated anyway. I chose to put the module structures
directly into the inode. I could have used compiler tricks so that
it would be less visable, but that adds ugly elsewhere.

My imperfect benchmarks with Fedora 20 and SELinux show a
1.2% improvement in system time on a kernel make and a
5.3% improvement on a make install. Similar improvements
can be expected for Smack systems. These measurements were
done with both SELinux and Smack compiled in, as is done by
most distributions.

Signed-off-by: Casey Schaufler <***@schaufler-ca.com>

---
fs/nfs/inode.c | 14 ++++-
include/linux/fs.h | 13 +++-
include/linux/security.h | 11 ++--
include/linux/selinux.h | 13 ++++
include/linux/smack.h | 38 ++++++++++++
security/security.c | 1 -
security/selinux/hooks.c | 136 ++++++++++++++++++------------------------
security/selinux/selinuxfs.c | 8 +--
security/smack/smack.h | 22 +------
security/smack/smack_lsm.c | 68 +++++++--------------
10 files changed, 168 insertions(+), 156 deletions(-)

diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index 9927913..63d545b 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -285,11 +285,23 @@ void nfs_setsecurity(struct inode *inode, struct nfs_fattr *fattr,
struct nfs4_label *label)
{
int error;
+ int has_label = 0;

if (label == NULL)
return;

- if ((fattr->valid & NFS_ATTR_FATTR_V4_SECURITY_LABEL) && inode->i_security) {
+#ifdef CONFIG_SECURITY_SELINUX
+ /*
+ * As of this writing the only LSM known to work with
+ * labeled NFS is SELinux.
+ *
+ * This should probably be
+ * has_label = security_inode_hasmaclabel(inode);
+ */
+ has_label = (inode->i_selinux.sid != 0);
+#endif
+
+ if ((fattr->valid & NFS_ATTR_FATTR_V4_SECURITY_LABEL) && has_label) {
error = security_inode_notifysecctx(inode, label->label,
label->len);
if (error)
diff --git a/include/linux/fs.h b/include/linux/fs.h
index e11d60c..02baf67 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -29,6 +29,12 @@
#include <linux/lockdep.h>
#include <linux/percpu-rwsem.h>
#include <linux/blk_types.h>
+#ifdef CONFIG_SECURITY_SELINUX
+#include <linux/selinux.h>
+#endif
+#ifdef CONFIG_SECURITY_SMACK
+#include <linux/smack.h>
+#endif

#include <asm/byteorder.h>
#include <uapi/linux/fs.h>
@@ -515,8 +521,11 @@ struct inode {
struct super_block *i_sb;
struct address_space *i_mapping;

-#ifdef CONFIG_SECURITY
- void *i_security;
+#ifdef CONFIG_SECURITY_SELINUX
+ struct inode_selinux i_selinux;
+#endif
+#ifdef CONFIG_SECURITY_SMACK
+ struct inode_smack i_smack;
#endif

/* Stat data, not accessed from path walking */
diff --git a/include/linux/security.h b/include/linux/security.h
index 29076d6..93d66e6 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -327,15 +327,12 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
* Security hooks for inode operations.
*
* @inode_alloc_security:
- * Allocate and attach a security structure to @inode->i_security. The
- * i_security field is initialized to NULL when the inode structure is
- * allocated.
+ * Allocate and attach a security structure to @inode.
* @inode contains the inode structure.
* Return 0 if operation was successful.
* @inode_free_security:
* @inode contains the inode structure.
- * Deallocate the inode security structure and set @inode->i_security to
- * NULL.
+ * Deallocate the inode security structure(s).
* @inode_init_security:
* Obtain the security attribute name suffix and value to set on a newly
* created inode and set up the incore security field for the new inode.
@@ -871,8 +868,8 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
* socket structure, but rather, the socket security information is stored
* in the associated inode. Typically, the inode alloc_security hook will
* allocate and and attach security information to
- * sock->inode->i_security. This hook may be used to update the
- * sock->inode->i_security field with additional information that wasn't
+ * sock->inode. This hook may be used to update the
+ * sock->inode with additional information that wasn't
* available when the inode was allocated.
* @sock contains the newly created socket structure.
* @family contains the requested protocol family.
diff --git a/include/linux/selinux.h b/include/linux/selinux.h
index 44f4596..9612bfc 100644
--- a/include/linux/selinux.h
+++ b/include/linux/selinux.h
@@ -19,6 +19,19 @@ struct audit_context;
struct kern_ipc_perm;

#ifdef CONFIG_SECURITY_SELINUX
+#include <linux/list.h>
+#include <linux/mutex.h>
+
+struct inode;
+
+struct inode_selinux {
+ struct list_head list; /* list of inode_selinux */
+ u32 task_sid; /* SID of creating task */
+ u32 sid; /* SID of this object */
+ u16 sclass; /* security class of this object */
+ unsigned char initialized; /* initialization flag */
+ struct mutex lock;
+};

/**
* selinux_is_enabled - is SELinux enabled?
diff --git a/include/linux/smack.h b/include/linux/smack.h
new file mode 100644
index 0000000..a427edc
--- /dev/null
+++ b/include/linux/smack.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2014 Casey Schaufler <***@schaufler-ca.com>
+ * 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 as published by
+ * the Free Software Foundation, version 2.
+ *
+ * Author:
+ * Casey Schaufler <***@schaufler-ca.com>
+ *
+ */
+
+#ifndef _LINUX_SMACK_H
+#define _LINUX_SMACK_H
+
+#include <linux/list.h>
+#include <linux/mutex.h>
+
+struct smack_known;
+
+/*
+ * Inode Smack data
+ */
+struct inode_smack {
+ char *smk_inode; /* label of the fso */
+ struct smack_known *smk_task; /* label of the task */
+ struct smack_known *smk_mmap; /* label of the mmap domain */
+ struct mutex smk_lock; /* initialization lock */
+ int smk_flags; /* smack inode flags */
+};
+
+#define SMK_INODE_INSTANT 0x01 /* inode is instantiated */
+#define SMK_INODE_TRANSMUTE 0x02 /* directory is transmuting */
+#define SMK_INODE_CHANGED 0x04 /* smack was transmuted */
+#define SMK_INODE_ALLOCATED 0x08 /* smack_inode_alloc_security done */
+
+#endif /* _LINUX_SMACK_H */
diff --git a/security/security.c b/security/security.c
index cf26b62..678b905 100644
--- a/security/security.c
+++ b/security/security.c
@@ -438,7 +438,6 @@ EXPORT_SYMBOL(security_sb_parse_opts_str);
static struct list_head hooks_inode_alloc_security;
int security_inode_alloc(struct inode *inode)
{
- inode->i_security = NULL;
return call_int_hook(inode_alloc_security, inode);
}

diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 4b8852c..9da2c76 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -215,35 +215,23 @@ static inline u32 current_sid(void)

static int inode_alloc_security(struct inode *inode)
{
- struct inode_security_struct *isec;
+ struct inode_selinux *isec = &inode->i_selinux;
u32 sid = current_sid();

- isec = kmem_cache_zalloc(sel_inode_cache, GFP_NOFS);
- if (!isec)
- return -ENOMEM;
+ memset(isec, 0, sizeof(*isec));

mutex_init(&isec->lock);
INIT_LIST_HEAD(&isec->list);
- isec->inode = inode;
isec->sid = SECINITSID_UNLABELED;
isec->sclass = SECCLASS_FILE;
isec->task_sid = sid;
- inode->i_security = isec;

return 0;
}

-static void inode_free_rcu(struct rcu_head *head)
-{
- struct inode_security_struct *isec;
-
- isec = container_of(head, struct inode_security_struct, rcu);
- kmem_cache_free(sel_inode_cache, isec);
-}
-
static void inode_free_security(struct inode *inode)
{
- struct inode_security_struct *isec = inode->i_security;
+ struct inode_selinux *isec = &inode->i_selinux;
struct superblock_security_struct *sbsec = inode->i_sb->s_security;

spin_lock(&sbsec->isec_lock);
@@ -251,16 +239,7 @@ static void inode_free_security(struct inode *inode)
list_del_init(&isec->list);
spin_unlock(&sbsec->isec_lock);

- /*
- * The inode may still be referenced in a path walk and
- * a call to selinux_inode_permission() can be made
- * after inode_free_security() is called. Ideally, the VFS
- * wouldn't do this, but fixing that is a much harder
- * job. For now, simply free the i_security via RCU, and
- * leave the current inode->i_security pointer intact.
- * The inode will be freed after the RCU grace period too.
- */
- call_rcu(&isec->rcu, inode_free_rcu);
+ memset(isec, 0, sizeof(*isec));
}

static int file_alloc_security(struct file *file)
@@ -466,10 +445,11 @@ static int sb_finish_set_opts(struct super_block *sb)
spin_lock(&sbsec->isec_lock);
next_inode:
if (!list_empty(&sbsec->isec_head)) {
- struct inode_security_struct *isec =
+ struct inode_selinux *isec =
list_entry(sbsec->isec_head.next,
- struct inode_security_struct, list);
- struct inode *inode = isec->inode;
+ struct inode_selinux, list);
+ struct inode *inode =
+ container_of(isec, struct inode, i_selinux);
spin_unlock(&sbsec->isec_lock);
inode = igrab(inode);
if (inode) {
@@ -558,7 +538,7 @@ static int selinux_get_mnt_opts(const struct super_block *sb,
}
if (sbsec->flags & ROOTCONTEXT_MNT) {
struct inode *root = sbsec->sb->s_root->d_inode;
- struct inode_security_struct *isec = root->i_security;
+ struct inode_selinux *isec = &root->i_selinux;

rc = security_sid_to_context(isec->sid, &context, &len);
if (rc)
@@ -614,7 +594,7 @@ static int selinux_set_mnt_opts(struct super_block *sb,
struct superblock_security_struct *sbsec = sb->s_security;
const char *name = sb->s_type->name;
struct inode *inode = sbsec->sb->s_root->d_inode;
- struct inode_security_struct *root_isec = inode->i_security;
+ struct inode_selinux *root_isec = &inode->i_selinux;
u32 fscontext_sid = 0, context_sid = 0, rootcontext_sid = 0;
u32 defcontext_sid = 0;
char **mount_options = opts->mnt_opts;
@@ -840,8 +820,10 @@ static int selinux_cmp_sb_context(const struct super_block *oldsb,
if ((oldflags & DEFCONTEXT_MNT) && old->def_sid != new->def_sid)
goto mismatch;
if (oldflags & ROOTCONTEXT_MNT) {
- struct inode_security_struct *oldroot = oldsb->s_root->d_inode->i_security;
- struct inode_security_struct *newroot = newsb->s_root->d_inode->i_security;
+ struct inode_selinux *oldroot =
+ &oldsb->s_root->d_inode->i_selinux;
+ struct inode_selinux *newroot =
+ &newsb->s_root->d_inode->i_selinux;
if (oldroot->sid != newroot->sid)
goto mismatch;
}
@@ -892,16 +874,16 @@ static int selinux_sb_clone_mnt_opts(const struct super_block *oldsb,
newsbsec->sid = sid;
if (!set_rootcontext) {
struct inode *newinode = newsb->s_root->d_inode;
- struct inode_security_struct *newisec = newinode->i_security;
+ struct inode_selinux *newisec = &newinode->i_selinux;
newisec->sid = sid;
}
newsbsec->mntpoint_sid = sid;
}
if (set_rootcontext) {
const struct inode *oldinode = oldsb->s_root->d_inode;
- const struct inode_security_struct *oldisec = oldinode->i_security;
+ const struct inode_selinux *oldisec = &oldinode->i_selinux;
struct inode *newinode = newsb->s_root->d_inode;
- struct inode_security_struct *newisec = newinode->i_security;
+ struct inode_selinux *newisec = &newinode->i_selinux;

newisec->sid = oldisec->sid;
}
@@ -1266,7 +1248,7 @@ static int selinux_proc_get_sid(struct dentry *dentry,
static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dentry)
{
struct superblock_security_struct *sbsec = NULL;
- struct inode_security_struct *isec = inode->i_security;
+ struct inode_selinux *isec = &inode->i_selinux;
u32 sid;
struct dentry *dentry;
#define INITCONTEXTLEN 255
@@ -1594,7 +1576,7 @@ static int inode_has_perm(const struct cred *cred,
u32 perms,
struct common_audit_data *adp)
{
- struct inode_security_struct *isec;
+ struct inode_selinux *isec;
u32 sid;

validate_creds(cred);
@@ -1603,7 +1585,7 @@ static int inode_has_perm(const struct cred *cred,
return 0;

sid = cred_sid(cred);
- isec = inode->i_security;
+ isec = &inode->i_selinux;

return avc_has_perm(sid, isec->sid, isec->sclass, perms, adp);
}
@@ -1695,13 +1677,13 @@ static int may_create(struct inode *dir,
u16 tclass)
{
const struct task_security_struct *tsec = current_security();
- struct inode_security_struct *dsec;
+ struct inode_selinux *dsec;
struct superblock_security_struct *sbsec;
u32 sid, newsid;
struct common_audit_data ad;
int rc;

- dsec = dir->i_security;
+ dsec = &dir->i_selinux;
sbsec = dir->i_sb->s_security;

sid = tsec->sid;
@@ -1751,14 +1733,14 @@ static int may_link(struct inode *dir,
int kind)

{
- struct inode_security_struct *dsec, *isec;
+ struct inode_selinux *dsec, *isec;
struct common_audit_data ad;
u32 sid = current_sid();
u32 av;
int rc;

- dsec = dir->i_security;
- isec = dentry->d_inode->i_security;
+ dsec = &dir->i_selinux;
+ isec = &dentry->d_inode->i_selinux;

ad.type = LSM_AUDIT_DATA_DENTRY;
ad.u.dentry = dentry;
@@ -1794,17 +1776,17 @@ static inline int may_rename(struct inode *old_dir,
struct inode *new_dir,
struct dentry *new_dentry)
{
- struct inode_security_struct *old_dsec, *new_dsec, *old_isec, *new_isec;
+ struct inode_selinux *old_dsec, *new_dsec, *old_isec, *new_isec;
struct common_audit_data ad;
u32 sid = current_sid();
u32 av;
int old_is_dir, new_is_dir;
int rc;

- old_dsec = old_dir->i_security;
- old_isec = old_dentry->d_inode->i_security;
+ old_dsec = &old_dir->i_selinux;
+ old_isec = &old_dentry->d_inode->i_selinux;
old_is_dir = S_ISDIR(old_dentry->d_inode->i_mode);
- new_dsec = new_dir->i_security;
+ new_dsec = &new_dir->i_selinux;

ad.type = LSM_AUDIT_DATA_DENTRY;

@@ -1832,7 +1814,7 @@ static inline int may_rename(struct inode *old_dir,
if (rc)
return rc;
if (new_dentry->d_inode) {
- new_isec = new_dentry->d_inode->i_security;
+ new_isec = &new_dentry->d_inode->i_selinux;
new_is_dir = S_ISDIR(new_dentry->d_inode->i_mode);
rc = avc_has_perm(sid, new_isec->sid,
new_isec->sclass,
@@ -2072,7 +2054,7 @@ static int selinux_bprm_set_creds(struct linux_binprm *bprm)
{
const struct task_security_struct *old_tsec;
struct task_security_struct *new_tsec;
- struct inode_security_struct *isec;
+ struct inode_selinux *isec;
struct common_audit_data ad;
struct inode *inode = file_inode(bprm->file);
int rc;
@@ -2084,7 +2066,7 @@ static int selinux_bprm_set_creds(struct linux_binprm *bprm)

old_tsec = current_security();
new_tsec = bprm->cred->security;
- isec = inode->i_security;
+ isec = &inode->i_selinux;

/* Default to the current task SID. */
new_tsec->sid = old_tsec->sid;
@@ -2506,8 +2488,8 @@ static int selinux_sb_remount(struct super_block *sb, void *data)
goto out_bad_option;
break;
case ROOTCONTEXT_MNT: {
- struct inode_security_struct *root_isec;
- root_isec = sb->s_root->d_inode->i_security;
+ struct inode_selinux *root_isec;
+ root_isec = &sb->s_root->d_inode->i_selinux;

if (bad_option(sbsec, ROOTCONTEXT_MNT, root_isec->sid, sid))
goto out_bad_option;
@@ -2605,14 +2587,14 @@ static int selinux_dentry_init_security(struct dentry *dentry, int mode,
{
const struct cred *cred = current_cred();
struct task_security_struct *tsec;
- struct inode_security_struct *dsec;
+ struct inode_selinux *dsec;
struct superblock_security_struct *sbsec;
struct inode *dir = dentry->d_parent->d_inode;
u32 newsid;
int rc;

tsec = cred->security;
- dsec = dir->i_security;
+ dsec = &dir->i_selinux;
sbsec = dir->i_sb->s_security;

if (tsec->create_sid && sbsec->behavior != SECURITY_FS_USE_MNTPOINT) {
@@ -2639,13 +2621,13 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
void **value, size_t *len)
{
const struct task_security_struct *tsec = current_security();
- struct inode_security_struct *dsec;
+ struct inode_selinux *dsec;
struct superblock_security_struct *sbsec;
u32 sid, newsid, clen;
int rc;
char *context;

- dsec = dir->i_security;
+ dsec = &dir->i_selinux;
sbsec = dir->i_sb->s_security;

sid = tsec->sid;
@@ -2670,7 +2652,7 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir,

/* Possibly defer initialization to selinux_complete_init. */
if (sbsec->flags & SE_SBINITIALIZED) {
- struct inode_security_struct *isec = inode->i_security;
+ struct inode_selinux *isec = &inode->i_selinux;
isec->sclass = inode_mode_to_security_class(inode->i_mode);
isec->sid = newsid;
isec->initialized = 1;
@@ -2754,7 +2736,7 @@ static noinline int audit_inode_permission(struct inode *inode,
unsigned flags)
{
struct common_audit_data ad;
- struct inode_security_struct *isec = inode->i_security;
+ struct inode_selinux *isec = &inode->i_selinux;
int rc;

ad.type = LSM_AUDIT_DATA_INODE;
@@ -2773,7 +2755,7 @@ static int selinux_inode_permission(struct inode *inode, int mask)
u32 perms;
bool from_access;
unsigned flags = mask & MAY_NOT_BLOCK;
- struct inode_security_struct *isec;
+ struct inode_selinux *isec;
u32 sid;
struct av_decision avd;
int rc, rc2;
@@ -2794,7 +2776,7 @@ static int selinux_inode_permission(struct inode *inode, int mask)
perms = file_mask_to_av(inode->i_mode, mask);

sid = cred_sid(cred);
- isec = inode->i_security;
+ isec = &inode->i_selinux;

rc = avc_has_perm_noaudit(sid, isec->sid, isec->sclass, perms, 0, &avd);
audited = avc_audit_required(perms, &avd, rc,
@@ -2869,7 +2851,7 @@ static int selinux_inode_setxattr(struct dentry *dentry, const char *name,
const void *value, size_t size, int flags)
{
struct inode *inode = dentry->d_inode;
- struct inode_security_struct *isec = inode->i_security;
+ struct inode_selinux *isec = &inode->i_selinux;
struct superblock_security_struct *sbsec;
struct common_audit_data ad;
u32 newsid, sid = current_sid();
@@ -2946,7 +2928,7 @@ static void selinux_inode_post_setxattr(struct dentry *dentry, const char *name,
int flags)
{
struct inode *inode = dentry->d_inode;
- struct inode_security_struct *isec = inode->i_security;
+ struct inode_selinux *isec = &inode->i_selinux;
u32 newsid;
int rc;

@@ -3004,7 +2986,7 @@ static int selinux_inode_getsecurity(const struct inode *inode, const char *name
u32 size;
int error;
char *context = NULL;
- struct inode_security_struct *isec = inode->i_security;
+ const struct inode_selinux *isec = &inode->i_selinux;

if (strcmp(name, XATTR_SELINUX_SUFFIX))
return -EOPNOTSUPP;
@@ -3040,7 +3022,7 @@ out_nofree:
static int selinux_inode_setsecurity(struct inode *inode, const char *name,
const void *value, size_t size, int flags)
{
- struct inode_security_struct *isec = inode->i_security;
+ struct inode_selinux *isec = &inode->i_selinux;
u32 newsid;
int rc;

@@ -3070,7 +3052,7 @@ static int selinux_inode_listsecurity(struct inode *inode, char *buffer, size_t

static void selinux_inode_getsecid(const struct inode *inode, u32 *secid)
{
- struct inode_security_struct *isec = inode->i_security;
+ const struct inode_selinux *isec = &inode->i_selinux;
*secid = isec->sid;
}

@@ -3093,7 +3075,7 @@ static int selinux_file_permission(struct file *file, int mask)
{
struct inode *inode = file_inode(file);
struct file_security_struct *fsec = file->f_security;
- struct inode_security_struct *isec = inode->i_security;
+ struct inode_selinux *isec = &inode->i_selinux;
u32 sid = current_sid();

if (!mask)
@@ -3355,10 +3337,10 @@ static int selinux_file_receive(struct file *file)
static int selinux_file_open(struct file *file, const struct cred *cred)
{
struct file_security_struct *fsec;
- struct inode_security_struct *isec;
+ struct inode_selinux *isec;

fsec = file->f_security;
- isec = file_inode(file)->i_security;
+ isec = &file_inode(file)->i_selinux;
/*
* Save inode label and policy sequence number
* at open-time so that selinux_file_permission
@@ -3476,7 +3458,7 @@ static int selinux_kernel_act_as(struct cred *new, u32 secid)
*/
static int selinux_kernel_create_files_as(struct cred *new, struct inode *inode)
{
- struct inode_security_struct *isec = inode->i_security;
+ struct inode_selinux *isec = &inode->i_selinux;
struct task_security_struct *tsec = new->security;
u32 sid = current_sid();
int ret;
@@ -3596,7 +3578,7 @@ static int selinux_task_wait(struct task_struct *p)
static void selinux_task_to_inode(struct task_struct *p,
struct inode *inode)
{
- struct inode_security_struct *isec = inode->i_security;
+ struct inode_selinux *isec = &inode->i_selinux;
u32 sid = task_sid(p);

isec->sid = sid;
@@ -3917,7 +3899,7 @@ static int selinux_socket_post_create(struct socket *sock, int family,
int type, int protocol, int kern)
{
const struct task_security_struct *tsec = current_security();
- struct inode_security_struct *isec = SOCK_INODE(sock)->i_security;
+ struct inode_selinux *isec = &SOCK_INODE(sock)->i_selinux;
struct sk_security_struct *sksec;
int err = 0;

@@ -4110,16 +4092,16 @@ static int selinux_socket_listen(struct socket *sock, int backlog)
static int selinux_socket_accept(struct socket *sock, struct socket *newsock)
{
int err;
- struct inode_security_struct *isec;
- struct inode_security_struct *newisec;
+ struct inode_selinux *isec;
+ struct inode_selinux *newisec;

err = sock_has_perm(current, sock->sk, SOCKET__ACCEPT);
if (err)
return err;

- newisec = SOCK_INODE(newsock)->i_security;
+ newisec = &SOCK_INODE(newsock)->i_selinux;

- isec = SOCK_INODE(sock)->i_security;
+ isec = &SOCK_INODE(sock)->i_selinux;
newisec->sclass = isec->sclass;
newisec->sid = isec->sid;
newisec->initialized = 1;
@@ -4456,7 +4438,7 @@ static void selinux_sk_getsecid(struct sock *sk, u32 *secid)

static void selinux_sock_graft(struct sock *sk, struct socket *parent)
{
- struct inode_security_struct *isec = SOCK_INODE(parent)->i_security;
+ struct inode_selinux *isec = &SOCK_INODE(parent)->i_selinux;
struct sk_security_struct *sksec = sk->sk_security;

if (sk->sk_family == PF_INET || sk->sk_family == PF_INET6 ||
@@ -5940,7 +5922,7 @@ static __init int selinux_init(void)
default_noexec = !(VM_DATA_DEFAULT_FLAGS & VM_EXEC);

sel_inode_cache = kmem_cache_create("selinux_inode_security",
- sizeof(struct inode_security_struct),
+ sizeof(struct inode_selinux),
0, SLAB_PANIC, NULL);
avc_init();

diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c
index c71737f..e786553 100644
--- a/security/selinux/selinuxfs.c
+++ b/security/selinux/selinuxfs.c
@@ -1230,7 +1230,7 @@ static int sel_make_bools(void)
struct dentry *dentry = NULL;
struct dentry *dir = bool_dir;
struct inode *inode = NULL;
- struct inode_security_struct *isec;
+ struct inode_selinux *isec;
char **names = NULL, *page;
int num;
int *values = NULL;
@@ -1272,7 +1272,7 @@ static int sel_make_bools(void)
if (len >= PAGE_SIZE)
goto out;

- isec = (struct inode_security_struct *)inode->i_security;
+ isec = &inode->i_selinux;
ret = security_genfs_sid("selinuxfs", page, SECCLASS_FILE, &sid);
if (ret)
goto out;
@@ -1793,7 +1793,7 @@ static int sel_fill_super(struct super_block *sb, void *data, int silent)
int ret;
struct dentry *dentry;
struct inode *inode;
- struct inode_security_struct *isec;
+ struct inode_selinux *isec;

static struct tree_descr selinux_files[] = {
[SEL_LOAD] = {"load", &sel_load_ops, S_IRUSR|S_IWUSR},
@@ -1837,7 +1837,7 @@ static int sel_fill_super(struct super_block *sb, void *data, int silent)
goto err;

inode->i_ino = ++sel_last_ino;
- isec = (struct inode_security_struct *)inode->i_security;
+ isec = &inode->i_selinux;
isec->sid = SECINITSID_DEVNULL;
isec->sclass = SECCLASS_CHR_FILE;
isec->initialized = 1;
diff --git a/security/smack/smack.h b/security/smack/smack.h
index 020307e..072a51e 100644
--- a/security/smack/smack.h
+++ b/security/smack/smack.h
@@ -84,17 +84,6 @@ struct socket_smack {
struct smack_known *smk_packet; /* TCP peer label */
};

-/*
- * Inode smack data
- */
-struct inode_smack {
- char *smk_inode; /* label of the fso */
- struct smack_known *smk_task; /* label of the task */
- struct smack_known *smk_mmap; /* label of the mmap domain */
- struct mutex smk_lock; /* initialization lock */
- int smk_flags; /* smack inode flags */
-};
-
struct task_smack {
struct smack_known *smk_task; /* label for access control */
struct smack_known *smk_forked; /* label when forked */
@@ -105,6 +94,7 @@ struct task_smack {
#define SMK_INODE_INSTANT 0x01 /* inode is instantiated */
#define SMK_INODE_TRANSMUTE 0x02 /* directory is transmuting */
#define SMK_INODE_CHANGED 0x04 /* smack was transmuted */
+#define SMK_INODE_ALLOCATED 0x08 /* smack_inode_alloc_security done */

/*
* A label access rule.
@@ -223,10 +213,6 @@ struct smk_audit_info {
struct smack_audit_data sad;
#endif
};
-/*
- * These functions are in smack_lsm.c
- */
-struct inode_smack *new_inode_smack(char *);

/*
* These functions are in smack_access.c
@@ -276,8 +262,7 @@ extern struct hlist_head smack_known_hash[SMACK_HASH_SLOTS];
*/
static inline int smk_inode_transmutable(const struct inode *isp)
{
- struct inode_smack *sip = isp->i_security;
- return (sip->smk_flags & SMK_INODE_TRANSMUTE) != 0;
+ return (isp->i_smack.smk_flags & SMK_INODE_TRANSMUTE) != 0;
}

/*
@@ -285,8 +270,7 @@ static inline int smk_inode_transmutable(const struct inode *isp)
*/
static inline char *smk_of_inode(const struct inode *isp)
{
- struct inode_smack *sip = isp->i_security;
- return sip->smk_inode;
+ return isp->i_smack.smk_inode;
}

/*
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index 4b071b3..2cac3e4 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -86,27 +86,6 @@ static struct smack_known *smk_fetch(const char *name, struct inode *ip,
}

/**
- * new_inode_smack - allocate an inode security blob
- * @smack: a pointer to the Smack label to use in the blob
- *
- * Returns the new blob or NULL if there's no memory available
- */
-struct inode_smack *new_inode_smack(char *smack)
-{
- struct inode_smack *isp;
-
- isp = kzalloc(sizeof(struct inode_smack), GFP_NOFS);
- if (isp == NULL)
- return NULL;
-
- isp->smk_inode = smack;
- isp->smk_flags = 0;
- mutex_init(&isp->smk_lock);
-
- return isp;
-}
-
-/**
* new_task_smack - allocate a task security blob
* @smack: a pointer to the Smack label to use in the blob
*
@@ -467,14 +446,12 @@ static int smack_sb_kern_mount(struct super_block *sb, int flags, void *data)
/*
* Initialize the root inode.
*/
- isp = inode->i_security;
- if (isp == NULL) {
- isp = new_inode_smack(sp->smk_root);
- if (isp == NULL)
- return -ENOMEM;
- inode->i_security = isp;
- } else
- isp->smk_inode = sp->smk_root;
+ if (!(inode->i_smack.smk_flags & SMK_INODE_ALLOCATED))
+ /*
+ * Don't optimize this. The desired result is that flags be
+ * cleared except for the ALLOCATED bit.
+ */
+ inode->i_smack.smk_flags = SMK_INODE_ALLOCATED;

if (transmute)
isp->smk_flags |= SMK_INODE_TRANSMUTE;
@@ -523,7 +500,7 @@ static int smack_bprm_set_creds(struct linux_binprm *bprm)
if (bprm->cred_prepared)
return 0;

- isp = inode->i_security;
+ isp = &inode->i_smack;
if (isp->smk_task == NULL || isp->smk_task == bsp->smk_task)
return 0;

@@ -594,10 +571,12 @@ static int smack_bprm_secureexec(struct linux_binprm *bprm)
static int smack_inode_alloc_security(struct inode *inode)
{
struct smack_known *skp = smk_of_current();
+ struct inode_smack *isp = &inode->i_smack;
+
+ memset(isp, 0, sizeof(*isp));
+ isp->smk_inode = skp->smk_known;
+ mutex_init(&isp->smk_lock);

- inode->i_security = new_inode_smack(skp->smk_known);
- if (inode->i_security == NULL)
- return -ENOMEM;
return 0;
}

@@ -609,8 +588,7 @@ static int smack_inode_alloc_security(struct inode *inode)
*/
static void smack_inode_free_security(struct inode *inode)
{
- kfree(inode->i_security);
- inode->i_security = NULL;
+ memset(&inode->i_smack, 0, sizeof(inode->i_smack));
}

/**
@@ -628,7 +606,7 @@ static int smack_inode_init_security(struct inode *inode, struct inode *dir,
const struct qstr *qstr, const char **name,
void **value, size_t *len)
{
- struct inode_smack *issp = inode->i_security;
+ struct inode_smack *issp = &inode->i_smack;
struct smack_known *skp = smk_of_current();
char *isp = smk_of_inode(inode);
char *dsp = smk_of_inode(dir);
@@ -941,7 +919,7 @@ static void smack_inode_post_setxattr(struct dentry *dentry, const char *name,
const void *value, size_t size, int flags)
{
struct smack_known *skp;
- struct inode_smack *isp = dentry->d_inode->i_security;
+ struct inode_smack *isp = &dentry->d_inode->i_smack;

if (strcmp(name, XATTR_NAME_SMACKTRANSMUTE) == 0) {
isp->smk_flags |= SMK_INODE_TRANSMUTE;
@@ -1024,7 +1002,7 @@ static int smack_inode_removexattr(struct dentry *dentry, const char *name)
if (rc != 0)
return rc;

- isp = dentry->d_inode->i_security;
+ isp = &dentry->d_inode->i_smack;
/*
* Don't do anything special for these.
* XATTR_NAME_SMACKIPIN
@@ -1126,7 +1104,7 @@ static int smack_inode_listsecurity(struct inode *inode, char *buffer,
*/
static void smack_inode_getsecid(const struct inode *inode, u32 *secid)
{
- struct inode_smack *isp = inode->i_security;
+ const struct inode_smack *isp = &inode->i_smack;

*secid = smack_to_secid(isp->smk_inode);
}
@@ -1296,7 +1274,7 @@ static int smack_mmap_file(struct file *file,
if (file == NULL)
return 0;

- isp = file_inode(file)->i_security;
+ isp = &file_inode(file)->i_smack;
if (isp->smk_mmap == NULL)
return 0;
mkp = isp->smk_mmap;
@@ -1462,7 +1440,7 @@ 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_smack *isp = &(file_inode(file)->i_smack);
struct smk_audit_info ad;
int rc;

@@ -1607,7 +1585,7 @@ static int smack_kernel_act_as(struct cred *new, u32 secid)
static int smack_kernel_create_files_as(struct cred *new,
struct inode *inode)
{
- struct inode_smack *isp = inode->i_security;
+ struct inode_smack *isp = &inode->i_smack;
struct task_smack *tsp = new->security;

tsp->smk_forked = smk_find_entry(isp->smk_inode);
@@ -1816,7 +1794,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 inode_smack *isp = &inode->i_smack;
struct smack_known *skp = smk_of_task(task_security(p));

isp->smk_inode = skp->smk_known;
@@ -2151,7 +2129,7 @@ static int smack_inode_setsecurity(struct inode *inode, const char *name,
const void *value, size_t size, int flags)
{
struct smack_known *skp;
- struct inode_smack *nsp = inode->i_security;
+ struct inode_smack *nsp = &inode->i_smack;
struct socket_smack *ssp;
struct socket *sock;
int rc = 0;
@@ -2769,7 +2747,7 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode)
if (inode == NULL)
return;

- isp = inode->i_security;
+ isp = &inode->i_smack;

mutex_lock(&isp->smk_lock);
/*

--
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
the body of a message to ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Stephen Smalley
2014-08-12 13:56:48 UTC
Permalink
Post by Casey Schaufler
Subject: [PATCH v16 4/4] LSM: Stop allocating inode->i_security
Both security modules (SELinux and Smack) that use inode security
data do so for all inodes. Every inode allocation results in a
subsequent security blob allocation as well. Access checks
have to use a level of indirection, impacting performance.
Instead of allocating the security module data separately, include
it in the inode. This makes the inode bigger, but the memory was
going to be allocated anyway. I chose to put the module structures
directly into the inode. I could have used compiler tricks so that
it would be less visable, but that adds ugly elsewhere.
My imperfect benchmarks with Fedora 20 and SELinux show a
1.2% improvement in system time on a kernel make and a
5.3% improvement on a make install. Similar improvements
can be expected for Smack systems. These measurements were
done with both SELinux and Smack compiled in, as is done by
most distributions.
---
fs/nfs/inode.c | 14 ++++-
include/linux/fs.h | 13 +++-
include/linux/security.h | 11 ++--
include/linux/selinux.h | 13 ++++
include/linux/smack.h | 38 ++++++++++++
security/security.c | 1 -
security/selinux/hooks.c | 136 ++++++++++++++++++------------------------
security/selinux/selinuxfs.c | 8 +--
security/smack/smack.h | 22 +------
security/smack/smack_lsm.c | 68 +++++++--------------
10 files changed, 168 insertions(+), 156 deletions(-)
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index 9927913..63d545b 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -285,11 +285,23 @@ void nfs_setsecurity(struct inode *inode, struct nfs_fattr *fattr,
struct nfs4_label *label)
{
int error;
+ int has_label = 0;
if (label == NULL)
return;
- if ((fattr->valid & NFS_ATTR_FATTR_V4_SECURITY_LABEL) && inode->i_security) {
+#ifdef CONFIG_SECURITY_SELINUX
+ /*
+ * As of this writing the only LSM known to work with
+ * labeled NFS is SELinux.
+ *
+ * This should probably be
+ * has_label = security_inode_hasmaclabel(inode);
+ */
+ has_label = (inode->i_selinux.sid != 0);
+#endif
+
+ if ((fattr->valid & NFS_ATTR_FATTR_V4_SECURITY_LABEL) && has_label) {
I would just get rid of the inode->i_security test and not add a new
one, i.e. always call security_inode_notifysecctx() if the fattr
included a security label and leave it up to the security module to
ignore or handle it as desired. Just change
security_inode_notifysecctx() in include/linux/security.h to return 0
(as already is the case for cap_inode_notifysecctx, which should be
consistent) or ignore -EOPNOTSUPP in the error handling code below so
that it does not log an error in the CONFIG_SECURITY=n case.
Post by Casey Schaufler
error = security_inode_notifysecctx(inode, label->label,
label->len);
if (error)
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 4b8852c..9da2c76 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
<snip>
Post by Casey Schaufler
static void inode_free_security(struct inode *inode)
{
- struct inode_security_struct *isec = inode->i_security;
+ struct inode_selinux *isec = &inode->i_selinux;
struct superblock_security_struct *sbsec = inode->i_sb->s_security;
spin_lock(&sbsec->isec_lock);
@@ -251,16 +239,7 @@ static void inode_free_security(struct inode *inode)
list_del_init(&isec->list);
spin_unlock(&sbsec->isec_lock);
- /*
- * The inode may still be referenced in a path walk and
- * a call to selinux_inode_permission() can be made
- * after inode_free_security() is called. Ideally, the VFS
- * wouldn't do this, but fixing that is a much harder
- * job. For now, simply free the i_security via RCU, and
- * leave the current inode->i_security pointer intact.
- * The inode will be freed after the RCU grace period too.
- */
- call_rcu(&isec->rcu, inode_free_rcu);
+ memset(isec, 0, sizeof(*isec));
}
This isn't safe; the fields can still be referenced in
selinux_inode_permission() as noted in the (deleted) comment. You can
just remove the call to call_rcu() but do not clear the structure here.
Looks like Smack is still subject to the NULL pointer dereference
problem there.
--
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
the body of a message to ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Kees Cook
2014-08-14 23:47:22 UTC
Permalink
Post by Casey Schaufler
Subject: [PATCH v15 0/3] LSM: Generalize existing module stacking
There are currently two different mechanisms used to
stack security modules. The capability module is set
up as the "default" module. The other modules that
replace it call the functions it contains directly.
The Yama module is stacked using ifdefs in the security
infrastructure.
This patch set changes the existing module stacking so that
all stacking gets done the same way. There is no
"default" module, instead there is a list of modules
for each hook. The capability module is now on the
list first. If Yama stacking is configured, that is
added to the list next. Finally, if another module is
configured it gets added to the lists. The capability
calls duplicated within existing LSMs have been
removed. Not all capability calls in other modules can
be treated this way, and the individual cases are
noted.
The fourth patch is motivated by a discussion I had
with Linus about LSM performance. We can get significant
performance improvement if we put the LSM inode data
into the inode rather than maintaining a pointer to
data that is allocated and freed separately. Rather
than having an i_security entry there is now a structure
for each LSM that needs one, i_selinux and i_smack for
the time being.
The downside is that there are more LSM configuration
ifdefs in header files. There are tricks that could
be used to reduce them, but they really make the code
ugly. Uglier than the ifdefs, by quite a margin. If you
configure LSMs that you're not using, the structures
get slightly bigger. That is more than offset by the
performance improvement gained by the inode change.
---
fs/nfs/inode.c | 14 +-
include/linux/fs.h | 13 +-
include/linux/security.h | 17 +-
include/linux/selinux.h | 13 +
include/linux/smack.h | 38 +
security/Makefile | 2 +-
security/apparmor/domain.c | 4 +-
security/apparmor/lsm.c | 20 +-
security/capability.c | 1131 ------------------------------
security/commoncap.c | 34 +
security/security.c | 1592 +++++++++++++++++++++++++++++++++++-------
security/selinux/hooks.c | 184 ++---
security/selinux/selinuxfs.c | 8 +-
security/smack/smack.h | 22 +-
security/smack/smack_lsm.c | 103 +--
security/tomoyo/tomoyo.c | 6 -
security/yama/yama_lsm.c | 36 +-
17 files changed, 1571 insertions(+), 1666 deletions(-)
Besides the SELinux nits that have been pointed out, I'm quite happy
with this series! Thanks for keeping it going. I've ported it forward
for -next (it just needed to gain the kernel_fw_from_file hook) here:
https://git.kernel.org/cgit/linux/kernel/git/kees/linux.git/log/?h=lsm/stacking

And it was very easy to add stacked mini-LSMs on top of this:
https://git.kernel.org/cgit/linux/kernel/git/kees/linux.git/commit/?h=lsm/modpin-stacking

The results will be featured in my Component Firmware slides and demo
at Linux Security Summit. :)

-Kees
--
Kees Cook
Chrome OS Security
--
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
the body of a message to ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Loading...