]> Pileus Git - ~andy/linux/blobdiff - net/netfilter/nfnetlink_queue_core.c
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/jesse/openvswitch
[~andy/linux] / net / netfilter / nfnetlink_queue_core.c
index 615ee12647ae95b56997e69597a7881c740b2944..f072fe803510320f7210c31b1a08ccddea5ae5b6 100644 (file)
@@ -29,6 +29,7 @@
 #include <linux/netfilter/nfnetlink_queue.h>
 #include <linux/list.h>
 #include <net/sock.h>
+#include <net/tcp_states.h>
 #include <net/netfilter/nf_queue.h>
 #include <net/netns/generic.h>
 #include <net/netfilter/nfnetlink_queue.h>
@@ -252,6 +253,31 @@ nfqnl_put_packet_info(struct sk_buff *nlskb, struct sk_buff *packet,
        return flags ? nla_put_be32(nlskb, NFQA_SKB_INFO, htonl(flags)) : 0;
 }
 
+static int nfqnl_put_sk_uidgid(struct sk_buff *skb, struct sock *sk)
+{
+       const struct cred *cred;
+
+       if (sk->sk_state == TCP_TIME_WAIT)
+               return 0;
+
+       read_lock_bh(&sk->sk_callback_lock);
+       if (sk->sk_socket && sk->sk_socket->file) {
+               cred = sk->sk_socket->file->f_cred;
+               if (nla_put_be32(skb, NFQA_UID,
+                   htonl(from_kuid_munged(&init_user_ns, cred->fsuid))))
+                       goto nla_put_failure;
+               if (nla_put_be32(skb, NFQA_GID,
+                   htonl(from_kgid_munged(&init_user_ns, cred->fsgid))))
+                       goto nla_put_failure;
+       }
+       read_unlock_bh(&sk->sk_callback_lock);
+       return 0;
+
+nla_put_failure:
+       read_unlock_bh(&sk->sk_callback_lock);
+       return -1;
+}
+
 static struct sk_buff *
 nfqnl_build_packet_message(struct net *net, struct nfqnl_instance *queue,
                           struct nf_queue_entry *entry,
@@ -321,6 +347,11 @@ nfqnl_build_packet_message(struct net *net, struct nfqnl_instance *queue,
        if (queue->flags & NFQA_CFG_F_CONNTRACK)
                ct = nfqnl_ct_get(entskb, &size, &ctinfo);
 
+       if (queue->flags & NFQA_CFG_F_UID_GID) {
+               size +=  (nla_total_size(sizeof(u_int32_t))     /* uid */
+                       + nla_total_size(sizeof(u_int32_t)));   /* gid */
+       }
+
        skb = nfnetlink_alloc_skb(net, size, queue->peer_portid,
                                  GFP_ATOMIC);
        if (!skb)
@@ -433,6 +464,10 @@ nfqnl_build_packet_message(struct net *net, struct nfqnl_instance *queue,
                        goto nla_put_failure;
        }
 
+       if ((queue->flags & NFQA_CFG_F_UID_GID) && entskb->sk &&
+           nfqnl_put_sk_uidgid(skb, entskb->sk) < 0)
+               goto nla_put_failure;
+
        if (ct && nfqnl_ct_put(skb, ct, ctinfo) < 0)
                goto nla_put_failure;