* [PATCH 1/2] netfilter_queue: enable UID/GID socket info retrieval
2013-12-18 18:04 [PATCH 0/2] Add UID/GID info to NFQUEUE valentina.giusti
@ 2013-12-18 18:04 ` valentina.giusti
2013-12-18 21:24 ` Florian Westphal
2013-12-18 18:04 ` [PATCH 2/2] libnetfilter_queue: add support for UID/GID socket info valentina.giusti
2013-12-30 22:39 ` [PATCH 0/2] Add UID/GID info to NFQUEUE JP Abgrall
2 siblings, 1 reply; 6+ messages in thread
From: valentina.giusti @ 2013-12-18 18:04 UTC (permalink / raw)
To: netfilter-devel
Cc: netdev, eric.dumazet, tgraf, jpa, pablo, davem, daniel.wagner,
Valentina Giusti
From: Valentina Giusti <valentina.giusti@bmw-carit.de>
Thanks to commits 41063e9 (ipv4: Early TCP socket demux) and 421b388 (udp:
ipv4: Add udp early demux) it is now possible to get UID and GID socket info
also for incoming TCP and UDP connections. Having this info available, it
is convenient to let NFQUEUE retrieve it in order to improve and refine the
traffic analysis in userspace.
Signed-off-by: Valentina Giusti <valentina.giusti@bmw-carit.de>
---
include/uapi/linux/netfilter/nfnetlink_queue.h | 2 ++
net/netfilter/nfnetlink_queue_core.c | 23 ++++++++++++++++++++++-
2 files changed, 24 insertions(+), 1 deletion(-)
diff --git a/include/uapi/linux/netfilter/nfnetlink_queue.h b/include/uapi/linux/netfilter/nfnetlink_queue.h
index 0132bad..46ebbc4 100644
--- a/include/uapi/linux/netfilter/nfnetlink_queue.h
+++ b/include/uapi/linux/netfilter/nfnetlink_queue.h
@@ -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
};
diff --git a/net/netfilter/nfnetlink_queue_core.c b/net/netfilter/nfnetlink_queue_core.c
index 21258cf..7257ddb 100644
--- a/net/netfilter/nfnetlink_queue_core.c
+++ b/net/netfilter/nfnetlink_queue_core.c
@@ -328,7 +328,9 @@ nfqnl_build_packet_message(struct net *net, struct nfqnl_instance *queue,
+ nla_total_size(sizeof(u_int32_t)) /* mark */
+ nla_total_size(sizeof(struct nfqnl_msg_packet_hw))
+ nla_total_size(sizeof(u_int32_t)) /* skbinfo */
- + nla_total_size(sizeof(u_int32_t)); /* cap_len */
+ + nla_total_size(sizeof(u_int32_t)) /* cap_len */
+ + nla_total_size(sizeof(u_int32_t)) /* uid */
+ + nla_total_size(sizeof(u_int32_t)); /* gid */
if (entskb->tstamp.tv64)
size += nla_total_size(sizeof(struct nfqnl_msg_packet_timestamp));
@@ -484,6 +486,25 @@ nfqnl_build_packet_message(struct net *net, struct nfqnl_instance *queue,
goto nla_put_failure;
}
+ if (entskb->sk) {
+ struct sock *sk = entskb->sk;
+ if (sk && sk->sk_state != TCP_TIME_WAIT) {
+ read_lock_bh(&sk->sk_callback_lock);
+ if (sk->sk_socket && sk->sk_socket->file) {
+ struct file *file = sk->sk_socket->file;
+ const struct cred *cred = file->f_cred;
+ if (nla_put_u32(skb, NFQA_UID,
+ htonl(cred->fsuid)))
+ goto nla_put_failure;
+ if (nla_put_u32(skb, NFQA_GID,
+ htonl(cred->fsgid)))
+ goto nla_put_failure;
+ read_unlock_bh(&sk->sk_callback_lock);
+ } else
+ read_unlock_bh(&sk->sk_callback_lock);
+ }
+ }
+
if (ct && nfqnl_ct_put(skb, ct, ctinfo) < 0)
goto nla_put_failure;
--
1.7.10.4
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH 2/2] libnetfilter_queue: add support for UID/GID socket info
2013-12-18 18:04 [PATCH 0/2] Add UID/GID info to NFQUEUE valentina.giusti
2013-12-18 18:04 ` [PATCH 1/2] netfilter_queue: enable UID/GID socket info retrieval valentina.giusti
@ 2013-12-18 18:04 ` valentina.giusti
2013-12-30 22:39 ` [PATCH 0/2] Add UID/GID info to NFQUEUE JP Abgrall
2 siblings, 0 replies; 6+ messages in thread
From: valentina.giusti @ 2013-12-18 18:04 UTC (permalink / raw)
To: netfilter-devel
Cc: netdev, eric.dumazet, tgraf, jpa, pablo, davem, daniel.wagner,
Valentina Giusti
From: Valentina Giusti <Valentina.Giusti@bmw-carit.de>
With this patch libnetfilter_queue is able to parse the UID/GID socket
information from nfnetlink_queue.
Signed-off-by: Valentina Giusti <Valentina.Giusti@bmw-carit.de>
---
include/libnetfilter_queue/libnetfilter_queue.h | 4 ++++
include/libnetfilter_queue/linux_nfnetlink_queue.h | 2 ++
include/linux/netfilter/nfnetlink_queue.h | 3 +++
src/libnetfilter_queue.c | 25 ++++++++++++++++++++++
src/nlmsg.c | 2 ++
5 files changed, 36 insertions(+)
diff --git a/include/libnetfilter_queue/libnetfilter_queue.h b/include/libnetfilter_queue/libnetfilter_queue.h
index b9f16e2..b4e2679 100644
--- a/include/libnetfilter_queue/libnetfilter_queue.h
+++ b/include/libnetfilter_queue/libnetfilter_queue.h
@@ -103,6 +103,8 @@ extern u_int32_t nfq_get_indev(struct nfq_data *nfad);
extern u_int32_t nfq_get_physindev(struct nfq_data *nfad);
extern u_int32_t nfq_get_outdev(struct nfq_data *nfad);
extern u_int32_t nfq_get_physoutdev(struct nfq_data *nfad);
+extern u_int32_t nfq_get_uid(struct nfq_data *nfad);
+extern u_int32_t nfq_get_gid(struct nfq_data *nfad);
extern int nfq_get_indev_name(struct nlif_handle *nlif_handle,
struct nfq_data *nfad, char *name);
@@ -125,6 +127,8 @@ enum {
NFQ_XML_PHYSDEV = (1 << 3),
NFQ_XML_PAYLOAD = (1 << 4),
NFQ_XML_TIME = (1 << 5),
+ NFQ_XML_UID = (1 << 6),
+ NFQ_XML_GID = (1 << 7),
NFQ_XML_ALL = ~0U,
};
diff --git a/include/libnetfilter_queue/linux_nfnetlink_queue.h b/include/libnetfilter_queue/linux_nfnetlink_queue.h
index 81a485b..88fd0c0 100644
--- a/include/libnetfilter_queue/linux_nfnetlink_queue.h
+++ b/include/libnetfilter_queue/linux_nfnetlink_queue.h
@@ -50,6 +50,8 @@ enum nfqnl_attr_type {
NFQA_CAP_LEN, /* __u32 length of captured packet */
NFQA_SKB_INFO, /* __u32 skb meta information */
+ NFQA_UID, /* __u32 sk uid */
+ NFQA_GID, /* __u32 sk gid */
__NFQA_MAX
};
#define NFQA_MAX (__NFQA_MAX - 1)
diff --git a/include/linux/netfilter/nfnetlink_queue.h b/include/linux/netfilter/nfnetlink_queue.h
index a2308ae..dfbd1ad 100644
--- a/include/linux/netfilter/nfnetlink_queue.h
+++ b/include/linux/netfilter/nfnetlink_queue.h
@@ -46,6 +46,9 @@ enum nfqnl_attr_type {
NFQA_CT_INFO, /* enum ip_conntrack_info */
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
};
diff --git a/src/libnetfilter_queue.c b/src/libnetfilter_queue.c
index fa8efe7..52456db 100644
--- a/src/libnetfilter_queue.c
+++ b/src/libnetfilter_queue.c
@@ -1180,6 +1180,18 @@ struct nfqnl_msg_packet_hw *nfq_get_packet_hw(struct nfq_data *nfad)
}
EXPORT_SYMBOL(nfq_get_packet_hw);
+uint32_t nfq_get_uid(struct nfq_data *nfad)
+{
+ return ntohl(nfnl_get_data(nfad->data, NFQA_UID, u_int32_t));
+}
+EXPORT_SYMBOL(nfq_get_uid);
+
+uint32_t nfq_get_gid(struct nfq_data *nfad)
+{
+ return ntohl(nfnl_get_data(nfad->data, NFQA_GID, u_int32_t));
+}
+EXPORT_SYMBOL(nfq_get_gid);
+
/**
* nfq_get_payload - get payload
* \param nfad Netlink packet data handle passed to callback function
@@ -1250,6 +1262,7 @@ int nfq_snprintf_xml(char *buf, size_t rem, struct nfq_data *tb, int flags)
struct nfqnl_msg_packet_hdr *ph;
struct nfqnl_msg_packet_hw *hwph;
u_int32_t mark, ifi;
+ u_int32_t uid, gid;
int size, offset = 0, len = 0, ret;
unsigned char *data;
@@ -1365,6 +1378,18 @@ int nfq_snprintf_xml(char *buf, size_t rem, struct nfq_data *tb, int flags)
SNPRINTF_FAILURE(size, rem, offset, len);
}
+ uid = nfq_get_uid(tb);
+ if (uid && (flags & NFQ_XML_UID)) {
+ size = snprintf(buf + offset, rem, "<uid>%u</uid>", uid);
+ SNPRINTF_FAILURE(size, rem, offset, len);
+ }
+
+ gid = nfq_get_gid(tb);
+ if (gid && (flags & NFQ_XML_GID)) {
+ size = snprintf(buf + offset, rem, "<gid>%u</gid>", gid);
+ SNPRINTF_FAILURE(size, rem, offset, len);
+ }
+
ret = nfq_get_payload(tb, &data);
if (ret >= 0 && (flags & NFQ_XML_PAYLOAD)) {
int i;
diff --git a/src/nlmsg.c b/src/nlmsg.c
index e7a30e0..81e170e 100644
--- a/src/nlmsg.c
+++ b/src/nlmsg.c
@@ -134,6 +134,8 @@ static int nfq_pkt_parse_attr_cb(const struct nlattr *attr, void *data)
case NFQA_IFINDEX_PHYSOUTDEV:
case NFQA_CAP_LEN:
case NFQA_SKB_INFO:
+ case NFQA_UID:
+ case NFQA_GID:
if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0)
return MNL_CB_ERROR;
break;
--
1.8.5.1
^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH 0/2] Add UID/GID info to NFQUEUE
2013-12-18 18:04 [PATCH 0/2] Add UID/GID info to NFQUEUE valentina.giusti
2013-12-18 18:04 ` [PATCH 1/2] netfilter_queue: enable UID/GID socket info retrieval valentina.giusti
2013-12-18 18:04 ` [PATCH 2/2] libnetfilter_queue: add support for UID/GID socket info valentina.giusti
@ 2013-12-30 22:39 ` JP Abgrall
2 siblings, 0 replies; 6+ messages in thread
From: JP Abgrall @ 2013-12-30 22:39 UTC (permalink / raw)
To: valentina.giusti
Cc: netfilter-devel, netdev, eric.dumazet, tgraf, Pablo Neira Ayuso,
davem, daniel.wagner
On Wed, Dec 18, 2013 at 10:04 AM, <valentina.giusti@bmw-carit.de> wrote:
> At the Linux Plumbers Conference 2013, there have been quite interesting
> discussions on the topic of network statistics, and it was proposed that it
> would make more sense to use NFQUEUE for this purpose, letting therefore
> userspace use the UID/GID information for application-based statistics purposes.
> This way the UID and GID information of the incoming TCP and UDP traffic is not
> "wasted" and can be used for more refined statistics.
Some things to keep in mind when doing these changes...
For mobile devices, having the UID/GID is not sufficient when services
are involved (download manager, http service, ...).
Currently, Android's xt_qtaguid netfilter module supports the notion
of "delegation" which is achieved by having the service "tag" a socket
(tracked internally based on the struct sock address), via the file
descriptor, with a UID of who should be blamed for the statistics.
It would be nice if NFQUEUE presented/tracked some data related to the
socket that could be used to that effect.
This tagging of the socket needs to have the following properties:
- a socket can stay open and be re-tagged (happens when pools are
used or when a stream can be used for multiple reasons).
- a socket can be tagged with a different UID only if the current
UID/GID/pcap allows for it.
- an app can have multiple sockets, each one belonging to different
UIDs (so no UID to UID mapping).
There are a few more, but those can be managed outside of the NFQUEUE changes.
Concerning the comment about TCP_TIMEWAIT in some other thread: the sk
is not a "struct sock" but "struct inet_timewait_sock" which is
missing fields. So beware when manipulating it. xt_qtaguid had to
ignore those struct sock.
^ permalink raw reply [flat|nested] 6+ messages in thread