netfilter: nfnetlink_queue: enable UID/GID socket info retrieval 14/68314/2
authorValentina Giusti <valentina.giusti@bmw-carit.de>
Tue, 12 Apr 2016 05:13:52 +0000 (14:13 +0900)
committerSeung-Woo Kim <sw0312.kim@samsung.com>
Thu, 25 Aug 2016 05:01:45 +0000 (22:01 -0700)
Thanks to commits 41063e9 (ipv4: Early TCP socket demux) and 421b388
(udp: ipv4: Add udp early demux) it is now possible to parse UID and
GID socket info also for incoming TCP and UDP connections. Having
this info available, it is convenient to let NFQUEUE parse it in
order to improve and refine the traffic analysis in userspace.

Change-Id: Ie38c073a3543534497ef0cc6080642c808690b85
Signed-off-by: Valentina Giusti <valentina.giusti@bmw-carit.de>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Signed-off-by: jooseong lee <jooseong.lee@samsung.com>
include/uapi/linux/netfilter/nfnetlink_queue.h
net/netfilter/nfnetlink_queue_core.c

index 0ee94e6..22f5d45 100644 (file)
@@ -47,6 +47,8 @@ enum nfqnl_attr_type {
        NFQA_CAP_LEN,                   /* __u32 length of captured packet */
        NFQA_SKB_INFO,                  /* __u32 skb meta information */
        NFQA_EXP,                       /* nf_conntrack_netlink.h */
+       NFQA_UID,                       /* __u32 sk uid */
+       NFQA_GID,                       /* __u32 sk gid */
 
        __NFQA_MAX
 };
@@ -99,7 +101,8 @@ enum nfqnl_attr_config {
 #define NFQA_CFG_F_FAIL_OPEN                   (1 << 0)
 #define NFQA_CFG_F_CONNTRACK                   (1 << 1)
 #define NFQA_CFG_F_GSO                         (1 << 2)
-#define NFQA_CFG_F_MAX                         (1 << 3)
+#define NFQA_CFG_F_UID_GID                     (1 << 3)
+#define NFQA_CFG_F_MAX                         (1 << 4)
 
 /* flags for NFQA_SKB_INFO */
 /* packet appears to have wrong checksums, but they are ok */
index f5c4a08..1d81b40 100644 (file)
@@ -292,6 +292,31 @@ static int 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 nfqnl_instance *queue,
                           struct nf_queue_entry *entry,
@@ -361,6 +386,11 @@ nfqnl_build_packet_message(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(&init_net, size, queue->peer_portid,
                                  GFP_ATOMIC);
        if (!skb) {
@@ -473,6 +503,10 @@ nfqnl_build_packet_message(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;