aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/net/netfilter/nf_tables.h22
-rw-r--r--net/netfilter/ipvs/ip_vs_sync.c3
-rw-r--r--net/netfilter/nf_tables_api.c61
-rw-r--r--net/netfilter/nft_compat.c14
4 files changed, 65 insertions, 35 deletions
diff --git a/include/net/netfilter/nf_tables.h b/include/net/netfilter/nf_tables.h
index 9eaaa7884586..decb9a095ae7 100644
--- a/include/net/netfilter/nf_tables.h
+++ b/include/net/netfilter/nf_tables.h
@@ -119,6 +119,22 @@ int nft_validate_data_load(const struct nft_ctx *ctx, enum nft_registers reg,
119 const struct nft_data *data, 119 const struct nft_data *data,
120 enum nft_data_types type); 120 enum nft_data_types type);
121 121
122
123/**
124 * struct nft_userdata - user defined data associated with an object
125 *
126 * @len: length of the data
127 * @data: content
128 *
129 * The presence of user data is indicated in an object specific fashion,
130 * so a length of zero can't occur and the value "len" indicates data
131 * of length len + 1.
132 */
133struct nft_userdata {
134 u8 len;
135 unsigned char data[0];
136};
137
122/** 138/**
123 * struct nft_set_elem - generic representation of set elements 139 * struct nft_set_elem - generic representation of set elements
124 * 140 *
@@ -380,7 +396,7 @@ static inline void *nft_expr_priv(const struct nft_expr *expr)
380 * @handle: rule handle 396 * @handle: rule handle
381 * @genmask: generation mask 397 * @genmask: generation mask
382 * @dlen: length of expression data 398 * @dlen: length of expression data
383 * @ulen: length of user data (used for comments) 399 * @udata: user data is appended to the rule
384 * @data: expression data 400 * @data: expression data
385 */ 401 */
386struct nft_rule { 402struct nft_rule {
@@ -388,7 +404,7 @@ struct nft_rule {
388 u64 handle:42, 404 u64 handle:42,
389 genmask:2, 405 genmask:2,
390 dlen:12, 406 dlen:12,
391 ulen:8; 407 udata:1;
392 unsigned char data[] 408 unsigned char data[]
393 __attribute__((aligned(__alignof__(struct nft_expr)))); 409 __attribute__((aligned(__alignof__(struct nft_expr))));
394}; 410};
@@ -476,7 +492,7 @@ static inline struct nft_expr *nft_expr_last(const struct nft_rule *rule)
476 return (struct nft_expr *)&rule->data[rule->dlen]; 492 return (struct nft_expr *)&rule->data[rule->dlen];
477} 493}
478 494
479static inline void *nft_userdata(const struct nft_rule *rule) 495static inline struct nft_userdata *nft_userdata(const struct nft_rule *rule)
480{ 496{
481 return (void *)&rule->data[rule->dlen]; 497 return (void *)&rule->data[rule->dlen];
482} 498}
diff --git a/net/netfilter/ipvs/ip_vs_sync.c b/net/netfilter/ipvs/ip_vs_sync.c
index c47ffd7a0a70..d93ceeb3ef04 100644
--- a/net/netfilter/ipvs/ip_vs_sync.c
+++ b/net/netfilter/ipvs/ip_vs_sync.c
@@ -896,6 +896,8 @@ static void ip_vs_proc_conn(struct net *net, struct ip_vs_conn_param *param,
896 IP_VS_DBG(2, "BACKUP, add new conn. failed\n"); 896 IP_VS_DBG(2, "BACKUP, add new conn. failed\n");
897 return; 897 return;
898 } 898 }
899 if (!(flags & IP_VS_CONN_F_TEMPLATE))
900 kfree(param->pe_data);
899 } 901 }
900 902
901 if (opt) 903 if (opt)
@@ -1169,6 +1171,7 @@ static inline int ip_vs_proc_sync_conn(struct net *net, __u8 *p, __u8 *msg_end)
1169 (opt_flags & IPVS_OPT_F_SEQ_DATA ? &opt : NULL) 1171 (opt_flags & IPVS_OPT_F_SEQ_DATA ? &opt : NULL)
1170 ); 1172 );
1171#endif 1173#endif
1174 ip_vs_pe_put(param.pe);
1172 return 0; 1175 return 0;
1173 /* Error exit */ 1176 /* Error exit */
1174out: 1177out:
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
index 199fd0f27b0e..6ab777912237 100644
--- a/net/netfilter/nf_tables_api.c
+++ b/net/netfilter/nf_tables_api.c
@@ -227,7 +227,7 @@ nft_rule_deactivate_next(struct net *net, struct nft_rule *rule)
227 227
228static inline void nft_rule_clear(struct net *net, struct nft_rule *rule) 228static inline void nft_rule_clear(struct net *net, struct nft_rule *rule)
229{ 229{
230 rule->genmask = 0; 230 rule->genmask &= ~(1 << gencursor_next(net));
231} 231}
232 232
233static int 233static int
@@ -1711,9 +1711,12 @@ static int nf_tables_fill_rule_info(struct sk_buff *skb, struct net *net,
1711 } 1711 }
1712 nla_nest_end(skb, list); 1712 nla_nest_end(skb, list);
1713 1713
1714 if (rule->ulen && 1714 if (rule->udata) {
1715 nla_put(skb, NFTA_RULE_USERDATA, rule->ulen, nft_userdata(rule))) 1715 struct nft_userdata *udata = nft_userdata(rule);
1716 goto nla_put_failure; 1716 if (nla_put(skb, NFTA_RULE_USERDATA, udata->len + 1,
1717 udata->data) < 0)
1718 goto nla_put_failure;
1719 }
1717 1720
1718 nlmsg_end(skb, nlh); 1721 nlmsg_end(skb, nlh);
1719 return 0; 1722 return 0;
@@ -1896,11 +1899,12 @@ static int nf_tables_newrule(struct sock *nlsk, struct sk_buff *skb,
1896 struct nft_table *table; 1899 struct nft_table *table;
1897 struct nft_chain *chain; 1900 struct nft_chain *chain;
1898 struct nft_rule *rule, *old_rule = NULL; 1901 struct nft_rule *rule, *old_rule = NULL;
1902 struct nft_userdata *udata;
1899 struct nft_trans *trans = NULL; 1903 struct nft_trans *trans = NULL;
1900 struct nft_expr *expr; 1904 struct nft_expr *expr;
1901 struct nft_ctx ctx; 1905 struct nft_ctx ctx;
1902 struct nlattr *tmp; 1906 struct nlattr *tmp;
1903 unsigned int size, i, n, ulen = 0; 1907 unsigned int size, i, n, ulen = 0, usize = 0;
1904 int err, rem; 1908 int err, rem;
1905 bool create; 1909 bool create;
1906 u64 handle, pos_handle; 1910 u64 handle, pos_handle;
@@ -1968,12 +1972,19 @@ static int nf_tables_newrule(struct sock *nlsk, struct sk_buff *skb,
1968 n++; 1972 n++;
1969 } 1973 }
1970 } 1974 }
1975 /* Check for overflow of dlen field */
1976 err = -EFBIG;
1977 if (size >= 1 << 12)
1978 goto err1;
1971 1979
1972 if (nla[NFTA_RULE_USERDATA]) 1980 if (nla[NFTA_RULE_USERDATA]) {
1973 ulen = nla_len(nla[NFTA_RULE_USERDATA]); 1981 ulen = nla_len(nla[NFTA_RULE_USERDATA]);
1982 if (ulen > 0)
1983 usize = sizeof(struct nft_userdata) + ulen;
1984 }
1974 1985
1975 err = -ENOMEM; 1986 err = -ENOMEM;
1976 rule = kzalloc(sizeof(*rule) + size + ulen, GFP_KERNEL); 1987 rule = kzalloc(sizeof(*rule) + size + usize, GFP_KERNEL);
1977 if (rule == NULL) 1988 if (rule == NULL)
1978 goto err1; 1989 goto err1;
1979 1990
@@ -1981,10 +1992,13 @@ static int nf_tables_newrule(struct sock *nlsk, struct sk_buff *skb,
1981 1992
1982 rule->handle = handle; 1993 rule->handle = handle;
1983 rule->dlen = size; 1994 rule->dlen = size;
1984 rule->ulen = ulen; 1995 rule->udata = ulen ? 1 : 0;
1985 1996
1986 if (ulen) 1997 if (ulen) {
1987 nla_memcpy(nft_userdata(rule), nla[NFTA_RULE_USERDATA], ulen); 1998 udata = nft_userdata(rule);
1999 udata->len = ulen - 1;
2000 nla_memcpy(udata->data, nla[NFTA_RULE_USERDATA], ulen);
2001 }
1988 2002
1989 expr = nft_expr_first(rule); 2003 expr = nft_expr_first(rule);
1990 for (i = 0; i < n; i++) { 2004 for (i = 0; i < n; i++) {
@@ -2031,12 +2045,6 @@ static int nf_tables_newrule(struct sock *nlsk, struct sk_buff *skb,
2031 2045
2032err3: 2046err3:
2033 list_del_rcu(&rule->list); 2047 list_del_rcu(&rule->list);
2034 if (trans) {
2035 list_del_rcu(&nft_trans_rule(trans)->list);
2036 nft_rule_clear(net, nft_trans_rule(trans));
2037 nft_trans_destroy(trans);
2038 chain->use++;
2039 }
2040err2: 2048err2:
2041 nf_tables_rule_destroy(&ctx, rule); 2049 nf_tables_rule_destroy(&ctx, rule);
2042err1: 2050err1:
@@ -3612,12 +3620,11 @@ static int nf_tables_commit(struct sk_buff *skb)
3612 &te->elem, 3620 &te->elem,
3613 NFT_MSG_DELSETELEM, 0); 3621 NFT_MSG_DELSETELEM, 0);
3614 te->set->ops->get(te->set, &te->elem); 3622 te->set->ops->get(te->set, &te->elem);
3615 te->set->ops->remove(te->set, &te->elem);
3616 nft_data_uninit(&te->elem.key, NFT_DATA_VALUE); 3623 nft_data_uninit(&te->elem.key, NFT_DATA_VALUE);
3617 if (te->elem.flags & NFT_SET_MAP) { 3624 if (te->set->flags & NFT_SET_MAP &&
3618 nft_data_uninit(&te->elem.data, 3625 !(te->elem.flags & NFT_SET_ELEM_INTERVAL_END))
3619 te->set->dtype); 3626 nft_data_uninit(&te->elem.data, te->set->dtype);
3620 } 3627 te->set->ops->remove(te->set, &te->elem);
3621 nft_trans_destroy(trans); 3628 nft_trans_destroy(trans);
3622 break; 3629 break;
3623 } 3630 }
@@ -3658,7 +3665,7 @@ static int nf_tables_abort(struct sk_buff *skb)
3658{ 3665{
3659 struct net *net = sock_net(skb->sk); 3666 struct net *net = sock_net(skb->sk);
3660 struct nft_trans *trans, *next; 3667 struct nft_trans *trans, *next;
3661 struct nft_set *set; 3668 struct nft_trans_elem *te;
3662 3669
3663 list_for_each_entry_safe(trans, next, &net->nft.commit_list, list) { 3670 list_for_each_entry_safe(trans, next, &net->nft.commit_list, list) {
3664 switch (trans->msg_type) { 3671 switch (trans->msg_type) {
@@ -3719,9 +3726,13 @@ static int nf_tables_abort(struct sk_buff *skb)
3719 break; 3726 break;
3720 case NFT_MSG_NEWSETELEM: 3727 case NFT_MSG_NEWSETELEM:
3721 nft_trans_elem_set(trans)->nelems--; 3728 nft_trans_elem_set(trans)->nelems--;
3722 set = nft_trans_elem_set(trans); 3729 te = (struct nft_trans_elem *)trans->data;
3723 set->ops->get(set, &nft_trans_elem(trans)); 3730 te->set->ops->get(te->set, &te->elem);
3724 set->ops->remove(set, &nft_trans_elem(trans)); 3731 nft_data_uninit(&te->elem.key, NFT_DATA_VALUE);
3732 if (te->set->flags & NFT_SET_MAP &&
3733 !(te->elem.flags & NFT_SET_ELEM_INTERVAL_END))
3734 nft_data_uninit(&te->elem.data, te->set->dtype);
3735 te->set->ops->remove(te->set, &te->elem);
3725 nft_trans_destroy(trans); 3736 nft_trans_destroy(trans);
3726 break; 3737 break;
3727 case NFT_MSG_DELSETELEM: 3738 case NFT_MSG_DELSETELEM:
diff --git a/net/netfilter/nft_compat.c b/net/netfilter/nft_compat.c
index 1279cd85663e..213584cf04b3 100644
--- a/net/netfilter/nft_compat.c
+++ b/net/netfilter/nft_compat.c
@@ -123,7 +123,7 @@ static void
123nft_target_set_tgchk_param(struct xt_tgchk_param *par, 123nft_target_set_tgchk_param(struct xt_tgchk_param *par,
124 const struct nft_ctx *ctx, 124 const struct nft_ctx *ctx,
125 struct xt_target *target, void *info, 125 struct xt_target *target, void *info,
126 union nft_entry *entry, u8 proto, bool inv) 126 union nft_entry *entry, u16 proto, bool inv)
127{ 127{
128 par->net = ctx->net; 128 par->net = ctx->net;
129 par->table = ctx->table->name; 129 par->table = ctx->table->name;
@@ -137,7 +137,7 @@ nft_target_set_tgchk_param(struct xt_tgchk_param *par,
137 entry->e6.ipv6.invflags = inv ? IP6T_INV_PROTO : 0; 137 entry->e6.ipv6.invflags = inv ? IP6T_INV_PROTO : 0;
138 break; 138 break;
139 case NFPROTO_BRIDGE: 139 case NFPROTO_BRIDGE:
140 entry->ebt.ethproto = proto; 140 entry->ebt.ethproto = (__force __be16)proto;
141 entry->ebt.invflags = inv ? EBT_IPROTO : 0; 141 entry->ebt.invflags = inv ? EBT_IPROTO : 0;
142 break; 142 break;
143 } 143 }
@@ -171,7 +171,7 @@ static const struct nla_policy nft_rule_compat_policy[NFTA_RULE_COMPAT_MAX + 1]
171 [NFTA_RULE_COMPAT_FLAGS] = { .type = NLA_U32 }, 171 [NFTA_RULE_COMPAT_FLAGS] = { .type = NLA_U32 },
172}; 172};
173 173
174static int nft_parse_compat(const struct nlattr *attr, u8 *proto, bool *inv) 174static int nft_parse_compat(const struct nlattr *attr, u16 *proto, bool *inv)
175{ 175{
176 struct nlattr *tb[NFTA_RULE_COMPAT_MAX+1]; 176 struct nlattr *tb[NFTA_RULE_COMPAT_MAX+1];
177 u32 flags; 177 u32 flags;
@@ -203,7 +203,7 @@ nft_target_init(const struct nft_ctx *ctx, const struct nft_expr *expr,
203 struct xt_target *target = expr->ops->data; 203 struct xt_target *target = expr->ops->data;
204 struct xt_tgchk_param par; 204 struct xt_tgchk_param par;
205 size_t size = XT_ALIGN(nla_len(tb[NFTA_TARGET_INFO])); 205 size_t size = XT_ALIGN(nla_len(tb[NFTA_TARGET_INFO]));
206 u8 proto = 0; 206 u16 proto = 0;
207 bool inv = false; 207 bool inv = false;
208 union nft_entry e = {}; 208 union nft_entry e = {};
209 int ret; 209 int ret;
@@ -334,7 +334,7 @@ static const struct nla_policy nft_match_policy[NFTA_MATCH_MAX + 1] = {
334static void 334static void
335nft_match_set_mtchk_param(struct xt_mtchk_param *par, const struct nft_ctx *ctx, 335nft_match_set_mtchk_param(struct xt_mtchk_param *par, const struct nft_ctx *ctx,
336 struct xt_match *match, void *info, 336 struct xt_match *match, void *info,
337 union nft_entry *entry, u8 proto, bool inv) 337 union nft_entry *entry, u16 proto, bool inv)
338{ 338{
339 par->net = ctx->net; 339 par->net = ctx->net;
340 par->table = ctx->table->name; 340 par->table = ctx->table->name;
@@ -348,7 +348,7 @@ nft_match_set_mtchk_param(struct xt_mtchk_param *par, const struct nft_ctx *ctx,
348 entry->e6.ipv6.invflags = inv ? IP6T_INV_PROTO : 0; 348 entry->e6.ipv6.invflags = inv ? IP6T_INV_PROTO : 0;
349 break; 349 break;
350 case NFPROTO_BRIDGE: 350 case NFPROTO_BRIDGE:
351 entry->ebt.ethproto = proto; 351 entry->ebt.ethproto = (__force __be16)proto;
352 entry->ebt.invflags = inv ? EBT_IPROTO : 0; 352 entry->ebt.invflags = inv ? EBT_IPROTO : 0;
353 break; 353 break;
354 } 354 }
@@ -385,7 +385,7 @@ nft_match_init(const struct nft_ctx *ctx, const struct nft_expr *expr,
385 struct xt_match *match = expr->ops->data; 385 struct xt_match *match = expr->ops->data;
386 struct xt_mtchk_param par; 386 struct xt_mtchk_param par;
387 size_t size = XT_ALIGN(nla_len(tb[NFTA_MATCH_INFO])); 387 size_t size = XT_ALIGN(nla_len(tb[NFTA_MATCH_INFO]));
388 u8 proto = 0; 388 u16 proto = 0;
389 bool inv = false; 389 bool inv = false;
390 union nft_entry e = {}; 390 union nft_entry e = {};
391 int ret; 391 int ret;