diff options
Diffstat (limited to 'security/security.c')
-rw-r--r-- | security/security.c | 203 |
1 files changed, 203 insertions, 0 deletions
diff --git a/security/security.c b/security/security.c new file mode 100644 index 000000000000..ed5fb80769c3 --- /dev/null +++ b/security/security.c @@ -0,0 +1,203 @@ +/* + * Security plug functions + * + * Copyright (C) 2001 WireX Communications, Inc <chris@wirex.com> + * Copyright (C) 2001-2002 Greg Kroah-Hartman <greg@kroah.com> + * Copyright (C) 2001 Networks Associates Technology, Inc <ssmalley@nai.com> + * + * 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/config.h> +#include <linux/module.h> +#include <linux/init.h> +#include <linux/kernel.h> +#include <linux/sched.h> +#include <linux/security.h> + +#define SECURITY_FRAMEWORK_VERSION "1.0.0" + +/* things that live in dummy.c */ +extern struct security_operations dummy_security_ops; +extern void security_fixup_ops(struct security_operations *ops); + +struct security_operations *security_ops; /* Initialized to NULL */ + +static inline int 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; + call = __security_initcall_start; + while (call < __security_initcall_end) { + (*call) (); + call++; + } +} + +/** + * security_init - initializes the security framework + * + * This should be called early in the kernel initialization sequence. + */ +int __init security_init(void) +{ + printk(KERN_INFO "Security Framework v" SECURITY_FRAMEWORK_VERSION + " initialized\n"); + + if (verify(&dummy_security_ops)) { + printk(KERN_ERR "%s could not verify " + "dummy_security_ops structure.\n", __FUNCTION__); + return -EIO; + } + + security_ops = &dummy_security_ops; + do_security_initcalls(); + + return 0; +} + +/** + * register_security - registers a security framework with the kernel + * @ops: a pointer to the struct security_options that is to be registered + * + * This function is to allow a security module to register itself with the + * kernel security subsystem. Some rudimentary checking is done on the @ops + * value passed to this function. A call to unregister_security() should be + * done to remove this security_options structure from the kernel. + * + * If there is already a security module registered with the kernel, + * an error will be returned. Otherwise 0 is returned on success. + */ +int register_security(struct security_operations *ops) +{ + if (verify(ops)) { + printk(KERN_DEBUG "%s could not verify " + "security_operations structure.\n", __FUNCTION__); + return -EINVAL; + } + + if (security_ops != &dummy_security_ops) + return -EAGAIN; + + security_ops = ops; + + return 0; +} + +/** + * unregister_security - unregisters a security framework with the kernel + * @ops: a pointer to the struct security_options that is to be registered + * + * This function removes a struct security_operations variable that had + * previously been registered with a successful call to register_security(). + * + * If @ops does not match the valued previously passed to register_security() + * an error is returned. Otherwise the default security options is set to the + * the dummy_security_ops structure, and 0 is returned. + */ +int unregister_security(struct security_operations *ops) +{ + if (ops != security_ops) { + printk(KERN_INFO "%s: trying to unregister " + "a security_opts structure that is not " + "registered, failing.\n", __FUNCTION__); + return -EINVAL; + } + + security_ops = &dummy_security_ops; + + return 0; +} + +/** + * mod_reg_security - allows security modules to be "stacked" + * @name: a pointer to a string with the name of the security_options to be registered + * @ops: a pointer to the struct security_options that is to be registered + * + * This function allows security modules to be stacked if the currently loaded + * security module allows this to happen. It passes the @name and @ops to the + * register_security function of the currently loaded security module. + * + * The return value depends on the currently loaded security module, with 0 as + * success. + */ +int mod_reg_security(const char *name, struct security_operations *ops) +{ + if (verify(ops)) { + printk(KERN_INFO "%s could not verify " + "security operations.\n", __FUNCTION__); + return -EINVAL; + } + + if (ops == security_ops) { + printk(KERN_INFO "%s security operations " + "already registered.\n", __FUNCTION__); + return -EINVAL; + } + + return security_ops->register_security(name, ops); +} + +/** + * mod_unreg_security - allows a security module registered with mod_reg_security() to be unloaded + * @name: a pointer to a string with the name of the security_options to be removed + * @ops: a pointer to the struct security_options that is to be removed + * + * This function allows security modules that have been successfully registered + * with a call to mod_reg_security() to be unloaded from the system. + * This calls the currently loaded security module's unregister_security() call + * with the @name and @ops variables. + * + * The return value depends on the currently loaded security module, with 0 as + * success. + */ +int mod_unreg_security(const char *name, struct security_operations *ops) +{ + if (ops == security_ops) { + printk(KERN_INFO "%s invalid attempt to unregister " + " primary security ops.\n", __FUNCTION__); + return -EINVAL; + } + + return security_ops->unregister_security(name, ops); +} + +/** + * capable - calls the currently loaded security module's capable() function with the specified capability + * @cap: the requested capability level. + * + * This function calls the currently loaded security module's capable() + * function with a pointer to the current task and the specified @cap value. + * + * This allows the security module to implement the capable function call + * however it chooses to. + */ +int capable(int cap) +{ + if (security_ops->capable(current, cap)) { + /* capability denied */ + return 0; + } + + /* capability granted */ + current->flags |= PF_SUPERPRIV; + return 1; +} + +EXPORT_SYMBOL_GPL(register_security); +EXPORT_SYMBOL_GPL(unregister_security); +EXPORT_SYMBOL_GPL(mod_reg_security); +EXPORT_SYMBOL_GPL(mod_unreg_security); +EXPORT_SYMBOL(capable); +EXPORT_SYMBOL(security_ops); |