Commit 2b15fe63 authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman

LSM: Add all of the new security/* files for basic task control

This includes the security_* functions, and the default and capability
modules.
parent c59ccd5f
/*
* Linux Security plug
*
* Copyright (C) 2001 WireX Communications, Inc <chris@wirex.com>
* Copyright (C) 2001 Greg Kroah-Hartman <greg@kroah.com>
* Copyright (C) 2001 Networks Associates Technology, Inc <ssmalley@nai.com>
* Copyright (C) 2001 James Morris <jmorris@intercode.com.au>
* 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 */
CONFIG_SECURITY_CAPABILITIES
This enables the "default" Linux capabilities functionality.
If you are unsure how to answer this question, answer Y.
#
# Security configuration
#
mainmenu_option next_comment
comment 'Security options'
tristate 'Capabilities Support' CONFIG_SECURITY_CAPABILITIES
endmenu
#
# 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
/*
* 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 (&current->fs->count) > 1
|| atomic_read (&current->files->count) > 1
|| atomic_read (&current->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");
/*
* Stub functions for the default security function pointers in case no
* security model is loaded.
*
* Copyright (C) 2001 WireX Communications, Inc <chris@wirex.com>
* Copyright (C) 2001 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/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,
};
/*
* Security plug functions
*
* Copyright (C) 2001 WireX Communications, Inc <chris@wirex.com>
* Copyright (C) 2001 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_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);
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment