Merge git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf
Pablo Neira Ayuso says: ==================== Netfilter fixes for net The following patchset contains Netfilter fixes for net: 1) Missing register size validation in bitwise and cmp offloads. 2) Fix error code in ip_set_sockfn_get() when copy_to_user() fails, from Dan Carpenter. 3) Oneliner to copy MAC address in IPv6 hash:ip,mac sets, from Stefano Brivio. 4) Missing policy validation in ipset with NL_VALIDATE_STRICT, from Jozsef Kadlecsik. 5) Fix unaligned access to private data area of nf_tables instructions, from Lukas Wunner. 6) Relax check for object updates, reported as a regression by Eric Garver, patch from Fernando Fernandez Mancera. 7) Crash on ebtables dnat extension when used from the output path. From Florian Westphal. 8) Fix bogus EOPNOTSUPP when updating basechain flags. 9) Fix bogus EBUSY when updating a basechain that is already offloaded. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
53ba60afb1
|
@ -820,7 +820,8 @@ struct nft_expr_ops {
|
|||
*/
|
||||
struct nft_expr {
|
||||
const struct nft_expr_ops *ops;
|
||||
unsigned char data[];
|
||||
unsigned char data[]
|
||||
__attribute__((aligned(__alignof__(u64))));
|
||||
};
|
||||
|
||||
static inline void *nft_expr_priv(const struct nft_expr *expr)
|
||||
|
|
|
@ -20,7 +20,6 @@ static unsigned int
|
|||
ebt_dnat_tg(struct sk_buff *skb, const struct xt_action_param *par)
|
||||
{
|
||||
const struct ebt_nat_info *info = par->targinfo;
|
||||
struct net_device *dev;
|
||||
|
||||
if (skb_ensure_writable(skb, ETH_ALEN))
|
||||
return EBT_DROP;
|
||||
|
@ -33,10 +32,22 @@ ebt_dnat_tg(struct sk_buff *skb, const struct xt_action_param *par)
|
|||
else
|
||||
skb->pkt_type = PACKET_MULTICAST;
|
||||
} else {
|
||||
if (xt_hooknum(par) != NF_BR_BROUTING)
|
||||
dev = br_port_get_rcu(xt_in(par))->br->dev;
|
||||
else
|
||||
const struct net_device *dev;
|
||||
|
||||
switch (xt_hooknum(par)) {
|
||||
case NF_BR_BROUTING:
|
||||
dev = xt_in(par);
|
||||
break;
|
||||
case NF_BR_PRE_ROUTING:
|
||||
dev = br_port_get_rcu(xt_in(par))->br->dev;
|
||||
break;
|
||||
default:
|
||||
dev = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!dev) /* NF_BR_LOCAL_OUT */
|
||||
return info->target;
|
||||
|
||||
if (ether_addr_equal(info->mac, dev->dev_addr))
|
||||
skb->pkt_type = PACKET_HOST;
|
||||
|
|
|
@ -296,7 +296,8 @@ ip_set_get_ipaddr4(struct nlattr *nla, __be32 *ipaddr)
|
|||
|
||||
if (unlikely(!flag_nested(nla)))
|
||||
return -IPSET_ERR_PROTOCOL;
|
||||
if (nla_parse_nested_deprecated(tb, IPSET_ATTR_IPADDR_MAX, nla, ipaddr_policy, NULL))
|
||||
if (nla_parse_nested(tb, IPSET_ATTR_IPADDR_MAX, nla,
|
||||
ipaddr_policy, NULL))
|
||||
return -IPSET_ERR_PROTOCOL;
|
||||
if (unlikely(!ip_set_attr_netorder(tb, IPSET_ATTR_IPADDR_IPV4)))
|
||||
return -IPSET_ERR_PROTOCOL;
|
||||
|
@ -314,7 +315,8 @@ ip_set_get_ipaddr6(struct nlattr *nla, union nf_inet_addr *ipaddr)
|
|||
if (unlikely(!flag_nested(nla)))
|
||||
return -IPSET_ERR_PROTOCOL;
|
||||
|
||||
if (nla_parse_nested_deprecated(tb, IPSET_ATTR_IPADDR_MAX, nla, ipaddr_policy, NULL))
|
||||
if (nla_parse_nested(tb, IPSET_ATTR_IPADDR_MAX, nla,
|
||||
ipaddr_policy, NULL))
|
||||
return -IPSET_ERR_PROTOCOL;
|
||||
if (unlikely(!ip_set_attr_netorder(tb, IPSET_ATTR_IPADDR_IPV6)))
|
||||
return -IPSET_ERR_PROTOCOL;
|
||||
|
@ -934,7 +936,8 @@ static int ip_set_create(struct net *net, struct sock *ctnl,
|
|||
|
||||
/* Without holding any locks, create private part. */
|
||||
if (attr[IPSET_ATTR_DATA] &&
|
||||
nla_parse_nested_deprecated(tb, IPSET_ATTR_CREATE_MAX, attr[IPSET_ATTR_DATA], set->type->create_policy, NULL)) {
|
||||
nla_parse_nested(tb, IPSET_ATTR_CREATE_MAX, attr[IPSET_ATTR_DATA],
|
||||
set->type->create_policy, NULL)) {
|
||||
ret = -IPSET_ERR_PROTOCOL;
|
||||
goto put_out;
|
||||
}
|
||||
|
@ -1281,6 +1284,14 @@ dump_attrs(struct nlmsghdr *nlh)
|
|||
}
|
||||
}
|
||||
|
||||
static const struct nla_policy
|
||||
ip_set_dump_policy[IPSET_ATTR_CMD_MAX + 1] = {
|
||||
[IPSET_ATTR_PROTOCOL] = { .type = NLA_U8 },
|
||||
[IPSET_ATTR_SETNAME] = { .type = NLA_NUL_STRING,
|
||||
.len = IPSET_MAXNAMELEN - 1 },
|
||||
[IPSET_ATTR_FLAGS] = { .type = NLA_U32 },
|
||||
};
|
||||
|
||||
static int
|
||||
dump_init(struct netlink_callback *cb, struct ip_set_net *inst)
|
||||
{
|
||||
|
@ -1292,9 +1303,9 @@ dump_init(struct netlink_callback *cb, struct ip_set_net *inst)
|
|||
ip_set_id_t index;
|
||||
int ret;
|
||||
|
||||
ret = nla_parse_deprecated(cda, IPSET_ATTR_CMD_MAX, attr,
|
||||
nlh->nlmsg_len - min_len,
|
||||
ip_set_setname_policy, NULL);
|
||||
ret = nla_parse(cda, IPSET_ATTR_CMD_MAX, attr,
|
||||
nlh->nlmsg_len - min_len,
|
||||
ip_set_dump_policy, NULL);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
@ -1543,9 +1554,9 @@ call_ad(struct sock *ctnl, struct sk_buff *skb, struct ip_set *set,
|
|||
memcpy(&errmsg->msg, nlh, nlh->nlmsg_len);
|
||||
cmdattr = (void *)&errmsg->msg + min_len;
|
||||
|
||||
ret = nla_parse_deprecated(cda, IPSET_ATTR_CMD_MAX, cmdattr,
|
||||
nlh->nlmsg_len - min_len,
|
||||
ip_set_adt_policy, NULL);
|
||||
ret = nla_parse(cda, IPSET_ATTR_CMD_MAX, cmdattr,
|
||||
nlh->nlmsg_len - min_len, ip_set_adt_policy,
|
||||
NULL);
|
||||
|
||||
if (ret) {
|
||||
nlmsg_free(skb2);
|
||||
|
@ -1596,7 +1607,9 @@ static int ip_set_ad(struct net *net, struct sock *ctnl,
|
|||
|
||||
use_lineno = !!attr[IPSET_ATTR_LINENO];
|
||||
if (attr[IPSET_ATTR_DATA]) {
|
||||
if (nla_parse_nested_deprecated(tb, IPSET_ATTR_ADT_MAX, attr[IPSET_ATTR_DATA], set->type->adt_policy, NULL))
|
||||
if (nla_parse_nested(tb, IPSET_ATTR_ADT_MAX,
|
||||
attr[IPSET_ATTR_DATA],
|
||||
set->type->adt_policy, NULL))
|
||||
return -IPSET_ERR_PROTOCOL;
|
||||
ret = call_ad(ctnl, skb, set, tb, adt, flags,
|
||||
use_lineno);
|
||||
|
@ -1606,7 +1619,8 @@ static int ip_set_ad(struct net *net, struct sock *ctnl,
|
|||
nla_for_each_nested(nla, attr[IPSET_ATTR_ADT], nla_rem) {
|
||||
if (nla_type(nla) != IPSET_ATTR_DATA ||
|
||||
!flag_nested(nla) ||
|
||||
nla_parse_nested_deprecated(tb, IPSET_ATTR_ADT_MAX, nla, set->type->adt_policy, NULL))
|
||||
nla_parse_nested(tb, IPSET_ATTR_ADT_MAX, nla,
|
||||
set->type->adt_policy, NULL))
|
||||
return -IPSET_ERR_PROTOCOL;
|
||||
ret = call_ad(ctnl, skb, set, tb, adt,
|
||||
flags, use_lineno);
|
||||
|
@ -1655,7 +1669,8 @@ static int ip_set_utest(struct net *net, struct sock *ctnl, struct sk_buff *skb,
|
|||
if (!set)
|
||||
return -ENOENT;
|
||||
|
||||
if (nla_parse_nested_deprecated(tb, IPSET_ATTR_ADT_MAX, attr[IPSET_ATTR_DATA], set->type->adt_policy, NULL))
|
||||
if (nla_parse_nested(tb, IPSET_ATTR_ADT_MAX, attr[IPSET_ATTR_DATA],
|
||||
set->type->adt_policy, NULL))
|
||||
return -IPSET_ERR_PROTOCOL;
|
||||
|
||||
rcu_read_lock_bh();
|
||||
|
@ -1961,7 +1976,7 @@ static const struct nfnl_callback ip_set_netlink_subsys_cb[IPSET_MSG_MAX] = {
|
|||
[IPSET_CMD_LIST] = {
|
||||
.call = ip_set_dump,
|
||||
.attr_count = IPSET_ATTR_CMD_MAX,
|
||||
.policy = ip_set_setname_policy,
|
||||
.policy = ip_set_dump_policy,
|
||||
},
|
||||
[IPSET_CMD_SAVE] = {
|
||||
.call = ip_set_dump,
|
||||
|
@ -2069,8 +2084,9 @@ ip_set_sockfn_get(struct sock *sk, int optval, void __user *user, int *len)
|
|||
}
|
||||
|
||||
req_version->version = IPSET_PROTOCOL;
|
||||
ret = copy_to_user(user, req_version,
|
||||
sizeof(struct ip_set_req_version));
|
||||
if (copy_to_user(user, req_version,
|
||||
sizeof(struct ip_set_req_version)))
|
||||
ret = -EFAULT;
|
||||
goto done;
|
||||
}
|
||||
case IP_SET_OP_GET_BYNAME: {
|
||||
|
@ -2129,7 +2145,8 @@ ip_set_sockfn_get(struct sock *sk, int optval, void __user *user, int *len)
|
|||
} /* end of switch(op) */
|
||||
|
||||
copy:
|
||||
ret = copy_to_user(user, data, copylen);
|
||||
if (copy_to_user(user, data, copylen))
|
||||
ret = -EFAULT;
|
||||
|
||||
done:
|
||||
vfree(data);
|
||||
|
|
|
@ -209,7 +209,7 @@ hash_ipmac6_kadt(struct ip_set *set, const struct sk_buff *skb,
|
|||
(skb_mac_header(skb) + ETH_HLEN) > skb->data)
|
||||
return -EINVAL;
|
||||
|
||||
if (opt->flags & IPSET_DIM_ONE_SRC)
|
||||
if (opt->flags & IPSET_DIM_TWO_SRC)
|
||||
ether_addr_copy(e.ether, eth_hdr(skb)->h_source);
|
||||
else
|
||||
ether_addr_copy(e.ether, eth_hdr(skb)->h_dest);
|
||||
|
|
|
@ -368,6 +368,7 @@ static struct ip_set_type hash_net_type __read_mostly = {
|
|||
[IPSET_ATTR_IP_TO] = { .type = NLA_NESTED },
|
||||
[IPSET_ATTR_CIDR] = { .type = NLA_U8 },
|
||||
[IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
|
||||
[IPSET_ATTR_LINENO] = { .type = NLA_U32 },
|
||||
[IPSET_ATTR_CADT_FLAGS] = { .type = NLA_U32 },
|
||||
[IPSET_ATTR_BYTES] = { .type = NLA_U64 },
|
||||
[IPSET_ATTR_PACKETS] = { .type = NLA_U64 },
|
||||
|
|
|
@ -476,6 +476,7 @@ static struct ip_set_type hash_netnet_type __read_mostly = {
|
|||
[IPSET_ATTR_CIDR] = { .type = NLA_U8 },
|
||||
[IPSET_ATTR_CIDR2] = { .type = NLA_U8 },
|
||||
[IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
|
||||
[IPSET_ATTR_LINENO] = { .type = NLA_U32 },
|
||||
[IPSET_ATTR_CADT_FLAGS] = { .type = NLA_U32 },
|
||||
[IPSET_ATTR_BYTES] = { .type = NLA_U64 },
|
||||
[IPSET_ATTR_PACKETS] = { .type = NLA_U64 },
|
||||
|
|
|
@ -1922,6 +1922,7 @@ static int nf_tables_newchain(struct net *net, struct sock *nlsk,
|
|||
if (nlh->nlmsg_flags & NLM_F_REPLACE)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
flags |= chain->flags & NFT_BASE_CHAIN;
|
||||
return nf_tables_updchain(&ctx, genmask, policy, flags);
|
||||
}
|
||||
|
||||
|
@ -5143,9 +5144,6 @@ static int nf_tables_updobj(const struct nft_ctx *ctx,
|
|||
struct nft_trans *trans;
|
||||
int err;
|
||||
|
||||
if (!obj->ops->update)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
trans = nft_trans_alloc(ctx, NFT_MSG_NEWOBJ,
|
||||
sizeof(struct nft_trans_obj));
|
||||
if (!trans)
|
||||
|
@ -6499,7 +6497,8 @@ static void nft_obj_commit_update(struct nft_trans *trans)
|
|||
obj = nft_trans_obj(trans);
|
||||
newobj = nft_trans_obj_newobj(trans);
|
||||
|
||||
obj->ops->update(obj, newobj);
|
||||
if (obj->ops->update)
|
||||
obj->ops->update(obj, newobj);
|
||||
|
||||
kfree(newobj);
|
||||
}
|
||||
|
|
|
@ -334,7 +334,8 @@ int nft_flow_rule_offload_commit(struct net *net)
|
|||
|
||||
switch (trans->msg_type) {
|
||||
case NFT_MSG_NEWCHAIN:
|
||||
if (!(trans->ctx.chain->flags & NFT_CHAIN_HW_OFFLOAD))
|
||||
if (!(trans->ctx.chain->flags & NFT_CHAIN_HW_OFFLOAD) ||
|
||||
nft_trans_chain_update(trans))
|
||||
continue;
|
||||
|
||||
policy = nft_trans_chain_policy(trans);
|
||||
|
|
|
@ -134,12 +134,13 @@ static int nft_bitwise_offload(struct nft_offload_ctx *ctx,
|
|||
const struct nft_expr *expr)
|
||||
{
|
||||
const struct nft_bitwise *priv = nft_expr_priv(expr);
|
||||
struct nft_offload_reg *reg = &ctx->regs[priv->dreg];
|
||||
|
||||
if (memcmp(&priv->xor, &zero, sizeof(priv->xor)) ||
|
||||
priv->sreg != priv->dreg)
|
||||
priv->sreg != priv->dreg || priv->len != reg->len)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
memcpy(&ctx->regs[priv->dreg].mask, &priv->mask, sizeof(priv->mask));
|
||||
memcpy(®->mask, &priv->mask, sizeof(priv->mask));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -116,7 +116,7 @@ static int __nft_cmp_offload(struct nft_offload_ctx *ctx,
|
|||
u8 *mask = (u8 *)&flow->match.mask;
|
||||
u8 *key = (u8 *)&flow->match.key;
|
||||
|
||||
if (priv->op != NFT_CMP_EQ)
|
||||
if (priv->op != NFT_CMP_EQ || reg->len != priv->len)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
memcpy(key + reg->offset, &priv->data, priv->len);
|
||||
|
|
Loading…
Reference in New Issue