diff options
author | JP Abgrall <jpa@google.com> | 2011-10-09 02:27:24 +0100 |
---|---|---|
committer | Andy Green <andy.green@linaro.org> | 2011-10-09 02:27:24 +0100 |
commit | e280fa256d383b76fc6f69784bb8e764d9350c5a (patch) | |
tree | ef5e89288f01a61acb738d876f3f1bb85c62aea1 /net | |
parent | c2f3f05bbf5daa2a9ffb27c0fe79c90f77936594 (diff) |
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 <jpa@google.com>
Change-Id: Id2a9912bb451a3e59d012fc55bbbd40fbb90693f
Diffstat (limited to 'net')
-rw-r--r-- | net/netfilter/xt_qtaguid.c | 45 |
1 files changed, 36 insertions, 9 deletions
diff --git a/net/netfilter/xt_qtaguid.c b/net/netfilter/xt_qtaguid.c index a764552cc38..320ad84890e 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 <linux/file.h> #include <linux/inetdevice.h> @@ -22,6 +22,10 @@ #include <net/udp.h> #include <linux/netfilter/xt_socket.h> +/* 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; |