diff mbox series

netfilter: Record uid and gid in xt_AUDIT

Message ID 20241009203218.26329-1-richard@nod.at (mailing list archive)
State Awaiting Upstream
Delegated to: Netdev Maintainers
Headers show
Series netfilter: Record uid and gid in xt_AUDIT | expand

Checks

Context Check Description
netdev/series_format warning Single patches do not need cover letters; Target tree name not specified in the subject
netdev/tree_selection success Guessed tree name to be net-next, async
netdev/ynl success Generated files up to date; no warnings/errors; no diff in generated;
netdev/fixes_present success Fixes tag not required for -next series
netdev/header_inline success No static functions without inline keyword in header files
netdev/build_32bit success Errors and warnings before: 6 this patch: 6
netdev/build_tools success No tools touched, skip
netdev/cc_maintainers success CCed 8 of 8 maintainers
netdev/build_clang success Errors and warnings before: 6 this patch: 6
netdev/verify_signedoff success Signed-off-by tag matches author and committer
netdev/deprecated_api success None detected
netdev/check_selftest success No net selftest shell script
netdev/verify_fixes success No Fixes tag
netdev/build_allmodconfig_warn success Errors and warnings before: 5 this patch: 5
netdev/checkpatch success total: 0 errors, 0 warnings, 0 checks, 54 lines checked
netdev/build_clang_rust success No Rust files in patch. Skipping build
netdev/kdoc success Errors and warnings before: 0 this patch: 0
netdev/source_inline success Was 0 now: 0
netdev/contest success net-next-2024-10-10--12-00 (tests: 775)

Commit Message

Richard Weinberger Oct. 9, 2024, 8:32 p.m. UTC
When recording audit events for new outgoing connections,
it is helpful to log the user info of the associated socket,
if available.
Therefore, check if the skb has a socket, and if it does,
log the owning fsuid/fsgid.

Signed-off-by: Richard Weinberger <richard@nod.at>
---
 net/netfilter/xt_AUDIT.c | 27 +++++++++++++++++++++++++--
 1 file changed, 25 insertions(+), 2 deletions(-)

Comments

Florian Westphal Oct. 9, 2024, 9:33 p.m. UTC | #1
Richard Weinberger <richard@nod.at> wrote:
> When recording audit events for new outgoing connections,
> it is helpful to log the user info of the associated socket,
> if available.
> Therefore, check if the skb has a socket, and if it does,
> log the owning fsuid/fsgid.

AFAIK audit isn't namespace aware at all (neither netns nor userns), so I
wonder how to handle this.

We can't reject adding a -j AUDIT rule for non-init-net (we could, but I'm sure
it'll break some setups...).

But I wonder if we should at least skip the uid if the user namespace is
'something else'.

> +	if (sk && sk_fullsock(sk)) {

I.e. check net->user_ns == &init_user_ns too and don't log the uid
otherwise.

I don't think auditd can make sense of the uid otherwise, resp.
its misleading, no?

Alternatively, use this instead?

kuid = sock_net_uid(sock_net(sk), sk);
from_kuid_munged(sock_net(sk)->user_ns, kuid);

There is no need to follow ->file backpointer anymore, see
6acc5c2910689fc6ee181bf63085c5efff6a42bd and
86741ec25462e4c8cdce6df2f41ead05568c7d5e,
"net: core: Add a UID field to struct sock.".

I think we could streamline all the existing paths that fetch uid
from sock->file to not do that and use sock_net_uid() instead as well.
Paul Moore Oct. 9, 2024, 9:46 p.m. UTC | #2
On Wed, Oct 9, 2024 at 5:34 PM Florian Westphal <fw@strlen.de> wrote:
> Richard Weinberger <richard@nod.at> wrote:
> > When recording audit events for new outgoing connections,
> > it is helpful to log the user info of the associated socket,
> > if available.
> > Therefore, check if the skb has a socket, and if it does,
> > log the owning fsuid/fsgid.
>
> AFAIK audit isn't namespace aware at all (neither netns nor userns), so I
> wonder how to handle this.
>
> We can't reject adding a -j AUDIT rule for non-init-net (we could, but I'm sure
> it'll break some setups...).
>
> But I wonder if we should at least skip the uid if the user namespace is
> 'something else'.

This isn't unique to netfilter and the approach we take in the rest of
audit is to always display UIDs/GIDs in the context of the
init_user_ns; grep for from_kuid() in kernel/audit*.c.
Paul Moore Oct. 9, 2024, 10:02 p.m. UTC | #3
On Wed, Oct 9, 2024 at 4:33 PM Richard Weinberger <richard@nod.at> wrote:
>
> When recording audit events for new outgoing connections,
> it is helpful to log the user info of the associated socket,
> if available.
> Therefore, check if the skb has a socket, and if it does,
> log the owning fsuid/fsgid.
>
> Signed-off-by: Richard Weinberger <richard@nod.at>
> ---
>  net/netfilter/xt_AUDIT.c | 27 +++++++++++++++++++++++++--
>  1 file changed, 25 insertions(+), 2 deletions(-)
>
> diff --git a/net/netfilter/xt_AUDIT.c b/net/netfilter/xt_AUDIT.c
> index b6a015aee0cec..d88b5442beaa6 100644
> --- a/net/netfilter/xt_AUDIT.c
> +++ b/net/netfilter/xt_AUDIT.c
> @@ -9,16 +9,19 @@
>  #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
>
>  #include <linux/audit.h>
> +#include <linux/cred.h>
> +#include <linux/file.h>
> +#include <linux/if_arp.h>
>  #include <linux/module.h>
>  #include <linux/skbuff.h>
>  #include <linux/tcp.h>
>  #include <linux/udp.h>
> -#include <linux/if_arp.h>
>  #include <linux/netfilter/x_tables.h>
>  #include <linux/netfilter/xt_AUDIT.h>
>  #include <linux/netfilter_bridge/ebtables.h>
> -#include <net/ipv6.h>
>  #include <net/ip.h>
> +#include <net/ipv6.h>
> +#include <net/sock.h>
>
>  MODULE_LICENSE("GPL");
>  MODULE_AUTHOR("Thomas Graf <tgraf@redhat.com>");
> @@ -66,7 +69,9 @@ static bool audit_ip6(struct audit_buffer *ab, struct sk_buff *skb)
>  static unsigned int
>  audit_tg(struct sk_buff *skb, const struct xt_action_param *par)
>  {
> +       struct sock *sk = skb->sk;
>         struct audit_buffer *ab;
> +       bool got_uidgid = false;
>         int fam = -1;
>
>         if (audit_enabled == AUDIT_OFF)
> @@ -99,6 +104,24 @@ audit_tg(struct sk_buff *skb, const struct xt_action_param *par)
>         if (fam == -1)
>                 audit_log_format(ab, " saddr=? daddr=? proto=-1");
>
> +       if (sk && sk_fullsock(sk)) {
> +               read_lock_bh(&sk->sk_callback_lock);
> +               if (sk->sk_socket && sk->sk_socket->file) {
> +                       const struct file *file = sk->sk_socket->file;
> +                       const struct cred *cred = file->f_cred;
> +
> +                       audit_log_format(ab, " uid=%u gid=%u",
> +                                        from_kuid(&init_user_ns, cred->fsuid),
> +                                        from_kgid(&init_user_ns, cred->fsgid));

[CC'ing the audit and LSM lists for obvious reasons]

If we're logging the subjective credentials of the skb's associated
socket, we really should also log the socket's LSM secctx similar to
what we do with audit_log_task() and audit_log_task_context().
Unfortunately, I don't believe we currently have a LSM interface that
return the secctx from a sock/socket, although we do have
security_inode_getsecctx() which *should* yield the same result using
SOCK_INODE(sk->sk_socket).

I should also mention that I'm currently reviewing a patchset which is
going to add proper support for multiple LSMs in audit which will
likely impact this work.

https://lore.kernel.org/linux-security-module/20241009173222.12219-1-casey@schaufler-ca.com/

> +                       got_uidgid = true;
> +               }
> +               read_unlock_bh(&sk->sk_callback_lock);
> +       }
> +
> +       if (!got_uidgid)
> +               audit_log_format(ab, " uid=? gid=?");
> +
>         audit_log_end(ab);
>
>  errout:
> --
> 2.35.3
Florian Westphal Oct. 9, 2024, 10:34 p.m. UTC | #4
Paul Moore <paul@paul-moore.com> wrote:
> On Wed, Oct 9, 2024 at 5:34 PM Florian Westphal <fw@strlen.de> wrote:
> > Richard Weinberger <richard@nod.at> wrote:
> > > When recording audit events for new outgoing connections,
> > > it is helpful to log the user info of the associated socket,
> > > if available.
> > > Therefore, check if the skb has a socket, and if it does,
> > > log the owning fsuid/fsgid.
> >
> > AFAIK audit isn't namespace aware at all (neither netns nor userns), so I
> > wonder how to handle this.
> >
> > We can't reject adding a -j AUDIT rule for non-init-net (we could, but I'm sure
> > it'll break some setups...).
> >
> > But I wonder if we should at least skip the uid if the user namespace is
> > 'something else'.
> 
> This isn't unique to netfilter and the approach we take in the rest of
> audit is to always display UIDs/GIDs in the context of the
> init_user_ns; grep for from_kuid() in kernel/audit*.c.

Hmm, audit_netlink_ok() bails with -ECONNREFUSED for current_user_ns()
!= &init_user_ns, so audit_log_common_recv_msg() won't be called from
tasks that reside in a different userns.

If you say its fine and audit can figure out that the retuned
uid is not related to the initial user namespace, then ok.

I was worried audit records could blame wrong/bogus user id.
Paul Moore Oct. 10, 2024, 2:02 a.m. UTC | #5
On Wed, Oct 9, 2024 at 6:34 PM Florian Westphal <fw@strlen.de> wrote:
> Paul Moore <paul@paul-moore.com> wrote:
> > On Wed, Oct 9, 2024 at 5:34 PM Florian Westphal <fw@strlen.de> wrote:
> > > Richard Weinberger <richard@nod.at> wrote:
> > > > When recording audit events for new outgoing connections,
> > > > it is helpful to log the user info of the associated socket,
> > > > if available.
> > > > Therefore, check if the skb has a socket, and if it does,
> > > > log the owning fsuid/fsgid.
> > >
> > > AFAIK audit isn't namespace aware at all (neither netns nor userns), so I
> > > wonder how to handle this.
> > >
> > > We can't reject adding a -j AUDIT rule for non-init-net (we could, but I'm sure
> > > it'll break some setups...).
> > >
> > > But I wonder if we should at least skip the uid if the user namespace is
> > > 'something else'.
> >
> > This isn't unique to netfilter and the approach we take in the rest of
> > audit is to always display UIDs/GIDs in the context of the
> > init_user_ns; grep for from_kuid() in kernel/audit*.c.
>
> Hmm, audit_netlink_ok() bails with -ECONNREFUSED for current_user_ns()
> != &init_user_ns, so audit_log_common_recv_msg() won't be called from
> tasks that reside in a different userns.

We have a requirement that the audit daemon and audit management tools
run in the initial user namespace, but these are the audit collection
and configuration mechanisms, not the audit record generation
mechanisms.  Regardless of the namespace limitations on auditd and
auditctl, we want to collect audit records across the system, which is
what we are doing in audit_tg().

> If you say its fine and audit can figure out that the retuned
> uid is not related to the initial user namespace, then ok.
>
> I was worried audit records could blame wrong/bogus user id.

Correct me if I'm wrong, but by using from_kXid(&init_user_ns, Xid) we
get the ID number that is correct for the init namespace, yes?  If so,
that's what we want as right now all of the audit records, filters,
etc. are intended to be set from the context of the initial namespace.
Richard Weinberger Oct. 10, 2024, 6:24 a.m. UTC | #6
Am Donnerstag, 10. Oktober 2024, 00:02:44 CEST schrieb Paul Moore:
> [CC'ing the audit and LSM lists for obvious reasons]
> 
> If we're logging the subjective credentials of the skb's associated
> socket, we really should also log the socket's LSM secctx similar to
> what we do with audit_log_task() and audit_log_task_context().
> Unfortunately, I don't believe we currently have a LSM interface that
> return the secctx from a sock/socket, although we do have
> security_inode_getsecctx() which *should* yield the same result using
> SOCK_INODE(sk->sk_socket).

Hm, I thought about that but saw 2173c519d5e91 ("audit: normalize NETFILTER_PKT").
It removed usage of audit_log_secctx() and many other, IMHO, useful fields.
What about skb->secctx?

> 
> I should also mention that I'm currently reviewing a patchset which is
> going to add proper support for multiple LSMs in audit which will
> likely impact this work.
> 
> https://lore.kernel.org/linux-security-module/20241009173222.12219-1-casey@schaufler-ca.com/

Ok!

Thanks,
//richard
Richard Weinberger Oct. 10, 2024, 6:27 a.m. UTC | #7
Am Mittwoch, 9. Oktober 2024, 23:33:45 CEST schrieb Florian Westphal:
> There is no need to follow ->file backpointer anymore, see
> 6acc5c2910689fc6ee181bf63085c5efff6a42bd and
> 86741ec25462e4c8cdce6df2f41ead05568c7d5e,
> "net: core: Add a UID field to struct sock.".

Oh, neat!
 
> I think we could streamline all the existing paths that fetch uid
> from sock->file to not do that and use sock_net_uid() instead as well.
 
Also xt_owner?

Thanks,
//richard
Florian Westphal Oct. 10, 2024, 1:48 p.m. UTC | #8
Richard Weinberger <richard@sigma-star.at> wrote:
> Am Mittwoch, 9. Oktober 2024, 23:33:45 CEST schrieb Florian Westphal:
> > There is no need to follow ->file backpointer anymore, see
> > 6acc5c2910689fc6ee181bf63085c5efff6a42bd and
> > 86741ec25462e4c8cdce6df2f41ead05568c7d5e,
> > "net: core: Add a UID field to struct sock.".
> 
> Oh, neat!
>  
> > I think we could streamline all the existing paths that fetch uid
> > from sock->file to not do that and use sock_net_uid() instead as well.
>  
> Also xt_owner?

sk->sk_uid is already used e.g. for fib lookups so I think it makes
sense to be consistent, so, yes, xt_owner, nfqueue, nft_meta.c, all can
be converted.
Jan Engelhardt Oct. 10, 2024, 1:53 p.m. UTC | #9
On Thursday 2024-10-10 15:48, Florian Westphal wrote:
>Richard Weinberger <richard@sigma-star.at> wrote:
>> Am Mittwoch, 9. Oktober 2024, 23:33:45 CEST schrieb Florian Westphal:
>> > There is no need to follow ->file backpointer anymore, see
>> > 6acc5c2910689fc6ee181bf63085c5efff6a42bd and
>> > 86741ec25462e4c8cdce6df2f41ead05568c7d5e,
>> > "net: core: Add a UID field to struct sock.".
>> 
>> Oh, neat!
>>  
>> > I think we could streamline all the existing paths that fetch uid
>> > from sock->file to not do that and use sock_net_uid() instead as well.
>>  
>> Also xt_owner?
>
>sk->sk_uid is already used e.g. for fib lookups so I think it makes
>sense to be consistent, so, yes, xt_owner, nfqueue, nft_meta.c, all can
>be converted.

I doubt it. We've been there before... if a process does setuid,
some uid field doesn't change, and others do, so that's user-visible
behavior you can't just change.
Florian Westphal Oct. 10, 2024, 5:59 p.m. UTC | #10
Paul Moore <paul@paul-moore.com> wrote:
> Correct me if I'm wrong, but by using from_kXid(&init_user_ns, Xid) we
> get the ID number that is correct for the init namespace, yes?  If so,
> that's what we want as right now all of the audit records, filters,
> etc. are intended to be set from the context of the initial namespace.

Seems to be the case, from_kuid() kdoc says
'There is always a mapping into the initial user_namespace.'.

I'm confused because of the various means of dealing with this:
9847371a84b0 ("netfilter: Allow xt_owner in any user namespace")

Does: make_kgid(net->user_ns, ... and also rejects rule-add if
net->user_ns != current_user_ns().  As this is for matching userids,
this makes sense to me, any userns will 'just work' for normal uid/gid
matching.

a6c6796c7127 ("userns: Convert cls_flow to work with user namespaces enabled")
Does: from_kuid(&init_user_ns, ... and rejects rule adds if sk_user_ns(NETLINK_CB(in_skb).ssk) != &init_user_ns)

Seems just a more conservative solution to the former one.

8c6e2a941ae7 ("userns: Convert xt_LOG to print socket kuids and kgids as uids and gids")
... which looks like the proposed xt_AUDIT change.

As I do not know what the use case is for xt_AUDIT rules residing in
another, possibly unprivileged network namespace not managed by root-root user,
I can't say if its right, but it should do the right thing.

Sorry for the noise.
Paul Moore Oct. 10, 2024, 7:09 p.m. UTC | #11
On Thu, Oct 10, 2024 at 2:24 AM Richard Weinberger
<richard@sigma-star.at> wrote:
> Am Donnerstag, 10. Oktober 2024, 00:02:44 CEST schrieb Paul Moore:
> > [CC'ing the audit and LSM lists for obvious reasons]
> >
> > If we're logging the subjective credentials of the skb's associated
> > socket, we really should also log the socket's LSM secctx similar to
> > what we do with audit_log_task() and audit_log_task_context().
> > Unfortunately, I don't believe we currently have a LSM interface that
> > return the secctx from a sock/socket, although we do have
> > security_inode_getsecctx() which *should* yield the same result using
> > SOCK_INODE(sk->sk_socket).
>
> Hm, I thought about that but saw 2173c519d5e91 ("audit: normalize NETFILTER_PKT").
> It removed usage of audit_log_secctx() and many other, IMHO, useful fields.

The main motivation for that patch was getting rid of the inconsistent
usage of fields in the NETFILTER_PKT record (as mentioned in the
commit description).  There's a lot of history around this, and why we
are stuck with this pretty awful IMO, but one of the audit rules is
that if a field appears in one instance of an audit record, it must
appear in all instances of an audit record (which is why it is
important and good that you used the "?" values for UID/GID when they
are not able to be logged).

However, as part of that commit we also dropped a number of fields
because it wasn't clear that anyone cared about them and if we were
going to (re)normalize the NETFILTER_PKT record we figured it would be
best to start small and re-add fields as needed to satisfy user
requirements.  I'm working under the assumption that if you've taken
the time to draft a patch and test it, you have a legitimate need :)

> What about skb->secctx?

Heh, if there is anything with more history than the swinging fields
in an audit record, it would be that :)  We don't currently have an
explicit LSM blob/secid/secctx in a skb and I wouldn't hold your
breath waiting for one; we do have a secmark, but that is something
entirely different.  We've invented some mechanisms to somewhat mimic
a LSM security label for packets, but that's complicated and not
something we would want to deal with in the NETFILTER_PKT record at
this point in time.
Paul Moore Oct. 10, 2024, 7:13 p.m. UTC | #12
On Thu, Oct 10, 2024 at 1:59 PM Florian Westphal <fw@strlen.de> wrote:
> Paul Moore <paul@paul-moore.com> wrote:
> > Correct me if I'm wrong, but by using from_kXid(&init_user_ns, Xid) we
> > get the ID number that is correct for the init namespace, yes?  If so,
> > that's what we want as right now all of the audit records, filters,
> > etc. are intended to be set from the context of the initial namespace.
>
> Seems to be the case, from_kuid() kdoc says
> 'There is always a mapping into the initial user_namespace.'.
>
> I'm confused because of the various means of dealing with this:
> 9847371a84b0 ("netfilter: Allow xt_owner in any user namespace")
>
> Does: make_kgid(net->user_ns, ... and also rejects rule-add if
> net->user_ns != current_user_ns().  As this is for matching userids,
> this makes sense to me, any userns will 'just work' for normal uid/gid
> matching.
>
> a6c6796c7127 ("userns: Convert cls_flow to work with user namespaces enabled")
> Does: from_kuid(&init_user_ns, ... and rejects rule adds if sk_user_ns(NETLINK_CB(in_skb).ssk) != &init_user_ns)
>
> Seems just a more conservative solution to the former one.
>
> 8c6e2a941ae7 ("userns: Convert xt_LOG to print socket kuids and kgids as uids and gids")
> ... which looks like the proposed xt_AUDIT change.
>
> As I do not know what the use case is for xt_AUDIT rules residing in
> another, possibly unprivileged network namespace not managed by root-root user,
> I can't say if its right, but it should do the right thing.
>
> Sorry for the noise.

No worries, it was a fair question and discussion about this is rarely
a bad thing as it can get rather complicated somewhat quickly.  With
audit our current philosophy is that we try to do our logging and run
the filters within the context of the host/initial namespace for the
sake of consistency.  Of course this introduces some limitations and
"hide" some details specific to a child namespace, but it's the only
solution we could think of that allows the current kernel audit
implementation to behave in a comprehensive and sane manner across all
the various namespace/container solutions.
Richard Weinberger Oct. 10, 2024, 8:09 p.m. UTC | #13
Am Donnerstag, 10. Oktober 2024, 15:48:27 CEST schrieb Florian Westphal:
> Richard Weinberger <richard@sigma-star.at> wrote:
> > Am Mittwoch, 9. Oktober 2024, 23:33:45 CEST schrieb Florian Westphal:
> > > There is no need to follow ->file backpointer anymore, see
> > > 6acc5c2910689fc6ee181bf63085c5efff6a42bd and
> > > 86741ec25462e4c8cdce6df2f41ead05568c7d5e,
> > > "net: core: Add a UID field to struct sock.".
> > 
> > Oh, neat!

I gave sock_net_uid() a try, but I kinda fail.

Maybe I have wrong expectations.
e.g. I expected that sock_net_uid() will return 1000 when
uid 1000 does something like: unshare -Umr followed by a veth connection
to the host (initial user/net namespace).
Shouldn't on the host side a forwarded skb have a ->dev that belongs uid
1000's net namespace?

Thanks,
//richard
Richard Weinberger Oct. 10, 2024, 8:40 p.m. UTC | #14
Am Donnerstag, 10. Oktober 2024, 21:09:31 CEST schrieb Paul Moore:
> However, as part of that commit we also dropped a number of fields
> because it wasn't clear that anyone cared about them and if we were
> going to (re)normalize the NETFILTER_PKT record we figured it would be
> best to start small and re-add fields as needed to satisfy user
> requirements.  I'm working under the assumption that if you've taken
> the time to draft a patch and test it, you have a legitimate need :)

I'm currently exploring ways to log reliable what users/containers
create what network connections.
So, netfilter+conntrack+xt_AUDIT seemed legit to me.

Thanks,
//richard
Florian Westphal Oct. 11, 2024, 1:27 a.m. UTC | #15
Richard Weinberger <richard@sigma-star.at> wrote:
> Maybe I have wrong expectations.
> e.g. I expected that sock_net_uid() will return 1000 when
> uid 1000 does something like: unshare -Umr followed by a veth connection
> to the host (initial user/net namespace).
> Shouldn't on the host side a forwarded skb have a ->dev that belongs uid
> 1000's net namespace?

You mean skb->sk?  dev doesn't make much sense in this context to me.
Else, please clarify.

ip stack orphans incoming skbs, i.e. skb->sk is gone, see skb_orphan()
call in ip_rcv_core().  So when packet enters init_net prerouting hook,
association with originating netns or sk is not present anymore.
Richard Weinberger Oct. 11, 2024, 1:12 p.m. UTC | #16
Am Freitag, 11. Oktober 2024, 03:27:13 CEST schrieb Florian Westphal:
> Richard Weinberger <richard@sigma-star.at> wrote:
> > Maybe I have wrong expectations.
> > e.g. I expected that sock_net_uid() will return 1000 when
> > uid 1000 does something like: unshare -Umr followed by a veth connection
> > to the host (initial user/net namespace).
> > Shouldn't on the host side a forwarded skb have a ->dev that belongs uid
> > 1000's net namespace?
> 
> You mean skb->sk?  dev doesn't make much sense in this context to me.
> Else, please clarify.

Well, this was a brain fart on my side.
I wondered about the sock_net_uid(net, NULL) case and wrongly assumed
that a skb I see in the outer namespace can have a skb->dev from another
namespace.
It would be awesome to have some information about
the originating net namespace.

Thanks,
//richard
diff mbox series

Patch

diff --git a/net/netfilter/xt_AUDIT.c b/net/netfilter/xt_AUDIT.c
index b6a015aee0cec..d88b5442beaa6 100644
--- a/net/netfilter/xt_AUDIT.c
+++ b/net/netfilter/xt_AUDIT.c
@@ -9,16 +9,19 @@ 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
 #include <linux/audit.h>
+#include <linux/cred.h>
+#include <linux/file.h>
+#include <linux/if_arp.h>
 #include <linux/module.h>
 #include <linux/skbuff.h>
 #include <linux/tcp.h>
 #include <linux/udp.h>
-#include <linux/if_arp.h>
 #include <linux/netfilter/x_tables.h>
 #include <linux/netfilter/xt_AUDIT.h>
 #include <linux/netfilter_bridge/ebtables.h>
-#include <net/ipv6.h>
 #include <net/ip.h>
+#include <net/ipv6.h>
+#include <net/sock.h>
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Thomas Graf <tgraf@redhat.com>");
@@ -66,7 +69,9 @@  static bool audit_ip6(struct audit_buffer *ab, struct sk_buff *skb)
 static unsigned int
 audit_tg(struct sk_buff *skb, const struct xt_action_param *par)
 {
+	struct sock *sk = skb->sk;
 	struct audit_buffer *ab;
+	bool got_uidgid = false;
 	int fam = -1;
 
 	if (audit_enabled == AUDIT_OFF)
@@ -99,6 +104,24 @@  audit_tg(struct sk_buff *skb, const struct xt_action_param *par)
 	if (fam == -1)
 		audit_log_format(ab, " saddr=? daddr=? proto=-1");
 
+	if (sk && sk_fullsock(sk)) {
+		read_lock_bh(&sk->sk_callback_lock);
+		if (sk->sk_socket && sk->sk_socket->file) {
+			const struct file *file = sk->sk_socket->file;
+			const struct cred *cred = file->f_cred;
+
+			audit_log_format(ab, " uid=%u gid=%u",
+					 from_kuid(&init_user_ns, cred->fsuid),
+					 from_kgid(&init_user_ns, cred->fsgid));
+
+			got_uidgid = true;
+		}
+		read_unlock_bh(&sk->sk_callback_lock);
+	}
+
+	if (!got_uidgid)
+		audit_log_format(ab, " uid=? gid=?");
+
 	audit_log_end(ab);
 
 errout: