Skip to contentSkip to conversation

Early init for security modules and various cleanups

PATCH New Chris Wright 5 participants 12 messages Jun 2, 2003

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

PATCH 1/1 Early init for security modules and various cleanups

Hi Linus,

Here is a batch of LSM updates. This patchset allows for statically linked security modules to be initialized earlier in the boot sequence to give consistent security labels to the earliest dynamically created objects such as filesystems and kernel threads. This patch was acked by nearly all the arch maintainers, then subsequently updated based on Sam Ravnborg's feedback. The current version was floated passed arch maintainers without much response, but it did at least get one ack from DaveM.

Additional changes are removing two unused hooks, fixing a bug that Jakub Jelinek reported in setfs[ug]id, and fixing some capability checks in oom killer.

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

This will update these files:

 arch/alpha/vmlinux.lds.S                  |    3 +
 arch/arm/vmlinux-armo.lds.in              |    1 
 arch/arm/vmlinux-armv.lds.in              |    1 
 arch/cris/vmlinux.lds.S                   |    4 +-
 arch/h8300/platform/h8300h/generic/rom.ld |    1 
 arch/i386/vmlinux.lds.S                   |    1 
 arch/ia64/vmlinux.lds.S                   |    4 ++
 arch/m68k/vmlinux-std.lds                 |    1 
 arch/m68k/vmlinux-sun3.lds                |    1 
 arch/m68knommu/vmlinux.lds.S              |    4 --
 arch/mips/vmlinux.lds.S                   |    1 
 arch/mips64/vmlinux.lds.S                 |    1 
 arch/parisc/vmlinux.lds.S                 |    1 
 arch/ppc/vmlinux.lds.S                    |    2 +
 arch/ppc64/vmlinux.lds.S                  |    1 
 arch/s390/vmlinux.lds.S                   |    1 
 arch/sh/vmlinux.lds.S                     |    1 
 arch/sparc/vmlinux.lds.S                  |    1 
 arch/sparc64/vmlinux.lds.S                |    1 
 arch/x86_64/vmlinux.lds.S                 |    1 
 fs/namei.c                                |    2 -
 include/asm-generic/vmlinux.lds.h         |    6 +++
 include/linux/init.h                      |    6 +++
 include/linux/security.h                  |   49 ++++++------------------------
 init/main.c                               |    2 -
 kernel/sys.c                              |   20 ++++--------
 mm/oom_kill.c                             |    7 ++--
 security/capability.c                     |   10 ------
 security/dummy.c                          |   12 -------
 security/root_plug.c                      |    3 -
 security/security.c                       |   13 +++++++
 31 files changed, 77 insertions(+), 85 deletions(-)

with these changes:

Chris Wright:
o [LSM] early init for security modules. As discussed before, this allows for early initialization of security modules when compiled statically into the kernel. The standard do_initcalls is too late for complete coverage of all filesystems and threads, for example.
o [LSM] Remove security_inode_permission_lite hook
o [LSM] Remove task_kmod_set_label hook, it is no longer necessary

Jakub Jelínek:
o [LSM] make sure setfsuid/setfsgid return values are right. Before include/linux/security.h was added, setfsuid/setfsgid always returned

Stephen D. Smalley:
o [LSM] Replaced the direct capability bit tests with calls to the security_capable hook in mm/oom_kill.c

thanks,
-chris
--
Linux Security Modules http://lsm.immunix.org http://lsm.bkbits.net

#1 lore raw

PATCH 1/1 Early init for security modules and various cleanups

# 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.1259 -> 1.1260
# mm/oom_kill.c 1.23 -> 1.24
# include/linux/security.h 1.21 -> 1.22
#
# The following is the BitKeeper ChangeSet Log
# --------------------------------------------
# 03/06/02 [email protected] 1.1260
# [LSM] Replaced the direct capability bit tests with calls to the

# security_capable hook in mm/oom_kill.c
# --------------------------------------------
#
diff -Nru a/include/linux/security.h b/include/linux/security.h
--- a/include/linux/security.h	Mon Jun  2 01:30:56 2003
+++ b/include/linux/security.h	Mon Jun  2 01:30:56 2003
@@ -1231,6 +1231,11 @@
 	return security_ops->sysctl(table, op);
 }

+static inline int security_capable(struct task_struct * tsk, int cap) +{
+ return security_ops->capable(tsk, cap);
+}
+
static inline int security_quotactl (int cmds, int type, int id,
struct super_block *sb)
{
@@ -1894,6 +1899,11 @@
static inline int security_sysctl(ctl_table * table, int op) {
return 0;
+}
+
+static inline int security_capable(struct task_struct * tsk, int cap) +{
+ return cap_capable(tsk, cap);
}

static inline int security_quotactl (int cmds, int type, int id,

mm/oom_kill.c +4 -3
diff -Nru a/mm/oom_kill.c b/mm/oom_kill.c
@@ -20,6 +20,7 @@
 #include <linux/swap.h>
 #include <linux/timex.h>
 #include <linux/jiffies.h>
+#include <linux/security.h>
 
 /* #define DEBUG */
 
@@ -91,7 +92,7 @@
 	 * Superuser processes are usually more important, so we make it
 	 * less likely that we kill those.
 	 */
-	if (cap_t(p->cap_effective) & CAP_TO_MASK(CAP_SYS_ADMIN) ||
+	if (!security_capable(p,CAP_SYS_ADMIN) ||
 				p->uid == 0 || p->euid == 0)
 		points /= 4;
 
@@ -101,7 +102,7 @@
 	 * tend to only have this flag set on applications they think
 	 * of as important.
 	 */
-	if (cap_t(p->cap_effective) & CAP_TO_MASK(CAP_SYS_RAWIO))
+	if (!security_capable(p,CAP_SYS_RAWIO))
 		points /= 4;
 #ifdef DEBUG
 	printk(KERN_DEBUG "OOMkill: task %d (%s) got %d points\n",
@@ -154,7 +155,7 @@
 	p->flags |= PF_MEMALLOC | PF_MEMDIE;
 
 	/* This process has hardware access, be more careful. */
-	if (cap_t(p->cap_effective) & CAP_TO_MASK(CAP_SYS_RAWIO)) {
+	if (!security_capable(p,CAP_SYS_RAWIO)) {
 		force_sig(SIGTERM, p);
 	} else {
 		force_sig(SIGKILL, p);
#2 lore raw

# 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.1260 -> 1.1261
# security/dummy.c 1.23 -> 1.24
# security/capability.c 1.15 -> 1.16
# include/linux/security.h 1.22 -> 1.23
# security/root_plug.c 1.2 -> 1.3
#
# The following is the BitKeeper ChangeSet Log
# --------------------------------------------
# 03/06/02 [email protected] 1.1261
# [LSM] Remove task_kmod_set_label hook, it is no longer necessary.

# kmod is now handled by keventd which already does reparent_to_init,
# so there is no need to worry about getting the security labels right
# for code running off the keventd workqueue.
# --------------------------------------------
#
diff -Nru a/include/linux/security.h b/include/linux/security.h
--- a/include/linux/security.h	Mon Jun  2 01:31:14 2003
+++ b/include/linux/security.h	Mon Jun  2 01:31:14 2003
@@ -46,7 +46,6 @@
 extern int cap_bprm_set_security (struct linux_binprm *bprm);
 extern void cap_bprm_compute_creds (struct linux_binprm *bprm);
 extern int cap_task_post_setuid (uid_t old_ruid, uid_t old_euid, uid_t old_suid, int flags);
-extern void cap_task_kmod_set_label (void);
 extern void cap_task_reparent_to_init (struct task_struct *p);
 extern int cap_syslog (int type);

@@ -607,10 +606,6 @@
* @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.
@@ -1111,7 +1106,6 @@
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); void (*task_to_inode)(struct task_struct *p, struct inode *inode);

@@ -1697,11 +1691,6 @@
return security_ops->task_prctl (option, arg2, arg3, arg4, arg5);
}

-static inline void security_task_kmod_set_label (void)
-{
- security_ops->task_kmod_set_label ();
-}
-
static inline void security_task_reparent_to_init (struct task_struct *p) {
security_ops->task_reparent_to_init (p);
@@ -2329,11 +2318,6 @@
unsigned long arg5)
{
return 0;
-}
-
-static inline void security_task_kmod_set_label (void)
-{
- cap_task_kmod_set_label ();
}

static inline void security_task_reparent_to_init (struct task_struct *p)

security/capability.c +0 -8
diff -Nru a/security/capability.c b/security/capability.c
@@ -248,12 +248,6 @@
 	return 0;
 }
 
-void cap_task_kmod_set_label (void)
-{
-	cap_set_full (current->cap_effective);
-	return;
-}
-
 void cap_task_reparent_to_init (struct task_struct *p)
 {
 	p->cap_effective = CAP_INIT_EFF_SET;
@@ -278,7 +272,6 @@
 EXPORT_SYMBOL(cap_bprm_set_security);
 EXPORT_SYMBOL(cap_bprm_compute_creds);
 EXPORT_SYMBOL(cap_task_post_setuid);
-EXPORT_SYMBOL(cap_task_kmod_set_label);
 EXPORT_SYMBOL(cap_task_reparent_to_init);
 EXPORT_SYMBOL(cap_syslog);
 
@@ -298,7 +291,6 @@
 	.bprm_set_security =		cap_bprm_set_security,
 
 	.task_post_setuid =		cap_task_post_setuid,
-	.task_kmod_set_label =		cap_task_kmod_set_label,
 	.task_reparent_to_init =	cap_task_reparent_to_init,
 
 	.syslog =                       cap_syslog,
security/dummy.c +0 -6
diff -Nru a/security/dummy.c b/security/dummy.c
@@ -517,11 +517,6 @@
 	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;
@@ -871,7 +866,6 @@
 	set_to_dummy_if_null(ops, task_wait);
 	set_to_dummy_if_null(ops, task_kill);
 	set_to_dummy_if_null(ops, task_prctl);
-	set_to_dummy_if_null(ops, task_kmod_set_label);
 	set_to_dummy_if_null(ops, task_reparent_to_init);
  	set_to_dummy_if_null(ops, task_to_inode);
 	set_to_dummy_if_null(ops, ipc_permission);
security/root_plug.c +0 -1
diff -Nru a/security/root_plug.c b/security/root_plug.c
@@ -143,7 +143,6 @@
 	.bprm_set_security =		cap_bprm_set_security,
 
 	.task_post_setuid =		cap_task_post_setuid,
-	.task_kmod_set_label =		cap_task_kmod_set_label,
 	.task_reparent_to_init =	cap_task_reparent_to_init,
 
 	.bprm_check_security =		rootplug_bprm_check_security,
#3 lore raw

# 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.1261  -> 1.1262 
#	    security/dummy.c	1.24    -> 1.25   
#	          fs/namei.c	1.73    -> 1.74   

# include/linux/security.h 1.23 -> 1.24
#
# The following is the BitKeeper ChangeSet Log # --------------------------------------------
# 03/06/02 [email protected] 1.1262
# [LSM] Remove security_inode_permission_lite hook # -------------------------------------------- #

fs/namei.c +1 -1
diff -Nru a/fs/namei.c b/fs/namei.c
@@ -325,7 +325,7 @@
 
 	return -EACCES;
 ok:
-	return security_inode_permission_lite(inode, MAY_EXEC);
+	return security_inode_permission(inode, MAY_EXEC);
 }
 
 /*
include/linux/security.h +0 -23
diff -Nru a/include/linux/security.h b/include/linux/security.h
@@ -327,16 +327,6 @@
  *	@inode contains the inode structure to check.
  *	@mask contains the permission mask.
  *	Return 0 if permission is granted.
- * @inode_permission_lite:
- * 	Check permission before accessing an inode.  This hook is
- * 	currently only called when checking MAY_EXEC access during
- * 	pathname resolution.  The dcache lock is held and thus modules
- * 	that could sleep or contend the lock should return -EAGAIN to
- * 	inform the kernel to drop the lock and try again calling the
- * 	full permission hook.
- * 	@inode contains the inode structure to check.
- * 	@mask contains the permission mask.
- * 	Return 0 if permission is granted.
  * @inode_setattr:
  *	Check permission before setting file attributes.  Note that the kernel
  *	call to notify_change is performed from several locations, whenever
@@ -1052,7 +1042,6 @@
 	int (*inode_readlink) (struct dentry *dentry);
 	int (*inode_follow_link) (struct dentry *dentry, struct nameidata *nd);
 	int (*inode_permission) (struct inode *inode, int mask);
-	int (*inode_permission_lite) (struct inode *inode, int mask);
 	int (*inode_setattr)	(struct dentry *dentry, struct iattr *attr);
 	int (*inode_getattr) (struct vfsmount *mnt, struct dentry *dentry);
         void (*inode_delete) (struct inode *inode);
@@ -1470,12 +1459,6 @@
 	return security_ops->inode_permission (inode, mask);
 }
 
-static inline int security_inode_permission_lite (struct inode *inode,
-						  int mask)
-{
-	return security_ops->inode_permission_lite (inode, mask);
-}
-
 static inline int security_inode_setattr (struct dentry *dentry,
 					  struct iattr *attr)
 {
@@ -2103,12 +2086,6 @@
 }
 
 static inline int security_inode_permission (struct inode *inode, int mask)
-{
-	return 0;
-}
-
-static inline int security_inode_permission_lite (struct inode *inode,
-						  int mask)
 {
 	return 0;
 }
security/dummy.c +0 -6
diff -Nru a/security/dummy.c b/security/dummy.c
@@ -308,11 +308,6 @@
 	return 0;
 }
 
-static int dummy_inode_permission_lite (struct inode *inode, int mask)
-{
-	return 0;
-}
-
 static int dummy_inode_setattr (struct dentry *dentry, struct iattr *iattr)
 {
 	return 0;
@@ -826,7 +821,6 @@
 	set_to_dummy_if_null(ops, inode_readlink);
 	set_to_dummy_if_null(ops, inode_follow_link);
 	set_to_dummy_if_null(ops, inode_permission);
-	set_to_dummy_if_null(ops, inode_permission_lite);
 	set_to_dummy_if_null(ops, inode_setattr);
 	set_to_dummy_if_null(ops, inode_getattr);
 	set_to_dummy_if_null(ops, inode_delete);
#4 lore raw

# 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.1262 -> 1.1263
# kernel/sys.c 1.45 -> 1.46
#
# The following is the BitKeeper ChangeSet Log
# --------------------------------------------
# 03/06/02 [email protected] 1.1263
# [LSM] make sure setfsuid/setfsgid return values are right. Before

# include/linux/security.h was added, setfsuid/setfsgid always returned
# old_fsuid, no matter if the fsuid was actually changed or not.  With
# the default security ops it seems to do the same, because both
# security_task_setuid and security_task_post_setuid return 0, but
# these are hooks which seem to return 0 on success, -errno on failure,
# so if some non-default security hook is installed and ever returns
# -errno in setfsuid/setfsgid, -errno will be returned from the syscall
# instead of the expected old_fsuid. This makes it hard to distinguish
# uids 0xfffff001 .. 0xffffffff from errors of security hooks.
# --------------------------------------------
#
diff -Nru a/kernel/sys.c b/kernel/sys.c
--- a/kernel/sys.c	Mon Jun  2 01:31:40 2003
+++ b/kernel/sys.c	Mon Jun  2 01:31:40 2003
@@ -829,13 +829,11 @@
 asmlinkage long sys_setfsuid(uid_t uid)
 {
 	int old_fsuid;
-	int retval;
-
-	retval = security_task_setuid(uid, (uid_t)-1, (uid_t)-1, LSM_SETID_FS);
-	if (retval)
-		return retval;

old_fsuid = current->fsuid;
+ if (security_task_setuid(uid, (uid_t)-1, (uid_t)-1, LSM_SETID_FS))
+ return old_fsuid;
+
if (uid == current->uid || uid == current->euid ||
uid == current->suid || uid == current->fsuid || capable(CAP_SETUID))
@@ -848,9 +846,7 @@
current->fsuid = uid;
}

- retval = security_task_post_setuid(old_fsuid, (uid_t)-1, (uid_t)-1, LSM_SETID_FS);
- if (retval)
- return retval;
+ security_task_post_setuid(old_fsuid, (uid_t)-1, (uid_t)-1, LSM_SETID_FS);

return old_fsuid;
}
@@ -861,13 +857,11 @@
asmlinkage long sys_setfsgid(gid_t gid)
{
int old_fsgid;
- int retval;
-
- retval = security_task_setgid(gid, (gid_t)-1, (gid_t)-1, LSM_SETID_FS);
- if (retval)
- return retval;

old_fsgid = current->fsgid;
+ if (security_task_setgid(gid, (gid_t)-1, (gid_t)-1, LSM_SETID_FS))
+ return old_fsgid;
+
if (gid == current->gid || gid == current->egid ||
gid == current->sgid || gid == current->fsgid || capable(CAP_SETGID))

#5 lore raw

# 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.1263 -> 1.1264
# arch/m68k/vmlinux-sun3.lds 1.14 -> 1.15
# security/security.c 1.7 -> 1.8
# include/linux/init.h 1.25 -> 1.26
# include/asm-generic/vmlinux.lds.h 1.7 -> 1.8
# arch/x86_64/vmlinux.lds.S 1.16 -> 1.17
# arch/sparc/vmlinux.lds.S 1.16 -> 1.17
# arch/h8300/platform/h8300h/generic/rom.ld 1.1 -> 1.2
# init/main.c 1.99 -> 1.100
# arch/i386/vmlinux.lds.S 1.30 -> 1.31
# arch/parisc/vmlinux.lds.S 1.13 -> 1.14
# arch/mips/vmlinux.lds.S 1.8 -> 1.9
# arch/arm/vmlinux-armv.lds.in 1.24 -> 1.25
# security/capability.c 1.16 -> 1.17
# arch/s390/vmlinux.lds.S 1.13 -> 1.14
# arch/m68knommu/vmlinux.lds.S 1.9 -> 1.10
# arch/cris/vmlinux.lds.S 1.16 -> 1.17
# arch/mips64/vmlinux.lds.S 1.7 -> 1.8
# arch/alpha/vmlinux.lds.S 1.21 -> 1.22
# arch/sh/vmlinux.lds.S 1.10 -> 1.11
# arch/ppc64/vmlinux.lds.S 1.14 -> 1.15
# arch/ia64/vmlinux.lds.S 1.29 -> 1.30
# arch/sparc64/vmlinux.lds.S 1.18 -> 1.19
# arch/m68k/vmlinux-std.lds 1.16 -> 1.17
# arch/arm/vmlinux-armo.lds.in 1.15 -> 1.16
# security/root_plug.c 1.3 -> 1.4
# arch/ppc/vmlinux.lds.S 1.19 -> 1.20
#
# The following is the BitKeeper ChangeSet Log
# --------------------------------------------
# 03/06/02 [email protected] 1.1264
# [LSM] early init for security modules. As discussed before, this allows

# for early initialization of security modules when compiled statically
# into the kernel.  The standard do_initcalls is too late for complete
# coverage of all filesystems and threads, for example.
# --------------------------------------------
#
diff -Nru a/arch/alpha/vmlinux.lds.S b/arch/alpha/vmlinux.lds.S
--- a/arch/alpha/vmlinux.lds.S	Mon Jun  2 01:31:49 2003
+++ b/arch/alpha/vmlinux.lds.S	Mon Jun  2 01:31:49 2003
@@ -74,6 +74,9 @@
 	__con_initcall_end = .;
   }

+ . = ALIGN(8);
+ SECURITY_INIT
+
. = ALIGN(64);
__per_cpu_start = .;
.data.percpu : { *(.data.percpu) }

arch/arm/vmlinux-armo.lds.in +1 -0
diff -Nru a/arch/arm/vmlinux-armo.lds.in b/arch/arm/vmlinux-armo.lds.in
@@ -43,6 +43,7 @@
 		__con_initcall_start = .;
 			*(.con_initcall.init)
 		__con_initcall_end = .;
+		SECURITY_INIT
 		. = ALIGN(32768);
 		__init_end = .;
 	}
arch/arm/vmlinux-armv.lds.in +1 -0
diff -Nru a/arch/arm/vmlinux-armv.lds.in b/arch/arm/vmlinux-armv.lds.in
@@ -53,6 +53,7 @@
 		__con_initcall_start = .;
 			*(.con_initcall.init)
 		__con_initcall_end = .;
+		SECURITY_INIT
 		. = ALIGN(32);
 		__initramfs_start = .;
 			usr/built-in.o(.init.ramfs)
arch/cris/vmlinux.lds.S +3 -1
diff -Nru a/arch/cris/vmlinux.lds.S b/arch/cris/vmlinux.lds.S
@@ -74,7 +74,9 @@
 		__con_initcall_start = .;
 		*(.con_initcall.init)
 		__con_initcall_end = .;
-	
+	}
+	SECURITY_INIT
+
 		/* We fill to the next page, so we can discard all init
 		   pages without needing to consider what payload might be
 		   appended to the kernel image.  */
arch/h8300/platform/h8300h/generic/rom.ld +1 -0
diff -Nru a/arch/h8300/platform/h8300h/generic/rom.ld b/arch/h8300/platform/h8300h/generic/rom.ld
@@ -83,6 +83,7 @@
 	___con_initcall_start = .;
 		*(.con_initcall.init)
 	___con_initcall_end = .;
+	SECURITY_INIT
 		. = ALIGN(4);
 	___initramfs_start = .;
   		*(.init.ramfs)
arch/i386/vmlinux.lds.S +1 -0
diff -Nru a/arch/i386/vmlinux.lds.S b/arch/i386/vmlinux.lds.S
@@ -81,6 +81,7 @@
   __con_initcall_start = .;
   .con_initcall.init : { *(.con_initcall.init) }
   __con_initcall_end = .;
+  SECURITY_INIT
   . = ALIGN(4);
   __alt_instructions = .;
   .altinstructions : { *(.altinstructions) } 
arch/ia64/vmlinux.lds.S +4 -0
diff -Nru a/arch/ia64/vmlinux.lds.S b/arch/ia64/vmlinux.lds.S
@@ -141,6 +141,10 @@
   .con_initcall.init : AT(ADDR(.con_initcall.init) - PAGE_OFFSET)
 	{ *(.con_initcall.init) }
   __con_initcall_end = .;
+  __security_initcall_start = .;
+  .security_initcall.init : AT(ADDR(.security_initcall.init) - PAGE_OFFSET)
+	{ *(.security_initcall.init) }
+  __security_initcall_end = .;
   . = ALIGN(PAGE_SIZE);
   __init_end = .;
 
arch/m68k/vmlinux-std.lds +1 -0
diff -Nru a/arch/m68k/vmlinux-std.lds b/arch/m68k/vmlinux-std.lds
@@ -67,6 +67,7 @@
   __con_initcall_start = .;
   .con_initcall.init : { *(.con_initcall.init) }
   __con_initcall_end = .;
+  SECURITY_INIT
   . = ALIGN(8192);
   __initramfs_start = .;
   .init.ramfs : { *(.init.ramfs) }
arch/m68k/vmlinux-sun3.lds +1 -0
diff -Nru a/arch/m68k/vmlinux-sun3.lds b/arch/m68k/vmlinux-sun3.lds
@@ -61,6 +61,7 @@
 	__con_initcall_start = .;
 	.con_initcall.init : { *(.con_initcall.init) }
 	__con_initcall_end = .;
+	SECURITY_INIT
 	. = ALIGN(8192);
 	__initramfs_start = .;
 	.init.ramfs : { *(.init.ramfs) }
arch/m68knommu/vmlinux.lds.S +1 -3
diff -Nru a/arch/m68knommu/vmlinux.lds.S b/arch/m68knommu/vmlinux.lds.S
@@ -277,9 +277,7 @@
 		__con_initcall_start = .;
 		*(.con_initcall.init)
 		__con_initcall_end = .;
-		__security_initcall_start = .;
-		*(.security_initcall.init)
-		__security_initcall_end = .;
+		SECURITY_INIT
 		. = ALIGN(4);
 		__initramfs_start = .;
 		*(.init.ramfs)
arch/mips/vmlinux.lds.S +1 -0
diff -Nru a/arch/mips/vmlinux.lds.S b/arch/mips/vmlinux.lds.S
@@ -54,6 +54,7 @@
   __con_initcall_start = .;
   .con_initcall.init : { *(.con_initcall.init) }
   __con_initcall_end = .;
+  SECURITY_INIT
   . = ALIGN(4096);	/* Align double page for init_task_union */
   __init_end = .;
 
arch/mips64/vmlinux.lds.S +1 -0
diff -Nru a/arch/mips64/vmlinux.lds.S b/arch/mips64/vmlinux.lds.S
@@ -53,6 +53,7 @@
   __con_initcall_start = .;
   .con_initcall.init : { *(.con_initcall.init) }
   __con_initcall_end = .;
+  SECURITY_INIT
   . = ALIGN(4096);	/* Align double page for init_task_union */
   __init_end = .;
 
arch/parisc/vmlinux.lds.S +1 -0
diff -Nru a/arch/parisc/vmlinux.lds.S b/arch/parisc/vmlinux.lds.S
@@ -80,6 +80,7 @@
   __con_initcall_start = .;
   .con_initcall.init : { *(.con_initcall.init) }
   __con_initcall_end = .;
+  SECURITY_INIT
   . = ALIGN(4096);
   __initramfs_start = .;
   .init.ramfs : { *(.init.ramfs) }
arch/ppc/vmlinux.lds.S +2 -0
diff -Nru a/arch/ppc/vmlinux.lds.S b/arch/ppc/vmlinux.lds.S
@@ -115,6 +115,8 @@
   .con_initcall.init : { *(.con_initcall.init) }
   __con_initcall_end = .;
 
+  SECURITY_INIT
+
   __start___ftr_fixup = .;
   __ftr_fixup : { *(__ftr_fixup) }
   __stop___ftr_fixup = .;
arch/ppc64/vmlinux.lds.S +1 -0
diff -Nru a/arch/ppc64/vmlinux.lds.S b/arch/ppc64/vmlinux.lds.S
@@ -104,6 +104,7 @@
   __con_initcall_start = .;
   .con_initcall.init : { *(.con_initcall.init) }
   __con_initcall_end = .;
+  SECURITY_INIT
   . = ALIGN(4096);
   __initramfs_start = .;
   .init.ramfs : { *(.init.ramfs) }
arch/s390/vmlinux.lds.S +1 -0
diff -Nru a/arch/s390/vmlinux.lds.S b/arch/s390/vmlinux.lds.S
@@ -94,6 +94,7 @@
   __con_initcall_start = .;
   .con_initcall.init : { *(.con_initcall.init) }
   __con_initcall_end = .;
+  SECURITY_INIT
   . = ALIGN(256);
   __initramfs_start = .;
   .init.ramfs : { *(.init.initramfs) }
arch/sh/vmlinux.lds.S +1 -0
diff -Nru a/arch/sh/vmlinux.lds.S b/arch/sh/vmlinux.lds.S
@@ -71,6 +71,7 @@
   __con_initcall_start = .;
   .con_initcall.init : { *(.con_initcall.init) }
   __con_initcall_end = .;
+  SECURITY_INIT
   __machvec_start = .;
   .machvec.init : { *(.machvec.init) }
   __machvec_end = .;
arch/sparc/vmlinux.lds.S +1 -0
diff -Nru a/arch/sparc/vmlinux.lds.S b/arch/sparc/vmlinux.lds.S
@@ -62,6 +62,7 @@
   __con_initcall_start = .;
   .con_initcall.init : { *(.con_initcall.init) }
   __con_initcall_end = .;
+  SECURITY_INIT
   . = ALIGN(4096);
   __initramfs_start = .;
   .init.ramfs : { *(.init.ramfs) }
arch/sparc64/vmlinux.lds.S +1 -0
diff -Nru a/arch/sparc64/vmlinux.lds.S b/arch/sparc64/vmlinux.lds.S
@@ -68,6 +68,7 @@
   __con_initcall_start = .;
   .con_initcall.init : { *(.con_initcall.init) }
   __con_initcall_end = .;
+  SECURITY_INIT
   . = ALIGN(8192); 
   __initramfs_start = .;
   .init.ramfs : { *(.init.ramfs) }
arch/x86_64/vmlinux.lds.S +1 -0
diff -Nru a/arch/x86_64/vmlinux.lds.S b/arch/x86_64/vmlinux.lds.S
@@ -105,6 +105,7 @@
   __con_initcall_start = .;
   .con_initcall.init : { *(.con_initcall.init) }
   __con_initcall_end = .;
+  SECURITY_INIT
   . = ALIGN(4096);
   __initramfs_start = .;
   .init.ramfs : { *(.init.ramfs) }
include/asm-generic/vmlinux.lds.h +6 -0
diff -Nru a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
@@ -45,3 +45,9 @@
 		*(__ksymtab_strings)					\
 	}
 
+#define SECURITY_INIT							\
+	.security_initcall.init : {					\
+		__security_initcall_start = .;				\
+		*(.security_initcall.init) 				\
+		__security_initcall_end = .;				\
+	}
include/linux/init.h +6 -0
diff -Nru a/include/linux/init.h b/include/linux/init.h
@@ -64,6 +64,7 @@
 typedef void (*exitcall_t)(void);
 
 extern initcall_t __con_initcall_start, __con_initcall_end;
+extern initcall_t __security_initcall_start, __security_initcall_end;
 #endif
   
 #ifndef MODULE
@@ -96,6 +97,9 @@
 #define console_initcall(fn) \
 	static initcall_t __initcall_##fn __attribute__ ((unused,__section__ (".con_initcall.init")))=fn
 
+#define security_initcall(fn) \
+	static initcall_t __initcall_##fn __attribute__ ((unused,__section__ (".security_initcall.init"))) = fn
+
 struct obs_kernel_param {
 	const char *str;
 	int (*setup_func)(char *);
@@ -142,6 +146,8 @@
 #define fs_initcall(fn)			module_init(fn)
 #define device_initcall(fn)		module_init(fn)
 #define late_initcall(fn)		module_init(fn)
+
+#define security_initcall(fn)		module_init(fn)
 
 /* These macros create a dummy inline: gcc 2.9x does not count alias
  as usage, hence the `unused function' warning when __init functions
init/main.c +1 -1
diff -Nru a/init/main.c b/init/main.c
@@ -435,8 +435,8 @@
 	pte_chain_init();
 	fork_init(num_physpages);
 	proc_caches_init();
-	security_scaffolding_startup();
 	buffer_init();
+	security_scaffolding_startup();
 	vfs_caches_init(num_physpages);
 	radix_tree_init();
 	signals_init();
security/capability.c +1 -1
diff -Nru a/security/capability.c b/security/capability.c
@@ -340,7 +340,7 @@
 	}
 }
 
-module_init (capability_init);
+security_initcall (capability_init);
 module_exit (capability_exit);
 
 MODULE_DESCRIPTION("Standard Linux Capabilities Security Module");
security/root_plug.c +1 -1
diff -Nru a/security/root_plug.c b/security/root_plug.c
@@ -183,7 +183,7 @@
 	printk (KERN_INFO "Root Plug module removed\n");
 }
 
-module_init (rootplug_init);
+security_initcall (rootplug_init);
 module_exit (rootplug_exit);
 
 MODULE_DESCRIPTION("Root Plug sample LSM module, written for Linux Journal article");
security/security.c +12 -1
diff -Nru a/security/security.c b/security/security.c
@@ -38,12 +38,22 @@
 	return 0;
 }
 
+static void __init do_security_initcalls(void)
+{
+	initcall_t *call;
+	call = &__security_initcall_start;
+	while (call < &__security_initcall_end) {
+		(*call)();
+		call++;
+	}
+}
+
 /**
  * security_scaffolding_startup - initialzes the security scaffolding framework
  *
  * This should be called early in the kernel initialization sequence.
  */
-int security_scaffolding_startup (void)
+int __init security_scaffolding_startup (void)
 {
 	printk (KERN_INFO "Security Scaffold v" SECURITY_SCAFFOLD_VERSION
 		" initialized\n");
@@ -55,6 +65,7 @@
 	}
 
 	security_ops = &dummy_security_ops;
+	do_security_initcalls();
 
 	return 0;
 }
#6 lore raw
In reply to Chris Wright
Quoted 8 lines · Chris Wright
mm/oom_kill.c +1 -1
@@ -91,7 +92,7 @@
 	 * Superuser processes are usually more important, so we make it
 	 * less likely that we kill those.
 	 */
-	if (cap_t(p->cap_effective) & CAP_TO_MASK(CAP_SYS_ADMIN) ||
+	if (!security_capable(p,CAP_SYS_ADMIN) ||
 				p->uid == 0 || p->euid == 0)
 		points /= 4;

..............

mm/oom_kill.c line 106

Quoted 3 lines
mm/oom_kill.c +1 -1
-	if (cap_t(p->cap_effective) & CAP_TO_MASK(CAP_SYS_RAWIO))
+	if (!security_capable(p,CAP_SYS_RAWIO))
 		points /= 4;

Correct me if i am wrong, but I think it is not a good idea to favor applications with more
capabilities, as ussualy those are most wanted target on a system.

--
Grzegorz Jaskiewcz

#7 lore raw
Quoted 11 lines · * Grzegorz Jaskiewicz ([email protected]) wrote:
Quoted 8 lines · Chris Wright
mm/oom_kill.c +1 -1
@@ -91,7 +92,7 @@
 	 * Superuser processes are usually more important, so we make it
 	 * less likely that we kill those.
 	 */
-	if (cap_t(p->cap_effective) & CAP_TO_MASK(CAP_SYS_ADMIN) ||
+	if (!security_capable(p,CAP_SYS_ADMIN) ||
 				p->uid == 0 || p->euid == 0)
 		points /= 4;

..............

Quoted 7 lines

mm/oom_kill.c line 106

Quoted 3 lines
mm/oom_kill.c +1 -1
-	if (cap_t(p->cap_effective) & CAP_TO_MASK(CAP_SYS_RAWIO))
+	if (!security_capable(p,CAP_SYS_RAWIO))
 		points /= 4;

Correct me if i am wrong, but I think it is not a good idea to favor applications with more
capabilities, as ussualy those are most wanted target on a system.

security_capable() returns 0 if that capability bit is set. so there is no functional change here, just allows the security module to see the capability check that was hand coded.

thanks,
-chris

Signature · 1 line
Linux Security Modules     http://lsm.immunix.org     http://lsm.bkbits.net
#8 lore raw
Quoted 2 lines · Chris Wright

security_capable() returns 0 if that capability bit is set.

That's just bizarre. Is there any logic behind it?

#9 lore raw
Quoted 5 lines · Andrew Morton
Quoted 2 lines · Chris Wright

security_capable() returns 0 if that capability bit is set.

That's just bizarre. Is there any logic behind it?

The LSM access control hooks all return 0 on success (i.e. permission granted) and negative error code on failure, like most of the rest of the kernel interfaces (e.g. consider permission()). Hence, the security_capable() hook returns 0 when the capability is granted to the specified task. Naturally, the capable() function (which now internally calls security_capable) preserves the old interface, and most callers still invoke it rather than directly calling security_capable(). However, the oom killer code is performing a capability test for a task other than current; hence, it makes a direct call to the security_capable() hook that supports passing a particular task, unlike the capable() function.

Signature · 2 lines
Stephen Smalley <[email protected]>
National Security Agency
#10 lore raw
Quoted 4 lines · Stephen Smalley
Quoted 2 lines · Andrew Morton

Chris Wright <[email protected]> wrote:

Quoted 8 lines
Quoted 4 lines
Quoted 2 lines

security_capable() returns 0 if that capability bit is set.

That's just bizarre. Is there any logic behind it?

The LSM access control hooks all return 0 on success (i.e. permission granted) and negative error code on failure, like most of the rest of the kernel interfaces (e.g. consider permission())

Maybe it should be called "security_incapable() and then the return code can be treated as a boolean true/false....

Chris

Signature · 4 lines
Chris Friesen                    | MailStop: 043/33/F10
Nortel Networks                  | work: (613) 765-0557
3500 Carling Avenue              | fax:  (613) 765-2986
Nepean, ON K2H 8E9 Canada        | email: [email protected]
#11 lore raw
In reply to Andrew Morton
Quoted 5 lines · * Andrew Morton ([email protected]) wrote:
Quoted 2 lines · Chris Wright

security_capable() returns 0 if that capability bit is set.

That's just bizarre. Is there any logic behind it?

Yes, as Stephen pointed out, it's common for the security interface to return 0 on success on -errno on failure.

cheers,
-chris

Signature · 1 line
Linux Security Modules     http://lsm.immunix.org     http://lsm.bkbits.net