summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJP Abgrall <jpa@google.com>2011-06-27 21:03:04 -0700
committerDan Willemsen <dwillemsen@nvidia.com>2011-11-30 21:38:43 -0800
commit70c55b8b4faf751a63eaf57fc6eff9ac196bcedd (patch)
tree714ff1b0ba54a9d863561bb78c1d53035262f312
parent370a7730afe97223c49ed22fb1bd3acc9847a58f (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
-rw-r--r--net/netfilter/xt_qtaguid.c45
1 files changed, 36 insertions, 9 deletions
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 <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;