Skip to contentSkip to conversation

BSD Secure Levels LSM (1/3)

PATCH In review Michael Halcrow 3 participants 6 messages Aug 30, 2004

Subsystems (4)
lore
Share & tools
lore
#0 lore raw

PATCH 1/1 BSD Secure Levels LSM (1/3)

This it the BSD Secure Levels LSM. This patch includes the seclvl module with changes to Kconfig and Makefile.

In the patch submitted a little while back, if mod_reg_security() failed, that return code was not being returned from seclvl_init(). That is fixed in this patch. It applies cleanly to 2.6.8.1 and has been tested on xSeries, pSeries, and zSeries. Please apply.

Mike

security/Kconfig +17 -0
@@ -44,6 +44,23 @@
 	  
 	  If you are unsure how to answer this question, answer N.
 
+config SECURITY_SECLVL
+	tristate "BSD Secure Levels"
+	depends on SECURITY
+	select CRYPTO_SHA1
+	help
+	  Implements BSD Secure Levels as an LSM.  See
+	  Documentation/seclvl.txt for instructions on how to use this
+	  module.
+
+	  If you are unsure how to answer this question, answer N.
+
+config SECURITY_STACKER
+	tristate "Stacker"
+	depends on SECURITY
+	help
+	  Implements LSM stacker.
+
 source security/selinux/Kconfig
 
 endmenu
security/Makefile +2 -0
@@ -15,3 +15,5 @@
 obj-$(CONFIG_SECURITY_SELINUX)		+= selinux/built-in.o
 obj-$(CONFIG_SECURITY_CAPABILITIES)	+= commoncap.o capability.o
 obj-$(CONFIG_SECURITY_ROOTPLUG)		+= commoncap.o root_plug.o
+obj-$(CONFIG_SECURITY_SECLVL)		+= seclvl.o
+obj-$(CONFIG_SECURITY_STACKER)		+= stacker.o
security/seclvl.c +754 -0

754 lines not on this page · raw message

#1 lore raw

PATCH 1/1 BSD Secure Levels LSM (2/3)

BSD Secure Levels LSM. This adds settime hooks necessary to support the BSD Secure Levels model.

arch/mips/kernel/sysirix.c +8 -2
@@ -614,8 +614,14 @@
 
 asmlinkage int irix_stime(int value)
 {
-	if (!capable(CAP_SYS_TIME))
-		return -EPERM;
+	int err;
+	struct timespec tv;
+
+	tv.tv_sec = value;
+	tv.tv_nsec = 0;
+	err = security_settime(&tv, NULL);
+	if (err)
+		return err;
 
 	write_seqlock_irq(&xtime_lock);
 	xtime.tv_sec = value;
arch/ppc64/kernel/time.c +10 -6
@@ -435,9 +435,7 @@
 {
 	int value;
 	struct timespec myTimeval;
-
-	if (!capable(CAP_SYS_TIME))
-		return -EPERM;
+	int err;
 
 	if (get_user(value, tptr))
 		return -EFAULT;
@@ -445,6 +443,10 @@
 	myTimeval.tv_sec = value;
 	myTimeval.tv_nsec = 0;
 
+	err = security_settime(&myTimeval, NULL);
+	if (err)
+		return err;
+
 	do_settimeofday(&myTimeval);
 
 	return 0;
@@ -460,9 +462,7 @@
 {
 	long value;
 	struct timespec myTimeval;
-
-	if (!capable(CAP_SYS_TIME))
-		return -EPERM;
+	int err;
 
 	if (get_user(value, tptr))
 		return -EFAULT;
@@ -470,6 +470,10 @@
 	myTimeval.tv_sec = value;
 	myTimeval.tv_nsec = 0;
 
+	err = security_settime(&myTimeval, NULL);
+	if (err)
+		return err;
+
 	do_settimeofday(&myTimeval);
 
 	return 0;
include/linux/security.h +19 -0
@@ -39,6 +39,7 @@
  * as the default capabilities functions
  */
 extern int cap_capable (struct task_struct *tsk, int cap);
+extern int cap_settime (struct timespec *ts, struct timezone *tz);
 extern int cap_ptrace (struct task_struct *parent, struct task_struct *child);
 extern int cap_capget (struct task_struct *target, kernel_cap_t *effective, kernel_cap_t *inheritable, kernel_cap_t *permitted);
 extern int cap_capset_check (struct task_struct *target, kernel_cap_t *effective, kernel_cap_t *inheritable, kernel_cap_t *permitted);
@@ -999,6 +1000,12 @@
  *	See the syslog(2) manual page for an explanation of the @type values.  
  *	@type contains the type of action.
  *	Return 0 if permission is granted.
+ * @settime:
+ *	Check permission to change the system time. 
+ *	struct timespec and timezone are defined in include/linux/time.h
+ *	@ts contains new time
+ *	@tz contains new timezone
+ *	Return 0 if permission is granted.
  * @vm_enough_memory:
  *	Check permissions for allocating a new virtual mapping.
  *      @pages contains the number of pages.
@@ -1034,6 +1041,7 @@
 	int (*quotactl) (int cmds, int type, int id, struct super_block * sb);
 	int (*quota_on) (struct file * f);
 	int (*syslog) (int type);
+	int (*settime) (struct timespec *ts, struct timezone *tz);
 	int (*vm_enough_memory) (long pages);
 
 	int (*bprm_alloc_security) (struct linux_binprm * bprm);
@@ -1289,6 +1297,12 @@
 	return security_ops->syslog(type);
 }
 
+static inline int security_settime(struct timespec *ts, struct timezone *tz)
+{
+	return security_ops->settime(ts, tz);
+}
+
+
 static inline int security_vm_enough_memory(long pages)
 {
 	return security_ops->vm_enough_memory(pages);
@@ -1961,6 +1975,11 @@
 	return cap_syslog(type);
 }
 
+static inline int security_settime(struct timespec *ts, struct timezone *tz)
+{
+	return cap_settime(ts, tz);
+}
+
 static inline int security_vm_enough_memory(long pages)
 {
 	return cap_vm_enough_memory(pages);
kernel/time.c +12 -5
@@ -28,6 +28,7 @@
 #include <linux/timex.h>
 #include <linux/errno.h>
 #include <linux/smp_lock.h>
+#include <linux/security.h>
 #include <asm/uaccess.h>
 #include <asm/unistd.h>
 
@@ -74,13 +75,17 @@
 asmlinkage long sys_stime(time_t __user *tptr)
 {
 	struct timespec tv;
+	int err;
 
-	if (!capable(CAP_SYS_TIME))
-		return -EPERM;
 	if (get_user(tv.tv_sec, tptr))
 		return -EFAULT;
 
 	tv.tv_nsec = 0;
+
+	err = security_settime(&tv, NULL);
+	if (err)
+		return err;
+
 	do_settimeofday(&tv);
 	return 0;
 }
@@ -142,10 +147,12 @@
 int do_sys_settimeofday(struct timespec *tv, struct timezone *tz)
 {
 	static int firsttime = 1;
+	int error = 0;
+
+	error = security_settime(tv, tz);
+	if (error)
+		return error;
 
-	if (!capable(CAP_SYS_TIME))
-		return -EPERM;
-		
 	if (tz) {
 		/* SMP safe, global irq locking makes it work. */
 		sys_tz = *tz;
security/capability.c +1 -0
@@ -30,6 +30,7 @@
 	.capset_check =			cap_capset_check,
 	.capset_set =			cap_capset_set,
 	.capable =			cap_capable,
+	.settime =			cap_settime,
 	.netlink_send =			cap_netlink_send,
 	.netlink_recv =			cap_netlink_recv,
 
security/commoncap.c +11 -5
@@ -27,20 +27,25 @@
 int cap_capable (struct task_struct *tsk, int cap)
 {
 	/* Derived from include/linux/sched.h:capable. */
-	if (cap_raised (tsk->cap_effective, cap))
+	if (cap_raised(tsk->cap_effective, cap))
 		return 0;
-	else
+	return -EPERM;
+}
+
+int cap_settime(struct timespec *ts, struct timezone *tz)
+{
+	if (!capable(CAP_SYS_TIME))
 		return -EPERM;
+	return 0;
 }
 
 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))
+	    !capable(CAP_SYS_PTRACE))
 		return -EPERM;
-	else
-		return 0;
+	return 0;
 }
 
 int cap_capget (struct task_struct *target, kernel_cap_t *effective,
@@ -368,6 +373,7 @@
 }
 
 EXPORT_SYMBOL(cap_capable);
+EXPORT_SYMBOL(cap_settime);
 EXPORT_SYMBOL(cap_ptrace);
 EXPORT_SYMBOL(cap_capget);
 EXPORT_SYMBOL(cap_capset_check);
security/dummy.c +8 -0
@@ -104,6 +104,13 @@
 	return 0;
 }
 
+static int dummy_settime (struct timeval *tv, struct timezone *tz)
+{
+	if (!capable(CAP_SYS_TIME))
+		return -EPERM;
+	return 0;
+}
+
 /*
  * Check that a process has enough memory to allocate a new virtual
  * mapping. 0 means there is enough memory for the allocation to
@@ -897,6 +904,7 @@
 	set_to_dummy_if_null(ops, quota_on);
 	set_to_dummy_if_null(ops, sysctl);
 	set_to_dummy_if_null(ops, syslog);
+	set_to_dummy_if_null(ops, settime);
 	set_to_dummy_if_null(ops, vm_enough_memory);
 	set_to_dummy_if_null(ops, bprm_alloc_security);
 	set_to_dummy_if_null(ops, bprm_free_security);
#2 lore raw

PATCH 1/1 BSD Secure Levels LSM (3/3)

BSD Secure Levels LSM. This is documentation for the module.

Documentation/seclvl.txt +97 -0
@@ -0,0 +1,97 @@
+BSD Secure Levels Linux Security Module
+Michael A. Halcrow <[email protected]>
+
+
+Introduction
+
+Under the BSD Secure Levels security model, sets of policies are
+associated with levels. Levels range from -1 to 2, with -1 being the
+weakest and 2 being the strongest. These security policies are
+enforced at the kernel level, so not even the superuser is able to
+disable or circumvent them. This hardens the machine against attackers
+who gain root access to the system.
+
+
+Levels and Policies
+
+Level -1 (Permanently Insecure):
+ - Cannot increase the secure level
+
+Level 0 (Insecure):
+ - Cannot ptrace the init process
+
+Level 1 (Default):
+ - /dev/mem and /dev/kmem are read-only
+ - IMMUTABLE and APPEND extended attributes, if set, may not be unset
+ - Cannot load or unload kernel modules
+ - Cannot write directly to a mounted block device
+ - Cannot perform raw I/O operations
+ - Cannot perform network administrative tasks
+ - Cannot setuid any file
+
+Level 2 (Secure):
+ - Cannot decrement the system time
+ - Cannot write to any block device, whether mounted or not
+ - Cannot unmount any mounted filesystems
+
+
+Compilation
+
+To compile the BSD Secure Levels LSM, seclvl.ko, enable the
+SECURITY_SECLVL configuration option.  This is found under Security
+options -> BSD Secure Levels in the kernel configuration menu.
+
+
+Basic Usage
+
+Once the machine is in a running state, with all the necessary modules
+loaded and all the filesystems mounted, you can load the seclvl.ko
+module:
+
+# insmod seclvl.ko
+
+The module defaults to secure level 1, except when compiled directly
+into the kernel, in which case it defaults to secure level 0. To raise
+the secure level to 2, the administrator writes ``2'' to the
+seclvl/seclvl file under the sysfs mount point (assumed to be /sys in
+these examples):
+
+# echo -n "2" > /sys/seclvl/seclvl
+
+Alternatively, you can initialize the module at secure level 2 with
+the initlvl module parameter:
+
+# insmod seclvl.ko initlvl=2
+
+At this point, it is impossible to remove the module or reduce the
+secure level.  If the administrator wishes to have the option of doing
+so, he must provide a module parameter, sha1_passwd, that specifies
+the SHA1 hash of the password that can be used to reduce the secure
+level to 0.
+
+To generate this SHA1 hash, the administrator can use OpenSSL:
+
+# echo -n "boogabooga" | openssl sha1
+abeda4e0f33defa51741217592bf595efb8d289c
+
+In order to use password-instigated secure level reduction, the SHA1
+crypto module must be loaded or compiled into the kernel:
+
+# insmod sha1.ko
+
+The administrator can then insmod the seclvl module, including the
+SHA1 hash of the password:
+
+# insmod seclvl.ko
+         sha1_passwd=abeda4e0f33defa51741217592bf595efb8d289c
+
+To reduce the secure level, write the password to seclvl/passwd under
+your sysfs mount point:
+
+# echo -n "boogabooga" > /sys/seclvl/passwd
+
+The September 2004 edition of Sys Admin Magazine has an article about
+the BSD Secure Levels LSM.  I encourage you to refer to that article
+for a more in-depth treatment of this security module:
+
+http://www.samag.com/documents/s=9304/sam0409a/0409a.htm
#3 lore raw
In reply to Michael Halcrow
Quoted 12 lines · * Michael Halcrow ([email protected]) wrote:
security/Kconfig +6 -0
+config SECURITY_STACKER
+	tristate "Stacker"
+	depends on SECURITY
+	help
+	  Implements LSM stacker.
+
 source security/selinux/Kconfig
 
 endmenu

security/Makefile line 19

Quoted 5 lines
security/Makefile +2 -0
@@ -15,3 +15,5 @@
 obj-$(CONFIG_SECURITY_SELINUX)		+= selinux/built-in.o
 obj-$(CONFIG_SECURITY_CAPABILITIES)	+= commoncap.o capability.o
 obj-$(CONFIG_SECURITY_ROOTPLUG)		+= commoncap.o root_plug.o
+obj-$(CONFIG_SECURITY_SECLVL)		+= seclvl.o
+obj-$(CONFIG_SECURITY_STACKER)		+= stacker.o

Looks like some extra stacker bits snuck in. Unused, correct?

thanks,
-chris

Signature · 1 line
Linux Security Modules     http://lsm.immunix.org     http://lsm.bkbits.net
#4 lore raw
Quoted 9 lines · Chris Wright
Quoted 8 lines · * Michael Halcrow ([email protected]) wrote:
(quoted diff) +6 -0
+config SECURITY_STACKER
+	tristate "Stacker"
+	depends on SECURITY
+	help
+	  Implements LSM stacker.
+
 source security/selinux/Kconfig
Quoted 11 lines

security/Makefile line 19

Quoted 9 lines

endmenu

security/Makefile +2 -0
@@ -15,3 +15,5 @@
 obj-$(CONFIG_SECURITY_SELINUX)		+= selinux/built-in.o
 obj-$(CONFIG_SECURITY_CAPABILITIES)	+= commoncap.o capability.o
 obj-$(CONFIG_SECURITY_ROOTPLUG)		+= commoncap.o root_plug.o
+obj-$(CONFIG_SECURITY_SECLVL)		+= seclvl.o
+obj-$(CONFIG_SECURITY_STACKER)		+= stacker.o

Looks like some extra stacker bits snuck in. Unused, correct?

Yup; I should have caught that. I was using stacker to test seclvl's ability to stack. Fixed.

security/Kconfig +11 -0
@@ -44,6 +44,17 @@
 	  
 	  If you are unsure how to answer this question, answer N.
 
+config SECURITY_SECLVL
+	tristate "BSD Secure Levels"
+	depends on SECURITY
+	select CRYPTO_SHA1
+	help
+	  Implements BSD Secure Levels as an LSM.  See
+	  Documentation/seclvl.txt for instructions on how to use this
+	  module.
+
+	  If you are unsure how to answer this question, answer N.
+
 source security/selinux/Kconfig
 
 endmenu
security/Makefile +1 -0
@@ -15,3 +15,4 @@
 obj-$(CONFIG_SECURITY_SELINUX)		+= selinux/built-in.o
 obj-$(CONFIG_SECURITY_CAPABILITIES)	+= commoncap.o capability.o
 obj-$(CONFIG_SECURITY_ROOTPLUG)		+= commoncap.o root_plug.o
+obj-$(CONFIG_SECURITY_SECLVL)		+= seclvl.o
security/seclvl.c +747 -0

747 lines not on this page · raw message

#5 lore raw
In reply to Michael Halcrow
Quoted 4 lines

+ * Potential future enhancements:
+ * - Export a kill_seclvl function to the rest of the kernel to allow
+ * other modules to disable or change the seclvl (i.e., rootplug
+ * could reduce the seclvl).

Please removed all that downgrading stuff. The whole point of the BSD surelevels is that they can't be turned back.