|
|
Log in / Subscribe / Register

[Stacking v4 1/3] New lsm chaining patch

From:  Serge Hallyn <serue@us.ibm.com>
To:  Chris Wright <chrisw@osdl.org>, Stephen Smalley <sds@epoch.ncsc.mil>, James Morris <jmorris@redhat.com>
Subject:  [RFC] [Stacking v4 1/3] New lsm chaining patch
Date:  Fri, 03 Dec 2004 12:03:59 -0600
Cc:  LSM Mailing List <linux-security-module@wirex.com>

Attached is a new version of lsm-chain.patch.  It moves
CONFIG_SECURITY_STACKER out of security.h, changing the
security_get_value and friends in the case of no CONFIG_SECURITY_STACKER
from #defines in security.h to brief static inlines in security.c.

thanks,
-serge
-- 
=======================================================
Serge Hallyn
Security Software Engineer, IBM Linux Technology Center
serue@us.ibm.com

Index: linux-2.6.9/fs/exec.c
===================================================================
--- linux-2.6.9.orig/fs/exec.c	2004-11-25 09:55:31.655895608 -0600
+++ linux-2.6.9/fs/exec.c	2004-11-25 09:57:12.615547408 -0600
@@ -1116,6 +1116,7 @@
 	bprm->file = file;
 	bprm->filename = filename;
 	bprm->interp = filename;
+	INIT_HLIST_HEAD(&bprm->security);
 	bprm->mm = mm_alloc();
 	if (!bprm->mm)
 		goto out_file;
@@ -1171,8 +1172,7 @@
 			__free_page(page);
 	}
 
-	if (bprm->security)
-		security_bprm_free(bprm);
+	security_bprm_free(bprm);
 
 out_mm:
 	if (bprm->mm)
Index: linux-2.6.9/fs/inode.c
===================================================================
--- linux-2.6.9.orig/fs/inode.c	2004-11-25 09:53:49.150478800 -0600
+++ linux-2.6.9/fs/inode.c	2004-11-25 09:57:12.616547256 -0600
@@ -134,7 +134,7 @@
 		inode->i_bdev = NULL;
 		inode->i_cdev = NULL;
 		inode->i_rdev = 0;
-		inode->i_security = NULL;
+		INIT_HLIST_HEAD(&inode->i_security);
 		inode->dirtied_when = 0;
 		if (security_inode_alloc(inode)) {
 			if (inode->i_sb->s_op->destroy_inode)
Index: linux-2.6.9/include/linux/binfmts.h
===================================================================
--- linux-2.6.9.orig/include/linux/binfmts.h	2004-10-18 16:54:30.000000000
-0500
+++ linux-2.6.9/include/linux/binfmts.h	2004-11-25 09:57:12.624546040 -0600
@@ -29,7 +29,7 @@
 	struct file * file;
 	int e_uid, e_gid;
 	kernel_cap_t cap_inheritable, cap_permitted, cap_effective;
-	void *security;
+	struct hlist_head security;
 	int argc, envc;
 	char * filename;	/* Name of binary as seen by procps */
 	char * interp;		/* Name of the binary really executed. Most
Index: linux-2.6.9/include/linux/fs.h
===================================================================
--- linux-2.6.9.orig/include/linux/fs.h	2004-11-25 09:53:52.144023712 -0600
+++ linux-2.6.9/include/linux/fs.h	2004-11-25 09:57:12.625545888 -0600
@@ -479,7 +479,7 @@
 	unsigned int		i_flags;
 
 	atomic_t		i_writecount;
-	void			*i_security;
+	struct hlist_head	i_security;
 	union {
 		void		*generic_ip;
 	} u;
@@ -553,7 +553,7 @@
 	rwlock_t lock;          /* protects pid, uid, euid fields */
 	int pid;		/* pid or -pgrp where SIGIO should be sent */
 	uid_t uid, euid;	/* uid/euid of process setting the owner */
-	void *security;
+	struct hlist_head security;
 	int signum;		/* posix.1b rt signal to be delivered on IO */
 };
 
@@ -589,7 +589,7 @@
 	struct file_ra_state	f_ra;
 
 	unsigned long		f_version;
-	void			*f_security;
+	struct hlist_head	f_security;
 
 	/* needed for tty driver, and maybe others */
 	void			*private_data;
@@ -773,7 +773,7 @@
 	int			s_syncing;
 	int			s_need_sync_fs;
 	atomic_t		s_active;
-	void                    *s_security;
+ 	struct hlist_head	s_security;
 	struct xattr_handler	**s_xattr;
 
 	struct list_head	s_dirty;	/* dirty inodes */
Index: linux-2.6.9/include/linux/ipc.h
===================================================================
--- linux-2.6.9.orig/include/linux/ipc.h	2004-10-18 16:53:05.000000000 -0500
+++ linux-2.6.9/include/linux/ipc.h	2004-11-25 09:57:12.632544824 -0600
@@ -65,7 +65,7 @@
 	gid_t		cgid;
 	mode_t		mode; 
 	unsigned long	seq;
-	void		*security;
+	struct hlist_head security;
 };
 
 #endif /* __KERNEL__ */
Index: linux-2.6.9/include/linux/msg.h
===================================================================
--- linux-2.6.9.orig/include/linux/msg.h	2004-10-18 16:54:31.000000000 -0500
+++ linux-2.6.9/include/linux/msg.h	2004-11-25 09:57:12.633544672 -0600
@@ -70,7 +70,7 @@
 	long  m_type;          
 	int m_ts;           /* message text size */
 	struct msg_msgseg* next;
-	void *security;
+	struct hlist_head security;
 	/* the actual message follows immediately */
 };
 
Index: linux-2.6.9/include/linux/sched.h
===================================================================
--- linux-2.6.9.orig/include/linux/sched.h	2004-11-25 09:53:52.644947560 -0600
+++ linux-2.6.9/include/linux/sched.h	2004-11-25 09:57:12.633544672 -0600
@@ -627,7 +627,7 @@
 	void *notifier_data;
 	sigset_t *notifier_mask;
 	
-	void *security;
+	struct hlist_head security;
 	struct audit_context *audit_context;
 
 /* Thread group tracking */
Index: linux-2.6.9/include/linux/security.h
===================================================================
--- linux-2.6.9.orig/include/linux/security.h	2004-11-25 09:53:52.660945128
-0600
+++ linux-2.6.9/include/linux/security.h	2004-11-25 14:18:04.943031944 -0600
@@ -34,6 +34,55 @@
 struct ctl_table;
 
 /*
+ * structure to be embedded at top of each LSM's security
+ * objects.
+ *
+ * XXX  If performance is still bad, then I guess start
+ * ifdefing this out again...
+ */
+struct security_list {
+	struct hlist_node list;
+	int security_id;
+};
+
+/*
+ * How to use:
+ *
+ * In any object which you wish to chain onto a kernel security object
+ * such as inode->i_security, add the following:
+ *     struct security_list lsm_list;
+ * 
+ * The function prototypes are as follows:
+ */
+
+extern rwlock_t security_list_rwlock;
+extern struct security_list *security_get_value(struct hlist_head *head,
+			int security_id);
+extern struct security_list *security_set_value(struct hlist_head *head,
+			int security_id, struct security_list *obj_node);
+extern void security_set_value_nocheck(struct hlist_head *head,
+			int security_id, struct security_list *obj_node);
+extern struct security_list *security_del_value(struct hlist_head *head,
+			int security_id);
+
+#define security_get_value_type(head, id, type) ( { \
+	struct security_list *v = security_get_value(head, id); \
+	v ? hlist_entry(v, type, lsm_list) : NULL; } )
+
+#define security_set_value_type(head, id, value, type) ( { \
+	struct security_list *v; \
+	v = security_set_value(head, id, &value->lsm_list); \
+	v ? hlist_entry(v, type, lsm_list) : NULL; } )
+
+#define security_set_value_nocheck_type(head, id, value) \
+	security_set_value_nocheck(head, id, &value->lsm_list);
+
+#define security_del_value_type(head, id, type) ( { \
+	struct security_list *v; \
+	v = security_del_value(head, id); \
+	v ? hlist_entry(v, type, lsm_list) : NULL; } )
+
+/*
  * These functions are in security/capability.c and are used
  * as the default capabilities functions
  */
Index: linux-2.6.9/include/net/sock.h
===================================================================
--- linux-2.6.9.orig/include/net/sock.h	2004-11-25 09:55:31.848866272 -0600
+++ linux-2.6.9/include/net/sock.h	2004-11-25 09:57:12.636544216 -0600
@@ -254,7 +254,7 @@
 	__u32			sk_sndmsg_off;
 	struct sk_buff		*sk_send_head;
 	int			sk_write_pending;
-	void			*sk_security;
+	struct hlist_head	sk_security;
 	__u8			sk_queue_shrunk;
 	/* three bytes hole, try to pack */
 	void			(*sk_state_change)(struct sock *sk);
Index: linux-2.6.9/ipc/msg.c
===================================================================
--- linux-2.6.9.orig/ipc/msg.c	2004-11-25 09:53:53.040887368 -0600
+++ linux-2.6.9/ipc/msg.c	2004-11-25 09:57:12.637544064 -0600
@@ -98,7 +98,7 @@
 	msq->q_perm.mode = (msgflg & S_IRWXUGO);
 	msq->q_perm.key = key;
 
-	msq->q_perm.security = NULL;
+	INIT_HLIST_HEAD(&msq->q_perm.security);
 	retval = security_msg_queue_alloc(msq);
 	if (retval) {
 		ipc_rcu_putref(msq);
Index: linux-2.6.9/ipc/msgutil.c
===================================================================
--- linux-2.6.9.orig/ipc/msgutil.c	2004-10-18 16:54:07.000000000 -0500
+++ linux-2.6.9/ipc/msgutil.c	2004-11-25 09:57:12.644543000 -0600
@@ -41,7 +41,7 @@
 		return ERR_PTR(-ENOMEM);
 
 	msg->next = NULL;
-	msg->security = NULL;
+	INIT_HLIST_HEAD(&msg->security);
 
 	if (copy_from_user(msg + 1, src, alen)) {
 		err = -EFAULT;
Index: linux-2.6.9/ipc/sem.c
===================================================================
--- linux-2.6.9.orig/ipc/sem.c	2004-11-25 09:53:53.041887216 -0600
+++ linux-2.6.9/ipc/sem.c	2004-11-25 09:57:12.645542848 -0600
@@ -177,7 +177,7 @@
 	sma->sem_perm.mode = (semflg & S_IRWXUGO);
 	sma->sem_perm.key = key;
 
-	sma->sem_perm.security = NULL;
+	INIT_HLIST_HEAD(&sma->sem_perm.security);
 	retval = security_sem_alloc(sma);
 	if (retval) {
 		ipc_rcu_putref(sma);
Index: linux-2.6.9/ipc/shm.c
===================================================================
--- linux-2.6.9.orig/ipc/shm.c	2004-11-25 09:53:53.042887064 -0600
+++ linux-2.6.9/ipc/shm.c	2004-11-25 09:57:12.645542848 -0600
@@ -196,7 +196,7 @@
 	shp->shm_flags = (shmflg & S_IRWXUGO);
 	shp->mlock_user = NULL;
 
-	shp->shm_perm.security = NULL;
+	INIT_HLIST_HEAD(&shp->shm_perm.security);
 	error = security_shm_alloc(shp);
 	if (error) {
 		ipc_rcu_putref(shp);
Index: linux-2.6.9/kernel/fork.c
===================================================================
--- linux-2.6.9.orig/kernel/fork.c	2004-11-25 09:55:31.858864752 -0600
+++ linux-2.6.9/kernel/fork.c	2004-11-25 09:57:12.646542696 -0600
@@ -872,7 +872,7 @@
 	p->utime = p->stime = 0;
 	p->lock_depth = -1;		/* -1 = no lock */
 	do_posix_clock_monotonic_gettime(&p->start_time);
-	p->security = NULL;
+	INIT_HLIST_HEAD(&p->security);
 	p->io_context = NULL;
 	p->io_wait = NULL;
 	p->audit_context = NULL;
Index: linux-2.6.9/security/dummy.c
===================================================================
--- linux-2.6.9.orig/security/dummy.c	2004-11-25 09:53:53.534812280 -0600
+++ linux-2.6.9/security/dummy.c	2004-11-25 09:57:12.647542544 -0600
@@ -1036,3 +1036,5 @@
 #endif	/* CONFIG_SECURITY_NETWORK */
 }
 
+EXPORT_SYMBOL_GPL(security_fixup_ops);
+
Index: linux-2.6.9/security/security.c
===================================================================
--- linux-2.6.9.orig/security/security.c	2004-11-25 09:53:53.545810608 -0600
+++ linux-2.6.9/security/security.c	2004-11-25 14:34:54.160607552 -0600
@@ -20,6 +20,128 @@
 
 #define SECURITY_FRAMEWORK_VERSION	"1.0.0"
 
+rwlock_t security_list_rwlock = RW_LOCK_UNLOCKED;
+
+#ifdef CONFIG_SECURITY_STACKER
+struct security_list *
+security_get_value(struct hlist_head *head, int security_id)
+{
+	unsigned long flags;
+	struct security_list *e, *ret = NULL;
+	struct hlist_node *tmp;
+
+	read_lock_irqsave(&security_list_rwlock, flags);
+	hlist_for_each_entry(e, tmp, head, list) {
+		if (e->security_id == security_id) {
+			ret = e;
+			goto out;
+		}
+	}
+
+out:
+	read_unlock_irqrestore(&security_list_rwlock, flags);
+	return ret;
+}
+
+void
+security_set_value_nocheck(struct hlist_head *head, int security_id,
+	struct security_list *obj_node)
+{
+	unsigned long flags;
+
+	write_lock_irqsave(&security_list_rwlock, flags);
+
+	INIT_HLIST_NODE(&obj_node->list);
+	obj_node->security_id = security_id;
+	hlist_add_head(&obj_node->list, head);
+
+	write_unlock_irqrestore(&security_list_rwlock, flags);
+}
+
+struct security_list *
+security_set_value(struct hlist_head *head, int security_id,
+	struct security_list *obj_node)
+{
+	unsigned long flags;
+	struct security_list *e, *ret = NULL;
+	struct hlist_node *tmp;
+
+	write_lock_irqsave(&security_list_rwlock, flags);
+	hlist_for_each_entry(e, tmp, head, list) {
+		if (e->security_id == security_id) {
+			ret = e;
+			hlist_del(&e->list);
+			break;
+		}
+	}
+
+	INIT_HLIST_NODE(&obj_node->list);
+	obj_node->security_id = security_id;
+	hlist_add_head(&obj_node->list, head);
+
+	write_unlock_irqrestore(&security_list_rwlock, flags);
+	return ret;
+}
+
+struct security_list *
+security_del_value(struct hlist_head *head, int security_id)
+{
+	unsigned long flags;
+	struct security_list *e, *ret = NULL;
+	struct hlist_node *tmp;
+
+	write_lock_irqsave(&security_list_rwlock, flags);
+	hlist_for_each_entry(e, tmp, head, list) {
+		if (e->security_id == security_id) {
+			ret = e;
+			hlist_del(&e->list);
+			goto out;
+		}
+	}
+
+out:
+	write_unlock_irqrestore(&security_list_rwlock, flags);
+	return ret;
+}
+
+#else
+struct security_list *
+security_get_value(struct hlist_head *head, int security_id)
+{
+	struct hlist_node *tmp = head->first;
+	return tmp ? hlist_entry(tmp, struct security_list, list) : NULL;
+}
+
+struct security_list *
+security_set_value(struct hlist_head *head, int security_id,
+	struct security_list *obj_node)
+{
+	struct hlist_node *tmp = head->first;
+	head->first = &obj_node->list;
+	return tmp ? hlist_entry(tmp, struct security_list, list) : NULL;
+}
+
+void
+security_set_value_nocheck(struct hlist_head *head, int security_id,
+	struct security_list *obj_node)
+{
+	head->first = &obj_node->list;
+}
+
+struct security_list *
+security_del_value(struct hlist_head *head, int security_id)
+{
+	struct hlist_node *tmp = head->first;
+	head->first = NULL;
+	return tmp ? hlist_entry(tmp, struct security_list, list) : NULL;
+}
+#endif
+
+EXPORT_SYMBOL_GPL(security_get_value);
+EXPORT_SYMBOL_GPL(security_set_value);
+EXPORT_SYMBOL_GPL(security_set_value_nocheck);
+EXPORT_SYMBOL_GPL(security_del_value);
+
 /* things that live in dummy.c */
 extern struct security_operations dummy_security_ops;
 extern void security_fixup_ops(struct security_operations *ops);



Copyright © 2004, Eklektix, Inc.
Comments and public postings are copyrighted by their creators.
Linux is a registered trademark of Linus Torvalds