public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: Michael Halcrow <lkml@halcrow.us>
To: LKML <linux-kernel@vger.kernel.org>
Subject: [PATCH] BSD Secure Levels LSM (1/3)
Date: Tue, 10 Aug 2004 10:14:20 -0500	[thread overview]
Message-ID: <20040810151420.GA4993@halcrow.us> (raw)


[-- Attachment #1.1: Type: text/plain, Size: 1199 bytes --]

This set of patches implements BSD Secure Levels as a Linux Security
Module (LSM).

The purpose of this patch is to leverage the LSM hook infrastructure
to provide administrators who are already familiar with BSD Secure
Levels the option of using a simple protection mechanism on their
Linux servers.  By using this module, those administrators who require
the security provided by BSD Secure Levels do not have to deal with
the complexity of deploying a capabilities- or SE Linux-based
mandatory access control solution.

Sys Admin Magazine is carrying an article about this module in its
September issue:

http://www.samag.com/documents/s=9304/sam0409a/0409a.htm

This particular patch adds a set of hooks that are necessary to catch
attempts to decrement the system time.  These hooks do not restrict
hardware devices that perform this operation, such as in
drivers/acorn/char/i2c.c.

Mike
.___________________________________________________________________.
                         Michael A. Halcrow                          
       Security Software Engineer, IBM Linux Technology Center       
GnuPG Fingerprint: 05B5 08A8 713A 64C1 D35D  2371 2D3C FDDA 3EB6 601D

[-- Attachment #1.2: settime_2.6.8-rc3.diff --]
[-- Type: text/plain, Size: 7046 bytes --]

--- linux-2.6.8-rc3/arch/mips/kernel/sysirix.c	2004-08-09 16:15:39.000000000 -0500
+++ linux-2.6.8-rc3_seclvl/arch/mips/kernel/sysirix.c	2004-08-09 16:16:33.000000000 -0500
@@ -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;
--- linux-2.6.8-rc3/arch/ppc64/kernel/time.c	2004-08-09 16:15:42.000000000 -0500
+++ linux-2.6.8-rc3_seclvl/arch/ppc64/kernel/time.c	2004-08-09 16:16:35.000000000 -0500
@@ -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;
--- linux-2.6.8-rc3/include/linux/security.h	2004-08-09 16:16:08.000000000 -0500
+++ linux-2.6.8-rc3_seclvl/include/linux/security.h	2004-08-09 16:17:00.000000000 -0500
@@ -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);
--- linux-2.6.8-rc3/kernel/time.c	2004-06-16 00:19:01.000000000 -0500
+++ linux-2.6.8-rc3_seclvl/kernel/time.c	2004-08-09 08:05:02.000000000 -0500
@@ -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;
--- linux-2.6.8-rc3/security/capability.c	2004-06-16 00:19:13.000000000 -0500
+++ linux-2.6.8-rc3_seclvl/security/capability.c	2004-08-09 08:03:30.000000000 -0500
@@ -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,
 
--- linux-2.6.8-rc3/security/commoncap.c	2004-06-16 00:19:13.000000000 -0500
+++ linux-2.6.8-rc3_seclvl/security/commoncap.c	2004-08-09 08:06:57.000000000 -0500
@@ -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);
--- linux-2.6.8-rc3/security/dummy.c	2004-08-09 16:16:09.000000000 -0500
+++ linux-2.6.8-rc3_seclvl/security/dummy.c	2004-08-09 16:17:05.000000000 -0500
@@ -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);

[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]

             reply	other threads:[~2004-08-10 16:47 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2004-08-10 15:14 Michael Halcrow [this message]
2004-08-10 17:17 ` [PATCH] BSD Secure Levels LSM (1/3) Lee Revell
  -- strict thread matches above, loose matches on Subject: below --
2004-08-30 14:35 Michael Halcrow
2004-08-30 16:08 ` Chris Wright
2004-08-30 15:15   ` Michael Halcrow
2004-08-30 16:10 ` Christoph Hellwig

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20040810151420.GA4993@halcrow.us \
    --to=lkml@halcrow.us \
    --cc=linux-kernel@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox