diff mbox series

[ghak25,v2,8/9] netfilter: add audit operation field

Message ID 6768f7c7d9804216853e6e9c59e44f8a10f46b99.1577830902.git.rgb@redhat.com
State Awaiting Upstream
Delegated to: Pablo Neira
Headers show
Series Address NETFILTER_CFG issues | expand

Commit Message

Richard Guy Briggs Jan. 6, 2020, 6:54 p.m. UTC
Add the operation performed (register or replace) to the NETFILTER_CFG
record.

Here is the sample record:
      type=NETFILTER_CFG msg=audit(1494981627.248:9764): family=7 table=broute entries=0 op=replace

See: https://github.com/linux-audit/audit-kernel/issues/25
Signed-off-by: Richard Guy Briggs <rgb@redhat.com>
---
 include/linux/audit.h           | 8 ++++----
 kernel/auditsc.c                | 7 ++++---
 net/bridge/netfilter/ebtables.c | 4 ++--
 net/netfilter/x_tables.c        | 3 ++-
 4 files changed, 12 insertions(+), 10 deletions(-)

Comments

Florian Westphal Jan. 6, 2020, 8:23 p.m. UTC | #1
Richard Guy Briggs <rgb@redhat.com> wrote:
> diff --git a/include/linux/audit.h b/include/linux/audit.h
> index 96cabb095eed..5eab4d898c26 100644
> --- a/include/linux/audit.h
> +++ b/include/linux/audit.h
> @@ -379,7 +379,7 @@ extern int __audit_log_bprm_fcaps(struct linux_binprm *bprm,
>  extern void __audit_fanotify(unsigned int response);
>  extern void __audit_tk_injoffset(struct timespec64 offset);
>  extern void __audit_ntp_log(const struct audit_ntp_data *ad);
> -extern void __audit_nf_cfg(const char *name, u8 af, int nentries);
> +extern void __audit_nf_cfg(const char *name, u8 af, int nentries, int op);

Consider adding an enum instead of int op.

>  	if (audit_enabled)
> -		audit_nf_cfg(repl->name, AF_BRIDGE, repl->nentries);
> +		audit_nf_cfg(repl->name, AF_BRIDGE, repl->nentries, 1);

audit_nf_cfg(repl->name, AF_BRIDGE, repl->nentries, AUDIT_XT_OP_REPLACE);

... would be a bit more readable than '1'.

The name is just an example, you can pick something else.
Paul Moore Jan. 31, 2020, 3:18 a.m. UTC | #2
On Mon, Jan 6, 2020 at 3:23 PM Florian Westphal <fw@strlen.de> wrote:
> Richard Guy Briggs <rgb@redhat.com> wrote:
> > diff --git a/include/linux/audit.h b/include/linux/audit.h
> > index 96cabb095eed..5eab4d898c26 100644
> > --- a/include/linux/audit.h
> > +++ b/include/linux/audit.h
> > @@ -379,7 +379,7 @@ extern int __audit_log_bprm_fcaps(struct linux_binprm *bprm,
> >  extern void __audit_fanotify(unsigned int response);
> >  extern void __audit_tk_injoffset(struct timespec64 offset);
> >  extern void __audit_ntp_log(const struct audit_ntp_data *ad);
> > -extern void __audit_nf_cfg(const char *name, u8 af, int nentries);
> > +extern void __audit_nf_cfg(const char *name, u8 af, int nentries, int op);
>
> Consider adding an enum instead of int op.
>
> >       if (audit_enabled)
> > -             audit_nf_cfg(repl->name, AF_BRIDGE, repl->nentries);
> > +             audit_nf_cfg(repl->name, AF_BRIDGE, repl->nentries, 1);
>
> audit_nf_cfg(repl->name, AF_BRIDGE, repl->nentries, AUDIT_XT_OP_REPLACE);
>
> ... would be a bit more readable than '1'.
>
> The name is just an example, you can pick something else.

I agree.  Also, please just merge this into patch 4; I don't see a
solid reason why it shouldn't be there.

--
paul moore
www.paul-moore.com
Richard Guy Briggs Feb. 13, 2020, 12:14 p.m. UTC | #3
On 2020-01-06 21:23, Florian Westphal wrote:
> Richard Guy Briggs <rgb@redhat.com> wrote:
> > diff --git a/include/linux/audit.h b/include/linux/audit.h
> > index 96cabb095eed..5eab4d898c26 100644
> > --- a/include/linux/audit.h
> > +++ b/include/linux/audit.h
> > @@ -379,7 +379,7 @@ extern int __audit_log_bprm_fcaps(struct linux_binprm *bprm,
> >  extern void __audit_fanotify(unsigned int response);
> >  extern void __audit_tk_injoffset(struct timespec64 offset);
> >  extern void __audit_ntp_log(const struct audit_ntp_data *ad);
> > -extern void __audit_nf_cfg(const char *name, u8 af, int nentries);
> > +extern void __audit_nf_cfg(const char *name, u8 af, int nentries, int op);
> 
> Consider adding an enum instead of int op.
> 
> >  	if (audit_enabled)
> > -		audit_nf_cfg(repl->name, AF_BRIDGE, repl->nentries);
> > +		audit_nf_cfg(repl->name, AF_BRIDGE, repl->nentries, 1);
> 
> audit_nf_cfg(repl->name, AF_BRIDGE, repl->nentries, AUDIT_XT_OP_REPLACE);
> 
> ... would be a bit more readable than '1'.
> 
> The name is just an example, you can pick something else.

Thanks Florian.

Another question occurs to me about table default policy.

I'd observed previously that if nentries was zero due to an empty table,
then it was due to table registration calls, which resulted from module
loading.  The default policy is NF_ACCEPT (because Rusty didn't want
more email, go figure...).  It occurred to me later that some table
loads took a command line parameter to be able to change the default
policy verdict from NF_ACCEPT to NF_DROP.  In particular, filter FORWARD
hook tables.  Is there a straightforward way to be able to detect this
in all the audit_nf_cfg() callers to be able to log it?  In particular,
in:
	net/bridge/netfilter/ebtables.c: ebt_register_table()
	net/bridge/netfilter/ebtables.c: do_replace_finish()
	net/bridge/netfilter/ebtables.c: __ebt_unregister_table()
	net/netfilter/x_tables.c: xt_replace_table()
	net/netfilter/x_tables.c: xt_unregister_table()

It appears to be stored in the second entry of struct ipt_replace and
struct ip6t_replace, of types struct ipt_standard and struct
ip6t_standard in target.verdict, which doesn't appear to be obvious or
easily accessible from xt_replace_table().  In ebtables, it appears to
be in the policy member of struct ebt_entries.

Both potential solutions are awkward, adding a parameter to pass that
value in, but also trying to reach into the protocol-specific entry
table to find that value.  Would you have a recommendation?  This
assumes that reporting that default policy value is even desired or
required.

- RGB

--
Richard Guy Briggs <rgb@redhat.com>
Sr. S/W Engineer, Kernel Security, Base Operating Systems
Remote, Ottawa, Red Hat Canada
IRC: rgb, SunRaycer
Voice: +1.647.777.2635, Internal: (81) 32635
Florian Westphal Feb. 13, 2020, 12:34 p.m. UTC | #4
Richard Guy Briggs <rgb@redhat.com> wrote:
> The default policy is NF_ACCEPT (because Rusty didn't want
> more email, go figure...).  It occurred to me later that some table
> loads took a command line parameter to be able to change the default
> policy verdict from NF_ACCEPT to NF_DROP.  In particular, filter FORWARD
> hook tables.  Is there a straightforward way to be able to detect this
> in all the audit_nf_cfg() callers to be able to log it?  In particular,
> in:
> 	net/bridge/netfilter/ebtables.c: ebt_register_table()
> 	net/bridge/netfilter/ebtables.c: do_replace_finish()
> 	net/bridge/netfilter/ebtables.c: __ebt_unregister_table()
> 	net/netfilter/x_tables.c: xt_replace_table()
> 	net/netfilter/x_tables.c: xt_unregister_table()

The module parameter or the policy?

The poliy can be changed via the xtables tools.
Given you can have:

*filter
:INPUT ACCEPT [0:0]
:FORWARD DROP [0:0]
:OUTPUT ACCEPT [0:0]
-A FORWARD -j ACCEPT
COMMIT

... which effectily gives a FORWARD ACCEPT policy I'm not sure logging
the policy is useful.

Furthermore, ebtables has polices even for user-defined chains.

> Both potential solutions are awkward, adding a parameter to pass that
> value in, but also trying to reach into the protocol-specific entry
> table to find that value.  Would you have a recommendation?  This
> assumes that reporting that default policy value is even desired or
> required.

See above, I don't think its useful.  If it is needed, its probably best
to define an informational struct containing the policy (accept/drop)
value for the each hook points (prerouting to postrouting),  fill
that from the backend specific code (as thats the only place that
exposes the backend specific structs ...) and then pass that to
the audit logging functions.
Richard Guy Briggs Feb. 13, 2020, 2:29 p.m. UTC | #5
On 2020-02-13 13:34, Florian Westphal wrote:
> Richard Guy Briggs <rgb@redhat.com> wrote:
> > The default policy is NF_ACCEPT (because Rusty didn't want
> > more email, go figure...).  It occurred to me later that some table
> > loads took a command line parameter to be able to change the default
> > policy verdict from NF_ACCEPT to NF_DROP.  In particular, filter FORWARD
> > hook tables.  Is there a straightforward way to be able to detect this
> > in all the audit_nf_cfg() callers to be able to log it?  In particular,
> > in:
> > 	net/bridge/netfilter/ebtables.c: ebt_register_table()
> > 	net/bridge/netfilter/ebtables.c: do_replace_finish()
> > 	net/bridge/netfilter/ebtables.c: __ebt_unregister_table()
> > 	net/netfilter/x_tables.c: xt_replace_table()
> > 	net/netfilter/x_tables.c: xt_unregister_table()
> 
> The module parameter or the policy?
> 
> The poliy can be changed via the xtables tools.
> Given you can have:
> 
> *filter
> :INPUT ACCEPT [0:0]
> :FORWARD DROP [0:0]
> :OUTPUT ACCEPT [0:0]
> -A FORWARD -j ACCEPT
> COMMIT
> 
> ... which effectily gives a FORWARD ACCEPT policy I'm not sure logging
> the policy is useful.
> 
> Furthermore, ebtables has polices even for user-defined chains.
> 
> > Both potential solutions are awkward, adding a parameter to pass that
> > value in, but also trying to reach into the protocol-specific entry
> > table to find that value.  Would you have a recommendation?  This
> > assumes that reporting that default policy value is even desired or
> > required.
> 
> See above, I don't think its useful.  If it is needed, its probably best
> to define an informational struct containing the policy (accept/drop)
> value for the each hook points (prerouting to postrouting),  fill
> that from the backend specific code (as thats the only place that
> exposes the backend specific structs ...) and then pass that to
> the audit logging functions.

Ok, for this set, I'll drop the idea.  If it becomes apparent later than
it is necessary, it can be added as a field at the end of the record.

Thanks for looking at this.

- RGB

--
Richard Guy Briggs <rgb@redhat.com>
Sr. S/W Engineer, Kernel Security, Base Operating Systems
Remote, Ottawa, Red Hat Canada
IRC: rgb, SunRaycer
Voice: +1.647.777.2635, Internal: (81) 32635
diff mbox series

Patch

diff --git a/include/linux/audit.h b/include/linux/audit.h
index 96cabb095eed..5eab4d898c26 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -379,7 +379,7 @@  extern int __audit_log_bprm_fcaps(struct linux_binprm *bprm,
 extern void __audit_fanotify(unsigned int response);
 extern void __audit_tk_injoffset(struct timespec64 offset);
 extern void __audit_ntp_log(const struct audit_ntp_data *ad);
-extern void __audit_nf_cfg(const char *name, u8 af, int nentries);
+extern void __audit_nf_cfg(const char *name, u8 af, int nentries, int op);
 
 static inline void audit_ipc_obj(struct kern_ipc_perm *ipcp)
 {
@@ -515,10 +515,10 @@  static inline void audit_ntp_log(const struct audit_ntp_data *ad)
 		__audit_ntp_log(ad);
 }
 
-static inline void audit_nf_cfg(const char *name, u8 af, int nentries)
+static inline void audit_nf_cfg(const char *name, u8 af, int nentries, int op)
 {
 	if (!audit_dummy_context())
-		__audit_nf_cfg(name, af, nentries);
+		__audit_nf_cfg(name, af, nentries, op);
 }
 
 extern int audit_n_rules;
@@ -654,7 +654,7 @@  static inline void audit_ntp_log(const struct audit_ntp_data *ad)
 static inline void audit_ptrace(struct task_struct *t)
 { }
 
-static inline void audit_nf_cfg(const char *name, u8 af, int nentries)
+static inline void audit_nf_cfg(const char *name, u8 af, int nentries, int op)
 { }
 
 #define audit_n_rules 0
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index 4e1df4233cd3..999ac184246b 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -2545,7 +2545,7 @@  void __audit_ntp_log(const struct audit_ntp_data *ad)
 	audit_log_ntp_val(ad, "adjust",	AUDIT_NTP_ADJUST);
 }
 
-void __audit_nf_cfg(const char *name, u8 af, int nentries)
+void __audit_nf_cfg(const char *name, u8 af, int nentries, int op)
 {
 	struct audit_buffer *ab;
 	struct audit_context *context = audit_context();
@@ -2555,8 +2555,9 @@  void __audit_nf_cfg(const char *name, u8 af, int nentries)
 	ab = audit_log_start(context, GFP_KERNEL, AUDIT_NETFILTER_CFG);
 	if (!ab)
 		return;	/* audit_panic or being filtered */
-	audit_log_format(ab, "table=%s family=%u entries=%u",
-			 name, af, nentries);
+	audit_log_format(ab, "table=%s family=%u entries=%u op=%s",
+			 name, af, nentries,
+			 op ? "replace" : "register");
 	audit_log_end(ab);
 }
 EXPORT_SYMBOL_GPL(__audit_nf_cfg);
diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c
index 58126547b175..baff2f05af43 100644
--- a/net/bridge/netfilter/ebtables.c
+++ b/net/bridge/netfilter/ebtables.c
@@ -1049,7 +1049,7 @@  static int do_replace_finish(struct net *net, struct ebt_replace *repl,
 	vfree(counterstmp);
 
 	if (audit_enabled)
-		audit_nf_cfg(repl->name, AF_BRIDGE, repl->nentries);
+		audit_nf_cfg(repl->name, AF_BRIDGE, repl->nentries, 1);
 	return ret;
 
 free_unlock:
@@ -1220,7 +1220,7 @@  int ebt_register_table(struct net *net, const struct ebt_table *input_table,
 	}
 
 	if (audit_enabled)
-		audit_nf_cfg(repl->name, AF_BRIDGE, repl->nentries);
+		audit_nf_cfg(repl->name, AF_BRIDGE, repl->nentries, 0);
 	return ret;
 free_unlock:
 	mutex_unlock(&ebt_mutex);
diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c
index c0416ae52f7f..4ae4f7bf8946 100644
--- a/net/netfilter/x_tables.c
+++ b/net/netfilter/x_tables.c
@@ -1402,7 +1402,8 @@  struct xt_table_info *xt_replace_table(struct xt_table *table,
 	}
 
 	if (audit_enabled)
-		audit_nf_cfg(table->name, table->af, private->number);
+		audit_nf_cfg(table->name, table->af, private->number,
+			     private->number);
 
 	return private;
 }