Below is an initial patch which adds lifecyle hooks to the sk_buff data structure used throughout the networking code. The purpose of these hooks is to facilitate the use of an opaque security context associated with each skb. These per-skb security contexts may be used for a number of purposes including: - Propagating security labels between network layers. - Maintaining general state across network layers to allow late access/audit calls to me made (e.g. may need to allow matching of both user and IP address on an incoming packet at the transport layer, after the network headers have been pulled out of the skb). - Tracking security state as packets are encapsulated and decapsulated (e.g. processing nested security associations on a packet). Note that the skb_ops calls are not themselves meant to be used for access/audit purposes, they just help an LSM module maintain the security context of an skb throughout it's lifecycle. A blank/default security context would be generated for the skb upon alloc_security(), then the security context would be maintained and used semantically by other types of network security ops. The following is a brief description of the skb_ops calls: alloc_security Called when a new skb is allocated, LSM module may return failure if it cannot allocate a security context under OOM. clone copy Called when an skb is cloned or copied. The module will need to determine what kind of copying is needed for the associated security context and do it, as well as manage any reference counts. fragment Called when an skb is being fragmented, with the original and new (fragment) skbs as arguments. The module again will need to copy any security context and/or manage reference counts. encapsulate decapsulate Called when an skb is being encapsulated or decapsulated, for situations such as IPIP tunneling and security association processing. free_security Called when an skb is about to die. The module should free any associated security context as well. This patch only contains protocol-specific hooks for IPv4 (and also needs to be audited to make sure nothing was missed). - James -- James Morris <jmorrisat_private> diff -urN --exclude BitKeeper --exclude SCCS --exclude ChangeSet lsm/include/linux/security.h lsm-w2/include/linux/security.h --- lsm/include/linux/security.h Sat Jul 21 15:07:21 2001 +++ lsm-w2/include/linux/security.h Sat Jul 21 22:07:37 2001 @@ -124,6 +124,17 @@ struct socket_security_ops { }; +struct sk_buff; +struct skb_security_ops { + int (* alloc_security) (struct sk_buff *skb); + void (* clone) (struct sk_buff *newskb, const struct sk_buff *oldskb); + void (* copy) (struct sk_buff *newskb, const struct sk_buff *oldskb); + void (* fragment) (struct sk_buff *newskb, const struct sk_buff *oldskb); + void (* decapsulate) (struct sk_buff *skb); + void (* encapsulate) (struct sk_buff *skb); + void (* free_security) (struct sk_buff *skb); +}; + struct module_security_ops { int (* create_module) (const char *name_user, size_t size); int (* init_module) (const char *name_user, struct module *mod_user); @@ -197,6 +208,7 @@ struct file_security_ops * file_ops; struct task_security_ops * task_ops; struct socket_security_ops * socket_ops; + struct skb_security_ops * skb_ops; struct module_security_ops * module_ops; struct ipc_security_ops * ipc_ops; struct msg_msg_security_ops * msg_msg_ops; diff -urN --exclude BitKeeper --exclude SCCS --exclude ChangeSet lsm/include/linux/skbuff.h lsm-w2/include/linux/skbuff.h --- lsm/include/linux/skbuff.h Sat Jun 30 22:04:37 2001 +++ lsm-w2/include/linux/skbuff.h Sat Jul 21 22:07:41 2001 @@ -213,6 +213,8 @@ #ifdef CONFIG_NET_SCHED __u32 tc_index; /* traffic control index */ #endif + + void *security_context; /* for LSM */ }; #define SK_WMEM_MAX 65535 diff -urN --exclude BitKeeper --exclude SCCS --exclude ChangeSet lsm/kernel/capability_plug.c lsm-w2/kernel/capability_plug.c --- lsm/kernel/capability_plug.c Sat Jul 21 15:07:21 2001 +++ lsm-w2/kernel/capability_plug.c Sat Jul 21 22:21:07 2001 @@ -325,6 +325,14 @@ static int cap_sem_semctl (struct sem_array *sma, int semid, int cmd) {return 0;} static int cap_sem_semop (struct sem_array *sma, int semid, struct sembuf *sops, unsigned nsops, int alter) {return 0;} +static int cap_skb_alloc_security (struct sk_buff *skb) {return 0;} +static void cap_skb_clone (struct sk_buff *newskb, const struct sk_buff *oldskb) {return;} +static void cap_skb_copy (struct sk_buff *newskb, const struct sk_buff *oldskb) {return;} +static void cap_skb_fragment (struct sk_buff *newskb, const struct sk_buff *oldskb) {return;} +static void cap_skb_decapsulate (struct sk_buff *skb) {return;} +static void cap_skb_encapsulate (struct sk_buff *skb) {return;} +static void cap_skb_free_security (struct sk_buff *skb) {return;} + static int cap_register (const char *name, struct security_operations *ops) {return -EINVAL;} static int cap_unregister (const char *name, struct security_operations *ops) {return -EINVAL;} @@ -404,6 +412,16 @@ static struct socket_security_ops cap_socket_ops = {}; +static struct skb_security_ops cap_skb_ops = { + alloc_security: cap_skb_alloc_security, + clone: cap_skb_clone, + copy: cap_skb_copy, + fragment: cap_skb_fragment, + decapsulate: cap_skb_decapsulate, + encapsulate: cap_skb_encapsulate, + free_security: cap_skb_free_security, +}; + static struct module_security_ops cap_module_ops = { create_module: cap_module_create_module, init_module: cap_module_init_module, @@ -475,6 +493,7 @@ file_ops: &cap_file_ops, task_ops: &cap_task_ops, socket_ops: &cap_socket_ops, + skb_ops: &cap_skb_ops, module_ops: &cap_module_ops, ipc_ops: &cap_ipc_ops, msg_msg_ops: &cap_msg_ops, diff -urN --exclude BitKeeper --exclude SCCS --exclude ChangeSet lsm/kernel/security.c lsm-w2/kernel/security.c --- lsm/kernel/security.c Sat Jul 21 15:07:21 2001 +++ lsm-w2/kernel/security.c Sat Jul 21 22:08:37 2001 @@ -162,6 +162,14 @@ static int dummy_sem_semctl (struct sem_array *sma, int semid, int cmd) {return 0;} static int dummy_sem_semop (struct sem_array *sma, int semid, struct sembuf *sops, unsigned nsops, int alter) {return 0;} +static int dummy_skb_alloc_security (struct sk_buff *skb) {return 0;} +static void dummy_skb_clone (struct sk_buff *newskb, const struct sk_buff *oldskb) {return;} +static void dummy_skb_copy (struct sk_buff *newskb, const struct sk_buff *oldskb) {return;} +static void dummy_skb_fragment (struct sk_buff *newskb, const struct sk_buff *oldskb) {return;} +static void dummy_skb_decapsulate (struct sk_buff *skb) {return;} +static void dummy_skb_encapsulate (struct sk_buff *skb) {return;} +static void dummy_skb_free_security (struct sk_buff *skb) {return;} + static int dummy_register (const char *name, struct security_operations *ops) {return -EINVAL;} static int dummy_unregister (const char *name, struct security_operations *ops) {return -EINVAL;} @@ -239,6 +247,16 @@ static struct socket_security_ops dummy_socket_ops = {}; +static struct skb_security_ops dummy_skb_ops = { + alloc_security: dummy_skb_alloc_security, + clone: dummy_skb_clone, + copy: dummy_skb_copy, + fragment: dummy_skb_fragment, + decapsulate: dummy_skb_decapsulate, + encapsulate: dummy_skb_encapsulate, + free_security: dummy_skb_free_security, +}; + static struct module_security_ops dummy_module_ops = { create_module: dummy_module_create_module, init_module: dummy_module_init_module, @@ -310,6 +328,7 @@ file_ops: &dummy_file_ops, task_ops: &dummy_task_ops, socket_ops: &dummy_socket_ops, + skb_ops: &dummy_skb_ops, ipc_ops: &dummy_ipc_ops, module_ops: &dummy_module_ops, msg_msg_ops: &dummy_msg_msg_ops, @@ -380,6 +399,7 @@ !ops->file_ops || !ops->task_ops || !ops->socket_ops || + !ops->skb_ops || !ops->module_ops || !ops->ipc_ops || !ops->msg_msg_ops || diff -urN --exclude BitKeeper --exclude SCCS --exclude ChangeSet lsm/net/core/skbuff.c lsm-w2/net/core/skbuff.c --- lsm/net/core/skbuff.c Thu Jun 28 04:02:01 2001 +++ lsm-w2/net/core/skbuff.c Sat Jul 21 22:25:23 2001 @@ -51,6 +51,7 @@ #include <linux/cache.h> #include <linux/init.h> #include <linux/highmem.h> +#include <linux/security.h> #include <net/ip.h> #include <net/protocol.h> @@ -191,6 +192,11 @@ if (data == NULL) goto nodata; + if (security_ops->skb_ops->alloc_security(skb)) { + kfree(data); + goto nodata; + } + /* XXX: does not include slab overhead */ skb->truesize = size + sizeof(struct sk_buff); @@ -250,6 +256,7 @@ #ifdef CONFIG_NET_SCHED skb->tc_index = 0; #endif + skb->security_context = NULL; } static void skb_drop_fraglist(struct sk_buff *skb) @@ -327,6 +334,7 @@ #ifdef CONFIG_NETFILTER nf_conntrack_put(skb->nfct); #endif + security_ops->skb_ops->free_security(skb); skb_headerinit(skb, NULL, 0); /* clean state */ kfree_skbmem(skb); } @@ -399,7 +407,7 @@ #ifdef CONFIG_NET_SCHED C(tc_index); #endif - + security_ops->skb_ops->clone(n, skb); atomic_inc(&(skb_shinfo(skb)->dataref)); skb->cloned = 1; #ifdef CONFIG_NETFILTER @@ -442,6 +450,7 @@ #ifdef CONFIG_NET_SCHED new->tc_index = old->tc_index; #endif + security_ops->skb_ops->copy(new, old); } /** diff -urN --exclude BitKeeper --exclude SCCS --exclude ChangeSet lsm/net/ipv4/ip_gre.c lsm-w2/net/ipv4/ip_gre.c --- lsm/net/ipv4/ip_gre.c Thu Jun 28 04:02:01 2001 +++ lsm-w2/net/ipv4/ip_gre.c Sat Jul 21 21:55:04 2001 @@ -655,6 +655,7 @@ skb->nf_debug = 0; #endif #endif + security_ops->skb_ops->decapsulate(skb); ipgre_ecn_decapsulate(iph, skb); netif_rx(skb); read_unlock(&ipgre_lock); @@ -884,7 +885,8 @@ skb->nf_debug = 0; #endif #endif - + security_ops->skb_ops->encapsulate(skb); + IPTUNNEL_XMIT(); tunnel->recursion--; return 0; diff -urN --exclude BitKeeper --exclude SCCS --exclude ChangeSet lsm/net/ipv4/ip_output.c lsm-w2/net/ipv4/ip_output.c --- lsm/net/ipv4/ip_output.c Thu Jun 28 04:02:01 2001 +++ lsm-w2/net/ipv4/ip_output.c Sat Jul 21 21:55:04 2001 @@ -856,6 +856,7 @@ skb2->nf_debug = skb->nf_debug; #endif #endif + security_ops->skb_ops->fragment(skb2, skb); /* * Put this fragment into the sending queue. diff -urN --exclude BitKeeper --exclude SCCS --exclude ChangeSet lsm/net/ipv4/ipip.c lsm-w2/net/ipv4/ipip.c --- lsm/net/ipv4/ipip.c Thu Jun 28 04:02:01 2001 +++ lsm-w2/net/ipv4/ipip.c Sat Jul 21 21:55:04 2001 @@ -500,6 +500,7 @@ skb->nf_debug = 0; #endif #endif + security_ops->skb_ops->decapsulate(skb); ipip_ecn_decapsulate(iph, skb); netif_rx(skb); read_unlock(&ipip_lock); @@ -647,6 +648,8 @@ skb->nf_debug = 0; #endif #endif + + security_ops->skb_ops->encapsulate(skb); IPTUNNEL_XMIT(); tunnel->recursion--; diff -urN --exclude BitKeeper --exclude SCCS --exclude ChangeSet lsm/net/ipv4/ipmr.c lsm-w2/net/ipv4/ipmr.c --- lsm/net/ipv4/ipmr.c Thu Jun 28 04:02:01 2001 +++ lsm-w2/net/ipv4/ipmr.c Sat Jul 21 21:55:04 2001 @@ -1104,6 +1104,7 @@ nf_conntrack_put(skb->nfct); skb->nfct = NULL; #endif + security_ops->skb_ops->encapsulate(skb); } static inline int ipmr_forward_finish(struct sk_buff *skb) @@ -1449,6 +1450,7 @@ nf_conntrack_put(skb->nfct); skb->nfct = NULL; #endif + security_ops->skb_ops->decapsulate(skb); netif_rx(skb); dev_put(reg_dev); return 0; @@ -1516,6 +1518,7 @@ nf_conntrack_put(skb->nfct); skb->nfct = NULL; #endif + security_ops->skb_ops->decapsulate(skb); netif_rx(skb); dev_put(reg_dev); return 0; _______________________________________________ linux-security-module mailing list linux-security-moduleat_private http://mail.wirex.com/mailman/listinfo/linux-security-module
This archive was generated by hypermail 2b30 : Sat Jul 21 2001 - 05:55:42 PDT