diff --git a/include/net/netfilter/nf_tables.h b/include/net/netfilter/nf_tables.h
index 2796153b03da..af0ef21f3780 100644
--- a/include/net/netfilter/nf_tables.h
+++ b/include/net/netfilter/nf_tables.h
@@ -1608,14 +1608,16 @@ static inline int nft_set_elem_is_dead(const struct nft_set_ext *ext)
 }
 
 /**
- *	struct nft_trans - nf_tables object update in transaction
+ * struct nft_trans - nf_tables object update in transaction
  *
- *	@list: used internally
- *	@binding_list: list of objects with possible bindings
- *	@msg_type: message type
- *	@put_net: ctx->net needs to be put
- *	@ctx: transaction context
- *	@data: internal information related to the transaction
+ * @list: used internally
+ * @binding_list: list of objects with possible bindings
+ * @msg_type: message type
+ * @put_net: ctx->net needs to be put
+ * @ctx: transaction context
+ *
+ * This is the information common to all objects in the transaction,
+ * this must always be the first member of derived sub-types.
  */
 struct nft_trans {
 	struct list_head		list;
@@ -1623,10 +1625,10 @@ struct nft_trans {
 	int				msg_type;
 	bool				put_net;
 	struct nft_ctx			ctx;
-	char				data[];
 };
 
 struct nft_trans_rule {
+	struct nft_trans		nft_trans;
 	struct nft_rule			*rule;
 	struct nft_flow_rule		*flow;
 	u32				rule_id;
@@ -1634,15 +1636,16 @@ struct nft_trans_rule {
 };
 
 #define nft_trans_rule(trans)	\
-	(((struct nft_trans_rule *)trans->data)->rule)
+	container_of(trans, struct nft_trans_rule, nft_trans)->rule
 #define nft_trans_flow_rule(trans)	\
-	(((struct nft_trans_rule *)trans->data)->flow)
+	container_of(trans, struct nft_trans_rule, nft_trans)->flow
 #define nft_trans_rule_id(trans)	\
-	(((struct nft_trans_rule *)trans->data)->rule_id)
+	container_of(trans, struct nft_trans_rule, nft_trans)->rule_id
 #define nft_trans_rule_bound(trans)	\
-	(((struct nft_trans_rule *)trans->data)->bound)
+	container_of(trans, struct nft_trans_rule, nft_trans)->bound
 
 struct nft_trans_set {
+	struct nft_trans		nft_trans;
 	struct nft_set			*set;
 	u32				set_id;
 	u32				gc_int;
@@ -1653,21 +1656,22 @@ struct nft_trans_set {
 };
 
 #define nft_trans_set(trans)	\
-	(((struct nft_trans_set *)trans->data)->set)
+	container_of(trans, struct nft_trans_set, nft_trans)->set
 #define nft_trans_set_id(trans)	\
-	(((struct nft_trans_set *)trans->data)->set_id)
+	container_of(trans, struct nft_trans_set, nft_trans)->set_id
 #define nft_trans_set_bound(trans)	\
-	(((struct nft_trans_set *)trans->data)->bound)
+	container_of(trans, struct nft_trans_set, nft_trans)->bound
 #define nft_trans_set_update(trans)	\
-	(((struct nft_trans_set *)trans->data)->update)
+	container_of(trans, struct nft_trans_set, nft_trans)->update
 #define nft_trans_set_timeout(trans)	\
-	(((struct nft_trans_set *)trans->data)->timeout)
+	container_of(trans, struct nft_trans_set, nft_trans)->timeout
 #define nft_trans_set_gc_int(trans)	\
-	(((struct nft_trans_set *)trans->data)->gc_int)
+	container_of(trans, struct nft_trans_set, nft_trans)->gc_int
 #define nft_trans_set_size(trans)	\
-	(((struct nft_trans_set *)trans->data)->size)
+	container_of(trans, struct nft_trans_set, nft_trans)->size
 
 struct nft_trans_chain {
+	struct nft_trans		nft_trans;
 	struct nft_chain		*chain;
 	bool				update;
 	char				*name;
@@ -1680,58 +1684,64 @@ struct nft_trans_chain {
 };
 
 #define nft_trans_chain(trans)	\
-	(((struct nft_trans_chain *)trans->data)->chain)
+	container_of(trans, struct nft_trans_chain, nft_trans)->chain
 #define nft_trans_chain_update(trans)	\
-	(((struct nft_trans_chain *)trans->data)->update)
+	container_of(trans, struct nft_trans_chain, nft_trans)->update
 #define nft_trans_chain_name(trans)	\
-	(((struct nft_trans_chain *)trans->data)->name)
+	container_of(trans, struct nft_trans_chain, nft_trans)->name
 #define nft_trans_chain_stats(trans)	\
-	(((struct nft_trans_chain *)trans->data)->stats)
+	container_of(trans, struct nft_trans_chain, nft_trans)->stats
 #define nft_trans_chain_policy(trans)	\
-	(((struct nft_trans_chain *)trans->data)->policy)
+	container_of(trans, struct nft_trans_chain, nft_trans)->policy
 #define nft_trans_chain_bound(trans)	\
-	(((struct nft_trans_chain *)trans->data)->bound)
+	container_of(trans, struct nft_trans_chain, nft_trans)->bound
 #define nft_trans_chain_id(trans)	\
-	(((struct nft_trans_chain *)trans->data)->chain_id)
+	container_of(trans, struct nft_trans_chain, nft_trans)->chain_id
 #define nft_trans_basechain(trans)	\
-	(((struct nft_trans_chain *)trans->data)->basechain)
+	container_of(trans, struct nft_trans_chain, nft_trans)->basechain
 #define nft_trans_chain_hooks(trans)	\
-	(((struct nft_trans_chain *)trans->data)->hook_list)
+	container_of(trans, struct nft_trans_chain, nft_trans)->hook_list
 
 struct nft_trans_table {
+	struct nft_trans		nft_trans;
 	bool				update;
 };
 
 #define nft_trans_table_update(trans)	\
-	(((struct nft_trans_table *)trans->data)->update)
+	container_of(trans, struct nft_trans_table, nft_trans)->update
 
 struct nft_trans_elem {
+	struct nft_trans		nft_trans;
 	struct nft_set			*set;
 	struct nft_elem_priv		*elem_priv;
 	bool				bound;
 };
 
+#define nft_trans_container_elem(t)	\
+	container_of(t, struct nft_trans_elem, nft_trans)
 #define nft_trans_elem_set(trans)	\
-	(((struct nft_trans_elem *)trans->data)->set)
+	container_of(trans, struct nft_trans_elem, nft_trans)->set
 #define nft_trans_elem_priv(trans)	\
-	(((struct nft_trans_elem *)trans->data)->elem_priv)
+	container_of(trans, struct nft_trans_elem, nft_trans)->elem_priv
 #define nft_trans_elem_set_bound(trans)	\
-	(((struct nft_trans_elem *)trans->data)->bound)
+	container_of(trans, struct nft_trans_elem, nft_trans)->bound
 
 struct nft_trans_obj {
+	struct nft_trans		nft_trans;
 	struct nft_object		*obj;
 	struct nft_object		*newobj;
 	bool				update;
 };
 
 #define nft_trans_obj(trans)	\
-	(((struct nft_trans_obj *)trans->data)->obj)
+	container_of(trans, struct nft_trans_obj, nft_trans)->obj
 #define nft_trans_obj_newobj(trans) \
-	(((struct nft_trans_obj *)trans->data)->newobj)
+	container_of(trans, struct nft_trans_obj, nft_trans)->newobj
 #define nft_trans_obj_update(trans)	\
-	(((struct nft_trans_obj *)trans->data)->update)
+	container_of(trans, struct nft_trans_obj, nft_trans)->update
 
 struct nft_trans_flowtable {
+	struct nft_trans		nft_trans;
 	struct nft_flowtable		*flowtable;
 	bool				update;
 	struct list_head		hook_list;
@@ -1739,13 +1749,13 @@ struct nft_trans_flowtable {
 };
 
 #define nft_trans_flowtable(trans)	\
-	(((struct nft_trans_flowtable *)trans->data)->flowtable)
+	container_of(trans, struct nft_trans_flowtable, nft_trans)->flowtable
 #define nft_trans_flowtable_update(trans)	\
-	(((struct nft_trans_flowtable *)trans->data)->update)
+	container_of(trans, struct nft_trans_flowtable, nft_trans)->update
 #define nft_trans_flowtable_hooks(trans)	\
-	(((struct nft_trans_flowtable *)trans->data)->hook_list)
+	container_of(trans, struct nft_trans_flowtable, nft_trans)->hook_list
 #define nft_trans_flowtable_flags(trans)	\
-	(((struct nft_trans_flowtable *)trans->data)->flags)
+	container_of(trans, struct nft_trans_flowtable, nft_trans)->flags
 
 #define NFT_TRANS_GC_BATCHCOUNT	256
 
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
index be3b4c90d2ed..cd355f63b1d2 100644
--- a/net/netfilter/nf_tables_api.c
+++ b/net/netfilter/nf_tables_api.c
@@ -153,7 +153,7 @@ static struct nft_trans *nft_trans_alloc_gfp(const struct nft_ctx *ctx,
 {
 	struct nft_trans *trans;
 
-	trans = kzalloc(sizeof(struct nft_trans) + size, gfp);
+	trans = kzalloc(size, gfp);
 	if (trans == NULL)
 		return NULL;
 
@@ -10348,7 +10348,7 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb)
 					     trans->msg_type, GFP_KERNEL);
 			break;
 		case NFT_MSG_NEWSETELEM:
-			te = (struct nft_trans_elem *)trans->data;
+			te = nft_trans_container_elem(trans);
 
 			nft_setelem_activate(net, te->set, te->elem_priv);
 			nf_tables_setelem_notify(&trans->ctx, te->set,
@@ -10363,7 +10363,7 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb)
 			break;
 		case NFT_MSG_DELSETELEM:
 		case NFT_MSG_DESTROYSETELEM:
-			te = (struct nft_trans_elem *)trans->data;
+			te = nft_trans_container_elem(trans);
 
 			nf_tables_setelem_notify(&trans->ctx, te->set,
 						 te->elem_priv,
@@ -10643,7 +10643,7 @@ static int __nf_tables_abort(struct net *net, enum nfnl_abort_action action)
 				nft_trans_destroy(trans);
 				break;
 			}
-			te = (struct nft_trans_elem *)trans->data;
+			te = nft_trans_container_elem(trans);
 			nft_setelem_remove(net, te->set, te->elem_priv);
 			if (!nft_setelem_is_catchall(te->set, te->elem_priv))
 				atomic_dec(&te->set->nelems);
@@ -10656,7 +10656,7 @@ static int __nf_tables_abort(struct net *net, enum nfnl_abort_action action)
 			break;
 		case NFT_MSG_DELSETELEM:
 		case NFT_MSG_DESTROYSETELEM:
-			te = (struct nft_trans_elem *)trans->data;
+			te = nft_trans_container_elem(trans);
 
 			if (!nft_setelem_active_next(net, te->set, te->elem_priv)) {
 				nft_setelem_data_activate(net, te->set, te->elem_priv);
