Merge 2b414a95b8 ("Merge tag 's390-7.1-5' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux") into android-mainline

Steps on the way to v7.1-rc8

Change-Id: Ie5d3d5bb80cf42a89f8b40b7a22af4db31cf8255
Signed-off-by: Carlos Llamas <cmllamas@google.com>
This commit is contained in:
Carlos Llamas committed 2026-06-14 13:14:25 +00:00
commit 3ff3e5e77c
80 files changed
+593 -290

No files matched your search

+3 -1
View File
@@ -39,7 +39,9 @@ ebt_dnat_tg(struct sk_buff *skb, const struct xt_action_param *par)
dev = xt_in(par);
break;
case NF_BR_PRE_ROUTING:
dev = br_port_get_rcu(xt_in(par))->br->dev;
dev = netdev_master_upper_dev_get_rcu(xt_in(par));
if (!dev) /* bridge port removed? */
return EBT_DROP;
break;
default:
dev = NULL;
+11 -5
View File
@@ -24,12 +24,18 @@ ebt_redirect_tg(struct sk_buff *skb, const struct xt_action_param *par)
if (skb_ensure_writable(skb, 0))
return EBT_DROP;
if (xt_hooknum(par) != NF_BR_BROUTING)
/* rcu_read_lock()ed by nf_hook_thresh */
ether_addr_copy(eth_hdr(skb)->h_dest,
br_port_get_rcu(xt_in(par))->br->dev->dev_addr);
else
if (xt_hooknum(par) != NF_BR_BROUTING) {
const struct net_device *dev;
dev = netdev_master_upper_dev_get_rcu(xt_in(par));
if (!dev)
return EBT_DROP;
ether_addr_copy(eth_hdr(skb)->h_dest, dev->dev_addr);
} else {
ether_addr_copy(eth_hdr(skb)->h_dest, xt_in(par)->dev_addr);
}
skb->pkt_type = PACKET_HOST;
return info->target;
}
+2
View File
@@ -64,6 +64,8 @@ static void nft_meta_bridge_get_eval(const struct nft_expr *expr,
if (!br_dev)
goto err;
/* ETH_ALEN (6) is shorter than the destination register span (8) */
dest[1] = 0;
memcpy(dest, br_dev->dev_addr, ETH_ALEN);
return;
default:
+5
View File
@@ -232,6 +232,11 @@ int skb_gro_receive_list(struct sk_buff *p, struct sk_buff *skb)
if (unlikely(p->len + skb->len >= 65536))
return -E2BIG;
if (!pskb_may_pull(skb, skb_gro_offset(skb))) {
NAPI_GRO_CB(skb)->flush = 1;
return -ENOMEM;
}
if (NAPI_GRO_CB(p)->last == p)
skb_shinfo(p)->frag_list = skb;
else
+1 -3
View File
@@ -1095,8 +1095,6 @@ int netdev_nl_bind_rx_doit(struct sk_buff *skb, struct genl_info *info)
genlmsg_end(rsp, hdr);
err = genlmsg_reply(rsp, info);
if (err)
goto err_unbind;
bitmap_free(rxq_bitmap);
@@ -1104,7 +1102,7 @@ int netdev_nl_bind_rx_doit(struct sk_buff *skb, struct genl_info *info)
mutex_unlock(&priv->lock);
return 0;
return err < 0 ? err : 0;
err_unbind:
net_devmem_unbind_dmabuf(binding);
+3 -3
View File
@@ -5450,7 +5450,7 @@ int skb_cow_data(struct sk_buff *skb, int tailbits, struct sk_buff **trailer)
}
EXPORT_SYMBOL_GPL(skb_cow_data);
static void sock_rmem_free(struct sk_buff *skb)
void sock_rmem_free(struct sk_buff *skb)
{
struct sock *sk = skb->sk;
@@ -5459,8 +5459,8 @@ static void sock_rmem_free(struct sk_buff *skb)
static void skb_set_err_queue(struct sk_buff *skb)
{
/* pkt_type of skbs received on local sockets is never PACKET_OUTGOING.
* So, it is safe to (mis)use it to mark skbs on the error queue.
/* The error-queue test in skb_is_err_queue() matches this marker
* with the sock_rmem_free destructor installed by sock_queue_err_skb().
*/
skb->pkt_type = PACKET_OUTGOING;
BUILD_BUG_ON(PACKET_OUTGOING == 0);
+5
View File
@@ -1466,6 +1466,11 @@ set_sndbuf:
case SO_ATTACH_FILTER: {
struct sock_fprog fprog;
if (sk_is_tcp(sk) &&
!sockopt_ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN)) {
ret = -EPERM;
break;
}
ret = copy_bpf_fprog_from_user(&fprog, optval, optlen);
if (!ret)
ret = sk_attach_filter(&fprog, sk);
+11 -6
View File
@@ -96,7 +96,7 @@ static inline struct scatterlist *esp_req_sg(struct crypto_aead *aead,
__alignof__(struct scatterlist));
}
static void esp_ssg_unref(struct xfrm_state *x, void *tmp, struct sk_buff *skb)
static void esp_ssg_unref(struct xfrm_state *x, void *tmp, struct sk_buff *skb, bool already_unref)
{
struct crypto_aead *aead = x->data;
int extralen = 0;
@@ -113,10 +113,13 @@ static void esp_ssg_unref(struct xfrm_state *x, void *tmp, struct sk_buff *skb)
/* Unref skb_frag_pages in the src scatterlist if necessary.
* Skip the first sg which comes from skb->data.
*/
if (req->src != req->dst)
for (sg = sg_next(req->src); sg; sg = sg_next(sg))
if (already_unref || req->src != req->dst) {
struct scatterlist *src = already_unref ? esp_req_sg(aead, req) : req->src;
for (sg = sg_next(src); sg; sg = sg_next(sg))
skb_page_unref(page_to_netmem(sg_page(sg)),
skb->pp_recycle);
}
}
#ifdef CONFIG_INET_ESPINTCP
@@ -220,7 +223,7 @@ static void esp_output_done(void *data, int err)
}
tmp = ESP_SKB_CB(skb)->tmp;
esp_ssg_unref(x, tmp, skb);
esp_ssg_unref(x, tmp, skb, false);
kfree(tmp);
if (xo && (xo->flags & XFRM_DEV_RESUME)) {
@@ -569,8 +572,10 @@ int esp_output_tail(struct xfrm_state *x, struct sk_buff *skb, struct esp_info *
err = skb_to_sgvec(skb, dsg,
(unsigned char *)esph - skb->data,
assoclen + ivlen + esp->clen + alen);
if (unlikely(err < 0))
if (unlikely(err < 0)) {
esp_ssg_unref(x, tmp, skb, true);
goto error_free;
}
}
if ((x->props.flags & XFRM_STATE_ESN))
@@ -602,7 +607,7 @@ int esp_output_tail(struct xfrm_state *x, struct sk_buff *skb, struct esp_info *
}
if (sg != dsg)
esp_ssg_unref(x, tmp, skb);
esp_ssg_unref(x, tmp, skb, false);
if (!err && x->encap && x->encap->encap_type == TCP_ENCAP_ESPINTCP)
err = esp_output_tail_tcp(x, skb);
+3
View File
@@ -328,6 +328,9 @@ void inet_frag_queue_flush(struct inet_frag_queue *q,
reason = reason ?: SKB_DROP_REASON_FRAG_REASM_TIMEOUT;
sum = inet_frag_rbtree_purge(&q->rb_fragments, reason);
sub_frag_mem_limit(q->fqdir, sum);
q->rb_fragments = RB_ROOT;
q->fragments_tail = NULL;
q->last_run_head = NULL;
}
EXPORT_SYMBOL(inet_frag_queue_flush);
-3
View File
@@ -250,9 +250,6 @@ static int ip_frag_reinit(struct ipq *qp)
qp->q.flags = 0;
qp->q.len = 0;
qp->q.meat = 0;
qp->q.rb_fragments = RB_ROOT;
qp->q.fragments_tail = NULL;
qp->q.last_run_head = NULL;
qp->iif = 0;
qp->ecn = 0;
+6 -9
View File
@@ -702,14 +702,12 @@ static int copy_entries_to_user(unsigned int total_size,
const struct xt_entry_target *t;
e = loc_cpu_entry + off;
if (copy_to_user(userptr + off, e, sizeof(*e))) {
ret = -EFAULT;
goto free_counters;
}
if (copy_to_user(userptr + off
if (copy_to_user(userptr + off, e,
offsetof(struct arpt_entry, counters)) ||
copy_to_user(userptr + off
+ offsetof(struct arpt_entry, counters),
&counters[num],
sizeof(counters[num])) != 0) {
sizeof(counters[num]))) {
ret = -EFAULT;
goto free_counters;
}
@@ -1327,9 +1325,8 @@ static int compat_copy_entry_to_user(struct arpt_entry *e, void __user **dstptr,
origsize = *size;
ce = *dstptr;
if (copy_to_user(ce, e, sizeof(struct arpt_entry)) != 0 ||
copy_to_user(&ce->counters, &counters[i],
sizeof(counters[i])) != 0)
if (copy_to_user(ce, e, offsetof(struct compat_arpt_entry, counters)) ||
copy_to_user(&ce->counters, &counters[i], sizeof(counters[i])))
return -EFAULT;
*dstptr += sizeof(struct compat_arpt_entry);
+6 -9
View File
@@ -832,14 +832,12 @@ copy_entries_to_user(unsigned int total_size,
const struct xt_entry_target *t;
e = loc_cpu_entry + off;
if (copy_to_user(userptr + off, e, sizeof(*e))) {
ret = -EFAULT;
goto free_counters;
}
if (copy_to_user(userptr + off
if (copy_to_user(userptr + off, e,
offsetof(struct ipt_entry, counters)) ||
copy_to_user(userptr + off
+ offsetof(struct ipt_entry, counters),
&counters[num],
sizeof(counters[num])) != 0) {
sizeof(counters[num]))) {
ret = -EFAULT;
goto free_counters;
}
@@ -1228,9 +1226,8 @@ compat_copy_entry_to_user(struct ipt_entry *e, void __user **dstptr,
origsize = *size;
ce = *dstptr;
if (copy_to_user(ce, e, sizeof(struct ipt_entry)) != 0 ||
copy_to_user(&ce->counters, &counters[i],
sizeof(counters[i])) != 0)
if (copy_to_user(ce, e, offsetof(struct compat_ipt_entry, counters)) ||
copy_to_user(&ce->counters, &counters[i], sizeof(counters[i])))
return -EFAULT;
*dstptr += sizeof(struct compat_ipt_entry);
+2
View File
@@ -555,6 +555,8 @@ static void __exit nf_nat_h323_fini(void)
nf_ct_helper_expectfn_unregister(&q931_nat);
nf_ct_helper_expectfn_unregister(&callforwarding_nat);
synchronize_rcu();
nf_ct_helper_expectfn_destroy(&q931_nat);
nf_ct_helper_expectfn_destroy(&callforwarding_nat);
}
/****************************************************************************/
+1 -1
View File
@@ -128,7 +128,7 @@ void nft_fib4_eval(const struct nft_expr *expr, struct nft_regs *regs,
fl4.saddr = get_saddr(iph->daddr);
}
*dest = 0;
nft_fib_store_result(dest, priv, NULL);
if (fib_lookup(nft_net(pkt), &fl4, &res, FIB_LOOKUP_IGNORE_LINKSTATE))
return;
+4 -2
View File
@@ -1267,6 +1267,7 @@ static void
cleanup_prefix_route(struct inet6_ifaddr *ifp, unsigned long expires,
bool del_rt, bool del_peer)
{
struct net *net = dev_net(ifp->idev->dev);
struct fib6_table *table;
struct fib6_info *f6i;
@@ -1275,9 +1276,10 @@ cleanup_prefix_route(struct inet6_ifaddr *ifp, unsigned long expires,
ifp->idev->dev, 0, RTF_DEFAULT, true);
if (f6i) {
if (del_rt)
ip6_del_rt(dev_net(ifp->idev->dev), f6i, false);
ip6_del_rt(net, f6i, false);
else {
if (!(f6i->fib6_flags & RTF_EXPIRES)) {
if (f6i != net->ipv6.fib6_null_entry &&
!(f6i->fib6_flags & RTF_EXPIRES)) {
table = f6i->fib6_table;
spin_lock_bh(&table->tb6_lock);
+11 -6
View File
@@ -113,7 +113,7 @@ static inline struct scatterlist *esp_req_sg(struct crypto_aead *aead,
__alignof__(struct scatterlist));
}
static void esp_ssg_unref(struct xfrm_state *x, void *tmp, struct sk_buff *skb)
static void esp_ssg_unref(struct xfrm_state *x, void *tmp, struct sk_buff *skb, bool already_unref)
{
struct crypto_aead *aead = x->data;
int extralen = 0;
@@ -130,10 +130,13 @@ static void esp_ssg_unref(struct xfrm_state *x, void *tmp, struct sk_buff *skb)
/* Unref skb_frag_pages in the src scatterlist if necessary.
* Skip the first sg which comes from skb->data.
*/
if (req->src != req->dst)
for (sg = sg_next(req->src); sg; sg = sg_next(sg))
if (already_unref || req->src != req->dst) {
struct scatterlist *src = already_unref ? esp_req_sg(aead, req) : req->src;
for (sg = sg_next(src); sg; sg = sg_next(sg))
skb_page_unref(page_to_netmem(sg_page(sg)),
skb->pp_recycle);
}
}
#ifdef CONFIG_INET6_ESPINTCP
@@ -254,7 +257,7 @@ static void esp_output_done(void *data, int err)
}
tmp = ESP_SKB_CB(skb)->tmp;
esp_ssg_unref(x, tmp, skb);
esp_ssg_unref(x, tmp, skb, false);
kfree(tmp);
esp_output_encap_csum(skb);
@@ -600,8 +603,10 @@ int esp6_output_tail(struct xfrm_state *x, struct sk_buff *skb, struct esp_info
err = skb_to_sgvec(skb, dsg,
(unsigned char *)esph - skb->data,
assoclen + ivlen + esp->clen + alen);
if (unlikely(err < 0))
if (unlikely(err < 0)) {
esp_ssg_unref(x, tmp, skb, true);
goto error_free;
}
}
if ((x->props.flags & XFRM_STATE_ESN))
@@ -634,7 +639,7 @@ int esp6_output_tail(struct xfrm_state *x, struct sk_buff *skb, struct esp_info
}
if (sg != dsg)
esp_ssg_unref(x, tmp, skb);
esp_ssg_unref(x, tmp, skb, false);
if (!err && x->encap && x->encap->encap_type == TCP_ENCAP_ESPINTCP)
err = esp_output_tail_tcp(x, skb);
+3
View File
@@ -106,6 +106,7 @@ vti6_tnl_lookup(struct net *net, const struct in6_addr *remote,
hash = HASH(&any, local);
for_each_vti6_tunnel_rcu(ip6n->tnls_r_l[hash]) {
if (ipv6_addr_equal(local, &t->parms.laddr) &&
ipv6_addr_any(&t->parms.raddr) &&
(t->dev->flags & IFF_UP))
return t;
}
@@ -113,6 +114,7 @@ vti6_tnl_lookup(struct net *net, const struct in6_addr *remote,
hash = HASH(remote, &any);
for_each_vti6_tunnel_rcu(ip6n->tnls_r_l[hash]) {
if (ipv6_addr_equal(remote, &t->parms.raddr) &&
ipv6_addr_any(&t->parms.laddr) &&
(t->dev->flags & IFF_UP))
return t;
}
@@ -1159,6 +1161,7 @@ static int __net_init vti6_init_net(struct net *net)
goto err_alloc_dev;
dev_net_set(ip6n->fb_tnl_dev, net);
ip6n->fb_tnl_dev->rtnl_link_ops = &vti6_link_ops;
ip6n->fb_tnl_dev->netns_immutable = true;
err = vti6_fb_tnl_dev_init(ip6n->fb_tnl_dev);
if (err < 0)
+6 -9
View File
@@ -848,14 +848,12 @@ copy_entries_to_user(unsigned int total_size,
const struct xt_entry_target *t;
e = loc_cpu_entry + off;
if (copy_to_user(userptr + off, e, sizeof(*e))) {
ret = -EFAULT;
goto free_counters;
}
if (copy_to_user(userptr + off
if (copy_to_user(userptr + off, e,
offsetof(struct ip6t_entry, counters)) ||
copy_to_user(userptr + off
+ offsetof(struct ip6t_entry, counters),
&counters[num],
sizeof(counters[num])) != 0) {
sizeof(counters[num]))) {
ret = -EFAULT;
goto free_counters;
}
@@ -1244,9 +1242,8 @@ compat_copy_entry_to_user(struct ip6t_entry *e, void __user **dstptr,
origsize = *size;
ce = *dstptr;
if (copy_to_user(ce, e, sizeof(struct ip6t_entry)) != 0 ||
copy_to_user(&ce->counters, &counters[i],
sizeof(counters[i])) != 0)
if (copy_to_user(ce, e, offsetof(struct compat_ip6t_entry, counters)) ||
copy_to_user(&ce->counters, &counters[i], sizeof(counters[i])))
return -EFAULT;
*dstptr += sizeof(struct compat_ip6t_entry);
+1 -1
View File
@@ -239,7 +239,7 @@ void nft_fib6_eval(const struct nft_expr *expr, struct nft_regs *regs,
lookup_flags = nft_fib6_flowi_init(&fl6, priv, pkt, oif, iph);
*dest = 0;
nft_fib_store_result(dest, priv, NULL);
ret = nft_fib6_lookup(nft_net(pkt), &fl6, &res, lookup_flags);
if (ret || res.fib6_flags & (RTF_REJECT | RTF_ANYCAST | RTF_LOCAL))
return;
+1
View File
@@ -961,6 +961,7 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb,
ip_rt_put(rt);
goto tx_error;
}
iph6 = ipv6_hdr(skb);
if (df) {
mtu = dst4_mtu(&rt->dst) - t_hlen;
+19
View File
@@ -283,6 +283,25 @@ void nf_ct_helper_expectfn_unregister(struct nf_ct_helper_expectfn *n)
}
EXPORT_SYMBOL_GPL(nf_ct_helper_expectfn_unregister);
static bool expect_iter_expectfn(struct nf_conntrack_expect *exp, void *data)
{
const struct nf_ct_helper_expectfn *n = data;
/* Relies on registered expectfn descriptors having unique ->expectfn
* pointers, which holds for the in-tree NAT helpers.
*/
return exp->expectfn == n->expectfn;
}
/* Destroy expectations still pointing at @n->expectfn; call after the
* caller's RCU grace period so none outlives the (often modular) callback.
*/
void nf_ct_helper_expectfn_destroy(const struct nf_ct_helper_expectfn *n)
{
nf_ct_expect_iterate_destroy(expect_iter_expectfn, (void *)n);
}
EXPORT_SYMBOL_GPL(nf_ct_helper_expectfn_destroy);
/* Caller should hold the rcu lock */
struct nf_ct_helper_expectfn *
nf_ct_helper_expectfn_find_by_name(const char *name)
+4 -2
View File
@@ -74,16 +74,18 @@ int nft_fwd_dup_netdev_offload(struct nft_offload_ctx *ctx,
struct flow_action_entry *entry;
struct net_device *dev;
/* nft_flow_rule_destroy() releases the reference on this device. */
dev = dev_get_by_index(ctx->net, oif);
if (!dev)
return -EOPNOTSUPP;
entry = nft_flow_action_entry_next(ctx, flow);
if (!entry)
if (!entry) {
dev_put(dev);
return -E2BIG;
}
entry->id = id;
/* nft_flow_rule_destroy() releases the reference on this device. */
entry->dev = dev;
return 0;
+2 -2
View File
@@ -815,8 +815,8 @@ static void dump_mac_header(struct nf_log_buf *m,
fallback:
nf_log_buf_add(m, "MAC=");
if (dev->hard_header_len &&
skb->mac_header != skb->network_header) {
if (dev->hard_header_len && skb_mac_header_was_set(skb) &&
skb_mac_header_len(skb) != 0) {
const unsigned char *p = skb_mac_header(skb);
unsigned int i;
+2
View File
@@ -1341,6 +1341,7 @@ static int __init nf_nat_init(void)
RCU_INIT_POINTER(nf_nat_hook, NULL);
nf_ct_helper_expectfn_unregister(&follow_master_nat);
synchronize_net();
nf_ct_helper_expectfn_destroy(&follow_master_nat);
unregister_pernet_subsys(&nat_net_ops);
kvfree(nf_nat_bysource);
}
@@ -1358,6 +1359,7 @@ static void __exit nf_nat_cleanup(void)
RCU_INIT_POINTER(nf_nat_hook, NULL);
synchronize_net();
nf_ct_helper_expectfn_destroy(&follow_master_nat);
kvfree(nf_nat_bysource);
unregister_pernet_subsys(&nat_net_ops);
}
+1
View File
@@ -655,6 +655,7 @@ static void __exit nf_nat_sip_fini(void)
RCU_INIT_POINTER(nf_nat_sip_hooks, NULL);
nf_ct_helper_expectfn_unregister(&sip_nat);
synchronize_rcu();
nf_ct_helper_expectfn_destroy(&sip_nat);
}
static const struct nf_nat_sip_hooks sip_hooks = {
+19 -4
View File
@@ -451,6 +451,23 @@ nla_put_failure:
return -1;
}
#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
static int nflog_put_master_ifindex(struct sk_buff *nlskb, int attr,
const struct net_device *dev)
{
const struct net_device *upper;
if (dev && !netif_is_bridge_port(dev))
return 0;
upper = netdev_master_upper_dev_get_rcu((struct net_device *)dev);
if (upper && nla_put_be32(nlskb, attr, htonl(upper->ifindex)))
return -EMSGSIZE;
return 0;
}
#endif
/* This is an inline function, we don't really care about a long
* list of arguments */
static inline int
@@ -505,8 +522,7 @@ __build_packet_message(struct nfnl_log_net *log,
/* rcu_read_lock()ed by nf_hook_thresh or
* nf_log_packet.
*/
nla_put_be32(inst->skb, NFULA_IFINDEX_INDEV,
htonl(br_port_get_rcu(indev)->br->dev->ifindex)))
nflog_put_master_ifindex(inst->skb, NFULA_IFINDEX_INDEV, indev))
goto nla_put_failure;
} else {
int physinif;
@@ -542,8 +558,7 @@ __build_packet_message(struct nfnl_log_net *log,
/* rcu_read_lock()ed by nf_hook_thresh or
* nf_log_packet.
*/
nla_put_be32(inst->skb, NFULA_IFINDEX_OUTDEV,
htonl(br_port_get_rcu(outdev)->br->dev->ifindex)))
nflog_put_master_ifindex(inst->skb, NFULA_IFINDEX_OUTDEV, outdev))
goto nla_put_failure;
} else {
struct net_device *physoutdev;
+56 -8
View File
@@ -440,10 +440,47 @@ static bool nf_ct_drop_unconfirmed(const struct nf_queue_entry *entry, bool *is_
return false;
}
static bool nf_bridge_port_valid(const struct net_device *dev)
{
if (!dev)
return true;
return netif_is_bridge_port(dev);
}
/* queued skbs leave rcu protection. We bump device refcount so that
* the device cannot go away. However, while packet was out the port
* could have been removed from the bridge.
*
* Ensure in+outdev are still part of a bridge at reinject time.
*
* The device rx_handler_data could even be pointing at data that is
* not a net_bridge_port structure.
*/
static bool nf_bridge_ports_valid(const struct nf_queue_entry *entry)
{
#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
if (!nf_bridge_port_valid(entry->physin) ||
!nf_bridge_port_valid(entry->physout))
return false;
#endif
if (entry->state.pf != PF_BRIDGE)
return true;
if (!nf_bridge_port_valid(entry->state.in) ||
!nf_bridge_port_valid(entry->state.out))
return false;
return true;
}
static void nfqnl_reinject(struct nf_queue_entry *entry, unsigned int verdict)
{
const struct nf_ct_hook *ct_hook;
if (!nf_bridge_ports_valid(entry))
verdict = NF_DROP;
if (verdict == NF_ACCEPT ||
verdict == NF_REPEAT ||
verdict == NF_STOP) {
@@ -636,6 +673,23 @@ static int nf_queue_checksum_help(struct sk_buff *entskb)
return skb_checksum_help(entskb);
}
#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
static int nfqnl_put_master_ifindex(struct sk_buff *nlskb, int attr,
const struct net_device *dev)
{
const struct net_device *upper;
if (dev && !netif_is_bridge_port(dev))
return 0;
upper = netdev_master_upper_dev_get_rcu((struct net_device *)dev);
if (upper && nla_put_be32(nlskb, attr, htonl(upper->ifindex)))
return -EMSGSIZE;
return 0;
}
#endif
static struct sk_buff *
nfqnl_build_packet_message(struct net *net, struct nfqnl_instance *queue,
struct nf_queue_entry *entry,
@@ -771,10 +825,7 @@ nfqnl_build_packet_message(struct net *net, struct nfqnl_instance *queue,
* netfilter_bridge) */
if (nla_put_be32(skb, NFQA_IFINDEX_PHYSINDEV,
htonl(indev->ifindex)) ||
/* this is the bridge group "brX" */
/* rcu_read_lock()ed by __nf_queue */
nla_put_be32(skb, NFQA_IFINDEX_INDEV,
htonl(br_port_get_rcu(indev)->br->dev->ifindex)))
nfqnl_put_master_ifindex(skb, NFQA_IFINDEX_INDEV, indev))
goto nla_put_failure;
} else {
int physinif;
@@ -805,10 +856,7 @@ nfqnl_build_packet_message(struct net *net, struct nfqnl_instance *queue,
* netfilter_bridge) */
if (nla_put_be32(skb, NFQA_IFINDEX_PHYSOUTDEV,
htonl(outdev->ifindex)) ||
/* this is the bridge group "brX" */
/* rcu_read_lock()ed by __nf_queue */
nla_put_be32(skb, NFQA_IFINDEX_OUTDEV,
htonl(br_port_get_rcu(outdev)->br->dev->ifindex)))
nfqnl_put_master_ifindex(skb, NFQA_IFINDEX_OUTDEV, outdev))
goto nla_put_failure;
} else {
int physoutif;
+3
View File
@@ -532,6 +532,9 @@ static int nft_exthdr_init(const struct nft_ctx *ctx,
return err;
}
if ((flags & NFT_EXTHDR_F_PRESENT) && len != 1)
return -EINVAL;
priv->type = nla_get_u8(tb[NFTA_EXTHDR_TYPE]);
priv->offset = offset;
priv->len = len;
+6
View File
@@ -107,6 +107,12 @@ int nft_fib_init(const struct nft_ctx *ctx, const struct nft_expr *expr,
return -EINVAL;
}
if (priv->flags & NFTA_FIB_F_PRESENT) {
if (priv->result != NFT_FIB_RESULT_OIF)
return -EINVAL;
len = sizeof(u8);
}
err = nft_parse_register_store(ctx, tb[NFTA_FIB_DREG], &priv->dreg,
NULL, NFT_DATA_VALUE, len);
if (err < 0)
+10 -20
View File
@@ -114,14 +114,14 @@ static struct genl_family netlbl_unlabel_gnl_family;
/* NetLabel Netlink attribute policy */
static const struct nla_policy netlbl_unlabel_genl_policy[NLBL_UNLABEL_A_MAX + 1] = {
[NLBL_UNLABEL_A_ACPTFLG] = { .type = NLA_U8 },
[NLBL_UNLABEL_A_IPV6ADDR] = { .type = NLA_BINARY,
.len = sizeof(struct in6_addr) },
[NLBL_UNLABEL_A_IPV6MASK] = { .type = NLA_BINARY,
.len = sizeof(struct in6_addr) },
[NLBL_UNLABEL_A_IPV4ADDR] = { .type = NLA_BINARY,
.len = sizeof(struct in_addr) },
[NLBL_UNLABEL_A_IPV4MASK] = { .type = NLA_BINARY,
.len = sizeof(struct in_addr) },
[NLBL_UNLABEL_A_IPV6ADDR] =
NLA_POLICY_EXACT_LEN(sizeof(struct in6_addr)),
[NLBL_UNLABEL_A_IPV6MASK] =
NLA_POLICY_EXACT_LEN(sizeof(struct in6_addr)),
[NLBL_UNLABEL_A_IPV4ADDR] =
NLA_POLICY_EXACT_LEN(sizeof(struct in_addr)),
[NLBL_UNLABEL_A_IPV4MASK] =
NLA_POLICY_EXACT_LEN(sizeof(struct in_addr)),
[NLBL_UNLABEL_A_IFACE] = { .type = NLA_NUL_STRING,
.len = IFNAMSIZ - 1 },
[NLBL_UNLABEL_A_SECCTX] = { .type = NLA_BINARY }
@@ -757,24 +757,14 @@ static int netlbl_unlabel_addrinfo_get(struct genl_info *info,
void **mask,
u32 *len)
{
u32 addr_len;
if (info->attrs[NLBL_UNLABEL_A_IPV4ADDR] &&
info->attrs[NLBL_UNLABEL_A_IPV4MASK]) {
addr_len = nla_len(info->attrs[NLBL_UNLABEL_A_IPV4ADDR]);
if (addr_len != sizeof(struct in_addr) &&
addr_len != nla_len(info->attrs[NLBL_UNLABEL_A_IPV4MASK]))
return -EINVAL;
*len = addr_len;
*len = sizeof(struct in_addr);
*addr = nla_data(info->attrs[NLBL_UNLABEL_A_IPV4ADDR]);
*mask = nla_data(info->attrs[NLBL_UNLABEL_A_IPV4MASK]);
return 0;
} else if (info->attrs[NLBL_UNLABEL_A_IPV6ADDR]) {
addr_len = nla_len(info->attrs[NLBL_UNLABEL_A_IPV6ADDR]);
if (addr_len != sizeof(struct in6_addr) &&
addr_len != nla_len(info->attrs[NLBL_UNLABEL_A_IPV6MASK]))
return -EINVAL;
*len = addr_len;
*len = sizeof(struct in6_addr);
*addr = nla_data(info->attrs[NLBL_UNLABEL_A_IPV6ADDR]);
*mask = nla_data(info->attrs[NLBL_UNLABEL_A_IPV6MASK]);
return 0;
+1
View File
@@ -1316,6 +1316,7 @@ static int ovs_flow_cmd_set(struct sk_buff *skb, struct genl_info *info)
if (IS_ERR(reply)) {
error = PTR_ERR(reply);
reply = NULL;
goto err_unlock_ovs;
}
}
+1 -1
View File
@@ -108,7 +108,7 @@ static void phonet_device_destroy(struct net_device *dev)
for_each_set_bit(addr, pnd->addrs, 64)
phonet_address_notify(net, RTM_DELADDR, ifindex, addr);
kfree(pnd);
kfree_rcu(pnd, rcu);
}
}
+2 -2
View File
@@ -707,13 +707,13 @@ static void qrtr_port_remove(struct qrtr_sock *ipc)
if (port == QRTR_PORT_CTRL)
port = 0;
__sock_put(&ipc->sk);
xa_erase(&qrtr_ports, port);
/* Ensure that if qrtr_port_lookup() did enter the RCU read section we
* wait for it to up increment the refcount */
synchronize_rcu();
__sock_put(&ipc->sk);
}
/* Assign port number to socket.
+2
View File
@@ -170,6 +170,8 @@ static struct rds_message *rds_ib_send_unmap_op(struct rds_ib_connection *ic,
break;
case IB_WR_ATOMIC_FETCH_AND_ADD:
case IB_WR_ATOMIC_CMP_AND_SWP:
case IB_WR_MASKED_ATOMIC_FETCH_AND_ADD:
case IB_WR_MASKED_ATOMIC_CMP_AND_SWP:
if (send->s_op) {
rm = container_of(send->s_op, struct rds_message, atomic);
rds_ib_send_unmap_atomic(ic, send->s_op, wc_status);
+1 -1
View File
@@ -235,7 +235,7 @@ call_func:
out:
if (pages)
unpin_user_pages(pages, nr_pages);
unpin_user_pages_dirty_lock(pages, nr_pages, true);
kfree(pages);
return ret;
+17 -9
View File
@@ -963,23 +963,34 @@ static void rxrpc_input_soft_acks(struct rxrpc_call *call,
struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
struct rxrpc_txqueue *tq = call->tx_queue;
unsigned long extracted = ~0UL;
unsigned int nr = 0;
unsigned int nr = 0, nsack;
rxrpc_seq_t seq = call->acks_hard_ack + 1;
rxrpc_seq_t lowest_nak = seq + sp->ack.nr_acks;
u8 *acks = skb->data + sizeof(struct rxrpc_wire_header) + sizeof(struct rxrpc_ackpacket);
u8 sack[256] __aligned(sizeof(unsigned long));
u8 *acks = sack;
_enter("%x,%x,%u", tq->qbase, seq, sp->ack.nr_acks);
while (after(seq, tq->qbase + RXRPC_NR_TXQUEUE - 1))
tq = tq->next;
/* Extract an individual SACK table. A normal SACK table is up to 255
* bytes with 1 ACK flag per byte, but an extended SACK table can be up
* to 256 bytes with up to 8 ACK/NACK flags per byte. The ACK flags go
* across all bit 0's then all bit 1's, then all bit 2's, ...
*/
memset(sack, 0, sizeof(sack));
nsack = umin(sp->ack.nr_acks, 256);
if (skb_copy_bits(skb,
sizeof(struct rxrpc_wire_header) + sizeof(struct rxrpc_ackpacket),
sack, nsack) < 0)
return;
for (unsigned int i = 0; i < sp->ack.nr_acks; i++) {
/* Decant ACKs until we hit a txqueue boundary. */
if ((i & 255) == 0)
acks = sack;
shiftr_adv_rotr(acks, extracted);
if (i == 256) {
acks -= i;
i = 0;
}
seq++;
nr++;
if ((seq & RXRPC_TXQ_MASK) != 0)
@@ -1117,9 +1128,6 @@ static void rxrpc_input_ack(struct rxrpc_call *call, struct sk_buff *skb)
skb_copy_bits(skb, ioffset, &trailer, sizeof(trailer)) < 0)
return rxrpc_proto_abort(call, 0, rxrpc_badmsg_short_ack_trailer);
if (nr_acks > 0)
skb_condense(skb);
call->acks_latest_ts = ktime_get_real();
call->acks_hard_ack = hard_ack;
call->acks_prev_seq = prev_pkt;
+10 -1
View File
@@ -275,6 +275,16 @@ int sctp_raw_to_bind_addrs(struct sctp_bind_addr *bp, __u8 *raw_addr_list,
param = (struct sctp_paramhdr *)raw_addr_list;
rawaddr = (union sctp_addr_param *)raw_addr_list;
if (addrs_len < sizeof(*param)) {
retval = -EINVAL;
goto out_err;
}
len = ntohs(param->length);
if (addrs_len < len) {
retval = -EINVAL;
goto out_err;
}
af = sctp_get_af_specific(param_type2af(param->type));
if (unlikely(!af) ||
!af->from_addr_param(&addr, rawaddr, htons(port), 0)) {
@@ -291,7 +301,6 @@ int sctp_raw_to_bind_addrs(struct sctp_bind_addr *bp, __u8 *raw_addr_list,
goto out_err;
next:
len = ntohs(param->length);
addrs_len -= len;
raw_addr_list += len;
}
+8
View File
@@ -1204,6 +1204,14 @@ static struct sctp_association *__sctp_rcv_asconf_lookup(
/* Skip over the ADDIP header and find the Address parameter */
param = (union sctp_addr_param *)(asconf + 1);
/* The whole address parameter must lie within the chunk before
* af->from_addr_param() reads the variable-length address; otherwise a
* truncated trailing ASCONF chunk lets it read uninitialized bytes past
* the parameter.
*/
if (sizeof(*asconf) + ntohs(param->p.length) > ntohs(ch->length))
return NULL;
af = sctp_get_af_specific(param_type2af(param->p.type));
if (unlikely(!af))
return NULL;
+7 -2
View File
@@ -1731,8 +1731,8 @@ struct sctp_association *sctp_unpack_cookie(
struct sk_buff *skb = chunk->skb;
struct sctp_cookie *bear_cookie;
struct sctp_chunkhdr *ch;
unsigned int len, chlen;
enum sctp_scope scope;
unsigned int len;
ktime_t kt;
/* Header size is static data prior to the actual cookie, including
@@ -1761,7 +1761,12 @@ struct sctp_association *sctp_unpack_cookie(
bear_cookie = &cookie->c;
ch = (struct sctp_chunkhdr *)(bear_cookie + 1);
if (ntohs(ch->length) > len - fixed_size)
chlen = ntohs(ch->length);
if (chlen < sizeof(struct sctp_init_chunk))
goto malformed;
if (chlen > len - fixed_size)
goto malformed;
if (bear_cookie->raw_addr_list_len > len - fixed_size - chlen)
goto malformed;
/* Verify the cookie's MAC, if cookie authentication is enabled. */
+5 -1
View File
@@ -1038,6 +1038,7 @@ struct sctp_chunk *sctp_process_strreset_resp(
stsn, rtsn, GFP_ATOMIC);
} else if (req->type == SCTP_PARAM_RESET_ADD_OUT_STREAMS) {
struct sctp_strreset_addstrm *addstrm;
const struct sctp_sched_ops *sched;
__u16 number;
addstrm = (struct sctp_strreset_addstrm *)req;
@@ -1048,7 +1049,10 @@ struct sctp_chunk *sctp_process_strreset_resp(
for (i = number; i < stream->outcnt; i++)
SCTP_SO(stream, i)->state = SCTP_STREAM_OPEN;
} else {
sctp_stream_shrink_out(stream, number);
sched = sctp_sched_ops_from_stream(stream);
sched->unsched_all(stream);
sctp_stream_outq_migrate(stream, NULL, number);
sched->sched_all(stream);
stream->outcnt = number;
}
+6 -5
View File
@@ -852,12 +852,13 @@ EXPORT_SYMBOL(kernel_sendmsg);
static bool skb_is_err_queue(const struct sk_buff *skb)
{
/* pkt_type of skbs enqueued on the error queue are set to
* PACKET_OUTGOING in skb_set_err_queue(). This is only safe to do
* in recvmsg, since skbs received on a local socket will never
* have a pkt_type of PACKET_OUTGOING.
/* Error-queue skbs are marked as PACKET_OUTGOING in
* skb_set_err_queue() and use the destructor installed by
* sock_queue_err_skb(). PACKET_OUTGOING alone is not unique:
* AF_PACKET outgoing taps use the same pkt_type.
*/
return skb->pkt_type == PACKET_OUTGOING;
return skb->pkt_type == PACKET_OUTGOING &&
skb->destructor == sock_rmem_free;
}
/* On transmit, software and hardware timestamps are returned independently.
+4
View File
@@ -346,6 +346,10 @@ static int espintcp_sendmsg(struct sock *sk, struct msghdr *msg, size_t size)
err = -ENOBUFS;
goto unlock;
}
if (emsg->len) {
err = -ENOBUFS;
goto unlock;
}
sk_msg_init(&emsg->skmsg);
while (1) {
+7 -4
View File
@@ -954,6 +954,7 @@ static bool __input_process_payload(struct xfrm_state *x, u32 data,
u32 first_iplen, iphlen, iplen, remaining, tail;
u32 capturelen;
u64 seq;
bool first_skb_partial = false;
xtfs = x->mode_data;
net = xs_net(x);
@@ -1161,6 +1162,7 @@ static bool __input_process_payload(struct xfrm_state *x, u32 data,
spin_unlock(&xtfs->drop_lock);
first_skb_partial = (first_skb == skb);
break;
}
@@ -1172,7 +1174,7 @@ static bool __input_process_payload(struct xfrm_state *x, u32 data,
/* this should not happen from the above code */
XFRM_INC_STATS(net, LINUX_MIB_XFRMINIPTFSERROR);
if (first_skb && first_iplen && !defer && first_skb != xtfs->ra_newskb) {
if (first_skb && first_iplen && !defer && !first_skb_partial) {
/* first_skb is queued b/c !defer and not partial */
if (pskb_trim(first_skb, first_iplen)) {
/* error trimming */
@@ -2168,6 +2170,8 @@ static void iptfs_consume_frags(struct sk_buff *to, struct sk_buff *from)
memcpy(&toi->frags[toi->nr_frags], fromi->frags,
sizeof(fromi->frags[0]) * fromi->nr_frags);
toi->nr_frags += fromi->nr_frags;
if (fromi->nr_frags)
toi->flags |= fromi->flags & SKBFL_SHARED_FRAG;
fromi->nr_frags = 0;
from->data_len = 0;
from->len = 0;
@@ -2726,8 +2730,9 @@ static void iptfs_destroy_state(struct xfrm_state *x)
if (!xtfs)
return;
spin_lock_bh(&xtfs->x->lock);
hrtimer_cancel(&xtfs->iptfs_timer);
spin_lock_bh(&xtfs->x->lock);
__skb_queue_head_init(&list);
skb_queue_splice_init(&xtfs->queue, &list);
spin_unlock_bh(&xtfs->x->lock);
@@ -2735,9 +2740,7 @@ static void iptfs_destroy_state(struct xfrm_state *x)
while ((skb = __skb_dequeue(&list)))
kfree_skb(skb);
spin_lock_bh(&xtfs->drop_lock);
hrtimer_cancel(&xtfs->drop_timer);
spin_unlock_bh(&xtfs->drop_lock);
if (xtfs->ra_newskb)
kfree_skb(xtfs->ra_newskb);
+2 -11
View File
@@ -1156,15 +1156,6 @@ static void __xfrm_policy_inexact_prune_bin(struct xfrm_pol_inexact_bin *b, bool
}
}
static void xfrm_policy_inexact_prune_bin(struct xfrm_pol_inexact_bin *b)
{
struct net *net = read_pnet(&b->k.net);
spin_lock_bh(&net->xfrm.xfrm_policy_lock);
__xfrm_policy_inexact_prune_bin(b, false);
spin_unlock_bh(&net->xfrm.xfrm_policy_lock);
}
static void __xfrm_policy_inexact_flush(struct net *net)
{
struct xfrm_pol_inexact_bin *bin, *t;
@@ -1707,12 +1698,12 @@ xfrm_policy_bysel_ctx(struct net *net, const struct xfrm_mark *mark, u32 if_id,
}
ret = pol;
}
if (bin && delete)
__xfrm_policy_inexact_prune_bin(bin, false);
spin_unlock_bh(&net->xfrm.xfrm_policy_lock);
if (ret && delete)
xfrm_policy_kill(ret);
if (bin && delete)
xfrm_policy_inexact_prune_bin(bin);
return ret;
}
EXPORT_SYMBOL(xfrm_policy_bysel_ctx);