From 70c55b8b4faf751a63eaf57fc6eff9ac196bcedd Mon Sep 17 00:00:00 2001 From: JP Abgrall Date: Mon, 27 Jun 2011 21:03:04 -0700 Subject: nf: qtaguid: workaround xt_socket_get_sk() returning bad SKs. (This is a direct cherry pick from 2.6.39: Id2a9912b) * xt_socket_get_sk() returns invalid sockets when the sk_state is TCP_TIME_WAIT. Added detection of time-wait. * Added more constrained usage: qtaguid insures that xt_socket_get*_sk() is not invoked for unexpected hooks or protocols (but I have not seen those active at the point where the returned sk is bad). Signed-off-by: JP Abgrall Change-Id: Id2a9912bb451a3e59d012fc55bbbd40fbb90693f --- net/netfilter/xt_qtaguid.c | 45 ++++++++++++++++++++++++++++++++++++--------- 1 file changed, 36 insertions(+), 9 deletions(-) (limited to 'net/netfilter') diff --git a/net/netfilter/xt_qtaguid.c b/net/netfilter/xt_qtaguid.c index a764552cc387..320ad84890e8 100644 --- a/net/netfilter/xt_qtaguid.c +++ b/net/netfilter/xt_qtaguid.c @@ -8,7 +8,7 @@ * published by the Free Software Foundation. */ -/* TODO: support ipv6 */ +/* TODO: support ipv6 for iface_stat */ #include #include @@ -22,6 +22,10 @@ #include #include +/* We only use the xt_socket funcs within a similar context to avoid unexpected + * return values. */ +#define XT_SOCKET_SUPPORTED_HOOKS \ + ((1 << NF_INET_PRE_ROUTING) | (1 << NF_INET_LOCAL_IN)) /*---------------------------------------------------------------------------*/ @@ -725,16 +729,39 @@ static struct sock *qtaguid_find_sk(const struct sk_buff *skb, struct xt_action_param *par) { struct sock *sk; + unsigned int hook_mask = (1 << par->hooknum); - sk = xt_socket_get4_sk(skb, par); - /* TODO: is this fixed? - * Seems to be issues on the file ptr for TCP+TIME_WAIT SKs. + pr_debug("xt_qtaguid: find_sk(skb=%p) hooknum=%d family=%d\n", skb, + par->hooknum, par->family); + + /* Let's not abuse the the xt_socket_get*_sk(), or else it will + * return garbage SKs. */ + if (!(hook_mask & XT_SOCKET_SUPPORTED_HOOKS)) + return NULL; + + switch (par->family) { + case NFPROTO_IPV6: + sk = xt_socket_get6_sk(skb, par); + break; + case NFPROTO_IPV4: + sk = xt_socket_get4_sk(skb, par); + break; + default: + return NULL; + } + + /* Seems to be issues on the file ptr for TCP_TIME_WAIT SKs. * http://kerneltrap.org/mailarchive/linux-netdev/2010/10/21/6287959 + * Not fixed in 3.0-r3 :( */ - if (sk) + if (sk) { pr_debug("xt_qtaguid: %p->sk_proto=%u " - "->sk_state=%d\n", sk, sk->sk_protocol, - sk->sk_state); + "->sk_state=%d\n", sk, sk->sk_protocol, sk->sk_state); + if (sk->sk_state == TCP_TIME_WAIT) { + xt_socket_put_sk(sk); + sk = NULL; + } + } return sk; } @@ -784,8 +811,8 @@ static bool qtaguid_mt(const struct sk_buff *skb, struct xt_action_param *par) struct sock *sk; uid_t sock_uid; bool res; - pr_debug("xt_qtaguid[%d]: entered skb=%p par->in=%p/out=%p\n", - par->hooknum, skb, par->in, par->out); + pr_debug("xt_qtaguid[%d]: entered skb=%p par->in=%p/out=%p fam=%d\n", + par->hooknum, skb, par->in, par->out, par->family); if (skb == NULL) { res = (info->match ^ info->invert) == 0; goto ret_res; -- cgit v1.2.3