@@ -66,6 +66,41 @@ static const struct rhashtable_params nft_objname_ht_params = {
6666 .automatic_shrinking = true,
6767};
6868
69+ struct nft_audit_data {
70+ struct nft_table * table ;
71+ int entries ;
72+ int op ;
73+ struct list_head list ;
74+ };
75+
76+ static const u8 nft2audit_op [NFT_MSG_MAX ] = { // enum nf_tables_msg_types
77+ [NFT_MSG_NEWTABLE ] = AUDIT_NFT_OP_TABLE_REGISTER ,
78+ [NFT_MSG_GETTABLE ] = AUDIT_NFT_OP_INVALID ,
79+ [NFT_MSG_DELTABLE ] = AUDIT_NFT_OP_TABLE_UNREGISTER ,
80+ [NFT_MSG_NEWCHAIN ] = AUDIT_NFT_OP_CHAIN_REGISTER ,
81+ [NFT_MSG_GETCHAIN ] = AUDIT_NFT_OP_INVALID ,
82+ [NFT_MSG_DELCHAIN ] = AUDIT_NFT_OP_CHAIN_UNREGISTER ,
83+ [NFT_MSG_NEWRULE ] = AUDIT_NFT_OP_RULE_REGISTER ,
84+ [NFT_MSG_GETRULE ] = AUDIT_NFT_OP_INVALID ,
85+ [NFT_MSG_DELRULE ] = AUDIT_NFT_OP_RULE_UNREGISTER ,
86+ [NFT_MSG_NEWSET ] = AUDIT_NFT_OP_SET_REGISTER ,
87+ [NFT_MSG_GETSET ] = AUDIT_NFT_OP_INVALID ,
88+ [NFT_MSG_DELSET ] = AUDIT_NFT_OP_SET_UNREGISTER ,
89+ [NFT_MSG_NEWSETELEM ] = AUDIT_NFT_OP_SETELEM_REGISTER ,
90+ [NFT_MSG_GETSETELEM ] = AUDIT_NFT_OP_INVALID ,
91+ [NFT_MSG_DELSETELEM ] = AUDIT_NFT_OP_SETELEM_UNREGISTER ,
92+ [NFT_MSG_NEWGEN ] = AUDIT_NFT_OP_GEN_REGISTER ,
93+ [NFT_MSG_GETGEN ] = AUDIT_NFT_OP_INVALID ,
94+ [NFT_MSG_TRACE ] = AUDIT_NFT_OP_INVALID ,
95+ [NFT_MSG_NEWOBJ ] = AUDIT_NFT_OP_OBJ_REGISTER ,
96+ [NFT_MSG_GETOBJ ] = AUDIT_NFT_OP_INVALID ,
97+ [NFT_MSG_DELOBJ ] = AUDIT_NFT_OP_OBJ_UNREGISTER ,
98+ [NFT_MSG_GETOBJ_RESET ] = AUDIT_NFT_OP_OBJ_RESET ,
99+ [NFT_MSG_NEWFLOWTABLE ] = AUDIT_NFT_OP_FLOWTABLE_REGISTER ,
100+ [NFT_MSG_GETFLOWTABLE ] = AUDIT_NFT_OP_INVALID ,
101+ [NFT_MSG_DELFLOWTABLE ] = AUDIT_NFT_OP_FLOWTABLE_UNREGISTER ,
102+ };
103+
69104static void nft_validate_state_update (struct net * net , u8 new_validate_state )
70105{
71106 switch (net -> nft .validate_state ) {
@@ -718,17 +753,6 @@ static void nf_tables_table_notify(const struct nft_ctx *ctx, int event)
718753{
719754 struct sk_buff * skb ;
720755 int err ;
721- char * buf = kasprintf (GFP_KERNEL , "%s:%llu;?:0" ,
722- ctx -> table -> name , ctx -> table -> handle );
723-
724- audit_log_nfcfg (buf ,
725- ctx -> family ,
726- ctx -> table -> use ,
727- event == NFT_MSG_NEWTABLE ?
728- AUDIT_NFT_OP_TABLE_REGISTER :
729- AUDIT_NFT_OP_TABLE_UNREGISTER ,
730- GFP_KERNEL );
731- kfree (buf );
732756
733757 if (!ctx -> report &&
734758 !nfnetlink_has_listeners (ctx -> net , NFNLGRP_NFTABLES ))
@@ -1502,18 +1526,6 @@ static void nf_tables_chain_notify(const struct nft_ctx *ctx, int event)
15021526{
15031527 struct sk_buff * skb ;
15041528 int err ;
1505- char * buf = kasprintf (GFP_KERNEL , "%s:%llu;%s:%llu" ,
1506- ctx -> table -> name , ctx -> table -> handle ,
1507- ctx -> chain -> name , ctx -> chain -> handle );
1508-
1509- audit_log_nfcfg (buf ,
1510- ctx -> family ,
1511- ctx -> chain -> use ,
1512- event == NFT_MSG_NEWCHAIN ?
1513- AUDIT_NFT_OP_CHAIN_REGISTER :
1514- AUDIT_NFT_OP_CHAIN_UNREGISTER ,
1515- GFP_KERNEL );
1516- kfree (buf );
15171529
15181530 if (!ctx -> report &&
15191531 !nfnetlink_has_listeners (ctx -> net , NFNLGRP_NFTABLES ))
@@ -2866,18 +2878,6 @@ static void nf_tables_rule_notify(const struct nft_ctx *ctx,
28662878{
28672879 struct sk_buff * skb ;
28682880 int err ;
2869- char * buf = kasprintf (GFP_KERNEL , "%s:%llu;%s:%llu" ,
2870- ctx -> table -> name , ctx -> table -> handle ,
2871- ctx -> chain -> name , ctx -> chain -> handle );
2872-
2873- audit_log_nfcfg (buf ,
2874- ctx -> family ,
2875- rule -> handle ,
2876- event == NFT_MSG_NEWRULE ?
2877- AUDIT_NFT_OP_RULE_REGISTER :
2878- AUDIT_NFT_OP_RULE_UNREGISTER ,
2879- GFP_KERNEL );
2880- kfree (buf );
28812881
28822882 if (!ctx -> report &&
28832883 !nfnetlink_has_listeners (ctx -> net , NFNLGRP_NFTABLES ))
@@ -3912,18 +3912,6 @@ static void nf_tables_set_notify(const struct nft_ctx *ctx,
39123912 struct sk_buff * skb ;
39133913 u32 portid = ctx -> portid ;
39143914 int err ;
3915- char * buf = kasprintf (gfp_flags , "%s:%llu;%s:%llu" ,
3916- ctx -> table -> name , ctx -> table -> handle ,
3917- set -> name , set -> handle );
3918-
3919- audit_log_nfcfg (buf ,
3920- ctx -> family ,
3921- set -> field_count ,
3922- event == NFT_MSG_NEWSET ?
3923- AUDIT_NFT_OP_SET_REGISTER :
3924- AUDIT_NFT_OP_SET_UNREGISTER ,
3925- gfp_flags );
3926- kfree (buf );
39273915
39283916 if (!ctx -> report &&
39293917 !nfnetlink_has_listeners (ctx -> net , NFNLGRP_NFTABLES ))
@@ -5108,18 +5096,6 @@ static void nf_tables_setelem_notify(const struct nft_ctx *ctx,
51085096 u32 portid = ctx -> portid ;
51095097 struct sk_buff * skb ;
51105098 int err ;
5111- char * buf = kasprintf (GFP_KERNEL , "%s:%llu;%s:%llu" ,
5112- ctx -> table -> name , ctx -> table -> handle ,
5113- set -> name , set -> handle );
5114-
5115- audit_log_nfcfg (buf ,
5116- ctx -> family ,
5117- set -> handle ,
5118- event == NFT_MSG_NEWSETELEM ?
5119- AUDIT_NFT_OP_SETELEM_REGISTER :
5120- AUDIT_NFT_OP_SETELEM_UNREGISTER ,
5121- GFP_KERNEL );
5122- kfree (buf );
51235099
51245100 if (!ctx -> report && !nfnetlink_has_listeners (net , NFNLGRP_NFTABLES ))
51255101 return ;
@@ -6321,12 +6297,11 @@ static int nf_tables_dump_obj(struct sk_buff *skb, struct netlink_callback *cb)
63216297 filter -> type != NFT_OBJECT_UNSPEC &&
63226298 obj -> ops -> type -> type != filter -> type )
63236299 goto cont ;
6324-
63256300 if (reset ) {
63266301 char * buf = kasprintf (GFP_ATOMIC ,
6327- "%s:%llu;?:0 " ,
6302+ "%s:%u " ,
63286303 table -> name ,
6329- table -> handle );
6304+ net -> nft . base_seq );
63306305
63316306 audit_log_nfcfg (buf ,
63326307 family ,
@@ -6447,8 +6422,8 @@ static int nf_tables_getobj(struct net *net, struct sock *nlsk,
64476422 reset = true;
64486423
64496424 if (reset ) {
6450- char * buf = kasprintf (GFP_ATOMIC , "%s:%llu;?:0 " ,
6451- table -> name , table -> handle );
6425+ char * buf = kasprintf (GFP_ATOMIC , "%s:%u " ,
6426+ table -> name , net -> nft . base_seq );
64526427
64536428 audit_log_nfcfg (buf ,
64546429 family ,
@@ -6536,15 +6511,15 @@ void nft_obj_notify(struct net *net, const struct nft_table *table,
65366511{
65376512 struct sk_buff * skb ;
65386513 int err ;
6539- char * buf = kasprintf (gfp , "%s:%llu;?:0 " ,
6540- table -> name , table -> handle );
6514+ char * buf = kasprintf (gfp , "%s:%u " ,
6515+ table -> name , net -> nft . base_seq );
65416516
65426517 audit_log_nfcfg (buf ,
65436518 family ,
65446519 obj -> handle ,
65456520 event == NFT_MSG_NEWOBJ ?
6546- AUDIT_NFT_OP_OBJ_REGISTER :
6547- AUDIT_NFT_OP_OBJ_UNREGISTER ,
6521+ AUDIT_NFT_OP_OBJ_REGISTER :
6522+ AUDIT_NFT_OP_OBJ_UNREGISTER ,
65486523 gfp );
65496524 kfree (buf );
65506525
@@ -7362,18 +7337,6 @@ static void nf_tables_flowtable_notify(struct nft_ctx *ctx,
73627337{
73637338 struct sk_buff * skb ;
73647339 int err ;
7365- char * buf = kasprintf (GFP_KERNEL , "%s:%llu;%s:%llu" ,
7366- flowtable -> table -> name , flowtable -> table -> handle ,
7367- flowtable -> name , flowtable -> handle );
7368-
7369- audit_log_nfcfg (buf ,
7370- ctx -> family ,
7371- flowtable -> hooknum ,
7372- event == NFT_MSG_NEWFLOWTABLE ?
7373- AUDIT_NFT_OP_FLOWTABLE_REGISTER :
7374- AUDIT_NFT_OP_FLOWTABLE_UNREGISTER ,
7375- GFP_KERNEL );
7376- kfree (buf );
73777340
73787341 if (!ctx -> report &&
73797342 !nfnetlink_has_listeners (ctx -> net , NFNLGRP_NFTABLES ))
@@ -7494,9 +7457,6 @@ static void nf_tables_gen_notify(struct net *net, struct sk_buff *skb,
74947457 struct sk_buff * skb2 ;
74957458 int err ;
74967459
7497- audit_log_nfcfg ("?:0;?:0" , 0 , net -> nft .base_seq ,
7498- AUDIT_NFT_OP_GEN_REGISTER , GFP_KERNEL );
7499-
75007460 if (!nlmsg_report (nlh ) &&
75017461 !nfnetlink_has_listeners (net , NFNLGRP_NFTABLES ))
75027462 return ;
@@ -8035,12 +7995,64 @@ static void nft_commit_notify(struct net *net, u32 portid)
80357995 WARN_ON_ONCE (!list_empty (& net -> nft .notify_list ));
80367996}
80377997
7998+ static int nf_tables_commit_audit_alloc (struct list_head * adl ,
7999+ struct nft_table * table )
8000+ {
8001+ struct nft_audit_data * adp ;
8002+
8003+ list_for_each_entry (adp , adl , list ) {
8004+ if (adp -> table == table )
8005+ return 0 ;
8006+ }
8007+ adp = kzalloc (sizeof (* adp ), GFP_KERNEL );
8008+ if (!adp )
8009+ return - ENOMEM ;
8010+ adp -> table = table ;
8011+ list_add (& adp -> list , adl );
8012+ return 0 ;
8013+ }
8014+
8015+ static void nf_tables_commit_audit_collect (struct list_head * adl ,
8016+ struct nft_table * table , u32 op )
8017+ {
8018+ struct nft_audit_data * adp ;
8019+
8020+ list_for_each_entry (adp , adl , list ) {
8021+ if (adp -> table == table )
8022+ goto found ;
8023+ }
8024+ WARN_ONCE ("table=%s not expected in commit list" , table -> name );
8025+ return ;
8026+ found :
8027+ adp -> entries ++ ;
8028+ if (!adp -> op || adp -> op > op )
8029+ adp -> op = op ;
8030+ }
8031+
8032+ #define AUNFTABLENAMELEN (NFT_TABLE_MAXNAMELEN + 22)
8033+
8034+ static void nf_tables_commit_audit_log (struct list_head * adl , u32 generation )
8035+ {
8036+ struct nft_audit_data * adp , * adn ;
8037+ char aubuf [AUNFTABLENAMELEN ];
8038+
8039+ list_for_each_entry_safe (adp , adn , adl , list ) {
8040+ snprintf (aubuf , AUNFTABLENAMELEN , "%s:%u" , adp -> table -> name ,
8041+ generation );
8042+ audit_log_nfcfg (aubuf , adp -> table -> family , adp -> entries ,
8043+ nft2audit_op [adp -> op ], GFP_KERNEL );
8044+ list_del (& adp -> list );
8045+ kfree (adp );
8046+ }
8047+ }
8048+
80388049static int nf_tables_commit (struct net * net , struct sk_buff * skb )
80398050{
80408051 struct nft_trans * trans , * next ;
80418052 struct nft_trans_elem * te ;
80428053 struct nft_chain * chain ;
80438054 struct nft_table * table ;
8055+ LIST_HEAD (adl );
80448056 int err ;
80458057
80468058 if (list_empty (& net -> nft .commit_list )) {
@@ -8060,6 +8072,11 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb)
80608072 list_for_each_entry_safe (trans , next , & net -> nft .commit_list , list ) {
80618073 int ret ;
80628074
8075+ ret = nf_tables_commit_audit_alloc (& adl , trans -> ctx .table );
8076+ if (ret ) {
8077+ nf_tables_commit_chain_prepare_cancel (net );
8078+ return ret ;
8079+ }
80638080 if (trans -> msg_type == NFT_MSG_NEWRULE ||
80648081 trans -> msg_type == NFT_MSG_DELRULE ) {
80658082 chain = trans -> ctx .chain ;
@@ -8088,6 +8105,8 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb)
80888105 net -> nft .gencursor = nft_gencursor_next (net );
80898106
80908107 list_for_each_entry_safe (trans , next , & net -> nft .commit_list , list ) {
8108+ nf_tables_commit_audit_collect (& adl , trans -> ctx .table ,
8109+ trans -> msg_type );
80918110 switch (trans -> msg_type ) {
80928111 case NFT_MSG_NEWTABLE :
80938112 if (nft_trans_table_update (trans )) {
@@ -8240,6 +8259,7 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb)
82408259
82418260 nft_commit_notify (net , NETLINK_CB (skb ).portid );
82428261 nf_tables_gen_notify (net , skb , NFT_MSG_NEWGEN );
8262+ nf_tables_commit_audit_log (& adl , net -> nft .base_seq );
82438263 nf_tables_commit_release (net );
82448264
82458265 return 0 ;
0 commit comments