Re: [PATCH 6/7 v22] LSM: Switch to lists of hooks

From: Paul Moore
Date: Thu May 07 2015 - 17:05:49 EST


On Saturday, May 02, 2015 03:11:42 PM Casey Schaufler wrote:
> Subject: [PATCH 6/7 v22] LSM: Switch to lists of hooks
>
> Instead of using a vector of security operations
> with explicit, special case stacking of the capability
> and yama hooks use lists of hooks with capability and
> yama hooks included as appropriate.
>
> The security_operations structure is no longer required.
> Instead, there is a union of the function pointers that
> allows all the hooks lists to use a common mechanism for
> list management while retaining typing. Each module
> supplies an array describing the hooks it provides instead
> of a sparsely populated security_operations structure.
> The description includes the element that gets put on
> the hook list, avoiding the issues surrounding individual
> element allocation.
>
> The method for registering security modules is changed to
> reflect the information available. The method for removing
> a module, currently only used by SELinux, has also changed.
> It should be generic now, however if there are potential
> race conditions based on ordering of hook removal that needs
> to be addressed by the calling module.
>
> The security hooks are called from the lists and the first
> failure is returned.
>
> Signed-off-by: Casey Schaufler <casey@xxxxxxxxxxxxxxxx>

Ah, here is the tricky one :)

It all looks very reasonable to me, in the interest of full disclosure I
didn't verify each and every hook but I know Stephen did previously so I trust
it - Stephen's much smarter about these things than I am anyway ;).

Acked-by: Paul Moore <paul@xxxxxxxxxxxxxx>

> diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h
> index bbbf6fe..f014f25 100644
> --- a/include/linux/lsm_hooks.h
> +++ b/include/linux/lsm_hooks.h
> @@ -25,21 +25,10 @@
> #define __LINUX_LSM_HOOKS_H
>
> #include <linux/security.h>
> -
> -/* Maximum number of letters for an LSM name string */
> -#define SECURITY_NAME_MAX 10
> -
> -#ifdef CONFIG_SECURITY
> +#include <linux/init.h>
> +#include <linux/rculist.h>
>
> /**
> - * struct security_operations - main security structure
> - *
> - * Security module identifier.
> - *
> - * @name:
> - * A string that acts as a unique identifier for the LSM with max number
> - * of characters = SECURITY_NAME_MAX.
> - *
> * Security hooks for program execution operations.
> *
> * @bprm_set_creds:
> @@ -1310,9 +1299,7 @@
> * This is the main security structure.
> */
>
> -struct security_operations {
> - char name[SECURITY_NAME_MAX + 1];
> -
> +union security_list_options {
> int (*binder_set_context_mgr)(struct task_struct *mgr);
> int (*binder_transaction)(struct task_struct *from,
> struct task_struct *to);
> @@ -1838,21 +1825,62 @@ struct security_hook_heads {
> };
>
> /*
> + * Security module hook list structure.
> + * For use with generic list macros for common operations.
> + */
> +struct security_hook_list {
> + struct list_head list;
> + struct list_head *head;
> + union security_list_options hook;
> +};
> +
> +/*
> * Initializing a security_hook_list structure takes
> * up a lot of space in a source file. This macro takes
> * care of the common case and reduces the amount of
> * text involved.
> - * Casey says: Comment is true in the next patch.
> */
> -#define LSM_HOOK_INIT(HEAD, HOOK) .HEAD = HOOK
> +#define LSM_HOOK_INIT(HEAD, HOOK) \
> + { .head = &security_hook_heads.HEAD, .hook = { .HEAD = HOOK } }
>
> -/* prototypes */
> -extern int security_module_enable(struct security_operations *ops);
> -extern int register_security(struct security_operations *ops);
> -extern void __init security_fixup_ops(struct security_operations *ops);
> -extern void reset_security_ops(void);
> +extern struct security_hook_heads security_hook_heads;
>
> -#endif /* CONFIG_SECURITY */
> +static inline void security_add_hooks(struct security_hook_list *hooks,
> + int count)
> +{
> + int i;
>
> -#endif /* ! __LINUX_LSM_HOOKS_H */
> + for (i = 0; i < count; i++)
> + list_add_tail_rcu(&hooks[i].list, hooks[i].head);
> +}
> +
> +#ifdef CONFIG_SECURITY_SELINUX_DISABLE
> +/*
> + * Assuring the safety of deleting a security module is up to
> + * the security module involved. This may entail ordering the
> + * module's hook list in a particular way, refusing to disable
> + * the module once a policy is loaded or any number of other
> + * actions better imagined than described.
> + *
> + * The name of the configuration option reflects the only module
> + * that currently uses the mechanism. Any developer who thinks
> + * disabling their module is a good idea needs to be at least as
> + * careful as the SELinux team.
> + */
> +static inline void security_delete_hooks(struct security_hook_list *hooks,
> + int count)
> +{
> + int i;
>
> + for (i = 0; i < count; i++)
> + list_del_rcu(&hooks[i].list);
> +}
> +#endif /* CONFIG_SECURITY_SELINUX_DISABLE */
> +
> +extern int __init security_module_enable(const char *module);
> +extern void __init capability_add_hooks(void);
> +#ifdef CONFIG_SECURITY_YAMA_STACKED
> +void __init yama_add_hooks(void);
> +#endif
> +
> +#endif /* ! __LINUX_LSM_HOOKS_H */
> diff --git a/include/linux/security.h b/include/linux/security.h
> index a2a100e..8c8175d 100644
> --- a/include/linux/security.h
> +++ b/include/linux/security.h
> @@ -27,6 +27,7 @@
> #include <linux/slab.h>
> #include <linux/err.h>
> #include <linux/string.h>
> +#include <linux/mm.h>
>
> struct linux_binprm;
> struct cred;
> @@ -54,9 +55,6 @@ struct xattr;
> struct xfrm_sec_ctx;
> struct mm_struct;
>
> -/* Maximum number of letters for an LSM name string */
> -#define SECURITY_NAME_MAX 10
> -
> /* If capable should audit the security request */
> #define SECURITY_CAP_NOAUDIT 0
> #define SECURITY_CAP_AUDIT 1
> @@ -69,10 +67,7 @@ struct audit_krule;
> struct user_namespace;
> struct timezone;
>
> -/*
> - * These functions are in security/capability.c and are used
> - * as the default capabilities functions
> - */
> +/* These functions are in security/commoncap.c */
> extern int cap_capable(const struct cred *cred, struct user_namespace *ns,
> int cap, int audit);
> extern int cap_settime(const struct timespec *ts, const struct timezone
> *tz); @@ -114,8 +109,6 @@ struct xfrm_state;
> struct xfrm_user_sec_ctx;
> struct seq_file;
>
> -extern int cap_netlink_send(struct sock *sk, struct sk_buff *skb);
> -
> #ifdef CONFIG_MMU
> extern unsigned long mmap_min_addr;
> extern unsigned long dac_mmap_min_addr;
> @@ -472,7 +465,7 @@ static inline int security_settime(const struct timespec
> *ts,
>
> static inline int security_vm_enough_memory_mm(struct mm_struct *mm, long
> pages) {
> - return cap_vm_enough_memory(mm, pages);
> + return __vm_enough_memory(mm, pages, cap_vm_enough_memory(mm, pages));
> }
>
> static inline int security_bprm_set_creds(struct linux_binprm *bprm)
> @@ -1075,7 +1068,7 @@ static inline int security_setprocattr(struct
> task_struct *p, char *name, void *
>
> static inline int security_netlink_send(struct sock *sk, struct sk_buff
> *skb) {
> - return cap_netlink_send(sk, skb);
> + return 0;
> }
>
> static inline int security_ismaclabel(const char *name)
> @@ -1643,36 +1636,5 @@ 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 */
> -
> #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..dc0027b 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;
> @@ -531,15 +529,13 @@ cleanup:
> */
> int apparmor_bprm_secureexec(struct linux_binprm *bprm)
> {
> - int ret = cap_bprm_secureexec(bprm);
> -
> /* the decision to use secure exec is computed in set_creds
> * and stored in bprm->unsafe.
> */
> - if (!ret && (bprm->unsafe & AA_SECURE_X_NEEDED))
> - ret = 1;
> + if (bprm->unsafe & AA_SECURE_X_NEEDED)
> + return 1;
>
> - return ret;
> + return 0;
> }
>
> /**
> diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c
> index f542532..5696874 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);
> }
>
> @@ -123,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);
> @@ -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;
> }
>
> @@ -615,9 +605,7 @@ static int apparmor_task_setrlimit(struct task_struct
> *task, return error;
> }
>
> -static struct security_operations apparmor_ops = {
> - LSM_HOOK_INIT(name, "apparmor"),
> -
> +static struct security_hook_list apparmor_hooks[] = {
> LSM_HOOK_INIT(ptrace_access_check, apparmor_ptrace_access_check),
> LSM_HOOK_INIT(ptrace_traceme, apparmor_ptrace_traceme),
> LSM_HOOK_INIT(capget, apparmor_capget),
> @@ -640,7 +628,6 @@ static struct security_operations apparmor_ops = {
> LSM_HOOK_INIT(file_alloc_security, apparmor_file_alloc_security),
> LSM_HOOK_INIT(file_free_security, apparmor_file_free_security),
> LSM_HOOK_INIT(mmap_file, apparmor_mmap_file),
> - LSM_HOOK_INIT(mmap_addr, cap_mmap_addr),
> LSM_HOOK_INIT(file_mprotect, apparmor_file_mprotect),
> LSM_HOOK_INIT(file_lock, apparmor_file_lock),
>
> @@ -898,7 +885,7 @@ static int __init apparmor_init(void)
> {
> int error;
>
> - if (!apparmor_enabled || !security_module_enable(&apparmor_ops)) {
> + if (!apparmor_enabled || !security_module_enable("apparmor")) {
> aa_info_message("AppArmor disabled by boot time parameter");
> apparmor_enabled = 0;
> return 0;
> @@ -913,17 +900,10 @@ static int __init apparmor_init(void)
> error = set_init_cxt();
> if (error) {
> AA_ERROR("Failed to set context on init task\n");
> - goto register_security_out;
> - }
> -
> - error = register_security(&apparmor_ops);
> - if (error) {
> - struct cred *cred = (struct cred *)current->real_cred;
> - aa_free_task_context(cred_cxt(cred));
> - cred_cxt(cred) = NULL;
> - AA_ERROR("Unable to register AppArmor\n");
> - goto register_security_out;
> + aa_free_root_ns();
> + goto alloc_out;
> }
> + security_add_hooks(apparmor_hooks, ARRAY_SIZE(apparmor_hooks));
>
> /* Report that AppArmor successfully initialized */
> apparmor_initialized = 1;
> @@ -936,9 +916,6 @@ static int __init apparmor_init(void)
>
> return error;
>
> -register_security_out:
> - aa_free_root_ns();
> -
> alloc_out:
> aa_destroy_aafs();
>
> diff --git a/security/commoncap.c b/security/commoncap.c
> index f2875cd..d103f5a4 100644
> --- a/security/commoncap.c
> +++ b/security/commoncap.c
> @@ -12,7 +12,7 @@
> #include <linux/module.h>
> #include <linux/init.h>
> #include <linux/kernel.h>
> -#include <linux/security.h>
> +#include <linux/lsm_hooks.h>
> #include <linux/file.h>
> #include <linux/mm.h>
> #include <linux/mman.h>
> @@ -53,11 +53,6 @@ static void warn_setuid_and_fcaps_mixed(const char
> *fname) }
> }
>
> -int cap_netlink_send(struct sock *sk, struct sk_buff *skb)
> -{
> - return 0;
> -}
> -
> /**
> * cap_capable - Determine whether a task has a particular effective
> capability * @cred: The credentials to use
> @@ -941,7 +936,7 @@ int cap_task_prctl(int option, unsigned long arg2,
> unsigned long arg3, * @pages: The size of the mapping
> *
> * Determine whether the allocation of a new virtual mapping by the current
> - * task is permitted, returning 0 if permission is granted, -ve if not. +
> * task is permitted, returning 1 if permission is granted, 0 if not. */
> int cap_vm_enough_memory(struct mm_struct *mm, long pages)
> {
> @@ -950,7 +945,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;
> }
>
> /*
> @@ -981,3 +976,33 @@ int cap_mmap_file(struct file *file, unsigned long
> reqprot, {
> return 0;
> }
> +
> +#ifdef CONFIG_SECURITY
> +
> +struct security_hook_list capability_hooks[] = {
> + LSM_HOOK_INIT(capable, cap_capable),
> + LSM_HOOK_INIT(settime, cap_settime),
> + LSM_HOOK_INIT(ptrace_access_check, cap_ptrace_access_check),
> + LSM_HOOK_INIT(ptrace_traceme, cap_ptrace_traceme),
> + LSM_HOOK_INIT(capget, cap_capget),
> + LSM_HOOK_INIT(capset, cap_capset),
> + LSM_HOOK_INIT(bprm_set_creds, cap_bprm_set_creds),
> + LSM_HOOK_INIT(bprm_secureexec, cap_bprm_secureexec),
> + LSM_HOOK_INIT(inode_need_killpriv, cap_inode_need_killpriv),
> + LSM_HOOK_INIT(inode_killpriv, cap_inode_killpriv),
> + LSM_HOOK_INIT(mmap_addr, cap_mmap_addr),
> + LSM_HOOK_INIT(mmap_file, cap_mmap_file),
> + LSM_HOOK_INIT(task_fix_setuid, cap_task_fix_setuid),
> + LSM_HOOK_INIT(task_prctl, cap_task_prctl),
> + LSM_HOOK_INIT(task_setscheduler, cap_task_setscheduler),
> + LSM_HOOK_INIT(task_setioprio, cap_task_setioprio),
> + LSM_HOOK_INIT(task_setnice, cap_task_setnice),
> + LSM_HOOK_INIT(vm_enough_memory, cap_vm_enough_memory),
> +};
> +
> +void __init capability_add_hooks(void)
> +{
> + security_add_hooks(capability_hooks, ARRAY_SIZE(capability_hooks));
> +}
> +
> +#endif /* CONFIG_SECURITY */
> diff --git a/security/security.c b/security/security.c
> index 02dc720..bd4c5f6 100644
> --- a/security/security.c
> +++ b/security/security.c
> @@ -29,24 +29,13 @@
>
> #define MAX_LSM_EVM_XATTR 2
>
> +/* Maximum number of letters for an LSM name string */
> +#define SECURITY_NAME_MAX 10
> +
> /* 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;
> @@ -64,20 +53,27 @@ static void __init do_security_initcalls(void)
> */
> int __init security_init(void)
> {
> - printk(KERN_INFO "Security Framework initialized\n");
> + pr_info("Security Framework initialized\n");
>
> - security_fixup_ops(&default_security_ops);
> - security_ops = &default_security_ops;
> + /*
> + * Always load the capability module.
> + */
> + capability_add_hooks();
> +#ifdef CONFIG_SECURITY_YAMA_STACKED
> + /*
> + * If Yama is configured for stacking load it next.
> + */
> + yama_add_hooks();
> +#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)
> {
> @@ -88,7 +84,7 @@ __setup("security=", choose_lsm);
>
> /**
> * security_module_enable - Load given security module on boot ?
> - * @ops: a pointer to the struct security_operations that is to be checked.
> + * @module: the name of the module
> *
> * Each LSM must pass this method before registering its own operations
> * to avoid security registration races. This method may also be used
> @@ -100,41 +96,13 @@ __setup("security=", choose_lsm);
> * choose an alternate LSM at boot time.
> * Otherwise, return false.
> */
> -int __init security_module_enable(struct security_operations *ops)
> +int __init security_module_enable(const char *module)
> {
> - return !strcmp(ops->name, chosen_lsm);
> -}
> -
> -/**
> - * register_security - registers a security framework with the kernel
> - * @ops: a pointer to the struct security_options that is to be registered
> - *
> - * This function allows a security module to register itself with the
> - * kernel security subsystem. Some rudimentary checking is done on the
> @ops - * value passed to this function. You'll need to check first if your
> LSM - * is allowed to register its @ops by calling
> security_module_enable(@ops). - *
> - * If there is already a security module registered with the kernel,
> - * an error will be returned. Otherwise %0 is returned on success.
> - */
> -int __init register_security(struct security_operations *ops)
> -{
> - if (verify(ops)) {
> - printk(KERN_DEBUG "%s could not verify "
> - "security_operations structure.\n", __func__);
> - return -EINVAL;
> - }
> -
> - if (security_ops != &default_security_ops)
> - return -EAGAIN;
> -
> - security_ops = ops;
> -
> - return 0;
> + return !strcmp(module, chosen_lsm);
> }
>
> /*
> - * Hook operation macros.
> + * Hook list operation macros.
> *
> * call_void_hook:
> * This is a hook that does not return a value.
> @@ -143,8 +111,27 @@ int __init register_security(struct security_operations
> *ops) * This is a hook that returns a value.
> */
>
> -#define call_void_hook(FUNC, ...) security_ops->FUNC(__VA_ARGS__)
> -#define call_int_hook(FUNC, IRC, ...) security_ops->FUNC(__VA_ARGS__)
> +#define call_void_hook(FUNC, ...) \
> + do { \
> + struct security_hook_list *P; \
> + \
> + list_for_each_entry(P, &security_hook_heads.FUNC, list) \
> + P->hook.FUNC(__VA_ARGS__); \
> + } while (0)
> +
> +#define call_int_hook(FUNC, IRC, ...) ({ \
> + int RC = IRC; \
> + do { \
> + struct security_hook_list *P; \
> + \
> + list_for_each_entry(P, &security_hook_heads.FUNC, list) { \
> + RC = P->hook.FUNC(__VA_ARGS__); \
> + if (RC != 0) \
> + break; \
> + } \
> + } while (0); \
> + RC; \
> +})
>
> /* Security operations */
>
> @@ -173,23 +160,11 @@ int security_binder_transfer_file(struct task_struct
> *from,
>
> 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, 0, child, mode);
> }
>
> 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, 0, parent);
> }
>
> @@ -245,7 +220,25 @@ int security_settime(const struct timespec *ts, const
> struct timezone *tz)
>
> int security_vm_enough_memory_mm(struct mm_struct *mm, long pages)
> {
> - return call_int_hook(vm_enough_memory, 0, mm, pages);
> + struct security_hook_list *hp;
> + 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(hp, &security_hook_heads.vm_enough_memory, list) {
> + rc = hp->hook.vm_enough_memory(mm, pages);
> + if (rc <= 0) {
> + cap_sys_admin = 0;
> + break;
> + }
> + }
> + return __vm_enough_memory(mm, pages, cap_sys_admin);
> }
>
> int security_bprm_set_creds(struct linux_binprm *bprm)
> @@ -335,8 +328,9 @@ int security_sb_set_mnt_opts(struct super_block *sb,
> unsigned long kern_flags,
> unsigned long *set_kern_flags)
> {
> - return call_int_hook(sb_set_mnt_opts, 0, sb, opts, kern_flags,
> - set_kern_flags);
> + return call_int_hook(sb_set_mnt_opts,
> + opts->num_mnt_opts ? -EOPNOTSUPP : 0, sb,
> + opts, kern_flags, set_kern_flags);
> }
> EXPORT_SYMBOL(security_sb_set_mnt_opts);
>
> @@ -369,8 +363,8 @@ int security_dentry_init_security(struct dentry *dentry,
> int mode, struct qstr *name, void **ctx,
> u32 *ctxlen)
> {
> - return call_int_hook(dentry_init_security, 0, dentry, mode, name,
> - ctx, ctxlen);
> + return call_int_hook(dentry_init_security, -EOPNOTSUPP, dentry, mode,
> + name, ctx, ctxlen);
> }
> EXPORT_SYMBOL(security_dentry_init_security);
>
> @@ -390,7 +384,7 @@ int security_inode_init_security(struct inode *inode,
> struct inode *dir, NULL, NULL, NULL);
> memset(new_xattrs, 0, sizeof(new_xattrs));
> lsm_xattr = new_xattrs;
> - ret = call_int_hook(inode_init_security, 0, inode, dir, qstr,
> + ret = call_int_hook(inode_init_security, -EOPNOTSUPP, inode, dir, qstr,
> &lsm_xattr->name,
> &lsm_xattr->value,
> &lsm_xattr->value_len);
> @@ -636,8 +630,15 @@ int security_inode_setxattr(struct dentry *dentry,
> const char *name,
>
> if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
> return 0;
> - ret = call_int_hook(inode_setxattr, 0, dentry, name, value, size,
> + /*
> + * SELinux and Smack integrate the cap call,
> + * so assume that all LSMs supplying this call do so.
> + */
> + ret = call_int_hook(inode_setxattr, 1, dentry, name, value, size,
> flags);
> +
> + if (ret == 1)
> + ret = cap_inode_setxattr(dentry, name, value, size, flags);
> if (ret)
> return ret;
> ret = ima_inode_setxattr(dentry, name, value, size);
> @@ -675,7 +676,13 @@ int security_inode_removexattr(struct dentry *dentry,
> const char *name)
>
> if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
> return 0;
> - ret = call_int_hook(inode_removexattr, 0, dentry, name);
> + /*
> + * SELinux and Smack integrate the cap call,
> + * so assume that all LSMs supplying this call do so.
> + */
> + ret = call_int_hook(inode_removexattr, 1, dentry, name);
> + if (ret == 1)
> + ret = cap_inode_removexattr(dentry, name);
> if (ret)
> return ret;
> ret = ima_inode_removexattr(dentry, name);
> @@ -698,15 +705,16 @@ int security_inode_getsecurity(const struct inode
> *inode, const char *name, void {
> if (unlikely(IS_PRIVATE(inode)))
> return -EOPNOTSUPP;
> - return call_int_hook(inode_getsecurity, 0, inode, name, buffer, alloc);
> + return call_int_hook(inode_getsecurity, -EOPNOTSUPP, 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 call_int_hook(inode_setsecurity, 0, inode, name, value, size,
> - flags);
> + return call_int_hook(inode_setsecurity, -EOPNOTSUPP, inode, name,
> + value, size, flags);
> }
>
> int security_inode_listsecurity(struct inode *inode, char *buffer, size_t
> buffer_size) @@ -847,9 +855,6 @@ int security_task_create(unsigned long
> clone_flags)
>
> void security_task_free(struct task_struct *task)
> {
> -#ifdef CONFIG_SECURITY_YAMA_STACKED
> - yama_task_free(task);
> -#endif
> call_void_hook(task_free, task);
> }
>
> @@ -932,6 +937,7 @@ int security_task_getsid(struct task_struct *p)
>
> void security_task_getsecid(struct task_struct *p, u32 *secid)
> {
> + *secid = 0;
> call_void_hook(task_getsecid, p, secid);
> }
> EXPORT_SYMBOL(security_task_getsecid);
> @@ -986,13 +992,19 @@ int security_task_wait(struct task_struct *p)
> 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, 0, option, arg2, arg3, arg4, arg5);
> + int thisrc;
> + int rc = -ENOSYS;
> + struct security_hook_list *hp;
> +
> + list_for_each_entry(hp, &security_hook_heads.task_prctl, list) {
> + thisrc = hp->hook.task_prctl(option, arg2, arg3, arg4, arg5);
> + if (thisrc != -ENOSYS) {
> + rc = thisrc;
> + if (thisrc != 0)
> + break;
> + }
> + }
> + return rc;
> }
>
> void security_task_to_inode(struct task_struct *p, struct inode *inode)
> @@ -1007,6 +1019,7 @@ int security_ipc_permission(struct kern_ipc_perm
> *ipcp, short flag)
>
> void security_ipc_getsecid(struct kern_ipc_perm *ipcp, u32 *secid)
> {
> + *secid = 0;
> call_void_hook(ipc_getsecid, ipcp, secid);
> }
>
> @@ -1113,12 +1126,12 @@ EXPORT_SYMBOL(security_d_instantiate);
>
> int security_getprocattr(struct task_struct *p, char *name, char **value)
> {
> - return call_int_hook(getprocattr, 0, p, name, value);
> + return call_int_hook(getprocattr, -EINVAL, p, name, value);
> }
>
> int security_setprocattr(struct task_struct *p, char *name, void *value,
> size_t size) {
> - return call_int_hook(setprocattr, 0, p, name, value, size);
> + return call_int_hook(setprocattr, -EINVAL, p, name, value, size);
> }
>
> int security_netlink_send(struct sock *sk, struct sk_buff *skb)
> @@ -1134,12 +1147,14 @@ EXPORT_SYMBOL(security_ismaclabel);
>
> int security_secid_to_secctx(u32 secid, char **secdata, u32 *seclen)
> {
> - return call_int_hook(secid_to_secctx, 0, secid, secdata, seclen);
> + return call_int_hook(secid_to_secctx, -EOPNOTSUPP, secid, secdata,
> + seclen);
> }
> EXPORT_SYMBOL(security_secid_to_secctx);
>
> int security_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid)
> {
> + *secid = 0;
> return call_int_hook(secctx_to_secid, 0, secdata, seclen, secid);
> }
> EXPORT_SYMBOL(security_secctx_to_secid);
> @@ -1164,7 +1179,7 @@ EXPORT_SYMBOL(security_inode_setsecctx);
>
> int security_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen)
> {
> - return call_int_hook(inode_getsecctx, 0, inode, ctx, ctxlen);
> + return call_int_hook(inode_getsecctx, -EOPNOTSUPP, inode, ctx, ctxlen);
> }
> EXPORT_SYMBOL(security_inode_getsecctx);
>
> @@ -1259,8 +1274,8 @@ EXPORT_SYMBOL(security_sock_rcv_skb);
> int security_socket_getpeersec_stream(struct socket *sock, char __user
> *optval, int __user *optlen, unsigned len)
> {
> - return call_int_hook(socket_getpeersec_stream, 0, sock, optval,
> - optlen, len);
> + return call_int_hook(socket_getpeersec_stream, -ENOPROTOOPT, sock,
> + optval, optlen, len);
> }
>
> int security_socket_getpeersec_dgram(struct socket *sock, struct sk_buff
> *skb, u32 *secid) @@ -1438,7 +1453,24 @@ int
> security_xfrm_state_pol_flow_match(struct xfrm_state *x, struct xfrm_policy
> *xp,
> const struct flowi *fl)
> {
> - return call_int_hook(xfrm_state_pol_flow_match, 0, x, xp, fl);
> + struct security_hook_list *hp;
> + int rc = 1;
> +
> + /*
> + * Since this function is expected to return 0 or 1, the judgment
> + * becomes difficult if multiple LSMs supply this call. Fortunately,
> + * we can use the first LSM's judgment because currently only SELinux
> + * supplies this call.
> + *
> + * For speed optimization, we explicitly break the loop rather than
> + * using the macro
> + */
> + list_for_each_entry(hp, &security_hook_heads.xfrm_state_pol_flow_match,
> + list) {
> + rc = hp->hook.xfrm_state_pol_flow_match(x, xp, fl);
> + break;
> + }
> + return rc;
> }
>
> int security_xfrm_decode_session(struct sk_buff *skb, u32 *secid)
> @@ -1478,6 +1510,7 @@ int security_key_permission(key_ref_t key_ref,
>
> int security_key_getsecurity(struct key *key, char **_buffer)
> {
> + *_buffer = NULL;
> return call_int_hook(key_getsecurity, 0, key, _buffer);
> }
>
> @@ -1506,5 +1539,350 @@ int security_audit_rule_match(u32 secid, u32 field,
> u32 op, void *lsmrule, return call_int_hook(audit_rule_match, 0, secid,
> field, op, lsmrule, actx);
> }
> +#endif /* CONFIG_AUDIT */
>
> +struct security_hook_heads security_hook_heads = {
> + .binder_set_context_mgr =
> + LIST_HEAD_INIT(security_hook_heads.binder_set_context_mgr),
> + .binder_transaction =
> + LIST_HEAD_INIT(security_hook_heads.binder_transaction),
> + .binder_transfer_binder =
> + LIST_HEAD_INIT(security_hook_heads.binder_transfer_binder),
> + .binder_transfer_file =
> + LIST_HEAD_INIT(security_hook_heads.binder_transfer_file),
> +
> + .ptrace_access_check =
> + LIST_HEAD_INIT(security_hook_heads.ptrace_access_check),
> + .ptrace_traceme =
> + LIST_HEAD_INIT(security_hook_heads.ptrace_traceme),
> + .capget = LIST_HEAD_INIT(security_hook_heads.capget),
> + .capset = LIST_HEAD_INIT(security_hook_heads.capset),
> + .capable = LIST_HEAD_INIT(security_hook_heads.capable),
> + .quotactl = LIST_HEAD_INIT(security_hook_heads.quotactl),
> + .quota_on = LIST_HEAD_INIT(security_hook_heads.quota_on),
> + .syslog = LIST_HEAD_INIT(security_hook_heads.syslog),
> + .settime = LIST_HEAD_INIT(security_hook_heads.settime),
> + .vm_enough_memory =
> + LIST_HEAD_INIT(security_hook_heads.vm_enough_memory),
> + .bprm_set_creds =
> + LIST_HEAD_INIT(security_hook_heads.bprm_set_creds),
> + .bprm_check_security =
> + LIST_HEAD_INIT(security_hook_heads.bprm_check_security),
> + .bprm_secureexec =
> + LIST_HEAD_INIT(security_hook_heads.bprm_secureexec),
> + .bprm_committing_creds =
> + LIST_HEAD_INIT(security_hook_heads.bprm_committing_creds),
> + .bprm_committed_creds =
> + LIST_HEAD_INIT(security_hook_heads.bprm_committed_creds),
> + .sb_alloc_security =
> + LIST_HEAD_INIT(security_hook_heads.sb_alloc_security),
> + .sb_free_security =
> + LIST_HEAD_INIT(security_hook_heads.sb_free_security),
> + .sb_copy_data = LIST_HEAD_INIT(security_hook_heads.sb_copy_data),
> + .sb_remount = LIST_HEAD_INIT(security_hook_heads.sb_remount),
> + .sb_kern_mount =
> + LIST_HEAD_INIT(security_hook_heads.sb_kern_mount),
> + .sb_show_options =
> + LIST_HEAD_INIT(security_hook_heads.sb_show_options),
> + .sb_statfs = LIST_HEAD_INIT(security_hook_heads.sb_statfs),
> + .sb_mount = LIST_HEAD_INIT(security_hook_heads.sb_mount),
> + .sb_umount = LIST_HEAD_INIT(security_hook_heads.sb_umount),
> + .sb_pivotroot = LIST_HEAD_INIT(security_hook_heads.sb_pivotroot),
> + .sb_set_mnt_opts =
> + LIST_HEAD_INIT(security_hook_heads.sb_set_mnt_opts),
> + .sb_clone_mnt_opts =
> + LIST_HEAD_INIT(security_hook_heads.sb_clone_mnt_opts),
> + .sb_parse_opts_str =
> + LIST_HEAD_INIT(security_hook_heads.sb_parse_opts_str),
> + .dentry_init_security =
> + LIST_HEAD_INIT(security_hook_heads.dentry_init_security),
> +#ifdef CONFIG_SECURITY_PATH
> + .path_unlink = LIST_HEAD_INIT(security_hook_heads.path_unlink),
> + .path_mkdir = LIST_HEAD_INIT(security_hook_heads.path_mkdir),
> + .path_rmdir = LIST_HEAD_INIT(security_hook_heads.path_rmdir),
> + .path_mknod = LIST_HEAD_INIT(security_hook_heads.path_mknod),
> + .path_truncate =
> + LIST_HEAD_INIT(security_hook_heads.path_truncate),
> + .path_symlink = LIST_HEAD_INIT(security_hook_heads.path_symlink),
> + .path_link = LIST_HEAD_INIT(security_hook_heads.path_link),
> + .path_rename = LIST_HEAD_INIT(security_hook_heads.path_rename),
> + .path_chmod = LIST_HEAD_INIT(security_hook_heads.path_chmod),
> + .path_chown = LIST_HEAD_INIT(security_hook_heads.path_chown),
> + .path_chroot = LIST_HEAD_INIT(security_hook_heads.path_chroot),
> +#endif
> + .inode_alloc_security =
> + LIST_HEAD_INIT(security_hook_heads.inode_alloc_security),
> + .inode_free_security =
> + LIST_HEAD_INIT(security_hook_heads.inode_free_security),
> + .inode_init_security =
> + LIST_HEAD_INIT(security_hook_heads.inode_init_security),
> + .inode_create = LIST_HEAD_INIT(security_hook_heads.inode_create),
> + .inode_link = LIST_HEAD_INIT(security_hook_heads.inode_link),
> + .inode_unlink = LIST_HEAD_INIT(security_hook_heads.inode_unlink),
> + .inode_symlink =
> + LIST_HEAD_INIT(security_hook_heads.inode_symlink),
> + .inode_mkdir = LIST_HEAD_INIT(security_hook_heads.inode_mkdir),
> + .inode_rmdir = LIST_HEAD_INIT(security_hook_heads.inode_rmdir),
> + .inode_mknod = LIST_HEAD_INIT(security_hook_heads.inode_mknod),
> + .inode_rename = LIST_HEAD_INIT(security_hook_heads.inode_rename),
> + .inode_readlink =
> + LIST_HEAD_INIT(security_hook_heads.inode_readlink),
> + .inode_follow_link =
> + LIST_HEAD_INIT(security_hook_heads.inode_follow_link),
> + .inode_permission =
> + LIST_HEAD_INIT(security_hook_heads.inode_permission),
> + .inode_setattr =
> + LIST_HEAD_INIT(security_hook_heads.inode_setattr),
> + .inode_getattr =
> + LIST_HEAD_INIT(security_hook_heads.inode_getattr),
> + .inode_setxattr =
> + LIST_HEAD_INIT(security_hook_heads.inode_setxattr),
> + .inode_post_setxattr =
> + LIST_HEAD_INIT(security_hook_heads.inode_post_setxattr),
> + .inode_getxattr =
> + LIST_HEAD_INIT(security_hook_heads.inode_getxattr),
> + .inode_listxattr =
> + LIST_HEAD_INIT(security_hook_heads.inode_listxattr),
> + .inode_removexattr =
> + LIST_HEAD_INIT(security_hook_heads.inode_removexattr),
> + .inode_need_killpriv =
> + LIST_HEAD_INIT(security_hook_heads.inode_need_killpriv),
> + .inode_killpriv =
> + LIST_HEAD_INIT(security_hook_heads.inode_killpriv),
> + .inode_getsecurity =
> + LIST_HEAD_INIT(security_hook_heads.inode_getsecurity),
> + .inode_setsecurity =
> + LIST_HEAD_INIT(security_hook_heads.inode_setsecurity),
> + .inode_listsecurity =
> + LIST_HEAD_INIT(security_hook_heads.inode_listsecurity),
> + .inode_getsecid =
> + LIST_HEAD_INIT(security_hook_heads.inode_getsecid),
> + .file_permission =
> + LIST_HEAD_INIT(security_hook_heads.file_permission),
> + .file_alloc_security =
> + LIST_HEAD_INIT(security_hook_heads.file_alloc_security),
> + .file_free_security =
> + LIST_HEAD_INIT(security_hook_heads.file_free_security),
> + .file_ioctl = LIST_HEAD_INIT(security_hook_heads.file_ioctl),
> + .mmap_addr = LIST_HEAD_INIT(security_hook_heads.mmap_addr),
> + .mmap_file = LIST_HEAD_INIT(security_hook_heads.mmap_file),
> + .file_mprotect =
> + LIST_HEAD_INIT(security_hook_heads.file_mprotect),
> + .file_lock = LIST_HEAD_INIT(security_hook_heads.file_lock),
> + .file_fcntl = LIST_HEAD_INIT(security_hook_heads.file_fcntl),
> + .file_set_fowner =
> + LIST_HEAD_INIT(security_hook_heads.file_set_fowner),
> + .file_send_sigiotask =
> + LIST_HEAD_INIT(security_hook_heads.file_send_sigiotask),
> + .file_receive = LIST_HEAD_INIT(security_hook_heads.file_receive),
> + .file_open = LIST_HEAD_INIT(security_hook_heads.file_open),
> + .task_create = LIST_HEAD_INIT(security_hook_heads.task_create),
> + .task_free = LIST_HEAD_INIT(security_hook_heads.task_free),
> + .cred_alloc_blank =
> + LIST_HEAD_INIT(security_hook_heads.cred_alloc_blank),
> + .cred_free = LIST_HEAD_INIT(security_hook_heads.cred_free),
> + .cred_prepare = LIST_HEAD_INIT(security_hook_heads.cred_prepare),
> + .cred_transfer =
> + LIST_HEAD_INIT(security_hook_heads.cred_transfer),
> + .kernel_act_as =
> + LIST_HEAD_INIT(security_hook_heads.kernel_act_as),
> + .kernel_create_files_as =
> + LIST_HEAD_INIT(security_hook_heads.kernel_create_files_as),
> + .kernel_fw_from_file =
> + LIST_HEAD_INIT(security_hook_heads.kernel_fw_from_file),
> + .kernel_module_request =
> + LIST_HEAD_INIT(security_hook_heads.kernel_module_request),
> + .kernel_module_from_file =
> + LIST_HEAD_INIT(security_hook_heads.kernel_module_from_file),
> + .task_fix_setuid =
> + LIST_HEAD_INIT(security_hook_heads.task_fix_setuid),
> + .task_setpgid = LIST_HEAD_INIT(security_hook_heads.task_setpgid),
> + .task_getpgid = LIST_HEAD_INIT(security_hook_heads.task_getpgid),
> + .task_getsid = LIST_HEAD_INIT(security_hook_heads.task_getsid),
> + .task_getsecid =
> + LIST_HEAD_INIT(security_hook_heads.task_getsecid),
> + .task_setnice = LIST_HEAD_INIT(security_hook_heads.task_setnice),
> + .task_setioprio =
> + LIST_HEAD_INIT(security_hook_heads.task_setioprio),
> + .task_getioprio =
> + LIST_HEAD_INIT(security_hook_heads.task_getioprio),
> + .task_setrlimit =
> + LIST_HEAD_INIT(security_hook_heads.task_setrlimit),
> + .task_setscheduler =
> + LIST_HEAD_INIT(security_hook_heads.task_setscheduler),
> + .task_getscheduler =
> + LIST_HEAD_INIT(security_hook_heads.task_getscheduler),
> + .task_movememory =
> + LIST_HEAD_INIT(security_hook_heads.task_movememory),
> + .task_kill = LIST_HEAD_INIT(security_hook_heads.task_kill),
> + .task_wait = LIST_HEAD_INIT(security_hook_heads.task_wait),
> + .task_prctl = LIST_HEAD_INIT(security_hook_heads.task_prctl),
> + .task_to_inode =
> + LIST_HEAD_INIT(security_hook_heads.task_to_inode),
> + .ipc_permission =
> + LIST_HEAD_INIT(security_hook_heads.ipc_permission),
> + .ipc_getsecid = LIST_HEAD_INIT(security_hook_heads.ipc_getsecid),
> + .msg_msg_alloc_security =
> + LIST_HEAD_INIT(security_hook_heads.msg_msg_alloc_security),
> + .msg_msg_free_security =
> + LIST_HEAD_INIT(security_hook_heads.msg_msg_free_security),
> + .msg_queue_alloc_security =
> + LIST_HEAD_INIT(security_hook_heads.msg_queue_alloc_security),
> + .msg_queue_free_security =
> + LIST_HEAD_INIT(security_hook_heads.msg_queue_free_security),
> + .msg_queue_associate =
> + LIST_HEAD_INIT(security_hook_heads.msg_queue_associate),
> + .msg_queue_msgctl =
> + LIST_HEAD_INIT(security_hook_heads.msg_queue_msgctl),
> + .msg_queue_msgsnd =
> + LIST_HEAD_INIT(security_hook_heads.msg_queue_msgsnd),
> + .msg_queue_msgrcv =
> + LIST_HEAD_INIT(security_hook_heads.msg_queue_msgrcv),
> + .shm_alloc_security =
> + LIST_HEAD_INIT(security_hook_heads.shm_alloc_security),
> + .shm_free_security =
> + LIST_HEAD_INIT(security_hook_heads.shm_free_security),
> + .shm_associate =
> + LIST_HEAD_INIT(security_hook_heads.shm_associate),
> + .shm_shmctl = LIST_HEAD_INIT(security_hook_heads.shm_shmctl),
> + .shm_shmat = LIST_HEAD_INIT(security_hook_heads.shm_shmat),
> + .sem_alloc_security =
> + LIST_HEAD_INIT(security_hook_heads.sem_alloc_security),
> + .sem_free_security =
> + LIST_HEAD_INIT(security_hook_heads.sem_free_security),
> + .sem_associate =
> + LIST_HEAD_INIT(security_hook_heads.sem_associate),
> + .sem_semctl = LIST_HEAD_INIT(security_hook_heads.sem_semctl),
> + .sem_semop = LIST_HEAD_INIT(security_hook_heads.sem_semop),
> + .netlink_send = LIST_HEAD_INIT(security_hook_heads.netlink_send),
> + .d_instantiate =
> + LIST_HEAD_INIT(security_hook_heads.d_instantiate),
> + .getprocattr = LIST_HEAD_INIT(security_hook_heads.getprocattr),
> + .setprocattr = LIST_HEAD_INIT(security_hook_heads.setprocattr),
> + .ismaclabel = LIST_HEAD_INIT(security_hook_heads.ismaclabel),
> + .secid_to_secctx =
> + LIST_HEAD_INIT(security_hook_heads.secid_to_secctx),
> + .secctx_to_secid =
> + LIST_HEAD_INIT(security_hook_heads.secctx_to_secid),
> + .release_secctx =
> + LIST_HEAD_INIT(security_hook_heads.release_secctx),
> + .inode_notifysecctx =
> + LIST_HEAD_INIT(security_hook_heads.inode_notifysecctx),
> + .inode_setsecctx =
> + LIST_HEAD_INIT(security_hook_heads.inode_setsecctx),
> + .inode_getsecctx =
> + LIST_HEAD_INIT(security_hook_heads.inode_getsecctx),
> +#ifdef CONFIG_SECURITY_NETWORK
> + .unix_stream_connect =
> + LIST_HEAD_INIT(security_hook_heads.unix_stream_connect),
> + .unix_may_send =
> + LIST_HEAD_INIT(security_hook_heads.unix_may_send),
> + .socket_create =
> + LIST_HEAD_INIT(security_hook_heads.socket_create),
> + .socket_post_create =
> + LIST_HEAD_INIT(security_hook_heads.socket_post_create),
> + .socket_bind = LIST_HEAD_INIT(security_hook_heads.socket_bind),
> + .socket_connect =
> + LIST_HEAD_INIT(security_hook_heads.socket_connect),
> + .socket_listen =
> + LIST_HEAD_INIT(security_hook_heads.socket_listen),
> + .socket_accept =
> + LIST_HEAD_INIT(security_hook_heads.socket_accept),
> + .socket_sendmsg =
> + LIST_HEAD_INIT(security_hook_heads.socket_sendmsg),
> + .socket_recvmsg =
> + LIST_HEAD_INIT(security_hook_heads.socket_recvmsg),
> + .socket_getsockname =
> + LIST_HEAD_INIT(security_hook_heads.socket_getsockname),
> + .socket_getpeername =
> + LIST_HEAD_INIT(security_hook_heads.socket_getpeername),
> + .socket_getsockopt =
> + LIST_HEAD_INIT(security_hook_heads.socket_getsockopt),
> + .socket_setsockopt =
> + LIST_HEAD_INIT(security_hook_heads.socket_setsockopt),
> + .socket_shutdown =
> + LIST_HEAD_INIT(security_hook_heads.socket_shutdown),
> + .socket_sock_rcv_skb =
> + LIST_HEAD_INIT(security_hook_heads.socket_sock_rcv_skb),
> + .socket_getpeersec_stream =
> + LIST_HEAD_INIT(security_hook_heads.socket_getpeersec_stream),
> + .socket_getpeersec_dgram =
> + LIST_HEAD_INIT(security_hook_heads.socket_getpeersec_dgram),
> + .sk_alloc_security =
> + LIST_HEAD_INIT(security_hook_heads.sk_alloc_security),
> + .sk_free_security =
> + LIST_HEAD_INIT(security_hook_heads.sk_free_security),
> + .sk_clone_security =
> + LIST_HEAD_INIT(security_hook_heads.sk_clone_security),
> + .sk_getsecid = LIST_HEAD_INIT(security_hook_heads.sk_getsecid),
> + .sock_graft = LIST_HEAD_INIT(security_hook_heads.sock_graft),
> + .inet_conn_request =
> + LIST_HEAD_INIT(security_hook_heads.inet_conn_request),
> + .inet_csk_clone =
> + LIST_HEAD_INIT(security_hook_heads.inet_csk_clone),
> + .inet_conn_established =
> + LIST_HEAD_INIT(security_hook_heads.inet_conn_established),
> + .secmark_relabel_packet =
> + LIST_HEAD_INIT(security_hook_heads.secmark_relabel_packet),
> + .secmark_refcount_inc =
> + LIST_HEAD_INIT(security_hook_heads.secmark_refcount_inc),
> + .secmark_refcount_dec =
> + LIST_HEAD_INIT(security_hook_heads.secmark_refcount_dec),
> + .req_classify_flow =
> + LIST_HEAD_INIT(security_hook_heads.req_classify_flow),
> + .tun_dev_alloc_security =
> + LIST_HEAD_INIT(security_hook_heads.tun_dev_alloc_security),
> + .tun_dev_free_security =
> + LIST_HEAD_INIT(security_hook_heads.tun_dev_free_security),
> + .tun_dev_create =
> + LIST_HEAD_INIT(security_hook_heads.tun_dev_create),
> + .tun_dev_attach_queue =
> + LIST_HEAD_INIT(security_hook_heads.tun_dev_attach_queue),
> + .tun_dev_attach =
> + LIST_HEAD_INIT(security_hook_heads.tun_dev_attach),
> + .tun_dev_open = LIST_HEAD_INIT(security_hook_heads.tun_dev_open),
> + .skb_owned_by = LIST_HEAD_INIT(security_hook_heads.skb_owned_by),
> +#endif /* CONFIG_SECURITY_NETWORK */
> +#ifdef CONFIG_SECURITY_NETWORK_XFRM
> + .xfrm_policy_alloc_security =
> + LIST_HEAD_INIT(security_hook_heads.xfrm_policy_alloc_security),
> + .xfrm_policy_clone_security =
> + LIST_HEAD_INIT(security_hook_heads.xfrm_policy_clone_security),
> + .xfrm_policy_free_security =
> + LIST_HEAD_INIT(security_hook_heads.xfrm_policy_free_security),
> + .xfrm_policy_delete_security =
> + LIST_HEAD_INIT(security_hook_heads.xfrm_policy_delete_security),
> + .xfrm_state_alloc =
> + LIST_HEAD_INIT(security_hook_heads.xfrm_state_alloc),
> + .xfrm_state_alloc_acquire =
> + LIST_HEAD_INIT(security_hook_heads.xfrm_state_alloc_acquire),
> + .xfrm_state_free_security =
> + LIST_HEAD_INIT(security_hook_heads.xfrm_state_free_security),
> + .xfrm_state_delete_security =
> + LIST_HEAD_INIT(security_hook_heads.xfrm_state_delete_security),
> + .xfrm_policy_lookup =
> + LIST_HEAD_INIT(security_hook_heads.xfrm_policy_lookup),
> + .xfrm_state_pol_flow_match =
> + LIST_HEAD_INIT(security_hook_heads.xfrm_state_pol_flow_match),
> + .xfrm_decode_session =
> + LIST_HEAD_INIT(security_hook_heads.xfrm_decode_session),
> +#endif /* CONFIG_SECURITY_NETWORK_XFRM */
> +#ifdef CONFIG_KEYS
> + .key_alloc = LIST_HEAD_INIT(security_hook_heads.key_alloc),
> + .key_free = LIST_HEAD_INIT(security_hook_heads.key_free),
> + .key_permission =
> + LIST_HEAD_INIT(security_hook_heads.key_permission),
> + .key_getsecurity =
> + LIST_HEAD_INIT(security_hook_heads.key_getsecurity),
> +#endif /* CONFIG_KEYS */
> +#ifdef CONFIG_AUDIT
> + .audit_rule_init =
> + LIST_HEAD_INIT(security_hook_heads.audit_rule_init),
> + .audit_rule_known =
> + LIST_HEAD_INIT(security_hook_heads.audit_rule_known),
> + .audit_rule_match =
> + LIST_HEAD_INIT(security_hook_heads.audit_rule_match),
> + .audit_rule_free =
> + LIST_HEAD_INIT(security_hook_heads.audit_rule_free),
> #endif /* CONFIG_AUDIT */
> +};
> diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
> index 0cf105f..06c9dd9 100644
> --- a/security/selinux/hooks.c
> +++ b/security/selinux/hooks.c
> @@ -1990,12 +1990,6 @@ static int selinux_binder_transfer_file(struct
> task_struct *from, 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);
> @@ -2007,25 +2001,13 @@ 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);
> }
>
> 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,
> @@ -2033,13 +2015,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);
> }
>
> @@ -2056,12 +2031,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);
> }
>
> @@ -2139,12 +2108,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 */
> @@ -2193,10 +2162,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)
> @@ -2320,7 +2285,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)
> @@ -3132,8 +3097,11 @@ 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 = cap_capable(current_cred(), &init_user_ns, CAP_MAC_ADMIN,
> + SECURITY_CAP_NOAUDIT);
> + if (!error)
> + error = cred_has_capability(current_cred(), CAP_MAC_ADMIN,
> + SECURITY_CAP_NOAUDIT);
> if (!error)
> error = security_sid_to_context_force(isec->sid, &context,
> &size);
> @@ -3318,12 +3286,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();
> @@ -3639,23 +3602,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);
> }
>
> @@ -3681,12 +3632,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);
> }
>
> @@ -5097,12 +5042,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);
> }
>
> @@ -5840,9 +5779,7 @@ static int selinux_key_getsecurity(struct key *key,
> char **_buffer)
>
> #endif
>
> -static struct security_operations selinux_ops = {
> - LSM_HOOK_INIT(name, "selinux"),
> -
> +static struct security_hook_list selinux_hooks[] = {
> LSM_HOOK_INIT(binder_set_context_mgr, selinux_binder_set_context_mgr),
> LSM_HOOK_INIT(binder_transaction, selinux_binder_transaction),
> LSM_HOOK_INIT(binder_transfer_binder, selinux_binder_transfer_binder),
> @@ -6055,7 +5992,7 @@ static struct security_operations selinux_ops = {
>
> static __init int selinux_init(void)
> {
> - if (!security_module_enable(&selinux_ops)) {
> + if (!security_module_enable("selinux")) {
> selinux_enabled = 0;
> return 0;
> }
> @@ -6077,8 +6014,7 @@ static __init int selinux_init(void)
> 0, SLAB_PANIC, NULL);
> avc_init();
>
> - if (register_security(&selinux_ops))
> - panic("SELinux: Unable to register with kernel.\n");
> + security_add_hooks(selinux_hooks, ARRAY_SIZE(selinux_hooks));
>
> if (avc_add_callback(selinux_netcache_avc_callback, AVC_CALLBACK_RESET))
> panic("SELinux: Unable to register AVC netcache callback\n");
> @@ -6206,7 +6142,7 @@ int selinux_disable(void)
> selinux_disabled = 1;
> selinux_enabled = 0;
>
> - reset_security_ops();
> + security_delete_hooks(selinux_hooks, ARRAY_SIZE(selinux_hooks));
>
> /* Try to destroy the avc node cache */
> avc_disable();
> diff --git a/security/smack/smack.h b/security/smack/smack.h
> index 262dad8..b8c1a86 100644
> --- a/security/smack/smack.h
> +++ b/security/smack/smack.h
> @@ -276,8 +276,6 @@ extern struct mutex smack_known_lock;
> extern struct list_head smack_known_list;
> extern struct list_head smk_netlbladdr_list;
>
> -extern struct security_operations smack_ops;
> -
> #define SMACK_HASH_SLOTS 16
> extern struct hlist_head smack_known_hash[SMACK_HASH_SLOTS];
>
> diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
> index 4313bf4..5eae42c 100644
> --- a/security/smack/smack_lsm.c
> +++ b/security/smack/smack_lsm.c
> @@ -436,17 +436,11 @@ static int smk_ptrace_rule_check(struct task_struct
> *tracer, */
> 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_struct(ctp);
>
> - rc = smk_ptrace_rule_check(current, skp, mode, __func__);
> - return rc;
> + return smk_ptrace_rule_check(current, skp, mode, __func__);
> }
>
> /**
> @@ -462,10 +456,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, PTRACE_MODE_ATTACH, __func__);
> @@ -721,10 +711,6 @@ static int smack_bprm_set_creds(struct linux_binprm
> *bprm) struct inode_smack *isp;
> int rc;
>
> - rc = cap_bprm_set_creds(bprm);
> - if (rc != 0)
> - return rc;
> -
> if (bprm->cred_prepared)
> return 0;
>
> @@ -779,12 +765,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;
> }
>
> /*
> @@ -1934,12 +1919,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__);
> }
>
> /**
> @@ -1951,12 +1931,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__);
> }
>
> /**
> @@ -1980,12 +1955,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__);
> }
>
> /**
> @@ -4266,9 +4236,7 @@ static int smack_inode_getsecctx(struct inode *inode,
> void **ctx, u32 *ctxlen) return 0;
> }
>
> -struct security_operations smack_ops = {
> - LSM_HOOK_INIT(name, "smack"),
> -
> +struct security_hook_list smack_hooks[] = {
> LSM_HOOK_INIT(ptrace_access_check, smack_ptrace_access_check),
> LSM_HOOK_INIT(ptrace_traceme, smack_ptrace_traceme),
> LSM_HOOK_INIT(syslog, smack_syslog),
> @@ -4451,7 +4419,7 @@ static __init int smack_init(void)
> struct cred *cred;
> struct task_smack *tsp;
>
> - if (!security_module_enable(&smack_ops))
> + if (!security_module_enable("smack"))
> return 0;
>
> smack_enabled = 1;
> @@ -4481,8 +4449,7 @@ static __init int smack_init(void)
> /*
> * Register with LSM
> */
> - if (register_security(&smack_ops))
> - panic("smack: Unable to register with kernel.\n");
> + security_add_hooks(smack_hooks, ARRAY_SIZE(smack_hooks));
>
> return 0;
> }
> diff --git a/security/smack/smackfs.c b/security/smack/smackfs.c
> index d968298..4aa12c8 100644
> --- a/security/smack/smackfs.c
> +++ b/security/smack/smackfs.c
> @@ -2547,7 +2547,7 @@ static int __init init_smk_fs(void)
> int err;
> int rc;
>
> - if (!security_module_enable(&smack_ops))
> + if (!security_module_enable("smack"))
> return 0;
>
> err = smk_init_sysfs();
> diff --git a/security/tomoyo/tomoyo.c b/security/tomoyo/tomoyo.c
> index bce1358..cbf3df4 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.
> @@ -502,8 +496,7 @@ static int tomoyo_socket_sendmsg(struct socket *sock,
> struct msghdr *msg, * tomoyo_security_ops is a "struct security_operations"
> which is used for * registering TOMOYO.
> */
> -static struct security_operations tomoyo_security_ops = {
> - LSM_HOOK_INIT(name, "tomoyo"),
> +static struct security_hook_list tomoyo_hooks[] = {
> LSM_HOOK_INIT(cred_alloc_blank, tomoyo_cred_alloc_blank),
> LSM_HOOK_INIT(cred_prepare, tomoyo_cred_prepare),
> LSM_HOOK_INIT(cred_transfer, tomoyo_cred_transfer),
> @@ -546,11 +539,10 @@ static int __init tomoyo_init(void)
> {
> struct cred *cred = (struct cred *) current_cred();
>
> - if (!security_module_enable(&tomoyo_security_ops))
> + if (!security_module_enable("tomoyo"))
> return 0;
> /* register ourselves with the security framework */
> - if (register_security(&tomoyo_security_ops))
> - panic("Failure registering TOMOYO Linux");
> + security_add_hooks(tomoyo_hooks, ARRAY_SIZE(tomoyo_hooks));
> printk(KERN_INFO "TOMOYO Linux initialized\n");
> cred->security = &tomoyo_kernel_domain;
> tomoyo_mm_init();
> diff --git a/security/yama/yama_lsm.c b/security/yama/yama_lsm.c
> index 23dd4c6..9ed3250 100644
> --- a/security/yama/yama_lsm.c
> +++ b/security/yama/yama_lsm.c
> @@ -154,13 +154,9 @@ void yama_task_free(struct task_struct *task)
> int yama_task_prctl(int option, unsigned long arg2, unsigned long arg3,
> unsigned long arg4, unsigned long arg5)
> {
> - int rc;
> + int rc = -ENOSYS;
> 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,17 +275,10 @@ 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;
> + int rc = 0;
>
> /* require ptrace target be a child of ptracer on attach */
> if (mode == PTRACE_MODE_ATTACH) {
> @@ -335,14 +324,7 @@ int yama_ptrace_access_check(struct task_struct *child,
> */
> int yama_ptrace_traceme(struct task_struct *parent)
> {
> - int rc;
> -
> - /* If standard caps disallows it, so does Yama. We should
> - * only tighten restrictions further.
> - */
> - rc = cap_ptrace_traceme(parent);
> - if (rc)
> - return rc;
> + int rc = 0;
>
> /* Only disallow PTRACE_TRACEME on more aggressive settings. */
> switch (ptrace_scope) {
> @@ -364,16 +346,17 @@ int yama_ptrace_traceme(struct task_struct *parent)
> return rc;
> }
>
> -#ifndef CONFIG_SECURITY_YAMA_STACKED
> -static struct security_operations yama_ops = {
> - LSM_HOOK_INIT(name, "yama"),
> -
> +static struct security_hook_list yama_hooks[] = {
> LSM_HOOK_INIT(ptrace_access_check, yama_ptrace_access_check),
> LSM_HOOK_INIT(ptrace_traceme, yama_ptrace_traceme),
> LSM_HOOK_INIT(task_prctl, yama_task_prctl),
> LSM_HOOK_INIT(task_free, yama_task_free),
> };
> -#endif
> +
> +void __init yama_add_hooks(void)
> +{
> + security_add_hooks(yama_hooks, ARRAY_SIZE(yama_hooks));
> +}
>
> #ifdef CONFIG_SYSCTL
> static int yama_dointvec_minmax(struct ctl_table *table, int write,
> @@ -418,16 +401,13 @@ static struct ctl_table yama_sysctl_table[] = {
> static __init int yama_init(void)
> {
> #ifndef CONFIG_SECURITY_YAMA_STACKED
> - if (!security_module_enable(&yama_ops))
> + /*
> + * If yama is being stacked this is already taken care of.
> + */
> + if (!security_module_enable("yama"))
> 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))
>
> --
> To unsubscribe from this list: send the line "unsubscribe
> linux-security-module" in the body of a message to
> majordomo@xxxxxxxxxxxxxxx
> More majordomo info at http://vger.kernel.org/majordomo-info.html

--
paul moore
security @ redhat

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/