public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [BK PATCH] LSM task control for 2.5.26
@ 2002-07-19 23:09 Greg KH
  2002-07-19 23:10 ` Greg KH
  0 siblings, 1 reply; 4+ messages in thread
From: Greg KH @ 2002-07-19 23:09 UTC (permalink / raw)
  To: torvalds; +Cc: linux-kernel, linux-security-module

Hi,

These changesets contain the initial LSM framework, offering hooks for
task control.  It includes the default capabilities module, which should
be selected in the kernel configuration if you want to keep the existing
"normal Linux" capabilities mode. 

Please pull from:  bk://lsm.bkbits.net/linus-2.5

These patches were created by Stephen Smalley <sds@tislabs.com> from the
main LSM tree.

If anyone has any questions about these changes, please let us know.

thanks,

greg k-h

 arch/arm/kernel/isa.c     |    2 
 arch/i386/config.in       |    1 
 arch/i386/kernel/entry.S  |    2 
 arch/i386/kernel/ptrace.c |    4 
 fs/exec.c                 |   71 ++----
 include/linux/binfmts.h   |    1 
 include/linux/sched.h     |   10 
 include/linux/security.h  |  383 +++++++++++++++++++++++++++++++++++++
 include/linux/sysctl.h    |    2 
 init/main.c               |    2 
 kernel/capability.c       |   19 -
 kernel/exit.c             |   11 -
 kernel/fork.c             |   13 +
 kernel/kmod.c             |    2 
 kernel/ptrace.c           |    8 
 kernel/sched.c            |   41 +++-
 kernel/signal.c           |    3 
 kernel/sys.c              |  178 ++++++++---------
 kernel/uid16.c            |    8 
 Makefile                  |    5 
 security/capability.c     |  471 ++++++++++++++++++++++++++++++++++++++++++++++
 security/Config.help      |    4 
 security/Config.in        |    7 
 security/dummy.c          |  236 +++++++++++++++++++++++
 security/Makefile         |   13 +
 security/security.c       |  249 ++++++++++++++++++++++++
 26 files changed, 1575 insertions(+), 171 deletions(-)
------

ChangeSet@1.663, 2002-07-19 16:01:00-07:00, greg@kroah.com
  LSM:  Enable the security framework.  This includes basic task control hooks.

 Makefile                  |    5 -
 arch/i386/config.in       |    1 
 arch/i386/kernel/entry.S  |    2 
 arch/i386/kernel/ptrace.c |    4 +
 fs/exec.c                 |   71 +++++-------------
 include/linux/binfmts.h   |    1 
 include/linux/sched.h     |   10 +-
 init/main.c               |    2 
 kernel/capability.c       |   19 ++--
 kernel/exit.c             |   11 +-
 kernel/fork.c             |   13 ++-
 kernel/kmod.c             |    2 
 kernel/ptrace.c           |    8 +-
 kernel/sched.c            |   41 ++++++++--
 kernel/signal.c           |    3 
 kernel/sys.c              |  178 +++++++++++++++++++++++-----------------------
 kernel/uid16.c            |    8 +-
 17 files changed, 210 insertions(+), 169 deletions(-)
------

ChangeSet@1.662, 2002-07-19 15:55:59-07:00, greg@kroah.com
  LSM: Add all of the new security/* files for basic task control
  
  This includes the security_* functions, and the default and capability
  modules.

 include/linux/security.h |  383 ++++++++++++++++++++++++++++++++++++++
 security/Config.help     |    4 
 security/Config.in       |    7 
 security/Makefile        |   13 +
 security/capability.c    |  471 +++++++++++++++++++++++++++++++++++++++++++++++
 security/dummy.c         |  236 +++++++++++++++++++++++
 security/security.c      |  249 ++++++++++++++++++++++++
 7 files changed, 1363 insertions(+)
------

ChangeSet@1.661, 2002-07-19 15:07:35-07:00, greg@kroah.com
  LSM: change BUS_ISA to CTL_BUS_ISA to prevent namespace collision with the input subsystem.
  
  This is needed due to the next header file changes.

 arch/arm/kernel/isa.c  |    2 +-
 include/linux/sysctl.h |    2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)
------


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [BK PATCH] LSM task control for 2.5.26
  2002-07-19 23:09 [BK PATCH] LSM task control for 2.5.26 Greg KH
@ 2002-07-19 23:10 ` Greg KH
  2002-07-19 23:10   ` Greg KH
  0 siblings, 1 reply; 4+ messages in thread
From: Greg KH @ 2002-07-19 23:10 UTC (permalink / raw)
  To: linux-kernel, linux-security-module

# 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.660   -> 1.661  
#	include/linux/sysctl.h	1.18    -> 1.19   
#	arch/arm/kernel/isa.c	1.1     -> 1.2    
#
# The following is the BitKeeper ChangeSet Log
# --------------------------------------------
# 02/07/19	greg@kroah.com	1.661
# LSM: change BUS_ISA to CTL_BUS_ISA to prevent namespace collision with the input subsystem.
# 
# This is needed due to the next header file changes.
# --------------------------------------------
#
diff -Nru a/arch/arm/kernel/isa.c b/arch/arm/kernel/isa.c
--- a/arch/arm/kernel/isa.c	Fri Jul 19 16:03:52 2002
+++ b/arch/arm/kernel/isa.c	Fri Jul 19 16:03:52 2002
@@ -38,7 +38,7 @@
 
 static struct ctl_table_header *isa_sysctl_header;
 
-static ctl_table ctl_isa[2] = {{BUS_ISA, "isa", NULL, 0, 0555, ctl_isa_vars},
+static ctl_table ctl_isa[2] = {{CTL_BUS_ISA, "isa", NULL, 0, 0555, ctl_isa_vars},
 			       {0}};
 static ctl_table ctl_bus[2] = {{CTL_BUS, "bus", NULL, 0, 0555, ctl_isa},
 			       {0}};
diff -Nru a/include/linux/sysctl.h b/include/linux/sysctl.h
--- a/include/linux/sysctl.h	Fri Jul 19 16:03:52 2002
+++ b/include/linux/sysctl.h	Fri Jul 19 16:03:52 2002
@@ -72,7 +72,7 @@
 /* CTL_BUS names: */
 enum
 {
-	BUS_ISA=1		/* ISA */
+	CTL_BUS_ISA=1		/* ISA */
 };
 
 /* CTL_KERN names: */

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [BK PATCH] LSM task control for 2.5.26
  2002-07-19 23:10 ` Greg KH
@ 2002-07-19 23:10   ` Greg KH
  2002-07-19 23:10     ` Greg KH
  0 siblings, 1 reply; 4+ messages in thread
From: Greg KH @ 2002-07-19 23:10 UTC (permalink / raw)
  To: linux-kernel, linux-security-module

# 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	greg@kroah.com	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 <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 */
+
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 (&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");
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 <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,
+};
+
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 <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);

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [BK PATCH] LSM task control for 2.5.26
  2002-07-19 23:10   ` Greg KH
@ 2002-07-19 23:10     ` Greg KH
  0 siblings, 0 replies; 4+ messages in thread
From: Greg KH @ 2002-07-19 23:10 UTC (permalink / raw)
  To: linux-kernel, linux-security-module

# 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.662   -> 1.663  
#	      kernel/uid16.c	1.1     -> 1.2    
#	       kernel/fork.c	1.50    -> 1.51   
#	include/linux/sched.h	1.71    -> 1.72   
#	        kernel/sys.c	1.20    -> 1.21   
#	            Makefile	1.274   -> 1.275  
#	 kernel/capability.c	1.4     -> 1.5    
#	         init/main.c	1.50    -> 1.51   
#	      kernel/sched.c	1.106   -> 1.107  
#	arch/i386/kernel/entry.S	1.32    -> 1.33   
#	arch/i386/kernel/ptrace.c	1.12    -> 1.13   
#	       kernel/kmod.c	1.9     -> 1.10   
#	 arch/i386/config.in	1.41    -> 1.42   
#	       kernel/exit.c	1.35    -> 1.36   
#	           fs/exec.c	1.32    -> 1.33   
#	     kernel/signal.c	1.22    -> 1.23   
#	include/linux/binfmts.h	1.2     -> 1.3    
#	     kernel/ptrace.c	1.11    -> 1.12   
#
# The following is the BitKeeper ChangeSet Log
# --------------------------------------------
# 02/07/19	greg@kroah.com	1.663
# LSM:  Enable the security framework.  This includes basic task control hooks.
# --------------------------------------------
#
diff -Nru a/Makefile b/Makefile
--- a/Makefile	Fri Jul 19 16:03:47 2002
+++ b/Makefile	Fri Jul 19 16:03:47 2002
@@ -157,7 +157,8 @@
 
 export srctree objtree
 
-SUBDIRS		:= init kernel mm fs ipc lib drivers sound net
+SUBDIRS		:= init kernel mm fs ipc lib drivers sound net security
+
 
 noconfig_targets := xconfig menuconfig config oldconfig randconfig \
 		    defconfig allyesconfig allnoconfig allmodconfig \
@@ -223,7 +224,7 @@
 # ---------------------------------------------------------------------------
 
 INIT		:= init/init.o
-CORE_FILES	:= kernel/kernel.o mm/mm.o fs/fs.o ipc/ipc.o
+CORE_FILES	:= kernel/kernel.o mm/mm.o fs/fs.o ipc/ipc.o security/built-in.o
 LIBS		:= lib/lib.a
 DRIVERS		:= drivers/built-in.o sound/sound.o
 NETWORKS	:= net/network.o
diff -Nru a/arch/i386/config.in b/arch/i386/config.in
--- a/arch/i386/config.in	Fri Jul 19 16:03:47 2002
+++ b/arch/i386/config.in	Fri Jul 19 16:03:47 2002
@@ -423,4 +423,5 @@
 
 endmenu
 
+source security/Config.in
 source lib/Config.in
diff -Nru a/arch/i386/kernel/entry.S b/arch/i386/kernel/entry.S
--- a/arch/i386/kernel/entry.S	Fri Jul 19 16:03:47 2002
+++ b/arch/i386/kernel/entry.S	Fri Jul 19 16:03:47 2002
@@ -744,7 +744,7 @@
 	.long sys_getdents64	/* 220 */
 	.long sys_fcntl64
 	.long sys_ni_syscall	/* reserved for TUX */
-	.long sys_ni_syscall	/* reserved for Security */
+	.long sys_security	/* reserved for Security */
 	.long sys_gettid
 	.long sys_readahead	/* 225 */
 	.long sys_setxattr
diff -Nru a/arch/i386/kernel/ptrace.c b/arch/i386/kernel/ptrace.c
--- a/arch/i386/kernel/ptrace.c	Fri Jul 19 16:03:47 2002
+++ b/arch/i386/kernel/ptrace.c	Fri Jul 19 16:03:47 2002
@@ -13,6 +13,7 @@
 #include <linux/errno.h>
 #include <linux/ptrace.h>
 #include <linux/user.h>
+#include <linux/security.h>
 
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
@@ -158,6 +159,9 @@
 	if (request == PTRACE_TRACEME) {
 		/* are we already being traced? */
 		if (current->ptrace & PT_PTRACED)
+			goto out;
+		ret = security_ops->ptrace(current->parent, current);
+		if (ret)
 			goto out;
 		/* set the ptrace bit in the process flags. */
 		current->ptrace |= PT_PTRACED;
diff -Nru a/fs/exec.c b/fs/exec.c
--- a/fs/exec.c	Fri Jul 19 16:03:47 2002
+++ b/fs/exec.c	Fri Jul 19 16:03:47 2002
@@ -623,6 +623,7 @@
 {
 	int mode;
 	struct inode * inode = bprm->file->f_dentry->d_inode;
+	int retval;
 
 	mode = inode->i_mode;
 	/*
@@ -652,27 +653,10 @@
 			bprm->e_gid = inode->i_gid;
 	}
 
-	/* 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);
-	}
+	/* fill in binprm security blob */
+	retval = security_ops->bprm_set_security(bprm);
+	if (retval)
+		return retval;
 
 	memset(bprm->buf,0,BINPRM_BUF_SIZE);
 	return kernel_read(bprm->file,0,bprm->buf,BINPRM_BUF_SIZE);
@@ -695,16 +679,9 @@
 
 void compute_creds(struct linux_binprm *bprm) 
 {
-	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 (bprm->e_uid != current->uid || bprm->e_gid != current->gid ||
-	    !cap_issubset(new_permitted, current->cap_permitted)) {
+	if (bprm->e_uid != current->uid || bprm->e_gid != current->gid) {
                 current->mm->dumpable = 0;
 		
 		lock_kernel();
@@ -716,32 +693,17 @@
 				bprm->e_uid = current->uid;
 				bprm->e_gid = current->gid;
 			}
-			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 */
-
         current->suid = current->euid = current->fsuid = bprm->e_uid;
         current->sgid = current->egid = current->fsgid = bprm->e_gid;
 
 	if(do_unlock)
 		unlock_kernel();
-	current->keep_capabilities = 0;
+
+	security_ops->bprm_compute_creds(bprm);
 }
 
 
@@ -811,6 +773,10 @@
 	    }
 	}
 #endif
+	retval = security_ops->bprm_check_security(bprm);
+	if (retval) 
+		return retval;
+
 	/* kernel module loader fixup */
 	/* so we don't try to load run modprobe in kernel space. */
 	set_fs(USER_DS);
@@ -887,7 +853,7 @@
 	bprm.sh_bang = 0;
 	bprm.loader = 0;
 	bprm.exec = 0;
-
+	bprm.security = NULL;
 	bprm.mm = mm_alloc();
 	retval = -ENOMEM;
 	if (!bprm.mm)
@@ -905,6 +871,10 @@
 	if ((retval = bprm.envc) < 0)
 		goto out_mm;
 
+	retval = security_ops->bprm_alloc_security(&bprm);
+	if (retval) 
+		goto out;
+
 	retval = prepare_binprm(&bprm);
 	if (retval < 0) 
 		goto out; 
@@ -923,9 +893,11 @@
 		goto out; 
 
 	retval = search_binary_handler(&bprm,regs);
-	if (retval >= 0)
+	if (retval >= 0) {
 		/* execve success */
+		security_ops->bprm_free_security(&bprm);
 		return retval;
+	}
 
 out:
 	/* Something went wrong, return the inode and free the argument pages*/
@@ -934,6 +906,9 @@
 		if (page)
 			__free_page(page);
 	}
+
+	if (bprm.security)
+		security_ops->bprm_free_security(&bprm);
 
 out_mm:
 	mmdrop(bprm.mm);
diff -Nru a/include/linux/binfmts.h b/include/linux/binfmts.h
--- a/include/linux/binfmts.h	Fri Jul 19 16:03:47 2002
+++ b/include/linux/binfmts.h	Fri Jul 19 16:03:47 2002
@@ -28,6 +28,7 @@
 	struct file * file;
 	int e_uid, e_gid;
 	kernel_cap_t cap_inheritable, cap_permitted, cap_effective;
+	void *security;
 	int argc, envc;
 	char * filename;	/* Name of binary */
 	unsigned long loader, exec;
diff -Nru a/include/linux/sched.h b/include/linux/sched.h
--- a/include/linux/sched.h	Fri Jul 19 16:03:47 2002
+++ b/include/linux/sched.h	Fri Jul 19 16:03:47 2002
@@ -354,6 +354,8 @@
 	void *notifier_data;
 	sigset_t *notifier_mask;
 	
+	void *security;
+
 /* Thread group tracking */
    	u32 parent_exec_id;
    	u32 self_exec_id;
@@ -587,10 +589,9 @@
 		       unsigned long, const char *, void *);
 extern void free_irq(unsigned int, void *);
 
-/*
- * capable() checks for a particular capability.
- * See include/linux/capability.h for defined capabilities.
- */
+/* capable prototype and code moved to security.[hc] */
+#include <linux/security.h>
+#if 0
 static inline int capable(int cap)
 {
 	if (cap_raised(current->cap_effective, cap)) {
@@ -599,6 +600,7 @@
 	}
 	return 0;
 }
+#endif	/* if 0 */
 
 /*
  * Routines for handling mm_structs
diff -Nru a/init/main.c b/init/main.c
--- a/init/main.c	Fri Jul 19 16:03:47 2002
+++ b/init/main.c	Fri Jul 19 16:03:47 2002
@@ -29,6 +29,7 @@
 #include <linux/tty.h>
 #include <linux/percpu.h>
 #include <linux/kernel_stat.h>
+#include <linux/security.h>
 
 #include <asm/io.h>
 #include <asm/bugs.h>
@@ -390,6 +391,7 @@
 
 	fork_init(mempages);
 	proc_caches_init();
+	security_scaffolding_startup();
 	buffer_init();
 	vfs_caches_init(mempages);
 	radix_tree_init();
diff -Nru a/kernel/capability.c b/kernel/capability.c
--- a/kernel/capability.c	Fri Jul 19 16:03:47 2002
+++ b/kernel/capability.c	Fri Jul 19 16:03:47 2002
@@ -63,6 +63,7 @@
      data.permitted = cap_t(target->cap_permitted);
      data.inheritable = cap_t(target->cap_inheritable); 
      data.effective = cap_t(target->cap_effective);
+     ret = security_ops->capget(target, &data.effective, &data.inheritable, &data.permitted);
 
 out:
      read_unlock(&tasklist_lock); 
@@ -87,9 +88,7 @@
      for_each_task(target) {
              if (target->pgrp != pgrp)
                      continue;
-             target->cap_effective   = *effective;
-             target->cap_inheritable = *inheritable;
-             target->cap_permitted   = *permitted;
+	     security_ops->capset_set(target, effective, inheritable, permitted);
      }
 }
 
@@ -106,9 +105,7 @@
      for_each_task(target) {
              if (target == current || target->pid == 1)
                      continue;
-             target->cap_effective   = *effective;
-             target->cap_inheritable = *inheritable;
-             target->cap_permitted   = *permitted;
+	     security_ops->capset_set(target, effective, inheritable, permitted);
      }
 }
 
@@ -166,7 +163,9 @@
 
      ret = -EPERM;
 
-     /* verify restrictions on target's new Inheritable set */
+     if (security_ops->capset_check(target, &effective, &inheritable, &permitted))
+	     goto out;
+
      if (!cap_issubset(inheritable, cap_combine(target->cap_inheritable,
                        current->cap_permitted)))
              goto out;
@@ -182,6 +181,8 @@
 
      ret = 0;
 
+     /* having verified that the proposed changes are legal,
+           we now put them into effect. */
      if (pid < 0) {
              if (pid == -1)  /* all procs other than current and init */
                      cap_set_all(&effective, &inheritable, &permitted);
@@ -189,9 +190,7 @@
              else            /* all procs in process group */
                      cap_set_pg(-pid, &effective, &inheritable, &permitted);
      } else {
-             target->cap_effective   = effective;
-             target->cap_inheritable = inheritable;
-             target->cap_permitted   = permitted;
+	     security_ops->capset_set(target, &effective, &inheritable, &permitted);
      }
 
 out:
diff -Nru a/kernel/exit.c b/kernel/exit.c
--- a/kernel/exit.c	Fri Jul 19 16:03:47 2002
+++ b/kernel/exit.c	Fri Jul 19 16:03:47 2002
@@ -14,6 +14,7 @@
 #include <linux/personality.h>
 #include <linux/tty.h>
 #include <linux/namespace.h>
+#include <linux/security.h>
 #include <linux/acct.h>
 #include <linux/file.h>
 #include <linux/binfmts.h>
@@ -61,6 +62,7 @@
 	wait_task_inactive(p);
 #endif
 	atomic_dec(&p->user->processes);
+	security_ops->task_free_security(p);
 	free_uid(p->user);
 	unhash_process(p);
 
@@ -187,10 +189,7 @@
 	/* cpus_allowed? */
 	/* rt_priority? */
 	/* signals? */
-	current->cap_effective = CAP_INIT_EFF_SET;
-	current->cap_inheritable = CAP_INIT_INH_SET;
-	current->cap_permitted = CAP_FULL_SET;
-	current->keep_capabilities = 0;
+	security_ops->task_reparent_to_init(current);
 	memcpy(current->rlim, init_task.rlim, sizeof(*(current->rlim)));
 	current->user = INIT_USER;
 
@@ -625,6 +624,10 @@
 			if (((p->exit_signal != SIGCHLD) ^ ((options & __WCLONE) != 0))
 			    && !(options & __WALL))
 				continue;
+
+			if (security_ops->task_wait(p))
+				continue;
+
 			flag = 1;
 			switch (p->state) {
 			case TASK_STOPPED:
diff -Nru a/kernel/fork.c b/kernel/fork.c
--- a/kernel/fork.c	Fri Jul 19 16:03:47 2002
+++ b/kernel/fork.c	Fri Jul 19 16:03:47 2002
@@ -24,7 +24,7 @@
 #include <linux/file.h>
 #include <linux/binfmts.h>
 #include <linux/fs.h>
-#include <linux/mm.h>
+#include <linux/security.h>
 
 #include <asm/pgtable.h>
 #include <asm/pgalloc.h>
@@ -618,6 +618,10 @@
 	if ((clone_flags & (CLONE_NEWNS|CLONE_FS)) == (CLONE_NEWNS|CLONE_FS))
 		return ERR_PTR(-EINVAL);
 
+	retval = security_ops->task_create(clone_flags);
+	if (retval)
+		goto fork_out;
+
 	retval = -ENOMEM;
 	p = dup_task_struct(current);
 	if (!p)
@@ -697,13 +701,16 @@
 	p->array = NULL;
 	p->lock_depth = -1;		/* -1 = no lock */
 	p->start_time = jiffies;
+	p->security = NULL;
 
 	INIT_LIST_HEAD(&p->local_pages);
 
 	retval = -ENOMEM;
+	if (security_ops->task_alloc_security(p))
+		goto bad_fork_cleanup;
 	/* copy all the process information */
 	if (copy_semundo(clone_flags, p))
-		goto bad_fork_cleanup;
+		goto bad_fork_cleanup_security;
 	if (copy_files(clone_flags, p))
 		goto bad_fork_cleanup_semundo;
 	if (copy_fs(clone_flags, p))
@@ -812,6 +819,8 @@
 	exit_files(p); /* blocking */
 bad_fork_cleanup_semundo:
 	exit_semundo(p);
+bad_fork_cleanup_security:
+	security_ops->task_free_security(p);
 bad_fork_cleanup:
 	put_exec_domain(p->thread_info->exec_domain);
 	if (p->binfmt && p->binfmt->module)
diff -Nru a/kernel/kmod.c b/kernel/kmod.c
--- a/kernel/kmod.c	Fri Jul 19 16:03:47 2002
+++ b/kernel/kmod.c	Fri Jul 19 16:03:47 2002
@@ -134,7 +134,7 @@
 	/* Give kmod all effective privileges.. */
 	curtask->euid = curtask->fsuid = 0;
 	curtask->egid = curtask->fsgid = 0;
-	cap_set_full(curtask->cap_effective);
+	security_ops->task_kmod_set_label();
 
 	/* Allow execve args to be in kernel space. */
 	set_fs(KERNEL_DS);
diff -Nru a/kernel/ptrace.c b/kernel/ptrace.c
--- a/kernel/ptrace.c	Fri Jul 19 16:03:47 2002
+++ b/kernel/ptrace.c	Fri Jul 19 16:03:47 2002
@@ -41,7 +41,9 @@
 
 int ptrace_attach(struct task_struct *task)
 {
+	int retval;
 	task_lock(task);
+	retval = -EPERM;
 	if (task->pid <= 1)
 		goto bad;
 	if (task == current)
@@ -53,7 +55,6 @@
 	    (current->uid != task->uid) ||
  	    (current->gid != task->egid) ||
  	    (current->gid != task->sgid) ||
- 	    (!cap_issubset(task->cap_permitted, current->cap_permitted)) ||
  	    (current->gid != task->gid)) && !capable(CAP_SYS_PTRACE))
 		goto bad;
 	rmb();
@@ -62,6 +63,9 @@
 	/* the same process cannot be attached many times */
 	if (task->ptrace & PT_PTRACED)
 		goto bad;
+	retval = security_ops->ptrace(current, task);
+	if (retval)
+		goto bad;
 
 	/* Go */
 	task->ptrace |= PT_PTRACED;
@@ -82,7 +86,7 @@
 
 bad:
 	task_unlock(task);
-	return -EPERM;
+	return retval;
 }
 
 int ptrace_detach(struct task_struct *child, unsigned int data)
diff -Nru a/kernel/sched.c b/kernel/sched.c
--- a/kernel/sched.c	Fri Jul 19 16:03:47 2002
+++ b/kernel/sched.c	Fri Jul 19 16:03:47 2002
@@ -26,6 +26,7 @@
 #include <linux/interrupt.h>
 #include <linux/completion.h>
 #include <linux/kernel_stat.h>
+#include <linux/security.h>
 
 /*
  * Convert user-nice values [ -20 ... 0 ... 19 ]
@@ -1123,6 +1124,7 @@
 
 asmlinkage long sys_nice(int increment)
 {
+	int retval;
 	long nice;
 
 	/*
@@ -1144,6 +1146,11 @@
 		nice = -20;
 	if (nice > 19)
 		nice = 19;
+
+	retval = security_ops->task_setnice(current, nice);
+	if (retval)
+		return retval;
+
 	set_user_nice(current, nice);
 	return 0;
 }
@@ -1236,6 +1243,10 @@
 	    !capable(CAP_SYS_NICE))
 		goto out_unlock;
 
+	retval = security_ops->task_setscheduler(p, policy, &lp);
+	if (retval)
+		goto out_unlock;
+
 	array = p->array;
 	if (array)
 		deactivate_task(p, task_rq(p));
@@ -1280,8 +1291,11 @@
 	retval = -ESRCH;
 	read_lock(&tasklist_lock);
 	p = find_process_by_pid(pid);
-	if (p)
-		retval = p->policy;
+	if (p) {
+		retval = security_ops->task_getscheduler(p);
+		if (!retval)
+			retval = p->policy;
+	}
 	read_unlock(&tasklist_lock);
 
 out_nounlock:
@@ -1302,6 +1316,11 @@
 	retval = -ESRCH;
 	if (!p)
 		goto out_unlock;
+
+	retval = security_ops->task_getscheduler(p);
+	if (retval)
+		goto out_unlock;
+
 	lp.sched_priority = p->rt_priority;
 	read_unlock(&tasklist_lock);
 
@@ -1509,13 +1528,21 @@
 	retval = -ESRCH;
 	read_lock(&tasklist_lock);
 	p = find_process_by_pid(pid);
-	if (p)
-		jiffies_to_timespec(p->policy & SCHED_FIFO ?
-					 0 : TASK_TIMESLICE(p), &t);
+	if (!p)
+		goto out_unlock;
+
+	retval = security_ops->task_getscheduler(p);
+	if (retval)
+		goto out_unlock;
+
+	jiffies_to_timespec(p->policy & SCHED_FIFO ?
+				0 : TASK_TIMESLICE(p), &t);
 	read_unlock(&tasklist_lock);
-	if (p)
-		retval = copy_to_user(interval, &t, sizeof(t)) ? -EFAULT : 0;
+	retval = copy_to_user(interval, &t, sizeof(t)) ? -EFAULT : 0;
 out_nounlock:
+	return retval;
+out_unlock:
+	read_unlock(&tasklist_lock);
 	return retval;
 }
 
diff -Nru a/kernel/signal.c b/kernel/signal.c
--- a/kernel/signal.c	Fri Jul 19 16:03:47 2002
+++ b/kernel/signal.c	Fri Jul 19 16:03:47 2002
@@ -548,6 +548,9 @@
 	ret = -EPERM;
 	if (bad_signal(sig, info, t))
 		goto out_nolock;
+	ret = security_ops->task_kill(t, info, sig);
+	if (ret)
+		goto out_nolock;
 
 	/* The null signal is a permissions and process existence probe.
 	   No signal is actually delivered.  Same goes for zombies. */
diff -Nru a/kernel/sys.c b/kernel/sys.c
--- a/kernel/sys.c	Fri Jul 19 16:03:47 2002
+++ b/kernel/sys.c	Fri Jul 19 16:03:47 2002
@@ -19,6 +19,7 @@
 #include <linux/tqueue.h>
 #include <linux/device.h>
 #include <linux/times.h>
+#include <linux/security.h>
 
 #include <asm/uaccess.h>
 #include <asm/io.h>
@@ -234,6 +235,7 @@
 
 	read_lock(&tasklist_lock);
 	for_each_task(p) {
+		int no_nice;
 		if (!proc_sel(p, which, who))
 			continue;
 		if (p->uid != current->euid &&
@@ -243,10 +245,17 @@
 		}
 		if (error == -ESRCH)
 			error = 0;
-		if (niceval < task_nice(p) && !capable(CAP_SYS_NICE))
+		if (niceval < task_nice(p) && !capable(CAP_SYS_NICE)) {
 			error = -EACCES;
-		else
-			set_user_nice(p, niceval);
+			continue;
+		}
+		no_nice = security_ops->task_setnice(p, niceval);
+		if (no_nice) {
+			error = no_nice;
+			continue;
+		}
+		set_user_nice(p, niceval);
+
 	}
 	read_unlock(&tasklist_lock);
 
@@ -416,6 +425,11 @@
 	int old_egid = current->egid;
 	int new_rgid = old_rgid;
 	int new_egid = old_egid;
+	int retval;
+
+	retval = security_ops->task_setgid(rgid, egid, (gid_t)-1, LSM_SETID_RE);
+	if (retval)
+		return retval;
 
 	if (rgid != (gid_t) -1) {
 		if ((old_rgid == rgid) ||
@@ -457,6 +471,11 @@
 asmlinkage long sys_setgid(gid_t gid)
 {
 	int old_egid = current->egid;
+	int retval;
+
+	retval = security_ops->task_setgid(gid, (gid_t)-1, (gid_t)-1, LSM_SETID_ID);
+	if (retval)
+		return retval;
 
 	if (capable(CAP_SETGID))
 	{
@@ -481,52 +500,6 @@
 	return 0;
 }
   
-/* 
- * 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 set_user(uid_t new_ruid, int dumpclear)
 {
 	struct user_struct *new_user, *old_user;
@@ -572,6 +545,11 @@
 asmlinkage long sys_setreuid(uid_t ruid, uid_t euid)
 {
 	int old_ruid, old_euid, old_suid, new_ruid, new_euid;
+	int retval;
+
+	retval = security_ops->task_setuid(ruid, euid, (uid_t)-1, LSM_SETID_RE);
+	if (retval)
+		return retval;
 
 	new_ruid = old_ruid = current->uid;
 	new_euid = old_euid = current->euid;
@@ -608,11 +586,7 @@
 		current->suid = current->euid;
 	current->fsuid = current->euid;
 
-	if (!issecure(SECURE_NO_SETUID_FIXUP)) {
-		cap_emulate_setxuid(old_ruid, old_euid, old_suid);
-	}
-
-	return 0;
+	return security_ops->task_post_setuid(old_ruid, old_euid, old_suid, LSM_SETID_RE);
 }
 
 
@@ -632,6 +606,11 @@
 {
 	int old_euid = current->euid;
 	int old_ruid, old_suid, new_ruid, new_suid;
+	int retval;
+
+	retval = security_ops->task_setuid(uid, (uid_t)-1, (uid_t)-1, LSM_SETID_ID);
+	if (retval)
+		return retval;
 
 	old_ruid = new_ruid = current->uid;
 	old_suid = current->suid;
@@ -652,11 +631,7 @@
 	current->fsuid = current->euid = uid;
 	current->suid = new_suid;
 
-	if (!issecure(SECURE_NO_SETUID_FIXUP)) {
-		cap_emulate_setxuid(old_ruid, old_euid, old_suid);
-	}
-
-	return 0;
+	return security_ops->task_post_setuid(old_ruid, old_euid, old_suid, LSM_SETID_ID);
 }
 
 
@@ -669,6 +644,11 @@
 	int old_ruid = current->uid;
 	int old_euid = current->euid;
 	int old_suid = current->suid;
+	int retval;
+
+	retval = security_ops->task_setuid(ruid, euid, suid, LSM_SETID_RES);
+	if (retval)
+		return retval;
 
 	if (!capable(CAP_SETUID)) {
 		if ((ruid != (uid_t) -1) && (ruid != current->uid) &&
@@ -697,11 +677,7 @@
 	if (suid != (uid_t) -1)
 		current->suid = suid;
 
-	if (!issecure(SECURE_NO_SETUID_FIXUP)) {
-		cap_emulate_setxuid(old_ruid, old_euid, old_suid);
-	}
-
-	return 0;
+	return security_ops->task_post_setuid(old_ruid, old_euid, old_suid, LSM_SETID_RES);
 }
 
 asmlinkage long sys_getresuid(uid_t *ruid, uid_t *euid, uid_t *suid)
@@ -720,6 +696,12 @@
  */
 asmlinkage long sys_setresgid(gid_t rgid, gid_t egid, gid_t sgid)
 {
+	int retval;
+
+	retval = security_ops->task_setgid(rgid, egid, sgid, LSM_SETID_RES);
+	if (retval)
+		return retval;
+
 	if (!capable(CAP_SETGID)) {
 		if ((rgid != (gid_t) -1) && (rgid != current->gid) &&
 		    (rgid != current->egid) && (rgid != current->sgid))
@@ -768,6 +750,11 @@
 asmlinkage long sys_setfsuid(uid_t uid)
 {
 	int old_fsuid;
+	int retval;
+
+	retval = security_ops->task_setuid(uid, (uid_t)-1, (uid_t)-1, LSM_SETID_FS);
+	if (retval)
+		return retval;
 
 	old_fsuid = current->fsuid;
 	if (uid == current->uid || uid == current->euid ||
@@ -782,24 +769,9 @@
 		current->fsuid = uid;
 	}
 
-	/* We emulate fsuid by essentially doing a scaled-down version
-	 * of what we did in setresuid and friends. However, we only
-	 * operate on the fs-specific bits of the process' effective
-	 * capabilities 
-	 *
-	 * 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);
-		}
-	}
+	retval = security_ops->task_post_setuid(old_fsuid, (uid_t)-1, (uid_t)-1, LSM_SETID_FS);
+	if (retval)
+		return retval;
 
 	return old_fsuid;
 }
@@ -810,6 +782,11 @@
 asmlinkage long sys_setfsgid(gid_t gid)
 {
 	int old_fsgid;
+	int retval;
+
+	retval = security_ops->task_setgid(gid, (gid_t)-1, (gid_t)-1, LSM_SETID_FS);
+	if (retval)
+		return retval;
 
 	old_fsgid = current->fsgid;
 	if (gid == current->gid || gid == current->egid ||
@@ -904,6 +881,10 @@
 	}
 
 ok_pgid:
+	err = security_ops->task_setpgid(p, pgid);
+	if (err)
+		goto out;
+
 	p->pgrp = pgid;
 	err = 0;
 out:
@@ -924,8 +905,11 @@
 		p = find_task_by_pid(pid);
 
 		retval = -ESRCH;
-		if (p)
-			retval = p->pgrp;
+		if (p) {
+			retval = security_ops->task_getpgid(p);
+			if (!retval)
+				retval = p->pgrp;
+		}
 		read_unlock(&tasklist_lock);
 		return retval;
 	}
@@ -949,8 +933,11 @@
 		p = find_task_by_pid(pid);
 
 		retval = -ESRCH;
-		if(p)
-			retval = p->session;
+		if(p) {
+			retval = security_ops->task_getsid(p);
+			if (!retval)
+				retval = p->session;
+		}
 		read_unlock(&tasklist_lock);
 		return retval;
 	}
@@ -1008,12 +995,19 @@
  
 asmlinkage long sys_setgroups(int gidsetsize, gid_t *grouplist)
 {
+	gid_t groups[NGROUPS];
+	int retval;
+
 	if (!capable(CAP_SETGID))
 		return -EPERM;
 	if ((unsigned) gidsetsize > NGROUPS)
 		return -EINVAL;
-	if(copy_from_user(current->groups, grouplist, gidsetsize * sizeof(gid_t)))
+	if(copy_from_user(groups, grouplist, gidsetsize * sizeof(gid_t)))
 		return -EFAULT;
+	retval = security_ops->task_setgroups(gidsetsize, groups);
+	if (retval)
+		return retval;
+	memcpy(current->groups, groups, gidsetsize * sizeof(gid_t));
 	current->ngroups = gidsetsize;
 	return 0;
 }
@@ -1158,6 +1152,7 @@
 asmlinkage long sys_setrlimit(unsigned int resource, struct rlimit *rlim)
 {
 	struct rlimit new_rlim, *old_rlim;
+	int retval;
 
 	if (resource >= RLIM_NLIMITS)
 		return -EINVAL;
@@ -1172,6 +1167,11 @@
 		if (new_rlim.rlim_cur > NR_OPEN || new_rlim.rlim_max > NR_OPEN)
 			return -EPERM;
 	}
+
+	retval = security_ops->task_setrlimit(resource, &new_rlim);
+	if (retval)
+		return retval;
+
 	*old_rlim = new_rlim;
 	return 0;
 }
@@ -1242,6 +1242,10 @@
 {
 	int error = 0;
 	int sig;
+
+	error = security_ops->task_prctl(option, arg2, arg3, arg4, arg5);
+	if (error)
+		return error;
 
 	switch (option) {
 		case PR_SET_PDEATHSIG:
diff -Nru a/kernel/uid16.c b/kernel/uid16.c
--- a/kernel/uid16.c	Fri Jul 19 16:03:47 2002
+++ b/kernel/uid16.c	Fri Jul 19 16:03:47 2002
@@ -12,6 +12,7 @@
 #include <linux/prctl.h>
 #include <linux/init.h>
 #include <linux/highuid.h>
+#include <linux/security.h>
 
 #include <asm/uaccess.h>
 
@@ -128,6 +129,7 @@
 asmlinkage long sys_setgroups16(int gidsetsize, old_gid_t *grouplist)
 {
 	old_gid_t groups[NGROUPS];
+	gid_t new_groups[NGROUPS];
 	int i;
 
 	if (!capable(CAP_SETGID))
@@ -137,7 +139,11 @@
 	if (copy_from_user(groups, grouplist, gidsetsize * sizeof(old_gid_t)))
 		return -EFAULT;
 	for (i = 0 ; i < gidsetsize ; i++)
-		current->groups[i] = (gid_t)groups[i];
+		new_groups[i] = (gid_t)groups[i];
+	i = security_ops->task_setgroups(gidsetsize, new_groups);
+	if (i)
+		return i;
+	memcpy(current->groups, new_groups, gidsetsize * sizeof(gid_t));
 	current->ngroups = gidsetsize;
 	return 0;
 }

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2002-07-19 23:10 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2002-07-19 23:09 [BK PATCH] LSM task control for 2.5.26 Greg KH
2002-07-19 23:10 ` Greg KH
2002-07-19 23:10   ` Greg KH
2002-07-19 23:10     ` Greg KH

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox