# This is a BitKeeper generated patch for the following project: # Project Name: Linux kernel tree # This patch format is intended for GNU patch command version 2.5 or higher. # This patch includes the following deltas: # ChangeSet 1.661 -> 1.662 # (new) -> 1.1 security/security.c # (new) -> 1.1 include/linux/security.h # (new) -> 1.1 security/dummy.c # (new) -> 1.1 security/Config.in # (new) -> 1.1 security/capability.c # (new) -> 1.1 security/Config.help # (new) -> 1.1 security/Makefile # # The following is the BitKeeper ChangeSet Log # -------------------------------------------- # 02/07/19 gregat_private 1.662 # LSM: Add all of the new security/* files for basic task control # # This includes the security_* functions, and the default and capability # modules. # -------------------------------------------- # diff -Nru a/include/linux/security.h b/include/linux/security.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/include/linux/security.h Fri Jul 19 16:03:50 2002 @@ -0,0 +1,383 @@ +/* + * Linux Security plug + * + * Copyright (C) 2001 WireX Communications, Inc <chrisat_private> + * Copyright (C) 2001 Greg Kroah-Hartman <gregat_private> + * Copyright (C) 2001 Networks Associates Technology, Inc <ssmalleyat_private> + * Copyright (C) 2001 James Morris <jmorrisat_private> + * Copyright (C) 2001 Silicon Graphics, Inc. (Trust Technology Group) + * + * 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. + * + * Due to this file being licensed under the GPL there is controversy over + * whether this permits you to write a module that #includes this file + * without placing your module under the GPL. Please consult a lawyer for + * advice before doing this. + * + */ + +#ifndef __LINUX_SECURITY_H +#define __LINUX_SECURITY_H + +#ifdef __KERNEL__ + +#include <linux/fs.h> +#include <linux/binfmts.h> +#include <linux/signal.h> +#include <linux/resource.h> +#include <linux/sem.h> +#include <linux/sysctl.h> +#include <linux/shm.h> +#include <linux/msg.h> + +/* + * Values used in the task_security_ops calls + */ +/* setuid or setgid, id0 == uid or gid */ +#define LSM_SETID_ID 1 + +/* setreuid or setregid, id0 == real, id1 == eff */ +#define LSM_SETID_RE 2 + +/* setresuid or setresgid, id0 == real, id1 == eff, uid2 == saved */ +#define LSM_SETID_RES 4 + +/* setfsuid or setfsgid, id0 == fsuid or fsgid */ +#define LSM_SETID_FS 8 + +/* forward declares to avoid warnings */ +struct sk_buff; +struct net_device; +struct nfsctl_arg; +struct sched_param; +struct swap_info_struct; + +/** + * struct security_operations - main security structure + * + * Security hooks for program execution operations. + * + * @bprm_alloc_security: + * Allocate and attach a security structure to the @bprm->security field. + * The security field is initialized to NULL when the bprm structure is + * allocated. + * @bprm contains the linux_binprm structure to be modified. + * Return 0 if operation was successful. + * @bprm_free_security: + * @bprm contains the linux_binprm structure to be modified. + * Deallocate and clear the @bprm->security field. + * @bprm_compute_creds: + * Compute and set the security attributes of a process being transformed + * by an execve operation based on the old attributes (current->security) + * and the information saved in @bprm->security by the set_security hook. + * Since this hook function (and its caller) are void, this hook can not + * return an error. However, it can leave the security attributes of the + * process unchanged if an access failure occurs at this point. It can + * also perform other state changes on the process (e.g. closing open + * file descriptors to which access is no longer granted if the attributes + * were changed). + * @bprm contains the linux_binprm structure. + * @bprm_set_security: + * Save security information in the bprm->security field, typically based + * on information about the bprm->file, for later use by the compute_creds + * hook. This hook may also optionally check permissions (e.g. for + * transitions between security domains). + * This hook may be called multiple times during a single execve, e.g. for + * interpreters. The hook can tell whether it has already been called by + * checking to see if @bprm->security is non-NULL. If so, then the hook + * may decide either to retain the security information saved earlier or + * to replace it. + * @bprm contains the linux_binprm structure. + * Return 0 if the hook is successful and permission is granted. + * @bprm_check_security: + * This hook mediates the point when a search for a binary handler will + * begin. It allows a check the @bprm->security value which is set in + * the preceding set_security call. The primary difference from + * set_security is that the argv list and envp list are reliably + * available in @bprm. This hook may be called multiple times + * during a single execve; and in each pass set_security is called + * first. + * @bprm contains the linux_binprm structure. + * Return 0 if the hook is successful and permission is granted. + * + * Security hooks for task operations. + * + * @task_create: + * Check permission before creating a child process. See the clone(2) + * manual page for definitions of the @clone_flags. + * @clone_flags contains the flags indicating what should be shared. + * Return 0 if permission is granted. + * @task_alloc_security: + * @p contains the task_struct for child process. + * Allocate and attach a security structure to the p->security field. The + * security field is initialized to NULL when the task structure is + * allocated. + * Return 0 if operation was successful. + * @task_free_security: + * @p contains the task_struct for process. + * Deallocate and clear the p->security field. + * @task_setuid: + * Check permission before setting one or more of the user identity + * attributes of the current process. The @flags parameter indicates + * which of the set*uid system calls invoked this hook and how to + * interpret the @id0, @id1, and @id2 parameters. See the LSM_SETID + * definitions at the beginning of this file for the @flags values and + * their meanings. + * @id0 contains a uid. + * @id1 contains a uid. + * @id2 contains a uid. + * @flags contains one of the LSM_SETID_* values. + * Return 0 if permission is granted. + * @task_post_setuid: + * Update the module's state after setting one or more of the user + * identity attributes of the current process. The @flags parameter + * indicates which of the set*uid system calls invoked this hook. If + * @flags is LSM_SETID_FS, then @old_ruid is the old fs uid and the other + * parameters are not used. + * @old_ruid contains the old real uid (or fs uid if LSM_SETID_FS). + * @old_euid contains the old effective uid (or -1 if LSM_SETID_FS). + * @old_suid contains the old saved uid (or -1 if LSM_SETID_FS). + * @flags contains one of the LSM_SETID_* values. + * Return 0 on success. + * @task_setgid: + * Check permission before setting one or more of the group identity + * attributes of the current process. The @flags parameter indicates + * which of the set*gid system calls invoked this hook and how to + * interpret the @id0, @id1, and @id2 parameters. See the LSM_SETID + * definitions at the beginning of this file for the @flags values and + * their meanings. + * @id0 contains a gid. + * @id1 contains a gid. + * @id2 contains a gid. + * @flags contains one of the LSM_SETID_* values. + * Return 0 if permission is granted. + * @task_setpgid: + * Check permission before setting the process group identifier of the + * process @p to @pgid. + * @p contains the task_struct for process being modified. + * @pgid contains the new pgid. + * Return 0 if permission is granted. + * @task_getpgid: + * Check permission before getting the process group identifier of the + * process @p. + * @p contains the task_struct for the process. + * Return 0 if permission is granted. + * @task_getsid: + * Check permission before getting the session identifier of the process + * @p. + * @p contains the task_struct for the process. + * Return 0 if permission is granted. + * @task_setgroups: + * Check permission before setting the supplementary group set of the + * current process to @grouplist. + * @gidsetsize contains the number of elements in @grouplist. + * @grouplist contains the array of gids. + * Return 0 if permission is granted. + * @task_setnice: + * Check permission before setting the nice value of @p to @nice. + * @p contains the task_struct of process. + * @nice contains the new nice value. + * Return 0 if permission is granted. + * @task_setrlimit: + * Check permission before setting the resource limits of the current + * process for @resource to @new_rlim. The old resource limit values can + * be examined by dereferencing (current->rlim + resource). + * @resource contains the resource whose limit is being set. + * @new_rlim contains the new limits for @resource. + * Return 0 if permission is granted. + * @task_setscheduler: + * Check permission before setting scheduling policy and/or parameters of + * process @p based on @policy and @lp. + * @p contains the task_struct for process. + * @policy contains the scheduling policy. + * @lp contains the scheduling parameters. + * Return 0 if permission is granted. + * @task_getscheduler: + * Check permission before obtaining scheduling information for process + * @p. + * @p contains the task_struct for process. + * Return 0 if permission is granted. + * @task_kill: + * Check permission before sending signal @sig to @p. @info can be NULL, + * the constant 1, or a pointer to a siginfo structure. If @info is 1 or + * SI_FROMKERNEL(info) is true, then the signal should be viewed as coming + * from the kernel and should typically be permitted. + * SIGIO signals are handled separately by the send_sigiotask hook in + * file_security_ops. + * @p contains the task_struct for process. + * @info contains the signal information. + * @sig contains the signal value. + * Return 0 if permission is granted. + * @task_wait: + * Check permission before allowing a process to reap a child process @p + * and collect its status information. + * @p contains the task_struct for process. + * Return 0 if permission is granted. + * @task_prctl: + * Check permission before performing a process control operation on the + * current process. + * @option contains the operation. + * @arg2 contains a argument. + * @arg3 contains a argument. + * @arg4 contains a argument. + * @arg5 contains a argument. + * Return 0 if permission is granted. + * @task_kmod_set_label: + * Set the security attributes in current->security for the kernel module + * loader thread, so that it has the permissions needed to perform its + * function. + * @task_reparent_to_init: + * Set the security attributes in @p->security for a kernel thread that + * is being reparented to the init task. + * @p contains the task_struct for the kernel thread. + * + * @ptrace: + * Check permission before allowing the @parent process to trace the + * @child process. + * Security modules may also want to perform a process tracing check + * during an execve in the set_security or compute_creds hooks of + * binprm_security_ops if the process is being traced and its security + * attributes would be changed by the execve. + * @parent contains the task_struct structure for parent process. + * @child contains the task_struct structure for child process. + * Return 0 if permission is granted. + * @capget: + * Get the @effective, @inheritable, and @permitted capability sets for + * the @target process. The hook may also perform permission checking to + * determine if the current process is allowed to see the capability sets + * of the @target process. + * @target contains the task_struct structure for target process. + * @effective contains the effective capability set. + * @inheritable contains the inheritable capability set. + * @permitted contains the permitted capability set. + * Return 0 if the capability sets were successfully obtained. + * @capset_check: + * Check permission before setting the @effective, @inheritable, and + * @permitted capability sets for the @target process. + * Caveat: @target is also set to current if a set of processes is + * specified (i.e. all processes other than current and init or a + * particular process group). Hence, the capset_set hook may need to + * revalidate permission to the actual target process. + * @target contains the task_struct structure for target process. + * @effective contains the effective capability set. + * @inheritable contains the inheritable capability set. + * @permitted contains the permitted capability set. + * Return 0 if permission is granted. + * @capset_set: + * Set the @effective, @inheritable, and @permitted capability sets for + * the @target process. Since capset_check cannot always check permission + * to the real @target process, this hook may also perform permission + * checking to determine if the current process is allowed to set the + * capability sets of the @target process. However, this hook has no way + * of returning an error due to the structure of the sys_capset code. + * @target contains the task_struct structure for target process. + * @effective contains the effective capability set. + * @inheritable contains the inheritable capability set. + * @permitted contains the permitted capability set. + * @capable: + * Check whether the @tsk process has the @cap capability. + * @tsk contains the task_struct for the process. + * @cap contains the capability <include/linux/capability.h>. + * Return 0 if the capability is granted for @tsk. + * @sys_security: + * Security modules may use this hook to implement new system calls for + * security-aware applications. The interface is similar to socketcall, + * but with an @id parameter to help identify the security module whose + * call is being invoked. The module is responsible for interpreting the + * parameters, and must copy in the @args array from user space if it is + * used. + * The recommended convention for creating the hexadecimal @id value is + * echo "Name_of_module" | md5sum | cut -c -8; by using this convention, + * there is no need for a central registry. + * @id contains the security module identifier. + * @call contains the call value. + * @args contains the call arguments (user space pointer). + * The module should return -ENOSYS if it does not implement any new + * system calls. + * + * @register_security: + * allow module stacking. + * @name contains the name of the security module being stacked. + * @ops contains a pointer to the struct security_operations of the module to stack. + * @unregister_security: + * remove a stacked module. + * @name contains the name of the security module being unstacked. + * @ops contains a pointer to the struct security_operations of the module to unstack. + * + * This is the main security structure. + */ +struct security_operations { + int (*ptrace) (struct task_struct * parent, struct task_struct * child); + int (*capget) (struct task_struct * target, + kernel_cap_t * effective, + kernel_cap_t * inheritable, kernel_cap_t * permitted); + int (*capset_check) (struct task_struct * target, + kernel_cap_t * effective, + kernel_cap_t * inheritable, + kernel_cap_t * permitted); + void (*capset_set) (struct task_struct * target, + kernel_cap_t * effective, + kernel_cap_t * inheritable, + kernel_cap_t * permitted); + int (*capable) (struct task_struct * tsk, int cap); + int (*sys_security) (unsigned int id, unsigned call, + unsigned long *args); + + int (*bprm_alloc_security) (struct linux_binprm * bprm); + void (*bprm_free_security) (struct linux_binprm * bprm); + void (*bprm_compute_creds) (struct linux_binprm * bprm); + int (*bprm_set_security) (struct linux_binprm * bprm); + int (*bprm_check_security) (struct linux_binprm * bprm); + + int (*task_create) (unsigned long clone_flags); + int (*task_alloc_security) (struct task_struct * p); + void (*task_free_security) (struct task_struct * p); + int (*task_setuid) (uid_t id0, uid_t id1, uid_t id2, int flags); + int (*task_post_setuid) (uid_t old_ruid /* or fsuid */ , + uid_t old_euid, uid_t old_suid, int flags); + int (*task_setgid) (gid_t id0, gid_t id1, gid_t id2, int flags); + int (*task_setpgid) (struct task_struct * p, pid_t pgid); + int (*task_getpgid) (struct task_struct * p); + int (*task_getsid) (struct task_struct * p); + int (*task_setgroups) (int gidsetsize, gid_t * grouplist); + int (*task_setnice) (struct task_struct * p, int nice); + int (*task_setrlimit) (unsigned int resource, struct rlimit * new_rlim); + int (*task_setscheduler) (struct task_struct * p, int policy, + struct sched_param * lp); + int (*task_getscheduler) (struct task_struct * p); + int (*task_kill) (struct task_struct * p, + struct siginfo * info, int sig); + int (*task_wait) (struct task_struct * p); + int (*task_prctl) (int option, unsigned long arg2, + unsigned long arg3, unsigned long arg4, + unsigned long arg5); + void (*task_kmod_set_label) (void); + void (*task_reparent_to_init) (struct task_struct * p); + + /* allow module stacking */ + int (*register_security) (const char *name, + struct security_operations *ops); + int (*unregister_security) (const char *name, + struct security_operations *ops); +}; + + +/* prototypes */ +extern int security_scaffolding_startup (void); +extern int register_security (struct security_operations *ops); +extern int unregister_security (struct security_operations *ops); +extern int mod_reg_security (const char *name, struct security_operations *ops); +extern int mod_unreg_security (const char *name, struct security_operations *ops); +extern int capable (int cap); + +/* global variables */ +extern struct security_operations *security_ops; + + +#endif /* __KERNEL__ */ + +#endif /* ! __LINUX_SECURITY_H */ + diff -Nru a/security/Config.help b/security/Config.help --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/security/Config.help Fri Jul 19 16:03:50 2002 @@ -0,0 +1,4 @@ +CONFIG_SECURITY_CAPABILITIES + This enables the "default" Linux capabilities functionality. + If you are unsure how to answer this question, answer Y. + diff -Nru a/security/Config.in b/security/Config.in --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/security/Config.in Fri Jul 19 16:03:50 2002 @@ -0,0 +1,7 @@ +# +# Security configuration +# +mainmenu_option next_comment +comment 'Security options' +tristate 'Capabilities Support' CONFIG_SECURITY_CAPABILITIES +endmenu diff -Nru a/security/Makefile b/security/Makefile --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/security/Makefile Fri Jul 19 16:03:50 2002 @@ -0,0 +1,13 @@ +# +# Makefile for the kernel security code +# + +# Objects that export symbols +export-objs := security.o + +# Object file lists +obj-y := security.o dummy.o + +obj-$(CONFIG_SECURITY_CAPABILITIES) += capability.o + +include $(TOPDIR)/Rules.make diff -Nru a/security/capability.c b/security/capability.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/security/capability.c Fri Jul 19 16:03:50 2002 @@ -0,0 +1,471 @@ +/* + * Capabilities Linux Security Module + * + * 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/security.h> +#include <linux/file.h> +#include <linux/mm.h> +#include <linux/smp_lock.h> +#include <linux/skbuff.h> +#include <linux/netlink.h> + +/* flag to keep track of how we were registered */ +static int secondary; + +static int cap_capable (struct task_struct *tsk, int cap) +{ + /* Derived from include/linux/sched.h:capable. */ + if (cap_raised (tsk->cap_effective, cap)) + return 0; + else + return -EPERM; +} + +static int cap_sys_security (unsigned int id, unsigned int call, + unsigned long *args) +{ + return -ENOSYS; +} + +static int cap_ptrace (struct task_struct *parent, struct task_struct *child) +{ + /* Derived from arch/i386/kernel/ptrace.c:sys_ptrace. */ + if (!cap_issubset (child->cap_permitted, current->cap_permitted) && + !capable (CAP_SYS_PTRACE)) + return -EPERM; + else + return 0; +} + +static int cap_capget (struct task_struct *target, kernel_cap_t * effective, + kernel_cap_t * inheritable, kernel_cap_t * permitted) +{ + /* Derived from kernel/capability.c:sys_capget. */ + *effective = cap_t (target->cap_effective); + *inheritable = cap_t (target->cap_inheritable); + *permitted = cap_t (target->cap_permitted); + return 0; +} + +static int cap_capset_check (struct task_struct *target, + kernel_cap_t * effective, + kernel_cap_t * inheritable, + kernel_cap_t * permitted) +{ + /* Derived from kernel/capability.c:sys_capset. */ + /* verify restrictions on target's new Inheritable set */ + if (!cap_issubset (*inheritable, + cap_combine (target->cap_inheritable, + current->cap_permitted))) { + return -EPERM; + } + + /* verify restrictions on target's new Permitted set */ + if (!cap_issubset (*permitted, + cap_combine (target->cap_permitted, + current->cap_permitted))) { + return -EPERM; + } + + /* verify the _new_Effective_ is a subset of the _new_Permitted_ */ + if (!cap_issubset (*effective, *permitted)) { + return -EPERM; + } + + return 0; +} + +static void cap_capset_set (struct task_struct *target, + kernel_cap_t * effective, + kernel_cap_t * inheritable, + kernel_cap_t * permitted) +{ + target->cap_effective = *effective; + target->cap_inheritable = *inheritable; + target->cap_permitted = *permitted; +} + +static int cap_bprm_alloc_security (struct linux_binprm *bprm) +{ + return 0; +} + +static int cap_bprm_set_security (struct linux_binprm *bprm) +{ + /* Copied from fs/exec.c:prepare_binprm. */ + + /* We don't have VFS support for capabilities yet */ + cap_clear (bprm->cap_inheritable); + cap_clear (bprm->cap_permitted); + cap_clear (bprm->cap_effective); + + /* To support inheritance of root-permissions and suid-root + * executables under compatibility mode, we raise all three + * capability sets for the file. + * + * If only the real uid is 0, we only raise the inheritable + * and permitted sets of the executable file. + */ + + if (!issecure (SECURE_NOROOT)) { + if (bprm->e_uid == 0 || current->uid == 0) { + cap_set_full (bprm->cap_inheritable); + cap_set_full (bprm->cap_permitted); + } + if (bprm->e_uid == 0) + cap_set_full (bprm->cap_effective); + } + return 0; +} + +static int cap_bprm_check_security (struct linux_binprm *bprm) +{ + return 0; +} + +static void cap_bprm_free_security (struct linux_binprm *bprm) +{ + return; +} + +/* Copied from fs/exec.c */ +static inline int must_not_trace_exec (struct task_struct *p) +{ + return (p->ptrace & PT_PTRACED) && !(p->ptrace & PT_PTRACE_CAP); +} + +static void cap_bprm_compute_creds (struct linux_binprm *bprm) +{ + /* Derived from fs/exec.c:compute_creds. */ + kernel_cap_t new_permitted, working; + int do_unlock = 0; + + new_permitted = cap_intersect (bprm->cap_permitted, cap_bset); + working = cap_intersect (bprm->cap_inheritable, + current->cap_inheritable); + new_permitted = cap_combine (new_permitted, working); + + if (!cap_issubset (new_permitted, current->cap_permitted)) { + current->mm->dumpable = 0; + + lock_kernel (); + if (must_not_trace_exec (current) + || atomic_read (¤t->fs->count) > 1 + || atomic_read (¤t->files->count) > 1 + || atomic_read (¤t->sig->count) > 1) { + if (!capable (CAP_SETPCAP)) { + new_permitted = cap_intersect (new_permitted, + current-> + cap_permitted); + } + } + do_unlock = 1; + } + + /* For init, we want to retain the capabilities set + * in the init_task struct. Thus we skip the usual + * capability rules */ + if (current->pid != 1) { + current->cap_permitted = new_permitted; + current->cap_effective = + cap_intersect (new_permitted, bprm->cap_effective); + } + + /* AUD: Audit candidate if current->cap_effective is set */ + + if (do_unlock) + unlock_kernel (); + + current->keep_capabilities = 0; +} + +static int cap_task_create (unsigned long clone_flags) +{ + return 0; +} + +static int cap_task_alloc_security (struct task_struct *p) +{ + return 0; +} + +static void cap_task_free_security (struct task_struct *p) +{ + return; +} + +static int cap_task_setuid (uid_t id0, uid_t id1, uid_t id2, int flags) +{ + return 0; +} + +/* moved from kernel/sys.c. */ +/* + * cap_emulate_setxuid() fixes the effective / permitted capabilities of + * a process after a call to setuid, setreuid, or setresuid. + * + * 1) When set*uiding _from_ one of {r,e,s}uid == 0 _to_ all of + * {r,e,s}uid != 0, the permitted and effective capabilities are + * cleared. + * + * 2) When set*uiding _from_ euid == 0 _to_ euid != 0, the effective + * capabilities of the process are cleared. + * + * 3) When set*uiding _from_ euid != 0 _to_ euid == 0, the effective + * capabilities are set to the permitted capabilities. + * + * fsuid is handled elsewhere. fsuid == 0 and {r,e,s}uid!= 0 should + * never happen. + * + * -astor + * + * cevans - New behaviour, Oct '99 + * A process may, via prctl(), elect to keep its capabilities when it + * calls setuid() and switches away from uid==0. Both permitted and + * effective sets will be retained. + * Without this change, it was impossible for a daemon to drop only some + * of its privilege. The call to setuid(!=0) would drop all privileges! + * Keeping uid 0 is not an option because uid 0 owns too many vital + * files.. + * Thanks to Olaf Kirch and Peter Benie for spotting this. + */ +static inline void cap_emulate_setxuid (int old_ruid, int old_euid, + int old_suid) +{ + if ((old_ruid == 0 || old_euid == 0 || old_suid == 0) && + (current->uid != 0 && current->euid != 0 && current->suid != 0) && + !current->keep_capabilities) { + cap_clear (current->cap_permitted); + cap_clear (current->cap_effective); + } + if (old_euid == 0 && current->euid != 0) { + cap_clear (current->cap_effective); + } + if (old_euid != 0 && current->euid == 0) { + current->cap_effective = current->cap_permitted; + } +} + +static int cap_task_post_setuid (uid_t old_ruid, uid_t old_euid, uid_t old_suid, + int flags) +{ + switch (flags) { + case LSM_SETID_RE: + case LSM_SETID_ID: + case LSM_SETID_RES: + /* Copied from kernel/sys.c:setreuid/setuid/setresuid. */ + if (!issecure (SECURE_NO_SETUID_FIXUP)) { + cap_emulate_setxuid (old_ruid, old_euid, old_suid); + } + break; + case LSM_SETID_FS: + { + uid_t old_fsuid = old_ruid; + + /* Copied from kernel/sys.c:setfsuid. */ + + /* + * FIXME - is fsuser used for all CAP_FS_MASK capabilities? + * if not, we might be a bit too harsh here. + */ + + if (!issecure (SECURE_NO_SETUID_FIXUP)) { + if (old_fsuid == 0 && current->fsuid != 0) { + cap_t (current->cap_effective) &= + ~CAP_FS_MASK; + } + if (old_fsuid != 0 && current->fsuid == 0) { + cap_t (current->cap_effective) |= + (cap_t (current->cap_permitted) & + CAP_FS_MASK); + } + } + break; + } + default: + return -EINVAL; + } + + return 0; +} + +static int cap_task_setgid (gid_t id0, gid_t id1, gid_t id2, int flags) +{ + 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 int cap_task_setgroups (int gidsetsize, gid_t * grouplist) +{ + return 0; +} + +static int cap_task_setnice (struct task_struct *p, int nice) +{ + return 0; +} + +static int cap_task_setrlimit (unsigned int resource, struct rlimit *new_rlim) +{ + return 0; +} + +static int cap_task_setscheduler (struct task_struct *p, int policy, + struct sched_param *lp) +{ + return 0; +} + +static int cap_task_getscheduler (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) +{ + return 0; +} + +static int cap_task_prctl (int option, unsigned long arg2, unsigned long arg3, + unsigned long arg4, unsigned long arg5) +{ + return 0; +} + +static void cap_task_kmod_set_label (void) +{ + cap_set_full (current->cap_effective); + return; +} + +static void cap_task_reparent_to_init (struct task_struct *p) +{ + p->cap_effective = CAP_INIT_EFF_SET; + p->cap_inheritable = CAP_INIT_INH_SET; + p->cap_permitted = CAP_FULL_SET; + p->keep_capabilities = 0; + return; +} + +static int cap_register (const char *name, struct security_operations *ops) +{ + return -EINVAL; +} + +static int cap_unregister (const char *name, struct security_operations *ops) +{ + return -EINVAL; +} + +static struct security_operations capability_ops = { + ptrace: cap_ptrace, + capget: cap_capget, + capset_check: cap_capset_check, + capset_set: cap_capset_set, + capable: cap_capable, + sys_security: cap_sys_security, + + bprm_alloc_security: cap_bprm_alloc_security, + bprm_free_security: cap_bprm_free_security, + bprm_compute_creds: cap_bprm_compute_creds, + bprm_set_security: cap_bprm_set_security, + bprm_check_security: cap_bprm_check_security, + + task_create: cap_task_create, + task_alloc_security: cap_task_alloc_security, + task_free_security: cap_task_free_security, + task_setuid: cap_task_setuid, + task_post_setuid: cap_task_post_setuid, + task_setgid: cap_task_setgid, + task_setpgid: cap_task_setpgid, + task_getpgid: cap_task_getpgid, + task_getsid: cap_task_getsid, + task_setgroups: cap_task_setgroups, + task_setnice: cap_task_setnice, + task_setrlimit: cap_task_setrlimit, + task_setscheduler: cap_task_setscheduler, + task_getscheduler: cap_task_getscheduler, + task_wait: cap_task_wait, + task_kill: cap_task_kill, + task_prctl: cap_task_prctl, + task_kmod_set_label: cap_task_kmod_set_label, + task_reparent_to_init: cap_task_reparent_to_init, + + register_security: cap_register, + unregister_security: cap_unregister, +}; + +#if defined(CONFIG_SECURITY_CAPABILITIES_MODULE) +#define MY_NAME THIS_MODULE->name +#else +#define MY_NAME "capability" +#endif + +static int __init capability_init (void) +{ + /* register ourselves with the security framework */ + if (register_security (&capability_ops)) { + printk (KERN_INFO + "Failure registering capabilities with the kernel\n"); + /* try registering with primary module */ + if (mod_reg_security (MY_NAME, &capability_ops)) { + printk (KERN_INFO "Failure registering capabilities " + "with primary security module.\n"); + return -EINVAL; + } + secondary = 1; + } + printk (KERN_INFO "Capability LSM initialized\n"); + return 0; +} + +static void __exit capability_exit (void) +{ + /* remove ourselves from the security framework */ + if (secondary) { + if (mod_unreg_security (MY_NAME, &capability_ops)) + printk (KERN_INFO "Failure unregistering capabilities " + "with primary module.\n"); + return; + } + + if (unregister_security (&capability_ops)) { + printk (KERN_INFO + "Failure unregistering capabilities with the kernel\n"); + } +} + +module_init (capability_init); +module_exit (capability_exit); + +MODULE_DESCRIPTION("Standard Linux Capabilities Security Module"); +MODULE_LICENSE("GPL"); diff -Nru a/security/dummy.c b/security/dummy.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/security/dummy.c Fri Jul 19 16:03:50 2002 @@ -0,0 +1,236 @@ +/* + * Stub functions for the default security function pointers in case no + * security model is loaded. + * + * Copyright (C) 2001 WireX Communications, Inc <chrisat_private> + * Copyright (C) 2001 Greg Kroah-Hartman <gregat_private> + * Copyright (C) 2001 Networks Associates Technology, Inc <ssmalleyat_private> + * + * 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/kernel.h> +#include <linux/security.h> +#include <linux/skbuff.h> +#include <linux/netlink.h> + +static int dummy_ptrace (struct task_struct *parent, struct task_struct *child) +{ + return 0; +} + +static int dummy_capget (struct task_struct *target, kernel_cap_t * effective, + kernel_cap_t * inheritable, kernel_cap_t * permitted) +{ + return 0; +} + +static int dummy_capset_check (struct task_struct *target, + kernel_cap_t * effective, + kernel_cap_t * inheritable, + kernel_cap_t * permitted) +{ + return 0; +} + +static void dummy_capset_set (struct task_struct *target, + kernel_cap_t * effective, + kernel_cap_t * inheritable, + kernel_cap_t * permitted) +{ + return; +} + +static int dummy_capable (struct task_struct *tsk, int cap) +{ + if (cap_is_fs_cap (cap) ? tsk->fsuid == 0 : tsk->euid == 0) + /* capability granted */ + return 0; + + /* capability denied */ + return -EPERM; +} + +static int dummy_sys_security (unsigned int id, unsigned int call, + unsigned long *args) +{ + return -ENOSYS; +} + +static int dummy_bprm_alloc_security (struct linux_binprm *bprm) +{ + return 0; +} + +static void dummy_bprm_free_security (struct linux_binprm *bprm) +{ + return; +} + +static void dummy_bprm_compute_creds (struct linux_binprm *bprm) +{ + return; +} + +static int dummy_bprm_set_security (struct linux_binprm *bprm) +{ + return 0; +} + +static int dummy_bprm_check_security (struct linux_binprm *bprm) +{ + return 0; +} + +static int dummy_task_create (unsigned long clone_flags) +{ + return 0; +} + +static int dummy_task_alloc_security (struct task_struct *p) +{ + return 0; +} + +static void dummy_task_free_security (struct task_struct *p) +{ + return; +} + +static int dummy_task_setuid (uid_t id0, uid_t id1, uid_t id2, int flags) +{ + return 0; +} + +static int dummy_task_post_setuid (uid_t id0, uid_t id1, uid_t id2, int flags) +{ + return 0; +} + +static int dummy_task_setgid (gid_t id0, gid_t id1, gid_t id2, int flags) +{ + return 0; +} + +static int dummy_task_setpgid (struct task_struct *p, pid_t pgid) +{ + return 0; +} + +static int dummy_task_getpgid (struct task_struct *p) +{ + return 0; +} + +static int dummy_task_getsid (struct task_struct *p) +{ + return 0; +} + +static int dummy_task_setgroups (int gidsetsize, gid_t * grouplist) +{ + return 0; +} + +static int dummy_task_setnice (struct task_struct *p, int nice) +{ + return 0; +} + +static int dummy_task_setrlimit (unsigned int resource, struct rlimit *new_rlim) +{ + return 0; +} + +static int dummy_task_setscheduler (struct task_struct *p, int policy, + struct sched_param *lp) +{ + return 0; +} + +static int dummy_task_getscheduler (struct task_struct *p) +{ + return 0; +} + +static int dummy_task_wait (struct task_struct *p) +{ + return 0; +} + +static int dummy_task_kill (struct task_struct *p, struct siginfo *info, + int sig) +{ + return 0; +} + +static int dummy_task_prctl (int option, unsigned long arg2, unsigned long arg3, + unsigned long arg4, unsigned long arg5) +{ + return 0; +} + +static void dummy_task_kmod_set_label (void) +{ + return; +} + +static void dummy_task_reparent_to_init (struct task_struct *p) +{ + p->euid = p->fsuid = 0; + return; +} + +static int dummy_register (const char *name, struct security_operations *ops) +{ + return -EINVAL; +} + +static int dummy_unregister (const char *name, struct security_operations *ops) +{ + return -EINVAL; +} + +struct security_operations dummy_security_ops = { + ptrace: dummy_ptrace, + capget: dummy_capget, + capset_check: dummy_capset_check, + capset_set: dummy_capset_set, + capable: dummy_capable, + sys_security: dummy_sys_security, + + bprm_alloc_security: dummy_bprm_alloc_security, + bprm_free_security: dummy_bprm_free_security, + bprm_compute_creds: dummy_bprm_compute_creds, + bprm_set_security: dummy_bprm_set_security, + bprm_check_security: dummy_bprm_check_security, + + task_create: dummy_task_create, + task_alloc_security: dummy_task_alloc_security, + task_free_security: dummy_task_free_security, + task_setuid: dummy_task_setuid, + task_post_setuid: dummy_task_post_setuid, + task_setgid: dummy_task_setgid, + task_setpgid: dummy_task_setpgid, + task_getpgid: dummy_task_getpgid, + task_getsid: dummy_task_getsid, + task_setgroups: dummy_task_setgroups, + task_setnice: dummy_task_setnice, + task_setrlimit: dummy_task_setrlimit, + task_setscheduler: dummy_task_setscheduler, + task_getscheduler: dummy_task_getscheduler, + task_wait: dummy_task_wait, + task_kill: dummy_task_kill, + task_prctl: dummy_task_prctl, + task_kmod_set_label: dummy_task_kmod_set_label, + task_reparent_to_init: dummy_task_reparent_to_init, + + register_security: dummy_register, + unregister_security: dummy_unregister, +}; + diff -Nru a/security/security.c b/security/security.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/security/security.c Fri Jul 19 16:03:50 2002 @@ -0,0 +1,249 @@ +/* + * Security plug functions + * + * Copyright (C) 2001 WireX Communications, Inc <chrisat_private> + * Copyright (C) 2001 Greg Kroah-Hartman <gregat_private> + * Copyright (C) 2001 Networks Associates Technology, Inc <ssmalleyat_private> + * + * 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_SCAFFOLD_VERSION "1.0.0" + +extern struct security_operations dummy_security_ops; /* lives in dummy.c */ + +struct security_operations *security_ops; /* Initialized to NULL */ + +/* This macro checks that all pointers in a struct are non-NULL. It + * can be fooled by struct padding for object tile alignment and when + * pointers to data and pointers to functions aren't the same size. + * Yes it's ugly, we'll replace it if it becomes a problem. + */ +#define VERIFY_STRUCT(struct_type, s, e) \ + do { \ + unsigned long * __start = (unsigned long *)(s); \ + unsigned long * __end = __start + \ + sizeof(struct_type)/sizeof(unsigned long *); \ + while (__start != __end) { \ + if (!*__start) { \ + printk(KERN_INFO "%s is missing something\n",\ + #struct_type); \ + e++; \ + break; \ + } \ + __start++; \ + } \ + } while (0) + +static int inline verify (struct security_operations *ops) +{ + int err; + + /* verify the security_operations structure exists */ + if (!ops) { + printk (KERN_INFO "Passed a NULL security_operations " + "pointer, " __FUNCTION__ " failed.\n"); + return -EINVAL; + } + + /* Perform a little sanity checking on our inputs */ + err = 0; + + /* This first check scans the whole security_ops struct for + * missing structs or functions. + * + * (There is no further check now, but will leave as is until + * the lazy registration stuff is done -- JM). + */ + VERIFY_STRUCT(struct security_operations, ops, err); + + if (err) { + printk (KERN_INFO "Not enough functions specified in the " + "security_operation structure, " __FUNCTION__ + " failed.\n"); + return -EINVAL; + } + return 0; +} + +/** + * security_scaffolding_startup - initialzes the security scaffolding framework + * + * This should be called early in the kernel initialization sequence. + */ +int security_scaffolding_startup (void) +{ + printk (KERN_INFO "Security Scaffold v" SECURITY_SCAFFOLD_VERSION + " initialized\n"); + + security_ops = &dummy_security_ops; + + 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 the @ops structure does not contain function pointers for all hooks in + * the structure, or 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_INFO __FUNCTION__ " could not verify " + "security_operations structure.\n"); + return -EINVAL; + } + if (security_ops != &dummy_security_ops) { + printk (KERN_INFO "There is already a security " + "framework initialized, " __FUNCTION__ " failed.\n"); + return -EINVAL; + } + + 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 __FUNCTION__ ": trying to unregister " + "a security_opts structure that is not " + "registered, failing.\n"); + 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 __FUNCTION__ " could not verify " + "security operations.\n"); + return -EINVAL; + } + + if (ops == security_ops) { + printk (KERN_INFO __FUNCTION__ " security operations " + "already registered.\n"); + 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 __FUNCTION__ " invalid attempt to unregister " + " primary security ops.\n"); + 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 cabable() + * 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; +} + +/** + * sys_security - security syscall multiplexor. + * @id: module id + * @call: call identifier + * @args: arg list for call + * + * Similar to sys_socketcall. Can use id to help identify which module user + * app is talking to. The recommended convention for creating the + * hexadecimal id value is: + * 'echo "Name_of_module" | md5sum | cut -c -8'. + * By following this convention, there's no need for a central registry. + */ +asmlinkage long sys_security (unsigned int id, unsigned int call, + unsigned long *args) +{ + return security_ops->sys_security (id, call, args); +} + +EXPORT_SYMBOL (register_security); +EXPORT_SYMBOL (unregister_security); +EXPORT_SYMBOL (mod_reg_security); +EXPORT_SYMBOL (mod_unreg_security); +EXPORT_SYMBOL (capable); +EXPORT_SYMBOL (security_ops); _______________________________________________ linux-security-module mailing list linux-security-moduleat_private http://mail.wirex.com/mailman/listinfo/linux-security-module
This archive was generated by hypermail 2b30 : Fri Jul 19 2002 - 16:14:55 PDT