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);