* [PATCH 0/2] Labeled networking core stack changes for 2.6.25 @ 2008-01-03 17:25 Paul Moore 2008-01-03 17:25 ` [PATCH 1/2] LSM: Add inet_sys_snd_skb() LSM hook Paul Moore 2008-01-03 17:25 ` [PATCH 2/2] NET: Clone the sk_buff 'iif' field in __skb_clone() Paul Moore 0 siblings, 2 replies; 9+ messages in thread From: Paul Moore @ 2008-01-03 17:25 UTC (permalink / raw) To: netdev; +Cc: davem Two small patches for 2.6.25 which enable some new labeled networking features and fixes. One patch introduces a new outbound packet LSM hook and one adds the skb 'iif' field to the list of fields copied during a clone operation. Both of these patches are part of a much larger patchset that has been under review on the SELinux and LSM mailing lists for the past few months (some bits have been under review since this past spring). I'll save everyone the spam and not post the entire patchset here, but if you want to take a look you can find the latest bits here: * git://git.infradead.org/users/pcmoore/lblnet-2.6_testing I'm posting these patches here for review and hopefully an 'Acked-by', not inclusion into net-2.6.25. If these patches are acceptable then they will pushed upstream with the rest of the changes when 2.6.25 is ready. Thanks. -- paul moore linux security @ hp ^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 1/2] LSM: Add inet_sys_snd_skb() LSM hook 2008-01-03 17:25 [PATCH 0/2] Labeled networking core stack changes for 2.6.25 Paul Moore @ 2008-01-03 17:25 ` Paul Moore 2008-01-04 4:45 ` David Miller 2008-01-03 17:25 ` [PATCH 2/2] NET: Clone the sk_buff 'iif' field in __skb_clone() Paul Moore 1 sibling, 1 reply; 9+ messages in thread From: Paul Moore @ 2008-01-03 17:25 UTC (permalink / raw) To: netdev; +Cc: davem Add an inet_sys_snd_skb() LSM hook to allow the LSM to provide packet level access control for all outbound packets. Using the existing postroute_last netfilter hook turns out to be problematic as it is can be invoked multiple times for a single packet, e.g. individual IPsec transforms, adding unwanted overhead and complicating the security policy. Signed-off-by: Paul Moore <paul.moore@hp.com> --- include/linux/security.h | 11 +++++++++++ net/ipv4/ip_output.c | 7 +++++++ net/ipv6/ip6_output.c | 5 +++++ security/dummy.c | 8 +++++++- security/security.c | 6 ++++++ 5 files changed, 36 insertions(+), 1 deletions(-) diff --git a/include/linux/security.h b/include/linux/security.h index db19c92..1b8d332 100644 --- a/include/linux/security.h +++ b/include/linux/security.h @@ -876,6 +876,10 @@ struct request_sock; * Sets the connection's peersid to the secmark on skb. * @req_classify_flow: * Sets the flow's sid to the openreq sid. + * @inet_sys_snd_skb: + * Check permissions on outgoing network packets. + * @skb is the packet to check + * @family is the packet's address family * * Security hooks for XFRM operations. * @@ -1416,6 +1420,7 @@ struct security_operations { void (*inet_csk_clone)(struct sock *newsk, const struct request_sock *req); void (*inet_conn_established)(struct sock *sk, struct sk_buff *skb); void (*req_classify_flow)(const struct request_sock *req, struct flowi *fl); + int (*inet_sys_snd_skb)(struct sk_buff *skb, int family); #endif /* CONFIG_SECURITY_NETWORK */ #ifdef CONFIG_SECURITY_NETWORK_XFRM @@ -2328,6 +2333,7 @@ void security_sk_free(struct sock *sk); void security_sk_clone(const struct sock *sk, struct sock *newsk); void security_sk_classify_flow(struct sock *sk, struct flowi *fl); void security_req_classify_flow(const struct request_sock *req, struct flowi *fl); +int security_inet_sys_snd_skb(struct sk_buff *skb, int family); void security_sock_graft(struct sock*sk, struct socket *parent); int security_inet_conn_request(struct sock *sk, struct sk_buff *skb, struct request_sock *req); @@ -2471,6 +2477,11 @@ static inline void security_req_classify_flow(const struct request_sock *req, st { } +static inline int security_inet_sys_snd_skb(struct sk_buff *skb, int family) +{ + return 0; +} + static inline void security_sock_graft(struct sock* sk, struct socket *parent) { } diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index fd99fbd..82a7297 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c @@ -204,6 +204,8 @@ static inline int ip_skb_dst_mtu(struct sk_buff *skb) static int ip_finish_output(struct sk_buff *skb) { + int err; + #if defined(CONFIG_NETFILTER) && defined(CONFIG_XFRM) /* Policy lookup after SNAT yielded a new policy */ if (skb->dst->xfrm != NULL) { @@ -211,6 +213,11 @@ static int ip_finish_output(struct sk_buff *skb) return dst_output(skb); } #endif + + err = security_inet_sys_snd_skb(skb, AF_INET); + if (err) + return err; + if (skb->len > ip_skb_dst_mtu(skb) && !skb_is_gso(skb)) return ip_fragment(skb, ip_finish_output2); else diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 6338a9c..44ddf32 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c @@ -72,8 +72,13 @@ static __inline__ void ipv6_select_ident(struct sk_buff *skb, struct frag_hdr *f static int ip6_output_finish(struct sk_buff *skb) { + int err; struct dst_entry *dst = skb->dst; + err = security_inet_sys_snd_skb(skb, AF_INET6); + if (err) + return err; + if (dst->hh) return neigh_hh_output(dst->hh, skb); else if (dst->neighbour) diff --git a/security/dummy.c b/security/dummy.c index 0b62f95..384979a 100644 --- a/security/dummy.c +++ b/security/dummy.c @@ -848,6 +848,11 @@ static inline void dummy_req_classify_flow(const struct request_sock *req, struct flowi *fl) { } + +static inline int dummy_inet_sys_snd_skb(struct sk_buff *skb, int family) +{ + return 0; +} #endif /* CONFIG_SECURITY_NETWORK */ #ifdef CONFIG_SECURITY_NETWORK_XFRM @@ -1122,7 +1127,8 @@ void security_fixup_ops (struct security_operations *ops) set_to_dummy_if_null(ops, inet_csk_clone); set_to_dummy_if_null(ops, inet_conn_established); set_to_dummy_if_null(ops, req_classify_flow); - #endif /* CONFIG_SECURITY_NETWORK */ + set_to_dummy_if_null(ops, inet_sys_snd_skb); +#endif /* CONFIG_SECURITY_NETWORK */ #ifdef CONFIG_SECURITY_NETWORK_XFRM set_to_dummy_if_null(ops, xfrm_policy_alloc_security); set_to_dummy_if_null(ops, xfrm_policy_clone_security); diff --git a/security/security.c b/security/security.c index 3bdcada..7f55459 100644 --- a/security/security.c +++ b/security/security.c @@ -961,6 +961,12 @@ void security_req_classify_flow(const struct request_sock *req, struct flowi *fl } EXPORT_SYMBOL(security_req_classify_flow); +int security_inet_sys_snd_skb(struct sk_buff *skb, int family) +{ + return security_ops->inet_sys_snd_skb(skb, family); +} +EXPORT_SYMBOL(security_inet_sys_snd_skb); + void security_sock_graft(struct sock *sk, struct socket *parent) { security_ops->sock_graft(sk, parent); ^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH 1/2] LSM: Add inet_sys_snd_skb() LSM hook 2008-01-03 17:25 ` [PATCH 1/2] LSM: Add inet_sys_snd_skb() LSM hook Paul Moore @ 2008-01-04 4:45 ` David Miller 2008-01-04 14:38 ` Paul Moore 0 siblings, 1 reply; 9+ messages in thread From: David Miller @ 2008-01-04 4:45 UTC (permalink / raw) To: paul.moore; +Cc: netdev From: Paul Moore <paul.moore@hp.com> Date: Thu, 03 Jan 2008 12:25:39 -0500 > Add an inet_sys_snd_skb() LSM hook to allow the LSM to provide packet level > access control for all outbound packets. Using the existing postroute_last > netfilter hook turns out to be problematic as it is can be invoked multiple > times for a single packet, e.g. individual IPsec transforms, adding unwanted > overhead and complicating the security policy. > > Signed-off-by: Paul Moore <paul.moore@hp.com> I disagree with this change. The packet is different each time you see it in the postrouting hook, and also the new hook is thus redundant. If it's a performance issue and you can classify the security early, mark the SKB as "seen" and then on subsequent hooks you can just return immediately if that flag is set. ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 1/2] LSM: Add inet_sys_snd_skb() LSM hook 2008-01-04 4:45 ` David Miller @ 2008-01-04 14:38 ` Paul Moore 2008-01-04 21:09 ` David Miller 0 siblings, 1 reply; 9+ messages in thread From: Paul Moore @ 2008-01-04 14:38 UTC (permalink / raw) To: David Miller; +Cc: netdev On Thursday 03 January 2008 11:45:49 pm David Miller wrote: > From: Paul Moore <paul.moore@hp.com> > Date: Thu, 03 Jan 2008 12:25:39 -0500 > > > Add an inet_sys_snd_skb() LSM hook to allow the LSM to provide > > packet level access control for all outbound packets. Using the > > existing postroute_last netfilter hook turns out to be problematic > > as it is can be invoked multiple times for a single packet, e.g. > > individual IPsec transforms, adding unwanted overhead and > > complicating the security policy. > > > > Signed-off-by: Paul Moore <paul.moore@hp.com> > > I disagree with this change. > > The packet is different each time you see it in the postrouting hook, > and also the new hook is thus redundant. Well, thanks for taking a look. > If it's a performance issue and you can classify the security early, > mark the SKB as "seen" and then on subsequent hooks you can just > return immediately if that flag is set. Unfortunately, it's not quite that easy at present. The only field we have in the skb where we could possibly set a flag is the secmark field which is already taken. Granted, there is the possibility of segmenting the secmark field to some degree but that brings about a new set of problems involving the number of unique labels, backwards compatibility, etc. Regardless, back to the drawing board. I'll have to think a bit harder about a way to make the netfilter hooks work ... -- paul moore linux security @ hp ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 1/2] LSM: Add inet_sys_snd_skb() LSM hook 2008-01-04 14:38 ` Paul Moore @ 2008-01-04 21:09 ` David Miller 2008-01-04 22:37 ` Paul Moore 0 siblings, 1 reply; 9+ messages in thread From: David Miller @ 2008-01-04 21:09 UTC (permalink / raw) To: paul.moore; +Cc: netdev From: Paul Moore <paul.moore@hp.com> Date: Fri, 4 Jan 2008 09:38:27 -0500 > Unfortunately, it's not quite that easy at present. The only field we > have in the skb where we could possibly set a flag is the secmark field > which is already taken. Herbert Xu added a "peeked" field in net-2.6.25 that is only used on input while processing socket receive queues. You could use it on output. ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 1/2] LSM: Add inet_sys_snd_skb() LSM hook 2008-01-04 21:09 ` David Miller @ 2008-01-04 22:37 ` Paul Moore 0 siblings, 0 replies; 9+ messages in thread From: Paul Moore @ 2008-01-04 22:37 UTC (permalink / raw) To: David Miller; +Cc: netdev On Friday 04 January 2008 4:09:02 pm David Miller wrote: > From: Paul Moore <paul.moore@hp.com> > Date: Fri, 4 Jan 2008 09:38:27 -0500 > > > Unfortunately, it's not quite that easy at present. The only field > > we have in the skb where we could possibly set a flag is the > > secmark field which is already taken. > > Herbert Xu added a "peeked" field in net-2.6.25 that is only used on > input while processing socket receive queues. You could use it on > output. Actually, I went back to the drawing board and I think I found a solution that _should_ work using the existing postroute hook. It isn't as general but it is relatively simple. Historically the problem has been with labeled IPsec and the fact that the postroute hook can get hit multiple times when it is in use. While yes, the packet is different each time through the hook but the packet's security label never changes (the packet's security label is determined by the original sender). From a security point of view we really only want to check the packet once on the way out and we want that check to happen at the very end, not while packet transforms are in progress. This was the motivation for the new LSM hook. After the new hook was rejected I took a step back and thought about the problem a bit more. The multi-hit postroute hook problem was really only an issue for IPsec; the other labeling protocols don't have this problem because they don't do any transformation of the packet. If we could find a quick way to determine when all of the IPsec processing was finished would could use the existing postroute hook approach and simply fall through if the hook was hit when IPsec processing was still needed. I still need to test this to make sure it does everything we need, but I'm pretty certain that using the we can key off the skb->dst->xfrm value as a way to determine if a packet is done with it's IPsec transformation, if any. Basically we rewrite our postroute hook to look something like this: int hook(...) { /* stuff to do every time */ if (skb->dst->xfrm != NULL) return NF_ACCEPT; /* stuff to do only on the last time we are called */ } If it doesn't end up meeting our needs I'll look into the 'peeked' field, thanks for the suggestion. -- paul moore linux security @ hp ^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 2/2] NET: Clone the sk_buff 'iif' field in __skb_clone() 2008-01-03 17:25 [PATCH 0/2] Labeled networking core stack changes for 2.6.25 Paul Moore 2008-01-03 17:25 ` [PATCH 1/2] LSM: Add inet_sys_snd_skb() LSM hook Paul Moore @ 2008-01-03 17:25 ` Paul Moore 2008-01-03 18:33 ` Joe Perches 1 sibling, 1 reply; 9+ messages in thread From: Paul Moore @ 2008-01-03 17:25 UTC (permalink / raw) To: netdev; +Cc: davem Both NetLabel and SELinux (other LSMs may grow to use it as well) rely on the 'iif' field to determine the receiving network interface of inbound packets. Unfortunately, at present this field is not preserved across a skb clone operation which can lead to garbage values if the cloned skb is sent back through the network stack. This patch corrects this problem by properly copying the 'iif' field in __skb_clone() and removing the 'iif' field assignment from skb_act_clone() since it is no longer needed. Also, while we are here, get rid of that silly C() macro. Signed-off-by: Paul Moore <paul.moore@hp.com> --- include/net/sch_generic.h | 1 - net/core/skbuff.c | 20 +++++++++----------- 2 files changed, 9 insertions(+), 12 deletions(-) diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h index c926551..4c3b351 100644 --- a/include/net/sch_generic.h +++ b/include/net/sch_generic.h @@ -325,7 +325,6 @@ static inline struct sk_buff *skb_act_clone(struct sk_buff *skb, gfp_t gfp_mask) n->tc_verd = SET_TC_VERD(n->tc_verd, 0); n->tc_verd = CLR_TC_OK2MUNGE(n->tc_verd); n->tc_verd = CLR_TC_MUNGED(n->tc_verd); - n->iif = skb->iif; } return n; } diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 5b4ce9b..c726cd4 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -407,31 +407,29 @@ static void __copy_skb_header(struct sk_buff *new, const struct sk_buff *old) static struct sk_buff *__skb_clone(struct sk_buff *n, struct sk_buff *skb) { -#define C(x) n->x = skb->x - n->next = n->prev = NULL; n->sk = NULL; __copy_skb_header(n, skb); - C(len); - C(data_len); - C(mac_len); + n->iif = skb->iif; + n->len = skb->len; + n->data_len = skb->data_len; + n->mac_len = skb->mac_len; n->cloned = 1; n->hdr_len = skb->nohdr ? skb_headroom(skb) : skb->hdr_len; n->nohdr = 0; n->destructor = NULL; - C(truesize); + n->truesize = skb->truesize; atomic_set(&n->users, 1); - C(head); - C(data); - C(tail); - C(end); + n->head = skb->head; + n->data = skb->data; + n->tail = skb->tail; + n->end = skb->end; atomic_inc(&(skb_shinfo(skb)->dataref)); skb->cloned = 1; return n; -#undef C } /** ^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH 2/2] NET: Clone the sk_buff 'iif' field in __skb_clone() 2008-01-03 17:25 ` [PATCH 2/2] NET: Clone the sk_buff 'iif' field in __skb_clone() Paul Moore @ 2008-01-03 18:33 ` Joe Perches 2008-01-03 18:40 ` Paul Moore 0 siblings, 1 reply; 9+ messages in thread From: Joe Perches @ 2008-01-03 18:33 UTC (permalink / raw) To: Paul Moore; +Cc: netdev, David Miller On Thu, 2008-01-03 at 12:25 -0500, Paul Moore wrote: > diff --git a/net/core/skbuff.c b/net/core/skbuff.c > index 5b4ce9b..c726cd4 100644 > --- a/net/core/skbuff.c > +++ b/net/core/skbuff.c > @@ -407,31 +407,29 @@ static void __copy_skb_header(struct sk_buff *new, const struct sk_buff *old) > > static struct sk_buff *__skb_clone(struct sk_buff *n, struct sk_buff *skb) > { > -#define C(x) n->x = skb->x > - > n->next = n->prev = NULL; > n->sk = NULL; > __copy_skb_header(n, skb); > > - C(len); > - C(data_len); > - C(mac_len); > + n->iif = skb->iif; > + n->len = skb->len; > + n->data_len = skb->data_len; > + n->mac_len = skb->mac_len; > n->cloned = 1; > n->hdr_len = skb->nohdr ? skb_headroom(skb) : skb->hdr_len; > n->nohdr = 0; To reduce possible cacheline bounces, shouldn't the order of operation on the elements be in struct order? iif should be after destructor. nohdr then hdr_len > n->destructor = NULL; > - C(truesize); > + n->truesize = skb->truesize; > atomic_set(&n->users, 1); > - C(head); > - C(data); > - C(tail); > - C(end); > + n->head = skb->head; > + n->data = skb->data; > + n->tail = skb->tail; > + n->end = skb->end; and perhaps tail,end,head,data,truesize,users? ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 2/2] NET: Clone the sk_buff 'iif' field in __skb_clone() 2008-01-03 18:33 ` Joe Perches @ 2008-01-03 18:40 ` Paul Moore 0 siblings, 0 replies; 9+ messages in thread From: Paul Moore @ 2008-01-03 18:40 UTC (permalink / raw) To: Joe Perches; +Cc: netdev, David Miller On Thursday 03 January 2008 1:33:05 pm Joe Perches wrote: > On Thu, 2008-01-03 at 12:25 -0500, Paul Moore wrote: > > diff --git a/net/core/skbuff.c b/net/core/skbuff.c > > index 5b4ce9b..c726cd4 100644 > > --- a/net/core/skbuff.c > > +++ b/net/core/skbuff.c > > @@ -407,31 +407,29 @@ static void __copy_skb_header(struct sk_buff > > *new, const struct sk_buff *old) > > > > static struct sk_buff *__skb_clone(struct sk_buff *n, struct > > sk_buff *skb) { > > -#define C(x) n->x = skb->x > > - > > n->next = n->prev = NULL; > > n->sk = NULL; > > __copy_skb_header(n, skb); > > > > - C(len); > > - C(data_len); > > - C(mac_len); > > + n->iif = skb->iif; > > + n->len = skb->len; > > + n->data_len = skb->data_len; > > + n->mac_len = skb->mac_len; > > n->cloned = 1; > > n->hdr_len = skb->nohdr ? skb_headroom(skb) : skb->hdr_len; > > n->nohdr = 0; > > To reduce possible cacheline bounces, shouldn't the order of > operation on the elements be in struct order? Sounds reasonable to me, I'll adjust the function to match the field offsets. -- paul moore linux security @ hp ^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2008-01-04 22:37 UTC | newest] Thread overview: 9+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2008-01-03 17:25 [PATCH 0/2] Labeled networking core stack changes for 2.6.25 Paul Moore 2008-01-03 17:25 ` [PATCH 1/2] LSM: Add inet_sys_snd_skb() LSM hook Paul Moore 2008-01-04 4:45 ` David Miller 2008-01-04 14:38 ` Paul Moore 2008-01-04 21:09 ` David Miller 2008-01-04 22:37 ` Paul Moore 2008-01-03 17:25 ` [PATCH 2/2] NET: Clone the sk_buff 'iif' field in __skb_clone() Paul Moore 2008-01-03 18:33 ` Joe Perches 2008-01-03 18:40 ` Paul Moore
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).