4.4.199-stable review
Subsystems (6)
Greg Kroah-Hartman
maintainercover 4.4.199-stable review
This is the start of the stable review cycle for the 4.4.199 release. There are 46 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Wed 06 Nov 2019 09:14:04 PM UTC. Anything received after that time might be too late.
The whole patch series can be found in one patch at:
https://www.kernel.org/pub/linux/kernel/v4.x/stable-review/patch-4.4.199-rc1.gz
or in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git linux-4.4.y
and the diffstat can be found below.
thanks,
greg k-h
-------------
Pseudo-Shortlog of commits:
Greg Kroah-Hartman <[email protected]>
Linux 4.4.199-rc1
Vratislav Bendel <[email protected]>
xfs: Correctly invert xfs_buftarg LRU isolation logic
Xin Long <[email protected]>
sctp: not bind the socket in sctp_connect
Xin Long <[email protected]>
sctp: fix the issue that flags are ignored when using kernel_connect
Eric Dumazet <[email protected]>
sch_netem: fix rcu splat in netem_enqueue()
Valentin Vidic <[email protected]>
net: usb: sr9800: fix uninitialized local variable
Eric Dumazet <[email protected]>
bonding: fix potential NULL deref in bond_update_slave_arr
Eric Biggers <[email protected]>
llc: fix sk_buff leak in llc_conn_service()
Eric Biggers <[email protected]>
llc: fix sk_buff leak in llc_sap_state_process()
Laura Abbott <[email protected]>
rtlwifi: Fix potential overflow on P2P code
Yihui ZENG <[email protected]>
s390/cmm: fix information leak in cmm_timeout_handler()
Markus Theil <[email protected]>
nl80211: fix validation of mesh path nexthop
Michał Mirosław <[email protected]>
HID: fix error message in hid_open_report()
Alan Stern <[email protected]>
HID: Fix assumption that devices have inputs
Johan Hovold <[email protected]>
USB: serial: whiteheat: fix line-speed endianness
Johan Hovold <[email protected]>
USB: serial: whiteheat: fix potential slab corruption
Johan Hovold <[email protected]>
USB: ldusb: fix control-message timeout
Johan Hovold <[email protected]>
USB: ldusb: fix ring-buffer locking
Alan Stern <[email protected]>
USB: gadget: Reject endpoints with 0 maxpacket value
Alan Stern <[email protected]>
UAS: Revert commit 3ae62a42090f ("UAS: fix alignment of scatter/gather segments")
Takashi Sakamoto <[email protected]>
ALSA: bebob: Fix prototype of helper function to return negative value
Miklos Szeredi <[email protected]>
fuse: truncate pending writes on O_TRUNC
Miklos Szeredi <[email protected]>
fuse: flush dirty data/metadata before non-truncate setattr
Hui Peng <[email protected]>
ath6kl: fix a NULL-ptr-deref bug in ath6kl_usb_alloc_urb_from_pipe()
Mika Westerberg <[email protected]>
thunderbolt: Use 32-bit writes when writing ring producer/consumer
Dan Carpenter <[email protected]>
USB: legousbtower: fix a signedness bug in tower_probe()
Petr Mladek <[email protected]>
tracing: Initialize iter->seq after zeroing in tracing_read_pipe()
Chuck Lever <[email protected]>
NFSv4: Fix leak of clp->cl_acceptor string
Thomas Bogendoerfer <[email protected]>
MIPS: fw: sni: Fix out of bounds init of o32 stack
Jia-Ju Bai <[email protected]>
fs: ocfs2: fix a possible null-pointer dereference in ocfs2_info_scan_inode_alloc()
Jia-Ju Bai <[email protected]>
fs: ocfs2: fix possible null-pointer dereferences in ocfs2_xa_prepare_entry()
Dave Young <[email protected]>
efi/x86: Do not clean dummy variable in kexec path
Lukas Wunner <[email protected]>
efi/cper: Fix endianness of PCIe class code
Adam Ford <[email protected]>
serial: mctrl_gpio: Check for NULL pointer
Austin Kim <[email protected]>
fs: cifs: mute -Wunused-const-variable message
Bart Van Assche <[email protected]>
RDMA/iwcm: Fix a lock inversion issue
Steve MacLean <[email protected]>
perf map: Fix overlapped map handling
Pascal Bouwmann <[email protected]>
iio: fix center temperature of bmc150-accel-core
Kees Cook <[email protected]>
exec: load_script: Do not exec truncated interpreter path
Jan-Marek Glogowski <[email protected]>
usb: handle warm-reset port requests on hub resume
Brian Norris <[email protected]>
scripts/setlocalversion: Improve -dirty check with git-status --no-optional-locks
Kan Liang <[email protected]>
x86/cpu: Add Atom Tremont (Jacobsville)
Phil Elwell <[email protected]>
sc16is7xx: Fix for "Unexpected interrupt: 8"
Kent Overstreet <[email protected]>
dm: Use kzalloc for all structs with embedded biosets/mempools
Mikulas Patocka <[email protected]>
dm snapshot: rework COW throttling to fix deadlock
Mikulas Patocka <[email protected]>
dm snapshot: introduce account_start_copy() and account_end_copy()
Mikulas Patocka <[email protected]>
dm snapshot: use mutex instead of rw_semaphore
-------------
Diffstat:
Makefile | 4 +- arch/mips/fw/sni/sniprom.c | 2 +- arch/s390/mm/cmm.c | 12 +- arch/x86/include/asm/intel-family.h | 3 +- arch/x86/platform/efi/efi.c | 3 - drivers/firmware/efi/cper.c | 2 +- drivers/hid/hid-axff.c | 11 +- drivers/hid/hid-core.c | 7 +- drivers/hid/hid-dr.c | 12 +- drivers/hid/hid-emsff.c | 12 +- drivers/hid/hid-gaff.c | 12 +- drivers/hid/hid-holtekff.c | 12 +- drivers/hid/hid-lg2ff.c | 12 +- drivers/hid/hid-lg3ff.c | 11 +- drivers/hid/hid-lg4ff.c | 11 +- drivers/hid/hid-lgff.c | 11 +- drivers/hid/hid-sony.c | 12 +- drivers/hid/hid-tmff.c | 12 +- drivers/hid/hid-zpff.c | 12 +- drivers/iio/accel/bmc150-accel-core.c | 2 +- drivers/infiniband/core/cma.c | 3 +- drivers/md/dm-bio-prison.c | 2 +- drivers/md/dm-io.c | 2 +- drivers/md/dm-kcopyd.c | 2 +- drivers/md/dm-region-hash.c | 2 +- drivers/md/dm-snap.c | 178 ++++++++++++++++++++---------- drivers/md/dm-thin.c | 2 +- drivers/net/bonding/bond_main.c | 2 +- drivers/net/usb/sr9800.c | 2 +- drivers/net/wireless/ath/ath6kl/usb.c | 8 ++ drivers/net/wireless/realtek/rtlwifi/ps.c | 6 + drivers/thunderbolt/nhi.c | 22 +++- drivers/tty/serial/sc16is7xx.c | 28 +++++ drivers/tty/serial/serial_mctrl_gpio.c | 3 + drivers/usb/core/hub.c | 7 ++ drivers/usb/misc/ldusb.c | 6 +- drivers/usb/misc/legousbtower.c | 2 +- drivers/usb/serial/whiteheat.c | 13 ++- drivers/usb/serial/whiteheat.h | 2 +- drivers/usb/storage/uas.c | 20 ---- fs/binfmt_script.c | 57 ++++++++-- fs/cifs/netmisc.c | 4 - fs/fuse/dir.c | 13 +++ fs/fuse/file.c | 10 +- fs/nfs/nfs4proc.c | 1 + fs/ocfs2/ioctl.c | 2 +- fs/ocfs2/xattr.c | 56 ++++------ fs/xfs/xfs_buf.c | 2 +- include/linux/usb/gadget.h | 10 ++ include/net/llc_conn.h | 2 +- include/net/sch_generic.h | 5 + include/net/sctp/sctp.h | 2 + kernel/trace/trace.c | 1 + net/llc/llc_c_ac.c | 8 +- net/llc/llc_conn.c | 32 ++---- net/llc/llc_s_ac.c | 12 +- net/llc/llc_sap.c | 23 ++-- net/sched/sch_netem.c | 2 +- net/sctp/ipv6.c | 2 +- net/sctp/protocol.c | 2 +- net/sctp/socket.c | 55 ++++----- net/wireless/nl80211.c | 3 +- scripts/setlocalversion | 12 +- sound/firewire/bebob/bebob_stream.c | 3 +- tools/perf/util/map.c | 3 + 65 files changed, 532 insertions(+), 277 deletions(-)
Greg Kroah-Hartman
maintainerPATCH 1/46 dm snapshot: use mutex instead of rw_semaphore
From: Mikulas Patocka <[email protected]>
[ Upstream commit ae1093be5a0ef997833e200a0dafb9ed0b1ff4fe ]
The rw_semaphore is acquired for read only in two places, neither is performance-critical. So replace it with a mutex -- which is more efficient.
--- drivers/md/dm-snap.c | 84 +++++++++++++++++++++++--------------------- 1 file changed, 43 insertions(+), 41 deletions(-)
drivers/md/dm-snap.c +43 -41
@@ -48,7 +48,7 @@ struct dm_exception_table { };struct dm_snapshot { -struct rw_semaphore lock; +struct mutex lock;struct dm_dev *origin;struct dm_dev *cow;
@@ -457,9 +457,9 @@ static int __find_snapshots_sharing_cow(struct dm_snapshot *snap,if (!bdev_equal (s->cow->bdev, snap->cow->bdev))continue ; -down_read (&s->lock); +mutex_lock (&s->lock); active = s->active; -up_read (&s->lock); +mutex_unlock (&s->lock);if (active) {if (snap_src)
@@ -927,7 +927,7 @@ static int remove_single_exception_chunk(struct dm_snapshot *s)int r;chunk_t old_chunk = s->first_merging_chunk + s->num_merging_chunks -1 ; -down_write (&s->lock); +mutex_lock (&s->lock);/* * Process chunks (and associated exceptions) in reverse order
@@ -942,7 +942,7 @@ static int remove_single_exception_chunk(struct dm_snapshot *s) b =__release_queued_bios_after_merge (s); out: -up_write (&s->lock); +mutex_unlock (&s->lock);if (b)flush_bios (b);
@@ -1001,9 +1001,9 @@ static void snapshot_merge_next_chunks(struct dm_snapshot *s)if (linear_chunks <0 ) {DMERR ("Read error in exception store: " "shutting down merge" ); -down_write (&s->lock); +mutex_lock (&s->lock); s->merge_failed =1 ; -up_write (&s->lock); +mutex_unlock (&s->lock); } goto shut; }
@@ -1044,10 +1044,10 @@ static void snapshot_merge_next_chunks(struct dm_snapshot *s) previous_count =read_pending_exceptions_done_count (); } -down_write (&s->lock); +mutex_lock (&s->lock); s->first_merging_chunk = old_chunk; s->num_merging_chunks = linear_chunks; -up_write (&s->lock); +mutex_unlock (&s->lock);/* Wait until writes to all 'linear_chunks' drain */ for (i =0 ; i < linear_chunks; i++)
@@ -1089,10 +1089,10 @@ static void merge_callback(int read_err, unsigned long write_err, void *context)return ; shut: -down_write (&s->lock); +mutex_lock (&s->lock); s->merge_failed =1 ; b =__release_queued_bios_after_merge (s); -up_write (&s->lock); +mutex_unlock (&s->lock);error_bios (b);merge_shutdown (s);
@@ -1191,7 +1191,7 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv) s->exception_start_sequence =0 ; s->exception_complete_sequence =0 ;INIT_LIST_HEAD (&s->out_of_order_list); -init_rwsem (&s->lock); +mutex_init (&s->lock);INIT_LIST_HEAD (&s->list);spin_lock_init (&s->pe_lock); s->state_bits =0 ;
@@ -1358,9 +1358,9 @@ static void snapshot_dtr(struct dm_target *ti)/* Check whether exception handover must be cancelled */ (void )__find_snapshots_sharing_cow (s, &snap_src, &snap_dest,NULL );if (snap_src && snap_dest && (s == snap_src)) { -down_write (&snap_dest->lock); +mutex_lock (&snap_dest->lock); snap_dest->valid =0 ; -up_write (&snap_dest->lock); +mutex_unlock (&snap_dest->lock);DMERR ("Cancelling snapshot handover." ); }up_read (&_origins_lock);
@@ -1391,6 +1391,8 @@ static void snapshot_dtr(struct dm_target *ti)dm_exception_store_destroy (s->store); +mutex_destroy (&s->lock); +dm_put_device (ti, s->cow);dm_put_device (ti, s->origin);
@@ -1478,7 +1480,7 @@ static void pending_complete(void *context, int success)if (!success) {/* Read/write error - snapshot is unusable */ -down_write (&s->lock); +mutex_lock (&s->lock);__invalidate_snapshot (s, -EIO ); error =1 ; goto out;
@@ -1486,14 +1488,14 @@ static void pending_complete(void *context, int success) e =alloc_completed_exception (GFP_NOIO );if (!e) { -down_write (&s->lock); +mutex_lock (&s->lock);__invalidate_snapshot (s, -ENOMEM ); error =1 ; goto out; } *e = pe->e; -down_write (&s->lock); +mutex_lock (&s->lock);if (!s->valid) {free_completed_exception (e); error =1 ;
@@ -1520,7 +1522,7 @@ out: }increment_pending_exceptions_done_count (); -up_write (&s->lock); +mutex_unlock (&s->lock);/* Submit any pending write bios */ if (error) {
@@ -1720,7 +1722,7 @@ static int snapshot_map(struct dm_target *ti, struct bio *bio)/* FIXME: should only take write lock if we need * to copy an exception */ -down_write (&s->lock); +mutex_lock (&s->lock);if (!s->valid || (unlikely (s->snapshot_overflowed) &&bio_rw (bio) ==WRITE )) { r = -EIO ;
@@ -1742,9 +1744,9 @@ static int snapshot_map(struct dm_target *ti, struct bio *bio)if (bio_rw (bio) ==WRITE ) { pe =__lookup_pending_exception (s, chunk);if (!pe) { -up_write (&s->lock); +mutex_unlock (&s->lock); pe =alloc_pending_exception (s); -down_write (&s->lock); +mutex_lock (&s->lock);if (!s->valid || s->snapshot_overflowed) {free_pending_exception (pe);
@@ -1779,7 +1781,7 @@ static int snapshot_map(struct dm_target *ti, struct bio *bio) bio->bi_iter.bi_size == (s->store->chunk_size << SECTOR_SHIFT)) { pe->started =1 ; -up_write (&s->lock); +mutex_unlock (&s->lock);start_full_bio (pe, bio); goto out; }
@@ -1789,7 +1791,7 @@ static int snapshot_map(struct dm_target *ti, struct bio *bio)if (!pe->started) {/* this is protected by snap->lock */ pe->started =1 ; -up_write (&s->lock); +mutex_unlock (&s->lock);start_copy (pe); goto out; }
@@ -1799,7 +1801,7 @@ static int snapshot_map(struct dm_target *ti, struct bio *bio) } out_unlock: -up_write (&s->lock); +mutex_unlock (&s->lock); out:return r; }
@@ -1835,7 +1837,7 @@ static int snapshot_merge_map(struct dm_target *ti, struct bio *bio) chunk =sector_to_chunk (s->store, bio->bi_iter.bi_sector); -down_write (&s->lock); +mutex_lock (&s->lock);/* Full merging snapshots are redirected to the origin */ if (!s->valid)
@@ -1866,12 +1868,12 @@ redirect_to_origin: bio->bi_bdev = s->origin->bdev;if (bio_rw (bio) ==WRITE ) { -up_write (&s->lock); +mutex_unlock (&s->lock);return do_origin (s->origin, bio); } out_unlock: -up_write (&s->lock); +mutex_unlock (&s->lock);return r; }
@@ -1902,7 +1904,7 @@ static int snapshot_preresume(struct dm_target *ti)down_read (&_origins_lock); (void )__find_snapshots_sharing_cow (s, &snap_src, &snap_dest,NULL );if (snap_src && snap_dest) { -down_read (&snap_src->lock); +mutex_lock (&snap_src->lock);if (s == snap_src) {DMERR ("Unable to resume snapshot source until " "handover completes." );
@@ -1912,7 +1914,7 @@ static int snapshot_preresume(struct dm_target *ti) "source is suspended."); r = -EINVAL ; } -up_read (&snap_src->lock); +mutex_unlock (&snap_src->lock); }up_read (&_origins_lock);
@@ -1958,11 +1960,11 @@ static void snapshot_resume(struct dm_target *ti) (void )__find_snapshots_sharing_cow (s, &snap_src, &snap_dest,NULL );if (snap_src && snap_dest) { -down_write (&snap_src->lock); -down_write_nested (&snap_dest->lock,SINGLE_DEPTH_NESTING ); +mutex_lock (&snap_src->lock); +mutex_lock_nested (&snap_dest->lock,SINGLE_DEPTH_NESTING );__handover_exceptions (snap_src, snap_dest); -up_write (&snap_dest->lock); -up_write (&snap_src->lock); +mutex_unlock (&snap_dest->lock); +mutex_unlock (&snap_src->lock); }up_read (&_origins_lock);
@@ -1977,9 +1979,9 @@ static void snapshot_resume(struct dm_target *ti)/* Now we have correct chunk size, reregister */ reregister_snapshot (s); -down_write (&s->lock); +mutex_lock (&s->lock); s->active =1 ; -up_write (&s->lock); +mutex_unlock (&s->lock); }static uint32_t get_origin_minimum_chunksize (struct block_device *bdev)
@@ -2019,7 +2021,7 @@ static void snapshot_status(struct dm_target *ti, status_type_t type,switch (type) {case STATUSTYPE_INFO : -down_write (&snap->lock); +mutex_lock (&snap->lock);if (!snap->valid)DMEMIT ("Invalid" );
@@ -2044,7 +2046,7 @@ static void snapshot_status(struct dm_target *ti, status_type_t type,DMEMIT ("Unknown" ); } -up_write (&snap->lock); +mutex_unlock (&snap->lock);break ;
@@ -2110,7 +2112,7 @@ static int __origin_write(struct list_head *snapshots, sector_t sector,if (dm_target_is_snapshot_merge (snap->ti))continue ; -down_write (&snap->lock); +mutex_lock (&snap->lock);/* Only deal with valid and active snapshots */ if (!snap->valid || !snap->active)
@@ -2137,9 +2139,9 @@ static int __origin_write(struct list_head *snapshots, sector_t sector, pe =__lookup_pending_exception (snap, chunk);if (!pe) { -up_write (&snap->lock); +mutex_unlock (&snap->lock); pe =alloc_pending_exception (snap); -down_write (&snap->lock); +mutex_lock (&snap->lock);if (!snap->valid) {free_pending_exception (pe);
@@ -2182,7 +2184,7 @@ static int __origin_write(struct list_head *snapshots, sector_t sector, } next_snapshot: -up_write (&snap->lock); +mutex_unlock (&snap->lock);if (pe_to_start_now) {start_copy (pe_to_start_now);
Signature · 1 line
2.20.1
Greg Kroah-Hartman
maintainerPATCH 2/46 dm snapshot: introduce account_start_copy() and account_end_copy()
In reply to Greg Kroah-HartmanFrom: Mikulas Patocka <[email protected]>
[ Upstream commit a2f83e8b0c82c9500421a26c49eb198b25fcdea3 ]
This simple refactoring moves code for modifying the semaphore cow_count into separate functions to prepare for changes that will extend these methods to provide for a more sophisticated mechanism for COW throttling.
--- drivers/md/dm-snap.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-)
drivers/md/dm-snap.c +13 -3
@@ -1400,6 +1400,16 @@ static void snapshot_dtr(struct dm_target *ti)kfree (s); } +static void account_start_copy (struct dm_snapshot *s) +{ +down (&s->cow_count); +} + +static void account_end_copy (struct dm_snapshot *s) +{ +up (&s->cow_count); +} +/* * Flush a list of buffers. */
@@ -1584,7 +1594,7 @@ static void copy_callback(int read_err, unsigned long write_err, void *context) }list_add (&pe->out_of_order_entry, lh); } -up (&s->cow_count); +account_end_copy (s); }/*
@@ -1608,7 +1618,7 @@ static void start_copy(struct dm_snap_pending_exception *pe) dest.count = src.count;/* Hand over to kcopyd */ -down (&s->cow_count); +account_start_copy (s);dm_kcopyd_copy (s->kcopyd_client, &src,1 , &dest,0 , copy_callback, pe); }
@@ -1629,7 +1639,7 @@ static void start_full_bio(struct dm_snap_pending_exception *pe, pe->full_bio_end_io = bio->bi_end_io; pe->full_bio_private = bio->bi_private; -down (&s->cow_count); +account_start_copy (s); callback_data =dm_kcopyd_prepare_callback (s->kcopyd_client, copy_callback, pe);
Signature · 1 line
2.20.1
Greg Kroah-Hartman
maintainerPATCH 3/46 dm snapshot: rework COW throttling to fix deadlock
In reply to Greg Kroah-HartmanFrom: Mikulas Patocka <[email protected]>
[ Upstream commit b21555786f18cd77f2311ad89074533109ae3ffa ]
Commit 721b1d98fb517a ("dm snapshot: Fix excessive memory usage and workqueue stalls") introduced a semaphore to limit the maximum number of in-flight kcopyd (COW) jobs.
The implementation of this throttling mechanism is prone to a deadlock:
1. One or more threads write to the origin device causing COW, which is performed by kcopyd.
2. At some point some of these threads might reach the s->cow_count semaphore limit and block in down(&s->cow_count), holding a read lock on _origins_lock.
3. Someone tries to acquire a write lock on _origins_lock, e.g., snapshot_ctr(), which blocks because the threads at step (2) already hold a read lock on it.
4. A COW operation completes and kcopyd runs dm-snapshot's completion callback, which ends up calling pending_complete(). pending_complete() tries to resubmit any deferred origin bios. This requires acquiring a read lock on _origins_lock, which blocks.
This happens because the read-write semaphore implementation gives priority to writers, meaning that as soon as a writer tries to enter the critical section, no readers will be allowed in, until all writers have completed their work.
So, pending_complete() waits for the writer at step (3) to acquire and release the lock. This writer waits for the readers at step (2) to release the read lock and those readers wait for pending_complete() (the kcopyd thread) to signal the s->cow_count
semaphore: DEADLOCK.
The above was thoroughly analyzed and documented by Nikos Tsironis as part of his initial proposal for fixing this deadlock, see:
https://www.redhat.com/archives/dm-devel/2019-October/msg00001.html
Fix this deadlock by reworking COW throttling so that it waits without holding any locks. Add a variable 'in_progress' that counts how many kcopyd jobs are running. A function wait_for_in_progress() will sleep if 'in_progress' is over the limit. It drops _origins_lock in order to avoid the deadlock.
Depends-on: 4a3f111a73a8c ("dm snapshot: introduce account_start_copy() and account_end_copy()")
--- drivers/md/dm-snap.c | 80 +++++++++++++++++++++++++++++++++++--------- 1 file changed, 64 insertions(+), 16 deletions(-)
drivers/md/dm-snap.c +64 -16
@@ -19,7 +19,6 @@#include <linux/vmalloc.h> #include <linux/log2.h> #include <linux/dm-kcopyd.h> -#include <linux/semaphore.h> #include "dm.h"
@@ -106,8 +105,8 @@ struct dm_snapshot {/* The on disk metadata handler */ struct dm_exception_store *store; -/* Maximum number of in-flight COW jobs. */ -struct semaphore cow_count; +unsigned in_progress; +wait_queue_head_t in_progress_wait;struct dm_kcopyd_client *kcopyd_client;
@@ -158,8 +157,8 @@ struct dm_snapshot {*/ #define DEFAULT_COW_THRESHOLD 2048 -static int cow_threshold =DEFAULT_COW_THRESHOLD ; -module_param_named (snapshot_cow_threshold, cow_threshold, int,0644 ); +static unsigned cow_threshold =DEFAULT_COW_THRESHOLD ; +module_param_named (snapshot_cow_threshold, cow_threshold, uint,0644 );MODULE_PARM_DESC (snapshot_cow_threshold,"Maximum number of chunks being copied on write" ); DECLARE_DM_KCOPYD_THROTTLE_WITH_MODULE_PARM(snapshot_copy_throttle,
@@ -1207,7 +1206,7 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv) goto bad_hash_tables; } -sema_init (&s->cow_count, (cow_threshold >0 ) ? cow_threshold :INT_MAX ); +init_waitqueue_head (&s->in_progress_wait); s->kcopyd_client =dm_kcopyd_client_create (&dm_kcopyd_throttle);if (IS_ERR (s->kcopyd_client)) {
@@ -1397,17 +1396,54 @@ static void snapshot_dtr(struct dm_target *ti)dm_put_device (ti, s->origin); +WARN_ON (s->in_progress); +kfree (s); }static void account_start_copy (struct dm_snapshot *s) { -down (&s->cow_count); +spin_lock (&s->in_progress_wait.lock); + s->in_progress++; +spin_unlock (&s->in_progress_wait.lock); }static void account_end_copy (struct dm_snapshot *s) { -up (&s->cow_count); +spin_lock (&s->in_progress_wait.lock); +BUG_ON (!s->in_progress); + s->in_progress--; +if (likely (s->in_progress <= cow_threshold) && +unlikely (waitqueue_active (&s->in_progress_wait))) +wake_up_locked (&s->in_progress_wait); +spin_unlock (&s->in_progress_wait.lock); +} + +static bool wait_for_in_progress (struct dm_snapshot *s,bool unlock_origins) +{ +if (unlikely (s->in_progress > cow_threshold)) { +spin_lock (&s->in_progress_wait.lock); +if (likely (s->in_progress > cow_threshold)) { +/* +* NOTE: this throttle doesn't account for whether +* the caller is servicing an IO that will trigger a COW +* so excess throttling may result for chunks not required +* to be COW'd. But if cow_threshold was reached, extra +* throttling is unlikely to negatively impact performance. +*/ +DECLARE_WAITQUEUE (wait, current); +__add_wait_queue (&s->in_progress_wait, &wait); +__set_current_state (TASK_UNINTERRUPTIBLE ); +spin_unlock (&s->in_progress_wait.lock); +if (unlock_origins) +up_read (&_origins_lock); +io_schedule (); +remove_wait_queue (&s->in_progress_wait, &wait); +return false; + } +spin_unlock (&s->in_progress_wait.lock); + } +return true; }/*
@@ -1425,7 +1461,7 @@ static void flush_bios(struct bio *bio) } } -static int do_origin (struct dm_dev *origin,struct bio *bio); +static int do_origin (struct dm_dev *origin,struct bio *bio,bool limit);/* * Flush a list of buffers.
@@ -1438,7 +1474,7 @@ static void retry_origin_bios(struct dm_snapshot *s, struct bio *bio)while (bio) { n = bio->bi_next; bio->bi_next =NULL ; - r =do_origin (s->origin, bio); + r =do_origin (s->origin, bio, false);if (r ==DM_MAPIO_REMAPPED )generic_make_request (bio); bio = n;
@@ -1730,8 +1766,11 @@ static int snapshot_map(struct dm_target *ti, struct bio *bio)if (!s->valid)return -EIO ; -/* FIXME: should only take write lock if we need -* to copy an exception */ +if (bio_data_dir (bio) ==WRITE ) { +while (unlikely (!wait_for_in_progress (s, false))) + ;/* wait_for_in_progress() has slept */ + } +mutex_lock (&s->lock);if (!s->valid || (unlikely (s->snapshot_overflowed) &&bio_rw (bio) ==WRITE )) {
@@ -1879,7 +1918,7 @@ redirect_to_origin:if (bio_rw (bio) ==WRITE ) {mutex_unlock (&s->lock); -return do_origin (s->origin, bio); +return do_origin (s->origin, bio, false); } out_unlock:
@@ -2215,15 +2254,24 @@ next_snapshot:/* * Called on a write from the origin driver. */ -static int do_origin (struct dm_dev *origin,struct bio *bio) +static int do_origin (struct dm_dev *origin,struct bio *bio,bool limit) {struct origin *o;int r =DM_MAPIO_REMAPPED ; +again:down_read (&_origins_lock); o =__lookup_origin (origin->bdev); -if (o) +if (o) { +if (limit) { +struct dm_snapshot *s; +list_for_each_entry (s, &o->snapshots, list) +if (unlikely (!wait_for_in_progress (s, true))) + goto again; + } + r =__origin_write (&o->snapshots, bio->bi_iter.bi_sector, bio); + }up_read (&_origins_lock);return r;
@@ -2336,7 +2384,7 @@ static int origin_map(struct dm_target *ti, struct bio *bio)dm_accept_partial_bio (bio, available_sectors);/* Only tell snapshots if this is a write */ -return do_origin (o->dev, bio); +return do_origin (o->dev, bio, true); }/*
Signature · 1 line
2.20.1
Greg Kroah-Hartman
maintainerPATCH 4/46 dm: Use kzalloc for all structs with embedded biosets/mempools
In reply to Greg Kroah-HartmanFrom: Kent Overstreet <[email protected]>
[ Upstream commit d377535405686f735b90a8ad4ba269484cd7c96e ]
mempool_init()/bioset_init() require that the mempools/biosets be zeroed first; they probably should not _require_ this, but not allocating those structs with kzalloc is a fairly nonsensical thing to do (calling mempool_exit()/bioset_exit() on an uninitialized mempool/bioset is legal and safe, but only works if said memory was zeroed.)
--- drivers/md/dm-bio-prison.c | 2 +- drivers/md/dm-io.c | 2 +- drivers/md/dm-kcopyd.c | 2 +- drivers/md/dm-region-hash.c | 2 +- drivers/md/dm-snap.c | 2 +- drivers/md/dm-thin.c | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-)
drivers/md/dm-bio-prison.c +1 -1
@@ -32,7 +32,7 @@ static struct kmem_cache *_cell_cache;*/ struct dm_bio_prison *dm_bio_prison_create (void ) { -struct dm_bio_prison *prison =kmalloc (sizeof (*prison),GFP_KERNEL ); +struct dm_bio_prison *prison =kzalloc (sizeof (*prison),GFP_KERNEL );if (!prison)return NULL ;
drivers/md/dm-io.c +1 -1
@@ -50,7 +50,7 @@ struct dm_io_client *dm_io_client_create(void)struct dm_io_client *client;unsigned min_ios =dm_get_reserved_bio_based_ios (); - client =kmalloc (sizeof (*client),GFP_KERNEL ); + client =kzalloc (sizeof (*client),GFP_KERNEL );if (!client)return ERR_PTR (-ENOMEM );
drivers/md/dm-kcopyd.c +1 -1
@@ -827,7 +827,7 @@ struct dm_kcopyd_client *dm_kcopyd_client_create(struct dm_kcopyd_throttle *throint r = -ENOMEM ;struct dm_kcopyd_client *kc; - kc =kmalloc (sizeof (*kc),GFP_KERNEL ); + kc =kzalloc (sizeof (*kc),GFP_KERNEL );if (!kc)return ERR_PTR (-ENOMEM );
drivers/md/dm-region-hash.c +1 -1
@@ -179,7 +179,7 @@ struct dm_region_hash *dm_region_hash_create( ; nr_buckets >>=1 ; - rh =kmalloc (sizeof (*rh),GFP_KERNEL ); + rh =kzalloc (sizeof (*rh),GFP_KERNEL );if (!rh) {DMERR ("unable to allocate region hash memory" );return ERR_PTR (-ENOMEM );
drivers/md/dm-snap.c +1 -1
@@ -1137,7 +1137,7 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv) origin_mode =FMODE_WRITE ; } - s =kmalloc (sizeof (*s),GFP_KERNEL ); + s =kzalloc (sizeof (*s),GFP_KERNEL );if (!s) { ti->error ="Cannot allocate private snapshot structure" ; r = -ENOMEM ;
drivers/md/dm-thin.c +1 -1
@@ -2882,7 +2882,7 @@ static struct pool *pool_create(struct mapped_device *pool_md,return (struct pool *)pmd; } - pool =kmalloc (sizeof (*pool),GFP_KERNEL ); + pool =kzalloc (sizeof (*pool),GFP_KERNEL );if (!pool) { *error ="Error allocating memory for pool" ; err_p =ERR_PTR (-ENOMEM );
Signature · 1 line
2.20.1
Greg Kroah-Hartman
maintainerPATCH 5/46 sc16is7xx: Fix for "Unexpected interrupt: 8"
In reply to Greg Kroah-HartmanFrom: Phil Elwell <[email protected]>
[ Upstream commit 30ec514d440cf2c472c8e4b0079af2c731f71a3e ]
The SC16IS752 has an Enhanced Feature Register which is aliased at the same address as the Interrupt Identification Register; accessing it requires that a magic value is written to the Line Configuration Register. If an interrupt is raised while the EFR is mapped in then the ISR won't be able to access the IIR, leading to the "Unexpected interrupt" error messages.
Avoid the problem by claiming a mutex around accesses to the EFR register, also claiming the mutex in the interrupt handler work item (this is equivalent to disabling interrupts to interlock against a non-threaded interrupt handler).
See: https://github.com/raspberrypi/linux/issues/2529
--- drivers/tty/serial/sc16is7xx.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+)
drivers/tty/serial/sc16is7xx.c +28 -0
@@ -332,6 +332,7 @@ struct sc16is7xx_port {struct kthread_worker kworker;struct task_struct *kworker_task;struct kthread_work irq_work; +struct mutex efr_lock;struct sc16is7xx_one p[0 ]; };
@@ -496,6 +497,21 @@ static int sc16is7xx_set_baud(struct uart_port *port, int baud) div /=4 ; } +/* In an amazing feat of design, the Enhanced Features Register shares +* the address of the Interrupt Identification Register, and is +* switched in by writing a magic value (0xbf) to the Line Control +* Register. Any interrupt firing during this time will see the EFR +* where it expects the IIR to be, leading to "Unexpected interrupt" +* messages. +* +* Prevent this possibility by claiming a mutex while accessing the +* EFR, and claiming the same mutex from within the interrupt handler. +* This is similar to disabling the interrupt, but that doesn't work +* because the bulk of the interrupt processing is run as a workqueue +* job in thread context. +*/ +mutex_lock (&s->efr_lock); + lcr =sc16is7xx_port_read (port,SC16IS7XX_LCR_REG );/* Open the LCR divisors for configuration */
@@ -511,6 +527,8 @@ static int sc16is7xx_set_baud(struct uart_port *port, int baud)/* Put LCR back to the normal mode */ sc16is7xx_port_write (port,SC16IS7XX_LCR_REG , lcr); +mutex_unlock (&s->efr_lock); +sc16is7xx_port_update (port,SC16IS7XX_MCR_REG ,SC16IS7XX_MCR_CLKSEL_BIT , prescaler);
@@ -693,6 +711,8 @@ static void sc16is7xx_ist(struct kthread_work *ws) {struct sc16is7xx_port *s =to_sc16is7xx_port (ws, irq_work); +mutex_lock (&s->efr_lock); +while (1 ) {bool keep_polling = false;int i;
@@ -702,6 +722,8 @@ static void sc16is7xx_ist(struct kthread_work *ws)if (!keep_polling)break ; } + +mutex_unlock (&s->efr_lock); }static irqreturn_t sc16is7xx_irq (int irq,void *dev_id)
@@ -888,6 +910,9 @@ static void sc16is7xx_set_termios(struct uart_port *port,if (!(termios->c_cflag &CREAD )) port->ignore_status_mask |=SC16IS7XX_LSR_BRK_ERROR_MASK ; +/* As above, claim the mutex while accessing the EFR. */ +mutex_lock (&s->efr_lock); +sc16is7xx_port_write (port,SC16IS7XX_LCR_REG ,SC16IS7XX_LCR_CONF_MODE_B );
@@ -909,6 +934,8 @@ static void sc16is7xx_set_termios(struct uart_port *port,/* Update LCR register */ sc16is7xx_port_write (port,SC16IS7XX_LCR_REG , lcr); +mutex_unlock (&s->efr_lock); +/* Get baud rate generator configuration */ baud = uart_get_baud_rate(port, termios, old, port->uartclk / 16 / 4 / 0xffff,
@@ -1172,6 +1199,7 @@ static int sc16is7xx_probe(struct device *dev, s->regmap = regmap; s->devtype = devtype;dev_set_drvdata (dev, s); +mutex_init (&s->efr_lock);init_kthread_worker (&s->kworker);init_kthread_work (&s->irq_work, sc16is7xx_ist);
Signature · 1 line
2.20.1
Greg Kroah-Hartman
maintainerPATCH 6/46 x86/cpu: Add Atom Tremont (Jacobsville)
In reply to Greg Kroah-HartmanFrom: Kan Liang <[email protected]>
[ Upstream commit 00ae831dfe4474ef6029558f5eb3ef0332d80043 ]
Add the Atom Tremont model number to the Intel family list.
[ Tony: Also update comment at head of file to say "_X" suffix is
also used for microserver parts. ]
--- arch/x86/include/asm/intel-family.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
arch/x86/include/asm/intel-family.h +2 -1
@@ -5,7 +5,7 @@* "Big Core" Processors (Branded as Core, Xeon, etc...) * * The "_X" parts are generally the EP and EX Xeons, or the -* "Extreme" ones, like Broadwell-E. +* "Extreme" ones, like Broadwell-E, or Atom microserver. * * Things ending in "2" are usually because we have no better * name for them. There's no processor called "WESTMERE2".
@@ -67,6 +67,7 @@#define INTEL_FAM6_ATOM_GOLDMONT 0x5C/* Apollo Lake */ #define INTEL_FAM6_ATOM_GOLDMONT_X 0x5F/* Denverton */ #define INTEL_FAM6_ATOM_GOLDMONT_PLUS 0x7A/* Gemini Lake */ +#define INTEL_FAM6_ATOM_TREMONT_X 0x86/* Jacobsville */ /* Xeon Phi */
Signature · 1 line
2.20.1
Greg Kroah-Hartman
maintainerPATCH 7/46 scripts/setlocalversion: Improve -dirty check with git-status --no-optional-locks
In reply to Greg Kroah-HartmanFrom: Brian Norris <[email protected]>
[ Upstream commit ff64dd4857303dd5550faed9fd598ac90f0f2238 ]
git-diff-index does not refresh the index for you, so using it for a "-dirty" check can give misleading results. Commit 6147b1cf19651 ("scripts/setlocalversion: git: Make -dirty check more robust") tried to fix this by switching to git-status, but it overlooked the fact that git-status also writes to the .git directory of the source tree, which is definitely not kosher for an out-of-tree (O=) build. That is getting reverted.
Fortunately, git-status now supports avoiding writing to the index via the --no-optional-locks flag, as of git 2.14. It still calculates an up-to-date index, but it avoids writing it out to the .git directory.
So, let's retry the solution from commit 6147b1cf19651 using this new flag first, and if it fails, we assume this is an older version of git and just use the old git-diff-index method.
It's hairy to get the 'grep -vq' (inverted matching) correct by stashing the output of git-status (you have to be careful about the difference betwen "empty stdin" and "blank line on stdin"), so just pipe the output directly to grep and use a regex that's good enough for both the git-status and git-diff-index version.
--- scripts/setlocalversion | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-)
scripts/setlocalversion +10 -2
@@ -72,8 +72,16 @@ scm_version() printf -- '-svn%s' "`git svn find-rev $head`" fi - # Check for uncommitted changes - if git diff-index --name-only HEAD | grep -qv "^scripts/package"; then + # Check for uncommitted changes. + # First, with git-status, but --no-optional-locks is only + # supported in git >= 2.14, so fall back to git-diff-index if + # it fails. Note that git-diff-index does not refresh the + # index, so it may give misleading results. See + # git-update-index(1), git-diff-index(1), and git-status(1). + if { + git --no-optional-locks status -uno --porcelain 2>/dev/null || + git diff-index --name-only HEAD + } | grep -qvE '^(.. )?scripts/package'; then printf '%s' -dirty fi
Signature · 1 line
2.20.1
Greg Kroah-Hartman
maintainerPATCH 8/46 usb: handle warm-reset port requests on hub resume
In reply to Greg Kroah-HartmanFrom: Jan-Marek Glogowski <[email protected]>
[ Upstream commit 4fdc1790e6a9ef22399c6bc6e63b80f4609f3b7e ]
On plug-in of my USB-C device, its USB_SS_PORT_LS_SS_INACTIVE link state bit is set. Greping all the kernel for this bit shows that the port status requests a warm-reset this way.
This just happens, if its the only device on the root hub, the hub therefore resumes and the HCDs status_urb isn't yet available. If a warm-reset request is detected, this sets the hubs event_bits, which will prevent any auto-suspend and allows the hubs workqueue to warm-reset the port later in port_event.
--- drivers/usb/core/hub.c | 7 +++++++ 1 file changed, 7 insertions(+)
drivers/usb/core/hub.c +7 -0
@@ -102,6 +102,8 @@ EXPORT_SYMBOL_GPL(ehci_cf_port_reset_rwsem);static void hub_release (struct kref *kref);static int usb_reset_and_verify_device (struct usb_device *udev);static int hub_port_disable (struct usb_hub *hub,int port1,int set_state); +static bool hub_port_warm_reset_required (struct usb_hub *hub,int port1, +u16 portstatus);static inline char *portspeed (struct usb_hub *hub,int portstatus) {
@@ -1092,6 +1094,11 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type) USB_PORT_FEAT_ENABLE); } +/* Make sure a warm-reset request is handled by port_event */ +if (type ==HUB_RESUME && +hub_port_warm_reset_required (hub, port1, portstatus)) +set_bit (port1, hub->event_bits); +/* * Add debounce if USB3 link is in polling/link training state. * Link will automatically transition to Enabled state after
Signature · 1 line
2.20.1
Greg Kroah-Hartman
maintainerPATCH 9/46 exec: load_script: Do not exec truncated interpreter path
In reply to Greg Kroah-HartmanFrom: Kees Cook <[email protected]>
[ Upstream commit b5372fe5dc84235dbe04998efdede3c4daa866a9 ]
Commit 8099b047ecc4 ("exec: load_script: don't blindly truncate shebang string") was trying to protect against a confused exec of a truncated interpreter path. However, it was overeager and also refused to truncate arguments as well, which broke userspace, and it was reverted. This attempts the protection again, but allows arguments to remain truncated. In an effort to improve readability, helper functions and comments have been added.
--- fs/binfmt_script.c | 57 ++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 48 insertions(+), 9 deletions(-)
fs/binfmt_script.c +48 -9
@@ -14,14 +14,31 @@#include <linux/err.h> #include <linux/fs.h> +static inline bool spacetab (char c) {return c ==' ' || c =='\t' ; } +static inline char *next_non_spacetab (char *first,const char *last) +{ +for (; first <= last; first++) +if (!spacetab (*first)) +return first; +return NULL ; +} +static inline char *next_terminator (char *first,const char *last) +{ +for (; first <= last; first++) +if (spacetab (*first) || !*first) +return first; +return NULL ; +} +static int load_script (struct linux_binprm *bprm) {const char *i_arg, *i_name; -char *cp; +char *cp, *buf_end;struct file *file;char interp[BINPRM_BUF_SIZE ];int retval; +/* Not ours to exec if we don't start with "#!". */ if ((bprm->buf[0 ] !='#' ) || (bprm->buf[1 ] !='!' ))return -ENOEXEC ;
@@ -34,18 +51,40 @@ static int load_script(struct linux_binprm *bprm)if (bprm->interp_flags &BINPRM_FLAGS_PATH_INACCESSIBLE )return -ENOENT ; -/* -* This section does the #! interpretation. -* Sorta complicated, but hopefully it will work. -TYT -*/ - +/* Release since we are not mapping a binary into memory. */ allow_write_access (bprm->file);fput (bprm->file); bprm->file =NULL ; - bprm->buf[BINPRM_BUF_SIZE -1 ] ='\0' ; -if ((cp =strchr (bprm->buf,'\n' )) ==NULL ) - cp = bprm->buf+BINPRM_BUF_SIZE -1 ; +/* +* This section handles parsing the #! line into separate +* interpreter path and argument strings. We must be careful +* because bprm->buf is not yet guaranteed to be NUL-terminated +* (though the buffer will have trailing NUL padding when the +* file size was smaller than the buffer size). +* +* We do not want to exec a truncated interpreter path, so either +* we find a newline (which indicates nothing is truncated), or +* we find a space/tab/NUL after the interpreter path (which +* itself may be preceded by spaces/tabs). Truncating the +* arguments is fine: the interpreter can re-read the script to +* parse them on its own. +*/ + buf_end = bprm->buf +sizeof (bprm->buf) -1 ; + cp =strnchr (bprm->buf,sizeof (bprm->buf),'\n' ); +if (!cp) { + cp =next_non_spacetab (bprm->buf +2 , buf_end); +if (!cp) +return -ENOEXEC ;/* Entire buf is spaces/tabs */ +/* +* If there is no later space/tab/NUL we must assume the +* interpreter path is truncated. +*/ +if (!next_terminator (cp, buf_end)) +return -ENOEXEC ; + cp = buf_end; + } +/* NUL-terminate the buffer and any trailing spaces/tabs. */ *cp ='\0' ;while (cp > bprm->buf) { cp--;
Signature · 1 line
2.20.1
Greg Kroah-Hartman
maintainerPATCH 10/46 iio: fix center temperature of bmc150-accel-core
In reply to Greg Kroah-HartmanFrom: Pascal Bouwmann <[email protected]>
[ Upstream commit 6c59a962e081df6d8fe43325bbfabec57e0d4751 ]
The center temperature of the supported devices stored in the constant BMC150_ACCEL_TEMP_CENTER_VAL is not 24 degrees but 23 degrees.
It seems that some datasheets were inconsistent on this value leading to the error. For most usecases will only make minor difference so not queued for stable.
--- drivers/iio/accel/bmc150-accel-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/iio/accel/bmc150-accel-core.c +1 -1
@@ -126,7 +126,7 @@#define BMC150_ACCEL_SLEEP_1_SEC 0x0F#define BMC150_ACCEL_REG_TEMP 0x08 -#define BMC150_ACCEL_TEMP_CENTER_VAL 24 +#define BMC150_ACCEL_TEMP_CENTER_VAL 23#define BMC150_ACCEL_AXIS_TO_REG (axis) (BMC150_ACCEL_REG_XOUT_L + (axis * 2))#define BMC150_AUTO_SUSPEND_DELAY_MS 2000
Signature · 1 line
2.20.1
Greg Kroah-Hartman
maintainerPATCH 11/46 perf map: Fix overlapped map handling
In reply to Greg Kroah-HartmanFrom: Steve MacLean <[email protected]>
[ Upstream commit ee212d6ea20887c0ef352be8563ca13dbf965906 ]
Whenever an mmap/mmap2 event occurs, the map tree must be updated to add a new entry. If a new map overlaps a previous map, the overlapped section of the previous map is effectively unmapped, but the non-overlapping sections are still valid.
maps__fixup_overlappings() is responsible for creating any new map entries from the previously overlapped map. It optionally creates a before and an after map.
When creating the after map the existing code failed to adjust the map.pgoff. This meant the new after map would incorrectly calculate the file offset for the ip. This results in incorrect symbol name resolution for any ip in the after region.
Make maps__fixup_overlappings() correctly populate map.pgoff.
Add an assert that new mapping matches old mapping at the beginning of the after map.
Committer-testing:
Validated correct parsing of libcoreclr.so symbols from .NET Core 3.0 preview9 (which didn't strip symbols).
Preparation:
~/dotnet3.0-preview9/dotnet new webapi -o perfSymbol
cd perfSymbol
~/dotnet3.0-preview9/dotnet publish
perf record ~/dotnet3.0-preview9/dotnet \
bin/Debug/netcoreapp3.0/publish/perfSymbol.dll
^CBefore:
perf script --show-mmap-events 2>&1 | grep -e MMAP -e unknown |\
grep libcoreclr.so | head -n 4
dotnet 1907 373352.698780: PERF_RECORD_MMAP2 1907/1907: \
[0x7fe615726000(0x768000) @ 0 08:02 5510620 765057155]: \
r-xp .../3.0.0-preview9-19423-09/libcoreclr.so
dotnet 1907 373352.701091: PERF_RECORD_MMAP2 1907/1907: \
[0x7fe615974000(0x1000) @ 0x24e000 08:02 5510620 765057155]: \
rwxp .../3.0.0-preview9-19423-09/libcoreclr.so
dotnet 1907 373352.701241: PERF_RECORD_MMAP2 1907/1907: \
[0x7fe615c42000(0x1000) @ 0x51c000 08:02 5510620 765057155]: \
rwxp .../3.0.0-preview9-19423-09/libcoreclr.so
dotnet 1907 373352.705249: 250000 cpu-clock: \
7fe6159a1f99 [unknown] \
(.../3.0.0-preview9-19423-09/libcoreclr.so)After:
perf script --show-mmap-events 2>&1 | grep -e MMAP -e unknown |\
grep libcoreclr.so | head -n 4
dotnet 1907 373352.698780: PERF_RECORD_MMAP2 1907/1907: \
[0x7fe615726000(0x768000) @ 0 08:02 5510620 765057155]: \
r-xp .../3.0.0-preview9-19423-09/libcoreclr.so
dotnet 1907 373352.701091: PERF_RECORD_MMAP2 1907/1907: \
[0x7fe615974000(0x1000) @ 0x24e000 08:02 5510620 765057155]: \
rwxp .../3.0.0-preview9-19423-09/libcoreclr.so
dotnet 1907 373352.701241: PERF_RECORD_MMAP2 1907/1907: \
[0x7fe615c42000(0x1000) @ 0x51c000 08:02 5510620 765057155]: \
rwxp .../3.0.0-preview9-19423-09/libcoreclr.soAll the [unknown] symbols were resolved.
--- tools/perf/util/map.c | 3 +++ 1 file changed, 3 insertions(+)
tools/perf/util/map.c +3 -0
@@ -1,4 +1,5 @@#include "symbol.h" +#include <assert.h> #include <errno.h> #include <inttypes.h> #include <limits.h>
@@ -702,6 +703,8 @@ static int maps__fixup_overlappings(struct maps *maps, struct map *map, FILE *fp } after->start = map->end; + after->pgoff += map->end - pos->start; +assert (pos->map_ip (pos, map->end) == after->map_ip (after, map->end));__map_groups__insert (pos->groups, after);if (verbose >=2 )map__fprintf (after, fp);
Signature · 1 line
2.20.1
Greg Kroah-Hartman
maintainerPATCH 12/46 RDMA/iwcm: Fix a lock inversion issue
In reply to Greg Kroah-HartmanFrom: Bart Van Assche <[email protected]>
[ Upstream commit b66f31efbdad95ec274345721d99d1d835e6de01 ]
This patch fixes the lock inversion complaint:
============================================
WARNING: possible recursive locking detected
5.3.0-rc7-dbg+ #1 Not tainted
--------------------------------------------
kworker/u16:6/171 is trying to acquire lock:00000000035c6e6c (&id_priv->handler_mutex){+.+.}, at: rdma_destroy_id+0x78/0x4a0 [rdma_cm]
but task is already holding lock:00000000bc7c307d (&id_priv->handler_mutex){+.+.}, at: iw_conn_req_handler+0x151/0x680 [rdma_cm]
other info that might help us debug this:
Possible unsafe locking scenario:
CPU0
---- lock(&id_priv->handler_mutex);
lock(&id_priv->handler_mutex);
*** DEADLOCK ***
May be due to missing lock nesting notation
3 locks held by kworker/u16:6/171:
#0: 00000000e2eaa773 ((wq_completion)iw_cm_wq){+.+.}, at: process_one_work+0x472/0xac0 #1: 000000001efd357b ((work_completion)(&work->work)#3){+.+.}, at: process_one_work+0x476/0xac0 #2: 00000000bc7c307d (&id_priv->handler_mutex){+.+.}, at: iw_conn_req_handler+0x151/0x680 [rdma_cm]
stack backtrace: CPU: 3 PID: 171 Comm: kworker/u16:6 Not tainted 5.3.0-rc7-dbg+ #1 Hardware name: Bochs Bochs, BIOS Bochs 01/01/2011 Workqueue: iw_cm_wq cm_work_handler [iw_cm] Call Trace: dump_stack+0x8a/0xd6 __lock_acquire.cold+0xe1/0x24d lock_acquire+0x106/0x240 __mutex_lock+0x12e/0xcb0 mutex_lock_nested+0x1f/0x30 rdma_destroy_id+0x78/0x4a0 [rdma_cm] iw_conn_req_handler+0x5c9/0x680 [rdma_cm] cm_work_handler+0xe62/0x1100 [iw_cm] process_one_work+0x56d/0xac0 worker_thread+0x7a/0x5d0 kthread+0x1bc/0x210 ret_from_fork+0x24/0x30
This is not a bug as there are actually two lock classes here.
--- drivers/infiniband/core/cma.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/infiniband/core/cma.c +2 -1
@@ -1976,9 +1976,10 @@ static int iw_conn_req_handler(struct iw_cm_id *cm_id, conn_id->cm_id.iw =NULL ;cma_exch (conn_id,RDMA_CM_DESTROYING );mutex_unlock (&conn_id->handler_mutex); +mutex_unlock (&listen_id->handler_mutex);cma_deref_id (conn_id);rdma_destroy_id (&conn_id->id); - goto out; +return ret; }mutex_unlock (&conn_id->handler_mutex);
Signature · 1 line
2.20.1
Greg Kroah-Hartman
maintainerPATCH 13/46 fs: cifs: mute -Wunused-const-variable message
In reply to Greg Kroah-HartmanFrom: Austin Kim <[email protected]>
[ Upstream commit dd19c106a36690b47bb1acc68372f2b472b495b8 ]
After 'Initial git repository build' commit, 'mapping_table_ERRHRD' variable has not been used.
So 'mapping_table_ERRHRD' const variable could be removed to mute below warning message:
fs/cifs/netmisc.c:120:40: warning: unused variable 'mapping_table_ERRHRD' [-Wunused-const-variable]
static const struct smb_to_posix_error mapping_table_ERRHRD[] = {
^--- fs/cifs/netmisc.c | 4 ---- 1 file changed, 4 deletions(-)
fs/cifs/netmisc.c +0 -4
@@ -130,10 +130,6 @@ static const struct smb_to_posix_error mapping_table_ERRSRV[] = { {0, 0} }; -static const struct smb_to_posix_error mapping_table_ERRHRD[] = { - {0 ,0 } -}; -/* * Convert a string containing text IPv4 or IPv6 address to binary form. *
Signature · 1 line
2.20.1
Greg Kroah-Hartman
maintainerPATCH 14/46 serial: mctrl_gpio: Check for NULL pointer
In reply to Greg Kroah-HartmanFrom: Adam Ford <[email protected]>
[ Upstream commit 37e3ab00e4734acc15d96b2926aab55c894f4d9c ]
When using mctrl_gpio_to_gpiod, it dereferences gpios into a single requested GPIO. This dereferencing can break if gpios is NULL, so this patch adds a NULL check before dereferencing it. If gpios is NULL, this function will also return NULL.
--- drivers/tty/serial/serial_mctrl_gpio.c | 3 +++ 1 file changed, 3 insertions(+)
drivers/tty/serial/serial_mctrl_gpio.c +3 -0
@@ -67,6 +67,9 @@ EXPORT_SYMBOL_GPL(mctrl_gpio_set);struct gpio_desc *mctrl_gpio_to_gpiod (struct mctrl_gpios *gpios,enum mctrl_gpio_idx gidx) { +if (gpios ==NULL ) +return NULL ; +return gpios->gpio[gidx]; }EXPORT_SYMBOL_GPL (mctrl_gpio_to_gpiod);
Signature · 1 line
2.20.1
Greg Kroah-Hartman
maintainerPATCH 15/46 efi/cper: Fix endianness of PCIe class code
In reply to Greg Kroah-HartmanFrom: Lukas Wunner <[email protected]>
[ Upstream commit 6fb9367a15d1a126d222d738b2702c7958594a5f ]
The CPER parser assumes that the class code is big endian, but at least on this edk2-derived Intel Purley platform it's little endian:
efi: EFI v2.50 by EDK II BIOS ID:PLYDCRB1.86B.0119.R05.1701181843
DMI: Intel Corporation PURLEY/PURLEY, BIOS PLYDCRB1.86B.0119.R05.1701181843 01/18/2017
{1}[Hardware Error]: device_id: 0000:5d:00.0
{1}[Hardware Error]: slot: 0
{1}[Hardware Error]: secondary_bus: 0x5e
{1}[Hardware Error]: vendor_id: 0x8086, device_id: 0x2030
{1}[Hardware Error]: class_code: 000406
^^^^^^ (should be 060400)--- drivers/firmware/efi/cper.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/firmware/efi/cper.c +1 -1
@@ -375,7 +375,7 @@ static void cper_print_pcie(const char *pfx, const struct cper_sec_pcie *pcie,printk ("%s""vendor_id: 0x%04x, device_id: 0x%04x\n" , pfx, pcie->device_id.vendor_id, pcie->device_id.device_id); p = pcie->device_id.class_code; -printk ("%s""class_code: %02x%02x%02x\n" , pfx, p[0 ], p[1 ], p[2 ]); +printk ("%s""class_code: %02x%02x%02x\n" , pfx, p[2 ], p[1 ], p[0 ]); }if (pcie->validation_bits &CPER_PCIE_VALID_SERIAL_NUMBER ) printk("%s""serial number: 0x%04x, 0x%04x\n", pfx,
Signature · 1 line
2.20.1
Greg Kroah-Hartman
maintainerPATCH 16/46 efi/x86: Do not clean dummy variable in kexec path
In reply to Greg Kroah-HartmanFrom: Dave Young <[email protected]>
[ Upstream commit 2ecb7402cfc7f22764e7bbc80790e66eadb20560 ]
kexec reboot fails randomly in UEFI based KVM guest. The firmware just resets while calling efi_delete_dummy_variable(); Unfortunately I don't know how to debug the firmware, it is also possible a potential problem on real hardware as well although nobody reproduced it.
The intention of the efi_delete_dummy_variable is to trigger garbage collection when entering virtual mode. But SetVirtualAddressMap can only run once for each physical reboot, thus kexec_enter_virtual_mode() is not necessarily a good place to clean a dummy object.
Drop the efi_delete_dummy_variable so that kexec reboot can work.
--- arch/x86/platform/efi/efi.c | 3 --- 1 file changed, 3 deletions(-)
arch/x86/platform/efi/efi.c +0 -3
@@ -859,9 +859,6 @@ static void __init kexec_enter_virtual_mode(void)if (efi_enabled (EFI_OLD_MEMMAP ) && (__supported_pte_mask & _PAGE_NX))runtime_code_page_mkexec (); - -/* clean DUMMY object */ -efi_delete_dummy_variable ();#endif }
Signature · 1 line
2.20.1
Greg Kroah-Hartman
maintainerPATCH 17/46 fs: ocfs2: fix possible null-pointer dereferences in ocfs2_xa_prepare_entry()
In reply to Greg Kroah-HartmanFrom: Jia-Ju Bai <[email protected]>
[ Upstream commit 56e94ea132bb5c2c1d0b60a6aeb34dcb7d71a53d ]
In ocfs2_xa_prepare_entry(), there is an if statement on line 2136 to check whether loc->xl_entry is NULL:
if (loc->xl_entry)
When loc->xl_entry is NULL, it is used on line 2158:
ocfs2_xa_add_entry(loc, name_hash);
loc->xl_entry->xe_name_hash = cpu_to_le32(name_hash);
loc->xl_entry->xe_name_offset = cpu_to_le16(loc->xl_size);and line 2164:
ocfs2_xa_add_namevalue(loc, xi);
loc->xl_entry->xe_value_size = cpu_to_le64(xi->xi_value_len);
loc->xl_entry->xe_name_len = xi->xi_name_len;Thus, possible null-pointer dereferences may occur.
To fix these bugs, if loc-xl_entry is NULL, ocfs2_xa_prepare_entry() abnormally returns with -EINVAL.
These bugs are found by a static analysis tool STCheck written by us.
--- fs/ocfs2/xattr.c | 56 ++++++++++++++++++++---------------------------- 1 file changed, 23 insertions(+), 33 deletions(-)
fs/ocfs2/xattr.c +23 -33
@@ -1475,18 +1475,6 @@ static int ocfs2_xa_check_space(struct ocfs2_xa_loc *loc,return loc->xl_ops->xlo_check_space (loc, xi); } -static void ocfs2_xa_add_entry (struct ocfs2_xa_loc *loc,u32 name_hash) -{ - loc->xl_ops->xlo_add_entry (loc, name_hash); - loc->xl_entry->xe_name_hash =cpu_to_le32 (name_hash); -/* -* We can't leave the new entry's xe_name_offset at zero or -* add_namevalue() will go nuts. We set it to the size of our -* storage so that it can never be less than any other entry. -*/ - loc->xl_entry->xe_name_offset =cpu_to_le16 (loc->xl_size); -} -static void ocfs2_xa_add_namevalue (struct ocfs2_xa_loc *loc,struct ocfs2_xattr_info *xi) {
@@ -2118,29 +2106,31 @@ static int ocfs2_xa_prepare_entry(struct ocfs2_xa_loc *loc,if (rc) goto out; -if (loc->xl_entry) { -if (ocfs2_xa_can_reuse_entry (loc, xi)) { - orig_value_size = loc->xl_entry->xe_value_size; - rc =ocfs2_xa_reuse_entry (loc, xi, ctxt); -if (rc) - goto out; - goto alloc_value; - } +if (!loc->xl_entry) { + rc = -EINVAL ; + goto out; + } -if (!ocfs2_xattr_is_local (loc->xl_entry)) { - orig_clusters =ocfs2_xa_value_clusters (loc); - rc =ocfs2_xa_value_truncate (loc,0 , ctxt); -if (rc) { -mlog_errno (rc); -ocfs2_xa_cleanup_value_truncate (loc, -"overwriting" , - orig_clusters); - goto out; - } +if (ocfs2_xa_can_reuse_entry (loc, xi)) { + orig_value_size = loc->xl_entry->xe_value_size; + rc =ocfs2_xa_reuse_entry (loc, xi, ctxt); +if (rc) + goto out; + goto alloc_value; + } + +if (!ocfs2_xattr_is_local (loc->xl_entry)) { + orig_clusters =ocfs2_xa_value_clusters (loc); + rc =ocfs2_xa_value_truncate (loc,0 , ctxt); +if (rc) { +mlog_errno (rc); +ocfs2_xa_cleanup_value_truncate (loc, +"overwriting" , + orig_clusters); + goto out; } -ocfs2_xa_wipe_namevalue (loc); - }else -ocfs2_xa_add_entry (loc, name_hash); + } +ocfs2_xa_wipe_namevalue (loc);/* * If we get here, we have a blank entry. Fill it. We grow our
Signature · 1 line
2.20.1
Greg Kroah-Hartman
maintainerPATCH 18/46 fs: ocfs2: fix a possible null-pointer dereference in ocfs2_info_scan_inode_alloc()
In reply to Greg Kroah-HartmanFrom: Jia-Ju Bai <[email protected]>
[ Upstream commit 2abb7d3b12d007c30193f48bebed781009bebdd2 ]
In ocfs2_info_scan_inode_alloc(), there is an if statement on line 283 to check whether inode_alloc is NULL:
if (inode_alloc)
When inode_alloc is NULL, it is used on line 287:
ocfs2_inode_lock(inode_alloc, &bh, 0);
ocfs2_inode_lock_full_nested(inode, ...)
struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);Thus, a possible null-pointer dereference may occur.
To fix this bug, inode_alloc is checked on line 286.
This bug is found by a static analysis tool STCheck written by us.
--- fs/ocfs2/ioctl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
fs/ocfs2/ioctl.c +1 -1
@@ -289,7 +289,7 @@ static int ocfs2_info_scan_inode_alloc(struct ocfs2_super *osb,if (inode_alloc)mutex_lock (&inode_alloc->i_mutex); -if (o2info_coherent (&fi->ifi_req)) { +if (inode_alloc &&o2info_coherent (&fi->ifi_req)) { status =ocfs2_inode_lock (inode_alloc, &bh,0 );if (status <0 ) {mlog_errno (status);
Signature · 1 line
2.20.1
Greg Kroah-Hartman
maintainerPATCH 19/46 MIPS: fw: sni: Fix out of bounds init of o32 stack
In reply to Greg Kroah-HartmanFrom: Thomas Bogendoerfer <[email protected]>
[ Upstream commit efcb529694c3b707dc0471b312944337ba16e4dd ]
Use ARRAY_SIZE to caluculate the top of the o32 stack.
--- arch/mips/fw/sni/sniprom.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/mips/fw/sni/sniprom.c +1 -1
@@ -42,7 +42,7 @@/* O32 stack has to be 8-byte aligned. */ static u64 o32_stk[4096 ]; -#define O32_STK &o32_stk[sizeof(o32_stk)] +#define O32_STK (&o32_stk[ARRAY_SIZE(o32_stk)])#define __PROM_O32 (fun, arg) fun arg __asm__(#fun); \ __asm__(#fun " = call_o32")
Signature · 1 line
2.20.1
Greg Kroah-Hartman
maintainerPATCH 20/46 NFSv4: Fix leak of clp->cl_acceptor string
In reply to Greg Kroah-HartmanFrom: Chuck Lever <[email protected]>
[ Upstream commit 1047ec868332034d1fbcb2fae19fe6d4cb869ff2 ]
Our client can issue multiple SETCLIENTID operations to the same server in some circumstances. Ensure that calls to nfs4_proc_setclientid() after the first one do not overwrite the previously allocated cl_acceptor string.
unreferenced object 0xffff888461031800 (size 32):
comm "mount.nfs", pid 2227, jiffies 4294822467 (age 1407.749s) hex dump (first 32 bytes):
6e 66 73 40 6b 6c 69 6d 74 2e 69 62 2e 31 30 31 [email protected] 35 67 72 61 6e 67 65 72 2e 6e 65 74 00 00 00 00 5granger.net.... backtrace: [<00000000ab820188>] __kmalloc+0x128/0x176 [<00000000eeaf4ec8>] gss_stringify_acceptor+0xbd/0x1a7 [auth_rpcgss] [<00000000e85e3382>] nfs4_proc_setclientid+0x34e/0x46c [nfsv4] [<000000003d9cf1fa>] nfs40_discover_server_trunking+0x7a/0xed [nfsv4] [<00000000b81c3787>] nfs4_discover_server_trunking+0x81/0x244 [nfsv4] [<000000000801b55f>] nfs4_init_client+0x1b0/0x238 [nfsv4] [<00000000977daf7f>] nfs4_set_client+0xfe/0x14d [nfsv4] [<0000000053a68a2a>] nfs4_create_server+0x107/0x1db [nfsv4] [<0000000088262019>] nfs4_remote_mount+0x2c/0x59 [nfsv4] [<00000000e84a2fd0>] legacy_get_tree+0x2d/0x4c [<00000000797e947c>] vfs_get_tree+0x20/0xc7 [<00000000ecabaaa8>] fc_mount+0xe/0x36 [<00000000f15fafc2>] vfs_kern_mount+0x74/0x8d [<00000000a3ff4e26>] nfs_do_root_mount+0x8a/0xa3 [nfsv4] [<00000000d1c2b337>] nfs4_try_mount+0x58/0xad [nfsv4] [<000000004c9bddee>] nfs_fs_mount+0x820/0x869 [nfs]
--- fs/nfs/nfs4proc.c | 1 + 1 file changed, 1 insertion(+)
fs/nfs/nfs4proc.c +1 -0
@@ -5255,6 +5255,7 @@ int nfs4_proc_setclientid(struct nfs_client *clp, u32 program, } status = task->tk_status;if (setclientid.sc_cred) { +kfree (clp->cl_acceptor); clp->cl_acceptor =rpcauth_stringify_acceptor (setclientid.sc_cred);put_rpccred (setclientid.sc_cred); }
Signature · 1 line
2.20.1
Greg Kroah-Hartman
maintainerPATCH 21/46 tracing: Initialize iter->seq after zeroing in tracing_read_pipe()
In reply to Greg Kroah-HartmanFrom: Petr Mladek <[email protected]>
[ Upstream commit d303de1fcf344ff7c15ed64c3f48a991c9958775 ]
A customer reported the following softlockup:
[899688.160002] NMI watchdog: BUG: soft lockup - CPU#0 stuck for 22s! [test.sh:16464] [899688.160002] CPU: 0 PID: 16464 Comm: test.sh Not tainted 4.12.14-6.23-azure #1 SLE12-SP4 [899688.160002] RIP: 0010:up_write+0x1a/0x30 [899688.160002] Kernel panic - not syncing: softlockup: hung tasks [899688.160002] RIP: 0010:up_write+0x1a/0x30 [899688.160002] RSP: 0018:ffffa86784d4fde8 EFLAGS: 00000257 ORIG_RAX: ffffffffffffff12 [899688.160002] RAX: ffffffff970fea00 RBX: 0000000000000001 RCX: 0000000000000000 [899688.160002] RDX: ffffffff00000001 RSI: 0000000000000080 RDI: ffffffff970fea00 [899688.160002] RBP: ffffffffffffffff R08: ffffffffffffffff R09: 0000000000000000 [899688.160002] R10: 0000000000000000 R11: 0000000000000000 R12: ffff8b59014720d8 [899688.160002] R13: ffff8b59014720c0 R14: ffff8b5901471090 R15: ffff8b5901470000 [899688.160002] tracing_read_pipe+0x336/0x3c0 [899688.160002] __vfs_read+0x26/0x140 [899688.160002] vfs_read+0x87/0x130 [899688.160002] SyS_read+0x42/0x90 [899688.160002] do_syscall_64+0x74/0x160
It caught the process in the middle of trace_access_unlock(). There is no loop. So, it must be looping in the caller tracing_read_pipe() via the "waitagain" label.
Crashdump analyze uncovered that iter->seq was completely zeroed at this point, including iter->seq.seq.size. It means that print_trace_line() was never able to print anything and there was no forward progress.
The culprit seems to be in the code:
/* reset all but tr, trace, and overruns */ memset(&iter->seq, 0, sizeof(struct trace_iterator) - offsetof(struct trace_iterator, seq));
It was added by the commit 53d0aa773053ab182877 ("ftrace:
add logic to record overruns"). It was v2.6.27-rc1. It was the time when iter->seq looked like:
struct trace_seq {
unsigned char buffer[PAGE_SIZE];
unsigned int len;
};There was no "size" variable and zeroing was perfectly fine.
The solution is to reinitialize the structure after or without zeroing.
--- kernel/trace/trace.c | 1 + 1 file changed, 1 insertion(+)
kernel/trace/trace.c +1 -0
@@ -4803,6 +4803,7 @@ waitagain:sizeof (struct trace_iterator ) - offsetof(struct trace_iterator, seq));cpumask_clear (iter->started); +trace_seq_init (&iter->seq); iter->pos =-1 ;trace_event_read_lock ();
Signature · 1 line
2.20.1
Greg Kroah-Hartman
maintainerPATCH 22/46 USB: legousbtower: fix a signedness bug in tower_probe()
In reply to Greg Kroah-HartmanFrom: Dan Carpenter <[email protected]>
[ Upstream commit fd47a417e75e2506eb3672ae569b1c87e3774155 ]
The problem is that sizeof() is unsigned long so negative error codes are type promoted to high positive values and the condition becomes false.
--- drivers/usb/misc/legousbtower.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/usb/misc/legousbtower.c +1 -1
@@ -910,7 +910,7 @@ static int tower_probe (struct usb_inter get_version_reply,sizeof (*get_version_reply), 1000); -if (result <sizeof (*get_version_reply)) { +if (result !=sizeof (*get_version_reply)) {if (result >=0 ) result = -EIO ;dev_err (idev,"get version request failed: %d\n" , result);
Greg Kroah-Hartman
maintainerPATCH 23/46 thunderbolt: Use 32-bit writes when writing ring producer/consumer
In reply to Greg Kroah-HartmanFrom: Mika Westerberg <[email protected]>
[ Upstream commit 943795219d3cb9f8ce6ce51cad3ffe1f61e95c6b ]
The register access should be using 32-bit reads/writes according to the datasheet. With the previous generation hardware 16-bit writes have been working but starting with ICL this is not the case anymore so fix producer/consumer register update to use correct width register address.
--- drivers/thunderbolt/nhi.c | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-)
drivers/thunderbolt/nhi.c +18 -4
@@ -94,9 +94,20 @@ static void __iomem *ring_options_base(struct tb_ring *ring)return io; } -static void ring_iowrite16desc (struct tb_ring *ring,u32 value,u32 offset) +static void ring_iowrite_cons (struct tb_ring *ring,u16 cons) { -iowrite16 (value,ring_desc_base (ring) + offset); +/* +* The other 16-bits in the register is read-only and writes to it +* are ignored by the hardware so we can save one ioread32() by +* filling the read-only bits with zeroes. +*/ +iowrite32 (cons,ring_desc_base (ring) +8 ); +} + +static void ring_iowrite_prod (struct tb_ring *ring,u16 prod) +{ +/* See ring_iowrite_cons() above for explanation */ +iowrite32 (prod <<16 ,ring_desc_base (ring) +8 ); }static void ring_iowrite32desc (struct tb_ring *ring,u32 value,u32 offset)
@@ -148,7 +159,10 @@ static void ring_write_descriptors(struct tb_ring *ring) descriptor->sof = frame->sof; } ring->head = (ring->head +1 ) % ring->size; -ring_iowrite16desc (ring, ring->head, ring->is_tx ?10 :8 ); +if (ring->is_tx) +ring_iowrite_prod (ring, ring->head); +else +ring_iowrite_cons (ring, ring->head); } }
@@ -368,7 +382,7 @@ void ring_stop(struct tb_ring *ring)ring_iowrite32options (ring,0 ,0 );ring_iowrite64desc (ring,0 ,0 ); -ring_iowrite16desc (ring,0 , ring->is_tx ?10 :8 ); +ring_iowrite32desc (ring,0 ,8 );ring_iowrite32desc (ring,0 ,12 ); ring->head =0 ; ring->tail =0 ;
Signature · 1 line
2.20.1
Greg Kroah-Hartman
maintainerPATCH 24/46 ath6kl: fix a NULL-ptr-deref bug in ath6kl_usb_alloc_urb_from_pipe()
In reply to Greg Kroah-HartmanFrom: Hui Peng <[email protected]>
[ Upstream commit 39d170b3cb62ba98567f5c4f40c27b5864b304e5 ]
The ar_usb field of ath6kl_usb_pipe_usb_pipe objects are initialized to point to the containing ath6kl_usb object according to endpoint descriptors read from the device side, as shown below in ath6kl_usb_setup_pipe_resources:
for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
endpoint = &iface_desc->endpoint[i].desc;
// get the address from endpoint descriptor
pipe_num = ath6kl_usb_get_logical_pipe_num(ar_usb,
endpoint->bEndpointAddress,
&urbcount);
......
// select the pipe object
pipe = &ar_usb->pipes[pipe_num];
// initialize the ar_usb field
pipe->ar_usb = ar_usb;
}The driver assumes that the addresses reported in endpoint descriptors from device side to be complete. If a device is malicious and does not report complete addresses, it may trigger NULL-ptr-deref ath6kl_usb_alloc_urb_from_pipe and ath6kl_usb_free_urb_to_pipe.
This patch fixes the bug by preventing potential NULL-ptr-deref (CVE-2019-15098).
--- drivers/net/wireless/ath/ath6kl/usb.c | 8 ++++++++ 1 file changed, 8 insertions(+)
drivers/net/wireless/ath/ath6kl/usb.c +8 -0
@@ -132,6 +132,10 @@ ath6kl_usb_alloc_urb_from_pipe(struct atstruct ath6kl_urb_context *urb_context =NULL ;unsigned long flags; +/* bail if this pipe is not initialized */ +if (!pipe->ar_usb) +return NULL ; +spin_lock_irqsave (&pipe->ar_usb->cs_lock, flags);if (!list_empty (&pipe->urb_list_head)) { urb_context =
@@ -150,6 +154,10 @@ static void ath6kl_usb_free_urb_to_pipe( {unsigned long flags; +/* bail if this pipe is not initialized */ +if (!pipe->ar_usb) +return ; +spin_lock_irqsave (&pipe->ar_usb->cs_lock, flags); pipe->urb_cnt++;
Greg Kroah-Hartman
maintainerPATCH 25/46 fuse: flush dirty data/metadata before non-truncate setattr
In reply to Greg Kroah-HartmanFrom: Miklos Szeredi <[email protected]>
commit b24e7598db62386a95a3c8b9c75630c5d56fe077 upstream.
If writeback cache is enabled, then writes might get reordered with chmod/chown/utimes. The problem with this is that performing the write in the fuse daemon might itself change some of these attributes. In such case the following sequence of operations will result in file ending up with the wrong mode, for example:
int fd = open ("suid", O_WRONLY|O_CREAT|O_EXCL);
write (fd, "1", 1);
fchown (fd, 0, 0);
fchmod (fd, 04755);
close (fd);This patch fixes this by flushing pending writes before performing chown/chmod/utimes.
--- fs/fuse/dir.c | 13 +++++++++++++ 1 file changed, 13 insertions(+)
fs/fuse/dir.c +13 -0
@@ -1628,6 +1628,19 @@ int fuse_do_setattr(struct inode *inode,if (attr->ia_valid &ATTR_SIZE ) is_truncate = true; +/* Flush dirty data/metadata before non-truncate SETATTR */ +if (is_wb &&S_ISREG (inode->i_mode) && + attr->ia_valid & + (ATTR_MODE |ATTR_UID |ATTR_GID |ATTR_MTIME_SET | +ATTR_TIMES_SET )) { + err =write_inode_now (inode, true); +if (err) +return err; + +fuse_set_nowrite (inode); +fuse_release_nowrite (inode); + } +if (is_truncate) {fuse_set_nowrite (inode);set_bit (FUSE_I_SIZE_UNSTABLE , &fi->state);
Greg Kroah-Hartman
maintainerPATCH 26/46 fuse: truncate pending writes on O_TRUNC
In reply to Greg Kroah-HartmanFrom: Miklos Szeredi <[email protected]>
commit e4648309b85a78f8c787457832269a8712a8673e upstream.
Make sure cached writes are not reordered around open(..., O_TRUNC), with the obvious wrong results.
--- fs/fuse/file.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-)
fs/fuse/file.c +7 -3
@@ -201,7 +201,7 @@ int fuse_open_common(struct inode *inode {struct fuse_conn *fc =get_fuse_conn (inode);int err; -bool lock_inode = (file->f_flags &O_TRUNC ) && +bool is_wb_truncate = (file->f_flags &O_TRUNC ) && fc->atomic_o_trunc && fc->writeback_cache;
@@ -209,16 +209,20 @@ int fuse_open_common(struct inode *inodeif (err)return err; -if (lock_inode) +if (is_wb_truncate) {mutex_lock (&inode->i_mutex); +fuse_set_nowrite (inode); + } err =fuse_do_open (fc,get_node_id (inode), file, isdir);if (!err)fuse_finish_open (inode, file); -if (lock_inode) +if (is_wb_truncate) { +fuse_release_nowrite (inode);mutex_unlock (&inode->i_mutex); + }return err; }
Greg Kroah-Hartman
maintainerPATCH 27/46 ALSA: bebob: Fix prototype of helper function to return negative value
In reply to Greg Kroah-HartmanFrom: Takashi Sakamoto <[email protected]>
commit f2bbdbcb075f3977a53da3bdcb7cd460bc8ae5f2 upstream.
A helper function of ALSA bebob driver returns negative value in a function which has a prototype to return unsigned value.
This commit fixes it by changing the prototype.
--- sound/firewire/bebob/bebob_stream.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
sound/firewire/bebob/bebob_stream.c +1 -2
@@ -253,8 +253,7 @@ end:return err; } -static unsigned int -map_data_channels (struct snd_bebob *bebob,struct amdtp_stream *s) +static int map_data_channels (struct snd_bebob *bebob,struct amdtp_stream *s) {unsigned int sec, sections, ch, channels;unsigned int pcm, midi, location;
Greg Kroah-Hartman
maintainerPATCH 28/46 UAS: Revert commit 3ae62a42090f ("UAS: fix alignment of scatter/gather segments")
In reply to Greg Kroah-HartmanFrom: Alan Stern <[email protected]>
commit 1186f86a71130a7635a20843e355bb880c7349b2 upstream.
Commit 3ae62a42090f ("UAS: fix alignment of scatter/gather segments"), copying a similar commit for usb-storage, attempted to solve a problem involving scatter-gather I/O and USB/IP by setting the virt_boundary_mask for mass-storage devices.
However, it now turns out that the analogous change in usb-storage interacted badly with commit 09324d32d2a0 ("block: force an unlimited segment size on queues with a virt boundary"), which was added later. A typical error message is:
ehci-pci 0000:00:13.2: swiotlb buffer is full (sz: 327680 bytes), total 32768 (slots), used 97 (slots)
There is no longer any reason to keep the virt_boundary_mask setting in the uas driver. It was needed in the first place only for handling devices with a block size smaller than the maxpacket size and where the host controller was not capable of fully general scatter-gather operation (that is, able to merge two SG segments into a single USB packet). But:
High-speed or slower connections never use a bulk maxpacket value larger than 512;
The SCSI layer does not handle block devices with a block size smaller than 512 bytes;
All the host controllers capable of SuperSpeed operation can handle fully general SG;
Since commit ea44d190764b ("usbip: Implement SG support to vhci-hcd and stub driver") was merged, the USB/IP driver can also handle SG.
Therefore all supported device/controller combinations should be okay with no need for any special virt_boundary_mask. So in order to head off potential problems similar to those affecting usb-storage, this patch reverts commit 3ae62a42090f.
--- drivers/usb/storage/uas.c | 20 -------------------- 1 file changed, 20 deletions(-)
drivers/usb/storage/uas.c +0 -20
@@ -772,30 +772,10 @@ static int uas_slave_alloc(struct scsi_d {struct uas_dev_info *devinfo = (struct uas_dev_info *)sdev->host->hostdata; -int maxp; sdev->hostdata = devinfo;/* -* We have two requirements here. We must satisfy the requirements -* of the physical HC and the demands of the protocol, as we -* definitely want no additional memory allocation in this path -* ruling out using bounce buffers. -* -* For a transmission on USB to continue we must never send -* a package that is smaller than maxpacket. Hence the length of each -* scatterlist element except the last must be divisible by the -* Bulk maxpacket value. -* If the HC does not ensure that through SG, -* the upper layer must do that. We must assume nothing -* about the capabilities off the HC, so we use the most -* pessimistic requirement. -*/ - - maxp =usb_maxpacket (devinfo->udev, devinfo->data_in_pipe,0 ); -blk_queue_virt_boundary (sdev->request_queue, maxp -1 ); - -/* * The protocol has no requirements on alignment in the strict sense. * Controllers may or may not have alignment restrictions. * As this is not exported, we use an extremely conservative guess.
Re: [PATCH 4.4 28/46] UAS: Revert commit 3ae62a42090f ("UAS: fix alignment of scatter/gather segments")
Am Montag, den 04.11.2019, 22:44 +0100 schrieb Greg Kroah-Hartman:
Quoted 8 lines
From: Alan Stern <[email protected]>
commit
1186f86a71130a7635a20843e355bb880c7349b2upstream.Commit
3ae62a42090f("UAS: fix alignment of scatter/gather segments"), copying a similar commit for usb-storage, attempted to solve a problem involving scatter-gather I/O and USB/IP by setting thevirt_boundary_maskfor mass-storage devices.
We have that in 4.4.x
Quoted 4 lines
However, it now turns out that the analogous change in usb-storage interacted badly with commit
09324d32d2a0("block: force an unlimited segment size on queues with a virt boundary"), which was added later. A typical error message is:
09324d32d2a0 I cannot find.
Quoted 16 lines
ehci-pci 0000:00:13.2: swiotlb buffer is full (sz: 327680 bytes), total 32768 (slots), used 97 (slots)There is no longer any reason to keep the
virt_boundary_masksetting in the uas driver. It was needed in the first place only for handling devices with a block size smaller than the maxpacket size and where the host controller was not capable of fully general scatter-gather operation (that is, able to merge two SG segments into a single USB packet). But:High-speed or slower connections never use a bulk maxpacket value larger than 512;
The SCSI layer does not handle block devices with a block size smaller than 512 bytes;
Quoted 6 lines
All the host controllers capable of SuperSpeed operation can handle fully general SG;
Since commit
ea44d190764b("usbip: Implement SG support to vhci-hcd and stub driver") was merged, the USB/IP driver can also handle SG.
Neither can I find ea44d190764b.
It seems to me that, while the patch is necessary in upstream, in 4.4.x it would break usbip.
Regards
Oliver
Greg Kroah-Hartman
maintainerPATCH 29/46 USB: gadget: Reject endpoints with 0 maxpacket value
In reply to Greg Kroah-HartmanFrom: Alan Stern <[email protected]>
commit 54f83b8c8ea9b22082a496deadf90447a326954e upstream.
Endpoints with a maxpacket length of 0 are probably useless. They can't transfer any data, and it's not at all unlikely that a UDC will crash or hang when trying to handle a non-zero-length usb_request for such an endpoint. Indeed, dummy-hcd gets a divide error when trying to calculate the remainder of a transfer length by the maxpacket value, as discovered by the syzbot fuzzer.
Currently the gadget core does not check for endpoints having a maxpacket value of 0. This patch adds a check to usb_ep_enable(), preventing such endpoints from being used.
As far as I know, none of the gadget drivers in the kernel tries to create an endpoint with maxpacket = 0, but until now there has been nothing to prevent userspace programs under gadgetfs or configfs from doing it.
--- include/linux/usb/gadget.h | 10 ++++++++++ 1 file changed, 10 insertions(+)
include/linux/usb/gadget.h +10 -0
@@ -270,6 +270,16 @@ static inline int usb_ep_enable(struct uif (ep->enabled)return 0 ; +/* UDC drivers can't handle endpoints with maxpacket size 0 */ +if (usb_endpoint_maxp (ep->desc) ==0 ) { +/* +* We should log an error message here, but we can't call +* dev_err() because there's no way to find the gadget +* given only ep. +*/ +return -EINVAL ; + } + ret = ep->ops->enable (ep, ep->desc);if (ret)return ret;
Greg Kroah-Hartman
maintainerPATCH 30/46 USB: ldusb: fix ring-buffer locking
In reply to Greg Kroah-HartmanFrom: Johan Hovold <[email protected]>
commit d98ee2a19c3334e9343df3ce254b496f1fc428eb upstream.
The custom ring-buffer implementation was merged without any locking or explicit memory barriers, but a spinlock was later added by commit 9d33efd9a791 ("USB: ldusb bugfix").
The lock did not cover the update of the tail index once the entry had been processed, something which could lead to memory corruption on weakly ordered architectures or due to compiler optimisations.
Specifically, a completion handler running on another CPU might observe the incremented tail index and update the entry before ld_usb_read() is done with it.
--- drivers/usb/misc/ldusb.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/usb/misc/ldusb.c +2 -2
@@ -499,11 +499,11 @@ static ssize_t ld_usb_read(struct file * retval = -EFAULT ; goto unlock_exit; } - dev->ring_tail = (dev->ring_tail+1 ) % ring_buffer_size; - retval = bytes_to_read;spin_lock_irq (&dev->rbsl); + dev->ring_tail = (dev->ring_tail +1 ) % ring_buffer_size; +if (dev->buffer_overflow) { dev->buffer_overflow =0 ;spin_unlock_irq (&dev->rbsl);
Greg Kroah-Hartman
maintainerPATCH 31/46 USB: ldusb: fix control-message timeout
In reply to Greg Kroah-HartmanFrom: Johan Hovold <[email protected]>
commit 52403cfbc635d28195167618690595013776ebde upstream.
USB control-message timeouts are specified in milliseconds, not jiffies. Waiting 83 minutes for a transfer to complete is a bit excessive.
--- drivers/usb/misc/ldusb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/usb/misc/ldusb.c +1 -1
@@ -584,7 +584,7 @@ static ssize_t ld_usb_write(struct file1 <<8 ,0 , dev->interrupt_out_buffer, bytes_to_write, - USB_CTRL_SET_TIMEOUT * HZ); + USB_CTRL_SET_TIMEOUT);if (retval <0 ) dev_err(&dev->intf->dev, "Couldn't submit HID_REQ_SET_REPORT %d\n",
Greg Kroah-Hartman
maintainerPATCH 32/46 USB: serial: whiteheat: fix potential slab corruption
In reply to Greg Kroah-HartmanFrom: Johan Hovold <[email protected]>
commit 1251dab9e0a2c4d0d2d48370ba5baa095a5e8774 upstream.
Fix a user-controlled slab buffer overflow due to a missing sanity check on the bulk-out transfer buffer used for control requests.
--- drivers/usb/serial/whiteheat.c | 4 ++++ 1 file changed, 4 insertions(+)
drivers/usb/serial/whiteheat.c +4 -0
@@ -604,6 +604,10 @@ static int firm_send_command(struct usb_ command_port = port->serial->port[COMMAND_PORT ]; command_info =usb_get_serial_port_data (command_port); + +if (command_port->bulk_out_size < datasize +1 ) +return -EIO ; +mutex_lock (&command_info->mutex); command_info->command_finished = false;
Greg Kroah-Hartman
maintainerPATCH 33/46 USB: serial: whiteheat: fix line-speed endianness
In reply to Greg Kroah-HartmanFrom: Johan Hovold <[email protected]>
commit 84968291d7924261c6a0624b9a72f952398e258b upstream.
Add missing endianness conversion when setting the line speed so that this driver might work also on big-endian machines.
Also use an unsigned format specifier in the corresponding debug message.
--- drivers/usb/serial/whiteheat.c | 9 ++++++--- drivers/usb/serial/whiteheat.h | 2 +- 2 files changed, 7 insertions(+), 4 deletions(-)
drivers/usb/serial/whiteheat.c +6 -3
@@ -681,6 +681,7 @@ static void firm_setup_port(struct tty_sstruct device *dev = &port->dev;struct whiteheat_port_settings port_settings;unsigned int cflag = tty->termios.c_cflag; +speed_t baud; port_settings.port = port->port_number +1 ;
@@ -741,11 +742,13 @@ static void firm_setup_port(struct tty_sdev_dbg (dev,"%s - XON = %2x, XOFF = %2x\n" , __func__, port_settings.xon, port_settings.xoff);/* get the baud rate wanted */ - port_settings.baud =tty_get_baud_rate (tty); -dev_dbg (dev,"%s - baud rate = %d\n" , __func__, port_settings.baud); + baud =tty_get_baud_rate (tty); + port_settings.baud =cpu_to_le32 (baud); +dev_dbg (dev,"%s - baud rate = %u\n" , __func__, baud);/* fixme: should set validated settings */ -tty_encode_baud_rate (tty, port_settings.baud, port_settings.baud); +tty_encode_baud_rate (tty, baud, baud); +/* handle any settings that aren't specified in the tty structure */ port_settings.lloop =0 ;
drivers/usb/serial/whiteheat.h +1 -1
@@ -91,7 +91,7 @@ struct whiteheat_simple {struct whiteheat_port_settings {__u8 port;/* port number (1 to N) */ -__u32 baud;/* any value 7 - 460800, firmware calculates +__le32 baud;/* any value 7 - 460800, firmware calculates best fit; arrives little endian */ __u8 bits;/* 5, 6, 7, or 8 */ __u8 stop;/* 1 or 2, default 1 (2 = 1.5 if bits = 5) */
Greg Kroah-Hartman
maintainerPATCH 34/46 HID: Fix assumption that devices have inputs
In reply to Greg Kroah-HartmanFrom: Alan Stern <[email protected]>
commit d9d4b1e46d9543a82c23f6df03f4ad697dab361b upstream.
The syzbot fuzzer found a slab-out-of-bounds write bug in the hid-gaff driver. The problem is caused by the driver's assumption that the device must have an input report. While this will be true for all normal HID input devices, a suitably malicious device can violate the assumption.
The same assumption is present in over a dozen other HID drivers. This patch fixes them by checking that the list of hid_inputs for the hid_device is nonempty before allowing it to be used.
--- drivers/hid/hid-axff.c | 11 +++++++++-- drivers/hid/hid-dr.c | 12 +++++++++--- drivers/hid/hid-emsff.c | 12 +++++++++--- drivers/hid/hid-gaff.c | 12 +++++++++--- drivers/hid/hid-holtekff.c | 12 +++++++++--- drivers/hid/hid-lg2ff.c | 12 +++++++++--- drivers/hid/hid-lg3ff.c | 11 +++++++++-- drivers/hid/hid-lg4ff.c | 11 +++++++++-- drivers/hid/hid-lgff.c | 11 +++++++++-- drivers/hid/hid-sony.c | 12 +++++++++--- drivers/hid/hid-tmff.c | 12 +++++++++--- drivers/hid/hid-zpff.c | 12 +++++++++--- 12 files changed, 108 insertions(+), 32 deletions(-)
drivers/hid/hid-axff.c +9 -2
@@ -75,13 +75,20 @@ static int axff_init(struct hid_device * {struct axff_device *axff;struct hid_report *report; - struct hid_input *hidinput = list_first_entry(&hid->inputs, struct hid_input, list); +struct hid_input *hidinput;struct list_head *report_list =&hid->report_enum[HID_OUTPUT_REPORT ].report_list; -struct input_dev *dev = hidinput->input; +struct input_dev *dev;int field_count =0 ;int i, j;int error; +if (list_empty (&hid->inputs)) { +hid_err (hid,"no inputs found\n" ); +return -ENODEV ; + } + hidinput = list_first_entry(&hid->inputs, struct hid_input, list); + dev = hidinput->input; +if (list_empty (report_list)) {hid_err (hid,"no output reports found\n" );return -ENODEV ;
drivers/hid/hid-dr.c +9 -3
@@ -87,13 +87,19 @@ static int drff_init(struct hid_device * {struct drff_device *drff;struct hid_report *report; -struct hid_input *hidinput =list_first_entry (&hid->inputs, - struct hid_input, list); +struct hid_input *hidinput;struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT ].report_list; -struct input_dev *dev = hidinput->input; +struct input_dev *dev;int error; +if (list_empty (&hid->inputs)) { +hid_err (hid,"no inputs found\n" ); +return -ENODEV ; + } + hidinput = list_first_entry(&hid->inputs, struct hid_input, list); + dev = hidinput->input; +if (list_empty (report_list)) {hid_err (hid,"no output reports found\n" );return -ENODEV ;
drivers/hid/hid-emsff.c +9 -3
@@ -59,13 +59,19 @@ static int emsff_init(struct hid_device {struct emsff_device *emsff;struct hid_report *report; -struct hid_input *hidinput =list_first_entry (&hid->inputs, - struct hid_input, list); +struct hid_input *hidinput;struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT ].report_list; -struct input_dev *dev = hidinput->input; +struct input_dev *dev;int error; +if (list_empty (&hid->inputs)) { +hid_err (hid,"no inputs found\n" ); +return -ENODEV ; + } + hidinput = list_first_entry(&hid->inputs, struct hid_input, list); + dev = hidinput->input; +if (list_empty (report_list)) {hid_err (hid,"no output reports found\n" );return -ENODEV ;
drivers/hid/hid-gaff.c +9 -3
@@ -77,14 +77,20 @@ static int gaff_init(struct hid_device * {struct gaff_device *gaff;struct hid_report *report; -struct hid_input *hidinput =list_entry (hid->inputs.next, - struct hid_input, list); +struct hid_input *hidinput;struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT ].report_list;struct list_head *report_ptr = report_list; -struct input_dev *dev = hidinput->input; +struct input_dev *dev;int error; +if (list_empty (&hid->inputs)) { +hid_err (hid,"no inputs found\n" ); +return -ENODEV ; + } + hidinput = list_entry(hid->inputs.next, struct hid_input, list); + dev = hidinput->input; +if (list_empty (report_list)) {hid_err (hid,"no output reports found\n" );return -ENODEV ;
drivers/hid/hid-holtekff.c +9 -3
@@ -140,13 +140,19 @@ static int holtekff_init(struct hid_devi {struct holtekff_device *holtekff;struct hid_report *report; -struct hid_input *hidinput =list_entry (hid->inputs.next, - struct hid_input, list); +struct hid_input *hidinput;struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT ].report_list; -struct input_dev *dev = hidinput->input; +struct input_dev *dev;int error; +if (list_empty (&hid->inputs)) { +hid_err (hid,"no inputs found\n" ); +return -ENODEV ; + } + hidinput = list_entry(hid->inputs.next, struct hid_input, list); + dev = hidinput->input; +if (list_empty (report_list)) {hid_err (hid,"no output report found\n" );return -ENODEV ;
drivers/hid/hid-lg2ff.c +9 -3
@@ -62,11 +62,17 @@ int lg2ff_init(struct hid_device *hid) {struct lg2ff_device *lg2ff;struct hid_report *report; -struct hid_input *hidinput =list_entry (hid->inputs.next, - struct hid_input, list); -struct input_dev *dev = hidinput->input; +struct hid_input *hidinput; +struct input_dev *dev;int error; +if (list_empty (&hid->inputs)) { +hid_err (hid,"no inputs found\n" ); +return -ENODEV ; + } + hidinput = list_entry(hid->inputs.next, struct hid_input, list); + dev = hidinput->input; +/* Check that the report looks ok */ report =hid_validate_values (hid,HID_OUTPUT_REPORT ,0 ,0 ,7 );if (!report)
drivers/hid/hid-lg3ff.c +9 -2
@@ -129,12 +129,19 @@ static const signed short ff3_joystick_aint lg3ff_init (struct hid_device *hid) { - struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list); -struct input_dev *dev = hidinput->input; +struct hid_input *hidinput; +struct input_dev *dev;const signed short *ff_bits = ff3_joystick_ac;int error;int i; +if (list_empty (&hid->inputs)) { +hid_err (hid,"no inputs found\n" ); +return -ENODEV ; + } + hidinput = list_entry(hid->inputs.next, struct hid_input, list); + dev = hidinput->input; +/* Check that the report looks ok */ if (!hid_validate_values (hid,HID_OUTPUT_REPORT ,0 ,0 ,35 ))return -ENODEV ;
drivers/hid/hid-lg4ff.c +9 -2
@@ -1158,8 +1158,8 @@ static int lg4ff_handle_multimode_wheel(int lg4ff_init (struct hid_device *hid) { - struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list); -struct input_dev *dev = hidinput->input; +struct hid_input *hidinput; +struct input_dev *dev;struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT ].report_list; struct hid_report *report = list_entry(report_list->next, struct hid_report, list);const struct usb_device_descriptor *udesc = &(hid_to_usb_dev (hid)->descriptor);
@@ -1171,6 +1171,13 @@ int lg4ff_init(struct hid_device *hid)int mmode_ret, mmode_idx =-1 ;u16 real_product_id; +if (list_empty (&hid->inputs)) { +hid_err (hid,"no inputs found\n" ); +return -ENODEV ; + } + hidinput = list_entry(hid->inputs.next, struct hid_input, list); + dev = hidinput->input; +/* Check that the report looks ok */ if (!hid_validate_values (hid,HID_OUTPUT_REPORT ,0 ,0 ,7 ))return -1 ;
drivers/hid/hid-lgff.c +9 -2
@@ -127,12 +127,19 @@ static void hid_lgff_set_autocenter(struint lgff_init (struct hid_device * hid) { - struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list); -struct input_dev *dev = hidinput->input; +struct hid_input *hidinput; +struct input_dev *dev;const signed short *ff_bits = ff_joystick;int error;int i; +if (list_empty (&hid->inputs)) { +hid_err (hid,"no inputs found\n" ); +return -ENODEV ; + } + hidinput = list_entry(hid->inputs.next, struct hid_input, list); + dev = hidinput->input; +/* Check that the report looks ok */ if (!hid_validate_values (hid,HID_OUTPUT_REPORT ,0 ,0 ,7 ))return -ENODEV ;
drivers/hid/hid-sony.c +9 -3
@@ -1960,9 +1960,15 @@ static int sony_play_effect(struct inputstatic int sony_init_ff (struct sony_sc *sc) { -struct hid_input *hidinput =list_entry (sc->hdev->inputs.next, - struct hid_input, list); -struct input_dev *input_dev = hidinput->input; +struct hid_input *hidinput; +struct input_dev *input_dev; + +if (list_empty (&sc->hdev->inputs)) { +hid_err (sc->hdev,"no inputs found\n" ); +return -ENODEV ; + } + hidinput = list_entry(sc->hdev->inputs.next, struct hid_input, list); + input_dev = hidinput->input;input_set_capability (input_dev,EV_FF ,FF_RUMBLE );return input_ff_create_memless (input_dev,NULL , sony_play_effect);
drivers/hid/hid-tmff.c +9 -3
@@ -136,12 +136,18 @@ static int tmff_init(struct hid_device *struct tmff_device *tmff;struct hid_report *report;struct list_head *report_list; -struct hid_input *hidinput =list_entry (hid->inputs.next, - struct hid_input, list); -struct input_dev *input_dev = hidinput->input; +struct hid_input *hidinput; +struct input_dev *input_dev;int error;int i; +if (list_empty (&hid->inputs)) { +hid_err (hid,"no inputs found\n" ); +return -ENODEV ; + } + hidinput = list_entry(hid->inputs.next, struct hid_input, list); + input_dev = hidinput->input; + tmff =kzalloc (sizeof (struct tmff_device ),GFP_KERNEL );if (!tmff)return -ENOMEM ;
drivers/hid/hid-zpff.c +9 -3
@@ -66,11 +66,17 @@ static int zpff_init(struct hid_device * {struct zpff_device *zpff;struct hid_report *report; -struct hid_input *hidinput =list_entry (hid->inputs.next, - struct hid_input, list); -struct input_dev *dev = hidinput->input; +struct hid_input *hidinput; +struct input_dev *dev;int i, error; +if (list_empty (&hid->inputs)) { +hid_err (hid,"no inputs found\n" ); +return -ENODEV ; + } + hidinput = list_entry(hid->inputs.next, struct hid_input, list); + dev = hidinput->input; +for (i =0 ; i <4 ; i++) { report =hid_validate_values (hid,HID_OUTPUT_REPORT ,0 , i,1 );if (!report)
Greg Kroah-Hartman
maintainerPATCH 35/46 HID: fix error message in hid_open_report()
In reply to Greg Kroah-HartmanFrom: Michał Mirosław <[email protected]>
commit b3a81c777dcb093020680490ab970d85e2f6f04f upstream.
On HID report descriptor parsing error the code displays bogus pointer instead of error offset (subtracts start=NULL from end). Make the message more useful by displaying correct error offset and include total buffer size for reference.
This was carried over from ancient times - "Fixed" commit just promoted the message from DEBUG to ERROR.
--- drivers/hid/hid-core.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-)
drivers/hid/hid-core.c +5 -2
@@ -959,6 +959,7 @@ int hid_open_report(struct hid_device *d__u8 *start;__u8 *buf;__u8 *end; +__u8 *next;int ret;static int (*dispatch_type[])(struct hid_parser *parser,struct hid_item *item) = {
@@ -1012,7 +1013,8 @@ int hid_open_report(struct hid_device *d device->collection_size =HID_DEFAULT_NUM_COLLECTIONS ; ret = -EINVAL ; -while ((start =fetch_item (start, end, &item)) !=NULL ) { +while ((next =fetch_item (start, end, &item)) !=NULL ) { + start = next;if (item.format !=HID_ITEM_FORMAT_SHORT ) {hid_err (device,"unexpected long global item\n" );
@@ -1041,7 +1043,8 @@ int hid_open_report(struct hid_device *d } } -hid_err (device,"item fetching failed at offset %d\n" , (int )(end - start)); +hid_err (device,"item fetching failed at offset %u/%u\n" , + size - (unsigned int )(end - start), size); err:vfree (parser);hid_close_report (device);
Greg Kroah-Hartman
maintainerPATCH 36/46 nl80211: fix validation of mesh path nexthop
In reply to Greg Kroah-HartmanFrom: Markus Theil <[email protected]>
commit 1fab1b89e2e8f01204a9c05a39fd0b6411a48593 upstream.
Mesh path nexthop should be a ethernet address, but current validation checks against 4 byte integers.
--- net/wireless/nl80211.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
net/wireless/nl80211.c +2 -1
@@ -292,7 +292,8 @@ static const struct nla_policy nl80211_p [NL80211_ATTR_MNTR_FLAGS] = { /* NLA_NESTED can't be empty */ }, [NL80211_ATTR_MESH_ID] = { .type = NLA_BINARY, .len = IEEE80211_MAX_MESH_ID_LEN }, - [NL80211_ATTR_MPATH_NEXT_HOP] = { .type = NLA_U32 }, + [NL80211_ATTR_MPATH_NEXT_HOP] = { .type = NLA_BINARY, + .len = ETH_ALEN }, [NL80211_ATTR_REG_ALPHA2] = { .type = NLA_STRING, .len = 2 }, [NL80211_ATTR_REG_RULES] = { .type = NLA_NESTED },
Greg Kroah-Hartman
maintainerPATCH 37/46 s390/cmm: fix information leak in cmm_timeout_handler()
In reply to Greg Kroah-HartmanFrom: Yihui ZENG <[email protected]>
commit b8e51a6a9db94bc1fb18ae831b3dab106b5a4b5f upstream.
The problem is that we were putting the NUL terminator too far:
buf[sizeof(buf) - 1] = '\0';
If the user input isn't NUL terminated and they haven't initialized the whole buffer then it leads to an info leak. The NUL terminator should be:
buf[len - 1] = '\0';
--- arch/s390/mm/cmm.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-)
arch/s390/mm/cmm.c +6 -6
@@ -306,16 +306,16 @@ static int cmm_timeout_handler(struct ct }if (write) { - len = *lenp; -if (copy_from_user (buf, buffer, - len >sizeof (buf) ?sizeof (buf) : len)) + len =min (*lenp,sizeof (buf)); +if (copy_from_user (buf, buffer, len))return -EFAULT ; - buf[sizeof (buf) -1 ] ='\0' ; + buf[len -1 ] ='\0' ;cmm_skip_blanks (buf, &p); nr =simple_strtoul (p, &p,0 );cmm_skip_blanks (p, &p); seconds =simple_strtoul (p, &p,0 );cmm_set_timeout (nr, seconds); + *ppos += *lenp; }else { len =sprintf (buf,"%ld %ld\n" , cmm_timeout_pages, cmm_timeout_seconds);
@@ -323,9 +323,9 @@ static int cmm_timeout_handler(struct ct len = *lenp;if (copy_to_user (buffer, buf, len))return -EFAULT ; + *lenp = len; + *ppos += len; } - *lenp = len; - *ppos += len;return 0 ; }
Greg Kroah-Hartman
maintainerPATCH 38/46 rtlwifi: Fix potential overflow on P2P code
In reply to Greg Kroah-HartmanFrom: Laura Abbott <[email protected]>
commit 8c55dedb795be8ec0cf488f98c03a1c2176f7fb1 upstream.
Nicolas Waisman noticed that even though noa_len is checked for a compatible length it's still possible to overrun the buffers of p2pinfo since there's no check on the upper bound of noa_num. Bound noa_num against P2P_MAX_NOA_NUM.
--- drivers/net/wireless/realtek/rtlwifi/ps.c | 6 ++++++ 1 file changed, 6 insertions(+)
drivers/net/wireless/realtek/rtlwifi/ps.c +6 -0
@@ -781,6 +781,9 @@ static void rtl_p2p_noa_ie(struct ieee80return ; }else { noa_num = (noa_len -2 ) /13 ; +if (noa_num >P2P_MAX_NOA_NUM ) + noa_num =P2P_MAX_NOA_NUM ; + } noa_index = ie[3 ]; if (rtlpriv->psc.p2p_ps_info.p2p_ps_mode ==
@@ -875,6 +878,9 @@ static void rtl_p2p_action_ie(struct ieereturn ; }else { noa_num = (noa_len -2 ) /13 ; +if (noa_num >P2P_MAX_NOA_NUM ) + noa_num =P2P_MAX_NOA_NUM ; + } noa_index = ie[3 ]; if (rtlpriv->psc.p2p_ps_info.p2p_ps_mode ==
Greg Kroah-Hartman
maintainerPATCH 39/46 llc: fix sk_buff leak in llc_sap_state_process()
In reply to Greg Kroah-HartmanFrom: Eric Biggers <[email protected]>
commit c6ee11c39fcc1fb55130748990a8f199e76263b4 upstream.
syzbot reported:
BUG: memory leak
unreferenced object 0xffff888116270800 (size 224):
comm "syz-executor641", pid 7047, jiffies 4294947360 (age 13.860s)
hex dump (first 32 bytes):
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00 20 e1 2a 81 88 ff ff 00 40 3d 2a 81 88 ff ff . .*.....@=*....
backtrace:
[<000000004d41b4cc>] kmemleak_alloc_recursive include/linux/kmemleak.h:55 [inline]
[<000000004d41b4cc>] slab_post_alloc_hook mm/slab.h:439 [inline]
[<000000004d41b4cc>] slab_alloc_node mm/slab.c:3269 [inline]
[<000000004d41b4cc>] kmem_cache_alloc_node+0x153/0x2a0 mm/slab.c:3579
[<00000000506a5965>] __alloc_skb+0x6e/0x210 net/core/skbuff.c:198
[<000000001ba5a161>] alloc_skb include/linux/skbuff.h:1058 [inline]
[<000000001ba5a161>] alloc_skb_with_frags+0x5f/0x250 net/core/skbuff.c:5327
[<0000000047d9c78b>] sock_alloc_send_pskb+0x269/0x2a0 net/core/sock.c:2225
[<000000003828fe54>] sock_alloc_send_skb+0x32/0x40 net/core/sock.c:2242
[<00000000e34d94f9>] llc_ui_sendmsg+0x10a/0x540 net/llc/af_llc.c:933
[<00000000de2de3fb>] sock_sendmsg_nosec net/socket.c:652 [inline]
[<00000000de2de3fb>] sock_sendmsg+0x54/0x70 net/socket.c:671
[<000000008fe16e7a>] __sys_sendto+0x148/0x1f0 net/socket.c:1964
[...]The bug is that llc_sap_state_process() always takes an extra reference to the skb, but sometimes neither llc_sap_next_state() nor llc_sap_state_process() itself drops this reference.
Fix it by changing llc_sap_next_state() to never consume a reference to the skb, rather than sometimes do so and sometimes not. Then remove the extra skb_get() and kfree_skb() from llc_sap_state_process().
--- net/llc/llc_s_ac.c | 12 +++++++++--- net/llc/llc_sap.c | 23 ++++++++--------------- 2 files changed, 17 insertions(+), 18 deletions(-)
net/llc/llc_s_ac.c +9 -3
@@ -58,8 +58,10 @@ int llc_sap_action_send_ui(struct llc_sa ev->daddr.lsap, LLC_PDU_CMD);llc_pdu_init_as_ui_cmd (skb); rc =llc_mac_hdr_init (skb, ev->saddr.mac, ev->daddr.mac); -if (likely (!rc)) +if (likely (!rc)) { +skb_get (skb); rc =dev_queue_xmit (skb); + }return rc; }
@@ -81,8 +83,10 @@ int llc_sap_action_send_xid_c(struct llc ev->daddr.lsap, LLC_PDU_CMD);llc_pdu_init_as_xid_cmd (skb,LLC_XID_NULL_CLASS_2 ,0 ); rc =llc_mac_hdr_init (skb, ev->saddr.mac, ev->daddr.mac); -if (likely (!rc)) +if (likely (!rc)) { +skb_get (skb); rc =dev_queue_xmit (skb); + }return rc; }
@@ -135,8 +139,10 @@ int llc_sap_action_send_test_c(struct ll ev->daddr.lsap, LLC_PDU_CMD);llc_pdu_init_as_test_cmd (skb); rc =llc_mac_hdr_init (skb, ev->saddr.mac, ev->daddr.mac); -if (likely (!rc)) +if (likely (!rc)) { +skb_get (skb); rc =dev_queue_xmit (skb); + }return rc; }
net/llc/llc_sap.c +8 -15
@@ -197,29 +197,22 @@ out:* After executing actions of the event, upper layer will be indicated * if needed(on receiving an UI frame). sk can be null for the * datalink_proto case. +* +* This function always consumes a reference to the skb. */ static void llc_sap_state_process (struct llc_sap *sap,struct sk_buff *skb) {struct llc_sap_state_ev *ev =llc_sap_ev (skb); -/* -* We have to hold the skb, because llc_sap_next_state -* will kfree it in the sending path and we need to -* look at the skb->cb, where we encode llc_sap_state_ev. -*/ -skb_get (skb); ev->ind_cfm_flag =0 ;llc_sap_next_state (sap, skb); -if (ev->ind_cfm_flag ==LLC_IND ) { -if (skb->sk->sk_state ==TCP_LISTEN ) -kfree_skb (skb); -else { -llc_save_primitive (skb->sk, skb, ev->prim); -/* queue skb to the user. */ -if (sock_queue_rcv_skb (skb->sk, skb)) -kfree_skb (skb); - } +if (ev->ind_cfm_flag ==LLC_IND && skb->sk->sk_state !=TCP_LISTEN ) { +llc_save_primitive (skb->sk, skb, ev->prim); + +/* queue skb to the user. */ +if (sock_queue_rcv_skb (skb->sk, skb) ==0 ) +return ; }kfree_skb (skb); }
Greg Kroah-Hartman
maintainerPATCH 40/46 llc: fix sk_buff leak in llc_conn_service()
In reply to Greg Kroah-HartmanFrom: Eric Biggers <[email protected]>
commit b74555de21acd791f12c4a1aeaf653dd7ac21133 upstream.
syzbot reported:
BUG: memory leak
unreferenced object 0xffff88811eb3de00 (size 224):
comm "syz-executor559", pid 7315, jiffies 4294943019 (age 10.300s)
hex dump (first 32 bytes):
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00 a0 38 24 81 88 ff ff 00 c0 f2 15 81 88 ff ff ..8$............
backtrace:
[<000000008d1c66a1>] kmemleak_alloc_recursive include/linux/kmemleak.h:55 [inline]
[<000000008d1c66a1>] slab_post_alloc_hook mm/slab.h:439 [inline]
[<000000008d1c66a1>] slab_alloc_node mm/slab.c:3269 [inline]
[<000000008d1c66a1>] kmem_cache_alloc_node+0x153/0x2a0 mm/slab.c:3579
[<00000000447d9496>] __alloc_skb+0x6e/0x210 net/core/skbuff.c:198
[<000000000cdbf82f>] alloc_skb include/linux/skbuff.h:1058 [inline]
[<000000000cdbf82f>] llc_alloc_frame+0x66/0x110 net/llc/llc_sap.c:54
[<000000002418b52e>] llc_conn_ac_send_sabme_cmd_p_set_x+0x2f/0x140 net/llc/llc_c_ac.c:777
[<000000001372ae17>] llc_exec_conn_trans_actions net/llc/llc_conn.c:475 [inline]
[<000000001372ae17>] llc_conn_service net/llc/llc_conn.c:400 [inline]
[<000000001372ae17>] llc_conn_state_process+0x1ac/0x640 net/llc/llc_conn.c:75
[<00000000f27e53c1>] llc_establish_connection+0x110/0x170 net/llc/llc_if.c:109
[<00000000291b2ca0>] llc_ui_connect+0x10e/0x370 net/llc/af_llc.c:477
[<000000000f9c740b>] __sys_connect+0x11d/0x170 net/socket.c:1840
[...]The bug is that most callers of llc_conn_send_pdu() assume it consumes a reference to the skb, when actually due to commit b85ab56c3f81 ("llc:
properly handle dev_queue_xmit() return value") it doesn't.
Revert most of that commit, and instead make the few places that need llc_conn_send_pdu() to *not* consume a reference call skb_get() before.
--- include/net/llc_conn.h | 2 +- net/llc/llc_c_ac.c | 8 ++++++-- net/llc/llc_conn.c | 32 +++++++++----------------------- 3 files changed, 16 insertions(+), 26 deletions(-)
include/net/llc_conn.h +1 -1
@@ -104,7 +104,7 @@ void llc_sk_reset(struct sock *sk);/* Access to a connection */ int llc_conn_state_process (struct sock *sk,struct sk_buff *skb); -int llc_conn_send_pdu (struct sock *sk,struct sk_buff *skb); +void llc_conn_send_pdu (struct sock *sk,struct sk_buff *skb);void llc_conn_rtn_pdu (struct sock *sk,struct sk_buff *skb);void llc_conn_resend_i_pdu_as_cmd (struct sock *sk,u8 nr,u8 first_p_bit);void llc_conn_resend_i_pdu_as_rsp (struct sock *sk,u8 nr,u8 first_f_bit);
net/llc/llc_c_ac.c +6 -2
@@ -372,6 +372,7 @@ int llc_conn_ac_send_i_cmd_p_set_1(strucllc_pdu_init_as_i_cmd (skb,1 , llc->vS, llc->vR); rc =llc_mac_hdr_init (skb, llc->dev->dev_addr, llc->daddr.mac);if (likely (!rc)) { +skb_get (skb);llc_conn_send_pdu (sk, skb);llc_conn_ac_inc_vs_by_1 (sk, skb); }
@@ -389,7 +390,8 @@ static int llc_conn_ac_send_i_cmd_p_set_llc_pdu_init_as_i_cmd (skb,0 , llc->vS, llc->vR); rc =llc_mac_hdr_init (skb, llc->dev->dev_addr, llc->daddr.mac);if (likely (!rc)) { - rc =llc_conn_send_pdu (sk, skb); +skb_get (skb); +llc_conn_send_pdu (sk, skb);llc_conn_ac_inc_vs_by_1 (sk, skb); }return rc;
@@ -406,6 +408,7 @@ int llc_conn_ac_send_i_xxx_x_set_0(strucllc_pdu_init_as_i_cmd (skb,0 , llc->vS, llc->vR); rc =llc_mac_hdr_init (skb, llc->dev->dev_addr, llc->daddr.mac);if (likely (!rc)) { +skb_get (skb);llc_conn_send_pdu (sk, skb);llc_conn_ac_inc_vs_by_1 (sk, skb); }
@@ -916,7 +919,8 @@ static int llc_conn_ac_send_i_rsp_f_set_llc_pdu_init_as_i_cmd (skb, llc->ack_pf, llc->vS, llc->vR); rc =llc_mac_hdr_init (skb, llc->dev->dev_addr, llc->daddr.mac);if (likely (!rc)) { - rc =llc_conn_send_pdu (sk, skb); +skb_get (skb); +llc_conn_send_pdu (sk, skb);llc_conn_ac_inc_vs_by_1 (sk, skb); }return rc;
net/llc/llc_conn.c +9 -23
@@ -30,7 +30,7 @@#endif static int llc_find_offset (int state,int ev_type); -static int llc_conn_send_pdus (struct sock *sk,struct sk_buff *skb); +static void llc_conn_send_pdus (struct sock *sk);static int llc_conn_service (struct sock *sk,struct sk_buff *skb); static int llc_exec_conn_trans_actions(struct sock *sk, struct llc_conn_state_trans *trans,
@@ -193,11 +193,11 @@ out_skb_put:return rc; } -int llc_conn_send_pdu (struct sock *sk,struct sk_buff *skb) +void llc_conn_send_pdu (struct sock *sk,struct sk_buff *skb) {/* queue PDU to send to MAC layer */ skb_queue_tail (&sk->sk_write_queue, skb); -return llc_conn_send_pdus (sk, skb); +llc_conn_send_pdus (sk); }/**
@@ -255,7 +255,7 @@ void llc_conn_resend_i_pdu_as_cmd(structif (howmany_resend >0 ) llc->vS = (llc->vS +1 ) %LLC_2_SEQ_NBR_MODULO ;/* any PDUs to re-send are queued up; start sending to MAC */ -llc_conn_send_pdus (sk,NULL ); +llc_conn_send_pdus (sk); out:; }
@@ -296,7 +296,7 @@ void llc_conn_resend_i_pdu_as_rsp(structif (howmany_resend >0 ) llc->vS = (llc->vS +1 ) %LLC_2_SEQ_NBR_MODULO ;/* any PDUs to re-send are queued up; start sending to MAC */ -llc_conn_send_pdus (sk,NULL ); +llc_conn_send_pdus (sk); out:; }
@@ -340,16 +340,12 @@ out:/** * llc_conn_send_pdus - Sends queued PDUs * @sk: active connection -* @hold_skb: the skb held by caller, or NULL if does not care * -* Sends queued pdus to MAC layer for transmission. When @hold_skb is -* NULL, always return 0. Otherwise, return 0 if @hold_skb is sent -* successfully, or 1 for failure. +* Sends queued pdus to MAC layer for transmission. */ -static int llc_conn_send_pdus (struct sock *sk,struct sk_buff *hold_skb) +static void llc_conn_send_pdus (struct sock *sk) {struct sk_buff *skb; -int ret =0 ;while ((skb =skb_dequeue (&sk->sk_write_queue)) !=NULL ) {struct llc_pdu_sn *pdu =llc_pdu_sn_hdr (skb);
@@ -361,20 +357,10 @@ static int llc_conn_send_pdus(struct socskb_queue_tail (&llc_sk (sk)->pdu_unack_q, skb);if (!skb2)break ; -dev_queue_xmit (skb2); - }else { -bool is_target = skb == hold_skb; -int rc; - -if (is_target) -skb_get (skb); - rc =dev_queue_xmit (skb); -if (is_target) - ret = rc; + skb = skb2; } +dev_queue_xmit (skb); } - -return ret; }/**
Greg Kroah-Hartman
maintainerPATCH 41/46 bonding: fix potential NULL deref in bond_update_slave_arr
In reply to Greg Kroah-HartmanFrom: Eric Dumazet <[email protected]>
commit a7137534b597b7c303203e6bc3ed87e87a273bb8 upstream.
syzbot got a NULL dereference in bond_update_slave_arr() [1], happening after a failure to allocate bond->slave_arr
A workqueue (bond_slave_arr_handler) is supposed to retry the allocation later, but if the slave is removed before the workqueue had a chance to complete, bond->slave_arr can still be NULL.
[1]
Failed to build slave-array.
kasan: CONFIG_KASAN_INLINE enabled
kasan: GPF could be caused by NULL-ptr deref or user memory access
general protection fault: 0000 [#1] SMP KASAN PTI Modules linked in: Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011 RIP: 0010:bond_update_slave_arr.cold+0xc6/0x198 drivers/net/bonding/bond_main.c:4039 RSP: 0018:ffff88018fe33678 EFLAGS: 00010246 RAX: dffffc0000000000 RBX: 0000000000000000 RCX: ffffc9000290b000 RDX: 0000000000000000 RSI: ffffffff82b63037 RDI: ffff88019745ea20 RBP: ffff88018fe33760 R08: ffff880170754280 R09: 0000000000000000 R10: 0000000000000000 R11: 0000000000000000 R12: 0000000000000000 R13: ffff88019745ea00 R14: 0000000000000000 R15: ffff88018fe338b0 FS: 00007febd837d700(0000) GS:ffff8801dad00000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00000000004540a0 CR3: 00000001c242e005 CR4: 00000000001626f0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 Call Trace: [<ffffffff82b5b45e>] __bond_release_one+0x43e/0x500 drivers/net/bonding/bond_main.c:1923 [<ffffffff82b5b966>] bond_release drivers/net/bonding/bond_main.c:2039 [inline] [<ffffffff82b5b966>] bond_do_ioctl+0x416/0x870 drivers/net/bonding/bond_main.c:3562 [<ffffffff83ae25f4>] dev_ifsioc+0x6f4/0x940 net/core/dev_ioctl.c:328 [<ffffffff83ae2e58>] dev_ioctl+0x1b8/0xc70 net/core/dev_ioctl.c:495 [<ffffffff83995ffd>] sock_do_ioctl+0x1bd/0x300 net/socket.c:1088 [<ffffffff83996a80>] sock_ioctl+0x300/0x5d0 net/socket.c:1196 [<ffffffff81b124db>] vfs_ioctl fs/ioctl.c:47 [inline] [<ffffffff81b124db>] file_ioctl fs/ioctl.c:501 [inline] [<ffffffff81b124db>] do_vfs_ioctl+0xacb/0x1300 fs/ioctl.c:688 [<ffffffff81b12dc6>] SYSC_ioctl fs/ioctl.c:705 [inline] [<ffffffff81b12dc6>] SyS_ioctl+0xb6/0xe0 fs/ioctl.c:696 [<ffffffff8101ccc8>] do_syscall_64+0x528/0x770 arch/x86/entry/common.c:305 [<ffffffff84400091>] entry_SYSCALL_64_after_hwframe+0x42/0xb7
--- drivers/net/bonding/bond_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/bonding/bond_main.c +1 -1
@@ -3889,7 +3889,7 @@ out:* this to-be-skipped slave to send a packet out. */ old_arr =rtnl_dereference (bond->slave_arr); -for (idx =0 ; idx < old_arr->count; idx++) { +for (idx =0 ; old_arr !=NULL && idx < old_arr->count; idx++) {if (skipslave == old_arr->arr[idx]) { old_arr->arr[idx] = old_arr->arr[old_arr->count-1 ];
Greg Kroah-Hartman
maintainerPATCH 42/46 net: usb: sr9800: fix uninitialized local variable
In reply to Greg Kroah-HartmanFrom: Valentin Vidic <[email protected]>
commit 77b6d09f4ae66d42cd63b121af67780ae3d1a5e9 upstream.
Make sure res does not contain random value if the call to sr_read_cmd fails for some reason.
--- drivers/net/usb/sr9800.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/usb/sr9800.c +1 -1
@@ -336,7 +336,7 @@ static void sr_set_multicast(struct net_static int sr_mdio_read (struct net_device *net,int phy_id,int loc) {struct usbnet *dev =netdev_priv (net); -__le16 res; +__le16 res =0 ;mutex_lock (&dev->phy_mutex);sr_set_sw_mii (dev);
Greg Kroah-Hartman
maintainerPATCH 43/46 sch_netem: fix rcu splat in netem_enqueue()
In reply to Greg Kroah-HartmanFrom: Eric Dumazet <[email protected]>
commit 159d2c7d8106177bd9a986fd005a311fe0d11285 upstream.
qdisc_root() use from netem_enqueue() triggers a lockdep warning.
__dev_queue_xmit() uses rcu_read_lock_bh() which is not equivalent to rcu_read_lock() + local_bh_disable_bh as far as lockdep is concerned.
WARNING: suspicious RCU usage
5.3.0-rc7+ #0 Not tainted
-----------------------------include/net/sch_generic.h:492 suspicious rcu_dereference_check() usage!
other info that might help us debug this:
rcu_scheduler_active = 2, debug_locks = 1
3 locks held by syz-executor427/8855:
#0: 00000000b5525c01 (rcu_read_lock_bh){....}, at: lwtunnel_xmit_redirect include/net/lwtunnel.h:92 [inline] #0: 00000000b5525c01 (rcu_read_lock_bh){....}, at: ip_finish_output2+0x2dc/0x2570 net/ipv4/ip_output.c:214 #1: 00000000b5525c01 (rcu_read_lock_bh){....}, at: __dev_queue_xmit+0x20a/0x3650 net/core/dev.c:3804 #2: 00000000364bae92 (&(&sch->q.lock)->rlock){+.-.}, at: spin_lock include/linux/spinlock.h:338 [inline] #2: 00000000364bae92 (&(&sch->q.lock)->rlock){+.-.}, at: __dev_xmit_skb net/core/dev.c:3502 [inline] #2: 00000000364bae92 (&(&sch->q.lock)->rlock){+.-.}, at: __dev_queue_xmit+0x14b8/0x3650 net/core/dev.c:3838
stack backtrace: CPU: 0 PID: 8855 Comm: syz-executor427 Not tainted 5.3.0-rc7+ #0 Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011 Call Trace: __dump_stack lib/dump_stack.c:77 [inline] dump_stack+0x172/0x1f0 lib/dump_stack.c:113 lockdep_rcu_suspicious+0x153/0x15d kernel/locking/lockdep.c:5357 qdisc_root include/net/sch_generic.h:492 [inline] netem_enqueue+0x1cfb/0x2d80 net/sched/sch_netem.c:479 __dev_xmit_skb net/core/dev.c:3527 [inline] __dev_queue_xmit+0x15d2/0x3650 net/core/dev.c:3838 dev_queue_xmit+0x18/0x20 net/core/dev.c:3902 neigh_hh_output include/net/neighbour.h:500 [inline] neigh_output include/net/neighbour.h:509 [inline] ip_finish_output2+0x1726/0x2570 net/ipv4/ip_output.c:228 __ip_finish_output net/ipv4/ip_output.c:308 [inline] __ip_finish_output+0x5fc/0xb90 net/ipv4/ip_output.c:290 ip_finish_output+0x38/0x1f0 net/ipv4/ip_output.c:318 NF_HOOK_COND include/linux/netfilter.h:294 [inline] ip_mc_output+0x292/0xf40 net/ipv4/ip_output.c:417 dst_output include/net/dst.h:436 [inline] ip_local_out+0xbb/0x190 net/ipv4/ip_output.c:125 ip_send_skb+0x42/0xf0 net/ipv4/ip_output.c:1555 udp_send_skb.isra.0+0x6b2/0x1160 net/ipv4/udp.c:887 udp_sendmsg+0x1e96/0x2820 net/ipv4/udp.c:1174 inet_sendmsg+0x9e/0xe0 net/ipv4/af_inet.c:807 sock_sendmsg_nosec net/socket.c:637 [inline] sock_sendmsg+0xd7/0x130 net/socket.c:657 ___sys_sendmsg+0x3e2/0x920 net/socket.c:2311 __sys_sendmmsg+0x1bf/0x4d0 net/socket.c:2413 __do_sys_sendmmsg net/socket.c:2442 [inline] __se_sys_sendmmsg net/socket.c:2439 [inline] __x64_sys_sendmmsg+0x9d/0x100 net/socket.c:2439 do_syscall_64+0xfd/0x6a0 arch/x86/entry/common.c:296 entry_SYSCALL_64_after_hwframe+0x49/0xbe
--- include/net/sch_generic.h | 5 +++++ net/sched/sch_netem.c | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-)
include/net/sch_generic.h +5 -0
@@ -289,6 +289,11 @@ static inline struct Qdisc *qdisc_root(creturn q; } +static inline struct Qdisc *qdisc_root_bh (const struct Qdisc *qdisc) +{ +return rcu_dereference_bh (qdisc->dev_queue->qdisc); +} +static inline struct Qdisc *qdisc_root_sleeping (const struct Qdisc *qdisc) {return qdisc->dev_queue->qdisc_sleeping;
net/sched/sch_netem.c +1 -1
@@ -464,7 +464,7 @@ static int netem_enqueue(struct sk_buff* skb will be queued. */ if (count >1 && (skb2 =skb_clone (skb,GFP_ATOMIC )) !=NULL ) { -struct Qdisc *rootq =qdisc_root (sch); +struct Qdisc *rootq =qdisc_root_bh (sch);u32 dupsave = q->duplicate;/* prevent duplicating a dup... */ q->duplicate =0 ;
Greg Kroah-Hartman
maintainerPATCH 44/46 sctp: fix the issue that flags are ignored when using kernel_connect
In reply to Greg Kroah-HartmanFrom: Xin Long <[email protected]>
commit 644fbdeacf1d3edd366e44b8ba214de9d1dd66a9 upstream.
Now sctp uses inet_dgram_connect as its proto_ops .connect, and the flags param can't be passed into its proto .connect where this flags is really needed.
sctp works around it by getting flags from socket file in __sctp_connect. It works for connecting from userspace, as inherently the user sock has socket file and it passes f_flags as the flags param into the proto_ops .connect.
However, the sock created by sock_create_kern doesn't have a socket file, and it passes the flags (like O_NONBLOCK) by using the flags param in kernel_connect, which calls proto_ops .connect later.
So to fix it, this patch defines a new proto_ops .connect for sctp, sctp_inet_connect, which calls __sctp_connect() directly with this flags param. After this, the sctp's proto .connect can be removed.
Note that sctp_inet_connect doesn't need to do some checks that are not needed for sctp, which makes thing better than with inet_dgram_connect.
--- include/net/sctp/sctp.h | 2 + net/sctp/ipv6.c | 2 - net/sctp/protocol.c | 2 - net/sctp/socket.c | 56 ++++++++++++++++++++++++++++++++---------------- 4 files changed, 42 insertions(+), 20 deletions(-)
include/net/sctp/sctp.h +2 -0
@@ -98,6 +98,8 @@ void sctp_addr_wq_mgmt(struct net *, str/* * sctp/socket.c */ +int sctp_inet_connect (struct socket *sock,struct sockaddr *uaddr, +int addr_len,int flags);int sctp_backlog_rcv (struct sock *sk,struct sk_buff *skb);int sctp_inet_listen (struct socket *sock,int backlog);void sctp_write_space (struct sock *sk);
net/sctp/ipv6.c +1 -1
@@ -970,7 +970,7 @@ static const struct proto_ops inet6_seqp .owner = THIS_MODULE, .release = inet6_release, .bind = inet6_bind, - .connect = inet_dgram_connect, + .connect = sctp_inet_connect, .socketpair = sock_no_socketpair, .accept = inet_accept, .getname = sctp_getname,
net/sctp/protocol.c +1 -1
@@ -1012,7 +1012,7 @@ static const struct proto_ops inet_seqpa .owner = THIS_MODULE, .release = inet_release, /* Needs to be wrapped... */ .bind = inet_bind, - .connect = inet_dgram_connect, + .connect = sctp_inet_connect, .socketpair = sock_no_socketpair, .accept = inet_accept, .getname = inet_getname, /* Semantics are different. */
net/sctp/socket.c +38 -18
126 lines not on this page · raw message
Greg Kroah-Hartman
maintainerPATCH 45/46 sctp: not bind the socket in sctp_connect
In reply to Greg Kroah-HartmanFrom: Xin Long <[email protected]>
commit 9b6c08878e23adb7cc84bdca94d8a944b03f099e upstream.
Now when sctp_connect() is called with a wrong sa_family, it binds to a port but doesn't set bp->port, then sctp_get_af_specific will return NULL and sctp_connect() returns -EINVAL.
Then if sctp_bind() is called to bind to another port, the last port it has bound will leak due to bp->port is NULL by then.
sctp_connect() doesn't need to bind ports, as later __sctp_connect will do it if bp->port is NULL. So remove it from sctp_connect(). While at it, remove the unnecessary sockaddr.sa_family len check as it's already done in sctp_inet_connect.
--- net/sctp/socket.c | 21 ++------------------- 1 file changed, 2 insertions(+), 19 deletions(-)
net/sctp/socket.c +2 -19
@@ -3897,34 +3897,17 @@ out_nounlock:static int sctp_connect (struct sock *sk,struct sockaddr *addr,int addr_len,int flags) { -struct inet_sock *inet =inet_sk (sk);struct sctp_af *af; -int err =0 ; +int err = -EINVAL ;lock_sock (sk); -pr_debug ("%s: sk:%p, sockaddr:%p, addr_len:%d\n" , __func__, sk, addr, addr_len); -/* We may need to bind the socket. */ -if (!inet->inet_num) { -if (sk->sk_prot->get_port (sk,0 )) { -release_sock (sk); -return -EAGAIN ; - } - inet->inet_sport =htons (inet->inet_num); - } -/* Validate addr_len before calling common connect/connectx routine. */ af =sctp_get_af_specific (addr->sa_family); -if (!af || addr_len < af->sockaddr_len) { - err = -EINVAL ; - }else { -/* Pass correct addr len to common routine (so it knows there -* is only one address being passed. -*/ +if (af && addr_len >= af->sockaddr_len) err =__sctp_connect (sk, addr, af->sockaddr_len, flags,NULL ); - }release_sock (sk);return err;
Greg Kroah-Hartman
maintainerPATCH 46/46 xfs: Correctly invert xfs_buftarg LRU isolation logic
In reply to Greg Kroah-HartmanFrom: Vratislav Bendel <[email protected]>
commit 19957a181608d25c8f4136652d0ea00b3738972d upstream.
Due to an inverted logic mistake in xfs_buftarg_isolate() the xfs_buffers with zero b_lru_ref will take another trip around LRU, while isolating buffers with non-zero b_lru_ref.
Additionally those isolated buffers end up right back on the LRU once they are released, because b_lru_ref remains elevated.
Fix that circuitous route by leaving them on the LRU as originally intended.
--- fs/xfs/xfs_buf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
fs/xfs/xfs_buf.c +1 -1
@@ -1584,7 +1584,7 @@ xfs_buftarg_isolate(* zero. If the value is already zero, we need to reclaim the * buffer, otherwise it gets another trip through the LRU. */ -if (!atomic_add_unless (&bp->b_lru_ref,-1 ,0 )) { +if (atomic_add_unless (&bp->b_lru_ref,-1 ,0 )) {spin_unlock (&bp->b_lock);return LRU_ROTATE ; }
stable-rc/linux-4.4.y boot: 80 boots: 0 failed, 72 passed with 7 offline, 1 conflict (v4.4.198-47-g3849b8fee3c3)
stable-rc/linux-4.4.y boot: 80 boots: 0 failed, 72 passed with 7 offline, 1 conflict (v4.4.198-47-g3849b8fee3c3)
Full Boot Summary: https://kernelci.org/boot/all/job/stable-rc/branch/linux-4.4.y/kernel/v4.4.198-47-g3849b8fee3c3/
Full Build Summary: https://kernelci.org/build/stable-rc/branch/linux-4.4.y/kernel/v4.4.198-47-g3849b8fee3c3/
Tree: stable-rc
Branch: linux-4.4.y
Git Describe: v4.4.198-47-g3849b8fee3c3
Git Commit: 3849b8fee3c31ec2cfef806e0e369ccbd50d0f1e
Git URL: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git
Tested: 41 unique boards, 17 SoC families, 13 builds out of 190
Offline Platforms:
arm:
sunxi_defconfig:
gcc-8
sun5i-r8-chip: 1 offline lab
sun7i-a20-bananapi: 1 offline lab
multi_v7_defconfig:
gcc-8
qcom-apq8064-cm-qs600: 1 offline lab
sun5i-r8-chip: 1 offline lab
sun7i-a20-bananapi: 1 offline lab
davinci_all_defconfig:
gcc-8
dm365evm,legacy: 1 offline lab
qcom_defconfig:
gcc-8
qcom-apq8064-cm-qs600: 1 offline labConflicting Boot Failure Detected: (These likely are not failures as other labs are reporting PASS. Needs review.)
x86_64:
x86_64_defconfig:
qemu_x86_64:
lab-collabora: PASS (gcc-8)
lab-baylibre: FAIL (gcc-8)
---
For more info write to <[email protected]>
Quoted 10 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 4.4.199 release. There are 46 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Wed 06 Nov 2019 09:14:04 PM UTC. Anything received after that time might be too late.
The whole patch series can be found in one patch at:
Quoted 8 lines
https://www.kernel.org/pub/linux/kernel/v4.x/stable-review/patch-4.4.199-rc1.gzor in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.gitlinux-4.4.y
and the diffstat can be found below.thanks,
greg k-h
Results from Linaro’s test farm.
No regressions on arm64, arm, x86_64, and i386.
Summary
------------------------------------------------------------------------
kernel: 4.4.199-rc1
git repo: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git
git branch: linux-4.4.y
git commit: 1e0d280e1f8dbd21a713507c208e2ed524c18257
git describe: v4.4.198-47-g1e0d280e1f8d
Test details: https://qa-reports.linaro.org/lkft/linux-stable-rc-4.4-oe/build/v4.4.198-47-g1e0d280e1f8d
No regressions (compared to build v4.4.198)
No fixes (compared to build v4.4.198)
Ran 14764 total tests in the following environments and test suites.
Environments
--------------
- i386
- juno-r2 - arm64
- qemu_arm
- qemu_arm64
- qemu_i386
- qemu_x86_64
- x15 - arm
- x86_64
Test Suites
-----------
* build
* libhugetlbfs
* ltp-cap_bounds-tests
* ltp-commands-tests
* ltp-containers-tests
* ltp-cpuhotplug-tests
* ltp-cve-tests
* ltp-dio-tests
* ltp-fcntl-locktests-tests
* ltp-filecaps-tests
* ltp-fs-tests
* ltp-fs_bind-tests
* ltp-fs_perms_simple-tests
* ltp-fsx-tests
* ltp-hugetlb-tests
* ltp-io-tests
* ltp-ipc-tests
* ltp-math-tests
* ltp-mm-tests
* ltp-nptl-tests
* ltp-pty-tests
* ltp-sched-tests
* ltp-securebits-tests
* ltp-syscalls-tests
* network-basic-tests
* perf
* spectre-meltdown-checker-test
* v4l2-compliance
* kselftest
* kvm-unit-tests
* ltp-open-posix-tests
* install-android-platform-tools-r2600
Signature · 2 lines
Linaro LKFT https://lkft.linaro.org
Quoted 8 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 4.4.199 release. There are 46 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Wed 06 Nov 2019 09:14:04 PM UTC. Anything received after that time might be too late.
Build results:
total: 170 pass: 170 fail: 0 Qemu test results: total: 324 pass: 324 fail: 0
Guenter
Jon Hunter
maintainerQuoted 9 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 4.4.199 release. There are 46 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Wed 06 Nov 2019 09:14:04 PM UTC. Anything received after that time might be too late.
The whole patch series can be found in one patch at:
Quoted 8 lines
https://www.kernel.org/pub/linux/kernel/v4.x/stable-review/patch-4.4.199-rc1.gzor in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.gitlinux-4.4.y
and the diffstat can be found below.thanks,
greg k-h
All tests for Tegra are passing ...
Test results for stable-v4.4:
6 builds: 6 pass, 0 fail
12 boots: 12 pass, 0 fail
19 tests: 19 pass, 0 failLinux version: 4.4.199-rc1-g3849b8fee3c3
Boards tested: tegra124-jetson-tk1, tegra20-ventana,
tegra30-cardhu-a04
Cheers
Jon
Signature · 1 line
nvpublic