Discussion:
[PATCH v17 0/4] LSM: Generalize existing module stacking
Casey Schaufler
2014-10-17 00:24:12 UTC
Permalink
Subject: [PATCH v17 0/4] 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.

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

---
include/linux/security.h | 40 +-
security/Makefile | 2 +-
security/apparmor/domain.c | 4 +-
security/apparmor/lsm.c | 29 +-
security/capability.c | 1137 --------------------------------
security/commoncap.c | 33 +-
security/security.c | 1564 +++++++++++++++++++++++++++++++++++++-------
security/selinux/hooks.c | 82 +--
security/smack/smack_lsm.c | 43 +-
security/tomoyo/tomoyo.c | 6 -
security/yama/yama_lsm.c | 44 +-
11 files changed, 1391 insertions(+), 1593 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-17 00:48:20 UTC
Permalink
Subject: [PATCH v17 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 | 430 +++++++++++++++++++++++++++------------------------
1 file changed, 228 insertions(+), 202 deletions(-)

diff --git a/security/security.c b/security/security.c
index e41b1a8..d51eb40 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,44 +834,44 @@ 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_fw_from_file(struct file *file, char *buf, size_t size)
{
int ret;

- ret = security_ops->kernel_fw_from_file(file, buf, size);
+ ret = call_int_hook(kernel_fw_from_file, file, buf, size);
if (ret)
return ret;
return ima_fw_from_file(file, buf, size);
@@ -858,14 +880,14 @@ EXPORT_SYMBOL_GPL(security_kernel_fw_from_file);

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);
@@ -874,75 +896,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,
@@ -954,179 +976,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);

@@ -1134,212 +1156,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 */
@@ -1350,71 +1373,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);
}
@@ -1427,23 +1453,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 */
@@ -1452,23 +1478,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
Casey Schaufler
2014-10-17 00:48:26 UTC
Permalink
Subject: [PATCH v17 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 | 40 +-
security/Makefile | 2 +-
security/apparmor/domain.c | 4 +-
security/apparmor/lsm.c | 21 +-
security/commoncap.c | 33 +-
security/security.c | 1160 +++++++++++++++++++++++++++++++++++++++++---
security/selinux/hooks.c | 67 +--
security/smack/smack_lsm.c | 43 +-
security/tomoyo/tomoyo.c | 6 -
security/yama/yama_lsm.c | 44 +-
10 files changed, 1171 insertions(+), 249 deletions(-)

diff --git a/include/linux/security.h b/include/linux/security.h
index 623f90e..611995a 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;
@@ -3169,36 +3173,8 @@ static inline void free_secdata(void *secdata)
{ }
#endif /* CONFIG_SECURITY */

-#ifdef CONFIG_SECURITY_YAMA
-extern int yama_ptrace_access_check(struct task_struct *child,
- unsigned int mode);
-extern int yama_ptrace_traceme(struct task_struct *parent);
-extern void yama_task_free(struct task_struct *task);
-extern int yama_task_prctl(int option, unsigned long arg2, unsigned long arg3,
- unsigned long arg4, unsigned long arg5);
-#else
-static inline int yama_ptrace_access_check(struct task_struct *child,
- unsigned int mode)
-{
- return 0;
-}
-
-static inline int yama_ptrace_traceme(struct task_struct *parent)
-{
- return 0;
-}
-
-static inline void yama_task_free(struct task_struct *task)
-{
-}
-
-static inline int yama_task_prctl(int option, unsigned long arg2,
- unsigned long arg3, unsigned long arg4,
- unsigned long arg5)
-{
- return -ENOSYS;
-}
-#endif /* CONFIG_SECURITY_YAMA */
+#ifdef CONFIG_SECURITY_YAMA_STACKED
+extern struct security_operations yama_ops;
+#endif

#endif /* ! __LINUX_SECURITY_H */
-
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 d97cba3..b09fff7 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..30e562a 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;
}

@@ -640,7 +630,6 @@ static struct security_operations apparmor_ops = {
.file_alloc_security = apparmor_file_alloc_security,
.file_free_security = apparmor_file_free_security,
.mmap_file = apparmor_mmap_file,
- .mmap_addr = cap_mmap_addr,
.file_mprotect = apparmor_file_mprotect,
.file_lock = apparmor_file_lock,

diff --git a/security/commoncap.c b/security/commoncap.c
index bab0611..02eb0c8 100644
--- a/security/commoncap.c
+++ b/security/commoncap.c
@@ -954,7 +954,7 @@ int cap_vm_enough_memory(struct mm_struct *mm, long pages)
if (cap_capable(current_cred(), &init_user_ns, CAP_SYS_ADMIN,
SECURITY_CAP_NOAUDIT) == 0)
cap_sys_admin = 1;
- return __vm_enough_memory(mm, pages, cap_sys_admin);
+ return cap_sys_admin;
}

/*
@@ -985,3 +985,34 @@ 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,
+ .bprm_secureexec = cap_bprm_secureexec,
+ /*
+ * Not stacked in the usual way.
+ * .inode_setxattr = cap_inode_setxattr,
+ * .inode_removexattr = cap_inode_removexattr,
+ */
+ .inode_need_killpriv = cap_inode_need_killpriv,
+ .inode_killpriv = cap_inode_killpriv,
+ .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 d51eb40..c1d8853 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,8 @@ static void __init do_security_initcalls(void)
}
}

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

- security_fixup_ops(&default_security_ops);
- security_ops = &default_security_ops;
+ pr_info("Security Framework initialized\n");
+
+ /*
+ * 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 +123,66 @@ int __init security_module_enable(struct security_operations *ops)
*/
int __init register_security(struct security_operations *ops)
{
- if (verify(ops)) {
- printk(KERN_DEBUG "%s could not verify "
- "security_operations structure.\n", __func__);
+ /*
+ * Verify the security_operations structure exists
+ */
+ if (!ops) {
+ pr_debug("%s could not verify security_operations.\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__)
+#define call_void_hook(FUNC, ...) \
+ do { \
+ struct security_hook_list *P; \
+ \
+ 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; \
+ \
+ list_for_each_entry(P, &hooks_##FUNC, shl_head) { \
+ RC = P->shl_ops->FUNC(__VA_ARGS__); \
+ if (RC != 0) \
+ break; \
+ } \
+ } while (0); \
+ RC; \
+}) \

/* Security operations */

+static 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 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 LIST_HEAD(hooks_capget);
int security_capget(struct task_struct *target,
kernel_cap_t *effective,
kernel_cap_t *inheritable,
@@ -177,6 +191,7 @@ int security_capget(struct task_struct *target,
return call_int_hook(capget, target, effective, inheritable, permitted);
}

+static 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 +201,7 @@ int security_capset(struct cred *new, const struct cred *old,
effective, inheritable, permitted);
}

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

+static 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 LIST_HEAD(hooks_quota_on);
int security_quota_on(struct dentry *dentry)
{
return call_int_hook(quota_on, dentry);
}

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

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

+static 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);
+ struct security_hook_list *shp;
+ int cap_sys_admin = 1;
+ int rc;
+
+ /*
+ * The module will respond with a positive value if
+ * it thinks the __vm_enough_memory() call should be
+ * made with the cap_sys_admin set. If all of the modules
+ * agree that it should be set it will. If any module
+ * thinks it should not be set it won't.
+ */
+ list_for_each_entry(shp, &hooks_vm_enough_memory, shl_head) {
+ rc = shp->shl_ops->vm_enough_memory(mm, pages);
+ if (rc <= 0) {
+ cap_sys_admin = 0;
+ break;
+ }
+ }
+ return __vm_enough_memory(mm, pages, cap_sys_admin);
}

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

+static LIST_HEAD(hooks_bprm_check_security);
int security_bprm_check(struct linux_binprm *bprm)
{
int ret;
@@ -242,83 +283,104 @@ int security_bprm_check(struct linux_binprm *bprm)
return ima_bprm_check(bprm);
}

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

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

+static LIST_HEAD(hooks_bprm_secureexec);
int security_bprm_secureexec(struct linux_binprm *bprm)
{
return call_int_hook(bprm_secureexec, bprm);
}

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

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

+static 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 LIST_HEAD(hooks_sb_remount);
int security_sb_remount(struct super_block *sb, void *data)
{
return call_int_hook(sb_remount, sb, data);
}

+static 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 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 LIST_HEAD(hooks_sb_statfs);
int security_sb_statfs(struct dentry *dentry)
{
return call_int_hook(sb_statfs, dentry);
}

+static 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 LIST_HEAD(hooks_sb_umount);
int security_sb_umount(struct vfsmount *mnt, int flags)
{
return call_int_hook(sb_umount, mnt, flags);
}

+static 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 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 0;
+ }
+
return call_int_hook(sb_set_mnt_opts, sb, opts, kern_flags,
set_kern_flags);
}
EXPORT_SYMBOL(security_sb_set_mnt_opts);

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

+static 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 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 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 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 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 +433,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,
@@ -404,6 +477,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 LIST_HEAD(hooks_path_mknod);
int security_path_mknod(struct path *dir, struct dentry *dentry, umode_t mode,
unsigned int dev)
{
@@ -413,6 +487,7 @@ int security_path_mknod(struct path *dir, struct dentry *dentry, umode_t mode,
}
EXPORT_SYMBOL(security_path_mknod);

+static 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 +496,7 @@ int security_path_mkdir(struct path *dir, struct dentry *dentry, umode_t mode)
}
EXPORT_SYMBOL(security_path_mkdir);

+static 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 +504,7 @@ int security_path_rmdir(struct path *dir, struct dentry *dentry)
return call_int_hook(path_rmdir, dir, dentry);
}

+static 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 +513,7 @@ int security_path_unlink(struct path *dir, struct dentry *dentry)
}
EXPORT_SYMBOL(security_path_unlink);

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

+static LIST_HEAD(hooks_path_link);
int security_path_link(struct dentry *old_dentry, struct path *new_dir,
struct dentry *new_dentry)
{
@@ -452,6 +531,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 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 +552,7 @@ int security_path_rename(struct path *old_dir, struct dentry *old_dentry,
}
EXPORT_SYMBOL(security_path_rename);

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

+static 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 +568,7 @@ int security_path_chmod(struct path *path, umode_t mode)
return call_int_hook(path_chmod, path, mode);
}

+static 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 +576,14 @@ int security_path_chown(struct path *path, kuid_t uid, kgid_t gid)
return call_int_hook(path_chown, path, uid, gid);
}

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

+static 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 +592,7 @@ int security_inode_create(struct inode *dir, struct dentry *dentry, umode_t mode
}
EXPORT_SYMBOL_GPL(security_inode_create);

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

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

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

+static 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 +627,7 @@ int security_inode_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
}
EXPORT_SYMBOL_GPL(security_inode_mkdir);

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

+static 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 +643,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 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 +663,7 @@ int security_inode_rename(struct inode *old_dir, struct dentry *old_dentry,
new_dir, new_dentry);
}

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

+static 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 +679,7 @@ int security_inode_follow_link(struct dentry *dentry, struct nameidata *nd)
return call_int_hook(inode_follow_link, dentry, nd);
}

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

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

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

+static 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 +717,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 +735,7 @@ int security_inode_setxattr(struct dentry *dentry, const char *name,
return evm_inode_setxattr(dentry, name, value, size);
}

+static 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 +745,7 @@ void security_inode_post_setxattr(struct dentry *dentry, const char *name,
evm_inode_post_setxattr(dentry, name, value, size);
}

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

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

+static 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 +782,55 @@ int security_inode_removexattr(struct dentry *dentry, const char *name)
return evm_inode_removexattr(dentry, name);
}

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

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

+static LIST_HEAD(hooks_inode_getsecurity);
int security_inode_getsecurity(const struct inode *inode, const char *name, void **buffer, bool alloc)
{
+ struct security_hook_list *shp;
+ int rc = -EOPNOTSUPP;
+
if (unlikely(IS_PRIVATE(inode)))
return -EOPNOTSUPP;
- return call_int_hook(inode_getsecurity, inode, name, buffer, alloc);
+
+ list_for_each_entry(shp, &hooks_inode_getsecurity, shl_head) {
+ rc = shp->shl_ops->inode_getsecurity(inode, name, buffer,
+ alloc);
+ if (rc != 0)
+ break;
+ }
+ return rc;
}

+static LIST_HEAD(hooks_inode_setsecurity);
int security_inode_setsecurity(struct inode *inode, const char *name, const void *value, size_t size, int flags)
{
+ struct security_hook_list *shp;
+ int rc = -EOPNOTSUPP;
+
if (unlikely(IS_PRIVATE(inode)))
return -EOPNOTSUPP;
- return call_int_hook(inode_setsecurity, inode, name, value, size,
- flags);
+
+ list_for_each_entry(shp, &hooks_inode_setsecurity, shl_head) {
+ rc = shp->shl_ops->inode_setsecurity(inode, name, value, size,
+ flags);
+ if (rc != 0)
+ break;
+ }
+ return rc;
}

+static 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 +839,14 @@ int security_inode_listsecurity(struct inode *inode, char *buffer, size_t buffer
}
EXPORT_SYMBOL(security_inode_listsecurity);

+static LIST_HEAD(hooks_inode_getsecid);
void security_inode_getsecid(const struct inode *inode, u32 *secid)
{
+ *secid = 0;
call_void_hook(inode_getsecid, inode, secid);
}

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

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

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

+static 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 +910,7 @@ static inline unsigned long mmap_prot(struct file *file, unsigned long prot)
return prot;
}

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

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

+static 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 LIST_HEAD(hooks_file_lock);
int security_file_lock(struct file *file, unsigned int cmd)
{
return call_int_hook(file_lock, file, cmd);
}

+static 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 LIST_HEAD(hooks_file_set_fowner);
int security_file_set_fowner(struct file *file)
{
return call_int_hook(file_set_fowner, file);
}

+static 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 LIST_HEAD(hooks_file_receive);
int security_file_receive(struct file *file)
{
return call_int_hook(file_receive, file);
}

+static LIST_HEAD(hooks_file_open);
int security_file_open(struct file *file, const struct cred *cred)
{
int ret;
@@ -824,49 +978,55 @@ int security_file_open(struct file *file, const struct cred *cred)
return fsnotify_perm(file, MAY_OPEN);
}

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

+static 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 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 LIST_HEAD(hooks_cred_free);
void security_cred_free(struct cred *cred)
{
call_void_hook(cred_free, cred);
}

+static 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 LIST_HEAD(hooks_cred_transfer);
void security_transfer_creds(struct cred *new, const struct cred *old)
{
call_void_hook(cred_transfer, new, old);
}

+static 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 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 LIST_HEAD(hooks_kernel_fw_from_file);
int security_kernel_fw_from_file(struct file *file, char *buf, size_t size)
{
int ret;
@@ -878,11 +1038,13 @@ int security_kernel_fw_from_file(struct file *file, char *buf, size_t size)
}
EXPORT_SYMBOL_GPL(security_kernel_fw_from_file);

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

+static LIST_HEAD(hooks_kernel_module_from_file);
int security_kernel_module_from_file(struct file *file)
{
int ret;
@@ -893,200 +1055,249 @@ int security_kernel_module_from_file(struct file *file)
return ima_module_check(file);
}

+static 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 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 LIST_HEAD(hooks_task_getpgid);
int security_task_getpgid(struct task_struct *p)
{
return call_int_hook(task_getpgid, p);
}

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

+static LIST_HEAD(hooks_task_getsecid);
void security_task_getsecid(struct task_struct *p, u32 *secid)
{
+ *secid = 0;
call_void_hook(task_getsecid, p, secid);
}
EXPORT_SYMBOL(security_task_getsecid);

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

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

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

+static 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 LIST_HEAD(hooks_task_setscheduler);
int security_task_setscheduler(struct task_struct *p)
{
return call_int_hook(task_setscheduler, p);
}

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

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

+static 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 LIST_HEAD(hooks_task_wait);
int security_task_wait(struct task_struct *p)
{
return call_int_hook(task_wait, p);
}

+static 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;
-#endif
- return call_int_hook(task_prctl, option, arg2, arg3, arg4, arg5);
+ 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) {
+ thisrc = shp->shl_ops->task_prctl(option, arg2, arg3,
+ arg4, arg5);
+ if (thisrc != -ENOSYS) {
+ rc = thisrc;
+ if (thisrc != 0)
+ break;
+ }
+ }
+ return rc;
}

+static 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 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 LIST_HEAD(hooks_ipc_getsecid);
void security_ipc_getsecid(struct kern_ipc_perm *ipcp, u32 *secid)
{
+ *secid = 0;
call_void_hook(ipc_getsecid, ipcp, secid);
}

+static 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 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 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 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 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 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 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 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 LIST_HEAD(hooks_shm_alloc_security);
int security_shm_alloc(struct shmid_kernel *shp)
{
return call_int_hook(shm_alloc_security, shp);
}

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

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

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

+static 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 LIST_HEAD(hooks_sem_alloc_security);
int security_sem_alloc(struct sem_array *sma)
{
return call_int_hook(sem_alloc_security, sma);
}

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

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

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

+static 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 LIST_HEAD(hooks_d_instantiate);
void security_d_instantiate(struct dentry *dentry, struct inode *inode)
{
if (unlikely(inode && IS_PRIVATE(inode)))
@@ -1095,82 +1306,111 @@ void security_d_instantiate(struct dentry *dentry, struct inode *inode)
}
EXPORT_SYMBOL(security_d_instantiate);

+static 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 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 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 LIST_HEAD(hooks_ismaclabel);
int security_ismaclabel(const char *name)
{
return call_int_hook(ismaclabel, name);
}
EXPORT_SYMBOL(security_ismaclabel);

+static 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 LIST_HEAD(hooks_secctx_to_secid);
int security_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid)
{
+ *secid = 0;
return call_int_hook(secctx_to_secid, secdata, seclen, secid);
}
EXPORT_SYMBOL(security_secctx_to_secid);

+static 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 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 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 LIST_HEAD(hooks_inode_getsecctx);
int security_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen)
{
- return call_int_hook(inode_getsecctx, inode, ctx, ctxlen);
+ struct security_hook_list *shp;
+ int rc = -EOPNOTSUPP;
+
+ list_for_each_entry(shp, &hooks_inode_getsecurity, shl_head) {
+ rc = shp->shl_ops->inode_getsecctx(inode, ctx, ctxlen);
+ if (rc != 0)
+ break;
+ }
+ return rc;
}
EXPORT_SYMBOL(security_inode_getsecctx);

#ifdef CONFIG_SECURITY_NETWORK

+static 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 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 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 LIST_HEAD(hooks_socket_post_create);
int security_socket_post_create(struct socket *sock, int family,
int type, int protocol, int kern)
{
@@ -1178,115 +1418,140 @@ int security_socket_post_create(struct socket *sock, int family,
protocol, kern);
}

+static 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 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 LIST_HEAD(hooks_socket_listen);
int security_socket_listen(struct socket *sock, int backlog)
{
return call_int_hook(socket_listen, sock, backlog);
}

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

+static 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 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 LIST_HEAD(hooks_socket_getsockname);
int security_socket_getsockname(struct socket *sock)
{
return call_int_hook(socket_getsockname, sock);
}

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

+static 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 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 LIST_HEAD(hooks_socket_shutdown);
int security_socket_shutdown(struct socket *sock, int how)
{
return call_int_hook(socket_shutdown, sock, how);
}

+static 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 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 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 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 LIST_HEAD(hooks_sk_free_security);
void security_sk_free(struct sock *sk)
{
call_void_hook(sk_free_security, sk);
}

+static 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 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 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 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 LIST_HEAD(hooks_inet_conn_request);
int security_inet_conn_request(struct sock *sk,
struct sk_buff *skb, struct request_sock *req)
{
@@ -1294,72 +1559,84 @@ int security_inet_conn_request(struct sock *sk,
}
EXPORT_SYMBOL(security_inet_conn_request);

+static 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 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 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 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 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 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 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 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 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 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 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 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);
@@ -1369,6 +1646,7 @@ void security_skb_owned_by(struct sk_buff *skb, struct sock *sk)

#ifdef CONFIG_SECURITY_NETWORK_XFRM

+static 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)
@@ -1377,23 +1655,27 @@ int security_xfrm_policy_alloc(struct xfrm_sec_ctx **ctxp,
}
EXPORT_SYMBOL(security_xfrm_policy_alloc);

+static 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 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 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 LIST_HEAD(hooks_xfrm_state_alloc);
int security_xfrm_state_alloc(struct xfrm_state *x,
struct xfrm_user_sec_ctx *sec_ctx)
{
@@ -1401,35 +1683,43 @@ int security_xfrm_state_alloc(struct xfrm_state *x,
}
EXPORT_SYMBOL(security_xfrm_state_alloc);

+static 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 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 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 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 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 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);
@@ -1440,7 +1730,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);
}
@@ -1450,25 +1742,30 @@ EXPORT_SYMBOL(security_skb_classify_flow);

#ifdef CONFIG_KEYS

+static 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 LIST_HEAD(hooks_key_free);
void security_key_free(struct key *key)
{
call_void_hook(key_free, key);
}

+static 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 LIST_HEAD(hooks_key_getsecurity);
int security_key_getsecurity(struct key *key, char **_buffer)
{
+ *_buffer = NULL;
return call_int_hook(key_getsecurity, key, _buffer);
}

@@ -1476,21 +1773,25 @@ int security_key_getsecurity(struct key *key, char **_buffer)

#ifdef CONFIG_AUDIT

+static 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 LIST_HEAD(hooks_audit_rule_known);
int security_audit_rule_known(struct audit_krule *krule)
{
return call_int_hook(audit_rule_known, krule);
}

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

+static LIST_HEAD(hooks_audit_rule_match);
int security_audit_rule_match(u32 secid, u32 field, u32 op, void *lsmrule,
struct audit_context *actx)
{
@@ -1498,3 +1799,736 @@ 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)
+{
+ pr_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_fw_from_file,
+ sop->kernel_fw_from_file, 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;
+
+ list_for_each_entry(shp, head, shl_head)
+ if (shp->shl_ops == sop) {
+ list_del_rcu(&shp->shl_head);
+ return;
+ }
+}
+
+void security_module_disable(struct security_operations *sop)
+{
+ pr_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_fw_from_file, 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 b0e9404..9530124 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -1938,12 +1938,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);
@@ -1955,12 +1949,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);
}

@@ -2004,12 +1992,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);
}

@@ -2087,12 +2069,12 @@ static int selinux_vm_enough_memory(struct mm_struct *mm, long pages)
{
int rc, cap_sys_admin = 0;

- rc = selinux_capable(current_cred(), &init_user_ns, CAP_SYS_ADMIN,
- SECURITY_CAP_NOAUDIT);
+ rc = cred_has_capability(current_cred(), CAP_SYS_ADMIN,
+ SECURITY_CAP_NOAUDIT);
if (rc == 0)
cap_sys_admin = 1;

- return __vm_enough_memory(mm, pages, cap_sys_admin);
+ return cap_sys_admin;
}

/* binprm security operations */
@@ -2106,10 +2088,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)
@@ -2233,7 +2211,7 @@ static int selinux_bprm_secureexec(struct linux_binprm *bprm)
PROCESS__NOATSECURE, NULL);
}

- return (atsecure || cap_bprm_secureexec(bprm));
+ return atsecure;
}

static int match_file(const void *p, struct file *file, unsigned fd)
@@ -3051,8 +3029,8 @@ static int selinux_inode_getsecurity(const struct inode *inode, const char *name
* and lack of permission just means that we fall back to the
* in-core context value, not a denial.
*/
- error = selinux_capable(current_cred(), &init_user_ns, CAP_MAC_ADMIN,
- SECURITY_CAP_NOAUDIT);
+ error = cred_has_capability(current_cred(), CAP_MAC_ADMIN,
+ SECURITY_CAP_NOAUDIT);
if (!error)
error = security_sid_to_context_force(isec->sid, &context,
&size);
@@ -3237,12 +3215,7 @@ error:

static int selinux_mmap_addr(unsigned long addr)
{
- int rc;
-
- /* do DAC check on address space usage */
- rc = cap_mmap_addr(addr);
- if (rc)
- return rc;
+ int rc = 0;

if (addr < CONFIG_LSM_MMAP_MIN_ADDR) {
u32 sid = current_sid();
@@ -3560,23 +3533,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);
}

@@ -3602,12 +3563,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);
}

@@ -5029,12 +4984,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);
}

@@ -6145,7 +6094,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 e6ab307..53660f9 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();
@@ -585,12 +573,11 @@ static void smack_bprm_committing_creds(struct linux_binprm *bprm)
static int smack_bprm_secureexec(struct linux_binprm *bprm)
{
struct task_smack *tsp = current_security();
- int ret = cap_bprm_secureexec(bprm);

- if (!ret && (tsp->smk_task != tsp->smk_forked))
- ret = 1;
+ if (tsp->smk_task != tsp->smk_forked)
+ return 1;

- return ret;
+ return 0;
}

/*
@@ -1703,12 +1690,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 +1702,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 +1726,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__);
}

/**
@@ -3892,7 +3864,6 @@ struct security_operations smack_ops = {
.file_lock = smack_file_lock,
.file_fcntl = smack_file_fcntl,
.mmap_file = smack_mmap_file,
- .mmap_addr = cap_mmap_addr,
.file_set_fowner = smack_file_set_fowner,
.file_send_sigiotask = smack_file_send_sigiotask,
.file_receive = smack_file_receive,
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..8fa7e30 100644
--- a/security/yama/yama_lsm.c
+++ b/security/yama/yama_lsm.c
@@ -135,7 +135,7 @@ static void yama_ptracer_del(struct task_struct *tracer,
* yama_task_free - check for task_pid to remove from exception list
* @task: task being removed
*/
-void yama_task_free(struct task_struct *task)
+static void yama_task_free(struct task_struct *task)
{
yama_ptracer_del(task, task);
}
@@ -151,16 +151,12 @@ void yama_task_free(struct task_struct *task)
* Return 0 on success, -ve on error. -ENOSYS is returned when Yama
* does not handle the given option.
*/
-int yama_task_prctl(int option, unsigned long arg2, unsigned long arg3,
+static 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
@@ -279,18 +275,11 @@ static int ptracer_exception_found(struct task_struct *tracer,
*
* Returns 0 if following the ptrace is allowed, -ve on error.
*/
-int yama_ptrace_access_check(struct task_struct *child,
+static int yama_ptrace_access_check(struct task_struct *child,
unsigned int mode)
{
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) {
@@ -333,16 +322,9 @@ int yama_ptrace_access_check(struct task_struct *child,
*
* Returns 0 if following the ptrace is allowed, -ve on error.
*/
-int yama_ptrace_traceme(struct task_struct *parent)
+static 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

+ pr_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-10-17 15:25:05 UTC
Permalink
Post by Casey Schaufler
Subject: [PATCH v17 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/selinux/hooks.c b/security/selinux/hooks.c
index b0e9404..9530124 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -2087,12 +2069,12 @@ static int selinux_vm_enough_memory(struct mm_struct *mm, long pages)
{
int rc, cap_sys_admin = 0;
- rc = selinux_capable(current_cred(), &init_user_ns, CAP_SYS_ADMIN,
- SECURITY_CAP_NOAUDIT);
+ rc = cred_has_capability(current_cred(), CAP_SYS_ADMIN,
+ SECURITY_CAP_NOAUDIT);
if (rc == 0)
cap_sys_admin = 1;
- return __vm_enough_memory(mm, pages, cap_sys_admin);
+ return cap_sys_admin;
}
Not sure it is a good idea to change the return code convention for the
hook, although I see you handle it in the caller. But why not just have
the hook return 0 if allowed, -errno otherwise like most other hooks
(and as it did before). This would mean just returning rc here.
Otherwise, you need to change include/linux/security.h inline
documentation for @vm_enough_memory to indicate the change in the return
code convention.
Post by Casey Schaufler
@@ -2233,7 +2211,7 @@ static int selinux_bprm_secureexec(struct linux_binprm *bprm)
PROCESS__NOATSECURE, NULL);
}
- return (atsecure || cap_bprm_secureexec(bprm));
+ return atsecure;
}
This hook on the other hand is expected to always return 0 or 1 and its
value is used directly to set the AT_SECURE auxv entry in
fs/binfmt_elf.c. So you should return !!atsecure or (atsecure != 0).
Post by Casey Schaufler
static int match_file(const void *p, struct file *file, unsigned fd)
@@ -3051,8 +3029,8 @@ static int selinux_inode_getsecurity(const struct inode *inode, const char *name
* and lack of permission just means that we fall back to the
* in-core context value, not a denial.
*/
- error = selinux_capable(current_cred(), &init_user_ns, CAP_MAC_ADMIN,
- SECURITY_CAP_NOAUDIT);
+ error = cred_has_capability(current_cred(), CAP_MAC_ADMIN,
+ SECURITY_CAP_NOAUDIT);
This loses the cap_capable(...CAC_MAC_ADMIN...) check that would have
been applied by selinux_capable() prior to the patch. Either you need
to also call cap_capable() here in addition to cred_has_capability() or
you need to call security_capable_noaudit() to invoke them both.
--
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-17 17:23:22 UTC
Permalink
Post by Stephen Smalley
Post by Casey Schaufler
Subject: [PATCH v17 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/selinux/hooks.c b/security/selinux/hooks.c
index b0e9404..9530124 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -2087,12 +2069,12 @@ static int selinux_vm_enough_memory(struct mm_struct *mm, long pages)
{
int rc, cap_sys_admin = 0;
- rc = selinux_capable(current_cred(), &init_user_ns, CAP_SYS_ADMIN,
- SECURITY_CAP_NOAUDIT);
+ rc = cred_has_capability(current_cred(), CAP_SYS_ADMIN,
+ SECURITY_CAP_NOAUDIT);
if (rc == 0)
cap_sys_admin = 1;
- return __vm_enough_memory(mm, pages, cap_sys_admin);
+ return cap_sys_admin;
}
Not sure it is a good idea to change the return code convention for the
hook, although I see you handle it in the caller. But why not just have
the hook return 0 if allowed, -errno otherwise like most other hooks
(and as it did before). This would mean just returning rc here.
Otherwise, you need to change include/linux/security.h inline
code convention.
The problem with security_vm_enough_memory() is that it's not asking
the module if an action is allowed, it's asking if it should be doing
the check with or without CAP_SYS_ADMIN, and then it's doing the check.
I suppose it would be rational to return -EPERM if you shouldn't use
the capability, but that would still just be a flag to the surrounding
code to call __vm_enough_memory(,,0). I think changing the documentation
in security.h is the better approach.
Post by Stephen Smalley
Post by Casey Schaufler
@@ -2233,7 +2211,7 @@ static int selinux_bprm_secureexec(struct linux_binprm *bprm)
PROCESS__NOATSECURE, NULL);
}
- return (atsecure || cap_bprm_secureexec(bprm));
+ return atsecure;
}
This hook on the other hand is expected to always return 0 or 1 and its
value is used directly to set the AT_SECURE auxv entry in
fs/binfmt_elf.c. So you should return !!atsecure or (atsecure != 0).
Easy enough fix.
Post by Stephen Smalley
Post by Casey Schaufler
static int match_file(const void *p, struct file *file, unsigned fd)
@@ -3051,8 +3029,8 @@ static int selinux_inode_getsecurity(const struct inode *inode, const char *name
* and lack of permission just means that we fall back to the
* in-core context value, not a denial.
*/
- error = selinux_capable(current_cred(), &init_user_ns, CAP_MAC_ADMIN,
- SECURITY_CAP_NOAUDIT);
+ error = cred_has_capability(current_cred(), CAP_MAC_ADMIN,
+ SECURITY_CAP_NOAUDIT);
This loses the cap_capable(...CAC_MAC_ADMIN...) check that would have
been applied by selinux_capable() prior to the patch. Either you need
to also call cap_capable() here in addition to cred_has_capability() or
you need to call security_capable_noaudit() to invoke them both.
Looks like I didn't dive deep enough in the SELinux code to see that
selinux_capable() wasn't making that call. I am really hesitant to call
security_capable() from inside a module. That just looks too much like
the layers are getting swirled. Do you want AppArmor checks made here?
It's not an issue now, but I think it best that each module protect its
own data its own way. I'm making allowances for the code in the capability
module, which is both an LSM and an independent security feature.

In any case, fair enough. A cap_capable call goes in.

Thank you for the review.
Post by Stephen Smalley
--
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
Paul Moore
2014-10-20 22:57:07 UTC
Permalink
Post by Casey Schaufler
Subject: [PATCH v17 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.
I apologize if I missed it in the v16 (or earlier) patchset, but thank you for
taking a simpler approach here and avoiding the difficulty of stacking
multiple "big" LSMs. I think the multiple small/stateless, one big LSM
approach is still very useful and a much easier problem to solve (note, that
is "easier", not "easy").

I hope to offer a proper review at some point, but time is tight at the
moment. I just wanted to pass along a thanks, for sticking with this and
incorporating my vague feedback.
--
paul moore
security and virtualization @ redhat

--
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-17 00:48:31 UTC
Permalink
Subject: [PATCH v17 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 | 1137 -------------------------------------------------
1 file changed, 1137 deletions(-)

diff --git a/security/capability.c b/security/capability.c
deleted file mode 100644
index a74fde6..0000000
--- a/security/capability.c
+++ /dev/null
@@ -1,1137 +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_fw_from_file(struct file *file, char *buf, size_t size)
-{
- 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_fw_from_file);
- 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
Casey Schaufler
2014-10-17 00:48:38 UTC
Permalink
Subject: [PATCH v17 4/4] LSM: Stacking for existing getcap hooks

The capget hooks required somewhat more thought for
stacking, but in the end proved simple enough. cap_capget
sets the basic values. AppArmor ands off some bits.
SELinux may decide you don't get to see the bits. Once
untangled there isn't anything preventing normal stacking.

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

---

security/apparmor/lsm.c | 8 ++++----
security/selinux/hooks.c | 15 +--------------
2 files changed, 5 insertions(+), 18 deletions(-)

diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c
index 30e562a..207b04f 100644
--- a/security/apparmor/lsm.c
+++ b/security/apparmor/lsm.c
@@ -115,10 +115,10 @@ static int apparmor_capget(struct task_struct *target, kernel_cap_t *effective,
cred = __task_cred(target);
profile = aa_cred_profile(cred);

- *effective = cred->cap_effective;
- *inheritable = cred->cap_inheritable;
- *permitted = cred->cap_permitted;
-
+ /*
+ * cap_capget is stacked ahead of this and will
+ * initialize effective and permitted.
+ */
if (!unconfined(profile) && !COMPLAIN_MODE(profile)) {
*effective = cap_intersect(*effective, profile->caps.allow);
*permitted = cap_intersect(*permitted, profile->caps.allow);
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 9530124..91b89dd 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -1955,13 +1955,7 @@ static int selinux_ptrace_traceme(struct task_struct *parent)
static int selinux_capget(struct task_struct *target, kernel_cap_t *effective,
kernel_cap_t *inheritable, kernel_cap_t *permitted)
{
- int error;
-
- error = current_has_perm(target, PROCESS__GETCAP);
- if (error)
- return error;
-
- return cap_capget(target, effective, inheritable, permitted);
+ return current_has_perm(target, PROCESS__GETCAP);
}

static int selinux_capset(struct cred *new, const struct cred *old,
@@ -1969,13 +1963,6 @@ static int selinux_capset(struct cred *new, const struct cred *old,
const kernel_cap_t *inheritable,
const kernel_cap_t *permitted)
{
- int error;
-
- error = cap_capset(new, old,
- effective, inheritable, permitted);
- if (error)
- return error;
-
return cred_has_perm(old, new, PROCESS__SETCAP);
}


--
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...