diff mbox series

[RFC] selinux: introduce and use ad_init_net*() helpers

Message ID 73a810980a8452f0cb98d25698c4ae83285b7393.1689604030.git.pabeni@redhat.com (mailing list archive)
State Changes Requested
Delegated to: Paul Moore
Headers show
Series [RFC] selinux: introduce and use ad_init_net*() helpers | expand

Commit Message

Paolo Abeni July 17, 2023, 2:27 p.m. UTC
Perf traces of network-related workload shows a measurable overhead
inside the network-related selinux hooks while zeroing the
lsm_network_audit struct.

In most cases we can delay the initialization of such structure to the
usage point, avoiding such overhead in a few cases.

Additionally, the audit code accesses the IP address information only
for AF_INET* families, and selinux_parse_skb() will fill-out the
relevant fields in such cases. When the family field is zeroed or the
initialization is followed by the mentioned parsing, the zeroing can be
limited to the sk, family and netif fields.

By factoring out the audit-data initialization to new helpers, this
patch removes some duplicate code and gives small but measurable
performance gain under UDP flood.

Signed-off-by: Paolo Abeni <pabeni@redhat.com>
---
Note the performance gain is small, but measurable and let the selinux
hooks almost disappear from the perf traces I collect. The only
remaining perf-related pain-point I see is the indirect call at the
security_ level, and tackling it looks much more difficult... :(
---
 security/selinux/hooks.c | 84 ++++++++++++++++++++--------------------
 1 file changed, 43 insertions(+), 41 deletions(-)

Comments

Paul Moore July 17, 2023, 8:07 p.m. UTC | #1
On Mon, Jul 17, 2023 at 10:28 AM Paolo Abeni <pabeni@redhat.com> wrote:
>
> Perf traces of network-related workload shows a measurable overhead
> inside the network-related selinux hooks while zeroing the
> lsm_network_audit struct.
>
> In most cases we can delay the initialization of such structure to the
> usage point, avoiding such overhead in a few cases.
>
> Additionally, the audit code accesses the IP address information only
> for AF_INET* families, and selinux_parse_skb() will fill-out the
> relevant fields in such cases. When the family field is zeroed or the
> initialization is followed by the mentioned parsing, the zeroing can be
> limited to the sk, family and netif fields.
>
> By factoring out the audit-data initialization to new helpers, this
> patch removes some duplicate code and gives small but measurable
> performance gain under UDP flood.
>
> Signed-off-by: Paolo Abeni <pabeni@redhat.com>
> ---
> Note the performance gain is small, but measurable and let the selinux
> hooks almost disappear from the perf traces I collect. The only
> remaining perf-related pain-point I see is the indirect call at the
> security_ level, and tackling it looks much more difficult... :(
> ---
>  security/selinux/hooks.c | 84 ++++++++++++++++++++--------------------
>  1 file changed, 43 insertions(+), 41 deletions(-)

Overall this looks good to me, I just have some bikeshed-y comments
around function names (below) ...

> diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
> index d06e350fedee..9a75b3bcff2b 100644
> --- a/security/selinux/hooks.c
> +++ b/security/selinux/hooks.c
> @@ -4495,18 +4495,41 @@ static int socket_sockcreate_sid(const struct task_security_struct *tsec,
>                                        secclass, NULL, socksid);
>  }
>
> +static void __ad_init_net(struct common_audit_data *ad,
> +                         struct lsm_network_audit *net,
> +                         int ifindex, struct sock *sk, u16 family)
> +{
> +       ad->type = LSM_AUDIT_DATA_NET;
> +       ad->u.net = net;
> +       net->netif = ifindex;
> +       net->sk = sk;
> +       net->family = family;
> +}

Let's call this "__ad_net_init()".

> +static void ad_init_net_from_sk(struct common_audit_data *ad,
> +                               struct lsm_network_audit *net,
> +                               struct sock *sk)
> +{
> +       __ad_init_net(ad, net, 0, sk, 0);
> +}

Similarly, let's call this "ad_net_init_from_sk()"

> +static void ad_init_net_from_netif_family(struct common_audit_data *ad,
> +                                         struct lsm_network_audit *net,
> +                                         int ifindex, u16 family)
> +{
> +       __ad_init_net(ad, net, ifindex, 0, family);
> +}

... and I think this should be "ad_net_init_from_iif()".
Ondrej Mosnacek July 18, 2023, 7:17 a.m. UTC | #2
On Mon, Jul 17, 2023 at 4:30 PM Paolo Abeni <pabeni@redhat.com> wrote:
>
> Perf traces of network-related workload shows a measurable overhead
> inside the network-related selinux hooks while zeroing the
> lsm_network_audit struct.
>
> In most cases we can delay the initialization of such structure to the
> usage point, avoiding such overhead in a few cases.
>
> Additionally, the audit code accesses the IP address information only
> for AF_INET* families, and selinux_parse_skb() will fill-out the
> relevant fields in such cases. When the family field is zeroed or the
> initialization is followed by the mentioned parsing, the zeroing can be
> limited to the sk, family and netif fields.
>
> By factoring out the audit-data initialization to new helpers, this
> patch removes some duplicate code and gives small but measurable
> performance gain under UDP flood.
>
> Signed-off-by: Paolo Abeni <pabeni@redhat.com>
> ---
> Note the performance gain is small, but measurable and let the selinux
> hooks almost disappear from the perf traces I collect. The only
> remaining perf-related pain-point I see is the indirect call at the
> security_ level, and tackling it looks much more difficult... :(
> ---
>  security/selinux/hooks.c | 84 ++++++++++++++++++++--------------------
>  1 file changed, 43 insertions(+), 41 deletions(-)
>
> diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
> index d06e350fedee..9a75b3bcff2b 100644
> --- a/security/selinux/hooks.c
> +++ b/security/selinux/hooks.c
> @@ -4495,18 +4495,41 @@ static int socket_sockcreate_sid(const struct task_security_struct *tsec,
>                                        secclass, NULL, socksid);
>  }
>
> +static void __ad_init_net(struct common_audit_data *ad,
> +                         struct lsm_network_audit *net,
> +                         int ifindex, struct sock *sk, u16 family)
> +{
> +       ad->type = LSM_AUDIT_DATA_NET;
> +       ad->u.net = net;
> +       net->netif = ifindex;
> +       net->sk = sk;
> +       net->family = family;
> +}
> +
> +static void ad_init_net_from_sk(struct common_audit_data *ad,
> +                               struct lsm_network_audit *net,
> +                               struct sock *sk)
> +{
> +       __ad_init_net(ad, net, 0, sk, 0);
> +}
> +
> +static void ad_init_net_from_netif_family(struct common_audit_data *ad,
> +                                         struct lsm_network_audit *net,
> +                                         int ifindex, u16 family)
> +{
> +       __ad_init_net(ad, net, ifindex, 0, family);
> +}
> +

Since there is nothing SELinux-specific in these helpers, maybe it
would be better to move them into <linux/lsm_audit.h> and also convert
the other users of lsm_network_audit (Smack and AppArmor) to use them.
(In fact AppArmor already seems to do something similar using its own
macros.)

<snip>
Paolo Abeni July 19, 2023, 9:36 a.m. UTC | #3
On Tue, 2023-07-18 at 09:17 +0200, Ondrej Mosnacek wrote:
> On Mon, Jul 17, 2023 at 4:30 PM Paolo Abeni <pabeni@redhat.com> wrote:
> > 
> > Perf traces of network-related workload shows a measurable overhead
> > inside the network-related selinux hooks while zeroing the
> > lsm_network_audit struct.
> > 
> > In most cases we can delay the initialization of such structure to the
> > usage point, avoiding such overhead in a few cases.
> > 
> > Additionally, the audit code accesses the IP address information only
> > for AF_INET* families, and selinux_parse_skb() will fill-out the
> > relevant fields in such cases. When the family field is zeroed or the
> > initialization is followed by the mentioned parsing, the zeroing can be
> > limited to the sk, family and netif fields.
> > 
> > By factoring out the audit-data initialization to new helpers, this
> > patch removes some duplicate code and gives small but measurable
> > performance gain under UDP flood.
> > 
> > Signed-off-by: Paolo Abeni <pabeni@redhat.com>
> > ---
> > Note the performance gain is small, but measurable and let the selinux
> > hooks almost disappear from the perf traces I collect. The only
> > remaining perf-related pain-point I see is the indirect call at the
> > security_ level, and tackling it looks much more difficult... :(
> > ---
> >  security/selinux/hooks.c | 84 ++++++++++++++++++++--------------------
> >  1 file changed, 43 insertions(+), 41 deletions(-)
> > 
> > diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
> > index d06e350fedee..9a75b3bcff2b 100644
> > --- a/security/selinux/hooks.c
> > +++ b/security/selinux/hooks.c
> > @@ -4495,18 +4495,41 @@ static int socket_sockcreate_sid(const struct task_security_struct *tsec,
> >                                        secclass, NULL, socksid);
> >  }
> > 
> > +static void __ad_init_net(struct common_audit_data *ad,
> > +                         struct lsm_network_audit *net,
> > +                         int ifindex, struct sock *sk, u16 family)
> > +{
> > +       ad->type = LSM_AUDIT_DATA_NET;
> > +       ad->u.net = net;
> > +       net->netif = ifindex;
> > +       net->sk = sk;
> > +       net->family = family;
> > +}
> > +
> > +static void ad_init_net_from_sk(struct common_audit_data *ad,
> > +                               struct lsm_network_audit *net,
> > +                               struct sock *sk)
> > +{
> > +       __ad_init_net(ad, net, 0, sk, 0);
> > +}
> > +
> > +static void ad_init_net_from_netif_family(struct common_audit_data *ad,
> > +                                         struct lsm_network_audit *net,
> > +                                         int ifindex, u16 family)
> > +{
> > +       __ad_init_net(ad, net, ifindex, 0, family);
> > +}
> > +
> 
> Since there is nothing SELinux-specific in these helpers, maybe it
> would be better to move them into <linux/lsm_audit.h> and also convert
> the other users of lsm_network_audit (Smack and AppArmor) to use them.
> (In fact AppArmor already seems to do something similar using its own
> macros.)

I'm even less familiar with the internal of AppArmor and smack than
with selinux. After a quick look, I think AppArmor will be better off
without by the above, as there is a single possible user of such
helper, not much relevant from perf perspective: socket creation is
much less critical then packet reception, transmission or bh
processing. Additional hooking the common helper in the existing
macro's layers will probably require 

Smacks uses lsm_network_audit in more places, I tried to give it a shot
but the diffstat looks quite not compelling to me. Additionally I had
to prepend the 'lsm_' prefix to Paul's suggested helpers names, to keep
them consistent with the common APIs.

The main point, I think, is that each lsm does net information parsing
in a slightly different way, makingthe common helpers for such task
quite not fitting, short of some refactory in each lsm module.

TL;DR: I would avoid extending the helpers usage at this point. If
there is interest from other other lsm's maintainers, I think such
extension could be a follow-up.

Cheers,

Paolo
Paul Moore July 19, 2023, 1:11 p.m. UTC | #4
On Wed, Jul 19, 2023 at 5:36 AM Paolo Abeni <pabeni@redhat.com> wrote:
> On Tue, 2023-07-18 at 09:17 +0200, Ondrej Mosnacek wrote:

...

> > Since there is nothing SELinux-specific in these helpers, maybe it
> > would be better to move them into <linux/lsm_audit.h> and also convert
> > the other users of lsm_network_audit (Smack and AppArmor) to use them.
> > (In fact AppArmor already seems to do something similar using its own
> > macros.)

...

> TL;DR: I would avoid extending the helpers usage at this point. If
> there is interest from other other lsm's maintainers, I think such
> extension could be a follow-up.

I agree.  Quite frankly there is a lot of stuff in the LSM common
audit code that could be improved.
Paolo Abeni July 21, 2023, 3:34 p.m. UTC | #5
Hi all,

On Mon, 2023-07-17 at 16:27 +0200, Paolo Abeni wrote:
> The only
> remaining perf-related pain-point I see is the indirect call at the
> security_ level, and tackling it looks much more difficult... :(

I spent a little more time on this latest topic. AFAICS recently such
overhead has increased due to the bpf lsm introduction. My
understanding is that a major LSM and BPF LSM simultaneously enabled is
a common usage scenario. That means 2 indirect calls + 2 untrain trails
and 3 additional cache-lines used per hook.

Under the assumption than having multiple major lsms enabled
concurrently is less common, I hacked some (not exactly spectacularly
beautiful) code to avoid the above. Basically, after initialization,
for a limited number of hooks, it checks if only the default major lsm
and eventually the bpf lsm are registered and if so, converts such
hooks to static call[s], using static branches.

The idea would be to keep the above infra usage restricted to the most
performance-relevant hooks (e.g. one-off initialization or
configuration  are not relevant from that perspective). For obvious
reasons I started from a few of network related hooks ;)

As said the code could be more nice: there is some quite heavy macro
usage and some duplication I was not able to avoid). On the flip side
it shows quite measurable benefit when enabled, 0 impact when disabled,
and it's available to all major LSM, except tomoyo (but even the latter
could be accommodated with some effort).

If there is some shared interest for the above I can share the current
status and try to cleanup the code.

Any feedback more then appreciated!

Cheers,

Paolo
Paul Moore July 21, 2023, 4:11 p.m. UTC | #6
On Fri, Jul 21, 2023 at 11:35 AM Paolo Abeni <pabeni@redhat.com> wrote:
>
> Hi all,
>
> On Mon, 2023-07-17 at 16:27 +0200, Paolo Abeni wrote:
> > The only
> > remaining perf-related pain-point I see is the indirect call at the
> > security_ level, and tackling it looks much more difficult... :(
>
> I spent a little more time on this latest topic. AFAICS recently such
> overhead has increased due to the bpf lsm introduction. My
> understanding is that a major LSM and BPF LSM simultaneously enabled is
> a common usage scenario. That means 2 indirect calls + 2 untrain trails
> and 3 additional cache-lines used per hook.
>
> Under the assumption than having multiple major lsms enabled
> concurrently is less common, I hacked some (not exactly spectacularly
> beautiful) code to avoid the above. Basically, after initialization,
> for a limited number of hooks, it checks if only the default major lsm
> and eventually the bpf lsm are registered and if so, converts such
> hooks to static call[s], using static branches.
>
> The idea would be to keep the above infra usage restricted to the most
> performance-relevant hooks (e.g. one-off initialization or
> configuration  are not relevant from that perspective). For obvious
> reasons I started from a few of network related hooks ;)
>
> As said the code could be more nice: there is some quite heavy macro
> usage and some duplication I was not able to avoid). On the flip side
> it shows quite measurable benefit when enabled, 0 impact when disabled,
> and it's available to all major LSM, except tomoyo (but even the latter
> could be accommodated with some effort).
>
> If there is some shared interest for the above I can share the current
> status and try to cleanup the code.
>
> Any feedback more then appreciated!

KP, the BPF LSM maintainer, has posted patches to move the LSM hooks
over to static calls, but to the best of my current understanding the
patchset intermingles a bug fix with the performance improvements,
which I want to avoid.

There have been updated patchsets posted, but the original link
(below) contains my comments:
https://lore.kernel.org/linux-security-module/20230119231033.1307221-1-kpsingh@kernel.org/
Casey Schaufler July 21, 2023, 4:31 p.m. UTC | #7
On 7/21/2023 8:34 AM, Paolo Abeni wrote:
> Hi all,
>
> On Mon, 2023-07-17 at 16:27 +0200, Paolo Abeni wrote:
>> The only
>> remaining perf-related pain-point I see is the indirect call at the
>> security_ level, and tackling it looks much more difficult... :(
> I spent a little more time on this latest topic. AFAICS recently such
> overhead has increased due to the bpf lsm introduction. My
> understanding is that a major LSM and BPF LSM simultaneously enabled is
> a common usage scenario. That means 2 indirect calls + 2 untrain trails
> and 3 additional cache-lines used per hook.
>
> Under the assumption than having multiple major lsms enabled
> concurrently is less common, I hacked some (not exactly spectacularly
> beautiful) code to avoid the above. Basically, after initialization,
> for a limited number of hooks, it checks if only the default major lsm
> and eventually the bpf lsm are registered and if so, converts such
> hooks to static call[s], using static branches.

K.P. Singh proposed similar changes recently, and Brendan Jackman
had something in 2020. The performance benefit demonstrated has
been encouraging. The approach has two serious problems. It doesn't
lend itself very well to special cases, and the code is incredibly
ugly.

>
> The idea would be to keep the above infra usage restricted to the most
> performance-relevant hooks (e.g. one-off initialization or
> configuration  are not relevant from that perspective). For obvious
> reasons I started from a few of network related hooks ;)
>
> As said the code could be more nice: there is some quite heavy macro
> usage and some duplication I was not able to avoid). On the flip side
> it shows quite measurable benefit when enabled, 0 impact when disabled,
> and it's available to all major LSM, except tomoyo (but even the latter
> could be accommodated with some effort).
>
> If there is some shared interest for the above I can share the current
> status and try to cleanup the code.
>
> Any feedback more then appreciated!
>
> Cheers,
>
> Paolo
>
Paolo Abeni July 24, 2023, 4:28 p.m. UTC | #8
Hi,

On Fri, 2023-07-21 at 12:11 -0400, Paul Moore wrote:
> There have been updated patchsets posted, but the original link
> (below) contains my comments:
> https://lore.kernel.org/linux-security-module/20230119231033.1307221-1-kpsingh@kernel.org/

Thanks for the reference. Interestingly there are both similarities and
differences between my approach and the above. I'll try to study the
above a little bit more and then possibly I'll share what I have, just
for reference.

Cheers,

Paolo
diff mbox series

Patch

diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index d06e350fedee..9a75b3bcff2b 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -4495,18 +4495,41 @@  static int socket_sockcreate_sid(const struct task_security_struct *tsec,
 				       secclass, NULL, socksid);
 }
 
+static void __ad_init_net(struct common_audit_data *ad,
+			  struct lsm_network_audit *net,
+			  int ifindex, struct sock *sk, u16 family)
+{
+	ad->type = LSM_AUDIT_DATA_NET;
+	ad->u.net = net;
+	net->netif = ifindex;
+	net->sk = sk;
+	net->family = family;
+}
+
+static void ad_init_net_from_sk(struct common_audit_data *ad,
+				struct lsm_network_audit *net,
+				struct sock *sk)
+{
+	__ad_init_net(ad, net, 0, sk, 0);
+}
+
+static void ad_init_net_from_netif_family(struct common_audit_data *ad,
+					  struct lsm_network_audit *net,
+					  int ifindex, u16 family)
+{
+	__ad_init_net(ad, net, ifindex, 0, family);
+}
+
 static int sock_has_perm(struct sock *sk, u32 perms)
 {
 	struct sk_security_struct *sksec = sk->sk_security;
 	struct common_audit_data ad;
-	struct lsm_network_audit net = {0,};
+	struct lsm_network_audit net;
 
 	if (sksec->sid == SECINITSID_KERNEL)
 		return 0;
 
-	ad.type = LSM_AUDIT_DATA_NET;
-	ad.u.net = &net;
-	ad.u.net->sk = sk;
+	ad_init_net_from_sk(&ad, &net, sk);
 
 	return avc_has_perm(current_sid(), sksec->sid, sksec->sclass, perms,
 			    &ad);
@@ -4899,12 +4922,10 @@  static int selinux_socket_unix_stream_connect(struct sock *sock,
 	struct sk_security_struct *sksec_other = other->sk_security;
 	struct sk_security_struct *sksec_new = newsk->sk_security;
 	struct common_audit_data ad;
-	struct lsm_network_audit net = {0,};
+	struct lsm_network_audit net;
 	int err;
 
-	ad.type = LSM_AUDIT_DATA_NET;
-	ad.u.net = &net;
-	ad.u.net->sk = other;
+	ad_init_net_from_sk(&ad, &net, other);
 
 	err = avc_has_perm(sksec_sock->sid, sksec_other->sid,
 			   sksec_other->sclass,
@@ -4931,11 +4952,9 @@  static int selinux_socket_unix_may_send(struct socket *sock,
 	struct sk_security_struct *ssec = sock->sk->sk_security;
 	struct sk_security_struct *osec = other->sk->sk_security;
 	struct common_audit_data ad;
-	struct lsm_network_audit net = {0,};
+	struct lsm_network_audit net;
 
-	ad.type = LSM_AUDIT_DATA_NET;
-	ad.u.net = &net;
-	ad.u.net->sk = other->sk;
+	ad_init_net_from_sk(&ad, &net, other->sk);
 
 	return avc_has_perm(ssec->sid, osec->sid, osec->sclass, SOCKET__SENDTO,
 			    &ad);
@@ -4971,13 +4990,10 @@  static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb,
 	struct sk_security_struct *sksec = sk->sk_security;
 	u32 sk_sid = sksec->sid;
 	struct common_audit_data ad;
-	struct lsm_network_audit net = {0,};
+	struct lsm_network_audit net;
 	char *addrp;
 
-	ad.type = LSM_AUDIT_DATA_NET;
-	ad.u.net = &net;
-	ad.u.net->netif = skb->skb_iif;
-	ad.u.net->family = family;
+	ad_init_net_from_netif_family(&ad, &net, skb->skb_iif, family);
 	err = selinux_parse_skb(skb, &ad, &addrp, 1, NULL);
 	if (err)
 		return err;
@@ -5004,7 +5020,7 @@  static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
 	u16 family = sk->sk_family;
 	u32 sk_sid = sksec->sid;
 	struct common_audit_data ad;
-	struct lsm_network_audit net = {0,};
+	struct lsm_network_audit net;
 	char *addrp;
 	u8 secmark_active;
 	u8 peerlbl_active;
@@ -5028,10 +5044,7 @@  static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
 	if (!secmark_active && !peerlbl_active)
 		return 0;
 
-	ad.type = LSM_AUDIT_DATA_NET;
-	ad.u.net = &net;
-	ad.u.net->netif = skb->skb_iif;
-	ad.u.net->family = family;
+	ad_init_net_from_netif_family(&ad, &net, skb->skb_iif, family);
 	err = selinux_parse_skb(skb, &ad, &addrp, 1, NULL);
 	if (err)
 		return err;
@@ -5201,7 +5214,7 @@  static int selinux_sctp_process_new_assoc(struct sctp_association *asoc,
 	u16 family = sk->sk_family;
 	struct sk_security_struct *sksec = sk->sk_security;
 	struct common_audit_data ad;
-	struct lsm_network_audit net = {0,};
+	struct lsm_network_audit net;
 	int err;
 
 	/* handle mapped IPv4 packets arriving via IPv6 sockets */
@@ -5237,9 +5250,7 @@  static int selinux_sctp_process_new_assoc(struct sctp_association *asoc,
 		/* Other association peer SIDs are checked to enforce
 		 * consistency among the peer SIDs.
 		 */
-		ad.type = LSM_AUDIT_DATA_NET;
-		ad.u.net = &net;
-		ad.u.net->sk = asoc->base.sk;
+		ad_init_net_from_sk(&ad, &net, asoc->base.sk);
 		err = avc_has_perm(sksec->peer_sid, asoc->peer_secid,
 				   sksec->sclass, SCTP_SOCKET__ASSOCIATION,
 				   &ad);
@@ -5584,7 +5595,7 @@  static unsigned int selinux_ip_forward(void *priv, struct sk_buff *skb,
 	char *addrp;
 	u32 peer_sid;
 	struct common_audit_data ad;
-	struct lsm_network_audit net = {0,};
+	struct lsm_network_audit net;
 	int secmark_active, peerlbl_active;
 
 	if (!selinux_policycap_netpeer())
@@ -5600,10 +5611,7 @@  static unsigned int selinux_ip_forward(void *priv, struct sk_buff *skb,
 		return NF_DROP;
 
 	ifindex = state->in->ifindex;
-	ad.type = LSM_AUDIT_DATA_NET;
-	ad.u.net = &net;
-	ad.u.net->netif = ifindex;
-	ad.u.net->family = family;
+	ad_init_net_from_netif_family(&ad, &net, ifindex, family);
 	if (selinux_parse_skb(skb, &ad, &addrp, 1, NULL) != 0)
 		return NF_DROP;
 
@@ -5683,7 +5691,7 @@  static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb,
 	struct sock *sk;
 	struct sk_security_struct *sksec;
 	struct common_audit_data ad;
-	struct lsm_network_audit net = {0,};
+	struct lsm_network_audit net;
 	u8 proto = 0;
 
 	sk = skb_to_full_sk(skb);
@@ -5691,10 +5699,7 @@  static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb,
 		return NF_ACCEPT;
 	sksec = sk->sk_security;
 
-	ad.type = LSM_AUDIT_DATA_NET;
-	ad.u.net = &net;
-	ad.u.net->netif = state->out->ifindex;
-	ad.u.net->family = state->pf;
+	ad_init_net_from_netif_family(&ad, &net, state->out->ifindex, state->pf);
 	if (selinux_parse_skb(skb, &ad, NULL, 0, &proto))
 		return NF_DROP;
 
@@ -5719,7 +5724,7 @@  static unsigned int selinux_ip_postroute(void *priv,
 	int ifindex;
 	struct sock *sk;
 	struct common_audit_data ad;
-	struct lsm_network_audit net = {0,};
+	struct lsm_network_audit net;
 	char *addrp;
 	int secmark_active, peerlbl_active;
 
@@ -5816,10 +5821,7 @@  static unsigned int selinux_ip_postroute(void *priv,
 	}
 
 	ifindex = state->out->ifindex;
-	ad.type = LSM_AUDIT_DATA_NET;
-	ad.u.net = &net;
-	ad.u.net->netif = ifindex;
-	ad.u.net->family = family;
+	ad_init_net_from_netif_family(&ad, &net, ifindex, family);
 	if (selinux_parse_skb(skb, &ad, &addrp, 0, NULL))
 		return NF_DROP;