Commit 6176b8c4 authored by Jakub Kicinski's avatar Jakub Kicinski

Merge tag 'nf-next-23-08-22' of https://git.kernel.org/pub/scm/linux/kernel/git/netfilter/nf-next

Florian Westphal says:

====================
netfilter updates for net-next

First patch resolves a fortify warning by wrapping the to-be-copied
members via struct_group.

Second patch replaces array[0] with array[] in ebtables uapi.
Both changes from GONG Ruiqi.

The largest chunk is replacement of strncpy with strscpy_pad()
in netfilter, from Justin Stitt.

Last patch, from myself, aborts ruleset validation if a fatal
signal is pending, this speeds up process exit.

* tag 'nf-next-23-08-22' of https://git.kernel.org/pub/scm/linux/kernel/git/netfilter/nf-next:
  netfilter: nf_tables: allow loop termination for pending fatal signal
  netfilter: xtables: refactor deprecated strncpy
  netfilter: x_tables: refactor deprecated strncpy
  netfilter: nft_meta: refactor deprecated strncpy
  netfilter: nft_osf: refactor deprecated strncpy
  netfilter: nf_tables: refactor deprecated strncpy
  netfilter: nf_tables: refactor deprecated strncpy
  netfilter: ipset: refactor deprecated strncpy
  netfilter: ebtables: replace zero-length array members
  netfilter: ebtables: fix fortify warnings in size_entry_mwt()
====================

Link: https://lore.kernel.org/r/20230822154336.12888-1-fw@strlen.deSigned-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents 978f4175 169384fb
...@@ -87,7 +87,7 @@ struct ebt_entries { ...@@ -87,7 +87,7 @@ struct ebt_entries {
/* nr. of entries */ /* nr. of entries */
unsigned int nentries; unsigned int nentries;
/* entry list */ /* entry list */
char data[0] __attribute__ ((aligned (__alignof__(struct ebt_replace)))); char data[] __attribute__ ((aligned (__alignof__(struct ebt_replace))));
}; };
/* used for the bitmask of struct ebt_entry */ /* used for the bitmask of struct ebt_entry */
...@@ -129,7 +129,7 @@ struct ebt_entry_match { ...@@ -129,7 +129,7 @@ struct ebt_entry_match {
} u; } u;
/* size of data */ /* size of data */
unsigned int match_size; unsigned int match_size;
unsigned char data[0] __attribute__ ((aligned (__alignof__(struct ebt_replace)))); unsigned char data[] __attribute__ ((aligned (__alignof__(struct ebt_replace))));
}; };
struct ebt_entry_watcher { struct ebt_entry_watcher {
...@@ -142,7 +142,7 @@ struct ebt_entry_watcher { ...@@ -142,7 +142,7 @@ struct ebt_entry_watcher {
} u; } u;
/* size of data */ /* size of data */
unsigned int watcher_size; unsigned int watcher_size;
unsigned char data[0] __attribute__ ((aligned (__alignof__(struct ebt_replace)))); unsigned char data[] __attribute__ ((aligned (__alignof__(struct ebt_replace))));
}; };
struct ebt_entry_target { struct ebt_entry_target {
...@@ -182,13 +182,15 @@ struct ebt_entry { ...@@ -182,13 +182,15 @@ struct ebt_entry {
unsigned char sourcemsk[ETH_ALEN]; unsigned char sourcemsk[ETH_ALEN];
unsigned char destmac[ETH_ALEN]; unsigned char destmac[ETH_ALEN];
unsigned char destmsk[ETH_ALEN]; unsigned char destmsk[ETH_ALEN];
__struct_group(/* no tag */, offsets, /* no attrs */,
/* sizeof ebt_entry + matches */ /* sizeof ebt_entry + matches */
unsigned int watchers_offset; unsigned int watchers_offset;
/* sizeof ebt_entry + matches + watchers */ /* sizeof ebt_entry + matches + watchers */
unsigned int target_offset; unsigned int target_offset;
/* sizeof ebt_entry + matches + watchers + target */ /* sizeof ebt_entry + matches + watchers + target */
unsigned int next_offset; unsigned int next_offset;
unsigned char elems[0] __attribute__ ((aligned (__alignof__(struct ebt_replace)))); );
unsigned char elems[] __attribute__ ((aligned (__alignof__(struct ebt_replace))));
}; };
static __inline__ struct ebt_entry_target * static __inline__ struct ebt_entry_target *
......
...@@ -2115,8 +2115,7 @@ static int size_entry_mwt(const struct ebt_entry *entry, const unsigned char *ba ...@@ -2115,8 +2115,7 @@ static int size_entry_mwt(const struct ebt_entry *entry, const unsigned char *ba
return ret; return ret;
offsets[0] = sizeof(struct ebt_entry); /* matches come first */ offsets[0] = sizeof(struct ebt_entry); /* matches come first */
memcpy(&offsets[1], &entry->watchers_offset, memcpy(&offsets[1], &entry->offsets, sizeof(entry->offsets));
sizeof(offsets) - sizeof(offsets[0]));
if (state->buf_kern_start) { if (state->buf_kern_start) {
buf_start = state->buf_kern_start + state->buf_kern_offset; buf_start = state->buf_kern_start + state->buf_kern_offset;
......
...@@ -872,7 +872,7 @@ ip_set_name_byindex(struct net *net, ip_set_id_t index, char *name) ...@@ -872,7 +872,7 @@ ip_set_name_byindex(struct net *net, ip_set_id_t index, char *name)
BUG_ON(!set); BUG_ON(!set);
read_lock_bh(&ip_set_ref_lock); read_lock_bh(&ip_set_ref_lock);
strncpy(name, set->name, IPSET_MAXNAMELEN); strscpy_pad(name, set->name, IPSET_MAXNAMELEN);
read_unlock_bh(&ip_set_ref_lock); read_unlock_bh(&ip_set_ref_lock);
} }
EXPORT_SYMBOL_GPL(ip_set_name_byindex); EXPORT_SYMBOL_GPL(ip_set_name_byindex);
...@@ -1326,7 +1326,7 @@ static int ip_set_rename(struct sk_buff *skb, const struct nfnl_info *info, ...@@ -1326,7 +1326,7 @@ static int ip_set_rename(struct sk_buff *skb, const struct nfnl_info *info,
goto out; goto out;
} }
} }
strncpy(set->name, name2, IPSET_MAXNAMELEN); strscpy_pad(set->name, name2, IPSET_MAXNAMELEN);
out: out:
write_unlock_bh(&ip_set_ref_lock); write_unlock_bh(&ip_set_ref_lock);
...@@ -1380,9 +1380,9 @@ static int ip_set_swap(struct sk_buff *skb, const struct nfnl_info *info, ...@@ -1380,9 +1380,9 @@ static int ip_set_swap(struct sk_buff *skb, const struct nfnl_info *info,
return -EBUSY; return -EBUSY;
} }
strncpy(from_name, from->name, IPSET_MAXNAMELEN); strscpy_pad(from_name, from->name, IPSET_MAXNAMELEN);
strncpy(from->name, to->name, IPSET_MAXNAMELEN); strscpy_pad(from->name, to->name, IPSET_MAXNAMELEN);
strncpy(to->name, from_name, IPSET_MAXNAMELEN); strscpy_pad(to->name, from_name, IPSET_MAXNAMELEN);
swap(from->ref, to->ref); swap(from->ref, to->ref);
ip_set(inst, from_id) = to; ip_set(inst, from_id) = to;
......
...@@ -3675,6 +3675,9 @@ int nft_chain_validate(const struct nft_ctx *ctx, const struct nft_chain *chain) ...@@ -3675,6 +3675,9 @@ int nft_chain_validate(const struct nft_ctx *ctx, const struct nft_chain *chain)
return -EMLINK; return -EMLINK;
list_for_each_entry(rule, &chain->rules, list) { list_for_each_entry(rule, &chain->rules, list) {
if (fatal_signal_pending(current))
return -EINTR;
if (!nft_is_active_next(ctx->net, rule)) if (!nft_is_active_next(ctx->net, rule))
continue; continue;
...@@ -10479,6 +10482,9 @@ static int nf_tables_check_loops(const struct nft_ctx *ctx, ...@@ -10479,6 +10482,9 @@ static int nf_tables_check_loops(const struct nft_ctx *ctx,
if (ctx->chain == chain) if (ctx->chain == chain)
return -ELOOP; return -ELOOP;
if (fatal_signal_pending(current))
return -EINTR;
list_for_each_entry(rule, &chain->rules, list) { list_for_each_entry(rule, &chain->rules, list) {
nft_rule_for_each_expr(expr, last, rule) { nft_rule_for_each_expr(expr, last, rule) {
struct nft_immediate_expr *priv; struct nft_immediate_expr *priv;
......
...@@ -108,7 +108,7 @@ static void nft_ct_get_eval(const struct nft_expr *expr, ...@@ -108,7 +108,7 @@ static void nft_ct_get_eval(const struct nft_expr *expr,
helper = rcu_dereference(help->helper); helper = rcu_dereference(help->helper);
if (helper == NULL) if (helper == NULL)
goto err; goto err;
strncpy((char *)dest, helper->name, NF_CT_HELPER_NAME_LEN); strscpy_pad((char *)dest, helper->name, NF_CT_HELPER_NAME_LEN);
return; return;
#ifdef CONFIG_NF_CONNTRACK_LABELS #ifdef CONFIG_NF_CONNTRACK_LABELS
case NFT_CT_LABELS: { case NFT_CT_LABELS: {
......
...@@ -151,7 +151,7 @@ void nft_fib_store_result(void *reg, const struct nft_fib *priv, ...@@ -151,7 +151,7 @@ void nft_fib_store_result(void *reg, const struct nft_fib *priv,
if (priv->flags & NFTA_FIB_F_PRESENT) if (priv->flags & NFTA_FIB_F_PRESENT)
*dreg = !!dev; *dreg = !!dev;
else else
strncpy(reg, dev ? dev->name : "", IFNAMSIZ); strscpy_pad(reg, dev ? dev->name : "", IFNAMSIZ);
break; break;
default: default:
WARN_ON_ONCE(1); WARN_ON_ONCE(1);
......
...@@ -185,12 +185,12 @@ static noinline bool nft_meta_get_eval_kind(enum nft_meta_keys key, ...@@ -185,12 +185,12 @@ static noinline bool nft_meta_get_eval_kind(enum nft_meta_keys key,
case NFT_META_IIFKIND: case NFT_META_IIFKIND:
if (!in || !in->rtnl_link_ops) if (!in || !in->rtnl_link_ops)
return false; return false;
strncpy((char *)dest, in->rtnl_link_ops->kind, IFNAMSIZ); strscpy_pad((char *)dest, in->rtnl_link_ops->kind, IFNAMSIZ);
break; break;
case NFT_META_OIFKIND: case NFT_META_OIFKIND:
if (!out || !out->rtnl_link_ops) if (!out || !out->rtnl_link_ops)
return false; return false;
strncpy((char *)dest, out->rtnl_link_ops->kind, IFNAMSIZ); strscpy_pad((char *)dest, out->rtnl_link_ops->kind, IFNAMSIZ);
break; break;
default: default:
return false; return false;
...@@ -206,7 +206,7 @@ static void nft_meta_store_ifindex(u32 *dest, const struct net_device *dev) ...@@ -206,7 +206,7 @@ static void nft_meta_store_ifindex(u32 *dest, const struct net_device *dev)
static void nft_meta_store_ifname(u32 *dest, const struct net_device *dev) static void nft_meta_store_ifname(u32 *dest, const struct net_device *dev)
{ {
strncpy((char *)dest, dev ? dev->name : "", IFNAMSIZ); strscpy_pad((char *)dest, dev ? dev->name : "", IFNAMSIZ);
} }
static bool nft_meta_store_iftype(u32 *dest, const struct net_device *dev) static bool nft_meta_store_iftype(u32 *dest, const struct net_device *dev)
......
...@@ -23,7 +23,7 @@ static void nft_osf_eval(const struct nft_expr *expr, struct nft_regs *regs, ...@@ -23,7 +23,7 @@ static void nft_osf_eval(const struct nft_expr *expr, struct nft_regs *regs,
struct nft_osf *priv = nft_expr_priv(expr); struct nft_osf *priv = nft_expr_priv(expr);
u32 *dest = &regs->data[priv->dreg]; u32 *dest = &regs->data[priv->dreg];
struct sk_buff *skb = pkt->skb; struct sk_buff *skb = pkt->skb;
char os_match[NFT_OSF_MAXGENRELEN + 1]; char os_match[NFT_OSF_MAXGENRELEN];
const struct tcphdr *tcp; const struct tcphdr *tcp;
struct nf_osf_data data; struct nf_osf_data data;
struct tcphdr _tcph; struct tcphdr _tcph;
...@@ -45,7 +45,7 @@ static void nft_osf_eval(const struct nft_expr *expr, struct nft_regs *regs, ...@@ -45,7 +45,7 @@ static void nft_osf_eval(const struct nft_expr *expr, struct nft_regs *regs,
} }
if (!nf_osf_find(skb, nf_osf_fingers, priv->ttl, &data)) { if (!nf_osf_find(skb, nf_osf_fingers, priv->ttl, &data)) {
strncpy((char *)dest, "unknown", NFT_OSF_MAXGENRELEN); strscpy_pad((char *)dest, "unknown", NFT_OSF_MAXGENRELEN);
} else { } else {
if (priv->flags & NFT_OSF_F_VERSION) if (priv->flags & NFT_OSF_F_VERSION)
snprintf(os_match, NFT_OSF_MAXGENRELEN, "%s:%s", snprintf(os_match, NFT_OSF_MAXGENRELEN, "%s:%s",
...@@ -53,7 +53,7 @@ static void nft_osf_eval(const struct nft_expr *expr, struct nft_regs *regs, ...@@ -53,7 +53,7 @@ static void nft_osf_eval(const struct nft_expr *expr, struct nft_regs *regs,
else else
strscpy(os_match, data.genre, NFT_OSF_MAXGENRELEN); strscpy(os_match, data.genre, NFT_OSF_MAXGENRELEN);
strncpy((char *)dest, os_match, NFT_OSF_MAXGENRELEN); strscpy_pad((char *)dest, os_match, NFT_OSF_MAXGENRELEN);
} }
} }
......
...@@ -768,7 +768,7 @@ void xt_compat_match_from_user(struct xt_entry_match *m, void **dstptr, ...@@ -768,7 +768,7 @@ void xt_compat_match_from_user(struct xt_entry_match *m, void **dstptr,
m->u.user.match_size = msize; m->u.user.match_size = msize;
strscpy(name, match->name, sizeof(name)); strscpy(name, match->name, sizeof(name));
module_put(match->me); module_put(match->me);
strncpy(m->u.user.name, name, sizeof(m->u.user.name)); strscpy_pad(m->u.user.name, name, sizeof(m->u.user.name));
*size += off; *size += off;
*dstptr += msize; *dstptr += msize;
...@@ -1148,7 +1148,7 @@ void xt_compat_target_from_user(struct xt_entry_target *t, void **dstptr, ...@@ -1148,7 +1148,7 @@ void xt_compat_target_from_user(struct xt_entry_target *t, void **dstptr,
t->u.user.target_size = tsize; t->u.user.target_size = tsize;
strscpy(name, target->name, sizeof(name)); strscpy(name, target->name, sizeof(name));
module_put(target->me); module_put(target->me);
strncpy(t->u.user.name, name, sizeof(t->u.user.name)); strscpy_pad(t->u.user.name, name, sizeof(t->u.user.name));
*size += off; *size += off;
*dstptr += tsize; *dstptr += tsize;
...@@ -2014,4 +2014,3 @@ static void __exit xt_fini(void) ...@@ -2014,4 +2014,3 @@ static void __exit xt_fini(void)
module_init(xt_init); module_init(xt_init);
module_exit(xt_fini); module_exit(xt_fini);
...@@ -29,7 +29,7 @@ ...@@ -29,7 +29,7 @@
if (tbl == NULL) \ if (tbl == NULL) \
return NULL; \ return NULL; \
term = (struct type##_error *)&(((char *)tbl)[term_offset]); \ term = (struct type##_error *)&(((char *)tbl)[term_offset]); \
strncpy(tbl->repl.name, info->name, sizeof(tbl->repl.name)); \ strscpy_pad(tbl->repl.name, info->name, sizeof(tbl->repl.name)); \
*term = (struct type##_error)typ2##_ERROR_INIT; \ *term = (struct type##_error)typ2##_ERROR_INIT; \
tbl->repl.valid_hooks = hook_mask; \ tbl->repl.valid_hooks = hook_mask; \
tbl->repl.num_entries = nhooks + 1; \ tbl->repl.num_entries = nhooks + 1; \
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment