5.5.14-rc1 review
Subsystems (2)
Greg Kroah-Hartman
maintainerPATCH 130/170 afs: Fix client call Rx-phase signal handling
In reply to Greg Kroah-HartmanFrom: David Howells <[email protected]>
commit 7d7587db0d7fd1138f2afcffdc46a8e15630b944 upstream.
Fix the handling of signals in client rxrpc calls made by the afs filesystem. Ignore signals completely, leaving call abandonment or connection loss to be detected by timeouts inside AF_RXRPC.
Allowing a filesystem call to be interrupted after the entire request has been transmitted and an abort sent means that the server may or may not have done the action - and we don't know. It may even be worse than that for older servers.
--- fs/afs/rxrpc.c | 34 ++-------------------------------- include/net/af_rxrpc.h | 4 +--- net/rxrpc/af_rxrpc.c | 33 +++------------------------------ net/rxrpc/ar-internal.h | 1 - net/rxrpc/input.c | 1 - 5 files changed, 6 insertions(+), 67 deletions(-)
fs/afs/rxrpc.c +2 -32
@@ -603,11 +603,7 @@ call_complete:long afs_wait_for_call_to_complete (struct afs_call *call,struct afs_addr_cursor *ac) { -signed long rtt2, timeout;long ret; -bool stalled = false; -u64 rtt; -u32 life, last_life;bool rxrpc_complete = false;DECLARE_WAITQUEUE (myself, current);
@@ -618,14 +614,6 @@ long afs_wait_for_call_to_complete(strucif (ret <0 ) goto out; - rtt =rxrpc_kernel_get_rtt (call->net->socket, call->rxcall); - rtt2 =nsecs_to_jiffies64 (rtt) *2 ; -if (rtt2 <2 ) - rtt2 =2 ; - - timeout = rtt2; -rxrpc_kernel_check_life (call->net->socket, call->rxcall, &last_life); -add_wait_queue (&call->waitq, &myself);for (;;) {set_current_state (TASK_UNINTERRUPTIBLE );
@@ -636,37 +624,19 @@ long afs_wait_for_call_to_complete(struc call->need_attention = false;__set_current_state (TASK_RUNNING );afs_deliver_to_call (call); - timeout = rtt2;continue ; }if (afs_check_call_state (call,AFS_CALL_COMPLETE ))break ; -if (!rxrpc_kernel_check_life (call->net->socket, call->rxcall, &life)) { +if (!rxrpc_kernel_check_life (call->net->socket, call->rxcall)) {/* rxrpc terminated the call. */ rxrpc_complete = true;break ; } -if (call->intr && timeout ==0 && - life == last_life &&signal_pending (current)) { -if (stalled) -break ; -__set_current_state (TASK_RUNNING ); -rxrpc_kernel_probe_life (call->net->socket, call->rxcall); - timeout = rtt2; - stalled = true; -continue ; - } - -if (life != last_life) { - timeout = rtt2; - last_life = life; - stalled = false; - } - - timeout =schedule_timeout (timeout); +schedule (); }remove_wait_queue (&call->waitq, &myself);
include/net/af_rxrpc.h +1 -3
@@ -58,9 +58,7 @@ int rxrpc_kernel_charge_accept(struct so rxrpc_user_attach_call_t, unsigned long, gfp_t, unsigned int);void rxrpc_kernel_set_tx_length (struct socket *,struct rxrpc_call *,s64 ); -bool rxrpc_kernel_check_life (const struct socket *,const struct rxrpc_call *, -u32 *); -void rxrpc_kernel_probe_life (struct socket *,struct rxrpc_call *); +bool rxrpc_kernel_check_life (const struct socket *,const struct rxrpc_call *);u32 rxrpc_kernel_get_epoch (struct socket *,struct rxrpc_call *);bool rxrpc_kernel_get_reply_time (struct socket *,struct rxrpc_call *,ktime_t *);
net/rxrpc/af_rxrpc.c +3 -30
@@ -371,45 +371,18 @@ EXPORT_SYMBOL(rxrpc_kernel_end_call);* rxrpc_kernel_check_life - Check to see whether a call is still alive * @sock: The socket the call is on * @call: The call to check -* @_life: Where to store the life value * -* Allow a kernel service to find out whether a call is still alive - ie. we're -* getting ACKs from the server. Passes back in *_life a number representing -* the life state which can be compared to that returned by a previous call and -* return true if the call is still alive. -* -* If the life state stalls, rxrpc_kernel_probe_life() should be called and -* then 2RTT waited. +* Allow a kernel service to find out whether a call is still alive - +* ie. whether it has completed. */ bool rxrpc_kernel_check_life (const struct socket *sock, -const struct rxrpc_call *call, -u32 *_life) +const struct rxrpc_call *call) { - *_life = call->acks_latest;return call->state !=RXRPC_CALL_COMPLETE ; }EXPORT_SYMBOL (rxrpc_kernel_check_life);/** -* rxrpc_kernel_probe_life - Poke the peer to see if it's still alive -* @sock: The socket the call is on -* @call: The call to check -* -* In conjunction with rxrpc_kernel_check_life(), allow a kernel service to -* find out whether a call is still alive by pinging it. This should cause the -* life state to be bumped in about 2*RTT. -* -* The must be called in TASK_RUNNING state on pain of might_sleep() objecting. -*/ -void rxrpc_kernel_probe_life (struct socket *sock,struct rxrpc_call *call) -{ -rxrpc_propose_ACK (call,RXRPC_ACK_PING ,0 , true, false, - rxrpc_propose_ack_ping_for_check_life); -rxrpc_send_ack_packet (call, true,NULL ); -} -EXPORT_SYMBOL (rxrpc_kernel_probe_life); - -/** * rxrpc_kernel_get_epoch - Retrieve the epoch value from a call. * @sock: The socket the call is on * @call: The call to query
net/rxrpc/ar-internal.h +0 -1
@@ -675,7 +675,6 @@ struct rxrpc_call {/* transmission-phase ACK management */ ktime_t acks_latest_ts;/* Timestamp of latest ACK received */ -rxrpc_serial_t acks_latest;/* serial number of latest ACK received */ rxrpc_seq_t acks_lowest_nak;/* Lowest NACK in the buffer (or ==tx_hard_ack) */ rxrpc_seq_t acks_lost_top;/* tx_top at the time lost-ack ping sent */ rxrpc_serial_t acks_lost_ping;/* Serial number of probe ACK */
net/rxrpc/input.c +0 -1
@@ -882,7 +882,6 @@ static void rxrpc_input_ack(struct rxrpc before(prev_pkt, call->ackr_prev_seq)) goto out; call->acks_latest_ts = skb->tstamp; - call->acks_latest = sp->hdr.serial; call->ackr_first_seq = first_soft_ack; call->ackr_prev_seq = prev_pkt;
Greg Kroah-Hartman
maintainerPATCH 131/170 afs: Fix some tracing details
In reply to Greg Kroah-HartmanFrom: David Howells <[email protected]>
commit 4636cf184d6d9a92a56c2554681ea520dd4fe49a upstream.
Fix a couple of tracelines to indicate the usage count after the atomic op, not the usage count before it to be consistent with other afs and rxrpc trace lines.
Change the wording of the afs_call_trace_work trace ID label from "WORK" to "QUEUE" to reflect the fact that it's queueing work, not doing work.
--- fs/afs/rxrpc.c | 4 ++-- include/trace/events/afs.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-)
fs/afs/rxrpc.c +2 -2
@@ -168,7 +168,7 @@ void afs_put_call(struct afs_call *call)int n =atomic_dec_return (&call->usage);int o =atomic_read (&net->nr_outstanding_calls); -trace_afs_call (call, afs_call_trace_put, n +1 , o, +trace_afs_call (call, afs_call_trace_put, n, o,__builtin_return_address (0 )); ASSERTCMP(n, >=, 0);
@@ -704,7 +704,7 @@ static void afs_wake_up_async_call(struc u =atomic_fetch_add_unless (&call->usage,1 ,0 );if (u !=0 ) { -trace_afs_call (call, afs_call_trace_wake, u, +trace_afs_call (call, afs_call_trace_wake, u +1 ,atomic_read (&call->net->nr_outstanding_calls),__builtin_return_address (0 ));
include/trace/events/afs.h +1 -1
@@ -233,7 +233,7 @@ enum afs_cb_break_reason { EM(afs_call_trace_get, "GET ") \ EM(afs_call_trace_put, "PUT ") \ EM(afs_call_trace_wake, "WAKE ") \ - E_(afs_call_trace_work, "WORK ") + E_(afs_call_trace_work, "QUEUE")#define afs_server_traces \ EM(afs_server_trace_alloc, "ALLOC ") \
Greg Kroah-Hartman
maintainerPATCH 132/170 afs: Fix unpinned address list during probing
In reply to Greg Kroah-HartmanFrom: David Howells <[email protected]>
commit 9efcc4a129363187c9bf15338692f107c5c9b6f0 upstream.
When it's probing all of a fileserver's interfaces to find which one is best to use, afs_do_probe_fileserver() takes a lock on the server record and notes the pointer to the address list.
It doesn't, however, pin the address list, so as soon as it drops the lock, there's nothing to stop the address list from being freed under us.
Fix this by taking a ref on the address list inside the locked section and dropping it at the end of the function.
--- fs/afs/fs_probe.c | 2 ++ 1 file changed, 2 insertions(+)
fs/afs/fs_probe.c +2 -0
@@ -145,6 +145,7 @@ static int afs_do_probe_fileserver(strucread_lock (&server->fs_lock); ac.alist =rcu_dereference_protected (server->addresses,lockdep_is_held (&server->fs_lock)); +afs_get_addrlist (ac.alist);read_unlock (&server->fs_lock);atomic_set (&server->probe_outstanding, ac.alist->nr_addrs);
@@ -163,6 +164,7 @@ static int afs_do_probe_fileserver(strucif (!in_progress)afs_fs_probe_done (server); +afs_put_addrlist (ac.alist);return in_progress; }
Greg Kroah-Hartman
maintainerPATCH 133/170 ieee80211: fix HE SPR size calculation
In reply to Greg Kroah-HartmanFrom: Johannes Berg <[email protected]>
commit 575a97acc3b7446094b0dcaf6285c7c6934c2477 upstream.
The he_sr_control field is just a u8, so le32_to_cpu() shouldn't be applied to it; this was evidently copied from ieee80211_he_oper_size(). Fix it, and also adjust the type of the local variable.
--- include/linux/ieee80211.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
include/linux/ieee80211.h +2 -2
@@ -2102,14 +2102,14 @@ ieee80211_he_spr_size(const u8 *he_spr_i {struct ieee80211_he_spr *he_spr = (void *)he_spr_ie;u8 spr_len =sizeof (struct ieee80211_he_spr ); -u32 he_spr_params; +u8 he_spr_params;/* Make sure the input is not NULL */ if (!he_spr_ie)return 0 ;/* Calc required length */ - he_spr_params =le32_to_cpu (he_spr->he_sr_control); + he_spr_params = he_spr->he_sr_control;if (he_spr_params &IEEE80211_HE_SPR_NON_SRG_OFFSET_PRESENT ) spr_len++;if (he_spr_params &IEEE80211_HE_SPR_SRG_INFORMATION_PRESENT )
Greg Kroah-Hartman
maintainerPATCH 134/170 mac80211: set IEEE80211_TX_CTRL_PORT_CTRL_PROTO for nl80211 TX
In reply to Greg Kroah-HartmanFrom: Johannes Berg <[email protected]>
commit b95d2ccd2ccb834394d50347d0e40dc38a954e4a upstream.
When a frame is transmitted via the nl80211 TX rather than as a normal frame, IEEE80211_TX_CTRL_PORT_CTRL_PROTO wasn't set and this will lead to wrong decisions (rate control etc.) being made about the frame; fix this.
--- net/mac80211/tx.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-)
net/mac80211/tx.c +6 -2
@@ -5,7 +5,7 @@* Copyright 2006-2007 Jiri Benc <[email protected]> * Copyright 2007 Johannes Berg <[email protected]> * Copyright 2013-2014 Intel Mobile Communications GmbH -* Copyright (C) 2018 Intel Corporation +* Copyright (C) 2018, 2020 Intel Corporation * * Transmit and frame generation functions. */
@@ -5135,6 +5135,7 @@ int ieee80211_tx_control_port(struct wipstruct ieee80211_local *local = sdata->local;struct sk_buff *skb;struct ethhdr *ehdr; +u32 ctrl_flags =0 ;u32 flags;/* Only accept CONTROL_PORT_PROTOCOL configured in CONNECT/ASSOCIATE
@@ -5144,6 +5145,9 @@ int ieee80211_tx_control_port(struct wip proto != cpu_to_be16(ETH_P_PREAUTH))return -EINVAL ; +if (proto == sdata->control_port_protocol) + ctrl_flags |=IEEE80211_TX_CTRL_PORT_CTRL_PROTO ; +if (unencrypted) flags =IEEE80211_TX_INTFL_DONT_ENCRYPT ;else
@@ -5169,7 +5173,7 @@ int ieee80211_tx_control_port(struct wipskb_reset_mac_header (skb);local_bh_disable (); -__ieee80211_subif_start_xmit (skb, skb->dev, flags,0 ); +__ieee80211_subif_start_xmit (skb, skb->dev, flags, ctrl_flags);local_bh_enable ();return 0 ;
Greg Kroah-Hartman
maintainerPATCH 135/170 netfilter: flowtable: reload ip{v6}h in nf_flow_tuple_ip{v6}
In reply to Greg Kroah-HartmanFrom: Haishuang Yan <[email protected]>
commit 41e9ec5a54f95eee1a57c8d26ab70e0492548c1b upstream.
Since pskb_may_pull may change skb->data, so we need to reload ip{v6}h at the right place.
--- net/netfilter/nf_flow_table_ip.c | 2 ++ 1 file changed, 2 insertions(+)
net/netfilter/nf_flow_table_ip.c +2 -0
@@ -189,6 +189,7 @@ static int nf_flow_tuple_ip(struct sk_buif (!pskb_may_pull (skb, thoff +sizeof (*ports)))return -1 ; + iph =ip_hdr (skb); ports = (struct flow_ports *)(skb_network_header (skb) + thoff); tuple->src_v4.s_addr = iph->saddr;
@@ -449,6 +450,7 @@ static int nf_flow_tuple_ipv6(struct sk_if (!pskb_may_pull (skb, thoff +sizeof (*ports)))return -1 ; + ip6h =ipv6_hdr (skb); ports = (struct flow_ports *)(skb_network_header (skb) + thoff); tuple->src_v6 = ip6h->saddr;
Greg Kroah-Hartman
maintainerPATCH 136/170 netfilter: flowtable: populate addr_type mask
In reply to Greg Kroah-HartmanFrom: Edward Cree <[email protected]>
commit 15ff197237e76c4dab06b7b518afaa4ebb1c43e0 upstream.
nf_flow_rule_match() sets control.addr_type in key, so needs to also set
the corresponding mask. An exact match is wanted, so mask is all ones.
--- net/netfilter/nf_flow_table_offload.c | 1 + 1 file changed, 1 insertion(+)
net/netfilter/nf_flow_table_offload.c +1 -0
@@ -87,6 +87,7 @@ static int nf_flow_rule_match(struct nf_default :return -EOPNOTSUPP ; } + mask->control.addr_type =0xffff ; match->dissector.used_keys |=BIT (key->control.addr_type); mask->basic.n_proto =0xffff ;
Greg Kroah-Hartman
maintainerPATCH 137/170 netfilter: nft_fwd_netdev: validate family and chain type
In reply to Greg Kroah-HartmanFrom: Pablo Neira Ayuso <[email protected]>
commit 76a109fac206e158eb3c967af98c178cff738e6a upstream.
Make sure the forward action is only used from ingress.
--- net/netfilter/nft_fwd_netdev.c | 9 +++++++++ 1 file changed, 9 insertions(+)
net/netfilter/nft_fwd_netdev.c +9 -0
@@ -190,6 +190,13 @@ nla_put_failure:return -1 ; } +static int nft_fwd_validate (const struct nft_ctx *ctx, +const struct nft_expr *expr, +const struct nft_data **data) +{ +return nft_chain_validate_hooks (ctx->chain, (1 <<NF_NETDEV_INGRESS )); +} +static struct nft_expr_type nft_fwd_netdev_type;static const struct nft_expr_ops nft_fwd_neigh_netdev_ops = { .type = &nft_fwd_netdev_type,
@@ -197,6 +204,7 @@ static const struct nft_expr_ops nft_fwd .eval = nft_fwd_neigh_eval, .init = nft_fwd_neigh_init, .dump = nft_fwd_neigh_dump, + .validate = nft_fwd_validate, };static const struct nft_expr_ops nft_fwd_netdev_ops = {
@@ -205,6 +213,7 @@ static const struct nft_expr_ops nft_fwd .eval = nft_fwd_netdev_eval, .init = nft_fwd_netdev_init, .dump = nft_fwd_netdev_dump, + .validate = nft_fwd_validate, .offload = nft_fwd_netdev_offload, };
Greg Kroah-Hartman
maintainerPATCH 138/170 netfilter: nft_fwd_netdev: allow to redirect to ifb via ingress
In reply to Greg Kroah-HartmanFrom: Pablo Neira Ayuso <[email protected]>
commit bcfabee1afd99484b6ba067361b8678e28bbc065 upstream.
Set skb->tc_redirected to 1, otherwise the ifb driver drops the packet. Set skb->tc_from_ingress to 1 to reinject the packet back to the ingress path after leaving the ifb egress path.
This patch inconditionally sets on these two skb fields that are meaningful to the ifb driver. The existing forward action is guaranteed to run from ingress path.
--- net/netfilter/nft_fwd_netdev.c | 4 ++++ 1 file changed, 4 insertions(+)
net/netfilter/nft_fwd_netdev.c +4 -0
@@ -28,6 +28,10 @@ static void nft_fwd_netdev_eval(const ststruct nft_fwd_netdev *priv =nft_expr_priv (expr);int oif = regs->data[priv->sreg_dev]; +/* These are used by ifb only. */ + pkt->skb->tc_redirected =1 ; + pkt->skb->tc_from_ingress =1 ; +nf_fwd_netdev_egress (pkt, oif); regs->verdict.code =NF_STOLEN ; }
Pablo Neira Ayuso
maintainerRe: [PATCH 5.5 138/170] netfilter: nft_fwd_netdev: allow to redirect to ifb via ingress
Quoted 23 lines · Greg Kroah-Hartman
From: Pablo Neira Ayuso <[email protected]>
commit
bcfabee1afd99484b6ba067361b8678e28bbc065upstream.Set
skb->tc_redirectedto 1, otherwise the ifb driver drops the packet. Setskb->tc_from_ingressto 1 to reinject the packet back to the ingress path after leaving the ifb egress path.This patch inconditionally sets on these two skb fields that are meaningful to the ifb driver. The existing forward action is guaranteed to run from ingress path.
Fixes 39e6dea28adc ("netfilter: nf_tables: add forward expression to the netdev family")Signed-off-by Pablo Neira Ayuso <[email protected]>Signed-off-by Greg Kroah-Hartman <[email protected]>--- net/netfilter/nft_fwd_netdev.c | 4 ++++ 1 file changed, 4 insertions(+)
net/netfilter/nft_fwd_netdev.c static void nft_fwd_netdev_eval(const st · line 33
Quoted 6 lines
net/netfilter/nft_fwd_netdev.c +3
-0@@ -28,6 +28,10 @@ static void nft_fwd_netdev_eval(const ststruct nft_fwd_netdev *priv =nft_expr_priv (expr);int oif = regs->data[priv->sreg_dev]; +/* These are used by ifb only. */ + pkt->skb->tc_redirected =1 ; + pkt->skb->tc_from_ingress =1 ;
This patch also requires:
2c64605b590e net: Fix CONFIG_NET_CLS_ACT=n and CONFIG_NFT_FWD_NETDEV={y, m} build
Otherwise build breaks with CONFIG_NET_CLS_ACT=n.
Thanks.
Greg Kroah-Hartman
maintainerRe: [PATCH 5.5 138/170] netfilter: nft_fwd_netdev: allow to redirect to ifb via ingress
Quoted 33 lines · Pablo Neira Ayuso
Quoted 23 lines · Greg Kroah-Hartman
From: Pablo Neira Ayuso <[email protected]>
commit
bcfabee1afd99484b6ba067361b8678e28bbc065upstream.Set
skb->tc_redirectedto 1, otherwise the ifb driver drops the packet. Setskb->tc_from_ingressto 1 to reinject the packet back to the ingress path after leaving the ifb egress path.This patch inconditionally sets on these two skb fields that are meaningful to the ifb driver. The existing forward action is guaranteed to run from ingress path.
Fixes 39e6dea28adc ("netfilter: nf_tables: add forward expression to the netdev family")Signed-off-by Pablo Neira Ayuso <[email protected]>Signed-off-by Greg Kroah-Hartman <[email protected]>--- net/netfilter/nft_fwd_netdev.c | 4 ++++ 1 file changed, 4 insertions(+)net/netfilter/nft_fwd_netdev.c static void nft_fwd_netdev_eval(const st · line 33
Quoted 6 lines
net/netfilter/nft_fwd_netdev.c +3
-0@@ -28,6 +28,10 @@ static void nft_fwd_netdev_eval(const ststruct nft_fwd_netdev *priv =nft_expr_priv (expr);int oif = regs->data[priv->sreg_dev]; +/* These are used by ifb only. */ + pkt->skb->tc_redirected =1 ; + pkt->skb->tc_from_ingress =1 ;This patch also requires:
Quoted 3 lines
2c64605b590enet: FixCONFIG_NET_CLS_ACT=nandCONFIG_NFT_FWD_NETDEV={y, m} buildOtherwise build breaks with
CONFIG_NET_CLS_ACT=n.
Thanks for the hint, will go do that now.
greg k-h
Greg Kroah-Hartman
maintainerPATCH 139/170 i2c: nvidia-gpu: Handle timeout correctly in gpu_i2c_check_status()
In reply to Greg Kroah-HartmanFrom: Kai-Heng Feng <[email protected]>
commit d944b27df121e2ee854a6c2fad13d6c6300792d4 upstream.
Nvidia card may come with a "phantom" UCSI device, and its driver gets stuck in probe routine, prevents any system PM operations like suspend.
There's an unaccounted case that the target time can equal to jiffies in gpu_i2c_check_status(), let's solve that by using readl_poll_timeout() instead of jiffies comparison functions.
--- drivers/i2c/busses/i2c-nvidia-gpu.c | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-)
drivers/i2c/busses/i2c-nvidia-gpu.c +7 -11
@@ -8,6 +8,7 @@#include <linux/delay.h> #include <linux/i2c.h> #include <linux/interrupt.h> +#include <linux/iopoll.h> #include <linux/module.h> #include <linux/pci.h> #include <linux/platform_device.h>
@@ -75,20 +76,15 @@ static void gpu_enable_i2c_bus(struct gpstatic int gpu_i2c_check_status (struct gpu_i2c_dev *i2cd) { -unsigned long target = jiffies +msecs_to_jiffies (1000 );u32 val; +int ret; -do { - val =readl (i2cd->regs +I2C_MST_CNTL ); -if (!(val &I2C_MST_CNTL_CYCLE_TRIGGER )) -break ; -if ((val &I2C_MST_CNTL_STATUS ) != -I2C_MST_CNTL_STATUS_BUS_BUSY ) -break ; -usleep_range (500 ,600 ); - }while (time_is_after_jiffies (target)); + ret =readl_poll_timeout (i2cd->regs +I2C_MST_CNTL , val, + !(val &I2C_MST_CNTL_CYCLE_TRIGGER ) || + (val &I2C_MST_CNTL_STATUS ) !=I2C_MST_CNTL_STATUS_BUS_BUSY , +500 ,1000 *USEC_PER_MSEC ); -if (time_is_before_jiffies (target)) { +if (ret) {dev_err (i2cd->dev,"i2c timeout error %x\n" , val);return -ETIMEDOUT ; }
Greg Kroah-Hartman
maintainerPATCH 140/170 bpf, x32: Fix bug with JMP32 JSET BPF_X checking upper bits
In reply to Greg Kroah-HartmanFrom: Luke Nelson <[email protected]>
commit 80f1f85036355e5581ec0b99913410345ad3491b upstream.
The current x32 BPF JIT is incorrect for JMP32 JSET BPF_X when the upper 32 bits of operand registers are non-zero in certain situations.
The problem is in the following code:
case BPF_JMP | BPF_JSET | BPF_X:
case BPF_JMP32 | BPF_JSET | BPF_X:
...
/* and dreg_lo,sreg_lo */ EMIT2(0x23, add_2reg(0xC0, sreg_lo, dreg_lo)); /* and dreg_hi,sreg_hi */ EMIT2(0x23, add_2reg(0xC0, sreg_hi, dreg_hi)); /* or dreg_lo,dreg_hi */ EMIT2(0x09, add_2reg(0xC0, dreg_lo, dreg_hi));
This code checks the upper bits of the operand registers regardless if the BPF instruction is BPF_JMP32 or BPF_JMP64. Registers dreg_hi and dreg_lo are not loaded from the stack for BPF_JMP32, however, they can still be polluted with values from previous instructions.
The following BPF program demonstrates the bug. The jset64 instruction loads the temporary registers and performs the jump, since ((u64)r7 & (u64)r8) is non-zero. The jset32 should _not_ be taken, as the lower 32 bits are all zero, however, the current JIT will take the branch due the pollution of temporary registers from the earlier jset64.
mov64 r0, 0 ld64 r7, 0x8000000000000000 ld64 r8, 0x8000000000000000 jset64 r7, r8, 1
exit
jset32 r7, r8, 1
mov64 r0, 2
exit
The expected return value of this program is 2; under the buggy x32 JIT it returns 0. The fix is to skip using the upper 32 bits for jset32 and compare the upper 32 bits for jset64 only.
All tests in test_bpf.ko and selftests/bpf/test_verifier continue to pass with this change.
We found this bug using our automated verification tool, Serval.
--- arch/x86/net/bpf_jit_comp32.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-)
arch/x86/net/bpf_jit_comp32.c +6 -4
@@ -2039,10 +2039,12 @@ static int do_jit(struct bpf_prog *bpf_p }/* and dreg_lo,sreg_lo */ EMIT2 (0x23 ,add_2reg (0xC0 , sreg_lo, dreg_lo)); -/* and dreg_hi,sreg_hi */ -EMIT2 (0x23 ,add_2reg (0xC0 , sreg_hi, dreg_hi)); -/* or dreg_lo,dreg_hi */ -EMIT2 (0x09 ,add_2reg (0xC0 , dreg_lo, dreg_hi)); +if (is_jmp64) { +/* and dreg_hi,sreg_hi */ +EMIT2 (0x23 ,add_2reg (0xC0 , sreg_hi, dreg_hi)); +/* or dreg_lo,dreg_hi */ +EMIT2 (0x09 ,add_2reg (0xC0 , dreg_lo, dreg_hi)); + } goto emit_cond_jmp; }case BPF_JMP |BPF_JSET |BPF_K :
Greg Kroah-Hartman
maintainerPATCH 141/170 bpf: Initialize storage pointers to NULL to prevent freeing garbage pointer
In reply to Greg Kroah-HartmanFrom: Andrii Nakryiko <[email protected]>
commit 62039c30c19dcab96621e074aeeb90da7100def7 upstream.
Local storage array isn't initialized, so if cgroup storage allocation fails for BPF_CGROUP_STORAGE_SHARED, error handling code will attempt to free uninitialized pointer for BPF_CGROUP_STORAGE_PERCPU storage type. Avoid this by always initializing storage pointers to NULLs.
--- kernel/bpf/cgroup.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
kernel/bpf/cgroup.c +2 -2
@@ -303,8 +303,8 @@ int __cgroup_bpf_attach(struct cgroup *c {struct list_head *progs = &cgrp->bpf.progs[type];struct bpf_prog *old_prog =NULL ; -struct bpf_cgroup_storage *storage[MAX_BPF_CGROUP_STORAGE_TYPE ], - *old_storage[MAX_BPF_CGROUP_STORAGE_TYPE ] = {NULL }; +struct bpf_cgroup_storage *storage[MAX_BPF_CGROUP_STORAGE_TYPE ] = {}; +struct bpf_cgroup_storage *old_storage[MAX_BPF_CGROUP_STORAGE_TYPE ] = {};enum bpf_cgroup_storage_type stype;struct bpf_prog_list *pl;bool pl_was_allocated;
Greg Kroah-Hartman
maintainerPATCH 142/170 bpf/btf: Fix BTF verification of enum members in struct/union
In reply to Greg Kroah-HartmanFrom: Yoshiki Komachi <[email protected]>
commit da6c7faeb103c493e505e87643272f70be586635 upstream.
btf_enum_check_member() was currently sure to recognize the size of "enum" type members in struct/union as the size of "int" even if its size was packed.
This patch fixes BTF enum verification to use the correct size of member in BPF programs.
--- kernel/bpf/btf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
kernel/bpf/btf.c +1 -1
@@ -2383,7 +2383,7 @@ static int btf_enum_check_member(struct struct_size = struct_type->size; bytes_offset =BITS_ROUNDDOWN_BYTES (struct_bits_off); -if (struct_size - bytes_offset <sizeof (int )) { +if (struct_size - bytes_offset < member_type->size) {btf_verifier_log_member (env, struct_type, member,"Member exceeds struct_size" );return -EINVAL ;
Greg Kroah-Hartman
maintainerPATCH 143/170 bpf, sockmap: Remove bucket->lock from sock_{hash|map}_free
In reply to Greg Kroah-HartmanFrom: John Fastabend <[email protected]>
commit 90db6d772f749e38171d04619a5e3cd8804a6d02 upstream.
The bucket->lock is not needed in the sock_hash_free and sock_map_free calls, in fact it is causing a splat due to being inside rcu block.
| BUG: sleeping function called from invalid context at net/core/sock.c:2935
| in_atomic(): 1, irqs_disabled(): 0, non_block: 0, pid: 62, name: kworker/0:1
| 3 locks held by kworker/0:1/62:
| #0: ffff88813b019748 ((wq_completion)events){+.+.}, at: process_one_work+0x1d7/0x5e0
| #1: ffffc900000abe50 ((work_completion)(&map->work)){+.+.}, at: process_one_work+0x1d7/0x5e0
| #2: ffff8881381f6df8 (&stab->lock){+...}, at: sock_map_free+0x26/0x180
| CPU: 0 PID: 62 Comm: kworker/0:1 Not tainted 5.5.0-04008-g7b083332376e #454
| Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS ?-20190727_073836-buildvm-ppc64le-16.ppc.fedoraproject.org-3.fc31 04/01/2014
| Workqueue: events bpf_map_free_deferred
| Call Trace:
| dump_stack+0x71/0xa0
| ___might_sleep.cold+0xa6/0xb6
| lock_sock_nested+0x28/0x90
| sock_map_free+0x5f/0x180
| bpf_map_free_deferred+0x58/0x80
| process_one_work+0x260/0x5e0
| worker_thread+0x4d/0x3e0
| kthread+0x108/0x140
| ? process_one_work+0x5e0/0x5e0
| ? kthread_park+0x90/0x90
| ret_from_fork+0x3a/0x50The reason we have stab->lock and bucket->locks in sockmap code is to handle checking EEXIST in update/delete cases. We need to be careful during an update operation that we check for EEXIST and we need to ensure that the psock object is not in some partial state of removal/insertion while we do this. So both map_update_common and sock_map_delete need to guard from being run together potentially deleting an entry we are checking, etc. But by the time we get to the tear-down code in sock_{ma[|hash}_free we have already disconnected the map and we just did synchronize_rcu() in the line above so no updates/deletes should be in flight. Because of this we can drop the bucket locks from the map free'ing code, noting no update/deletes can be in-flight.
--- net/core/sock_map.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-)
net/core/sock_map.c +8 -4
@@ -233,8 +233,11 @@ static void sock_map_free(struct bpf_map struct bpf_stab *stab = container_of(map, struct bpf_stab, map);int i; +/* After the sync no updates or deletes will be in-flight so it +* is safe to walk map and remove entries without risking a race +* in EEXIST update case. +*/ synchronize_rcu (); -raw_spin_lock_bh (&stab->lock);for (i =0 ; i < stab->map.max_entries; i++) {struct sock **psk = &stab->sks[i];struct sock *sk;
@@ -248,7 +251,6 @@ static void sock_map_free(struct bpf_maprelease_sock (sk); } } -raw_spin_unlock_bh (&stab->lock);/* wait for psock readers accessing its map link */ synchronize_rcu ();
@@ -863,10 +865,13 @@ static void sock_hash_free(struct bpf_mastruct hlist_node *node;int i; +/* After the sync no updates or deletes will be in-flight so it +* is safe to walk map and remove entries without risking a race +* in EEXIST update case. +*/ synchronize_rcu ();for (i =0 ; i < htab->buckets_num; i++) { bucket =sock_hash_select_bucket (htab, i); -raw_spin_lock_bh (&bucket->lock);hlist_for_each_entry_safe (elem, node, &bucket->head, node) {hlist_del_rcu (&elem->node);lock_sock (elem->sk);
@@ -875,7 +880,6 @@ static void sock_hash_free(struct bpf_marcu_read_unlock ();release_sock (elem->sk); } -raw_spin_unlock_bh (&bucket->lock); }/* wait for psock readers accessing its map link */
Greg Kroah-Hartman
maintainerPATCH 144/170 ARM: dts: sun8i-a83t-tbs-a711: Fix USB OTG mode detection
In reply to Greg Kroah-HartmanFrom: Ondrej Jirman <[email protected]>
commit b642d4825441bf30c72b72deb739bd2d5f53af08 upstream.
USB-ID signal has a pullup on the schematic, but in reality it's not pulled up, so add a GPIO pullup. And we also need a usb0_vbus_power-supply for VBUS detection.
This fixes OTG mode detection and charging issues on TBS A711 tablet. The issues came from ID pin reading 0, causing host mode to be enabled, when it should not be, leading to DRVVBUS being enabled, which disabled the charger.
--- arch/arm/boot/dts/sun8i-a83t-tbs-a711.dts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
arch/arm/boot/dts/sun8i-a83t-tbs-a711.dts +2 -1
@@ -498,7 +498,8 @@ }; &usbphy { - usb0_id_det-gpios = <&pio 7 11 GPIO_ACTIVE_HIGH>; /* PH11 */ + usb0_id_det-gpios = <&pio 7 11 (GPIO_ACTIVE_HIGH | GPIO_PULL_UP)>; /* PH11 */ + usb0_vbus_power-supply = <&usb_power_supply>; usb0_vbus-supply = <®_drivevbus>; usb1_vbus-supply = <®_vmain>; usb2_vbus-supply = <®_vmain>;
Greg Kroah-Hartman
maintainerPATCH 145/170 vti6: Fix memory leak of skb if input policy check fails
In reply to Greg Kroah-HartmanFrom: Torsten Hilbrich <[email protected]>
commit 2a9de3af21aa8c31cd68b0b39330d69f8c1e59df upstream.
The vti6_rcv function performs some tests on the retrieved tunnel including checking the IP protocol, the XFRM input policy, the source and destination address.
In all but one places the skb is released in the error case. When the input policy check fails the network packet is leaked.
Using the same goto-label discard in this case to fix this problem.
--- net/ipv6/ip6_vti.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/ipv6/ip6_vti.c +1 -1
@@ -311,7 +311,7 @@ static int vti6_rcv(struct sk_buff *skb)if (!xfrm6_policy_check (NULL ,XFRM_POLICY_IN , skb)) {rcu_read_unlock (); -return 0 ; + goto discard; } ipv6h =ipv6_hdr (skb);
Greg Kroah-Hartman
maintainerPATCH 146/170 r8169: fix PHY driver check on platforms w/o module softdeps
In reply to Greg Kroah-HartmanFrom: Heiner Kallweit <[email protected]>
commit 2e8c339b4946490a922a21aa8cd869c6cfad2023 upstream.
On Android/x86 the module loading infrastructure can't deal with softdeps. Therefore the check for presence of the Realtek PHY driver module fails. mdiobus_register() will try to load the PHY driver module, therefore move the check to after this call and explicitly check that a dedicated PHY driver is bound to the PHY device.
--- drivers/net/ethernet/realtek/r8169_main.c | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-)
drivers/net/ethernet/realtek/r8169_main.c +7 -9
@@ -6670,6 +6670,13 @@ static int r8169_mdio_register(struct rtif (!tp->phydev) {mdiobus_unregister (new_bus);return -ENODEV ; + }else if (!tp->phydev->drv) { +/* Most chip versions fail with the genphy driver. +* Therefore ensure that the dedicated PHY driver is loaded. +*/ +dev_err (&pdev->dev,"realtek.ko not loaded, maybe it needs to be added to initramfs?\n" ); +mdiobus_unregister (new_bus); +return -EUNATCH ; }/* PHY will be woken up in rtl_open() */
@@ -6831,15 +6838,6 @@ static int rtl_init_one(struct pci_dev *int chipset, region;int jumbo_max, rc; -/* Some tools for creating an initramfs don't consider softdeps, then -* r8169.ko may be in initramfs, but realtek.ko not. Then the generic -* PHY driver is used that doesn't work with most chip versions. -*/ -if (!driver_find ("RTL8201CP Ethernet" , &mdio_bus_type)) { -dev_err (&pdev->dev,"realtek.ko not loaded, maybe it needs to be added to initramfs?\n" ); -return -ENOENT ; - } - dev =devm_alloc_etherdev (&pdev->dev,sizeof (*tp));if (!dev)return -ENOMEM ;
Greg Kroah-Hartman
maintainerPATCH 147/170 clocksource/drivers/hyper-v: Untangle stimers and timesync from clocksources
In reply to Greg Kroah-HartmanFrom: Yubo Xie <[email protected]>
[ Upstream commit 0af3e137c144377fbaf5025ba784ff5ba7ad40c9 ]
hyperv_timer.c exports hyperv_cs, which is used by stimers and the timesync mechanism. However, the clocksource dependency is not
needed: these mechanisms only depend on the partition reference counter (which can be read via a MSR or via the TSC Reference Page).
Introduce the (function) pointer hv_read_reference_counter, as an embodiment of the partition reference counter read, and export it in place of the hyperv_cs pointer. The latter can be removed.
This should clarify that there's no relationship between Hyper-V stimers & timesync and the Linux clocksource abstractions. No functional or semantic change.
--- drivers/clocksource/hyperv_timer.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
drivers/clocksource/hyperv_timer.c +4 -2
@@ -327,7 +327,8 @@ static u64 notrace read_hv_clock_tsc(strstatic u64 read_hv_sched_clock_tsc (void ) { -return read_hv_clock_tsc (NULL ) - hv_sched_clock_offset; +return (read_hv_clock_tsc (NULL ) - hv_sched_clock_offset) * + (NSEC_PER_SEC /HV_CLOCK_HZ ); }static struct clocksource hyperv_cs_tsc = {
@@ -352,7 +353,8 @@ static u64 notrace read_hv_clock_msr(strstatic u64 read_hv_sched_clock_msr (void ) { -return read_hv_clock_msr (NULL ) - hv_sched_clock_offset; +return (read_hv_clock_msr (NULL ) - hv_sched_clock_offset) * + (NSEC_PER_SEC /HV_CLOCK_HZ ); }static struct clocksource hyperv_cs_msr = {
Greg Kroah-Hartman
maintainerPATCH 148/170 bpf: Undo incorrect __reg_bound_offset32 handling
In reply to Greg Kroah-HartmanFrom: Daniel Borkmann <[email protected]>
commit f2d67fec0b43edce8c416101cdc52e71145b5fef upstream.
Anatoly has been fuzzing with kBdysch harness and reported a hang in one of the outcomes:
0: (b7) r0 = 808464432
1: (7f) r0 >>= r0
2: (14) w0 -= 808464432
3: (07) r0 += 808464432
4: (b7) r1 = 808464432
5: (de) if w1 s<= w0 goto pc+0
R0_w=invP(id=0,umin_value=808464432,umax_value=5103431727,var_off=(0x30303020;0x10000001f)) R1_w=invP808464432 R10=fp0
6: (07) r0 += -2144337872
7: (14) w0 -= -1607454672
8: (25) if r0 > 0x30303030 goto pc+0
R0_w=invP(id=0,umin_value=271581184,umax_value=271581311,var_off=(0x10300000;0x7f)) R1_w=invP808464432 R10=fp0
9: (76) if w0 s>= 0x303030 goto pc+2
12: (95) exit
from 8 to 9: safe
from 5 to 6: R0_w=invP(id=0,umin_value=808464432,umax_value=5103431727,var_off=(0x30303020;0x10000001f)) R1_w=invP808464432 R10=fp0 6: (07) r0 += -2144337872
7: (14) w0 -= -1607454672
8: (25) if r0 > 0x30303030 goto pc+0
R0_w=invP(id=0,umin_value=271581184,umax_value=271581311,var_off=(0x10300000;0x7f)) R1_w=invP808464432 R10=fp0
9: safe
from 8 to 9: safe
verification time 589 usec
stack depth 0
processed 17 insns (limit 1000000) [...]
The underlying program was xlated as follows:
# bpftool p d x i 9 0: (b7) r0 = 808464432 1: (7f) r0 >>= r0 2: (14) w0 -= 808464432 3: (07) r0 += 808464432 4: (b7) r1 = 808464432 5: (de) if w1 s<= w0 goto pc+0 6: (07) r0 += -2144337872 7: (14) w0 -= -1607454672 8: (25) if r0 > 0x30303030 goto pc+0 9: (76) if w0 s>= 0x303030 goto pc+2 10: (05) goto pc-1 11: (05) goto pc-1 12: (95) exit
The verifier rewrote original instructions it recognized as dead code with 'goto pc-1', but reality differs from verifier simulation in that we're actually able to trigger a hang due to hitting the 'goto pc-1' instructions.
Taking different examples to make the issue more obvious: in this example we're probing bounds on a completely unknown scalar variable in r1:
[...]
5: R0_w=inv1 R1_w=inv(id=0) R10=fp0
5: (18) r2 = 0x4000000000
7: R0_w=inv1 R1_w=inv(id=0) R2_w=inv274877906944 R10=fp0
7: (18) r3 = 0x2000000000
9: R0_w=inv1 R1_w=inv(id=0) R2_w=inv274877906944 R3_w=inv137438953472 R10=fp0
9: (18) r4 = 0x400
11: R0_w=inv1 R1_w=inv(id=0) R2_w=inv274877906944 R3_w=inv137438953472 R4_w=inv1024 R10=fp0
11: (18) r5 = 0x200
13: R0_w=inv1 R1_w=inv(id=0) R2_w=inv274877906944 R3_w=inv137438953472 R4_w=inv1024 R5_w=inv512 R10=fp0
13: (2d) if r1 > r2 goto pc+4
R0_w=inv1 R1_w=inv(id=0,umax_value=274877906944,var_off=(0x0; 0x7fffffffff)) R2_w=inv274877906944 R3_w=inv137438953472 R4_w=inv1024 R5_w=inv512 R10=fp0
14: R0_w=inv1 R1_w=inv(id=0,umax_value=274877906944,var_off=(0x0; 0x7fffffffff)) R2_w=inv274877906944 R3_w=inv137438953472 R4_w=inv1024 R5_w=inv512 R10=fp0 14: (ad) if r1 < r3 goto pc+3
R0_w=inv1 R1_w=inv(id=0,umin_value=137438953472,umax_value=274877906944,var_off=(0x0; 0x7fffffffff)) R2_w=inv274877906944 R3_w=inv137438953472 R4_w=inv1024 R5_w=inv512 R10=fp0
15: R0=inv1 R1=inv(id=0,umin_value=137438953472,umax_value=274877906944,var_off=(0x0; 0x7fffffffff)) R2=inv274877906944 R3=inv137438953472 R4=inv1024 R5=inv512 R10=fp0 15: (2e) if w1 > w4 goto pc+2
R0=inv1 R1=inv(id=0,umin_value=137438953472,umax_value=274877906944,var_off=(0x0; 0x7f00000000)) R2=inv274877906944 R3=inv137438953472 R4=inv1024 R5=inv512 R10=fp0
16: R0=inv1 R1=inv(id=0,umin_value=137438953472,umax_value=274877906944,var_off=(0x0; 0x7f00000000)) R2=inv274877906944 R3=inv137438953472 R4=inv1024 R5=inv512 R10=fp0 16: (ae) if w1 < w5 goto pc+1
R0=inv1 R1=inv(id=0,umin_value=137438953472,umax_value=274877906944,var_off=(0x0; 0x7f00000000)) R2=inv274877906944 R3=inv137438953472 R4=inv1024 R5=inv512 R10=fp0
[...]
We're first probing lower/upper bounds via jmp64, later we do a similar check via jmp32 and examine the resulting var_off there. After fall-through in insn 14, we get the following bounded r1 with 0x7fffffffff unknown marked bits in the variable section.
Thus, after knowing r1 <= 0x4000000000 and r1 >= 0x2000000000:
max: 0b100000000000000000000000000000000000000 / 0x4000000000
var: 0b111111111111111111111111111111111111111 / 0x7fffffffff
min: 0b010000000000000000000000000000000000000 / 0x2000000000
Now, in insn 15 and 16, we perform a similar probe with lower/upper bounds in jmp32.
Thus, after knowing r1 <= 0x4000000000 and r1 >= 0x2000000000 and
w1 <= 0x400 and w1 >= 0x200:
max: 0b100000000000000000000000000000000000000 / 0x4000000000
var: 0b111111100000000000000000000000000000000 / 0x7f00000000
min: 0b010000000000000000000000000000000000000 / 0x2000000000
The lower/upper bounds haven't changed since they have high bits set in u64 space and the jmp32 tests can only refine bounds in the low bits.
However, for the var part the expectation would have been 0x7f000007ff or something less precise up to 0x7fffffffff. A outcome of 0x7f00000000 is not correct since it would contradict the earlier probed bounds where we know that the result should have been in [0x200,0x400] in u32 space. Therefore, tests with such info will lead to wrong verifier assumptions later on like falsely predicting conditional jumps to be always taken, etc.
The issue here is that __reg_bound_offset32()'s implementation from commit 581738a681b6 ("bpf: Provide better register bounds after jmp32 instructions") makes an incorrect range assumption:
static void __reg_bound_offset32(struct bpf_reg_state *reg)
{
u64 mask = 0xffffFFFF;
struct tnum range = tnum_range(reg->umin_value & mask,
reg->umax_value & mask);
struct tnum lo32 = tnum_cast(reg->var_off, 4);
struct tnum hi32 = tnum_lshift(tnum_rshift(reg->var_off, 32), 32);reg->var_off = tnum_or(hi32, tnum_intersect(lo32, range));
}
In the above walk-through example, __reg_bound_offset32() as-is chose a range after masking with 0xffffffff of [0x0,0x0] since umin:0x2000000000 and umax:0x4000000000 and therefore the lo32 part was clamped to 0x0 as well. However, in the umin:0x2000000000 and umax:0x4000000000 range above we'd end up with an actual possible interval of [0x0,0xffffffff] for u32 space instead.
In case of the original reproducer, the situation looked as follows at insn 5 for r0:
[...]
5: R0_w=invP(id=0,umin_value=808464432,umax_value=5103431727,var_off=(0x0; 0x1ffffffff)) R1_w=invP808464432 R10=fp0
0x30303030 0x13030302f
5: (de) if w1 s<= w0 goto pc+0
R0_w=invP(id=0,umin_value=808464432,umax_value=5103431727,var_off=(0x30303020; 0x10000001f)) R1_w=invP808464432 R10=fp0
0x30303030 0x13030302f[...]
After the fall-through, we similarly forced the var_off result into the wrong range [0x30303030,0x3030302f] suggesting later on that fixed bits must only be of 0x30303020 with 0x10000001f unknowns whereas such assumption can only be made when both bounds in hi32 range match.
Originally, I was thinking to fix this by moving reg into a temp reg and use proper coerce_reg_to_size() helper on the temp reg where we can then based on that define the range tnum for later intersection:
static void __reg_bound_offset32(struct bpf_reg_state *reg)
{
struct bpf_reg_state tmp = *reg;
struct tnum lo32, hi32, range; coerce_reg_to_size(&tmp, 4);
range = tnum_range(tmp.umin_value, tmp.umax_value);
lo32 = tnum_cast(reg->var_off, 4);
hi32 = tnum_lshift(tnum_rshift(reg->var_off, 32), 32);
reg->var_off = tnum_or(hi32, tnum_intersect(lo32, range));}
In the case of the concrete example, this gives us a more conservative unknown section. Thus, after knowing r1 <= 0x4000000000 and r1 >= 0x2000000000 and
w1 <= 0x400 and w1 >= 0x200:
max: 0b100000000000000000000000000000000000000 / 0x4000000000
var: 0b111111111111111111111111111111111111111 / 0x7fffffffff
min: 0b010000000000000000000000000000000000000 / 0x2000000000
However, above new __reg_bound_offset32() has no effect on refining the knowledge of the register contents. Meaning, if the bounds in hi32 range mismatch we'll get the identity function given the range reg spans [0x0,0xffffffff] and we cast var_off into lo32 only to later on binary or it again with the hi32.
Likewise, if the bounds in hi32 range match, then we mask both bounds with 0xffffffff, use the resulting umin/umax for the range to later intersect the lo32 with it. However, _prior_ called __reg_bound_offset() did already such intersection on the full reg and we therefore would only repeat the same operation on the lo32 part twice.
Given this has no effect and the original commit had false assumptions, this patch reverts the code entirely which is also more straight forward for stable trees: apparently 581738a681b6 got auto-selected by Sasha's ML system and misclassified as a fix, so it got sucked into v5.4 where it should never have landed. A revert is low-risk also from a user PoV since it requires a recent kernel and llc to opt-into -mcpu=v3 BPF CPU to generate jmp32 instructions. A proper bounds refinement would need a significantly more complex approach which is currently being worked, but no stable material [0]. Hence revert is best option for stable. After the revert, the original reported program gets rejected as follows:
1: (7f) r0 >>= r0
2: (14) w0 -= 808464432
3: (07) r0 += 808464432
4: (b7) r1 = 808464432
5: (de) if w1 s<= w0 goto pc+0
R0_w=invP(id=0,umin_value=808464432,umax_value=5103431727,var_off=(0x0; 0x1ffffffff)) R1_w=invP808464432 R10=fp0
6: (07) r0 += -2144337872
7: (14) w0 -= -1607454672
8: (25) if r0 > 0x30303030 goto pc+0
R0_w=invP(id=0,umax_value=808464432,var_off=(0x0; 0x3fffffff)) R1_w=invP808464432 R10=fp0
9: (76) if w0 s>= 0x303030 goto pc+2
R0=invP(id=0,umax_value=3158063,var_off=(0x0; 0x3fffff)) R1=invP808464432 R10=fp0
10: (30) r0 = *(u8 *)skb[808464432]
BPF_LD_[ABS|IND] uses reserved fields
processed 11 insns (limit 1000000) [...]
--- kernel/bpf/verifier.c | 19 ------------------- 1 file changed, 19 deletions(-)
kernel/bpf/verifier.c +0 -19
@@ -1034,17 +1034,6 @@ static void __reg_bound_offset(struct bp reg->umax_value)); } -static void __reg_bound_offset32 (struct bpf_reg_state *reg) -{ -u64 mask =0xffffFFFF ; -struct tnum range =tnum_range (reg->umin_value & mask, - reg->umax_value & mask); -struct tnum lo32 =tnum_cast (reg->var_off,4 ); -struct tnum hi32 =tnum_lshift (tnum_rshift (reg->var_off,32 ),32 ); - - reg->var_off =tnum_or (hi32,tnum_intersect (lo32, range)); -} -/* Reset the min/max bounds of a register */ static void __mark_reg_unbounded (struct bpf_reg_state *reg) {
@@ -5677,10 +5666,6 @@ static void reg_set_min_max(struct bpf_r/* We might have learned some bits from the bounds. */ __reg_bound_offset (false_reg);__reg_bound_offset (true_reg); -if (is_jmp32) { -__reg_bound_offset32 (false_reg); -__reg_bound_offset32 (true_reg); - }/* Intersecting with the old var_off might have improved our bounds * slightly. e.g. if umax was 0x7f...f and var_off was (0; 0xf...fc), * then new var_off is (0; 0x7f...fc) which improves our umax.
@@ -5790,10 +5775,6 @@ static void reg_set_min_max_inv(struct b/* We might have learned some bits from the bounds. */ __reg_bound_offset (false_reg);__reg_bound_offset (true_reg); -if (is_jmp32) { -__reg_bound_offset32 (false_reg); -__reg_bound_offset32 (true_reg); - }/* Intersecting with the old var_off might have improved our bounds * slightly. e.g. if umax was 0x7f...f and var_off was (0; 0xf...fc), * then new var_off is (0; 0x7f...fc) which improves our umax.
Greg Kroah-Hartman
maintainerPATCH 149/170 USB: serial: option: add support for ASKEY WWHC050
In reply to Greg Kroah-HartmanFrom: Pawel Dembicki <[email protected]>
commit 007d20dca2376a751b1dad03442f118438b7e65e upstream.
ASKEY WWHC050 is a mcie LTE modem.
The oem configuration states:
T: Bus=01 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#= 2 Spd=480 MxCh= 0 D: Ver= 2.10 Cls=00(>ifc ) Sub=00 Prot=00 MxPS=64 #Cfgs= 1 P: Vendor=1690 ProdID=7588 Rev=ff.ff S: Manufacturer=Android S: Product=Android S: SerialNumber=813f0eef6e6e C:* #Ifs= 6 Cfg#= 1 Atr=80 MxPwr=500mA I:* If#= 0 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=ff Driver=option E: Ad=81(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=01(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms I:* If#= 1 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=42 Prot=01 Driver=(none) E: Ad=02(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=82(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms I:* If#= 2 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=00 Prot=00 Driver=option E: Ad=84(I) Atr=03(Int.) MxPS= 10 Ivl=32ms E: Ad=83(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=03(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms I:* If#= 3 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=00 Prot=00 Driver=option E: Ad=86(I) Atr=03(Int.) MxPS= 10 Ivl=32ms E: Ad=85(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=04(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms I:* If#= 4 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=ff Driver=qmi_wwan E: Ad=88(I) Atr=03(Int.) MxPS= 8 Ivl=32ms E: Ad=87(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=05(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms I:* If#= 5 Alt= 0 #EPs= 2 Cls=08(stor.) Sub=06 Prot=50 Driver=(none) E: Ad=89(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=06(O) Atr=02(Bulk) MxPS= 512 Ivl=125us
Tested on openwrt distribution.
--- drivers/usb/serial/option.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/usb/serial/option.c +2 -0
@@ -1992,6 +1992,8 @@ static const struct usb_device_id option { USB_DEVICE_AND_INTERFACE_INFO(0x07d1, 0x3e01, 0xff, 0xff, 0xff) }, /* D-Link DWM-152/C1 */ { USB_DEVICE_AND_INTERFACE_INFO(0x07d1, 0x3e02, 0xff, 0xff, 0xff) }, /* D-Link DWM-156/C1 */ { USB_DEVICE_AND_INTERFACE_INFO(0x07d1, 0x7e11, 0xff, 0xff, 0xff) }, /* D-Link DWM-156/A3 */ + { USB_DEVICE_INTERFACE_CLASS(0x1690, 0x7588, 0xff), /* ASKEY WWHC050 */ + .driver_info = RSVD(1) | RSVD(4) }, { USB_DEVICE_INTERFACE_CLASS(0x2020, 0x2031, 0xff), /* Olicard 600 */ .driver_info = RSVD(4) }, { USB_DEVICE_INTERFACE_CLASS(0x2020, 0x2060, 0xff), /* BroadMobi BM818 */
Greg Kroah-Hartman
maintainerPATCH 150/170 USB: serial: option: add BroadMobi BM806U
In reply to Greg Kroah-HartmanFrom: Pawel Dembicki <[email protected]>
commit 6cb2669cb97fc4fdf526127159ac59caae052247 upstream.
BroadMobi BM806U is an Qualcomm MDM9225 based 3G/4G modem. Tested hardware BM806U is mounted on D-Link DWR-921-C3 router.
T: Bus=01 Lev=01 Prnt=01 Port=01 Cnt=01 Dev#= 2 Spd=480 MxCh= 0 D: Ver= 2.01 Cls=00(>ifc ) Sub=00 Prot=00 MxPS=64 #Cfgs= 1 P: Vendor=2020 ProdID=2033 Rev= 2.28 S: Manufacturer=Mobile Connect S: Product=Mobile Connect S: SerialNumber=f842866cfd5a C:* #Ifs= 5 Cfg#= 1 Atr=80 MxPwr=500mA I:* If#= 0 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=ff Driver=option E: Ad=81(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=01(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms I:* If#= 1 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=00 Prot=00 Driver=option E: Ad=83(I) Atr=03(Int.) MxPS= 10 Ivl=32ms E: Ad=82(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=02(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms I:* If#= 2 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=00 Prot=00 Driver=option E: Ad=85(I) Atr=03(Int.) MxPS= 10 Ivl=32ms E: Ad=84(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=03(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms I:* If#= 3 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=00 Prot=00 Driver=option E: Ad=87(I) Atr=03(Int.) MxPS= 10 Ivl=32ms E: Ad=86(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=04(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms I:* If#= 4 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=ff Driver=qmi_wwan E: Ad=89(I) Atr=03(Int.) MxPS= 8 Ivl=32ms E: Ad=88(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=05(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
--- drivers/usb/serial/option.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/usb/serial/option.c +2 -0
@@ -1996,6 +1996,8 @@ static const struct usb_device_id option .driver_info = RSVD(1) | RSVD(4) }, { USB_DEVICE_INTERFACE_CLASS(0x2020, 0x2031, 0xff), /* Olicard 600 */ .driver_info = RSVD(4) }, + { USB_DEVICE_INTERFACE_CLASS(0x2020, 0x2033, 0xff), /* BroadMobi BM806U */ + .driver_info = RSVD(4) }, { USB_DEVICE_INTERFACE_CLASS(0x2020, 0x2060, 0xff), /* BroadMobi BM818 */ .driver_info = RSVD(4) }, { USB_DEVICE_INTERFACE_CLASS(0x2020, 0x4000, 0xff) }, /* OLICARD300 - MT6225 */
Greg Kroah-Hartman
maintainerPATCH 151/170 USB: serial: option: add Wistron Neweb D19Q1
In reply to Greg Kroah-HartmanFrom: Pawel Dembicki <[email protected]>
commit dfee7e2f478346b12ea651d5c28b069f6a4af563 upstream.
This modem is embedded on dlink dwr-960 router.
The oem configuration states:
T: Bus=01 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#= 2 Spd=480 MxCh= 0
D: Ver= 2.10 Cls=00(>ifc ) Sub=00 Prot=00 MxPS=64 #Cfgs= 1
P: Vendor=1435 ProdID=d191 Rev=ff.ff
S: Manufacturer=Android
S: Product=Android
S: SerialNumber=0123456789ABCDEF
C:* #Ifs= 6 Cfg#= 1 Atr=80 MxPwr=500mA
I:* If#= 0 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=ff Driver=(none)
E: Ad=81(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
E: Ad=01(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
I:* If#= 1 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=42 Prot=01 Driver=(none)
E: Ad=02(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
E: Ad=82(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
I:* If#= 2 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=00 Prot=00 Driver=(none)
E: Ad=84(I) Atr=03(Int.) MxPS= 10 Ivl=32ms
E: Ad=83(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
E: Ad=03(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
I:* If#= 3 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=00 Prot=00 Driver=(none)
E: Ad=86(I) Atr=03(Int.) MxPS= 10 Ivl=32ms
E: Ad=85(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
E: Ad=04(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
I:* If#= 4 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=ff Driver=qmi_wwan
E: Ad=88(I) Atr=03(Int.) MxPS= 8 Ivl=32ms
E: Ad=87(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
E: Ad=05(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
I:* If#= 5 Alt= 0 #EPs= 2 Cls=08(stor.) Sub=06 Prot=50 Driver=(none)
E: Ad=89(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
E: Ad=06(O) Atr=02(Bulk) MxPS= 512 Ivl=125us
Tested on openwrt distribution
--- drivers/usb/serial/option.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/usb/serial/option.c +2 -0
@@ -1992,6 +1992,8 @@ static const struct usb_device_id option { USB_DEVICE_AND_INTERFACE_INFO(0x07d1, 0x3e01, 0xff, 0xff, 0xff) }, /* D-Link DWM-152/C1 */ { USB_DEVICE_AND_INTERFACE_INFO(0x07d1, 0x3e02, 0xff, 0xff, 0xff) }, /* D-Link DWM-156/C1 */ { USB_DEVICE_AND_INTERFACE_INFO(0x07d1, 0x7e11, 0xff, 0xff, 0xff) }, /* D-Link DWM-156/A3 */ + { USB_DEVICE_INTERFACE_CLASS(0x1435, 0xd191, 0xff), /* Wistron Neweb D19Q1 */ + .driver_info = RSVD(1) | RSVD(4) }, { USB_DEVICE_INTERFACE_CLASS(0x1690, 0x7588, 0xff), /* ASKEY WWHC050 */ .driver_info = RSVD(1) | RSVD(4) }, { USB_DEVICE_INTERFACE_CLASS(0x2020, 0x2031, 0xff), /* Olicard 600 */
Greg Kroah-Hartman
maintainerPATCH 152/170 USB: cdc-acm: restore capability check order
In reply to Greg Kroah-HartmanFrom: Matthias Reichl <[email protected]>
commit 62d65bdd9d05158aa2547f8ef72375535f3bc6e3 upstream.
commit b401f8c4f492c ("USB: cdc-acm: fix rounding error in TIOCSSERIAL") introduced a regression by changing the order of capability and close settings change checks. When running with CAP_SYS_ADMIN setting the close settings to the values already set resulted in -EOPNOTSUPP.
Fix this by changing the check order back to how it was before.
--- drivers/usb/class/cdc-acm.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-)
drivers/usb/class/cdc-acm.c +9 -9
@@ -923,16 +923,16 @@ static int set_serial_info(struct tty_stmutex_lock (&acm->port.mutex); -if ((ss->close_delay != old_close_delay) || - (ss->closing_wait != old_closing_wait)) { -if (!capable (CAP_SYS_ADMIN )) +if (!capable (CAP_SYS_ADMIN )) { +if ((ss->close_delay != old_close_delay) || + (ss->closing_wait != old_closing_wait)) retval = -EPERM ; -else { - acm->port.close_delay = close_delay; - acm->port.closing_wait = closing_wait; - } - }else - retval = -EOPNOTSUPP ; +else + retval = -EOPNOTSUPP ; + }else { + acm->port.close_delay = close_delay; + acm->port.closing_wait = closing_wait; + }mutex_unlock (&acm->port.mutex);return retval;
Greg Kroah-Hartman
maintainerPATCH 153/170 USB: serial: io_edgeport: fix slab-out-of-bounds read in edge_interrupt_callback
In reply to Greg Kroah-HartmanFrom: Qiujun Huang <[email protected]>
commit 57aa9f294b09463492f604feaa5cc719beaace32 upstream.
Fix slab-out-of-bounds read in the interrupt-URB completion handler.
The boundary condition should be (length - 1) as we access data[position + 1].
--- drivers/usb/serial/io_edgeport.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/usb/serial/io_edgeport.c +1 -1
@@ -710,7 +710,7 @@ static void edge_interrupt_callback(stru/* grab the txcredits for the ports if available */ position =2 ; portNumber =0 ; -while ((position < length) && +while ((position < length -1 ) && (portNumber < edge_serial->serial->num_ports)) { txCredits = data[position] | (data[position+1 ] <<8 );if (txCredits) {
Greg Kroah-Hartman
maintainerPATCH 154/170 usb: musb: fix crash with highmen PIO and usbmon
In reply to Greg Kroah-HartmanFrom: Mans Rullgard <[email protected]>
commit 52974d94a206ce428d9d9b6eaa208238024be82a upstream.
When handling a PIO bulk transfer with highmem buffer, a temporary mapping is assigned to urb->transfer_buffer. After the transfer is complete, an invalid address is left behind in this pointer. This is not ordinarily a problem since nothing touches that buffer before the urb is released. However, when usbmon is active, usbmon_urb_complete() calls (indirectly) mon_bin_get_data() which does access the transfer buffer if it is set. To prevent an invalid memory access here, reset urb->transfer_buffer to NULL when finished (musb_host_rx()), or do not set it at all (musb_host_tx()).
--- drivers/usb/musb/musb_host.c | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-)
drivers/usb/musb/musb_host.c +5 -12
@@ -1462,10 +1462,7 @@ done:* We need to map sg if the transfer_buffer is * NULL. */ -if (!urb->transfer_buffer) - qh->use_sg = true; - -if (qh->use_sg) { +if (!urb->transfer_buffer) {/* sg_miter_start is already done in musb_ep_program */ if (!sg_miter_next (&qh->sg_miter)) {dev_err (musb->controller,"error: sg list empty\n" );
@@ -1473,9 +1470,8 @@ done: status = -EINVAL ; goto done; } - urb->transfer_buffer = qh->sg_miter.addr; length =min_t (u32, length, qh->sg_miter.length); -musb_write_fifo (hw_ep, length, urb->transfer_buffer); +musb_write_fifo (hw_ep, length, qh->sg_miter.addr); qh->sg_miter.consumed = length;sg_miter_stop (&qh->sg_miter); }else {
@@ -1484,11 +1480,6 @@ done: qh->segsize = length; -if (qh->use_sg) { -if (offset + length >= urb->transfer_buffer_length) - qh->use_sg = false; - } -musb_ep_select (mbase, epnum);musb_writew (epio,MUSB_TXCSR ,MUSB_TXCSR_H_WZC_BITS |MUSB_TXCSR_TXPKTRDY );
@@ -2003,8 +1994,10 @@ finish: urb->actual_length += xfer_len; qh->offset += xfer_len;if (done) { -if (qh->use_sg) +if (qh->use_sg) { qh->use_sg = false; + urb->transfer_buffer =NULL ; + }if (urb->status == -EINPROGRESS ) urb->status = status;
Greg Kroah-Hartman
maintainerPATCH 155/170 media: flexcop-usb: fix endpoint sanity check
In reply to Greg Kroah-HartmanFrom: Johan Hovold <[email protected]>
commit bca243b1ce0e46be26f7c63b5591dfbb41f558e5 upstream.
commit 1b976fc6d684 ("media: b2c2-flexcop-usb: add sanity checking") added an endpoint sanity check to address a NULL-pointer dereference on probe. Unfortunately the check was done on the current altsetting which was later changed.
Fix this by moving the sanity check to after the altsetting is changed.
--- drivers/media/usb/b2c2/flexcop-usb.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
drivers/media/usb/b2c2/flexcop-usb.c +3 -3
@@ -511,6 +511,9 @@ static int flexcop_usb_init(struct flexcreturn ret; } +if (fc_usb->uintf->cur_altsetting->desc.bNumEndpoints <1 ) +return -ENODEV ; +switch (fc_usb->udev->speed) {case USB_SPEED_LOW :err ("cannot handle USB speed because it is too slow." );
@@ -544,9 +547,6 @@ static int flexcop_usb_probe(struct usb_struct flexcop_device *fc =NULL ;int ret; -if (intf->cur_altsetting->desc.bNumEndpoints <1 ) -return -ENODEV ; -if ((fc =flexcop_device_kmalloc (sizeof (struct flexcop_usb ))) ==NULL ) {err ("out of memory\n" );return -ENOMEM ;
Greg Kroah-Hartman
maintainerPATCH 156/170 media: usbtv: fix control-message timeouts
In reply to Greg Kroah-HartmanFrom: Johan Hovold <[email protected]>
commit 536f561d871c5781bc33d26d415685211b94032e upstream.
The driver was issuing synchronous uninterruptible control requests without using a timeout. This could lead to the driver hanging on various user requests due to a malfunctioning (or malicious) device until the device is physically disconnected.
The USB upper limit of five seconds per request should be more than enough.
--- drivers/media/usb/usbtv/usbtv-core.c | 2 +- drivers/media/usb/usbtv/usbtv-video.c | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-)
drivers/media/usb/usbtv/usbtv-core.c +1 -1
@@ -56,7 +56,7 @@ int usbtv_set_regs(struct usbtv *usbtv, ret =usb_control_msg (usbtv->udev, pipe,USBTV_REQUEST_REG ,USB_DIR_OUT |USB_TYPE_VENDOR |USB_RECIP_DEVICE , - value, index,NULL ,0 ,0 ); + value, index,NULL ,0 ,USB_CTRL_GET_TIMEOUT );if (ret <0 )return ret; }
drivers/media/usb/usbtv/usbtv-video.c +3 -2
@@ -800,7 +800,8 @@ static int usbtv_s_ctrl(struct v4l2_ctrl ret =usb_control_msg (usbtv->udev,usb_rcvctrlpipe (usbtv->udev,0 ),USBTV_CONTROL_REG ,USB_DIR_IN |USB_TYPE_VENDOR |USB_RECIP_DEVICE , -0 ,USBTV_BASE +0x0244 , (void *)data,3 ,0 ); +0 ,USBTV_BASE +0x0244 , (void *)data,3 , +USB_CTRL_GET_TIMEOUT );if (ret <0 ) goto error; }
@@ -851,7 +852,7 @@ static int usbtv_s_ctrl(struct v4l2_ctrl ret =usb_control_msg (usbtv->udev,usb_sndctrlpipe (usbtv->udev,0 ),USBTV_CONTROL_REG ,USB_DIR_OUT |USB_TYPE_VENDOR |USB_RECIP_DEVICE , -0 , index, (void *)data, size,0 ); +0 , index, (void *)data, size,USB_CTRL_SET_TIMEOUT ); error:if (ret <0 )
Greg Kroah-Hartman
maintainerPATCH 157/170 staging: kpc2000: prevent underflow in cpld_reconfigure()
In reply to Greg Kroah-HartmanFrom: Dan Carpenter <[email protected]>
commit 72db61d7d17a475d3cc9de1a7c871d518fcd82f0 upstream.
This function should not allow negative values of "wr_val". If negatives are allowed then capping the upper bound at 7 is meaningless. Let's make it unsigned.
--- drivers/staging/kpc2000/kpc2000/core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/staging/kpc2000/kpc2000/core.c +2 -2
@@ -110,10 +110,10 @@ static ssize_t cpld_reconfigure(struct d const char *buf, size_t count) {struct kp2000_device *pcard =dev_get_drvdata (dev); -long wr_val; +unsigned long wr_val;int rv; - rv =kstrtol (buf,0 , &wr_val); + rv =kstrtoul (buf,0 , &wr_val);if (rv <0 )return rv;if (wr_val >7 )
Greg Kroah-Hartman
maintainerPATCH 158/170 staging: rtl8188eu: Add ASUS USB-N10 Nano B1 to device table
In reply to Greg Kroah-HartmanFrom: Larry Finger <[email protected]>
commit 38ef48f7d4b7342f145a1b4f96023bde99aeb245 upstream.
The ASUS USB-N10 Nano B1 has been reported as a new RTL8188EU device. Add it to the device tables.
--- drivers/staging/rtl8188eu/os_dep/usb_intf.c | 1 + 1 file changed, 1 insertion(+)
drivers/staging/rtl8188eu/os_dep/usb_intf.c +1 -0
@@ -32,6 +32,7 @@ static const struct usb_device_id rtw_us/****** 8188EUS ********/ {USB_DEVICE(0x056e, 0x4008)}, /* Elecom WDC-150SU2M */ {USB_DEVICE(0x07b8, 0x8179)}, /* Abocom - Abocom */ + {USB_DEVICE(0x0B05, 0x18F0)}, /* ASUS USB-N10 Nano B1 */ {USB_DEVICE(0x2001, 0x330F)}, /* DLink DWA-125 REV D1 */ {USB_DEVICE(0x2001, 0x3310)}, /* Dlink DWA-123 REV D1 */ {USB_DEVICE(0x2001, 0x3311)}, /* DLink GO-USB-N150 REV B1 */
Greg Kroah-Hartman
maintainerPATCH 159/170 staging: wlan-ng: fix ODEBUG bug in prism2sta_disconnect_usb
In reply to Greg Kroah-HartmanFrom: Qiujun Huang <[email protected]>
commit a1f165a6b738f0c9d744bad4af7a53909278f5fc upstream.
We should cancel hw->usb_work before kfree(hw).
--- drivers/staging/wlan-ng/prism2usb.c | 1 + 1 file changed, 1 insertion(+)
drivers/staging/wlan-ng/prism2usb.c +1 -0
@@ -180,6 +180,7 @@ static void prism2sta_disconnect_usb(strcancel_work_sync (&hw->link_bh);cancel_work_sync (&hw->commsqual_bh); +cancel_work_sync (&hw->usb_work);/* Now we complete any outstanding commands * and tell everyone who is waiting for their
Greg Kroah-Hartman
maintainerPATCH 160/170 staging: wlan-ng: fix use-after-free Read in hfa384x_usbin_callback
In reply to Greg Kroah-HartmanFrom: Qiujun Huang <[email protected]>
commit 1165dd73e811a07d947aee218510571f516081f6 upstream.
We can't handle the case length > WLAN_DATA_MAXLEN.
Because the size of rxfrm->data is WLAN_DATA_MAXLEN(2312), and we can't read more than that.
Thanks-to: Hillf Danton <[email protected]>
--- drivers/staging/wlan-ng/hfa384x_usb.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/staging/wlan-ng/hfa384x_usb.c +2 -0
@@ -3372,6 +3372,8 @@ static void hfa384x_int_rxmonitor(struct WLAN_HDR_A4_LEN + WLAN_DATA_MAXLEN + WLAN_CRC_LEN)) {pr_debug ("overlen frm: len=%zd\n" , skblen -sizeof (struct p80211_caphdr )); + +return ; } skb =dev_alloc_skb (skblen);
Greg Kroah-Hartman
maintainerPATCH 161/170 staging: wfx: add proper "compatible" string
In reply to Greg Kroah-HartmanFrom: Michał Mirosław <[email protected]>
commit eec6e3ee636ec3adaa85ebe4b4acaacfcf06277e upstream.
Add "compatible" string matching "vendor,chip" template and proper GPIO flags handling. Keep support for old name and reset polarity for older devicetrees.
--- drivers/staging/wfx/Documentation/devicetree/bindings/net/wireless/siliabs,wfx.txt | 7 ++--- drivers/staging/wfx/bus_spi.c | 14 +++++++--- 2 files changed, 14 insertions(+), 7 deletions(-)
drivers/staging/wfx/Documentation/devicetree/bindings/net/wireless/siliabs,wfx.txt +4 -3
@@ -6,7 +6,7 @@ SPI You have to declare the WFxxx chip in your device tree. Required properties: - - compatible: Should be "silabs,wfx-spi" + - compatible: Should be "silabs,wf200" - reg: Chip select address of device - spi-max-frequency: Maximum SPI clocking speed of device in Hz - interrupts-extended: Should contain interrupt line (interrupt-parent +
@@ -15,6 +15,7 @@ Required properties: Optional properties: - reset-gpios: phandle of gpio that will be used to reset chip during probe. Without this property, you may encounter issues with warm boot. + (Legacy: when compatible == "silabs,wfx-spi", the gpio is inverted.) Please consult Documentation/devicetree/bindings/spi/spi-bus.txt for optional SPI connection related properties,
@@ -23,12 +24,12 @@ Example: &spi1 { wfx { - compatible = "silabs,wfx-spi"; + compatible = "silabs,wf200"; pinctrl-names = "default"; pinctrl-0 = <&wfx_irq &wfx_gpios>; interrupts-extended = <&gpio 16 IRQ_TYPE_EDGE_RISING>; wakeup-gpios = <&gpio 12 GPIO_ACTIVE_HIGH>; - reset-gpios = <&gpio 13 GPIO_ACTIVE_HIGH>; + reset-gpios = <&gpio 13 GPIO_ACTIVE_LOW>; reg = <0>; spi-max-frequency = <42000000>; };
drivers/staging/wfx/bus_spi.c +10 -4
@@ -27,6 +27,8 @@ MODULE_PARM_DESC(gpio_reset, "gpio numbe#define SET_WRITE 0x7FFF/* usage: and operation */ #define SET_READ 0x8000/* usage: or operation */ +#define WFX_RESET_INVERTED 1 +static const struct wfx_platform_data wfx_spi_pdata = { .file_fw ="wfm_wf200" , .file_pds ="wf200.pds" ,
@@ -199,9 +201,11 @@ static int wfx_spi_probe(struct spi_deviif (!bus->gpio_reset) {dev_warn (&func->dev,"try to load firmware anyway\n" ); }else { -gpiod_set_value (bus->gpio_reset,0 ); -udelay (100 ); +if (spi_get_device_id (func)->driver_data &WFX_RESET_INVERTED ) +gpiod_toggle_active_low (bus->gpio_reset);gpiod_set_value (bus->gpio_reset,1 ); +udelay (100 ); +gpiod_set_value (bus->gpio_reset,0 );udelay (2000 ); }
@@ -243,14 +247,16 @@ static int wfx_spi_disconnect(struct spi* stripped. */ static const struct spi_device_id wfx_spi_id[] = { - {"wfx-spi" ,0 }, + {"wfx-spi" ,WFX_RESET_INVERTED }, + {"wf200" ,0 }, { }, };MODULE_DEVICE_TABLE (spi, wfx_spi_id);#ifdef CONFIG_OF static const struct of_device_id wfx_spi_of_match[] = { - { .compatible ="silabs,wfx-spi" }, + { .compatible ="silabs,wfx-spi" , .data = (void *)WFX_RESET_INVERTED }, + { .compatible ="silabs,wf200" }, { }, };MODULE_DEVICE_TABLE (of, wfx_spi_of_match);
Greg Kroah-Hartman
maintainerPATCH 162/170 staging: wfx: fix init/remove vs IRQ race
In reply to Greg Kroah-HartmanFrom: Michał Mirosław <[email protected]>
commit 4033714d6cbe04893aa0708d1fcaa45dd8eb3f53 upstream.
Current code races in init/exit with interrupt handlers. This is noticed by the warning below. Fix it by using devres for ordering allocations and IRQ de/registration.
WARNING: CPU: 0 PID: 827 at drivers/staging/wfx/bus_spi.c:142 wfx_spi_irq_handler+0x5c/0x64 [wfx]
race condition in driver init/deinit
--- drivers/staging/wfx/bus_sdio.c | 15 ++++++--------- drivers/staging/wfx/bus_spi.c | 27 ++++++++++++++------------- drivers/staging/wfx/main.c | 21 +++++++++++++-------- drivers/staging/wfx/main.h | 1 - 4 files changed, 33 insertions(+), 31 deletions(-)
drivers/staging/wfx/bus_sdio.c +6 -9
@@ -200,25 +200,23 @@ static int wfx_sdio_probe(struct sdio_fuif (ret) goto err0; - ret =wfx_sdio_irq_subscribe (bus); -if (ret) - goto err1; - bus->core =wfx_init_common (&func->dev, &wfx_sdio_pdata, &wfx_sdio_hwbus_ops, bus);if (!bus->core) { ret = -EIO ; - goto err2; + goto err1; } + ret =wfx_sdio_irq_subscribe (bus); +if (ret) + goto err1; + ret =wfx_probe (bus->core);if (ret) - goto err3; + goto err2;return 0 ; -err3: -wfx_free_common (bus->core); err2:wfx_sdio_irq_unsubscribe (bus); err1:
@@ -234,7 +232,6 @@ static void wfx_sdio_remove(struct sdio_struct wfx_sdio_priv *bus =sdio_get_drvdata (func);wfx_release (bus->core); -wfx_free_common (bus->core);wfx_sdio_irq_unsubscribe (bus);sdio_claim_host (func);sdio_disable_func (func);
drivers/staging/wfx/bus_spi.c +14 -13
@@ -154,6 +154,11 @@ static void wfx_spi_request_rx(struct wowfx_bh_request_rx (bus->core); } +static void wfx_flush_irq_work (void *w) +{ +flush_work (w); +} +static size_t wfx_spi_align_size (void *priv,size_t size) {// Most of SPI controllers avoid DMA if buffer size is not 32bit aligned
@@ -209,22 +214,23 @@ static int wfx_spi_probe(struct spi_deviudelay (2000 ); } - ret =devm_request_irq (&func->dev, func->irq, wfx_spi_irq_handler, -IRQF_TRIGGER_RISING ,"wfx" , bus); -if (ret) -return ret; -INIT_WORK (&bus->request_rx, wfx_spi_request_rx); bus->core =wfx_init_common (&func->dev, &wfx_spi_pdata, &wfx_spi_hwbus_ops, bus);if (!bus->core)return -EIO ; - ret =wfx_probe (bus->core); + ret =devm_add_action_or_reset (&func->dev, wfx_flush_irq_work, + &bus->request_rx);if (ret) -wfx_free_common (bus->core); +return ret; + + ret =devm_request_irq (&func->dev, func->irq, wfx_spi_irq_handler, +IRQF_TRIGGER_RISING ,"wfx" , bus); +if (ret) +return ret; -return ret; +return wfx_probe (bus->core); }/* Disconnect Function to be called by SPI stack when device is disconnected */
@@ -233,11 +239,6 @@ static int wfx_spi_disconnect(struct spistruct wfx_spi_priv *bus =spi_get_drvdata (func);wfx_release (bus->core); -wfx_free_common (bus->core); -// A few IRQ will be sent during device release. Hopefully, no IRQ -// should happen after wdev/wvif are released. -devm_free_irq (&func->dev, func->irq, bus); -flush_work (&bus->request_rx);return 0 ; }
drivers/staging/wfx/main.c +13 -8
@@ -261,6 +261,16 @@ static int wfx_send_pdata_pds(struct wfxreturn ret; } +static void wfx_free_common (void *data) +{ +struct wfx_dev *wdev = data; + +mutex_destroy (&wdev->rx_stats_lock); +mutex_destroy (&wdev->conf_mutex); +wfx_tx_queues_deinit (wdev); +ieee80211_free_hw (wdev->hw); +} + struct wfx_dev *wfx_init_common(struct device *dev, const struct wfx_platform_data *pdata, const struct hwbus_ops *hwbus_ops,
@@ -326,15 +336,10 @@ struct wfx_dev *wfx_init_common(struct dwfx_init_hif_cmd (&wdev->hif_cmd);wfx_tx_queues_init (wdev); -return wdev; -} +if (devm_add_action_or_reset (dev, wfx_free_common, wdev)) +return NULL ; -void wfx_free_common (struct wfx_dev *wdev) -{ -mutex_destroy (&wdev->rx_stats_lock); -mutex_destroy (&wdev->conf_mutex); -wfx_tx_queues_deinit (wdev); -ieee80211_free_hw (wdev->hw); +return wdev; }int wfx_probe (struct wfx_dev *wdev)
drivers/staging/wfx/main.h +0 -1
@@ -34,7 +34,6 @@ struct wfx_dev *wfx_init_common(struct dconst struct wfx_platform_data *pdata, const struct hwbus_ops *hwbus_ops, void *hwbus_priv); -void wfx_free_common (struct wfx_dev *wdev);int wfx_probe (struct wfx_dev *wdev);void wfx_release (struct wfx_dev *wdev);
Greg Kroah-Hartman
maintainerPATCH 163/170 staging: wfx: annotate nested gc_list vs tx queue locking
In reply to Greg Kroah-HartmanFrom: Michał Mirosław <[email protected]>
commit e2525a95cc0887c7dc0549cb5d0ac3e796e1d54c upstream.
Lockdep is complaining about recursive locking, because it can't make a difference between locked skb_queues. Annotate nested locks and avoid double bh_disable/enable.
[...]
insmod/815 is trying to acquire lock:cb7d6418 (&(&list->lock)->rlock){+...}, at: wfx_tx_queues_clear+0xfc/0x198 [wfx]
but task is already holding lock:cb7d61f4 (&(&list->lock)->rlock){+...}, at: wfx_tx_queues_clear+0xa0/0x198 [wfx]
[...]
Possible unsafe locking scenario:
CPU0
---- lock(&(&list->lock)->rlock);
lock(&(&list->lock)->rlock);
--- drivers/staging/wfx/queue.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-)
drivers/staging/wfx/queue.c +8 -8
@@ -132,12 +132,12 @@ static void wfx_tx_queue_clear(struct wfspin_lock_bh (&queue->queue.lock);while ((item =__skb_dequeue (&queue->queue)) !=NULL )skb_queue_head (gc_list, item); -spin_lock_bh (&stats->pending.lock); +spin_lock_nested (&stats->pending.lock,1 );for (i =0 ; i <ARRAY_SIZE (stats->link_map_cache); ++i) { stats->link_map_cache[i] -= queue->link_map_cache[i]; queue->link_map_cache[i] =0 ; } -spin_unlock_bh (&stats->pending.lock); +spin_unlock (&stats->pending.lock);spin_unlock_bh (&queue->queue.lock); }
@@ -213,9 +213,9 @@ void wfx_tx_queue_put(struct wfx_dev *wd ++queue->link_map_cache[tx_priv->link_id]; -spin_lock_bh (&stats->pending.lock); +spin_lock_nested (&stats->pending.lock,1 ); ++stats->link_map_cache[tx_priv->link_id]; -spin_unlock_bh (&stats->pending.lock); +spin_unlock (&stats->pending.lock);spin_unlock_bh (&queue->queue.lock); }
@@ -244,11 +244,11 @@ static struct sk_buff *wfx_tx_queue_get(__skb_unlink (skb, &queue->queue); --queue->link_map_cache[tx_priv->link_id]; -spin_lock_bh (&stats->pending.lock); +spin_lock_nested (&stats->pending.lock,1 );__skb_queue_tail (&stats->pending, skb);if (!--stats->link_map_cache[tx_priv->link_id]) wakeup_stats = true; -spin_unlock_bh (&stats->pending.lock); +spin_unlock (&stats->pending.lock); }spin_unlock_bh (&queue->queue.lock);if (wakeup_stats)
@@ -266,10 +266,10 @@ int wfx_pending_requeue(struct wfx_dev *spin_lock_bh (&queue->queue.lock); ++queue->link_map_cache[tx_priv->link_id]; -spin_lock_bh (&stats->pending.lock); +spin_lock_nested (&stats->pending.lock,1 ); ++stats->link_map_cache[tx_priv->link_id];__skb_unlink (skb, &stats->pending); -spin_unlock_bh (&stats->pending.lock); +spin_unlock (&stats->pending.lock);__skb_queue_tail (&queue->queue, skb);spin_unlock_bh (&queue->queue.lock);return 0 ;
Greg Kroah-Hartman
maintainerPATCH 164/170 ahci: Add Intel Comet Lake H RAID PCI ID
In reply to Greg Kroah-HartmanFrom: Kai-Heng Feng <[email protected]>
commit 32d2545462c6cede998267b86e57cda5d1dc2225 upstream.
Add the PCI ID to the driver list to support this new device.
--- drivers/ata/ahci.c | 1 + 1 file changed, 1 insertion(+)
drivers/ata/ahci.c +1 -0
@@ -401,6 +401,7 @@ static const struct pci_device_id ahci_p { PCI_VDEVICE(INTEL, 0xa252), board_ahci }, /* Lewisburg RAID*/ { PCI_VDEVICE(INTEL, 0xa256), board_ahci }, /* Lewisburg RAID*/ { PCI_VDEVICE(INTEL, 0xa356), board_ahci }, /* Cannon Lake PCH-H RAID */ + { PCI_VDEVICE(INTEL, 0x06d7), board_ahci }, /* Comet Lake-H RAID */ { PCI_VDEVICE(INTEL, 0x0f22), board_ahci_mobile }, /* Bay Trail AHCI */ { PCI_VDEVICE(INTEL, 0x0f23), board_ahci_mobile }, /* Bay Trail AHCI */ { PCI_VDEVICE(INTEL, 0x22a3), board_ahci_mobile }, /* Cherry Tr. AHCI */
Greg Kroah-Hartman
maintainerPATCH 165/170 libfs: fix infoleak in simple_attr_read()
In reply to Greg Kroah-HartmanFrom: Eric Biggers <[email protected]>
commit a65cab7d7f05c2061a3e2490257d3086ff3202c6 upstream.
Reading from a debugfs file at a nonzero position, without first reading at position 0, leaks uninitialized memory to userspace.
It's a bit tricky to do this, since lseek() and pread() aren't allowed on these files, and write() doesn't update the position on them. But writing to them with splice() *does* update the position:
#define _GNU_SOURCE 1
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
int main()
{
int pipes[2], fd, n, i;
char buf[32];
pipe(pipes);
write(pipes[1], "0", 1);
fd = open("/sys/kernel/debug/fault_around_bytes", O_RDWR);
splice(pipes[0], NULL, fd, NULL, 1, 0);
n = read(fd, buf, sizeof(buf));
for (i = 0; i < n; i++)
printf("%02x", buf[i]);
printf("\n");
}Output:
5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a30
Fix the infoleak by making simple_attr_read() always fill simple_attr::get_buf if it hasn't been filled yet.
--- fs/libfs.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-)
fs/libfs.c +5 -3
@@ -821,7 +821,7 @@ int simple_attr_open(struct inode *inode {struct simple_attr *attr; - attr =kmalloc (sizeof (*attr),GFP_KERNEL ); + attr =kzalloc (sizeof (*attr),GFP_KERNEL );if (!attr)return -ENOMEM ;
@@ -861,9 +861,11 @@ ssize_t simple_attr_read(struct file *fiif (ret)return ret; -if (*ppos) {/* continued read */ +if (*ppos && attr->get_buf[0 ]) { +/* continued read */ size =strlen (attr->get_buf); - }else {/* first read */ + }else { +/* first read */ u64 val; ret = attr->get (attr->data, &val);if (ret)
Greg Kroah-Hartman
maintainerPATCH 166/170 media: ov519: add missing endpoint sanity checks
In reply to Greg Kroah-HartmanFrom: Johan Hovold <[email protected]>
commit 998912346c0da53a6dbb71fab3a138586b596b30 upstream.
Make sure to check that we have at least one endpoint before accessing the endpoint array to avoid dereferencing a NULL-pointer on stream start.
Note that these sanity checks are not redundant as the driver is mixing looking up altsettings by index and by number, which need not coincide.
--- drivers/media/usb/gspca/ov519.c | 10 ++++++++++ 1 file changed, 10 insertions(+)
drivers/media/usb/gspca/ov519.c +10 -0
@@ -3477,6 +3477,11 @@ static void ov511_mode_init_regs(structreturn ; } +if (alt->desc.bNumEndpoints <1 ) { + sd->gspca_dev.usb_err = -ENODEV ; +return ; + } + packet_size =le16_to_cpu (alt->endpoint[0 ].desc.wMaxPacketSize);reg_w (sd, R51x_FIFO_PSIZE, packet_size >>5 );
@@ -3603,6 +3608,11 @@ static void ov518_mode_init_regs(structreturn ; } +if (alt->desc.bNumEndpoints <1 ) { + sd->gspca_dev.usb_err = -ENODEV ; +return ; + } + packet_size =le16_to_cpu (alt->endpoint[0 ].desc.wMaxPacketSize);ov518_reg_w32 (sd, R51x_FIFO_PSIZE, packet_size & ~7 ,2 );
Greg Kroah-Hartman
maintainerPATCH 167/170 media: dib0700: fix rc endpoint lookup
In reply to Greg Kroah-HartmanFrom: Johan Hovold <[email protected]>
commit f52981019ad8d6718de79b425a574c6bddf81f7c upstream.
Make sure to use the current alternate setting when verifying the interface descriptors to avoid submitting an URB to an invalid endpoint.
Failing to do so could cause the driver to misbehave or trigger a WARN() in usb_submit_urb() that kernels with panic_on_warn set would choke on.
--- drivers/media/usb/dvb-usb/dib0700_core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/media/usb/dvb-usb/dib0700_core.c +2 -2
@@ -818,7 +818,7 @@ int dib0700_rc_setup(struct dvb_usb_devi/* Starting in firmware 1.20, the RC info is provided on a bulk pipe */ -if (intf->altsetting[0 ].desc.bNumEndpoints < rc_ep +1 ) +if (intf->cur_altsetting->desc.bNumEndpoints < rc_ep +1 )return -ENODEV ; purb =usb_alloc_urb (0 ,GFP_KERNEL );
@@ -838,7 +838,7 @@ int dib0700_rc_setup(struct dvb_usb_devi* Some devices like the Hauppauge NovaTD model 52009 use an interrupt * endpoint, while others use a bulk one. */ - e = &intf->altsetting[0 ].endpoint[rc_ep].desc; + e = &intf->cur_altsetting->endpoint[rc_ep].desc;if (usb_endpoint_dir_in (e)) {if (usb_endpoint_xfer_bulk (e)) { pipe =usb_rcvbulkpipe (d->udev, rc_ep);
Greg Kroah-Hartman
maintainerPATCH 168/170 media: stv06xx: add missing descriptor sanity checks
In reply to Greg Kroah-HartmanFrom: Johan Hovold <[email protected]>
commit 485b06aadb933190f4bc44e006076bc27a23f205 upstream.
Make sure to check that we have two alternate settings and at least one endpoint before accessing the second altsetting structure and dereferencing the endpoint arrays.
This specifically avoids dereferencing NULL-pointers or corrupting memory when a device does not have the expected descriptors.
Note that the sanity checks in stv06xx_start() and pb0100_start() are not redundant as the driver is mixing looking up altsettings by index and by number, which may not coincide.
--- drivers/media/usb/gspca/stv06xx/stv06xx.c | 19 ++++++++++++++++++- drivers/media/usb/gspca/stv06xx/stv06xx_pb0100.c | 4 ++++ 2 files changed, 22 insertions(+), 1 deletion(-)
drivers/media/usb/gspca/stv06xx/stv06xx.c +18 -1
@@ -282,6 +282,9 @@ static int stv06xx_start(struct gspca_dereturn -EIO ; } +if (alt->desc.bNumEndpoints <1 ) +return -ENODEV ; + packet_size =le16_to_cpu (alt->endpoint[0 ].desc.wMaxPacketSize); err =stv06xx_write_bridge (sd,STV_ISO_SIZE_L , packet_size);if (err <0 )
@@ -306,11 +309,21 @@ out:static int stv06xx_isoc_init (struct gspca_dev *gspca_dev) { +struct usb_interface_cache *intfc;struct usb_host_interface *alt;struct sd *sd = (struct sd *) gspca_dev; + intfc = gspca_dev->dev->actconfig->intf_cache[0 ]; + +if (intfc->num_altsetting <2 ) +return -ENODEV ; + + alt = &intfc->altsetting[1 ]; + +if (alt->desc.bNumEndpoints <1 ) +return -ENODEV ; +/* Start isoc bandwidth "negotiation" at max isoc bandwidth */ - alt = &gspca_dev->dev->actconfig->intf_cache[0 ]->altsetting[1 ]; alt->endpoint[0 ].desc.wMaxPacketSize =cpu_to_le16 (sd->sensor->max_packet_size[gspca_dev->curr_mode]);
@@ -323,6 +336,10 @@ static int stv06xx_isoc_nego(struct gspcstruct usb_host_interface *alt;struct sd *sd = (struct sd *) gspca_dev; +/* +* Existence of altsetting and endpoint was verified in +* stv06xx_isoc_init() +*/ alt = &gspca_dev->dev->actconfig->intf_cache[0 ]->altsetting[1 ]; packet_size =le16_to_cpu (alt->endpoint[0 ].desc.wMaxPacketSize); min_packet_size = sd->sensor->min_packet_size[gspca_dev->curr_mode];
drivers/media/usb/gspca/stv06xx/stv06xx_pb0100.c +4 -0
@@ -185,6 +185,10 @@ static int pb0100_start(struct sd *sd) alt =usb_altnum_to_altsetting (intf, sd->gspca_dev.alt);if (!alt)return -ENODEV ; + +if (alt->desc.bNumEndpoints <1 ) +return -ENODEV ; + packet_size =le16_to_cpu (alt->endpoint[0 ].desc.wMaxPacketSize);/* If we don't have enough bandwidth use a lower framerate */
Greg Kroah-Hartman
maintainerPATCH 169/170 media: xirlink_cit: add missing descriptor sanity checks
In reply to Greg Kroah-HartmanFrom: Johan Hovold <[email protected]>
commit a246b4d547708f33ff4d4b9a7a5dbac741dc89d8 upstream.
Make sure to check that we have two alternate settings and at least one endpoint before accessing the second altsetting structure and dereferencing the endpoint arrays.
This specifically avoids dereferencing NULL-pointers or corrupting memory when a device does not have the expected descriptors.
Note that the sanity check in cit_get_packet_size() is not redundant as the driver is mixing looking up altsettings by index and by number, which may not coincide.
--- drivers/media/usb/gspca/xirlink_cit.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-)
drivers/media/usb/gspca/xirlink_cit.c +17 -1
@@ -1442,6 +1442,9 @@ static int cit_get_packet_size(struct gsreturn -EIO ; } +if (alt->desc.bNumEndpoints <1 ) +return -ENODEV ; +return le16_to_cpu (alt->endpoint[0 ].desc.wMaxPacketSize); }
@@ -2626,6 +2629,7 @@ static int sd_start(struct gspca_dev *gsstatic int sd_isoc_init (struct gspca_dev *gspca_dev) { +struct usb_interface_cache *intfc;struct usb_host_interface *alt;int max_packet_size;
@@ -2641,8 +2645,17 @@ static int sd_isoc_init(struct gspca_devbreak ; } + intfc = gspca_dev->dev->actconfig->intf_cache[0 ]; + +if (intfc->num_altsetting <2 ) +return -ENODEV ; + + alt = &intfc->altsetting[1 ]; + +if (alt->desc.bNumEndpoints <1 ) +return -ENODEV ; +/* Start isoc bandwidth "negotiation" at max isoc bandwidth */ - alt = &gspca_dev->dev->actconfig->intf_cache[0 ]->altsetting[1 ]; alt->endpoint[0 ].desc.wMaxPacketSize =cpu_to_le16 (max_packet_size);return 0 ;
@@ -2665,6 +2678,9 @@ static int sd_isoc_nego(struct gspca_devbreak ; } +/* +* Existence of altsetting and endpoint was verified in sd_isoc_init() +*/ alt = &gspca_dev->dev->actconfig->intf_cache[0 ]->altsetting[1 ]; packet_size =le16_to_cpu (alt->endpoint[0 ].desc.wMaxPacketSize);if (packet_size <= min_packet_size)
Greg Kroah-Hartman
maintainerPATCH 170/170 media: v4l2-core: fix a use-after-free bug of sd->devnode
In reply to Greg Kroah-HartmanFrom: Dafna Hirschfeld <[email protected]>
commit 6990570f7e0a6078e11b9c5dc13f4b6e3f49a398 upstream.
sd->devnode is released after callingv4l2_subdev_release. Therefore it should be set
to NULL so that the subdev won't hold a pointer
to a released object. This fixes a reference
after free bug in functionv4l2_device_unregister_subdev
--- drivers/media/v4l2-core/v4l2-device.c | 1 + 1 file changed, 1 insertion(+)
drivers/media/v4l2-core/v4l2-device.c +1 -0
@@ -179,6 +179,7 @@ static void v4l2_subdev_release(struct vif (sd->internal_ops && sd->internal_ops->release) sd->internal_ops->release (sd); + sd->devnode =NULL ;module_put (owner); }