This is the start of the stable review cycle for the 3.16.83 release.
There are 245 patches in this series, which will be posted as responses
to this one. If anyone has any issues with these being applied, please
let me know.
Responses should be made by Tue Apr 28 18:00:00 UTC 2020.
Anything received after that time might be too late.
All the patches have also been committed to the linux-3.16.y-rc branch of
https://git.kernel.org/pub/scm/linux/kernel/git/bwh/linux-stable-rc.git .
A shortlog and diffstat can be found below.
Ben.
-------------
Al Viro (2):
do_last(): fetch directory ->i_mode and ->i_uid before it's too late
[d0cb50185ae942b03c4327be322055d622dc79f6]
vfs: fix do_last() regression
[6404674acd596de41fd3ad5f267b4525494a891a]
Alan Cox (1):
usb: dwc3: pci: Add PCI ID for Intel Braswell
[7d643664ea559b36188cae264047ce3c9bfec3a2]
Alan Stern (1):
HID: Fix slab-out-of-bounds read in hid_field_extract
[8ec321e96e056de84022c032ffea253431a83c3c]
Alberto Aguirre (2):
ALSA: usb-audio: add implicit fb quirk for Axe-Fx II
[17f08b0d9aafccdb10038ab6dbd9ddb6433c13e2]
ALSA: usb-audio: simplify set_sync_ep_implicit_fb_quirk
[103e9625647ad74d201e26fb74afcd8479142a37]
Alex Sverdlin (1):
ARM: 8950/1: ftrace/recordmcount: filter relocation types
[927d780ee371d7e121cea4fc7812f6ef2cea461c]
Amir Goldstein (1):
locks: print unsigned ino in /proc/locks
[98ca480a8f22fdbd768e3dad07024c8d4856576c]
Ard Biesheuvel (1):
x86/efistub: Disable paging at mixed mode entry
[4911ee401b7ceff8f38e0ac597cbf503d71e690c]
Arnd Bergmann (2):
btrfs: tree-checker: use %zu format string for size_t
[7cfad65297bfe0aa2996cd72d21c898aa84436d9]
scsi: fnic: fix invalid stack access
[42ec15ceaea74b5f7a621fc6686cbf69ca66c4cf]
Avinash Patil (1):
mwifiex: fix probable memory corruption while processing TDLS frame
[3c99832d74777c9ec5545a92450fac5d37b0d0e1]
Brian Norris (1):
mwifiex: fix unbalanced locking in mwifiex_process_country_ie()
[65b1aae0d9d5962faccc06bdb8e91a2a0b09451c]
Cengiz Can (1):
blktrace: fix dereference after null check
[153031a301bb07194e9c37466cfce8eacb977621]
Chao Yu (1):
quota: fix wrong condition in is_quota_modification()
[6565c182094f69e4ffdece337d395eb7ec760efc]
Chen-Yu Tsai (1):
net: stmmac: dwmac-sunxi: Allow all RGMII modes
[52cc73e5404c7ba0cbfc50cb4c265108c84b3d5a]
Christian Brauner (1):
taskstats: fix data-race
[0b8d616fb5a8ffa307b1d3af37f55c15dae14f28]
Christophe Leroy (1):
powerpc/irq: fix stack overflow verification
[099bc4812f09155da77eeb960a983470249c9ce1]
Cong Wang (2):
net_sched: fix datalen for ematch
[61678d28d4a45ef376f5d02a839cc37509ae9281]
netfilter: fix a use-after-free in mtype_destroy()
[c120959387efa51479056fd01dc90adfba7a590c]
Dan Carpenter (1):
scsi: iscsi: qla4xxx: fix double free in probe
[fee92f25777789d73e1936b91472e9c4644457c8]
David Hildenbrand (1):
virtio-balloon: fix managed page counts when migrating pages between zones
[63341ab03706e11a31e3dd8ccc0fbc9beaf723f0]
David Sterba (6):
btrfs: add more checks to btrfs_read_sys_array
[e3540eab29e1b2260bc4b9b3979a49a00e3e3af8]
btrfs: cleanup, rename a few variables in btrfs_read_sys_array
[1ffb22cf8c322bbfea6b35fe23d025841b49fede]
btrfs: handle invalid num_stripes in sys_array
[f5cdedd73fa71b74dcc42f2a11a5735d89ce7c4f]
btrfs: kill extent_buffer_page helper
[fb85fc9a675738ee2746b51c3aedde944b18ca02]
btrfs: new define for the inline extent data start
[7ec20afbcb7b257aec82ea5d66e6b0b7499abaca]
btrfs: tree-check: reduce stack consumption in check_dir_item
[e2683fc9d219430f5b78889b50cde7f40efeba7b]
Davidlohr Bueso (1):
blktrace: re-write setting q->blk_trace
[cdea01b2bf98affb7e9c44530108a4a28535eee8]
Dedy Lansky (1):
cfg80211/mac80211: make ieee80211_send_layer2_update a public function
[30ca1aa536211f5ac3de0173513a7a99a98a97f3]
Dmitry Torokhov (5):
HID: hid-input: clear unmapped usages
[4f3882177240a1f55e45a3d241d3121341bead78]
Input: add safety guards to input_set_keycode()
[cb222aed03d798fc074be55e59d9a112338ee784]
ptp: create "pins" together with the rest of attributes
[85a66e55019583da1e0f18706b7a8281c9f6de5b]
ptp: do not explicitly set drvdata in ptp_clock_register()
[882f312dc0751c973db26478f07f082c584d16aa]
ptp: use is_visible method to hide unused attributes
[af59e717d5ff9c8dbf9bcc581c0dfb3b2a9c9030]
Emiliano Ingrassia (1):
usb: core: urb: fix URB structure initialization function
[1cd17f7f0def31e3695501c4f86cd3faf8489840]
Eric Dumazet (9):
6pack,mkiss: fix possible deadlock
[5c9934b6767b16ba60be22ec3cbd4379ad64170d]
bonding: fix bond_neigh_init()
[9e99bfefdbce2e23ef37487a3bcb4adf90a791d1]
macvlan: do not assume mac_header is set in macvlan_broadcast()
[96cc4b69581db68efc9749ef32e9cf8e0160c509]
macvlan: use skb_reset_mac_header() in macvlan_queue_xmit()
[1712b2fff8c682d145c7889d2290696647d82dab]
neighbour: remove neigh_cleanup() method
[f394722fb0d0f701119368959d7cd0ecbc46363a]
netfilter: bridge: make sure to pull arp header in br_nf_forward_arp()
[5604285839aaedfb23ebe297799c6e558939334d]
pkt_sched: fq: do not accept silly TCA_FQ_QUANTUM
[d9e15a2733067c9328fb56d98fe8e574fa19ec31]
tcp: do not send empty skb from tcp_write_xmit()
[1f85e6267caca44b30c54711652b0726fadbb131]
vlan: vlan_changelink() should propagate errors
[eb8ef2a3c50092bb018077c047b8dba1ce0e78e3]
Erkka Talvitie (1):
USB: EHCI: Do not return -EPIPE when hub is disconnected
[64cc3f12d1c7dd054a215bc1ff9cc2abcfe35832]
Eryu Guan (1):
ext4: update c/mtime on truncate up
[911af577de4e444622d46500c1f9a37ab4335d3a]
Eugenio Pérez (1):
vhost: Check docket sk_family instead of call getname
[42d84c8490f9f0931786f1623191fcab397c3d64]
Fabian Henneke (1):
hidraw: Return EPOLLOUT from hidraw_poll
[378b80370aa1fe50f9c48a3ac8af3e416e73b89f]
Felipe Balbi (3):
usb: dwc3: pci: Add Support for Intel Elkhart Lake Devices
[dbb0569de852fb4576d6f62078d515f989a181ca]
usb: dwc3: pci: add support for Comet Lake PCH ID
[7ae622c978db6b2e28b4fced6ecd2a174492059d]
usb: dwc3: pci: add support for TigerLake Devices
[b3649dee5fbb0f6585010e6e9313dfcbb075b22b]
Filipe Manana (3):
Btrfs: fix emptiness check for dirtied extent buffers at check_leaf()
[f177d73949bf758542ca15a1c1945bd2e802cc65]
Btrfs: fix infinite loop during nocow writeback due to race
[de7999afedff02c6631feab3ea726a0e8f8c3d40]
Btrfs: fix removal logic of the tree mod log that leads to use-after-free issues
[6609fee8897ac475378388238456c84298bff802]
Finn Thain (4):
net/sonic: Add mutual exclusion for accessing shared state
[865ad2f2201dc18685ba2686f13217f8b3a9c52c]
net/sonic: Fix receive buffer handling
[9e311820f67e740f4fb8dcb82b4c4b5b05bdd1a5]
net/sonic: Quiesce SONIC before re-initializing descriptor memory
[3f4b7e6a2be982fd8820a2b54d46dd9c351db899]
net/sonic: Use MMIO accessors
[e3885f576196ddfc670b3d53e745de96ffcb49ab]
Florian Faber (1):
can: mscan: mscan_rx_poll(): fix rx path lockup when returning from polling to irq mode
[2d77bd61a2927be8f4e00d9478fe6996c47e8d45]
Florian Westphal (6):
netfilter: arp_tables: init netns pointer in xt_tgchk_param struct
[1b789577f655060d98d20ed0c6f9fbd469d6ba63]
netfilter: arp_tables: init netns pointer in xt_tgdtor_param struct
[212e7f56605ef9688d0846db60c6c6ec06544095]
netfilter: ctnetlink: netns exit must wait for callbacks
[18a110b022a5c02e7dc9f6109d0bd93e58ac6ebb]
netfilter: ebtables: compat: reject all padding in matches/watchers
[e608f631f0ba5f1fc5ee2e260a3a35d13107cbfe]
netfilter: ebtables: convert BUG_ONs to WARN_ONs
[fc6a5d0601c5ac1d02f283a46f60b87b2033e5ca]
netfilter: ipset: avoid null deref when IPSET_ATTR_LINENO is present
[22dad713b8a5ff488e07b821195270672f486eb2]
Geert Uytterhoeven (1):
gpio: Fix error message on out-of-range GPIO in lookup table
[d935bd50dd14a7714cbdba9a76435dbb56edb1ae]
Goldwyn Rodrigues (1):
dm flakey: check for null arg_name in parse_features()
[7690e25302dc7d0cd42b349e746fe44b44a94f2b]
Gu Jinxiang (1):
btrfs: validate type when reading a chunk
[315409b0098fb2651d86553f0436b70502b29bb2]
Hangbin Liu (1):
vxlan: fix tos value before xmit
[71130f29979c7c7956b040673e6b9d5643003176]
Hans de Goede (2):
pinctrl: baytrail: Really serialize all register accesses
[40ecab551232972a39cdd8b6f17ede54a3fdb296]
platform/x86: hp-wmi: Make buffer for HPWMI_FEATURE2_QUERY 128 bytes
[133b2acee3871ae6bf123b8fe34be14464aa3d2c]
Heikki Krogerus (8):
usb: dwc3: pci: add ID for one more Intel Broxton platform
[1ffb4d5cc78a3a99109ff0808ce6915de07a0588]
usb: dwc3: pci: add ID for the Intel Comet Lake -H variant
[3c3caae4cd6e122472efcf64759ff6392fb6bce2]
usb: dwc3: pci: add Intel Cannonlake PCI IDs
[682179592e48fa66056fbad1a86604be4992f885]
usb: dwc3: pci: add Intel Gemini Lake PCI ID
[8f8983a5683623b62b339d159573f95a1fce44f3]
usb: dwc3: pci: add Intel Kabylake PCI ID
[4491ed5042f0419b22a4b08331adb54af31e2caa]
usb: dwc3: pci: add support for Intel Broxton SOC
[b4c580a43d520b7812c0fd064fbab929ce2f1da0]
usb: dwc3: pci: add support for Intel IceLake
[00908693c481f7298adf8cf4d2ff3dfbea8c375f]
usb: dwc3: pci: add support for Intel Sunrise Point PCH
[84a2b61b6eb94036093531cdabc448dddfbae45a]
Hou Tao (1):
dm btree: increase rebalance threshold in __rebalance2()
[474e559567fa631dea8fb8407ab1b6090c903755]
James Bottomley (1):
scsi: enclosure: Fix stale device oops with hot replug
[529244bd1afc102ab164429d338d310d5d65e60d]
Jan Kara (7):
blktrace: Protect q->blk_trace with RCU
[c780e86dd48ef6467a1146cf7d0fe1e05a635039]
ext4: check for directory entries too close to block end
[109ba779d6cca2d519c5dd624a3276d03e21948e]
ext4: fix races between buffered IO and collapse / insert range
[32ebffd3bbb4162da5ff88f9a35dd32d0a28ea70]
ext4: fix races between page faults and hole punching
[ea3d7209ca01da209cda6f0dea8be9cc4b7a933b]
ext4: fix races of writeback with punch hole and zero range
[011278485ecc3cd2a3954b5d4c73101d919bf1fa]
ext4: move unlocked dio protection from ext4_alloc_file_blocks()
[17048e8a083fec7ad841d88ef0812707fbc7e39f]
kobject: Export kobject_get_unless_zero()
[c70c176ff8c3ff0ac6ef9a831cd591ea9a66bd1a]
Jari Ruusu (1):
Fix built-in early-load Intel microcode alignment
[f5ae2ea6347a308cfe91f53b53682ce635497d0d]
Jeff Mahoney (2):
btrfs: cleanup, stop casting for extent_map->lookup everywhere
[95617d69326ce386c95e33db7aeb832b45ee9f8f]
btrfs: struct-funcs, constify readers
[1cbb1f454e5321e47fc1e6b233066c7ccc979d15]
Jerónimo Borque (1):
USB: serial: simple: Add Motorola Solutions TETRA MTP3xxx and MTP85xx
[260e41ac4dd3e5acb90be624c03ba7f019615b75]
Jian-Hong Pan (1):
platform/x86: asus-wmi: Fix keyboard brightness cannot be set to 0
[176a7fca81c5090a7240664e3002c106d296bf31]
Jim Mattson (1):
kvm: x86: Host feature SSBD doesn't imply guest feature SPEC_CTRL_SSBD
[396d2e878f92ec108e4293f1c77ea3bc90b414ff]
Jiri Kosina (1):
HID: hidraw, uhid: Always report EPOLLOUT
[9e635c2851df6caee651e589fbf937b637973c91]
Jiri Slaby (4):
vt: selection, close sel_buffer race
[07e6124a1a46b4b5a9b3cacc0c306b50da87abf5]
vt: selection, handle pending signals in paste_selection
[687bff0cd08f790d540cfb7b2349f0d876cdddec]
vt: selection, push console lock down
[4b70dd57a15d2f4685ac6e38056bad93e81e982f]
vt: selection, push sel_lock up
[e8c75a30a23c6ba63f4ef6895cbf41fd42f21aa2]
Johan Hovold (29):
ALSA: usb-audio: fix sync-ep altsetting sanity check
[5d1b71226dc4d44b4b65766fa9d74492f9d4587b]
Input: aiptek - fix endpoint sanity check
[3111491fca4f01764e0c158c5e0f7ced808eef51]
Input: gtco - fix endpoint sanity check
[a8eeb74df5a6bdb214b2b581b14782c5f5a0cf83]
Input: keyspan-remote - fix control-message timeouts
[ba9a103f40fc4a3ec7558ec9b0b97d4f92034249]
Input: sur40 - fix interface sanity checks
[6b32391ed675827f8425a414abbc6fbd54ea54fe]
USB: adutux: fix interface sanity check
[3c11c4bed02b202e278c0f5c319ae435d7fb9815]
USB: atm: ueagle-atm: add missing endpoint check
[09068c1ad53fb077bdac288869dec2435420bdc4]
USB: core: add endpoint-blacklist quirk
[73f8bda9b5dc1c69df2bc55c0cbb24461a6391a9]
USB: core: fix check for duplicate endpoints
[3e4f8e21c4f27bcf30a48486b9dcc269512b79ff]
USB: idmouse: fix interface sanity checks
[59920635b89d74b9207ea803d5e91498d39e8b69]
USB: quirks: blacklist duplicate ep on Sound Devices USBPre2
[bdd1b147b8026df0e4260b387026b251d888ed01]
USB: serial: ch341: handle unbound port at reset_resume
[4d5ef53f75c22d28f490bcc5c771fcc610a9afa4]
USB: serial: io_edgeport: add missing active-port sanity check
[1568c58d11a7c851bd09341aeefd6a1c308ac40d]
USB: serial: io_edgeport: fix epic endpoint lookup
[7c5a2df3367a2c4984f1300261345817d95b71f8]
USB: serial: io_edgeport: handle unbound ports on URB completion
[e37d1aeda737a20b1846a91a3da3f8b0f00cf690]
USB: serial: keyspan: handle unbound ports
[3018dd3fa114b13261e9599ddb5656ef97a1fa17]
USB: serial: opticon: fix control-message timeouts
[5e28055f340275a8616eee88ef19186631b4d136]
USB: serial: quatech2: handle unbound ports
[9715a43eea77e42678a1002623f2d9a78f5b81a1]
USB: serial: suppress driver bind attributes
[fdb838efa31e1ed9a13ae6ad0b64e30fdbd00570]
can: gs_usb: gs_usb_probe(): use descriptors of current altsetting
[2f361cd9474ab2c4ab9ac8db20faf81e66c6279b]
media: ov519: add missing endpoint sanity checks
[998912346c0da53a6dbb71fab3a138586b596b30]
media: stv06xx: add missing descriptor sanity checks
[485b06aadb933190f4bc44e006076bc27a23f205]
media: xirlink_cit: add missing descriptor sanity checks
[a246b4d547708f33ff4d4b9a7a5dbac741dc89d8]
r8152: add missing endpoint sanity check
[86f3f4cd53707ceeec079b83205c8d3c756eca93]
staging: gigaset: add endpoint-type sanity check
[ed9ed5a89acba51b82bdff61144d4e4a4245ec8a]
staging: gigaset: fix general protection fault on probe
[53f35a39c3860baac1e5ca80bf052751cfb24a99]
staging: gigaset: fix illegal free on probe errors
[84f60ca7b326ed8c08582417493982fe2573a9ad]
staging: rtl8188eu: fix interface sanity check
[74ca34118a0e05793935d804ccffcedd6eb56596]
staging: rtl8712: fix interface sanity check
[c724f776f048538ecfdf53a52b7a522309f5c504]
Johannes Thumshirn (1):
btrfs: ensure that a DUP or RAID1 block group has exactly two stripes
[349ae63f40638a28c6fce52e8447c2d14b84cc0c]
Jose Abreu (2):
net: stmmac: 16KB buffer must be 16 byte aligned
[8605131747e7e1fd8f6c9f97a00287aae2b2c640]
net: stmmac: Enable 16KB buffer size
[b2f3a481c4cd62f78391b836b64c0a6e72b503d2]
Josef Bacik (9):
Btrfs: fix em leak in find_first_block_group
[187ee58c62c1d0d238d3dc4835869d33e1869906]
btrfs: abort transaction after failed inode updates in create_subvol
[c7e54b5102bf3614cadb9ca32d7be73bad6cecf0]
btrfs: check rw_devices, not num_devices for balance
[b35cf1f0bf1f2b0b193093338414b9bd63b29015]
btrfs: do not call synchronize_srcu() in inode_tree_del
[f72ff01df9cf5db25c76674cac16605992d15467]
btrfs: do not delete mismatched root refs
[423a716cd7be16fb08690760691befe3be97d3fc]
btrfs: do not leak reloc root if we fail to read the fs root
[ca1aa2818a53875cfdd175fb5e9a2984e997cce9]
btrfs: handle ENOENT in btrfs_uuid_tree_iterate
[714cd3e8cba6841220dce9063a7388a81de03825]
btrfs: skip log replay on orphaned roots
[9bc574de590510eff899c3ca8dbaf013566b5efe]
ext4: only call ext4_truncate when size <= isize
[3da40c7b089810ac9cf2bb1e59633f619f3a7312]
Jouni Malinen (1):
mac80211: Do not send Layer 2 Update frame before authorization
[3e493173b7841259a08c5c8e5cbe90adb349da7e]
Kaitao Cheng (1):
kernel/trace: Fix do not unregister tracepoints when register sched_migrate_task fail
[50f9ad607ea891a9308e67b81f774c71736d1098]
Keiya Nobuta (1):
usb: core: hub: Improved device recognition on remote wakeup
[9c06ac4c83df6d6fbdbf7488fbad822b4002ba19]
Kenneth Klette Jonassen (1):
pkt_sched: fq: avoid hang when quantum 0
[3725a269815ba6dbb415feddc47da5af7d1fac58]
Lars Möllendorf (1):
iio: buffer: align the size of scan bytes to size of the largest element
[883f616530692d81cb70f8a32d85c0d2afc05f69]
Leo Yan (1):
tty: serial: msm_serial: Fix lockup for sysrq and oops
[0e4f7f920a5c6bfe5e851e989f27b35a0cc7fb7e]
Linus Torvalds (1):
floppy: check FDC index for errors before assigning it
[2e90ca68b0d2f5548804f22f0dd61145516171e3]
Liu Bo (9):
Btrfs: add validadtion checks for chunk loading
[e06cd3dd7cea50e87663a88acdfdb7ac1c53a5ca]
Btrfs: check btree node's nritems
[053ab70f0604224c7893b43f9d9d5efa283580d6]
Btrfs: check inconsistence between chunk and block group
[6fb37b756acce6d6e045f79c3764206033f617b4]
Btrfs: detect corruption when non-root leaf has zero item
[1ba98d086fe3a14d6a31f2f66dbab70c45d00f63]
Btrfs: fix BUG_ON in btrfs_mark_buffer_dirty
[ef85b25e982b5bba1530b936e283ef129f02ab9d]
Btrfs: improve check_node to avoid reading corrupted nodes
[6b722c1747d533ac6d4df110dc8233db46918b65]
Btrfs: kill BUG_ON in run_delayed_tree_ref
[02794222c4132ac003e7281fb71f4ec1645ffc87]
Btrfs: memset to avoid stale content in btree leaf
[851cd173f06045816528176001cf82948282029c]
Btrfs: memset to avoid stale content in btree node block
[3eb548ee3a8042d95ad81be254e67a5222c24e03]
Logan Gunthorpe (1):
chardev: add helper function to register char devs with a struct device
[233ed09d7fdacf592ee91e6c97ce5f4364fbe7c0]
Lu Fengqi (1):
btrfs: Remove redundant btrfs_release_path from btrfs_unlink_subvol
[5b7d687ad5913a56b6a8788435d7a53990b4176d]
Lukas Czerner (1):
ext4: wait for existing dio workers in ext4_alloc_file_blocks()
[0d306dcf86e8f065dff42a4a934ae9d99af35ba5]
Luuk Paulussen (1):
hwmon: (adt7475) Make volt2reg return same reg as reg2volt input
[cf3ca1877574a306c0207cbf7fdf25419d9229df]
Mao Wenan (2):
af_packet: set defaule value for tmo
[b43d1f9f7067c6759b1051e8ecb84e82cef569fe]
net: sonic: return NETDEV_TX_OK if failed to map buffer
[6e1cdedcf0362fed3aedfe051d46bd7ee2a85fe1]
Marcel Holtmann (2):
HID: hidraw: Fix returning EPOLLOUT from hidraw_poll
[9f3b61dc1dd7b81e99e7ed23776bb64a35f39e1a]
HID: uhid: Fix returning EPOLLOUT from uhid_char_poll
[be54e7461ffdc5809b67d2aeefc1ddc9a91470c7]
Mathias Nyman (2):
xhci: handle some XHCI_TRUST_TX_LENGTH quirks cases as default behaviour.
[7ff11162808cc2ec66353fc012c58bb449c892c3]
xhci: make sure interrupts are restored to correct state
[bd82873f23c9a6ad834348f8b83f3b6a5bca2c65]
Mauro Carvalho Chehab (3):
[media] media-device: dynamically allocate struct media_devnode
[a087ce704b802becbb4b0f2a20f2cb3f6911802e]
[media] media-devnode: fix namespace mess
[163f1e93e995048b894c5fc86a6034d16beed740]
[media] media-devnode: just return 0 instead of using a var
[8b37c6455fc8f43e0e95db2847284e618db6a4f8]
Max Kellermann (2):
[media] drivers/media/media-devnode: clear private_data before put_device()
[bf244f665d76d20312c80524689b32a752888838]
[media] media-devnode: add missing mutex lock in error handler
[88336e174645948da269e1812f138f727cd2896b]
Michael Straube (1):
staging: rtl8188eu: Add device code for TP-Link TL-WN727N v5.21
[58dcc5bf4030cab548d5c98cd4cd3632a5444d5a]
Michał Mirosław (1):
mmc: sdhci: fix minimum clock rate for v3 controller
[2a187d03352086e300daa2044051db00044cd171]
Mika Westerberg (4):
pinctrl: baytrail: Clear interrupt triggering from pins that are in GPIO mode
[95f0972c7e4cbf3fc68160131c5ac2f033481d00]
pinctrl: baytrail: Relax GPIO request rules
[f8323b6bb2cc7d26941d4838dd4375952980a88a]
pinctrl: baytrail: Rework interrupt handling
[31e4329f99062a06dca5a493bb4495a63b2dc6ba]
pinctrl: baytrail: Serialize all register access
[39ce8150a079e3ae6ed9abf26d7918a558ef7c19]
Mike Snitzer (1):
dm flakey: fix reads to be issued if drop_writes configured
[299f6230bc6d0ccd5f95bb0fb865d80a9c7d5ccc]
Mikulas Patocka (1):
block: fix an integer overflow in logical block size
[ad6bf88a6c19a39fb3b0045d78ea880325dfcf15]
Moni Shoua (1):
IB/mlx4: Avoid executing gid task when device is being removed
[4bf9715f184969dc703bde7be94919995024a6a9]
Nicolai Stange (2):
libertas: don't exit from lbs_ibss_join_existing() with RCU read lock held
[c7bf1fb7ddca331780b9a733ae308737b39f1ad4]
libertas: make lbs_ibss_join_existing() return error code on rates overflow
[1754c4f60aaf1e17d886afefee97e94d7f27b4cb]
Nikos Tsironis (1):
dm thin metadata: Add support for a pre-commit callback
[ecda7c0280e6b3398459dc589b9a41c1adb45529]
Pablo Neira Ayuso (2):
netfilter: nf_tables: missing sanitization in data from userspace
[71df14b0ce094be46d105b5a3ededd83b8e779a0]
netfilter: nf_tables: validate NFT_DATA_VALUE after nft_data_init()
[0d2c96af797ba149e559c5875c0151384ab6dd14]
Paolo Bonzini (1):
KVM: nVMX: Don't emulate instructions in guest mode
[07721feee46b4b248402133228235318199b05ec]
Parav Pandit (1):
IB/mlx4: Follow mirror sequence of device add during device removal
[89f988d93c62384758b19323c886db917a80c371]
Paul Cercueil (1):
usb: musb: dma: Correct parameter passed to IRQ handler
[c80d0f4426c7fdc7efd6ae8d8b021dcfc89b4254]
Pavel Tatashin (1):
x86/pti/efi: broken conversion from efi to kernel page table
[not upstream; fixes a bug specific to KAISER]
Pengcheng Yang (1):
tcp: fix "old stuff" D-SACK causing SACK to be treated as D-SACK
[c9655008e7845bcfdaac10a1ed8554ec167aea88]
Pete Zaitcev (1):
usb: mon: Fix a deadlock in usbmon between mmap and read
[19e6317d24c25ee737c65d1ffb7483bdda4bb54a]
Peter Hurley (1):
tty: vt: Fix !TASK_RUNNING diagnostic warning from paste_selection()
[61e86cc90af49cecef9c54ccea1f572fbcb695ac]
Qize Wang (1):
mwifiex: Fix heap overflow in mmwifiex_process_tdls_action_frame()
[1e58252e334dc3f3756f424a157d1b7484464c40]
Qu Wenruo (14):
btrfs: Add checker for EXTENT_CSUM
[4b865cab96fe2a30ed512cf667b354bd291b3b0a]
btrfs: Add sanity check for EXTENT_DATA when reading out leaf
[40c3c40947324d9f40bf47830c92c59a9bbadf4a]
btrfs: Check if item pointer overlaps with the item itself
[7f43d4affb2a254d421ab20b0cf65ac2569909fb]
btrfs: Check that each block group has corresponding chunk at mount time
[514c7dca85a0bf40be984dab0b477403a6db901f]
btrfs: Enhance chunk validation check
[f04b772bfc17f502703794f4d100d12155c1a1a9]
btrfs: Move leaf and node validation checker to tree-checker.c
[557ea5dd003d371536f6b4e8f7c8209a2b6fd4e3]
btrfs: Refactor check_leaf function for later expansion
[c3267bbaa9cae09b62960eafe33ad19196803285]
btrfs: Verify that every chunk has corresponding block group at mount time
[7ef49515fa6727cb4b6f2f5b0ffbc5fc20a9f8c6]
btrfs: tree-checker: Add checker for dir item
[ad7b0368f33cffe67fecd302028915926e50ef7e]
btrfs: tree-checker: Check level for leaves and nodes
[f556faa46eb4e96d0d0772e74ecf66781e132f72]
btrfs: tree-checker: Detect invalid and empty essential trees
[ba480dd4db9f1798541eb2d1c423fc95feee8d36]
btrfs: tree-checker: Enhance btrfs_check_node output
[bba4f29896c986c4cec17bc0f19f2ce644fceae1]
btrfs: tree-checker: Fix false panic for sanity test
[69fc6cbbac542c349b3d350d10f6e394c253c81d]
btrfs: tree-checker: Verify block_group_item
[fce466eab7ac6baa9d2dcd88abcf945be3d4a089]
Radoslaw Tyl (1):
ixgbevf: Remove limit of 10 entries for unicast filter list
[aa604651d523b1493988d0bf6710339f3ee60272]
Rafael J. Wysocki (1):
ACPI: PM: Avoid attaching ACPI PM domain to certain devices
[b9ea0bae260f6aae546db224daa6ac1bd9d94b91]
Randy Dunlap (1):
mm: mempolicy: require at least one nodeid for MPOL_PREFERRED
[aa9f7d5172fac9bf1f09e678c35e287a40a7b7dd]
Richard Palethorpe (2):
can, slip: Protect tty->disc_data in write_wakeup and close with RCU
[0ace17d56824165c7f4c68785d6b58971db954dd]
slcan: Don't transmit uninitialized stack data in padding
[b9258a2cece4ec1f020715fe3554bc2e360f6264]
Russell King (2):
gpiolib: fix up emulated open drain outputs
[256efaea1fdc4e38970489197409a26125ee0aaa]
mod_devicetable: fix PHY module format
[d2ed49cf6c13e379c5819aa5ac20e1f9674ebc89]
Sabrina Dubroca (1):
net: ipv6_stub: use ip6_dst_lookup_flow instead of ip6_dst_lookup
[6c8991f41546c3c472503dff1ea9daaddf9331c2]
Salvatore Mesoraca (1):
namei: allow restricted O_CREAT of FIFOs and regular files
[30aba6656f61ed44cba445a3c0d38b296fa9e8f5]
Shaokun Zhang (1):
btrfs: tree-checker: Fix misleading group system information
[761333f2f50ccc887aa9957ae829300262c0d15b]
Shengjiu Wang (1):
ASoC: wm8962: fix lambda value
[556672d75ff486e0b6786056da624131679e0576]
Shuah Khan (3):
[media] media: Fix media_open() to clear filp->private_data in error leg
[d40ec6fdb0b03b7be4c7923a3da0e46bf943740a]
[media] media: fix media devnode ioctl/syscall and unregister race
[6f0dd24a084a17f9984dd49dffbf7055bf123993]
[media] media: fix use-after-free in cdev_put() when app exits after driver unbind
[5b28dde51d0ccc54cee70756e1800d70bed7114a]
Steven Rostedt (1):
tracing: Have stack tracer compile when MCOUNT_INSN_SIZE is not defined
[b8299d362d0837ae39e87e9019ebe6b736e0f035]
Sudip Mukherjee (2):
tty: always relink the port
[273f632912f1b24b642ba5b7eb5022e43a72f3b5]
tty: link tty and port before configuring it as console
[fb2b90014d782d80d7ebf663e50f96d8c507a73c]
Suren Baghdasaryan (1):
staging: android: ashmem: Disallow ashmem memory from being remapped
[6d67b0290b4b84c477e6a2fc6e005e174d3c7786]
Suwan Kim (1):
usbip: Fix error path of vhci_recv_ret_submit()
[aabb5b833872524eaf28f52187e5987984982264]
Sven Eckelmann (1):
batman-adv: Fix DAT candidate selection on little endian systems
[4cc4a1708903f404d2ca0dfde30e71e052c6cbc9]
Takashi Iwai (4):
ALSA: hda/ca0132 - Avoid endless loop
[cb04fc3b6b076f67d228a0b7d096c69ad486c09c]
ALSA: ice1724: Fix sleep-in-atomic in Infrasonic Quartet support code
[0aec96f5897ac16ad9945f531b4bef9a2edd2ebd]
ALSA: pcm: Avoid possible info leaks from PCM stream buffers
[add9d56d7b3781532208afbff5509d7382fb6efe]
ALSA: seq: Fix racy access for queue timer in proc read
[60adcfde92fa40fcb2dbf7cc52f9b096e0cd109a]
Tom Lendacky (1):
x86/microcode/AMD: Add support for fam17h microcode loading
[f4e9b7af0cd58dd039a0fb2cd67d57cea4889abf]
Vivek Goyal (1):
dm: do not override error code returned from dm_get_device()
[e80d1c805a3b2f0ad2081369be5dc5deedd5ee59]
Vladis Dronov (2):
ptp: fix the race between the release of ptp_clock and cdev
[a33121e5487b424339636b25c35d3a180eaa5f5e]
ptp: free ptp device pin descriptors properly
[75718584cb3c64e6269109d4d54f888ac5a5fd15]
Wang Shilong (1):
Btrfs: fix wrong max inline data size limit
[c01a5c074c0f6f85a3b02e39432b9e5576ab51de]
Wei Yongjun (1):
dm flakey: return -EINVAL on interval bounds error in flakey_ctr()
[bff7e067ee518f9ed7e1cbc63e4c9e01670d0b71]
Wen Huang (1):
libertas: Fix two buffer overflows at parsing bss descriptor
[e5e884b42639c74b5b57dc277909915c0aefc8bb]
Wen Yang (1):
ftrace: Avoid potential division by zero in function profiler
[e31f7939c1c27faa5d0e3f14519eaf7c89e8a69d]
Will Deacon (1):
chardev: Avoid potential use-after-free in 'chrdev_open()'
[68faa679b8be1a74e6663c21c3a9d25d32f1c079]
Xiang Chen (1):
scsi: sd: Clear sdkp->protection_type if disk is reformatted without PI
[465f4edaecc6c37f81349233e84d46246bcac11a]
Xin Long (1):
sctp: free cmd->obj.chunk for the unprocessed SCTP_CMD_REPLY
[be7a7729207797476b6666f046d765bdf9630407]
YueHaibing (1):
ptp: Fix pass zero to ERR_PTR() in ptp_clock_register
[aea0a897af9e44c258e8ab9296fad417f1bc063a]
Zhang Xiaoxu (1):
vgacon: Fix a UAF in vgacon_invert_region
[513dc792d6060d5ef572e43852683097a8420f56]
Documentation/sysctl/fs.txt | 36 ++++
Makefile | 4 +-
arch/powerpc/kernel/irq.c | 4 +-
arch/x86/boot/compressed/head_64.S | 5 +
arch/x86/include/asm/kaiser.h | 10 +
arch/x86/kernel/cpu/microcode/amd.c | 4 +
arch/x86/kvm/cpuid.c | 3 +-
arch/x86/kvm/vmx.c | 2 +-
arch/x86/realmode/init.c | 4 +-
arch/x86/realmode/rm/trampoline_64.S | 3 +-
block/blk-settings.c | 2 +-
drivers/acpi/device_pm.c | 12 +-
drivers/block/floppy.c | 7 +-
drivers/gpio/gpiolib.c | 13 +-
drivers/hid/hid-core.c | 6 +
drivers/hid/hid-input.c | 16 +-
drivers/hid/hidraw.c | 7 +-
drivers/hid/uhid.c | 5 +-
drivers/hwmon/adt7475.c | 5 +-
drivers/iio/industrialio-buffer.c | 6 +-
drivers/infiniband/hw/mlx4/main.c | 16 +-
drivers/input/input.c | 26 ++-
drivers/input/misc/keyspan_remote.c | 9 +-
drivers/input/tablet/aiptek.c | 6 +-
drivers/input/tablet/gtco.c | 10 +-
drivers/input/touchscreen/sur40.c | 2 +-
drivers/isdn/gigaset/usb-gigaset.c | 23 ++-
drivers/md/dm-crypt.c | 4 +-
drivers/md/dm-delay.c | 16 +-
drivers/md/dm-flakey.c | 40 ++--
drivers/md/dm-linear.c | 7 +-
drivers/md/dm-raid1.c | 8 +-
drivers/md/dm-snap-persistent.c | 2 +-
drivers/md/dm-stripe.c | 8 +-
drivers/md/dm-thin-metadata.c | 29 +++
drivers/md/dm-thin-metadata.h | 7 +
drivers/md/persistent-data/dm-btree-remove.c | 8 +-
drivers/md/raid0.c | 2 +-
drivers/media/media-device.c | 43 +++--
drivers/media/media-devnode.c | 171 +++++++++--------
drivers/media/usb/gspca/ov519.c | 10 +
drivers/media/usb/gspca/stv06xx/stv06xx.c | 19 +-
drivers/media/usb/gspca/stv06xx/stv06xx_pb0100.c | 4 +
drivers/media/usb/gspca/xirlink_cit.c | 18 +-
drivers/media/usb/uvc/uvc_driver.c | 2 +-
drivers/misc/enclosure.c | 3 +-
drivers/mmc/host/sdhci.c | 10 +-
drivers/net/bonding/bond_main.c | 40 ++--
drivers/net/can/mscan/mscan.c | 21 +--
drivers/net/can/slcan.c | 16 +-
drivers/net/can/usb/gs_usb.c | 4 +-
drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c | 5 -
drivers/net/ethernet/natsemi/sonic.c | 113 +++++++++---
drivers/net/ethernet/natsemi/sonic.h | 25 ++-
drivers/net/ethernet/stmicro/stmmac/common.h | 5 +-
drivers/net/ethernet/stmicro/stmmac/dwmac-sunxi.c | 2 +-
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 4 +-
drivers/net/hamradio/6pack.c | 4 +-
drivers/net/hamradio/mkiss.c | 4 +-
drivers/net/macvlan.c | 3 +-
drivers/net/slip/slip.c | 12 +-
drivers/net/usb/r8152.c | 3 +
drivers/net/vxlan.c | 5 +-
drivers/net/wireless/libertas/cfg.c | 18 +-
drivers/net/wireless/mwifiex/sta_ioctl.c | 1 +
drivers/net/wireless/mwifiex/tdls.c | 74 +++++++-
drivers/pinctrl/pinctrl-baytrail.c | 212 +++++++++++++---------
drivers/platform/x86/asus-wmi.c | 8 +-
drivers/platform/x86/hp-wmi.c | 2 +-
drivers/ptp/ptp_clock.c | 42 ++---
drivers/ptp/ptp_private.h | 9 +-
drivers/ptp/ptp_sysfs.c | 162 +++++++----------
drivers/scsi/fnic/vnic_dev.c | 20 +-
drivers/scsi/qla4xxx/ql4_os.c | 1 -
drivers/scsi/sd.c | 4 +-
drivers/staging/android/ashmem.c | 28 +++
drivers/staging/rtl8188eu/os_dep/usb_intf.c | 3 +-
drivers/staging/rtl8712/usb_intf.c | 2 +-
drivers/staging/usbip/vhci_rx.c | 13 +-
drivers/tty/serial/msm_serial.c | 13 +-
drivers/tty/serial/serial_core.c | 1 +
drivers/tty/vt/selection.c | 34 +++-
drivers/tty/vt/vt.c | 2 -
drivers/usb/atm/ueagle-atm.c | 18 +-
drivers/usb/core/config.c | 77 +++++++-
drivers/usb/core/hub.c | 1 +
drivers/usb/core/quirks.c | 37 ++++
drivers/usb/core/urb.c | 1 +
drivers/usb/core/usb.h | 3 +
drivers/usb/dwc3/dwc3-pci.c | 30 +++
drivers/usb/host/ehci-q.c | 13 +-
drivers/usb/host/xhci-hub.c | 8 +-
drivers/usb/host/xhci-ring.c | 3 +-
drivers/usb/misc/adutux.c | 2 +-
drivers/usb/misc/idmouse.c | 2 +-
drivers/usb/mon/mon_bin.c | 32 ++--
drivers/usb/musb/musbhsdma.c | 2 +-
drivers/usb/serial/ch341.c | 6 +-
drivers/usb/serial/io_edgeport.c | 26 +--
drivers/usb/serial/keyspan.c | 4 +
drivers/usb/serial/opticon.c | 2 +-
drivers/usb/serial/quatech2.c | 6 +
drivers/usb/serial/usb-serial-simple.c | 2 +
drivers/usb/serial/usb-serial.c | 3 +
drivers/vhost/net.c | 13 +-
drivers/video/console/vgacon.c | 3 +
drivers/virtio/virtio_balloon.c | 10 +
firmware/Makefile | 2 +-
fs/btrfs/Makefile | 2 +-
fs/btrfs/ctree.c | 19 +-
fs/btrfs/ctree.h | 157 +++++++++-------
fs/btrfs/dev-replace.c | 2 +-
fs/btrfs/disk-io.c | 80 ++------
fs/btrfs/extent-tree.c | 110 ++++++++++-
fs/btrfs/extent_io.c | 98 +++++-----
fs/btrfs/extent_io.h | 25 +--
fs/btrfs/extent_map.c | 2 +-
fs/btrfs/extent_map.h | 10 +-
fs/btrfs/inode.c | 8 +-
fs/btrfs/ioctl.c | 10 +-
fs/btrfs/relocation.c | 1 +
fs/btrfs/root-tree.c | 10 +-
fs/btrfs/scrub.c | 2 +-
fs/btrfs/struct-funcs.c | 9 +-
fs/btrfs/tree-log.c | 24 ++-
fs/btrfs/uuid-tree.c | 2 +
fs/btrfs/volumes.c | 206 +++++++++++++++++----
fs/btrfs/volumes.h | 2 +
fs/char_dev.c | 88 ++++++++-
fs/ext4/dir.c | 5 +
fs/ext4/ext4.h | 13 ++
fs/ext4/extents.c | 89 +++++----
fs/ext4/file.c | 2 +-
fs/ext4/inode.c | 117 +++++++++---
fs/ext4/super.c | 1 +
fs/ext4/truncate.h | 2 +
fs/locks.c | 2 +-
fs/namei.c | 56 +++++-
include/linux/blkdev.h | 10 +-
include/linux/blktrace_api.h | 6 +-
include/linux/cdev.h | 5 +
include/linux/fs.h | 2 +
include/linux/if_ether.h | 8 +
include/linux/kobject.h | 2 +
include/linux/mod_devicetable.h | 4 +-
include/linux/netfilter_arp/arp_tables.h | 2 +-
include/linux/posix-clock.h | 19 +-
include/linux/quotaops.h | 2 +-
include/linux/usb/quirks.h | 3 +
include/media/media-device.h | 5 +-
include/media/media-devnode.h | 32 +++-
include/net/addrconf.h | 5 +-
include/net/cfg80211.h | 11 ++
include/net/neighbour.h | 1 -
kernel/sysctl.c | 18 ++
kernel/taskstats.c | 30 +--
kernel/time/posix-clock.c | 31 ++--
kernel/trace/blktrace.c | 129 ++++++++-----
kernel/trace/ftrace.c | 6 +-
kernel/trace/trace_sched_wakeup.c | 4 +-
kernel/trace/trace_stack.c | 5 +
lib/kobject.c | 5 +-
mm/mempolicy.c | 6 +-
net/8021q/vlan_netlink.c | 10 +-
net/batman-adv/distributed-arp-table.c | 4 +-
net/bridge/br_netfilter.c | 3 +
net/bridge/netfilter/ebtables.c | 58 +++---
net/core/neighbour.c | 3 -
net/ipv4/netfilter/arp_tables.c | 42 +++--
net/ipv4/netfilter/arptable_filter.c | 2 +-
net/ipv4/tcp_input.c | 5 +-
net/ipv4/tcp_output.c | 8 +
net/ipv6/af_inet6.c | 2 +-
net/mac80211/cfg.c | 55 +-----
net/mac80211/sta_info.c | 4 +
net/netfilter/ipset/ip_set_bitmap_gen.h | 2 +-
net/netfilter/ipset/ip_set_core.c | 3 +-
net/netfilter/nf_conntrack_netlink.c | 3 +
net/netfilter/nft_bitwise.c | 19 +-
net/netfilter/nft_cmp.c | 18 +-
net/packet/af_packet.c | 3 +-
net/sched/ematch.c | 2 +-
net/sched/sch_fq.c | 10 +-
net/sctp/sm_sideeffect.c | 28 ++-
net/wireless/util.c | 45 +++++
scripts/recordmcount.c | 17 ++
sound/core/pcm_native.c | 4 +
sound/core/seq/seq_timer.c | 14 +-
sound/pci/hda/patch_ca0132.c | 5 +-
sound/pci/ice1712/ice1724.c | 9 +-
sound/soc/codecs/wm8962.c | 4 +-
sound/usb/pcm.c | 44 +++--
192 files changed, 2624 insertions(+), 1185 deletions(-)
--
Ben Hutchings
Knowledge is power. France is bacon.
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Felipe Balbi <[email protected]>
commit b3649dee5fbb0f6585010e6e9313dfcbb075b22b upstream.
This patch adds the necessary PCI ID for TGP-LP devices.
Signed-off-by: Felipe Balbi <[email protected]>
[bwh: Backported to 3.16:
- No properties support
- Adjust context, indentation]
Signed-off-by: Ben Hutchings <[email protected]>
---
drivers/usb/dwc3/dwc3-pci.c | 4 ++++
1 file changed, 4 insertions(+)
--- a/drivers/usb/dwc3/dwc3-pci.c
+++ b/drivers/usb/dwc3/dwc3-pci.c
@@ -43,6 +43,7 @@
#define PCI_DEVICE_ID_INTEL_CNPH 0xa36e
#define PCI_DEVICE_ID_INTEL_ICLLP 0x34ee
#define PCI_DEVICE_ID_INTEL_EHLLP 0x4b7e
+#define PCI_DEVICE_ID_INTEL_TGPLP 0xa0ee
struct dwc3_pci {
struct device *dev;
@@ -211,6 +212,7 @@ static const struct pci_device_id dwc3_p
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_CNPH), },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICLLP), },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_EHLLP), },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_TGPLP), },
{ } /* Terminating Entry */
};
MODULE_DEVICE_TABLE(pci, dwc3_pci_id_table);
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Mathias Nyman <[email protected]>
commit 7ff11162808cc2ec66353fc012c58bb449c892c3 upstream.
xhci driver claims it needs XHCI_TRUST_TX_LENGTH quirk for both
Broadcom/Cavium and a Renesas xHC controllers.
The quirk was inteded for handling false "success" complete event for
transfers that had data left untransferred.
These transfers should complete with "short packet" events instead.
In these two new cases the false "success" completion is reported
after a "short packet" if the TD consists of several TRBs.
xHCI specs 4.10.1.1.2 say remaining TRBs should report "short packet"
as well after the first short packet in a TD, but this issue seems so
common it doesn't make sense to add the quirk for all vendors.
Turn these events into short packets automatically instead.
This gets rid of the "The WARN Successful completion on short TX for
slot 1 ep 1: needs XHCI_TRUST_TX_LENGTH quirk" warning in many cases.
Reported-by: Eli Billauer <[email protected]>
Reported-by: Ard Biesheuvel <[email protected]>
Tested-by: Eli Billauer <[email protected]>
Tested-by: Ard Biesheuvel <[email protected]>
Signed-off-by: Mathias Nyman <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Greg Kroah-Hartman <[email protected]>
[bwh: Backported to 3.16: adjust context]
Signed-off-by: Ben Hutchings <[email protected]>
---
drivers/usb/host/xhci-ring.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -2345,7 +2345,8 @@ static int handle_tx_event(struct xhci_h
case COMP_SUCCESS:
if (EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)) == 0)
break;
- if (xhci->quirks & XHCI_TRUST_TX_LENGTH)
+ if (xhci->quirks & XHCI_TRUST_TX_LENGTH ||
+ ep_ring->last_td_was_short)
trb_comp_code = COMP_SHORT_TX;
else
xhci_warn_ratelimited(xhci,
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Johan Hovold <[email protected]>
commit bdd1b147b8026df0e4260b387026b251d888ed01 upstream.
This device has a broken vendor-specific altsetting for interface 1,
where endpoint 0x85 is declared as an isochronous endpoint despite being
used by interface 2 for audio capture.
Device Descriptor:
bLength 18
bDescriptorType 1
bcdUSB 2.00
bDeviceClass 239 Miscellaneous Device
bDeviceSubClass 2
bDeviceProtocol 1 Interface Association
bMaxPacketSize0 64
idVendor 0x0926
idProduct 0x0202
bcdDevice 1.00
iManufacturer 1 Sound Devices
iProduct 2 USBPre2
iSerial 3 [...]
bNumConfigurations 1
[...]
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 1
bAlternateSetting 3
bNumEndpoints 2
bInterfaceClass 255 Vendor Specific Class
bInterfaceSubClass 0
bInterfaceProtocol 0
iInterface 0
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x85 EP 5 IN
bmAttributes 5
Transfer Type Isochronous
Synch Type Asynchronous
Usage Type Data
wMaxPacketSize 0x0126 1x 294 bytes
bInterval 1
[...]
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 2
bAlternateSetting 1
bNumEndpoints 1
bInterfaceClass 1 Audio
bInterfaceSubClass 2 Streaming
bInterfaceProtocol 0
iInterface 0
AudioStreaming Interface Descriptor:
bLength 7
bDescriptorType 36
bDescriptorSubtype 1 (AS_GENERAL)
bTerminalLink 4
bDelay 1 frames
wFormatTag 0x0001 PCM
AudioStreaming Interface Descriptor:
bLength 26
bDescriptorType 36
bDescriptorSubtype 2 (FORMAT_TYPE)
bFormatType 1 (FORMAT_TYPE_I)
bNrChannels 2
bSubframeSize 2
bBitResolution 16
bSamFreqType 6 Discrete
tSamFreq[ 0] 8000
tSamFreq[ 1] 16000
tSamFreq[ 2] 24000
tSamFreq[ 3] 32000
tSamFreq[ 4] 44100
tSamFreq[ 5] 48000
Endpoint Descriptor:
bLength 9
bDescriptorType 5
bEndpointAddress 0x85 EP 5 IN
bmAttributes 5
Transfer Type Isochronous
Synch Type Asynchronous
Usage Type Data
wMaxPacketSize 0x0126 1x 294 bytes
bInterval 4
bRefresh 0
bSynchAddress 0
AudioStreaming Endpoint Descriptor:
bLength 7
bDescriptorType 37
bDescriptorSubtype 1 (EP_GENERAL)
bmAttributes 0x01
Sampling Frequency
bLockDelayUnits 2 Decoded PCM samples
wLockDelay 0x0000
Since commit 3e4f8e21c4f2 ("USB: core: fix check for duplicate
endpoints") USB core ignores any duplicate endpoints found during
descriptor parsing, but in this case we need to ignore the first
instance in order to avoid breaking the audio capture interface.
Fixes: 3e4f8e21c4f2 ("USB: core: fix check for duplicate endpoints")
Reported-by: edes <[email protected]>
Tested-by: edes <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Johan Hovold <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Greg Kroah-Hartman <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
drivers/usb/core/quirks.c | 5 +++++
1 file changed, 5 insertions(+)
--- a/drivers/usb/core/quirks.c
+++ b/drivers/usb/core/quirks.c
@@ -206,6 +206,10 @@ static const struct usb_device_id usb_qu
{ USB_DEVICE(0x0904, 0x6103), .driver_info =
USB_QUIRK_LINEAR_FRAME_INTR_BINTERVAL },
+ /* Sound Devices USBPre2 */
+ { USB_DEVICE(0x0926, 0x0202), .driver_info =
+ USB_QUIRK_ENDPOINT_BLACKLIST },
+
/* Keytouch QWERTY Panel keyboard */
{ USB_DEVICE(0x0926, 0x3333), .driver_info =
USB_QUIRK_CONFIG_INTF_STRINGS },
@@ -325,6 +329,7 @@ static const struct usb_device_id usb_am
* Matched for devices with USB_QUIRK_ENDPOINT_BLACKLIST.
*/
static const struct usb_device_id usb_endpoint_blacklist[] = {
+ { USB_DEVICE_INTERFACE_NUMBER(0x0926, 0x0202, 1), .driver_info = 0x85 },
{ }
};
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Filipe Manana <[email protected]>
commit de7999afedff02c6631feab3ea726a0e8f8c3d40 upstream.
When starting writeback for a range that covers part of a preallocated
extent, due to a race with writeback for another range that also covers
another part of the same preallocated extent, we can end up in an infinite
loop.
Consider the following example where for inode 280 we have two dirty
ranges:
range A, from 294912 to 303103, 8192 bytes
range B, from 348160 to 438271, 90112 bytes
and we have the following file extent item layout for our inode:
leaf 38895616 gen 24544 total ptrs 29 free space 13820 owner 5
(...)
item 27 key (280 108 200704) itemoff 14598 itemsize 53
extent data disk bytenr 0 nr 0 type 1 (regular)
extent data offset 0 nr 94208 ram 94208
item 28 key (280 108 294912) itemoff 14545 itemsize 53
extent data disk bytenr 10433052672 nr 81920 type 2 (prealloc)
extent data offset 0 nr 81920 ram 81920
Then the following happens:
1) Writeback starts for range B (from 348160 to 438271), execution of
run_delalloc_nocow() starts;
2) The first iteration of run_delalloc_nocow()'s whil loop leaves us at
the extent item at slot 28, pointing to the prealloc extent item
covering the range from 294912 to 376831. This extent covers part of
our range;
3) An ordered extent is created against that extent, covering the file
range from 348160 to 376831 (28672 bytes);
4) We adjust 'cur_offset' to 376832 and move on to the next iteration of
the while loop;
5) The call to btrfs_lookup_file_extent() leaves us at the same leaf,
pointing to slot 29, 1 slot after the last item (the extent item
we processed in the previous iteration);
6) Because we are a slot beyond the last item, we call btrfs_next_leaf(),
which releases the search path before doing a another search for the
last key of the leaf (280 108 294912);
7) Right after btrfs_next_leaf() released the path, and before it did
another search for the last key of the leaf, writeback for the range
A (from 294912 to 303103) completes (it was previously started at
some point);
8) Upon completion of the ordered extent for range A, the prealloc extent
we previously found got split into two extent items, one covering the
range from 294912 to 303103 (8192 bytes), with a type of regular extent
(and no longer prealloc) and another covering the range from 303104 to
376831 (73728 bytes), with a type of prealloc and an offset of 8192
bytes. So our leaf now has the following layout:
leaf 38895616 gen 24544 total ptrs 31 free space 13664 owner 5
(...)
item 27 key (280 108 200704) itemoff 14598 itemsize 53
extent data disk bytenr 0 nr 0 type 1
extent data offset 0 nr 8192 ram 94208
item 28 key (280 108 208896) itemoff 14545 itemsize 53
extent data disk bytenr 10433142784 nr 86016 type 1
extent data offset 0 nr 86016 ram 86016
item 29 key (280 108 294912) itemoff 14492 itemsize 53
extent data disk bytenr 10433052672 nr 81920 type 1
extent data offset 0 nr 8192 ram 81920
item 30 key (280 108 303104) itemoff 14439 itemsize 53
extent data disk bytenr 10433052672 nr 81920 type 2
extent data offset 8192 nr 73728 ram 81920
9) After btrfs_next_leaf() returns, we have our path pointing to that same
leaf and at slot 30, since it has a key we didn't have before and it's
the first key greater then the key that was previously the last key of
the leaf (key (280 108 294912));
10) The extent item at slot 30 covers the range from 303104 to 376831
which is in our target range, so we process it, despite having already
created an ordered extent against this extent for the file range from
348160 to 376831. This is because we skip to the next extent item only
if its end is less than or equals to the start of our delalloc range,
and not less than or equals to the current offset ('cur_offset');
11) As a result we compute 'num_bytes' as:
num_bytes = min(end + 1, extent_end) - cur_offset;
= min(438271 + 1, 376832) - 376832 = 0
12) We then call create_io_em() for a 0 bytes range starting at offset
376832;
13) Then create_io_em() enters an infinite loop because its calls to
btrfs_drop_extent_cache() do nothing due to the 0 length range
passed to it. So no existing extent maps that cover the offset
376832 get removed, and therefore calls to add_extent_mapping()
return -EEXIST, resulting in an infinite loop. This loop from
create_io_em() is the following:
do {
btrfs_drop_extent_cache(BTRFS_I(inode), em->start,
em->start + em->len - 1, 0);
write_lock(&em_tree->lock);
ret = add_extent_mapping(em_tree, em, 1);
write_unlock(&em_tree->lock);
/*
* The caller has taken lock_extent(), who could race with us
* to add em?
*/
} while (ret == -EEXIST);
Also, each call to btrfs_drop_extent_cache() triggers a warning because
the start offset passed to it (376832) is smaller then the end offset
(376832 - 1) passed to it by -1, due to the 0 length:
[258532.052621] ------------[ cut here ]------------
[258532.052643] WARNING: CPU: 0 PID: 9987 at fs/btrfs/file.c:602 btrfs_drop_extent_cache+0x3f4/0x590 [btrfs]
(...)
[258532.052672] CPU: 0 PID: 9987 Comm: fsx Tainted: G W 5.4.0-rc7-btrfs-next-64 #1
[258532.052673] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.12.0-0-ga698c8995f-prebuilt.qemu.org 04/01/2014
[258532.052691] RIP: 0010:btrfs_drop_extent_cache+0x3f4/0x590 [btrfs]
(...)
[258532.052695] RSP: 0018:ffffb4be0153f860 EFLAGS: 00010287
[258532.052700] RAX: ffff975b445ee360 RBX: ffff975b44eb3e08 RCX: 0000000000000000
[258532.052700] RDX: 0000000000038fff RSI: 0000000000039000 RDI: ffff975b445ee308
[258532.052700] RBP: 0000000000038fff R08: 0000000000000000 R09: 0000000000000001
[258532.052701] R10: ffff975b513c5c10 R11: 00000000e3c0cfa9 R12: 0000000000039000
[258532.052703] R13: ffff975b445ee360 R14: 00000000ffffffef R15: ffff975b445ee308
[258532.052705] FS: 00007f86a821de80(0000) GS:ffff975b76a00000(0000) knlGS:0000000000000000
[258532.052707] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[258532.052708] CR2: 00007fdacf0f3ab4 CR3: 00000001f9d26002 CR4: 00000000003606f0
[258532.052712] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
[258532.052717] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
[258532.052717] Call Trace:
[258532.052718] ? preempt_schedule_common+0x32/0x70
[258532.052722] ? ___preempt_schedule+0x16/0x20
[258532.052741] create_io_em+0xff/0x180 [btrfs]
[258532.052767] run_delalloc_nocow+0x942/0xb10 [btrfs]
[258532.052791] btrfs_run_delalloc_range+0x30b/0x520 [btrfs]
[258532.052812] ? find_lock_delalloc_range+0x221/0x250 [btrfs]
[258532.052834] writepage_delalloc+0xe4/0x140 [btrfs]
[258532.052855] __extent_writepage+0x110/0x4e0 [btrfs]
[258532.052876] extent_write_cache_pages+0x21c/0x480 [btrfs]
[258532.052906] extent_writepages+0x52/0xb0 [btrfs]
[258532.052911] do_writepages+0x23/0x80
[258532.052915] __filemap_fdatawrite_range+0xd2/0x110
[258532.052938] btrfs_fdatawrite_range+0x1b/0x50 [btrfs]
[258532.052954] start_ordered_ops+0x57/0xa0 [btrfs]
[258532.052973] ? btrfs_sync_file+0x225/0x490 [btrfs]
[258532.052988] btrfs_sync_file+0x225/0x490 [btrfs]
[258532.052997] __x64_sys_msync+0x199/0x200
[258532.053004] do_syscall_64+0x5c/0x250
[258532.053007] entry_SYSCALL_64_after_hwframe+0x49/0xbe
[258532.053010] RIP: 0033:0x7f86a7dfd760
(...)
[258532.053014] RSP: 002b:00007ffd99af0368 EFLAGS: 00000246 ORIG_RAX: 000000000000001a
[258532.053016] RAX: ffffffffffffffda RBX: 0000000000000ec9 RCX: 00007f86a7dfd760
[258532.053017] RDX: 0000000000000004 RSI: 000000000000836c RDI: 00007f86a8221000
[258532.053019] RBP: 0000000000021ec9 R08: 0000000000000003 R09: 00007f86a812037c
[258532.053020] R10: 0000000000000001 R11: 0000000000000246 R12: 00000000000074a3
[258532.053021] R13: 00007f86a8221000 R14: 000000000000836c R15: 0000000000000001
[258532.053032] irq event stamp: 1653450494
[258532.053035] hardirqs last enabled at (1653450493): [<ffffffff9dec69f9>] _raw_spin_unlock_irq+0x29/0x50
[258532.053037] hardirqs last disabled at (1653450494): [<ffffffff9d4048ea>] trace_hardirqs_off_thunk+0x1a/0x20
[258532.053039] softirqs last enabled at (1653449852): [<ffffffff9e200466>] __do_softirq+0x466/0x6bd
[258532.053042] softirqs last disabled at (1653449845): [<ffffffff9d4c8a0c>] irq_exit+0xec/0x120
[258532.053043] ---[ end trace 8476fce13d9ce20a ]---
Which results in flooding dmesg/syslog since btrfs_drop_extent_cache()
uses WARN_ON() and not WARN_ON_ONCE().
So fix this issue by changing run_delalloc_nocow()'s loop to move to the
next extent item when the current extent item ends at at offset less than
or equals to the current offset instead of the start offset.
Fixes: 80ff385665b7fc ("Btrfs: update nodatacow code v2")
Reviewed-by: Josef Bacik <[email protected]>
Signed-off-by: Filipe Manana <[email protected]>
Signed-off-by: David Sterba <[email protected]>
[bwh: Backported to 3.16: adjust context]
Signed-off-by: Ben Hutchings <[email protected]>
---
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -1283,7 +1283,11 @@ next_slot:
btrfs_file_extent_num_bytes(leaf, fi);
disk_num_bytes =
btrfs_file_extent_disk_num_bytes(leaf, fi);
- if (extent_end <= start) {
+ /*
+ * If the extent we got ends before our current offset,
+ * skip to the next extent.
+ */
+ if (extent_end <= cur_offset) {
path->slots[0]++;
goto next_slot;
}
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Kaitao Cheng <[email protected]>
commit 50f9ad607ea891a9308e67b81f774c71736d1098 upstream.
In the function, if register_trace_sched_migrate_task() returns error,
sched_switch/sched_wakeup_new/sched_wakeup won't unregister. That is
why fail_deprobe_sched_switch was added.
Link: http://lkml.kernel.org/r/[email protected]
Fixes: 478142c39c8c2 ("tracing: do not grab lock in wakeup latency function tracing")
Signed-off-by: Kaitao Cheng <[email protected]>
Signed-off-by: Steven Rostedt (VMware) <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
kernel/trace/trace_sched_wakeup.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
--- a/kernel/trace/trace_sched_wakeup.c
+++ b/kernel/trace/trace_sched_wakeup.c
@@ -567,7 +567,7 @@ static void start_wakeup_tracer(struct t
if (ret) {
pr_info("wakeup trace: Couldn't activate tracepoint"
" probe to kernel_sched_migrate_task\n");
- return;
+ goto fail_deprobe_sched_switch;
}
wakeup_reset(tr);
@@ -585,6 +585,8 @@ static void start_wakeup_tracer(struct t
printk(KERN_ERR "failed to start wakeup tracer\n");
return;
+fail_deprobe_sched_switch:
+ unregister_trace_sched_switch(probe_wakeup_sched_switch, NULL);
fail_deprobe_wake_new:
unregister_trace_sched_wakeup_new(probe_wakeup, NULL);
fail_deprobe:
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Paolo Bonzini <[email protected]>
commit 07721feee46b4b248402133228235318199b05ec upstream.
vmx_check_intercept is not yet fully implemented. To avoid emulating
instructions disallowed by the L1 hypervisor, refuse to emulate
instructions by default.
[Made commit, added commit msg - Oliver]
Signed-off-by: Oliver Upton <[email protected]>
Signed-off-by: Paolo Bonzini <[email protected]>
[bwh: Backported to 3.16: adjust filename, context]
Signed-off-by: Ben Hutchings <[email protected]>
---
arch/x86/kvm/vmx.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -8938,7 +8938,7 @@ static int vmx_check_intercept(struct kv
struct x86_instruction_info *info,
enum x86_intercept_stage stage)
{
- return X86EMUL_CONTINUE;
+ return X86EMUL_UNHANDLEABLE;
}
static struct kvm_x86_ops vmx_x86_ops = {
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Jiri Slaby <[email protected]>
commit 07e6124a1a46b4b5a9b3cacc0c306b50da87abf5 upstream.
syzkaller reported this UAF:
BUG: KASAN: use-after-free in n_tty_receive_buf_common+0x2481/0x2940 drivers/tty/n_tty.c:1741
Read of size 1 at addr ffff8880089e40e9 by task syz-executor.1/13184
CPU: 0 PID: 13184 Comm: syz-executor.1 Not tainted 5.4.7 #1
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.12.0-1 04/01/2014
Call Trace:
...
kasan_report+0xe/0x20 mm/kasan/common.c:634
n_tty_receive_buf_common+0x2481/0x2940 drivers/tty/n_tty.c:1741
tty_ldisc_receive_buf+0xac/0x190 drivers/tty/tty_buffer.c:461
paste_selection+0x297/0x400 drivers/tty/vt/selection.c:372
tioclinux+0x20d/0x4e0 drivers/tty/vt/vt.c:3044
vt_ioctl+0x1bcf/0x28d0 drivers/tty/vt/vt_ioctl.c:364
tty_ioctl+0x525/0x15a0 drivers/tty/tty_io.c:2657
vfs_ioctl fs/ioctl.c:47 [inline]
It is due to a race between parallel paste_selection (TIOCL_PASTESEL)
and set_selection_user (TIOCL_SETSEL) invocations. One uses sel_buffer,
while the other frees it and reallocates a new one for another
selection. Add a mutex to close this race.
The mutex takes care properly of sel_buffer and sel_buffer_lth only. The
other selection global variables (like sel_start, sel_end, and sel_cons)
are protected only in set_selection_user. The other functions need quite
some more work to close the races of the variables there. This is going
to happen later.
This likely fixes (I am unsure as there is no reproducer provided) bug
206361 too. It was marked as CVE-2020-8648.
Signed-off-by: Jiri Slaby <[email protected]>
Reported-by: [email protected]
References: https://bugzilla.kernel.org/show_bug.cgi?id=206361
Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Greg Kroah-Hartman <[email protected]>
[bwh: Backported to 3.16: adjust context]
Signed-off-by: Ben Hutchings <[email protected]>
---
drivers/tty/vt/selection.c | 23 +++++++++++++++++------
1 file changed, 17 insertions(+), 6 deletions(-)
--- a/drivers/tty/vt/selection.c
+++ b/drivers/tty/vt/selection.c
@@ -13,6 +13,7 @@
#include <linux/tty.h>
#include <linux/sched.h>
#include <linux/mm.h>
+#include <linux/mutex.h>
#include <linux/slab.h>
#include <linux/types.h>
@@ -40,6 +41,7 @@ static volatile int sel_start = -1; /*
static int sel_end;
static int sel_buffer_lth;
static char *sel_buffer;
+static DEFINE_MUTEX(sel_lock);
/* clear_selection, highlight and highlight_pointer can be called
from interrupt (via scrollback/front) */
@@ -163,7 +165,7 @@ int set_selection(const struct tiocl_sel
char *bp, *obp;
int i, ps, pe, multiplier;
u16 c;
- int mode;
+ int mode, ret = 0;
poke_blanked_console();
@@ -203,6 +205,7 @@ int set_selection(const struct tiocl_sel
pe = tmp;
}
+ mutex_lock(&sel_lock);
if (sel_cons != vc_cons[fg_console].d) {
clear_selection();
sel_cons = vc_cons[fg_console].d;
@@ -248,9 +251,10 @@ int set_selection(const struct tiocl_sel
break;
case TIOCL_SELPOINTER:
highlight_pointer(pe);
- return 0;
+ goto unlock;
default:
- return -EINVAL;
+ ret = -EINVAL;
+ goto unlock;
}
/* remove the pointer */
@@ -272,7 +276,7 @@ int set_selection(const struct tiocl_sel
else if (new_sel_start == sel_start)
{
if (new_sel_end == sel_end) /* no action required */
- return 0;
+ goto unlock;
else if (new_sel_end > sel_end) /* extend to right */
highlight(sel_end + 2, new_sel_end);
else /* contract from right */
@@ -299,7 +303,8 @@ int set_selection(const struct tiocl_sel
if (!bp) {
printk(KERN_WARNING "selection: kmalloc() failed\n");
clear_selection();
- return -ENOMEM;
+ ret = -ENOMEM;
+ goto unlock;
}
kfree(sel_buffer);
sel_buffer = bp;
@@ -324,7 +329,9 @@ int set_selection(const struct tiocl_sel
}
}
sel_buffer_lth = bp - sel_buffer;
- return 0;
+unlock:
+ mutex_unlock(&sel_lock);
+ return ret;
}
/* Insert the contents of the selection buffer into the
@@ -351,6 +358,7 @@ int paste_selection(struct tty_struct *t
tty_buffer_lock_exclusive(&vc->port);
add_wait_queue(&vc->paste_wait, &wait);
+ mutex_lock(&sel_lock);
while (sel_buffer && sel_buffer_lth > pasted) {
set_current_state(TASK_INTERRUPTIBLE);
if (signal_pending(current)) {
@@ -358,7 +366,9 @@ int paste_selection(struct tty_struct *t
break;
}
if (test_bit(TTY_THROTTLED, &tty->flags)) {
+ mutex_unlock(&sel_lock);
schedule();
+ mutex_lock(&sel_lock);
continue;
}
__set_current_state(TASK_RUNNING);
@@ -367,6 +377,7 @@ int paste_selection(struct tty_struct *t
count);
pasted += count;
}
+ mutex_unlock(&sel_lock);
remove_wait_queue(&vc->paste_wait, &wait);
__set_current_state(TASK_RUNNING);
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Ard Biesheuvel <[email protected]>
commit 4911ee401b7ceff8f38e0ac597cbf503d71e690c upstream.
The EFI mixed mode entry code goes through the ordinary startup_32()
routine before jumping into the kernel's EFI boot code in 64-bit
mode. The 32-bit startup code must be entered with paging disabled,
but this is not documented as a requirement for the EFI handover
protocol, and so we should disable paging explicitly when entering
the kernel from 32-bit EFI firmware.
Signed-off-by: Ard Biesheuvel <[email protected]>
Cc: Arvind Sankar <[email protected]>
Cc: Hans de Goede <[email protected]>
Cc: Linus Torvalds <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Thomas Gleixner <[email protected]>
Cc: [email protected]
Link: https://lkml.kernel.org/r/[email protected]
Signed-off-by: Ingo Molnar <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
arch/x86/boot/compressed/head_64.S | 5 +++++
1 file changed, 5 insertions(+)
--- a/arch/x86/boot/compressed/head_64.S
+++ b/arch/x86/boot/compressed/head_64.S
@@ -216,6 +216,11 @@ ENTRY(efi32_stub_entry)
leal efi32_config(%ebp), %eax
movl %eax, efi_config(%ebp)
+ /* Disable paging */
+ movl %cr0, %eax
+ btrl $X86_CR0_PG_BIT, %eax
+ movl %eax, %cr0
+
jmp startup_32
ENDPROC(efi32_stub_entry)
#endif
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Florian Faber <[email protected]>
commit 2d77bd61a2927be8f4e00d9478fe6996c47e8d45 upstream.
Under load, the RX side of the mscan driver can get stuck while TX still
works. Restarting the interface locks up the system. This behaviour
could be reproduced reliably on a MPC5121e based system.
The patch fixes the return value of the NAPI polling function (should be
the number of processed packets, not constant 1) and the condition under
which IRQs are enabled again after polling is finished.
With this patch, no more lockups were observed over a test period of ten
days.
Fixes: afa17a500a36 ("net/can: add driver for mscan family & mpc52xx_mscan")
Signed-off-by: Florian Faber <[email protected]>
Signed-off-by: Marc Kleine-Budde <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
drivers/net/can/mscan/mscan.c | 21 ++++++++++-----------
1 file changed, 10 insertions(+), 11 deletions(-)
--- a/drivers/net/can/mscan/mscan.c
+++ b/drivers/net/can/mscan/mscan.c
@@ -412,13 +412,12 @@ static int mscan_rx_poll(struct napi_str
struct net_device *dev = napi->dev;
struct mscan_regs __iomem *regs = priv->reg_base;
struct net_device_stats *stats = &dev->stats;
- int npackets = 0;
- int ret = 1;
+ int work_done = 0;
struct sk_buff *skb;
struct can_frame *frame;
u8 canrflg;
- while (npackets < quota) {
+ while (work_done < quota) {
canrflg = in_8(®s->canrflg);
if (!(canrflg & (MSCAN_RXF | MSCAN_ERR_IF)))
break;
@@ -439,18 +438,18 @@ static int mscan_rx_poll(struct napi_str
stats->rx_packets++;
stats->rx_bytes += frame->can_dlc;
- npackets++;
+ work_done++;
netif_receive_skb(skb);
}
- if (!(in_8(®s->canrflg) & (MSCAN_RXF | MSCAN_ERR_IF))) {
- napi_complete(&priv->napi);
- clear_bit(F_RX_PROGRESS, &priv->flags);
- if (priv->can.state < CAN_STATE_BUS_OFF)
- out_8(®s->canrier, priv->shadow_canrier);
- ret = 0;
+ if (work_done < quota) {
+ if (likely(napi_complete_done(&priv->napi, work_done))) {
+ clear_bit(F_RX_PROGRESS, &priv->flags);
+ if (priv->can.state < CAN_STATE_BUS_OFF)
+ out_8(®s->canrier, priv->shadow_canrier);
+ }
}
- return ret;
+ return work_done;
}
static irqreturn_t mscan_isr(int irq, void *dev_id)
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Alex Sverdlin <[email protected]>
commit 927d780ee371d7e121cea4fc7812f6ef2cea461c upstream.
Scenario 1, ARMv7
=================
If code in arch/arm/kernel/ftrace.c would operate on mcount() pointer
the following may be generated:
00000230 <prealloc_fixed_plts>:
230: b5f8 push {r3, r4, r5, r6, r7, lr}
232: b500 push {lr}
234: f7ff fffe bl 0 <__gnu_mcount_nc>
234: R_ARM_THM_CALL __gnu_mcount_nc
238: f240 0600 movw r6, #0
238: R_ARM_THM_MOVW_ABS_NC __gnu_mcount_nc
23c: f8d0 1180 ldr.w r1, [r0, #384] ; 0x180
FTRACE currently is not able to deal with it:
WARNING: CPU: 0 PID: 0 at .../kernel/trace/ftrace.c:1979 ftrace_bug+0x1ad/0x230()
...
CPU: 0 PID: 0 Comm: swapper/0 Not tainted 4.4.116-... #1
...
[<c0314e3d>] (unwind_backtrace) from [<c03115e9>] (show_stack+0x11/0x14)
[<c03115e9>] (show_stack) from [<c051a7f1>] (dump_stack+0x81/0xa8)
[<c051a7f1>] (dump_stack) from [<c0321c5d>] (warn_slowpath_common+0x69/0x90)
[<c0321c5d>] (warn_slowpath_common) from [<c0321cf3>] (warn_slowpath_null+0x17/0x1c)
[<c0321cf3>] (warn_slowpath_null) from [<c038ee9d>] (ftrace_bug+0x1ad/0x230)
[<c038ee9d>] (ftrace_bug) from [<c038f1f9>] (ftrace_process_locs+0x27d/0x444)
[<c038f1f9>] (ftrace_process_locs) from [<c08915bd>] (ftrace_init+0x91/0xe8)
[<c08915bd>] (ftrace_init) from [<c0885a67>] (start_kernel+0x34b/0x358)
[<c0885a67>] (start_kernel) from [<00308095>] (0x308095)
---[ end trace cb88537fdc8fa200 ]---
ftrace failed to modify [<c031266c>] prealloc_fixed_plts+0x8/0x60
actual: 44:f2:e1:36
ftrace record flags: 0
(0) expected tramp: c03143e9
Scenario 2, ARMv4T
==================
ftrace: allocating 14435 entries in 43 pages
------------[ cut here ]------------
WARNING: CPU: 0 PID: 0 at kernel/trace/ftrace.c:2029 ftrace_bug+0x204/0x310
CPU: 0 PID: 0 Comm: swapper Not tainted 4.19.5 #1
Hardware name: Cirrus Logic EDB9302 Evaluation Board
[<c0010a24>] (unwind_backtrace) from [<c000ecb0>] (show_stack+0x20/0x2c)
[<c000ecb0>] (show_stack) from [<c03c72e8>] (dump_stack+0x20/0x30)
[<c03c72e8>] (dump_stack) from [<c0021c18>] (__warn+0xdc/0x104)
[<c0021c18>] (__warn) from [<c0021d7c>] (warn_slowpath_null+0x4c/0x5c)
[<c0021d7c>] (warn_slowpath_null) from [<c0095360>] (ftrace_bug+0x204/0x310)
[<c0095360>] (ftrace_bug) from [<c04dabac>] (ftrace_init+0x3b4/0x4d4)
[<c04dabac>] (ftrace_init) from [<c04cef4c>] (start_kernel+0x20c/0x410)
[<c04cef4c>] (start_kernel) from [<00000000>] ( (null))
---[ end trace 0506a2f5dae6b341 ]---
ftrace failed to modify
[<c000c350>] perf_trace_sys_exit+0x5c/0xe8
actual: 1e:ff:2f:e1
Initializing ftrace call sites
ftrace record flags: 0
(0)
expected tramp: c000fb24
The analysis for this problem has been already performed previously,
refer to the link below.
Fix the above problems by allowing only selected reloc types in
__mcount_loc. The list itself comes from the legacy recordmcount.pl
script.
Link: https://lore.kernel.org/lkml/[email protected]/
Fixes: ed60453fa8f8 ("ARM: 6511/1: ftrace: add ARM support for C version of recordmcount")
Signed-off-by: Alexander Sverdlin <[email protected]>
Acked-by: Steven Rostedt (VMware) <[email protected]>
Signed-off-by: Russell King <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
scripts/recordmcount.c | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
--- a/scripts/recordmcount.c
+++ b/scripts/recordmcount.c
@@ -52,6 +52,10 @@
#define R_AARCH64_ABS64 257
#endif
+#define R_ARM_PC24 1
+#define R_ARM_THM_CALL 10
+#define R_ARM_CALL 28
+
static int fd_map; /* File descriptor for file being modified. */
static int mmap_failed; /* Boolean flag. */
static char gpfx; /* prefix for global symbol name (sometimes '_') */
@@ -355,6 +359,18 @@ is_mcounted_section_name(char const *con
#define RECORD_MCOUNT_64
#include "recordmcount.h"
+static int arm_is_fake_mcount(Elf32_Rel const *rp)
+{
+ switch (ELF32_R_TYPE(w(rp->r_info))) {
+ case R_ARM_THM_CALL:
+ case R_ARM_CALL:
+ case R_ARM_PC24:
+ return 0;
+ }
+
+ return 1;
+}
+
/* 64-bit EM_MIPS has weird ELF64_Rela.r_info.
* http://techpubs.sgi.com/library/manuals/4000/007-4658-001/pdf/007-4658-001.pdf
* We interpret Table 29 Relocation Operation (Elf64_Rel, Elf64_Rela) [p.40]
@@ -443,6 +459,7 @@ do_file(char const *const fname)
break;
case EM_ARM: reltype = R_ARM_ABS32;
altmcount = "__gnu_mcount_nc";
+ is_fake_mcount32 = arm_is_fake_mcount;
break;
case EM_AARCH64:
reltype = R_AARCH64_ABS64; gpfx = '_'; break;
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Johan Hovold <[email protected]>
commit 5d1b71226dc4d44b4b65766fa9d74492f9d4587b upstream.
The altsetting sanity check in set_sync_ep_implicit_fb_quirk() was
checking for there to be at least one altsetting but then went on to
access the second one, which may not exist.
This could lead to random slab data being used to initialise the sync
endpoint in snd_usb_add_endpoint().
Fixes: c75a8a7ae565 ("ALSA: snd-usb: add support for implicit feedback")
Fixes: ca10a7ebdff1 ("ALSA: usb-audio: FT C400 sync playback EP to capture EP")
Fixes: 5e35dc0338d8 ("ALSA: usb-audio: add implicit fb quirk for Behringer UFX1204")
Fixes: 17f08b0d9aaf ("ALSA: usb-audio: add implicit fb quirk for Axe-Fx II")
Fixes: 103e9625647a ("ALSA: usb-audio: simplify set_sync_ep_implicit_fb_quirk")
Signed-off-by: Johan Hovold <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Takashi Iwai <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
sound/usb/pcm.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/sound/usb/pcm.c
+++ b/sound/usb/pcm.c
@@ -368,7 +368,7 @@ static int set_sync_ep_implicit_fb_quirk
add_sync_ep_from_ifnum:
iface = usb_ifnum_to_if(dev, ifnum);
- if (!iface || iface->num_altsetting == 0)
+ if (!iface || iface->num_altsetting < 2)
return -EINVAL;
alts = &iface->altsetting[1];
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Lukas Czerner <[email protected]>
commit 0d306dcf86e8f065dff42a4a934ae9d99af35ba5 upstream.
Currently existing dio workers can jump in and potentially increase
extent tree depth while we're allocating blocks in
ext4_alloc_file_blocks(). This may cause us to underestimate the
number of credits needed for the transaction because the extent tree
depth can change after our estimation.
Fix this by waiting for all the existing dio workers in the same way
as we do it in ext4_punch_hole. We've seen errors caused by this in
xfstest generic/299, however it's really hard to reproduce.
Signed-off-by: Lukas Czerner <[email protected]>
Signed-off-by: Theodore Ts'o <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
fs/ext4/extents.c | 6 ++++++
1 file changed, 6 insertions(+)
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -4707,6 +4707,10 @@ static int ext4_alloc_file_blocks(struct
if (len <= EXT_UNWRITTEN_MAX_LEN)
flags |= EXT4_GET_BLOCKS_NO_NORMALIZE;
+ /* Wait all existing dio workers, newcomers will block on i_mutex */
+ ext4_inode_block_unlocked_dio(inode);
+ inode_dio_wait(inode);
+
/*
* credits to insert 1 extent into extent tree
*/
@@ -4756,6 +4760,8 @@ retry:
goto retry;
}
+ ext4_inode_resume_unlocked_dio(inode);
+
return ret > 0 ? ret2 : ret;
}
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Richard Palethorpe <[email protected]>
commit b9258a2cece4ec1f020715fe3554bc2e360f6264 upstream.
struct can_frame contains some padding which is not explicitly zeroed in
slc_bump. This uninitialized data will then be transmitted if the stack
initialization hardening feature is not enabled (CONFIG_INIT_STACK_ALL).
This commit just zeroes the whole struct including the padding.
Signed-off-by: Richard Palethorpe <[email protected]>
Fixes: a1044e36e457 ("can: add slcan driver for serial/USB-serial CAN adapters")
Reviewed-by: Kees Cook <[email protected]>
Cc: [email protected]
Cc: [email protected]
Cc: [email protected]
Cc: [email protected]
Cc: [email protected]
Cc: [email protected]
Acked-by: Marc Kleine-Budde <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
drivers/net/can/slcan.c | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
--- a/drivers/net/can/slcan.c
+++ b/drivers/net/can/slcan.c
@@ -150,7 +150,7 @@ static void slc_bump(struct slcan *sl)
u32 tmpid;
char *cmd = sl->rbuff;
- cf.can_id = 0;
+ memset(&cf, 0, sizeof(cf));
switch (*cmd) {
case 'r':
@@ -189,8 +189,6 @@ static void slc_bump(struct slcan *sl)
else
return;
- *(u64 *) (&cf.data) = 0; /* clear payload */
-
/* RTR frames may have a dlc > 0 but they never have any data bytes */
if (!(cf.can_id & CAN_RTR_FLAG)) {
for (i = 0; i < cf.can_dlc; i++) {
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Takashi Iwai <[email protected]>
commit 0aec96f5897ac16ad9945f531b4bef9a2edd2ebd upstream.
Jia-Ju Bai reported a possible sleep-in-atomic scenario in the ice1724
driver with Infrasonic Quartet support code: namely, ice->set_rate
callback gets called inside ice->reg_lock spinlock, while the callback
in quartet.c holds ice->gpio_mutex.
This patch fixes the invalid call: it simply moves the calls of
ice->set_rate and ice->set_mclk callbacks outside the spinlock.
Reported-by: Jia-Ju Bai <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Takashi Iwai <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
sound/pci/ice1712/ice1724.c | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
--- a/sound/pci/ice1712/ice1724.c
+++ b/sound/pci/ice1712/ice1724.c
@@ -663,6 +663,7 @@ static int snd_vt1724_set_pro_rate(struc
unsigned long flags;
unsigned char mclk_change;
unsigned int i, old_rate;
+ bool call_set_rate = false;
if (rate > ice->hw_rates->list[ice->hw_rates->count - 1])
return -EINVAL;
@@ -686,7 +687,7 @@ static int snd_vt1724_set_pro_rate(struc
* setting clock rate for internal clock mode */
old_rate = ice->get_rate(ice);
if (force || (old_rate != rate))
- ice->set_rate(ice, rate);
+ call_set_rate = true;
else if (rate == ice->cur_rate) {
spin_unlock_irqrestore(&ice->reg_lock, flags);
return 0;
@@ -694,12 +695,14 @@ static int snd_vt1724_set_pro_rate(struc
}
ice->cur_rate = rate;
+ spin_unlock_irqrestore(&ice->reg_lock, flags);
+
+ if (call_set_rate)
+ ice->set_rate(ice, rate);
/* setting master clock */
mclk_change = ice->set_mclk(ice, rate);
- spin_unlock_irqrestore(&ice->reg_lock, flags);
-
if (mclk_change && ice->gpio.i2s_mclk_changed)
ice->gpio.i2s_mclk_changed(ice);
if (ice->gpio.set_pro_rate)
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Cengiz Can <[email protected]>
commit 153031a301bb07194e9c37466cfce8eacb977621 upstream.
There was a recent change in blktrace.c that added a RCU protection to
`q->blk_trace` in order to fix a use-after-free issue during access.
However the change missed an edge case that can lead to dereferencing of
`bt` pointer even when it's NULL:
Coverity static analyzer marked this as a FORWARD_NULL issue with CID
1460458.
```
/kernel/trace/blktrace.c: 1904 in sysfs_blk_trace_attr_store()
1898 ret = 0;
1899 if (bt == NULL)
1900 ret = blk_trace_setup_queue(q, bdev);
1901
1902 if (ret == 0) {
1903 if (attr == &dev_attr_act_mask)
>>> CID 1460458: Null pointer dereferences (FORWARD_NULL)
>>> Dereferencing null pointer "bt".
1904 bt->act_mask = value;
1905 else if (attr == &dev_attr_pid)
1906 bt->pid = value;
1907 else if (attr == &dev_attr_start_lba)
1908 bt->start_lba = value;
1909 else if (attr == &dev_attr_end_lba)
```
Added a reassignment with RCU annotation to fix the issue.
Fixes: c780e86dd48 ("blktrace: Protect q->blk_trace with RCU")
Reviewed-by: Ming Lei <[email protected]>
Reviewed-by: Bob Liu <[email protected]>
Reviewed-by: Steven Rostedt (VMware) <[email protected]>
Signed-off-by: Cengiz Can <[email protected]>
Signed-off-by: Jens Axboe <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
kernel/trace/blktrace.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
--- a/kernel/trace/blktrace.c
+++ b/kernel/trace/blktrace.c
@@ -1834,8 +1834,11 @@ static ssize_t sysfs_blk_trace_attr_stor
}
ret = 0;
- if (bt == NULL)
+ if (bt == NULL) {
ret = blk_trace_setup_queue(q, bdev);
+ bt = rcu_dereference_protected(q->blk_trace,
+ lockdep_is_held(&q->blk_trace_mutex));
+ }
if (ret == 0) {
if (attr == &dev_attr_act_mask)
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Sudip Mukherjee <[email protected]>
commit fb2b90014d782d80d7ebf663e50f96d8c507a73c upstream.
There seems to be a race condition in tty drivers and I could see on
many boot cycles a NULL pointer dereference as tty_init_dev() tries to
do 'tty->port->itty = tty' even though tty->port is NULL.
'tty->port' will be set by the driver and if the driver has not yet done
it before we open the tty device we can get to this situation. By adding
some extra debug prints, I noticed that:
6.650130: uart_add_one_port
6.663849: register_console
6.664846: tty_open
6.674391: tty_init_dev
6.675456: tty_port_link_device
uart_add_one_port() registers the console, as soon as it registers, the
userspace tries to use it and that leads to tty_open() but
uart_add_one_port() has not yet done tty_port_link_device() and so
tty->port is not yet configured when control reaches tty_init_dev().
Further look into the code and tty_port_link_device() is done by
uart_add_one_port(). After registering the console uart_add_one_port()
will call tty_port_register_device_attr_serdev() and
tty_port_link_device() is called from this.
Call add tty_port_link_device() before uart_configure_port() is done and
add a check in tty_port_link_device() so that it only links the port if
it has not been done yet.
Suggested-by: Jiri Slaby <[email protected]>
Signed-off-by: Sudip Mukherjee <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Greg Kroah-Hartman <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
drivers/tty/serial/serial_core.c | 1 +
drivers/tty/tty_port.c | 3 ++-
2 files changed, 3 insertions(+), 1 deletion(-)
--- a/drivers/tty/serial/serial_core.c
+++ b/drivers/tty/serial/serial_core.c
@@ -2639,6 +2639,7 @@ int uart_add_one_port(struct uart_driver
lockdep_set_class(&uport->lock, &port_lock_key);
}
+ tty_port_link_device(port, drv->tty_driver, uport->line);
uart_configure_port(drv, state, uport);
/*
--- a/drivers/tty/tty_port.c
+++ b/drivers/tty/tty_port.c
@@ -49,7 +49,8 @@ void tty_port_link_device(struct tty_por
{
if (WARN_ON(index >= driver->num))
return;
- driver->ports[index] = port;
+ if (!driver->ports[index])
+ driver->ports[index] = port;
}
EXPORT_SYMBOL_GPL(tty_port_link_device);
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Jan Kara <[email protected]>
commit 109ba779d6cca2d519c5dd624a3276d03e21948e upstream.
ext4_check_dir_entry() currently does not catch a case when a directory
entry ends so close to the block end that the header of the next
directory entry would not fit in the remaining space. This can lead to
directory iteration code trying to access address beyond end of current
buffer head leading to oops.
Signed-off-by: Jan Kara <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Theodore Ts'o <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
fs/ext4/dir.c | 5 +++++
1 file changed, 5 insertions(+)
--- a/fs/ext4/dir.c
+++ b/fs/ext4/dir.c
@@ -78,6 +78,11 @@ int __ext4_check_dir_entry(const char *f
error_msg = "rec_len is too small for name_len";
else if (unlikely(((char *) de - buf) + rlen > size))
error_msg = "directory entry overrun";
+ else if (unlikely(((char *) de - buf) + rlen >
+ size - EXT4_DIR_REC_LEN(1) &&
+ ((char *) de - buf) + rlen != size)) {
+ error_msg = "directory entry too close to block end";
+ }
else if (unlikely(le32_to_cpu(de->inode) >
le32_to_cpu(EXT4_SB(dir->i_sb)->s_es->s_inodes_count)))
error_msg = "inode out of bounds";
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Parav Pandit <[email protected]>
commit 89f988d93c62384758b19323c886db917a80c371 upstream.
Current code device add sequence is:
ib_register_device()
ib_mad_init()
init_sriov_init()
register_netdev_notifier()
Therefore, the remove sequence should be,
unregister_netdev_notifier()
close_sriov()
mad_cleanup()
ib_unregister_device()
However it is not above.
Hence, make do above remove sequence.
Fixes: fa417f7b520ee ("IB/mlx4: Add support for IBoE")
Signed-off-by: Parav Pandit <[email protected]>
Reviewed-by: Maor Gottlieb <[email protected]>
Signed-off-by: Leon Romanovsky <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Doug Ledford <[email protected]>
[bwh: Backported to 3.16: No need to call mlx4_ib_diag_cleanup()]
Signed-off-by: Ben Hutchings <[email protected]>
---
--- a/drivers/infiniband/hw/mlx4/main.c
+++ b/drivers/infiniband/hw/mlx4/main.c
@@ -2372,15 +2372,16 @@ static void mlx4_ib_remove(struct mlx4_d
ibdev->ib_active = false;
flush_workqueue(wq);
- mlx4_ib_close_sriov(ibdev);
- mlx4_ib_mad_cleanup(ibdev);
- ib_unregister_device(&ibdev->ib_dev);
if (ibdev->iboe.nb.notifier_call) {
if (unregister_netdevice_notifier(&ibdev->iboe.nb))
pr_warn("failure unregistering notifier\n");
ibdev->iboe.nb.notifier_call = NULL;
}
+ mlx4_ib_close_sriov(ibdev);
+ mlx4_ib_mad_cleanup(ibdev);
+ ib_unregister_device(&ibdev->ib_dev);
+
mlx4_qp_release_range(dev, ibdev->steer_qpn_base,
ibdev->steer_qpn_count);
kfree(ibdev->ib_uc_qpns_bitmap);
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Shuah Khan <[email protected]>
commit 6f0dd24a084a17f9984dd49dffbf7055bf123993 upstream.
Media devnode open/ioctl could be in progress when media device unregister
is initiated. System calls and ioctls check media device registered status
at the beginning, however, there is a window where unregister could be in
progress without changing the media devnode status to unregistered.
process 1 process 2
fd = open(/dev/media0)
media_devnode_is_registered()
(returns true here)
media_device_unregister()
(unregister is in progress
and devnode isn't
unregistered yet)
...
ioctl(fd, ...)
__media_ioctl()
media_devnode_is_registered()
(returns true here)
...
media_devnode_unregister()
...
(driver releases the media device
memory)
media_device_ioctl()
(By this point
devnode->media_dev does not
point to allocated memory.
use-after free in in mutex_lock_nested)
BUG: KASAN: use-after-free in mutex_lock_nested+0x79c/0x800 at addr
ffff8801ebe914f0
Fix it by clearing register bit when unregister starts to avoid the race.
process 1 process 2
fd = open(/dev/media0)
media_devnode_is_registered()
(could return true here)
media_device_unregister()
(clear the register bit,
then start unregister.)
...
ioctl(fd, ...)
__media_ioctl()
media_devnode_is_registered()
(return false here, ioctl
returns I/O error, and
will not access media
device memory)
...
media_devnode_unregister()
...
(driver releases the media device
memory)
Signed-off-by: Shuah Khan <[email protected]>
Suggested-by: Sakari Ailus <[email protected]>
Reported-by: Mauro Carvalho Chehab <[email protected]>
Tested-by: Mauro Carvalho Chehab <[email protected]>
Signed-off-by: Mauro Carvalho Chehab <[email protected]>
[bwh: Backported to 3.16: adjut filename, context]
Signed-off-by: Ben Hutchings <[email protected]>
---
--- a/drivers/media/media-device.c
+++ b/drivers/media/media-device.c
@@ -407,6 +407,7 @@ int __must_check __media_device_register
if (ret < 0) {
/* devnode free is handled in media_devnode_*() */
mdev->devnode = NULL;
+ media_devnode_unregister_prepare(devnode);
media_devnode_unregister(devnode);
return ret;
}
@@ -425,16 +426,16 @@ void media_device_unregister(struct medi
struct media_entity *entity;
struct media_entity *next;
+ /* Clear the devnode register bit to avoid races with media dev open */
+ media_devnode_unregister_prepare(mdev->devnode);
+
list_for_each_entry_safe(entity, next, &mdev->entities, list)
media_device_unregister_entity(entity);
- /* Check if mdev devnode was registered */
- if (media_devnode_is_registered(mdev->devnode)) {
- device_remove_file(&mdev->devnode->dev, &dev_attr_model);
- media_devnode_unregister(mdev->devnode);
- /* devnode free is handled in media_devnode_*() */
- mdev->devnode = NULL;
- }
+ device_remove_file(&mdev->devnode->dev, &dev_attr_model);
+ media_devnode_unregister(mdev->devnode);
+ /* devnode free is handled in media_devnode_*() */
+ mdev->devnode = NULL;
}
EXPORT_SYMBOL_GPL(media_device_unregister);
--- a/drivers/media/media-devnode.c
+++ b/drivers/media/media-devnode.c
@@ -302,6 +302,17 @@ cdev_add_error:
return ret;
}
+void media_devnode_unregister_prepare(struct media_devnode *devnode)
+{
+ /* Check if devnode was ever registered at all */
+ if (!media_devnode_is_registered(devnode))
+ return;
+
+ mutex_lock(&media_devnode_lock);
+ clear_bit(MEDIA_FLAG_REGISTERED, &devnode->flags);
+ mutex_unlock(&media_devnode_lock);
+}
+
/**
* media_devnode_unregister - unregister a media device node
* @devnode: the device node to unregister
@@ -309,17 +320,11 @@ cdev_add_error:
* This unregisters the passed device. Future open calls will be met with
* errors.
*
- * This function can safely be called if the device node has never been
- * registered or has already been unregistered.
+ * Should be called after media_devnode_unregister_prepare()
*/
void media_devnode_unregister(struct media_devnode *devnode)
{
- /* Check if devnode was ever registered at all */
- if (!media_devnode_is_registered(devnode))
- return;
-
mutex_lock(&media_devnode_lock);
- clear_bit(MEDIA_FLAG_REGISTERED, &devnode->flags);
/* Delete the cdev on this minor as well */
cdev_del(&devnode->cdev);
mutex_unlock(&media_devnode_lock);
--- a/include/media/media-devnode.h
+++ b/include/media/media-devnode.h
@@ -89,6 +89,20 @@ struct media_devnode {
int __must_check media_devnode_register(struct media_device *mdev,
struct media_devnode *devnode,
struct module *owner);
+
+/**
+ * media_devnode_unregister_prepare - clear the media device node register bit
+ * @devnode: the device node to prepare for unregister
+ *
+ * This clears the passed device register bit. Future open calls will be met
+ * with errors. Should be called before media_devnode_unregister() to avoid
+ * races with unregister and device file open calls.
+ *
+ * This function can safely be called if the device node has never been
+ * registered or has already been unregistered.
+ */
+void media_devnode_unregister_prepare(struct media_devnode *devnode);
+
void media_devnode_unregister(struct media_devnode *devnode);
static inline struct media_devnode *media_devnode_data(struct file *filp)
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Max Kellermann <[email protected]>
commit 88336e174645948da269e1812f138f727cd2896b upstream.
We should protect the device unregister patch too, at the error
condition.
Signed-off-by: Max Kellermann <[email protected]>
Signed-off-by: Mauro Carvalho Chehab <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
drivers/media/media-devnode.c | 3 +++
1 file changed, 3 insertions(+)
--- a/drivers/media/media-devnode.c
+++ b/drivers/media/media-devnode.c
@@ -282,8 +282,11 @@ int __must_check media_devnode_register(
return 0;
error:
+ mutex_lock(&media_devnode_lock);
cdev_del(&mdev->cdev);
clear_bit(mdev->minor, media_devnode_nums);
+ mutex_unlock(&media_devnode_lock);
+
return ret;
}
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Mauro Carvalho Chehab <[email protected]>
commit 8b37c6455fc8f43e0e95db2847284e618db6a4f8 upstream.
Instead of allocating a var to store 0 and just return it,
change the code to return 0 directly.
Signed-off-by: Mauro Carvalho Chehab <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
drivers/media/media-devnode.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
--- a/drivers/media/media-devnode.c
+++ b/drivers/media/media-devnode.c
@@ -192,7 +192,6 @@ static int media_open(struct inode *inod
static int media_release(struct inode *inode, struct file *filp)
{
struct media_devnode *mdev = media_devnode_data(filp);
- int ret = 0;
if (mdev->fops->release)
mdev->fops->release(filp);
@@ -201,7 +200,7 @@ static int media_release(struct inode *i
return value is ignored. */
put_device(&mdev->dev);
filp->private_data = NULL;
- return ret;
+ return 0;
}
static const struct file_operations media_devnode_fops = {
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Vladis Dronov <[email protected]>
commit a33121e5487b424339636b25c35d3a180eaa5f5e upstream.
In a case when a ptp chardev (like /dev/ptp0) is open but an underlying
device is removed, closing this file leads to a race. This reproduces
easily in a kvm virtual machine:
ts# cat openptp0.c
int main() { ... fp = fopen("/dev/ptp0", "r"); ... sleep(10); }
ts# uname -r
5.5.0-rc3-46cf053e
ts# cat /proc/cmdline
... slub_debug=FZP
ts# modprobe ptp_kvm
ts# ./openptp0 &
[1] 670
opened /dev/ptp0, sleeping 10s...
ts# rmmod ptp_kvm
ts# ls /dev/ptp*
ls: cannot access '/dev/ptp*': No such file or directory
ts# ...woken up
[ 48.010809] general protection fault: 0000 [#1] SMP
[ 48.012502] CPU: 6 PID: 658 Comm: openptp0 Not tainted 5.5.0-rc3-46cf053e #25
[ 48.014624] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), ...
[ 48.016270] RIP: 0010:module_put.part.0+0x7/0x80
[ 48.017939] RSP: 0018:ffffb3850073be00 EFLAGS: 00010202
[ 48.018339] RAX: 000000006b6b6b6b RBX: 6b6b6b6b6b6b6b6b RCX: ffff89a476c00ad0
[ 48.018936] RDX: fffff65a08d3ea08 RSI: 0000000000000247 RDI: 6b6b6b6b6b6b6b6b
[ 48.019470] ... ^^^ a slub poison
[ 48.023854] Call Trace:
[ 48.024050] __fput+0x21f/0x240
[ 48.024288] task_work_run+0x79/0x90
[ 48.024555] do_exit+0x2af/0xab0
[ 48.024799] ? vfs_write+0x16a/0x190
[ 48.025082] do_group_exit+0x35/0x90
[ 48.025387] __x64_sys_exit_group+0xf/0x10
[ 48.025737] do_syscall_64+0x3d/0x130
[ 48.026056] entry_SYSCALL_64_after_hwframe+0x44/0xa9
[ 48.026479] RIP: 0033:0x7f53b12082f6
[ 48.026792] ...
[ 48.030945] Modules linked in: ptp i6300esb watchdog [last unloaded: ptp_kvm]
[ 48.045001] Fixing recursive fault but reboot is needed!
This happens in:
static void __fput(struct file *file)
{ ...
if (file->f_op->release)
file->f_op->release(inode, file); <<< cdev is kfree'd here
if (unlikely(S_ISCHR(inode->i_mode) && inode->i_cdev != NULL &&
!(mode & FMODE_PATH))) {
cdev_put(inode->i_cdev); <<< cdev fields are accessed here
Namely:
__fput()
posix_clock_release()
kref_put(&clk->kref, delete_clock) <<< the last reference
delete_clock()
delete_ptp_clock()
kfree(ptp) <<< cdev is embedded in ptp
cdev_put
module_put(p->owner) <<< *p is kfree'd, bang!
Here cdev is embedded in posix_clock which is embedded in ptp_clock.
The race happens because ptp_clock's lifetime is controlled by two
refcounts: kref and cdev.kobj in posix_clock. This is wrong.
Make ptp_clock's sysfs device a parent of cdev with cdev_device_add()
created especially for such cases. This way the parent device with its
ptp_clock is not released until all references to the cdev are released.
This adds a requirement that an initialized but not exposed struct
device should be provided to posix_clock_register() by a caller instead
of a simple dev_t.
This approach was adopted from the commit 72139dfa2464 ("watchdog: Fix
the race between the release of watchdog_core_data and cdev"). See
details of the implementation in the commit 233ed09d7fda ("chardev: add
helper function to register char devs with a struct device").
Link: https://lore.kernel.org/linux-fsdevel/[email protected]/T/#u
Analyzed-by: Stephen Johnston <[email protected]>
Analyzed-by: Vern Lovejoy <[email protected]>
Signed-off-by: Vladis Dronov <[email protected]>
Acked-by: Richard Cochran <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
drivers/ptp/ptp_clock.c | 31 ++++++++++++++-----------------
drivers/ptp/ptp_private.h | 2 +-
include/linux/posix-clock.h | 19 +++++++++++--------
kernel/time/posix-clock.c | 31 +++++++++++++------------------
4 files changed, 39 insertions(+), 44 deletions(-)
--- a/drivers/ptp/ptp_clock.c
+++ b/drivers/ptp/ptp_clock.c
@@ -167,9 +167,9 @@ static struct posix_clock_operations ptp
.read = ptp_read,
};
-static void delete_ptp_clock(struct posix_clock *pc)
+static void ptp_clock_release(struct device *dev)
{
- struct ptp_clock *ptp = container_of(pc, struct ptp_clock, clock);
+ struct ptp_clock *ptp = container_of(dev, struct ptp_clock, dev);
mutex_destroy(&ptp->tsevq_mux);
mutex_destroy(&ptp->pincfg_mux);
@@ -201,7 +201,6 @@ struct ptp_clock *ptp_clock_register(str
}
ptp->clock.ops = ptp_clock_ops;
- ptp->clock.release = delete_ptp_clock;
ptp->info = info;
ptp->devid = MKDEV(major, index);
ptp->index = index;
@@ -214,15 +213,6 @@ struct ptp_clock *ptp_clock_register(str
if (err)
goto no_pin_groups;
- /* Create a new device in our class. */
- ptp->dev = device_create_with_groups(ptp_class, parent, ptp->devid,
- ptp, ptp->pin_attr_groups,
- "ptp%d", ptp->index);
- if (IS_ERR(ptp->dev)) {
- err = PTR_ERR(ptp->dev);
- goto no_device;
- }
-
/* Register a new PPS source. */
if (info->pps) {
struct pps_source_info pps;
@@ -238,8 +228,18 @@ struct ptp_clock *ptp_clock_register(str
}
}
- /* Create a posix clock. */
- err = posix_clock_register(&ptp->clock, ptp->devid);
+ /* Initialize a new device of our class in our clock structure. */
+ device_initialize(&ptp->dev);
+ ptp->dev.devt = ptp->devid;
+ ptp->dev.class = ptp_class;
+ ptp->dev.parent = parent;
+ ptp->dev.groups = ptp->pin_attr_groups;
+ ptp->dev.release = ptp_clock_release;
+ dev_set_drvdata(&ptp->dev, ptp);
+ dev_set_name(&ptp->dev, "ptp%d", ptp->index);
+
+ /* Create a posix clock and link it to the device. */
+ err = posix_clock_register(&ptp->clock, &ptp->dev);
if (err) {
pr_err("failed to create posix clock\n");
goto no_clock;
@@ -251,8 +251,6 @@ no_clock:
if (ptp->pps_source)
pps_unregister_source(ptp->pps_source);
no_pps:
- device_destroy(ptp_class, ptp->devid);
-no_device:
ptp_cleanup_pin_groups(ptp);
no_pin_groups:
mutex_destroy(&ptp->tsevq_mux);
@@ -273,7 +271,6 @@ int ptp_clock_unregister(struct ptp_cloc
if (ptp->pps_source)
pps_unregister_source(ptp->pps_source);
- device_destroy(ptp_class, ptp->devid);
ptp_cleanup_pin_groups(ptp);
posix_clock_unregister(&ptp->clock);
--- a/drivers/ptp/ptp_private.h
+++ b/drivers/ptp/ptp_private.h
@@ -40,7 +40,7 @@ struct timestamp_event_queue {
struct ptp_clock {
struct posix_clock clock;
- struct device *dev;
+ struct device dev;
struct ptp_clock_info *info;
dev_t devid;
int index; /* index into clocks.map */
--- a/include/linux/posix-clock.h
+++ b/include/linux/posix-clock.h
@@ -104,29 +104,32 @@ struct posix_clock_operations {
*
* @ops: Functional interface to the clock
* @cdev: Character device instance for this clock
- * @kref: Reference count.
+ * @dev: Pointer to the clock's device.
* @rwsem: Protects the 'zombie' field from concurrent access.
* @zombie: If 'zombie' is true, then the hardware has disappeared.
- * @release: A function to free the structure when the reference count reaches
- * zero. May be NULL if structure is statically allocated.
*
* Drivers should embed their struct posix_clock within a private
* structure, obtaining a reference to it during callbacks using
* container_of().
+ *
+ * Drivers should supply an initialized but not exposed struct device
+ * to posix_clock_register(). It is used to manage lifetime of the
+ * driver's private structure. It's 'release' field should be set to
+ * a release function for this private structure.
*/
struct posix_clock {
struct posix_clock_operations ops;
struct cdev cdev;
- struct kref kref;
+ struct device *dev;
struct rw_semaphore rwsem;
bool zombie;
- void (*release)(struct posix_clock *clk);
};
/**
* posix_clock_register() - register a new clock
- * @clk: Pointer to the clock. Caller must provide 'ops' and 'release'
- * @devid: Allocated device id
+ * @clk: Pointer to the clock. Caller must provide 'ops' field
+ * @dev: Pointer to the initialized device. Caller must provide
+ * 'release' field
*
* A clock driver calls this function to register itself with the
* clock device subsystem. If 'clk' points to dynamically allocated
@@ -135,7 +138,7 @@ struct posix_clock {
*
* Returns zero on success, non-zero otherwise.
*/
-int posix_clock_register(struct posix_clock *clk, dev_t devid);
+int posix_clock_register(struct posix_clock *clk, struct device *dev);
/**
* posix_clock_unregister() - unregister a clock
--- a/kernel/time/posix-clock.c
+++ b/kernel/time/posix-clock.c
@@ -25,8 +25,6 @@
#include <linux/syscalls.h>
#include <linux/uaccess.h>
-static void delete_clock(struct kref *kref);
-
/*
* Returns NULL if the posix_clock instance attached to 'fp' is old and stale.
*/
@@ -168,7 +166,7 @@ static int posix_clock_open(struct inode
err = 0;
if (!err) {
- kref_get(&clk->kref);
+ get_device(clk->dev);
fp->private_data = clk;
}
out:
@@ -184,7 +182,7 @@ static int posix_clock_release(struct in
if (clk->ops.release)
err = clk->ops.release(clk);
- kref_put(&clk->kref, delete_clock);
+ put_device(clk->dev);
fp->private_data = NULL;
@@ -206,38 +204,35 @@ static const struct file_operations posi
#endif
};
-int posix_clock_register(struct posix_clock *clk, dev_t devid)
+int posix_clock_register(struct posix_clock *clk, struct device *dev)
{
int err;
- kref_init(&clk->kref);
init_rwsem(&clk->rwsem);
cdev_init(&clk->cdev, &posix_clock_file_operations);
+ err = cdev_device_add(&clk->cdev, dev);
+ if (err) {
+ pr_err("%s unable to add device %d:%d\n",
+ dev_name(dev), MAJOR(dev->devt), MINOR(dev->devt));
+ return err;
+ }
clk->cdev.owner = clk->ops.owner;
- err = cdev_add(&clk->cdev, devid, 1);
+ clk->dev = dev;
- return err;
+ return 0;
}
EXPORT_SYMBOL_GPL(posix_clock_register);
-static void delete_clock(struct kref *kref)
-{
- struct posix_clock *clk = container_of(kref, struct posix_clock, kref);
-
- if (clk->release)
- clk->release(clk);
-}
-
void posix_clock_unregister(struct posix_clock *clk)
{
- cdev_del(&clk->cdev);
+ cdev_device_del(&clk->cdev, clk->dev);
down_write(&clk->rwsem);
clk->zombie = true;
up_write(&clk->rwsem);
- kref_put(&clk->kref, delete_clock);
+ put_device(clk->dev);
}
EXPORT_SYMBOL_GPL(posix_clock_unregister);
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Jose Abreu <[email protected]>
commit 8605131747e7e1fd8f6c9f97a00287aae2b2c640 upstream.
The 16KB RX Buffer must also be 16 byte aligned. Fix it.
Fixes: 7ac6653a085b ("stmmac: Move the STMicroelectronics driver")
Signed-off-by: Jose Abreu <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
drivers/net/ethernet/stmicro/stmmac/common.h | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
--- a/drivers/net/ethernet/stmicro/stmmac/common.h
+++ b/drivers/net/ethernet/stmicro/stmmac/common.h
@@ -270,9 +270,8 @@ struct dma_features {
unsigned int enh_desc;
};
-/* GMAC TX FIFO is 8K, Rx FIFO is 16K */
-#define BUF_SIZE_16KiB 16384
-/* RX Buffer size must be < 8191 and multiple of 4/8/16 bytes */
+/* RX Buffer size must be multiple of 4/8/16 bytes */
+#define BUF_SIZE_16KiB 16368
#define BUF_SIZE_8KiB 8188
#define BUF_SIZE_4KiB 4096
#define BUF_SIZE_2KiB 2048
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Randy Dunlap <[email protected]>
commit aa9f7d5172fac9bf1f09e678c35e287a40a7b7dd upstream.
Using an empty (malformed) nodelist that is not caught during mount option
parsing leads to a stack-out-of-bounds access.
The option string that was used was: "mpol=prefer:,". However,
MPOL_PREFERRED requires a single node number, which is not being provided
here.
Add a check that 'nodes' is not empty after parsing for MPOL_PREFERRED's
nodeid.
Fixes: 095f1fc4ebf3 ("mempolicy: rework shmem mpol parsing and display")
Reported-by: Entropy Moe <[email protected]>
Reported-by: [email protected]
Signed-off-by: Randy Dunlap <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Tested-by: [email protected]
Cc: Lee Schermerhorn <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Linus Torvalds <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
mm/mempolicy.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
--- a/mm/mempolicy.c
+++ b/mm/mempolicy.c
@@ -2711,7 +2711,9 @@ int mpol_parse_str(char *str, struct mem
switch (mode) {
case MPOL_PREFERRED:
/*
- * Insist on a nodelist of one node only
+ * Insist on a nodelist of one node only, although later
+ * we use first_node(nodes) to grab a single node, so here
+ * nodelist (or nodes) cannot be empty.
*/
if (nodelist) {
char *rest = nodelist;
@@ -2719,6 +2721,8 @@ int mpol_parse_str(char *str, struct mem
rest++;
if (*rest)
goto out;
+ if (nodes_empty(nodes))
+ goto out;
}
break;
case MPOL_INTERLEAVE:
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Logan Gunthorpe <[email protected]>
commit 233ed09d7fdacf592ee91e6c97ce5f4364fbe7c0 upstream.
Credit for this patch goes is shared with Dan Williams [1]. I've
taken things one step further to make the helper function more
useful and clean up calling code.
There's a common pattern in the kernel whereby a struct cdev is placed
in a structure along side a struct device which manages the life-cycle
of both. In the naive approach, the reference counting is broken and
the struct device can free everything before the chardev code
is entirely released.
Many developers have solved this problem by linking the internal kobjs
in this fashion:
cdev.kobj.parent = &parent_dev.kobj;
The cdev code explicitly gets and puts a reference to it's kobj parent.
So this seems like it was intended to be used this way. Dmitrty Torokhov
first put this in place in 2012 with this commit:
2f0157f char_dev: pin parent kobject
and the first instance of the fix was then done in the input subsystem
in the following commit:
4a215aa Input: fix use-after-free introduced with dynamic minor changes
Subsequently over the years, however, this issue seems to have tripped
up multiple developers independently. For example, see these commits:
0d5b7da iio: Prevent race between IIO chardev opening and IIO device
(by Lars-Peter Clausen in 2013)
ba0ef85 tpm: Fix initialization of the cdev
(by Jason Gunthorpe in 2015)
5b28dde [media] media: fix use-after-free in cdev_put() when app exits
after driver unbind
(by Shauh Khan in 2016)
This technique is similarly done in at least 15 places within the kernel
and probably should have been done so in another, at least, 5 places.
The kobj line also looks very suspect in that one would not expect
drivers to have to mess with kobject internals in this way.
Even highly experienced kernel developers can be surprised by this
code, as seen in [2].
To help alleviate this situation, and hopefully prevent future
wasted effort on this problem, this patch introduces a helper function
to register a char device along with its parent struct device.
This creates a more regular API for tying a char device to its parent
without the developer having to set members in the underlying kobject.
This patch introduce cdev_device_add and cdev_device_del which
replaces a common pattern including setting the kobj parent, calling
cdev_add and then calling device_add. It also introduces cdev_set_parent
for the few cases that set the kobject parent without using device_add.
[1] https://lkml.org/lkml/2017/2/13/700
[2] https://lkml.org/lkml/2017/2/10/370
Signed-off-by: Logan Gunthorpe <[email protected]>
Signed-off-by: Dan Williams <[email protected]>
Reviewed-by: Hans Verkuil <[email protected]>
Reviewed-by: Alexandre Belloni <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
fs/char_dev.c | 86 ++++++++++++++++++++++++++++++++++++++++++++
include/linux/cdev.h | 5 +++
2 files changed, 91 insertions(+)
--- a/fs/char_dev.c
+++ b/fs/char_dev.c
@@ -488,6 +488,85 @@ int cdev_add(struct cdev *p, dev_t dev,
return 0;
}
+/**
+ * cdev_set_parent() - set the parent kobject for a char device
+ * @p: the cdev structure
+ * @kobj: the kobject to take a reference to
+ *
+ * cdev_set_parent() sets a parent kobject which will be referenced
+ * appropriately so the parent is not freed before the cdev. This
+ * should be called before cdev_add.
+ */
+void cdev_set_parent(struct cdev *p, struct kobject *kobj)
+{
+ WARN_ON(!kobj->state_initialized);
+ p->kobj.parent = kobj;
+}
+
+/**
+ * cdev_device_add() - add a char device and it's corresponding
+ * struct device, linkink
+ * @dev: the device structure
+ * @cdev: the cdev structure
+ *
+ * cdev_device_add() adds the char device represented by @cdev to the system,
+ * just as cdev_add does. It then adds @dev to the system using device_add
+ * The dev_t for the char device will be taken from the struct device which
+ * needs to be initialized first. This helper function correctly takes a
+ * reference to the parent device so the parent will not get released until
+ * all references to the cdev are released.
+ *
+ * This helper uses dev->devt for the device number. If it is not set
+ * it will not add the cdev and it will be equivalent to device_add.
+ *
+ * This function should be used whenever the struct cdev and the
+ * struct device are members of the same structure whose lifetime is
+ * managed by the struct device.
+ *
+ * NOTE: Callers must assume that userspace was able to open the cdev and
+ * can call cdev fops callbacks at any time, even if this function fails.
+ */
+int cdev_device_add(struct cdev *cdev, struct device *dev)
+{
+ int rc = 0;
+
+ if (dev->devt) {
+ cdev_set_parent(cdev, &dev->kobj);
+
+ rc = cdev_add(cdev, dev->devt, 1);
+ if (rc)
+ return rc;
+ }
+
+ rc = device_add(dev);
+ if (rc)
+ cdev_del(cdev);
+
+ return rc;
+}
+
+/**
+ * cdev_device_del() - inverse of cdev_device_add
+ * @dev: the device structure
+ * @cdev: the cdev structure
+ *
+ * cdev_device_del() is a helper function to call cdev_del and device_del.
+ * It should be used whenever cdev_device_add is used.
+ *
+ * If dev->devt is not set it will not remove the cdev and will be equivalent
+ * to device_del.
+ *
+ * NOTE: This guarantees that associated sysfs callbacks are not running
+ * or runnable, however any cdevs already open will remain and their fops
+ * will still be callable even after this function returns.
+ */
+void cdev_device_del(struct cdev *cdev, struct device *dev)
+{
+ device_del(dev);
+ if (dev->devt)
+ cdev_del(cdev);
+}
+
static void cdev_unmap(dev_t dev, unsigned count)
{
kobj_unmap(cdev_map, dev, count);
@@ -499,6 +578,10 @@ static void cdev_unmap(dev_t dev, unsign
*
* cdev_del() removes @p from the system, possibly freeing the structure
* itself.
+ *
+ * NOTE: This guarantees that cdev device will no longer be able to be
+ * opened, however any cdevs already open will remain and their fops will
+ * still be callable even after cdev_del returns.
*/
void cdev_del(struct cdev *p)
{
@@ -589,6 +672,9 @@ EXPORT_SYMBOL(cdev_init);
EXPORT_SYMBOL(cdev_alloc);
EXPORT_SYMBOL(cdev_del);
EXPORT_SYMBOL(cdev_add);
+EXPORT_SYMBOL(cdev_set_parent);
+EXPORT_SYMBOL(cdev_device_add);
+EXPORT_SYMBOL(cdev_device_del);
EXPORT_SYMBOL(__register_chrdev);
EXPORT_SYMBOL(__unregister_chrdev);
EXPORT_SYMBOL(directly_mappable_cdev_bdi);
--- a/include/linux/cdev.h
+++ b/include/linux/cdev.h
@@ -4,6 +4,7 @@
#include <linux/kobject.h>
#include <linux/kdev_t.h>
#include <linux/list.h>
+#include <linux/device.h>
struct file_operations;
struct inode;
@@ -26,6 +27,10 @@ void cdev_put(struct cdev *p);
int cdev_add(struct cdev *, dev_t, unsigned);
+void cdev_set_parent(struct cdev *p, struct kobject *kobj);
+int cdev_device_add(struct cdev *cdev, struct device *dev);
+void cdev_device_del(struct cdev *cdev, struct device *dev);
+
void cdev_del(struct cdev *);
void cd_forget(struct inode *);
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Shuah Khan <[email protected]>
commit 5b28dde51d0ccc54cee70756e1800d70bed7114a upstream.
When driver unbinds while media_ioctl is in progress, cdev_put() fails with
when app exits after driver unbinds.
Add devnode struct device kobj as the cdev parent kobject. cdev_add() gets
a reference to it and releases it in cdev_del() ensuring that the devnode
is not deallocated as long as the application has the device file open.
media_devnode_register() initializes the struct device kobj before calling
cdev_add(). media_devnode_unregister() does cdev_del() and then deletes the
device. devnode is released when the last reference to the struct device is
gone.
This problem is found on uvcvideo, em28xx, and au0828 drivers and fix has
been tested on all three.
kernel: [ 193.599736] BUG: KASAN: use-after-free in cdev_put+0x4e/0x50
kernel: [ 193.599745] Read of size 8 by task media_device_te/1851
kernel: [ 193.599792] INFO: Allocated in __media_device_register+0x54
kernel: [ 193.599951] INFO: Freed in media_devnode_release+0xa4/0xc0
kernel: [ 193.601083] Call Trace:
kernel: [ 193.601093] [<ffffffff81aecac3>] dump_stack+0x67/0x94
kernel: [ 193.601102] [<ffffffff815359b2>] print_trailer+0x112/0x1a0
kernel: [ 193.601111] [<ffffffff8153b5e4>] object_err+0x34/0x40
kernel: [ 193.601119] [<ffffffff8153d9d4>] kasan_report_error+0x224/0x530
kernel: [ 193.601128] [<ffffffff814a2c3d>] ? kzfree+0x2d/0x40
kernel: [ 193.601137] [<ffffffff81539d72>] ? kfree+0x1d2/0x1f0
kernel: [ 193.601154] [<ffffffff8157ca7e>] ? cdev_put+0x4e/0x50
kernel: [ 193.601162] [<ffffffff8157ca7e>] cdev_put+0x4e/0x50
kernel: [ 193.601170] [<ffffffff815767eb>] __fput+0x52b/0x6c0
kernel: [ 193.601179] [<ffffffff8117743a>] ? switch_task_namespaces+0x2a
kernel: [ 193.601188] [<ffffffff815769ee>] ____fput+0xe/0x10
kernel: [ 193.601196] [<ffffffff81170023>] task_work_run+0x133/0x1f0
kernel: [ 193.601204] [<ffffffff8117746e>] ? switch_task_namespaces+0x5e
kernel: [ 193.601213] [<ffffffff8111b50c>] do_exit+0x72c/0x2c20
kernel: [ 193.601224] [<ffffffff8111ade0>] ? release_task+0x1250/0x1250
-
-
-
kernel: [ 193.601360] [<ffffffff81003587>] ? exit_to_usermode_loop+0xe7
kernel: [ 193.601368] [<ffffffff810035c0>] exit_to_usermode_loop+0x120
kernel: [ 193.601376] [<ffffffff810061da>] syscall_return_slowpath+0x16a
kernel: [ 193.601386] [<ffffffff82848b33>] entry_SYSCALL_64_fastpath+0xa6
Signed-off-by: Shuah Khan <[email protected]>
Tested-by: Mauro Carvalho Chehab <[email protected]>
Signed-off-by: Mauro Carvalho Chehab <[email protected]>
[bwh: Backported to 3.16: adjust context]
Signed-off-by: Ben Hutchings <[email protected]>
---
drivers/media/media-device.c | 6 +++--
drivers/media/media-devnode.c | 48 +++++++++++++++++++++--------------
2 files changed, 33 insertions(+), 21 deletions(-)
--- a/drivers/media/media-device.c
+++ b/drivers/media/media-device.c
@@ -398,16 +398,16 @@ int __must_check __media_device_register
devnode->release = media_device_release;
ret = media_devnode_register(mdev, devnode, owner);
if (ret < 0) {
+ /* devnode free is handled in media_devnode_*() */
mdev->devnode = NULL;
- kfree(devnode);
return ret;
}
ret = device_create_file(&devnode->dev, &dev_attr_model);
if (ret < 0) {
+ /* devnode free is handled in media_devnode_*() */
mdev->devnode = NULL;
media_devnode_unregister(devnode);
- kfree(devnode);
return ret;
}
@@ -432,6 +432,8 @@ void media_device_unregister(struct medi
if (media_devnode_is_registered(mdev->devnode)) {
device_remove_file(&mdev->devnode->dev, &dev_attr_model);
media_devnode_unregister(mdev->devnode);
+ /* devnode free is handled in media_devnode_*() */
+ mdev->devnode = NULL;
}
}
EXPORT_SYMBOL_GPL(media_device_unregister);
--- a/drivers/media/media-devnode.c
+++ b/drivers/media/media-devnode.c
@@ -63,13 +63,8 @@ static void media_devnode_release(struct
struct media_devnode *devnode = to_media_devnode(cd);
mutex_lock(&media_devnode_lock);
-
- /* Delete the cdev on this minor as well */
- cdev_del(&devnode->cdev);
-
/* Mark device node number as free */
clear_bit(devnode->minor, media_devnode_nums);
-
mutex_unlock(&media_devnode_lock);
/* Release media_devnode and perform other cleanups as needed. */
@@ -77,6 +72,7 @@ static void media_devnode_release(struct
devnode->release(devnode);
kfree(devnode);
+ pr_debug("%s: Media Devnode Deallocated\n", __func__);
}
static struct bus_type media_bus_type = {
@@ -205,6 +201,8 @@ static int media_release(struct inode *i
/* decrease the refcount unconditionally since the release()
return value is ignored. */
put_device(&devnode->dev);
+
+ pr_debug("%s: Media Release\n", __func__);
return 0;
}
@@ -250,6 +248,7 @@ int __must_check media_devnode_register(
if (minor == MEDIA_NUM_DEVICES) {
mutex_unlock(&media_devnode_lock);
pr_err("could not get a free minor\n");
+ kfree(devnode);
return -ENFILE;
}
@@ -259,27 +258,31 @@ int __must_check media_devnode_register(
devnode->minor = minor;
devnode->media_dev = mdev;
+ /* Part 1: Initialize dev now to use dev.kobj for cdev.kobj.parent */
+ devnode->dev.bus = &media_bus_type;
+ devnode->dev.devt = MKDEV(MAJOR(media_dev_t), devnode->minor);
+ devnode->dev.release = media_devnode_release;
+ if (devnode->parent)
+ devnode->dev.parent = devnode->parent;
+ dev_set_name(&devnode->dev, "media%d", devnode->minor);
+ device_initialize(&devnode->dev);
+
/* Part 2: Initialize and register the character device */
cdev_init(&devnode->cdev, &media_devnode_fops);
devnode->cdev.owner = owner;
+ devnode->cdev.kobj.parent = &devnode->dev.kobj;
ret = cdev_add(&devnode->cdev, MKDEV(MAJOR(media_dev_t), devnode->minor), 1);
if (ret < 0) {
pr_err("%s: cdev_add failed\n", __func__);
- goto error;
+ goto cdev_add_error;
}
- /* Part 3: Register the media device */
- devnode->dev.bus = &media_bus_type;
- devnode->dev.devt = MKDEV(MAJOR(media_dev_t), devnode->minor);
- devnode->dev.release = media_devnode_release;
- if (devnode->parent)
- devnode->dev.parent = devnode->parent;
- dev_set_name(&devnode->dev, "media%d", devnode->minor);
- ret = device_register(&devnode->dev);
+ /* Part 3: Add the media device */
+ ret = device_add(&devnode->dev);
if (ret < 0) {
- pr_err("%s: device_register failed\n", __func__);
- goto error;
+ pr_err("%s: device_add failed\n", __func__);
+ goto device_add_error;
}
/* Part 4: Activate this minor. The char device can now be used. */
@@ -287,12 +290,15 @@ int __must_check media_devnode_register(
return 0;
-error:
- mutex_lock(&media_devnode_lock);
+device_add_error:
cdev_del(&devnode->cdev);
+cdev_add_error:
+ mutex_lock(&media_devnode_lock);
clear_bit(devnode->minor, media_devnode_nums);
+ devnode->media_dev = NULL;
mutex_unlock(&media_devnode_lock);
+ put_device(&devnode->dev);
return ret;
}
@@ -314,8 +320,12 @@ void media_devnode_unregister(struct med
mutex_lock(&media_devnode_lock);
clear_bit(MEDIA_FLAG_REGISTERED, &devnode->flags);
+ /* Delete the cdev on this minor as well */
+ cdev_del(&devnode->cdev);
mutex_unlock(&media_devnode_lock);
- device_unregister(&devnode->dev);
+ device_del(&devnode->dev);
+ devnode->media_dev = NULL;
+ put_device(&devnode->dev);
}
/*
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: YueHaibing <[email protected]>
commit aea0a897af9e44c258e8ab9296fad417f1bc063a upstream.
Fix smatch warning:
drivers/ptp/ptp_clock.c:298 ptp_clock_register() warn:
passing zero to 'ERR_PTR'
'err' should be set while device_create_with_groups and
pps_register_source fails
Fixes: 85a66e550195 ("ptp: create "pins" together with the rest of attributes")
Signed-off-by: YueHaibing <[email protected]>
Acked-by: Richard Cochran <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
drivers/ptp/ptp_clock.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
--- a/drivers/ptp/ptp_clock.c
+++ b/drivers/ptp/ptp_clock.c
@@ -218,8 +218,10 @@ struct ptp_clock *ptp_clock_register(str
ptp->dev = device_create_with_groups(ptp_class, parent, ptp->devid,
ptp, ptp->pin_attr_groups,
"ptp%d", ptp->index);
- if (IS_ERR(ptp->dev))
+ if (IS_ERR(ptp->dev)) {
+ err = PTR_ERR(ptp->dev);
goto no_device;
+ }
/* Register a new PPS source. */
if (info->pps) {
@@ -230,6 +232,7 @@ struct ptp_clock *ptp_clock_register(str
pps.owner = info->owner;
ptp->pps_source = pps_register_source(&pps, PTP_PPS_DEFAULTS);
if (!ptp->pps_source) {
+ err = -EINVAL;
pr_err("failed to register pps source\n");
goto no_pps;
}
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Dmitry Torokhov <[email protected]>
commit 85a66e55019583da1e0f18706b7a8281c9f6de5b upstream.
Let's switch to using device_create_with_groups(), which will allow us to
create "pins" attribute group together with the rest of ptp device
attributes, and before userspace gets notified about ptp device creation.
Signed-off-by: Dmitry Torokhov <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
[bwh: Backported to 3.16: adjust context]
Signed-off-by: Ben Hutchings <[email protected]>
---
drivers/ptp/ptp_clock.c | 20 +++++++++++---------
drivers/ptp/ptp_private.h | 7 ++++---
drivers/ptp/ptp_sysfs.c | 39 +++++++++------------------------------
3 files changed, 24 insertions(+), 42 deletions(-)
--- a/drivers/ptp/ptp_clock.c
+++ b/drivers/ptp/ptp_clock.c
@@ -210,16 +210,17 @@ struct ptp_clock *ptp_clock_register(str
mutex_init(&ptp->pincfg_mux);
init_waitqueue_head(&ptp->tsev_wq);
+ err = ptp_populate_pin_groups(ptp);
+ if (err)
+ goto no_pin_groups;
+
/* Create a new device in our class. */
- ptp->dev = device_create(ptp_class, parent, ptp->devid, ptp,
- "ptp%d", ptp->index);
+ ptp->dev = device_create_with_groups(ptp_class, parent, ptp->devid,
+ ptp, ptp->pin_attr_groups,
+ "ptp%d", ptp->index);
if (IS_ERR(ptp->dev))
goto no_device;
- err = ptp_populate_sysfs(ptp);
- if (err)
- goto no_sysfs;
-
/* Register a new PPS source. */
if (info->pps) {
struct pps_source_info pps;
@@ -247,10 +248,10 @@ no_clock:
if (ptp->pps_source)
pps_unregister_source(ptp->pps_source);
no_pps:
- ptp_cleanup_sysfs(ptp);
-no_sysfs:
device_destroy(ptp_class, ptp->devid);
no_device:
+ ptp_cleanup_pin_groups(ptp);
+no_pin_groups:
mutex_destroy(&ptp->tsevq_mux);
mutex_destroy(&ptp->pincfg_mux);
no_slot:
@@ -268,8 +269,9 @@ int ptp_clock_unregister(struct ptp_cloc
/* Release the clock's resources. */
if (ptp->pps_source)
pps_unregister_source(ptp->pps_source);
- ptp_cleanup_sysfs(ptp);
+
device_destroy(ptp_class, ptp->devid);
+ ptp_cleanup_pin_groups(ptp);
posix_clock_unregister(&ptp->clock);
return 0;
--- a/drivers/ptp/ptp_private.h
+++ b/drivers/ptp/ptp_private.h
@@ -54,6 +54,8 @@ struct ptp_clock {
struct device_attribute *pin_dev_attr;
struct attribute **pin_attr;
struct attribute_group pin_attr_group;
+ /* 1st entry is a pointer to the real group, 2nd is NULL terminator */
+ const struct attribute_group *pin_attr_groups[2];
};
/*
@@ -94,8 +96,7 @@ uint ptp_poll(struct posix_clock *pc,
extern const struct attribute_group *ptp_groups[];
-int ptp_cleanup_sysfs(struct ptp_clock *ptp);
-
-int ptp_populate_sysfs(struct ptp_clock *ptp);
+int ptp_populate_pin_groups(struct ptp_clock *ptp);
+void ptp_cleanup_pin_groups(struct ptp_clock *ptp);
#endif
--- a/drivers/ptp/ptp_sysfs.c
+++ b/drivers/ptp/ptp_sysfs.c
@@ -268,25 +268,14 @@ static ssize_t ptp_pin_store(struct devi
return count;
}
-int ptp_cleanup_sysfs(struct ptp_clock *ptp)
+int ptp_populate_pin_groups(struct ptp_clock *ptp)
{
- struct device *dev = ptp->dev;
- struct ptp_clock_info *info = ptp->info;
-
- if (info->n_pins) {
- sysfs_remove_group(&dev->kobj, &ptp->pin_attr_group);
- kfree(ptp->pin_attr);
- kfree(ptp->pin_dev_attr);
- }
- return 0;
-}
-
-static int ptp_populate_pins(struct ptp_clock *ptp)
-{
- struct device *dev = ptp->dev;
struct ptp_clock_info *info = ptp->info;
int err = -ENOMEM, i, n_pins = info->n_pins;
+ if (!n_pins)
+ return 0;
+
ptp->pin_dev_attr = kzalloc(n_pins * sizeof(*ptp->pin_dev_attr),
GFP_KERNEL);
if (!ptp->pin_dev_attr)
@@ -310,28 +299,18 @@ static int ptp_populate_pins(struct ptp_
ptp->pin_attr_group.name = "pins";
ptp->pin_attr_group.attrs = ptp->pin_attr;
- err = sysfs_create_group(&dev->kobj, &ptp->pin_attr_group);
- if (err)
- goto no_group;
+ ptp->pin_attr_groups[0] = &ptp->pin_attr_group;
+
return 0;
-no_group:
- kfree(ptp->pin_attr);
no_pin_attr:
kfree(ptp->pin_dev_attr);
no_dev_attr:
return err;
}
-int ptp_populate_sysfs(struct ptp_clock *ptp)
+void ptp_cleanup_pin_groups(struct ptp_clock *ptp)
{
- struct ptp_clock_info *info = ptp->info;
- int err;
-
- if (info->n_pins) {
- err = ptp_populate_pins(ptp);
- if (err)
- return err;
- }
- return 0;
+ kfree(ptp->pin_attr);
+ kfree(ptp->pin_dev_attr);
}
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Mauro Carvalho Chehab <[email protected]>
commit a087ce704b802becbb4b0f2a20f2cb3f6911802e upstream.
struct media_devnode is currently embedded at struct media_device.
While this works fine during normal usage, it leads to a race
condition during devnode unregister. the problem is that drivers
assume that, after calling media_device_unregister(), the struct
that contains media_device can be freed. This is not true, as it
can't be freed until userspace closes all opened /dev/media devnodes.
In other words, if the media devnode is still open, and media_device
gets freed, any call to an ioctl will make the core to try to access
struct media_device, with will cause an use-after-free and even GPF.
Fix this by dynamically allocating the struct media_devnode and only
freeing it when it is safe.
Signed-off-by: Mauro Carvalho Chehab <[email protected]>
Signed-off-by: Mauro Carvalho Chehab <[email protected]>
[bwh: Backported to 3.16:
- Drop change in au0828
- Include <linux/slab.h> in media-device.c
- Adjust context]
Signed-off-by: Ben Hutchings <[email protected]>
---
--- a/drivers/media/media-device.c
+++ b/drivers/media/media-device.c
@@ -24,6 +24,7 @@
#include <linux/export.h>
#include <linux/ioctl.h>
#include <linux/media.h>
+#include <linux/slab.h>
#include <linux/types.h>
#include <media/media-device.h>
@@ -236,7 +237,7 @@ static long media_device_ioctl(struct fi
unsigned long arg)
{
struct media_devnode *devnode = media_devnode_data(filp);
- struct media_device *dev = to_media_device(devnode);
+ struct media_device *dev = devnode->media_dev;
long ret;
switch (cmd) {
@@ -305,7 +306,7 @@ static long media_device_compat_ioctl(st
unsigned long arg)
{
struct media_devnode *devnode = media_devnode_data(filp);
- struct media_device *dev = to_media_device(devnode);
+ struct media_device *dev = devnode->media_dev;
long ret;
switch (cmd) {
@@ -346,7 +347,8 @@ static const struct media_file_operation
static ssize_t show_model(struct device *cd,
struct device_attribute *attr, char *buf)
{
- struct media_device *mdev = to_media_device(to_media_devnode(cd));
+ struct media_devnode *devnode = to_media_devnode(cd);
+ struct media_device *mdev = devnode->media_dev;
return sprintf(buf, "%.*s\n", (int)sizeof(mdev->model), mdev->model);
}
@@ -374,6 +376,7 @@ static void media_device_release(struct
int __must_check __media_device_register(struct media_device *mdev,
struct module *owner)
{
+ struct media_devnode *devnode;
int ret;
if (WARN_ON(mdev->dev == NULL || mdev->model[0] == 0))
@@ -384,17 +387,27 @@ int __must_check __media_device_register
spin_lock_init(&mdev->lock);
mutex_init(&mdev->graph_mutex);
+ devnode = kzalloc(sizeof(*devnode), GFP_KERNEL);
+ if (!devnode)
+ return -ENOMEM;
+
/* Register the device node. */
- mdev->devnode.fops = &media_device_fops;
- mdev->devnode.parent = mdev->dev;
- mdev->devnode.release = media_device_release;
- ret = media_devnode_register(&mdev->devnode, owner);
- if (ret < 0)
+ mdev->devnode = devnode;
+ devnode->fops = &media_device_fops;
+ devnode->parent = mdev->dev;
+ devnode->release = media_device_release;
+ ret = media_devnode_register(mdev, devnode, owner);
+ if (ret < 0) {
+ mdev->devnode = NULL;
+ kfree(devnode);
return ret;
+ }
- ret = device_create_file(&mdev->devnode.dev, &dev_attr_model);
+ ret = device_create_file(&devnode->dev, &dev_attr_model);
if (ret < 0) {
- media_devnode_unregister(&mdev->devnode);
+ mdev->devnode = NULL;
+ media_devnode_unregister(devnode);
+ kfree(devnode);
return ret;
}
@@ -415,8 +428,11 @@ void media_device_unregister(struct medi
list_for_each_entry_safe(entity, next, &mdev->entities, list)
media_device_unregister_entity(entity);
- device_remove_file(&mdev->devnode.dev, &dev_attr_model);
- media_devnode_unregister(&mdev->devnode);
+ /* Check if mdev devnode was registered */
+ if (media_devnode_is_registered(mdev->devnode)) {
+ device_remove_file(&mdev->devnode->dev, &dev_attr_model);
+ media_devnode_unregister(mdev->devnode);
+ }
}
EXPORT_SYMBOL_GPL(media_device_unregister);
--- a/drivers/media/media-devnode.c
+++ b/drivers/media/media-devnode.c
@@ -44,6 +44,7 @@
#include <linux/uaccess.h>
#include <media/media-devnode.h>
+#include <media/media-device.h>
#define MEDIA_NUM_DEVICES 256
#define MEDIA_NAME "media"
@@ -74,6 +75,8 @@ static void media_devnode_release(struct
/* Release media_devnode and perform other cleanups as needed. */
if (devnode->release)
devnode->release(devnode);
+
+ kfree(devnode);
}
static struct bus_type media_bus_type = {
@@ -221,6 +224,7 @@ static const struct file_operations medi
/**
* media_devnode_register - register a media device node
+ * @media_dev: struct media_device we want to register a device node
* @devnode: media device node structure we want to register
*
* The registration code assigns minor numbers and registers the new device node
@@ -233,7 +237,8 @@ static const struct file_operations medi
* the media_devnode structure is *not* called, so the caller is responsible for
* freeing any data.
*/
-int __must_check media_devnode_register(struct media_devnode *devnode,
+int __must_check media_devnode_register(struct media_device *mdev,
+ struct media_devnode *devnode,
struct module *owner)
{
int minor;
@@ -252,6 +257,7 @@ int __must_check media_devnode_register(
mutex_unlock(&media_devnode_lock);
devnode->minor = minor;
+ devnode->media_dev = mdev;
/* Part 2: Initialize and register the character device */
cdev_init(&devnode->cdev, &media_devnode_fops);
--- a/include/media/media-device.h
+++ b/include/media/media-device.h
@@ -60,7 +60,7 @@ struct device;
struct media_device {
/* dev->driver_data points to this struct. */
struct device *dev;
- struct media_devnode devnode;
+ struct media_devnode *devnode;
char model[32];
char serial[40];
@@ -84,9 +84,6 @@ struct media_device {
#define MEDIA_DEV_NOTIFY_PRE_LINK_CH 0
#define MEDIA_DEV_NOTIFY_POST_LINK_CH 1
-/* media_devnode to media_device */
-#define to_media_device(node) container_of(node, struct media_device, devnode)
-
int __must_check __media_device_register(struct media_device *mdev,
struct module *owner);
#define media_device_register(mdev) __media_device_register(mdev, THIS_MODULE)
--- a/drivers/media/usb/uvc/uvc_driver.c
+++ b/drivers/media/usb/uvc/uvc_driver.c
@@ -1640,7 +1640,7 @@ static void uvc_delete(struct uvc_device
if (dev->vdev.dev)
v4l2_device_unregister(&dev->vdev);
#ifdef CONFIG_MEDIA_CONTROLLER
- if (media_devnode_is_registered(&dev->mdev.devnode))
+ if (media_devnode_is_registered(dev->mdev.devnode))
media_device_unregister(&dev->mdev);
#endif
--- a/include/media/media-devnode.h
+++ b/include/media/media-devnode.h
@@ -33,6 +33,8 @@
#include <linux/device.h>
#include <linux/cdev.h>
+struct media_device;
+
/*
* Flag to mark the media_devnode struct as registered. Drivers must not touch
* this flag directly, it will be set and cleared by media_devnode_register and
@@ -63,6 +65,8 @@ struct media_file_operations {
* before registering the node.
*/
struct media_devnode {
+ struct media_device *media_dev;
+
/* device ops */
const struct media_file_operations *fops;
@@ -82,7 +86,8 @@ struct media_devnode {
/* dev to media_devnode */
#define to_media_devnode(cd) container_of(cd, struct media_devnode, dev)
-int __must_check media_devnode_register(struct media_devnode *devnode,
+int __must_check media_devnode_register(struct media_device *mdev,
+ struct media_devnode *devnode,
struct module *owner);
void media_devnode_unregister(struct media_devnode *devnode);
@@ -93,6 +98,9 @@ static inline struct media_devnode *medi
static inline int media_devnode_is_registered(struct media_devnode *devnode)
{
+ if (!devnode)
+ return false;
+
return test_bit(MEDIA_FLAG_REGISTERED, &devnode->flags);
}
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Johan Hovold <[email protected]>
commit a246b4d547708f33ff4d4b9a7a5dbac741dc89d8 upstream.
Make sure to check that we have two alternate settings and at least one
endpoint before accessing the second altsetting structure and
dereferencing the endpoint arrays.
This specifically avoids dereferencing NULL-pointers or corrupting
memory when a device does not have the expected descriptors.
Note that the sanity check in cit_get_packet_size() is not redundant as
the driver is mixing looking up altsettings by index and by number,
which may not coincide.
Fixes: 659fefa0eb17 ("V4L/DVB: gspca_xirlink_cit: Add support for camera with a bcd version of 0.01")
Fixes: 59f8b0bf3c12 ("V4L/DVB: gspca_xirlink_cit: support bandwidth changing for devices with 1 alt setting")
Cc: Hans de Goede <[email protected]>
Signed-off-by: Johan Hovold <[email protected]>
Signed-off-by: Hans Verkuil <[email protected]>
Signed-off-by: Mauro Carvalho Chehab <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
drivers/media/usb/gspca/xirlink_cit.c | 18 +++++++++++++++++-
1 file changed, 17 insertions(+), 1 deletion(-)
--- a/drivers/media/usb/gspca/xirlink_cit.c
+++ b/drivers/media/usb/gspca/xirlink_cit.c
@@ -1455,6 +1455,9 @@ static int cit_get_packet_size(struct gs
return -EIO;
}
+ if (alt->desc.bNumEndpoints < 1)
+ return -ENODEV;
+
return le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize);
}
@@ -2632,6 +2635,7 @@ static int sd_start(struct gspca_dev *gs
static int sd_isoc_init(struct gspca_dev *gspca_dev)
{
+ struct usb_interface_cache *intfc;
struct usb_host_interface *alt;
int max_packet_size;
@@ -2647,8 +2651,17 @@ static int sd_isoc_init(struct gspca_dev
break;
}
+ intfc = gspca_dev->dev->actconfig->intf_cache[0];
+
+ if (intfc->num_altsetting < 2)
+ return -ENODEV;
+
+ alt = &intfc->altsetting[1];
+
+ if (alt->desc.bNumEndpoints < 1)
+ return -ENODEV;
+
/* Start isoc bandwidth "negotiation" at max isoc bandwidth */
- alt = &gspca_dev->dev->actconfig->intf_cache[0]->altsetting[1];
alt->endpoint[0].desc.wMaxPacketSize = cpu_to_le16(max_packet_size);
return 0;
@@ -2671,6 +2684,9 @@ static int sd_isoc_nego(struct gspca_dev
break;
}
+ /*
+ * Existence of altsetting and endpoint was verified in sd_isoc_init()
+ */
alt = &gspca_dev->dev->actconfig->intf_cache[0]->altsetting[1];
packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize);
if (packet_size <= min_packet_size)
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Jiri Slaby <[email protected]>
commit e8c75a30a23c6ba63f4ef6895cbf41fd42f21aa2 upstream.
sel_lock cannot nest in the console lock. Thanks to syzkaller, the
kernel states firmly:
> WARNING: possible circular locking dependency detected
> 5.6.0-rc3-syzkaller #0 Not tainted
> ------------------------------------------------------
> syz-executor.4/20336 is trying to acquire lock:
> ffff8880a2e952a0 (&tty->termios_rwsem){++++}, at: tty_unthrottle+0x22/0x100 drivers/tty/tty_ioctl.c:136
>
> but task is already holding lock:
> ffffffff89462e70 (sel_lock){+.+.}, at: paste_selection+0x118/0x470 drivers/tty/vt/selection.c:374
>
> which lock already depends on the new lock.
>
> the existing dependency chain (in reverse order) is:
>
> -> #2 (sel_lock){+.+.}:
> mutex_lock_nested+0x1b/0x30 kernel/locking/mutex.c:1118
> set_selection_kernel+0x3b8/0x18a0 drivers/tty/vt/selection.c:217
> set_selection_user+0x63/0x80 drivers/tty/vt/selection.c:181
> tioclinux+0x103/0x530 drivers/tty/vt/vt.c:3050
> vt_ioctl+0x3f1/0x3a30 drivers/tty/vt/vt_ioctl.c:364
This is ioctl(TIOCL_SETSEL).
Locks held on the path: console_lock -> sel_lock
> -> #1 (console_lock){+.+.}:
> console_lock+0x46/0x70 kernel/printk/printk.c:2289
> con_flush_chars+0x50/0x650 drivers/tty/vt/vt.c:3223
> n_tty_write+0xeae/0x1200 drivers/tty/n_tty.c:2350
> do_tty_write drivers/tty/tty_io.c:962 [inline]
> tty_write+0x5a1/0x950 drivers/tty/tty_io.c:1046
This is write().
Locks held on the path: termios_rwsem -> console_lock
> -> #0 (&tty->termios_rwsem){++++}:
> down_write+0x57/0x140 kernel/locking/rwsem.c:1534
> tty_unthrottle+0x22/0x100 drivers/tty/tty_ioctl.c:136
> mkiss_receive_buf+0x12aa/0x1340 drivers/net/hamradio/mkiss.c:902
> tty_ldisc_receive_buf+0x12f/0x170 drivers/tty/tty_buffer.c:465
> paste_selection+0x346/0x470 drivers/tty/vt/selection.c:389
> tioclinux+0x121/0x530 drivers/tty/vt/vt.c:3055
> vt_ioctl+0x3f1/0x3a30 drivers/tty/vt/vt_ioctl.c:364
This is ioctl(TIOCL_PASTESEL).
Locks held on the path: sel_lock -> termios_rwsem
> other info that might help us debug this:
>
> Chain exists of:
> &tty->termios_rwsem --> console_lock --> sel_lock
Clearly. From the above, we have:
console_lock -> sel_lock
sel_lock -> termios_rwsem
termios_rwsem -> console_lock
Fix this by reversing the console_lock -> sel_lock dependency in
ioctl(TIOCL_SETSEL). First, lock sel_lock, then console_lock.
Signed-off-by: Jiri Slaby <[email protected]>
Reported-by: [email protected]
Fixes: 07e6124a1a46 ("vt: selection, close sel_buffer race")
Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Greg Kroah-Hartman <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
drivers/tty/vt/selection.c | 16 +++++++---------
1 file changed, 7 insertions(+), 9 deletions(-)
--- a/drivers/tty/vt/selection.c
+++ b/drivers/tty/vt/selection.c
@@ -205,7 +205,6 @@ static int __set_selection(const struct
pe = tmp;
}
- mutex_lock(&sel_lock);
if (sel_cons != vc_cons[fg_console].d) {
clear_selection();
sel_cons = vc_cons[fg_console].d;
@@ -251,10 +250,9 @@ static int __set_selection(const struct
break;
case TIOCL_SELPOINTER:
highlight_pointer(pe);
- goto unlock;
+ return 0;
default:
- ret = -EINVAL;
- goto unlock;
+ return -EINVAL;
}
/* remove the pointer */
@@ -276,7 +274,7 @@ static int __set_selection(const struct
else if (new_sel_start == sel_start)
{
if (new_sel_end == sel_end) /* no action required */
- goto unlock;
+ return 0;
else if (new_sel_end > sel_end) /* extend to right */
highlight(sel_end + 2, new_sel_end);
else /* contract from right */
@@ -303,8 +301,7 @@ static int __set_selection(const struct
if (!bp) {
printk(KERN_WARNING "selection: kmalloc() failed\n");
clear_selection();
- ret = -ENOMEM;
- goto unlock;
+ return -ENOMEM;
}
kfree(sel_buffer);
sel_buffer = bp;
@@ -329,8 +326,7 @@ static int __set_selection(const struct
}
}
sel_buffer_lth = bp - sel_buffer;
-unlock:
- mutex_unlock(&sel_lock);
+
return ret;
}
@@ -338,9 +334,11 @@ int set_selection(const struct tiocl_sel
{
int ret;
+ mutex_lock(&sel_lock);
console_lock();
ret = __set_selection(v, tty);
console_unlock();
+ mutex_unlock(&sel_lock);
return ret;
}
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Johan Hovold <[email protected]>
commit 485b06aadb933190f4bc44e006076bc27a23f205 upstream.
Make sure to check that we have two alternate settings and at least one
endpoint before accessing the second altsetting structure and
dereferencing the endpoint arrays.
This specifically avoids dereferencing NULL-pointers or corrupting
memory when a device does not have the expected descriptors.
Note that the sanity checks in stv06xx_start() and pb0100_start() are
not redundant as the driver is mixing looking up altsettings by index
and by number, which may not coincide.
Fixes: 8668d504d72c ("V4L/DVB (12082): gspca_stv06xx: Add support for st6422 bridge and sensor")
Fixes: c0b33bdc5b8d ("[media] gspca-stv06xx: support bandwidth changing")
Cc: Hans de Goede <[email protected]>
Signed-off-by: Johan Hovold <[email protected]>
Signed-off-by: Hans Verkuil <[email protected]>
Signed-off-by: Mauro Carvalho Chehab <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
drivers/media/usb/gspca/stv06xx/stv06xx.c | 19 ++++++++++++++++++-
.../media/usb/gspca/stv06xx/stv06xx_pb0100.c | 4 ++++
2 files changed, 22 insertions(+), 1 deletion(-)
--- a/drivers/media/usb/gspca/stv06xx/stv06xx.c
+++ b/drivers/media/usb/gspca/stv06xx/stv06xx.c
@@ -293,6 +293,9 @@ static int stv06xx_start(struct gspca_de
return -EIO;
}
+ if (alt->desc.bNumEndpoints < 1)
+ return -ENODEV;
+
packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize);
err = stv06xx_write_bridge(sd, STV_ISO_SIZE_L, packet_size);
if (err < 0)
@@ -317,11 +320,21 @@ out:
static int stv06xx_isoc_init(struct gspca_dev *gspca_dev)
{
+ struct usb_interface_cache *intfc;
struct usb_host_interface *alt;
struct sd *sd = (struct sd *) gspca_dev;
+ intfc = gspca_dev->dev->actconfig->intf_cache[0];
+
+ if (intfc->num_altsetting < 2)
+ return -ENODEV;
+
+ alt = &intfc->altsetting[1];
+
+ if (alt->desc.bNumEndpoints < 1)
+ return -ENODEV;
+
/* Start isoc bandwidth "negotiation" at max isoc bandwidth */
- alt = &gspca_dev->dev->actconfig->intf_cache[0]->altsetting[1];
alt->endpoint[0].desc.wMaxPacketSize =
cpu_to_le16(sd->sensor->max_packet_size[gspca_dev->curr_mode]);
@@ -334,6 +347,10 @@ static int stv06xx_isoc_nego(struct gspc
struct usb_host_interface *alt;
struct sd *sd = (struct sd *) gspca_dev;
+ /*
+ * Existence of altsetting and endpoint was verified in
+ * stv06xx_isoc_init()
+ */
alt = &gspca_dev->dev->actconfig->intf_cache[0]->altsetting[1];
packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize);
min_packet_size = sd->sensor->min_packet_size[gspca_dev->curr_mode];
--- a/drivers/media/usb/gspca/stv06xx/stv06xx_pb0100.c
+++ b/drivers/media/usb/gspca/stv06xx/stv06xx_pb0100.c
@@ -198,6 +198,10 @@ static int pb0100_start(struct sd *sd)
alt = usb_altnum_to_altsetting(intf, sd->gspca_dev.alt);
if (!alt)
return -ENODEV;
+
+ if (alt->desc.bNumEndpoints < 1)
+ return -ENODEV;
+
packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize);
/* If we don't have enough bandwidth use a lower framerate */
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Dmitry Torokhov <[email protected]>
commit 882f312dc0751c973db26478f07f082c584d16aa upstream.
We do not need explicitly call dev_set_drvdata(), as it is done for us by
device_create().
Acked-by: Richard Cochran <[email protected]>
Signed-off-by: Dmitry Torokhov <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
drivers/ptp/ptp_clock.c | 2 --
1 file changed, 2 deletions(-)
--- a/drivers/ptp/ptp_clock.c
+++ b/drivers/ptp/ptp_clock.c
@@ -216,8 +216,6 @@ struct ptp_clock *ptp_clock_register(str
if (IS_ERR(ptp->dev))
goto no_device;
- dev_set_drvdata(ptp->dev, ptp);
-
err = ptp_populate_sysfs(ptp);
if (err)
goto no_sysfs;
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Hans de Goede <[email protected]>
commit 133b2acee3871ae6bf123b8fe34be14464aa3d2c upstream.
At least on the HP Envy x360 15-cp0xxx model the WMI interface
for HPWMI_FEATURE2_QUERY requires an outsize of at least 128 bytes,
otherwise it fails with an error code 5 (HPWMI_RET_INVALID_PARAMETERS):
Dec 06 00:59:38 kernel: hp_wmi: query 0xd returned error 0x5
We do not care about the contents of the buffer, we just want to know
if the HPWMI_FEATURE2_QUERY command is supported.
This commits bumps the buffer size, fixing the error.
Fixes: 8a1513b4932 ("hp-wmi: limit hotkey enable")
BugLink: https://bugzilla.redhat.com/show_bug.cgi?id=1520703
Signed-off-by: Hans de Goede <[email protected]>
Signed-off-by: Andy Shevchenko <[email protected]>
[bwh: Backported to 3.16: adjust context]
Signed-off-by: Ben Hutchings <[email protected]>
---
drivers/platform/x86/hp-wmi.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/platform/x86/hp-wmi.c
+++ b/drivers/platform/x86/hp-wmi.c
@@ -309,7 +309,7 @@ static int __init hp_wmi_bios_2008_later
static int __init hp_wmi_bios_2009_later(void)
{
- int state = 0;
+ u8 state[128];
int ret = hp_wmi_perform_query(HPWMI_FEATURE2_QUERY, 0, &state,
sizeof(state), sizeof(state));
if (!ret)
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Heikki Krogerus <[email protected]>
commit 8f8983a5683623b62b339d159573f95a1fce44f3 upstream.
Intel Gemini Lake SoC has the same DWC3 than Broxton. Add
the new ID to the supported Devices.
Signed-off-by: Heikki Krogerus <[email protected]>
Signed-off-by: Felipe Balbi <[email protected]>
[bwh: Backported to 3.16: adjust context, indentation]
Signed-off-by: Ben Hutchings <[email protected]>
---
drivers/usb/dwc3/dwc3-pci.c | 2 ++
1 file changed, 2 insertions(+)
--- a/drivers/usb/dwc3/dwc3-pci.c
+++ b/drivers/usb/dwc3/dwc3-pci.c
@@ -37,6 +37,7 @@
#define PCI_DEVICE_ID_INTEL_BXT_M 0x1aaa
#define PCI_DEVICE_ID_INTEL_APL 0x5aaa
#define PCI_DEVICE_ID_INTEL_KBP 0xa2b0
+#define PCI_DEVICE_ID_INTEL_GLK 0x31aa
struct dwc3_pci {
struct device *dev;
@@ -199,6 +200,7 @@ static const struct pci_device_id dwc3_p
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BXT_M), },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_APL), },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_KBP), },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_GLK), },
{ } /* Terminating Entry */
};
MODULE_DEVICE_TABLE(pci, dwc3_pci_id_table);
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Jiri Slaby <[email protected]>
commit 4b70dd57a15d2f4685ac6e38056bad93e81e982f upstream.
We need to nest the console lock in sel_lock, so we have to push it down
a bit. Fortunately, the callers of set_selection_* just lock the console
lock around the function call. So moving it down is easy.
In the next patch, we switch the order.
Signed-off-by: Jiri Slaby <[email protected]>
Fixes: 07e6124a1a46 ("vt: selection, close sel_buffer race")
Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Greg Kroah-Hartman <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
drivers/tty/vt/selection.c | 13 ++++++++++++-
drivers/tty/vt/vt.c | 2 --
2 files changed, 12 insertions(+), 3 deletions(-)
--- a/drivers/tty/vt/selection.c
+++ b/drivers/tty/vt/selection.c
@@ -158,7 +158,7 @@ static int store_utf8(u16 c, char *p)
* The entire selection process is managed under the console_lock. It's
* a lot under the lock but its hardly a performance path
*/
-int set_selection(const struct tiocl_selection __user *sel, struct tty_struct *tty)
+static int __set_selection(const struct tiocl_selection __user *sel, struct tty_struct *tty)
{
struct vc_data *vc = vc_cons[fg_console].d;
int sel_mode, new_sel_start, new_sel_end, spc;
@@ -334,6 +334,17 @@ unlock:
return ret;
}
+int set_selection(const struct tiocl_selection __user *v, struct tty_struct *tty)
+{
+ int ret;
+
+ console_lock();
+ ret = __set_selection(v, tty);
+ console_unlock();
+
+ return ret;
+}
+
/* Insert the contents of the selection buffer into the
* queue of the tty associated with the current console.
* Invoked by ioctl().
--- a/drivers/tty/vt/vt.c
+++ b/drivers/tty/vt/vt.c
@@ -2670,9 +2670,7 @@ int tioclinux(struct tty_struct *tty, un
switch (type)
{
case TIOCL_SETSEL:
- console_lock();
ret = set_selection((struct tiocl_selection __user *)(p+1), tty);
- console_unlock();
break;
case TIOCL_PASTESEL:
ret = paste_selection(tty);
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Peter Hurley <[email protected]>
commit 61e86cc90af49cecef9c54ccea1f572fbcb695ac upstream.
Pasting text with gpm on a VC produced warning [1]. Reset task state
to TASK_RUNNING in the paste_selection() loop, if the loop did not
sleep.
[1]
WARNING: CPU: 6 PID: 1960 at /home/peter/src/kernels/mainline/kernel/sched/core.c:7286 __might_sleep+0x7f/0x90()
do not call blocking ops when !TASK_RUNNING; state=1 set at [<ffffffff8151805e>] paste_selection+0x9e/0x1a0
Modules linked in: btrfs xor raid6_pq ufs qnx4 hfsplus hfs minix ntfs msdos jfs xfs libcrc32c .....
CPU: 6 PID: 1960 Comm: gpm Not tainted 4.1.0-rc7+tty-xeon+debug #rc7+tty
Hardware name: Dell Inc. Precision WorkStation T5400 /0RW203, BIOS A11 04/30/2012
ffffffff81c9c0a0 ffff8802b0fd3ac8 ffffffff8185778a 0000000000000001
ffff8802b0fd3b18 ffff8802b0fd3b08 ffffffff8108039a ffffffff82ae8510
ffffffff81c9ce00 0000000000000015 0000000000000000 0000000000000000
Call Trace:
[<ffffffff8185778a>] dump_stack+0x4f/0x7b
[<ffffffff8108039a>] warn_slowpath_common+0x8a/0xc0
[<ffffffff81080416>] warn_slowpath_fmt+0x46/0x50
[<ffffffff810ddced>] ? __lock_acquire+0xe2d/0x13a0
[<ffffffff8151805e>] ? paste_selection+0x9e/0x1a0
[<ffffffff8151805e>] ? paste_selection+0x9e/0x1a0
[<ffffffff810ad4ff>] __might_sleep+0x7f/0x90
[<ffffffff8185f76a>] down_read+0x2a/0xa0
[<ffffffff810bb1d8>] ? sched_clock_cpu+0xb8/0xe0
[<ffffffff8150d1dc>] n_tty_receive_buf_common+0x4c/0xba0
[<ffffffff810dc875>] ? mark_held_locks+0x75/0xa0
[<ffffffff81861c95>] ? _raw_spin_unlock_irqrestore+0x65/0x80
[<ffffffff810b49a1>] ? get_parent_ip+0x11/0x50
[<ffffffff8150dd44>] n_tty_receive_buf2+0x14/0x20
[<ffffffff81518117>] paste_selection+0x157/0x1a0
[<ffffffff810b77b0>] ? wake_up_state+0x20/0x20
[<ffffffff815203f8>] tioclinux+0xb8/0x2c0
[<ffffffff81515bfe>] vt_ioctl+0xaee/0x11a0
[<ffffffff810baf75>] ? sched_clock_local+0x25/0x90
[<ffffffff810bbe11>] ? vtime_account_user+0x91/0xa0
[<ffffffff8150810c>] tty_ioctl+0x20c/0xe20
[<ffffffff810bbe11>] ? vtime_account_user+0x91/0xa0
[<ffffffff810b49a1>] ? get_parent_ip+0x11/0x50
[<ffffffff810b4a69>] ? preempt_count_sub+0x49/0x50
[<ffffffff811ab71c>] ? context_tracking_exit+0x5c/0x290
[<ffffffff811ab71c>] ? context_tracking_exit+0x5c/0x290
[<ffffffff81248b98>] do_vfs_ioctl+0x318/0x570
[<ffffffff810dca8d>] ? trace_hardirqs_on+0xd/0x10
[<ffffffff810dc9b5>] ? trace_hardirqs_on_caller+0x115/0x1e0
[<ffffffff81254acc>] ? __fget_light+0x6c/0xa0
[<ffffffff81248e71>] SyS_ioctl+0x81/0xa0
[<ffffffff81862832>] system_call_fastpath+0x16/0x7a
Signed-off-by: Peter Hurley <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
drivers/tty/vt/selection.c | 1 +
1 file changed, 1 insertion(+)
--- a/drivers/tty/vt/selection.c
+++ b/drivers/tty/vt/selection.c
@@ -356,6 +356,7 @@ int paste_selection(struct tty_struct *t
schedule();
continue;
}
+ __set_current_state(TASK_RUNNING);
count = sel_buffer_lth - pasted;
count = tty_ldisc_receive_buf(ld, sel_buffer + pasted, NULL,
count);
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Jiri Slaby <[email protected]>
commit 687bff0cd08f790d540cfb7b2349f0d876cdddec upstream.
When pasting a selection to a vt, the task is set as INTERRUPTIBLE while
waiting for a tty to unthrottle. But signals are not handled at all.
Normally, this is not a problem as tty_ldisc_receive_buf receives all
the goods and a user has no reason to interrupt the task.
There are two scenarios where this matters:
1) when the tty is throttled and a signal is sent to the process, it
spins on a CPU until the tty is unthrottled. schedule() does not
really echedule, but returns immediately, of course.
2) when the sel_buffer becomes invalid, KASAN prevents any reads from it
and the loop simply does not proceed and spins forever (causing the
tty to throttle, but the code never sleeps, the same as above). This
sometimes happens as there is a race in the sel_buffer handling code.
So add signal handling to this ioctl (TIOCL_PASTESEL) and return -EINTR
in case a signal is pending.
Signed-off-by: Jiri Slaby <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Greg Kroah-Hartman <[email protected]>
[bwh: Backported to 3.16:
- No need to include <linux/sched/signal.h>
- Adjust context]
Signed-off-by: Ben Hutchings <[email protected]>
---
--- a/drivers/tty/vt/selection.c
+++ b/drivers/tty/vt/selection.c
@@ -341,6 +341,7 @@ int paste_selection(struct tty_struct *t
unsigned int count;
struct tty_ldisc *ld;
DECLARE_WAITQUEUE(wait, current);
+ int ret = 0;
console_lock();
poke_blanked_console();
@@ -352,6 +353,10 @@ int paste_selection(struct tty_struct *t
add_wait_queue(&vc->paste_wait, &wait);
while (sel_buffer && sel_buffer_lth > pasted) {
set_current_state(TASK_INTERRUPTIBLE);
+ if (signal_pending(current)) {
+ ret = -EINTR;
+ break;
+ }
if (test_bit(TTY_THROTTLED, &tty->flags)) {
schedule();
continue;
@@ -367,5 +372,5 @@ int paste_selection(struct tty_struct *t
tty_buffer_unlock_exclusive(&vc->port);
tty_ldisc_deref(ld);
- return 0;
+ return ret;
}
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Vladis Dronov <[email protected]>
commit 75718584cb3c64e6269109d4d54f888ac5a5fd15 upstream.
There is a bug in ptp_clock_unregister(), where ptp_cleanup_pin_groups()
first frees ptp->pin_{,dev_}attr, but then posix_clock_unregister() needs
them to destroy a related sysfs device.
These functions can not be just swapped, as posix_clock_unregister() frees
ptp which is needed in the ptp_cleanup_pin_groups(). Fix this by calling
ptp_cleanup_pin_groups() in ptp_clock_release(), right before ptp is freed.
This makes this patch fix an UAF bug in a patch which fixes an UAF bug.
Reported-by: Antti Laakso <[email protected]>
Fixes: a33121e5487b ("ptp: fix the race between the release of ptp_clock and cdev")
Link: https://lore.kernel.org/netdev/[email protected]/
Signed-off-by: Vladis Dronov <[email protected]>
Acked-by: Richard Cochran <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
drivers/ptp/ptp_clock.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
--- a/drivers/ptp/ptp_clock.c
+++ b/drivers/ptp/ptp_clock.c
@@ -171,6 +171,7 @@ static void ptp_clock_release(struct dev
{
struct ptp_clock *ptp = container_of(dev, struct ptp_clock, dev);
+ ptp_cleanup_pin_groups(ptp);
mutex_destroy(&ptp->tsevq_mux);
mutex_destroy(&ptp->pincfg_mux);
ida_simple_remove(&ptp_clocks_map, ptp->index);
@@ -271,9 +272,8 @@ int ptp_clock_unregister(struct ptp_cloc
if (ptp->pps_source)
pps_unregister_source(ptp->pps_source);
- ptp_cleanup_pin_groups(ptp);
-
posix_clock_unregister(&ptp->clock);
+
return 0;
}
EXPORT_SYMBOL(ptp_clock_unregister);
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Jan Kara <[email protected]>
commit c780e86dd48ef6467a1146cf7d0fe1e05a635039 upstream.
KASAN is reporting that __blk_add_trace() has a use-after-free issue
when accessing q->blk_trace. Indeed the switching of block tracing (and
thus eventual freeing of q->blk_trace) is completely unsynchronized with
the currently running tracing and thus it can happen that the blk_trace
structure is being freed just while __blk_add_trace() works on it.
Protect accesses to q->blk_trace by RCU during tracing and make sure we
wait for the end of RCU grace period when shutting down tracing. Luckily
that is rare enough event that we can afford that. Note that postponing
the freeing of blk_trace to an RCU callback should better be avoided as
it could have unexpected user visible side-effects as debugfs files
would be still existing for a short while block tracing has been shut
down.
Link: https://bugzilla.kernel.org/show_bug.cgi?id=205711
Reviewed-by: Chaitanya Kulkarni <[email protected]>
Reviewed-by: Ming Lei <[email protected]>
Tested-by: Ming Lei <[email protected]>
Reviewed-by: Bart Van Assche <[email protected]>
Reported-by: Tristan Madani <[email protected]>
Signed-off-by: Jan Kara <[email protected]>
Signed-off-by: Jens Axboe <[email protected]>
[bwh: Backported to 3.16:
- Drop changes in blk_trace_note_message_enabled(), blk_trace_bio_get_cgid()
- Adjust context]
Signed-off-by: Ben Hutchings <[email protected]>
---
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -447,7 +447,7 @@ struct request_queue {
unsigned int sg_reserved_size;
int node;
#ifdef CONFIG_BLK_DEV_IO_TRACE
- struct blk_trace *blk_trace;
+ struct blk_trace __rcu *blk_trace;
struct mutex blk_trace_mutex;
#endif
/*
--- a/include/linux/blktrace_api.h
+++ b/include/linux/blktrace_api.h
@@ -51,9 +51,13 @@ void __trace_note_message(struct blk_tra
**/
#define blk_add_trace_msg(q, fmt, ...) \
do { \
- struct blk_trace *bt = (q)->blk_trace; \
+ struct blk_trace *bt; \
+ \
+ rcu_read_lock(); \
+ bt = rcu_dereference((q)->blk_trace); \
if (unlikely(bt)) \
__trace_note_message(bt, fmt, ##__VA_ARGS__); \
+ rcu_read_unlock(); \
} while (0)
#define BLK_TN_MAX_MSG 128
--- a/kernel/trace/blktrace.c
+++ b/kernel/trace/blktrace.c
@@ -302,6 +302,7 @@ static void blk_trace_free(struct blk_tr
static void blk_trace_cleanup(struct blk_trace *bt)
{
+ synchronize_rcu();
blk_trace_free(bt);
if (atomic_dec_and_test(&blk_probes_ref))
blk_unregister_tracepoints();
@@ -616,8 +617,10 @@ static int compat_blk_trace_setup(struct
static int __blk_trace_startstop(struct request_queue *q, int start)
{
int ret;
- struct blk_trace *bt = q->blk_trace;
+ struct blk_trace *bt;
+ bt = rcu_dereference_protected(q->blk_trace,
+ lockdep_is_held(&q->blk_trace_mutex));
if (bt == NULL)
return -EINVAL;
@@ -726,8 +729,8 @@ int blk_trace_ioctl(struct block_device
void blk_trace_shutdown(struct request_queue *q)
{
mutex_lock(&q->blk_trace_mutex);
-
- if (q->blk_trace) {
+ if (rcu_dereference_protected(q->blk_trace,
+ lockdep_is_held(&q->blk_trace_mutex))) {
__blk_trace_startstop(q, 0);
__blk_trace_remove(q);
}
@@ -753,10 +756,14 @@ void blk_trace_shutdown(struct request_q
static void blk_add_trace_rq(struct request_queue *q, struct request *rq,
unsigned int nr_bytes, u32 what)
{
- struct blk_trace *bt = q->blk_trace;
+ struct blk_trace *bt;
- if (likely(!bt))
+ rcu_read_lock();
+ bt = rcu_dereference(q->blk_trace);
+ if (likely(!bt)) {
+ rcu_read_unlock();
return;
+ }
if (rq->cmd_type == REQ_TYPE_BLOCK_PC) {
what |= BLK_TC_ACT(BLK_TC_PC);
@@ -767,6 +774,7 @@ static void blk_add_trace_rq(struct requ
__blk_add_trace(bt, blk_rq_pos(rq), nr_bytes,
rq->cmd_flags, what, rq->errors, 0, NULL);
}
+ rcu_read_unlock();
}
static void blk_add_trace_rq_abort(void *ignore,
@@ -816,16 +824,21 @@ static void blk_add_trace_rq_complete(vo
static void blk_add_trace_bio(struct request_queue *q, struct bio *bio,
u32 what, int error)
{
- struct blk_trace *bt = q->blk_trace;
+ struct blk_trace *bt;
- if (likely(!bt))
+ rcu_read_lock();
+ bt = rcu_dereference(q->blk_trace);
+ if (likely(!bt)) {
+ rcu_read_unlock();
return;
+ }
if (!error && !bio_flagged(bio, BIO_UPTODATE))
error = EIO;
__blk_add_trace(bt, bio->bi_iter.bi_sector, bio->bi_iter.bi_size,
bio->bi_rw, what, error, 0, NULL);
+ rcu_read_unlock();
}
static void blk_add_trace_bio_bounce(void *ignore,
@@ -870,10 +883,13 @@ static void blk_add_trace_getrq(void *ig
if (bio)
blk_add_trace_bio(q, bio, BLK_TA_GETRQ, 0);
else {
- struct blk_trace *bt = q->blk_trace;
+ struct blk_trace *bt;
+ rcu_read_lock();
+ bt = rcu_dereference(q->blk_trace);
if (bt)
__blk_add_trace(bt, 0, 0, rw, BLK_TA_GETRQ, 0, 0, NULL);
+ rcu_read_unlock();
}
}
@@ -885,27 +901,35 @@ static void blk_add_trace_sleeprq(void *
if (bio)
blk_add_trace_bio(q, bio, BLK_TA_SLEEPRQ, 0);
else {
- struct blk_trace *bt = q->blk_trace;
+ struct blk_trace *bt;
+ rcu_read_lock();
+ bt = rcu_dereference(q->blk_trace);
if (bt)
__blk_add_trace(bt, 0, 0, rw, BLK_TA_SLEEPRQ,
0, 0, NULL);
+ rcu_read_unlock();
}
}
static void blk_add_trace_plug(void *ignore, struct request_queue *q)
{
- struct blk_trace *bt = q->blk_trace;
+ struct blk_trace *bt;
+ rcu_read_lock();
+ bt = rcu_dereference(q->blk_trace);
if (bt)
__blk_add_trace(bt, 0, 0, 0, BLK_TA_PLUG, 0, 0, NULL);
+ rcu_read_unlock();
}
static void blk_add_trace_unplug(void *ignore, struct request_queue *q,
unsigned int depth, bool explicit)
{
- struct blk_trace *bt = q->blk_trace;
+ struct blk_trace *bt;
+ rcu_read_lock();
+ bt = rcu_dereference(q->blk_trace);
if (bt) {
__be64 rpdu = cpu_to_be64(depth);
u32 what;
@@ -917,14 +941,17 @@ static void blk_add_trace_unplug(void *i
__blk_add_trace(bt, 0, 0, 0, what, 0, sizeof(rpdu), &rpdu);
}
+ rcu_read_unlock();
}
static void blk_add_trace_split(void *ignore,
struct request_queue *q, struct bio *bio,
unsigned int pdu)
{
- struct blk_trace *bt = q->blk_trace;
+ struct blk_trace *bt;
+ rcu_read_lock();
+ bt = rcu_dereference(q->blk_trace);
if (bt) {
__be64 rpdu = cpu_to_be64(pdu);
@@ -933,6 +960,7 @@ static void blk_add_trace_split(void *ig
!bio_flagged(bio, BIO_UPTODATE),
sizeof(rpdu), &rpdu);
}
+ rcu_read_unlock();
}
/**
@@ -952,11 +980,15 @@ static void blk_add_trace_bio_remap(void
struct request_queue *q, struct bio *bio,
dev_t dev, sector_t from)
{
- struct blk_trace *bt = q->blk_trace;
+ struct blk_trace *bt;
struct blk_io_trace_remap r;
- if (likely(!bt))
+ rcu_read_lock();
+ bt = rcu_dereference(q->blk_trace);
+ if (likely(!bt)) {
+ rcu_read_unlock();
return;
+ }
r.device_from = cpu_to_be32(dev);
r.device_to = cpu_to_be32(bio->bi_bdev->bd_dev);
@@ -965,6 +997,7 @@ static void blk_add_trace_bio_remap(void
__blk_add_trace(bt, bio->bi_iter.bi_sector, bio->bi_iter.bi_size,
bio->bi_rw, BLK_TA_REMAP,
!bio_flagged(bio, BIO_UPTODATE), sizeof(r), &r);
+ rcu_read_unlock();
}
/**
@@ -985,11 +1018,15 @@ static void blk_add_trace_rq_remap(void
struct request *rq, dev_t dev,
sector_t from)
{
- struct blk_trace *bt = q->blk_trace;
+ struct blk_trace *bt;
struct blk_io_trace_remap r;
- if (likely(!bt))
+ rcu_read_lock();
+ bt = rcu_dereference(q->blk_trace);
+ if (likely(!bt)) {
+ rcu_read_unlock();
return;
+ }
r.device_from = cpu_to_be32(dev);
r.device_to = cpu_to_be32(disk_devt(rq->rq_disk));
@@ -998,6 +1035,7 @@ static void blk_add_trace_rq_remap(void
__blk_add_trace(bt, blk_rq_pos(rq), blk_rq_bytes(rq),
rq_data_dir(rq), BLK_TA_REMAP, !!rq->errors,
sizeof(r), &r);
+ rcu_read_unlock();
}
/**
@@ -1015,10 +1053,14 @@ void blk_add_driver_data(struct request_
struct request *rq,
void *data, size_t len)
{
- struct blk_trace *bt = q->blk_trace;
+ struct blk_trace *bt;
- if (likely(!bt))
+ rcu_read_lock();
+ bt = rcu_dereference(q->blk_trace);
+ if (likely(!bt)) {
+ rcu_read_unlock();
return;
+ }
if (rq->cmd_type == REQ_TYPE_BLOCK_PC)
__blk_add_trace(bt, 0, blk_rq_bytes(rq), 0,
@@ -1026,6 +1068,7 @@ void blk_add_driver_data(struct request_
else
__blk_add_trace(bt, blk_rq_pos(rq), blk_rq_bytes(rq), 0,
BLK_TA_DRV_DATA, rq->errors, len, data);
+ rcu_read_unlock();
}
EXPORT_SYMBOL_GPL(blk_add_driver_data);
@@ -1537,6 +1580,7 @@ static int blk_trace_remove_queue(struct
spin_lock_irq(&running_trace_lock);
list_del(&bt->running_list);
spin_unlock_irq(&running_trace_lock);
+ synchronize_rcu();
blk_trace_free(bt);
return 0;
}
@@ -1698,6 +1742,7 @@ static ssize_t sysfs_blk_trace_attr_show
struct hd_struct *p = dev_to_part(dev);
struct request_queue *q;
struct block_device *bdev;
+ struct blk_trace *bt;
ssize_t ret = -ENXIO;
bdev = bdget(part_devt(p));
@@ -1710,21 +1755,23 @@ static ssize_t sysfs_blk_trace_attr_show
mutex_lock(&q->blk_trace_mutex);
+ bt = rcu_dereference_protected(q->blk_trace,
+ lockdep_is_held(&q->blk_trace_mutex));
if (attr == &dev_attr_enable) {
- ret = sprintf(buf, "%u\n", !!q->blk_trace);
+ ret = sprintf(buf, "%u\n", !!bt);
goto out_unlock_bdev;
}
- if (q->blk_trace == NULL)
+ if (bt == NULL)
ret = sprintf(buf, "disabled\n");
else if (attr == &dev_attr_act_mask)
- ret = blk_trace_mask2str(buf, q->blk_trace->act_mask);
+ ret = blk_trace_mask2str(buf, bt->act_mask);
else if (attr == &dev_attr_pid)
- ret = sprintf(buf, "%u\n", q->blk_trace->pid);
+ ret = sprintf(buf, "%u\n", bt->pid);
else if (attr == &dev_attr_start_lba)
- ret = sprintf(buf, "%llu\n", q->blk_trace->start_lba);
+ ret = sprintf(buf, "%llu\n", bt->start_lba);
else if (attr == &dev_attr_end_lba)
- ret = sprintf(buf, "%llu\n", q->blk_trace->end_lba);
+ ret = sprintf(buf, "%llu\n", bt->end_lba);
out_unlock_bdev:
mutex_unlock(&q->blk_trace_mutex);
@@ -1741,6 +1788,7 @@ static ssize_t sysfs_blk_trace_attr_stor
struct block_device *bdev;
struct request_queue *q;
struct hd_struct *p;
+ struct blk_trace *bt;
u64 value;
ssize_t ret = -EINVAL;
@@ -1771,8 +1819,10 @@ static ssize_t sysfs_blk_trace_attr_stor
mutex_lock(&q->blk_trace_mutex);
+ bt = rcu_dereference_protected(q->blk_trace,
+ lockdep_is_held(&q->blk_trace_mutex));
if (attr == &dev_attr_enable) {
- if (!!value == !!q->blk_trace) {
+ if (!!value == !!bt) {
ret = 0;
goto out_unlock_bdev;
}
@@ -1784,18 +1834,18 @@ static ssize_t sysfs_blk_trace_attr_stor
}
ret = 0;
- if (q->blk_trace == NULL)
+ if (bt == NULL)
ret = blk_trace_setup_queue(q, bdev);
if (ret == 0) {
if (attr == &dev_attr_act_mask)
- q->blk_trace->act_mask = value;
+ bt->act_mask = value;
else if (attr == &dev_attr_pid)
- q->blk_trace->pid = value;
+ bt->pid = value;
else if (attr == &dev_attr_start_lba)
- q->blk_trace->start_lba = value;
+ bt->start_lba = value;
else if (attr == &dev_attr_end_lba)
- q->blk_trace->end_lba = value;
+ bt->end_lba = value;
}
out_unlock_bdev:
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Richard Palethorpe <[email protected]>
commit 0ace17d56824165c7f4c68785d6b58971db954dd upstream.
write_wakeup can happen in parallel with close/hangup where tty->disc_data
is set to NULL and the netdevice is freed thus also freeing
disc_data. write_wakeup accesses disc_data so we must prevent close from
freeing the netdev while write_wakeup has a non-NULL view of
tty->disc_data.
We also need to make sure that accesses to disc_data are atomic. Which can
all be done with RCU.
This problem was found by Syzkaller on SLCAN, but the same issue is
reproducible with the SLIP line discipline using an LTP test based on the
Syzkaller reproducer.
A fix which didn't use RCU was posted by Hillf Danton.
Fixes: 661f7fda21b1 ("slip: Fix deadlock in write_wakeup")
Fixes: a8e83b17536a ("slcan: Port write_wakeup deadlock fix from slip")
Reported-by: [email protected]
Signed-off-by: Richard Palethorpe <[email protected]>
Cc: Wolfgang Grandegger <[email protected]>
Cc: Marc Kleine-Budde <[email protected]>
Cc: "David S. Miller" <[email protected]>
Cc: Tyler Hall <[email protected]>
Cc: [email protected]
Cc: [email protected]
Cc: [email protected]
Cc: [email protected]
Signed-off-by: David S. Miller <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
drivers/net/can/slcan.c | 12 ++++++++++--
drivers/net/slip/slip.c | 12 ++++++++++--
2 files changed, 20 insertions(+), 4 deletions(-)
--- a/drivers/net/can/slcan.c
+++ b/drivers/net/can/slcan.c
@@ -346,9 +346,16 @@ static void slcan_transmit(struct work_s
*/
static void slcan_write_wakeup(struct tty_struct *tty)
{
- struct slcan *sl = tty->disc_data;
+ struct slcan *sl;
+
+ rcu_read_lock();
+ sl = rcu_dereference(tty->disc_data);
+ if (!sl)
+ goto out;
schedule_work(&sl->tx_work);
+out:
+ rcu_read_unlock();
}
/* Send a can_frame to a TTY queue. */
@@ -640,10 +647,11 @@ static void slcan_close(struct tty_struc
return;
spin_lock_bh(&sl->lock);
- tty->disc_data = NULL;
+ rcu_assign_pointer(tty->disc_data, NULL);
sl->tty = NULL;
spin_unlock_bh(&sl->lock);
+ synchronize_rcu();
flush_work(&sl->tx_work);
/* Flush network side */
--- a/drivers/net/slip/slip.c
+++ b/drivers/net/slip/slip.c
@@ -452,9 +452,16 @@ static void slip_transmit(struct work_st
*/
static void slip_write_wakeup(struct tty_struct *tty)
{
- struct slip *sl = tty->disc_data;
+ struct slip *sl;
+
+ rcu_read_lock();
+ sl = rcu_dereference(tty->disc_data);
+ if (!sl)
+ goto out;
schedule_work(&sl->tx_work);
+out:
+ rcu_read_unlock();
}
static void sl_tx_timeout(struct net_device *dev)
@@ -885,10 +892,11 @@ static void slip_close(struct tty_struct
return;
spin_lock_bh(&sl->lock);
- tty->disc_data = NULL;
+ rcu_assign_pointer(tty->disc_data, NULL);
sl->tty = NULL;
spin_unlock_bh(&sl->lock);
+ synchronize_rcu();
flush_work(&sl->tx_work);
/* VSV = very important to remove timers */
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Mauro Carvalho Chehab <[email protected]>
commit 163f1e93e995048b894c5fc86a6034d16beed740 upstream.
Along all media controller code, "mdev" is used to represent
a pointer to struct media_device, and "devnode" for a pointer
to struct media_devnode.
However, inside media-devnode.[ch], "mdev" is used to represent
a pointer to struct media_devnode.
This is very confusing and may lead to development errors.
So, let's change all occurrences at media-devnode.[ch] to
also use "devnode" for such pointers.
This patch doesn't make any functional changes.
Signed-off-by: Mauro Carvalho Chehab <[email protected]>
Signed-off-by: Mauro Carvalho Chehab <[email protected]>
[bwh: Backported to 3.16: adjust filename, context]
Signed-off-by: Ben Hutchings <[email protected]>
---
drivers/media/media-devnode.c | 110 +++++++++++++++++-----------------
include/media/media-devnode.h | 16 ++---
2 files changed, 63 insertions(+), 63 deletions(-)
--- a/drivers/media/media-devnode.c
+++ b/drivers/media/media-devnode.c
@@ -59,21 +59,21 @@ static DECLARE_BITMAP(media_devnode_nums
/* Called when the last user of the media device exits. */
static void media_devnode_release(struct device *cd)
{
- struct media_devnode *mdev = to_media_devnode(cd);
+ struct media_devnode *devnode = to_media_devnode(cd);
mutex_lock(&media_devnode_lock);
/* Delete the cdev on this minor as well */
- cdev_del(&mdev->cdev);
+ cdev_del(&devnode->cdev);
/* Mark device node number as free */
- clear_bit(mdev->minor, media_devnode_nums);
+ clear_bit(devnode->minor, media_devnode_nums);
mutex_unlock(&media_devnode_lock);
/* Release media_devnode and perform other cleanups as needed. */
- if (mdev->release)
- mdev->release(mdev);
+ if (devnode->release)
+ devnode->release(devnode);
}
static struct bus_type media_bus_type = {
@@ -83,37 +83,37 @@ static struct bus_type media_bus_type =
static ssize_t media_read(struct file *filp, char __user *buf,
size_t sz, loff_t *off)
{
- struct media_devnode *mdev = media_devnode_data(filp);
+ struct media_devnode *devnode = media_devnode_data(filp);
- if (!mdev->fops->read)
+ if (!devnode->fops->read)
return -EINVAL;
- if (!media_devnode_is_registered(mdev))
+ if (!media_devnode_is_registered(devnode))
return -EIO;
- return mdev->fops->read(filp, buf, sz, off);
+ return devnode->fops->read(filp, buf, sz, off);
}
static ssize_t media_write(struct file *filp, const char __user *buf,
size_t sz, loff_t *off)
{
- struct media_devnode *mdev = media_devnode_data(filp);
+ struct media_devnode *devnode = media_devnode_data(filp);
- if (!mdev->fops->write)
+ if (!devnode->fops->write)
return -EINVAL;
- if (!media_devnode_is_registered(mdev))
+ if (!media_devnode_is_registered(devnode))
return -EIO;
- return mdev->fops->write(filp, buf, sz, off);
+ return devnode->fops->write(filp, buf, sz, off);
}
static unsigned int media_poll(struct file *filp,
struct poll_table_struct *poll)
{
- struct media_devnode *mdev = media_devnode_data(filp);
+ struct media_devnode *devnode = media_devnode_data(filp);
- if (!media_devnode_is_registered(mdev))
+ if (!media_devnode_is_registered(devnode))
return POLLERR | POLLHUP;
- if (!mdev->fops->poll)
+ if (!devnode->fops->poll)
return DEFAULT_POLLMASK;
- return mdev->fops->poll(filp, poll);
+ return devnode->fops->poll(filp, poll);
}
static long
@@ -121,12 +121,12 @@ __media_ioctl(struct file *filp, unsigne
long (*ioctl_func)(struct file *filp, unsigned int cmd,
unsigned long arg))
{
- struct media_devnode *mdev = media_devnode_data(filp);
+ struct media_devnode *devnode = media_devnode_data(filp);
if (!ioctl_func)
return -ENOTTY;
- if (!media_devnode_is_registered(mdev))
+ if (!media_devnode_is_registered(devnode))
return -EIO;
return ioctl_func(filp, cmd, arg);
@@ -134,9 +134,9 @@ __media_ioctl(struct file *filp, unsigne
static long media_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
- struct media_devnode *mdev = media_devnode_data(filp);
+ struct media_devnode *devnode = media_devnode_data(filp);
- return __media_ioctl(filp, cmd, arg, mdev->fops->ioctl);
+ return __media_ioctl(filp, cmd, arg, devnode->fops->ioctl);
}
#ifdef CONFIG_COMPAT
@@ -144,9 +144,9 @@ static long media_ioctl(struct file *fil
static long media_compat_ioctl(struct file *filp, unsigned int cmd,
unsigned long arg)
{
- struct media_devnode *mdev = media_devnode_data(filp);
+ struct media_devnode *devnode = media_devnode_data(filp);
- return __media_ioctl(filp, cmd, arg, mdev->fops->compat_ioctl);
+ return __media_ioctl(filp, cmd, arg, devnode->fops->compat_ioctl);
}
#endif /* CONFIG_COMPAT */
@@ -154,7 +154,7 @@ static long media_compat_ioctl(struct fi
/* Override for the open function */
static int media_open(struct inode *inode, struct file *filp)
{
- struct media_devnode *mdev;
+ struct media_devnode *devnode;
int ret;
/* Check if the media device is available. This needs to be done with
@@ -164,23 +164,23 @@ static int media_open(struct inode *inod
* a crash.
*/
mutex_lock(&media_devnode_lock);
- mdev = container_of(inode->i_cdev, struct media_devnode, cdev);
+ devnode = container_of(inode->i_cdev, struct media_devnode, cdev);
/* return ENXIO if the media device has been removed
already or if it is not registered anymore. */
- if (!media_devnode_is_registered(mdev)) {
+ if (!media_devnode_is_registered(devnode)) {
mutex_unlock(&media_devnode_lock);
return -ENXIO;
}
/* and increase the device refcount */
- get_device(&mdev->dev);
+ get_device(&devnode->dev);
mutex_unlock(&media_devnode_lock);
- filp->private_data = mdev;
+ filp->private_data = devnode;
- if (mdev->fops->open) {
- ret = mdev->fops->open(filp);
+ if (devnode->fops->open) {
+ ret = devnode->fops->open(filp);
if (ret) {
- put_device(&mdev->dev);
+ put_device(&devnode->dev);
filp->private_data = NULL;
return ret;
}
@@ -192,16 +192,16 @@ static int media_open(struct inode *inod
/* Override for the release function */
static int media_release(struct inode *inode, struct file *filp)
{
- struct media_devnode *mdev = media_devnode_data(filp);
+ struct media_devnode *devnode = media_devnode_data(filp);
- if (mdev->fops->release)
- mdev->fops->release(filp);
+ if (devnode->fops->release)
+ devnode->fops->release(filp);
filp->private_data = NULL;
/* decrease the refcount unconditionally since the release()
return value is ignored. */
- put_device(&mdev->dev);
+ put_device(&devnode->dev);
return 0;
}
@@ -221,7 +221,7 @@ static const struct file_operations medi
/**
* media_devnode_register - register a media device node
- * @mdev: media device node structure we want to register
+ * @devnode: media device node structure we want to register
*
* The registration code assigns minor numbers and registers the new device node
* with the kernel. An error is returned if no free minor number can be found,
@@ -233,7 +233,7 @@ static const struct file_operations medi
* the media_devnode structure is *not* called, so the caller is responsible for
* freeing any data.
*/
-int __must_check media_devnode_register(struct media_devnode *mdev,
+int __must_check media_devnode_register(struct media_devnode *devnode,
struct module *owner)
{
int minor;
@@ -251,40 +251,40 @@ int __must_check media_devnode_register(
set_bit(minor, media_devnode_nums);
mutex_unlock(&media_devnode_lock);
- mdev->minor = minor;
+ devnode->minor = minor;
/* Part 2: Initialize and register the character device */
- cdev_init(&mdev->cdev, &media_devnode_fops);
- mdev->cdev.owner = owner;
+ cdev_init(&devnode->cdev, &media_devnode_fops);
+ devnode->cdev.owner = owner;
- ret = cdev_add(&mdev->cdev, MKDEV(MAJOR(media_dev_t), mdev->minor), 1);
+ ret = cdev_add(&devnode->cdev, MKDEV(MAJOR(media_dev_t), devnode->minor), 1);
if (ret < 0) {
pr_err("%s: cdev_add failed\n", __func__);
goto error;
}
/* Part 3: Register the media device */
- mdev->dev.bus = &media_bus_type;
- mdev->dev.devt = MKDEV(MAJOR(media_dev_t), mdev->minor);
- mdev->dev.release = media_devnode_release;
- if (mdev->parent)
- mdev->dev.parent = mdev->parent;
- dev_set_name(&mdev->dev, "media%d", mdev->minor);
- ret = device_register(&mdev->dev);
+ devnode->dev.bus = &media_bus_type;
+ devnode->dev.devt = MKDEV(MAJOR(media_dev_t), devnode->minor);
+ devnode->dev.release = media_devnode_release;
+ if (devnode->parent)
+ devnode->dev.parent = devnode->parent;
+ dev_set_name(&devnode->dev, "media%d", devnode->minor);
+ ret = device_register(&devnode->dev);
if (ret < 0) {
pr_err("%s: device_register failed\n", __func__);
goto error;
}
/* Part 4: Activate this minor. The char device can now be used. */
- set_bit(MEDIA_FLAG_REGISTERED, &mdev->flags);
+ set_bit(MEDIA_FLAG_REGISTERED, &devnode->flags);
return 0;
error:
mutex_lock(&media_devnode_lock);
- cdev_del(&mdev->cdev);
- clear_bit(mdev->minor, media_devnode_nums);
+ cdev_del(&devnode->cdev);
+ clear_bit(devnode->minor, media_devnode_nums);
mutex_unlock(&media_devnode_lock);
return ret;
@@ -292,7 +292,7 @@ error:
/**
* media_devnode_unregister - unregister a media device node
- * @mdev: the device node to unregister
+ * @devnode: the device node to unregister
*
* This unregisters the passed device. Future open calls will be met with
* errors.
@@ -300,16 +300,16 @@ error:
* This function can safely be called if the device node has never been
* registered or has already been unregistered.
*/
-void media_devnode_unregister(struct media_devnode *mdev)
+void media_devnode_unregister(struct media_devnode *devnode)
{
- /* Check if mdev was ever registered at all */
- if (!media_devnode_is_registered(mdev))
+ /* Check if devnode was ever registered at all */
+ if (!media_devnode_is_registered(devnode))
return;
mutex_lock(&media_devnode_lock);
- clear_bit(MEDIA_FLAG_REGISTERED, &mdev->flags);
+ clear_bit(MEDIA_FLAG_REGISTERED, &devnode->flags);
mutex_unlock(&media_devnode_lock);
- device_unregister(&mdev->dev);
+ device_unregister(&devnode->dev);
}
/*
--- a/include/media/media-devnode.h
+++ b/include/media/media-devnode.h
@@ -76,24 +76,24 @@ struct media_devnode {
unsigned long flags; /* Use bitops to access flags */
/* callbacks */
- void (*release)(struct media_devnode *mdev);
+ void (*release)(struct media_devnode *devnode);
};
/* dev to media_devnode */
#define to_media_devnode(cd) container_of(cd, struct media_devnode, dev)
-int __must_check media_devnode_register(struct media_devnode *mdev,
+int __must_check media_devnode_register(struct media_devnode *devnode,
struct module *owner);
-void media_devnode_unregister(struct media_devnode *mdev);
+void media_devnode_unregister(struct media_devnode *devnode);
static inline struct media_devnode *media_devnode_data(struct file *filp)
{
return filp->private_data;
}
-static inline int media_devnode_is_registered(struct media_devnode *mdev)
+static inline int media_devnode_is_registered(struct media_devnode *devnode)
{
- return test_bit(MEDIA_FLAG_REGISTERED, &mdev->flags);
+ return test_bit(MEDIA_FLAG_REGISTERED, &devnode->flags);
}
#endif /* _MEDIA_DEVNODE_H */
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Max Kellermann <[email protected]>
commit bf244f665d76d20312c80524689b32a752888838 upstream.
Callbacks invoked from put_device() may free the struct media_devnode
pointer, so any cleanup needs to be done before put_device().
Signed-off-by: Max Kellermann <[email protected]>
Signed-off-by: Mauro Carvalho Chehab <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
drivers/media/media-devnode.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
--- a/drivers/media/media-devnode.c
+++ b/drivers/media/media-devnode.c
@@ -197,10 +197,11 @@ static int media_release(struct inode *i
if (mdev->fops->release)
mdev->fops->release(filp);
+ filp->private_data = NULL;
+
/* decrease the refcount unconditionally since the release()
return value is ignored. */
put_device(&mdev->dev);
- filp->private_data = NULL;
return 0;
}
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Shuah Khan <[email protected]>
commit d40ec6fdb0b03b7be4c7923a3da0e46bf943740a upstream.
Fix media_open() to clear filp->private_data when file open
fails.
Signed-off-by: Shuah Khan <[email protected]>
Acked-by: Sakari Ailus <[email protected]>
Signed-off-by: Mauro Carvalho Chehab <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
drivers/media/media-devnode.c | 1 +
1 file changed, 1 insertion(+)
--- a/drivers/media/media-devnode.c
+++ b/drivers/media/media-devnode.c
@@ -181,6 +181,7 @@ static int media_open(struct inode *inod
ret = mdev->fops->open(filp);
if (ret) {
put_device(&mdev->dev);
+ filp->private_data = NULL;
return ret;
}
}
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Keiya Nobuta <[email protected]>
commit 9c06ac4c83df6d6fbdbf7488fbad822b4002ba19 upstream.
If hub_activate() is called before D+ has stabilized after remote
wakeup, the following situation might occur:
__ ___________________
/ \ /
D+ __/ \__/
Hub _______________________________
| ^ ^ ^
| | | |
Host _____v__|___|___________|______
| | | |
| | | \-- Interrupt Transfer (*3)
| | \-- ClearPortFeature (*2)
| \-- GetPortStatus (*1)
\-- Host detects remote wakeup
- D+ goes high, Host starts running by remote wakeup
- D+ is not stable, goes low
- Host requests GetPortStatus at (*1) and gets the following hub status:
- Current Connect Status bit is 0
- Connect Status Change bit is 1
- D+ stabilizes, goes high
- Host requests ClearPortFeature and thus Connect Status Change bit is
cleared at (*2)
- After waiting 100 ms, Host starts the Interrupt Transfer at (*3)
- Since the Connect Status Change bit is 0, Hub returns NAK.
In this case, port_event() is not called in hub_event() and Host cannot
recognize device. To solve this issue, flag change_bits even if only
Connect Status Change bit is 1 when got in the first GetPortStatus.
This issue occurs rarely because it only if D+ changes during a very
short time between GetPortStatus and ClearPortFeature. However, it is
fatal if it occurs in embedded system.
Signed-off-by: Keiya Nobuta <[email protected]>
Acked-by: Alan Stern <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Greg Kroah-Hartman <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
drivers/usb/core/hub.c | 1 +
1 file changed, 1 insertion(+)
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -1125,6 +1125,7 @@ static void hub_activate(struct usb_hub
* PORT_OVER_CURRENT is not. So check for any of them.
*/
if (udev || (portstatus & USB_PORT_STAT_CONNECTION) ||
+ (portchange & USB_PORT_STAT_C_CONNECTION) ||
(portstatus & USB_PORT_STAT_OVERCURRENT) ||
(portchange & USB_PORT_STAT_C_OVERCURRENT))
set_bit(port1, hub->change_bits);
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Salvatore Mesoraca <[email protected]>
commit 30aba6656f61ed44cba445a3c0d38b296fa9e8f5 upstream.
Disallows open of FIFOs or regular files not owned by the user in world
writable sticky directories, unless the owner is the same as that of the
directory or the file is opened without the O_CREAT flag. The purpose
is to make data spoofing attacks harder. This protection can be turned
on and off separately for FIFOs and regular files via sysctl, just like
the symlinks/hardlinks protection. This patch is based on Openwall's
"HARDEN_FIFO" feature by Solar Designer.
This is a brief list of old vulnerabilities that could have been prevented
by this feature, some of them even allow for privilege escalation:
CVE-2000-1134
CVE-2007-3852
CVE-2008-0525
CVE-2009-0416
CVE-2011-4834
CVE-2015-1838
CVE-2015-7442
CVE-2016-7489
This list is not meant to be complete. It's difficult to track down all
vulnerabilities of this kind because they were often reported without any
mention of this particular attack vector. In fact, before
hardlinks/symlinks restrictions, fifos/regular files weren't the favorite
vehicle to exploit them.
[[email protected]: fix bug reported by Dan Carpenter]
Link: https://lkml.kernel.org/r/20180426081456.GA7060@mwanda
Link: http://lkml.kernel.org/r/[email protected]
[[email protected]: drop pr_warn_ratelimited() in favor of audit changes in the future]
[[email protected]: adjust commit subjet]
Link: http://lkml.kernel.org/r/20180416175918.GA13494@beast
Signed-off-by: Salvatore Mesoraca <[email protected]>
Signed-off-by: Kees Cook <[email protected]>
Suggested-by: Solar Designer <[email protected]>
Suggested-by: Kees Cook <[email protected]>
Cc: Al Viro <[email protected]>
Cc: Dan Carpenter <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
[bwh: Backported to 3.16: adjust context]
Signed-off-by: Ben Hutchings <[email protected]>
---
Documentation/sysctl/fs.txt | 36 +++++++++++++++++++++++++
fs/namei.c | 53 ++++++++++++++++++++++++++++++++++---
include/linux/fs.h | 2 ++
kernel/sysctl.c | 18 +++++++++++++
4 files changed, 106 insertions(+), 3 deletions(-)
--- a/Documentation/sysctl/fs.txt
+++ b/Documentation/sysctl/fs.txt
@@ -34,7 +34,9 @@ Currently, these files are in /proc/sys/
- overflowgid
- pipe-user-pages-hard
- pipe-user-pages-soft
+- protected_fifos
- protected_hardlinks
+- protected_regular
- protected_symlinks
- suid_dumpable
- super-max
@@ -182,6 +184,24 @@ applied.
==============================================================
+protected_fifos:
+
+The intent of this protection is to avoid unintentional writes to
+an attacker-controlled FIFO, where a program expected to create a regular
+file.
+
+When set to "0", writing to FIFOs is unrestricted.
+
+When set to "1" don't allow O_CREAT open on FIFOs that we don't own
+in world writable sticky directories, unless they are owned by the
+owner of the directory.
+
+When set to "2" it also applies to group writable sticky directories.
+
+This protection is based on the restrictions in Openwall.
+
+==============================================================
+
protected_hardlinks:
A long-standing class of security issues is the hardlink-based
@@ -202,6 +222,22 @@ This protection is based on the restrict
==============================================================
+protected_regular:
+
+This protection is similar to protected_fifos, but it
+avoids writes to an attacker-controlled regular file, where a program
+expected to create one.
+
+When set to "0", writing to regular files is unrestricted.
+
+When set to "1" don't allow O_CREAT open on regular files that we
+don't own in world writable sticky directories, unless they are
+owned by the owner of the directory.
+
+When set to "2" it also applies to group writable sticky directories.
+
+==============================================================
+
protected_symlinks:
A long-standing class of security issues is the symlink-based
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -723,6 +723,8 @@ static inline void put_link(struct namei
int sysctl_protected_symlinks __read_mostly = 0;
int sysctl_protected_hardlinks __read_mostly = 0;
+int sysctl_protected_fifos __read_mostly;
+int sysctl_protected_regular __read_mostly;
/**
* may_follow_link - Check symlink following for unsafe situations
@@ -837,6 +839,45 @@ static int may_linkat(struct path *link)
return -EPERM;
}
+/**
+ * may_create_in_sticky - Check whether an O_CREAT open in a sticky directory
+ * should be allowed, or not, on files that already
+ * exist.
+ * @dir: the sticky parent directory
+ * @inode: the inode of the file to open
+ *
+ * Block an O_CREAT open of a FIFO (or a regular file) when:
+ * - sysctl_protected_fifos (or sysctl_protected_regular) is enabled
+ * - the file already exists
+ * - we are in a sticky directory
+ * - we don't own the file
+ * - the owner of the directory doesn't own the file
+ * - the directory is world writable
+ * If the sysctl_protected_fifos (or sysctl_protected_regular) is set to 2
+ * the directory doesn't have to be world writable: being group writable will
+ * be enough.
+ *
+ * Returns 0 if the open is allowed, -ve on error.
+ */
+static int may_create_in_sticky(struct dentry * const dir,
+ struct inode * const inode)
+{
+ if ((!sysctl_protected_fifos && S_ISFIFO(inode->i_mode)) ||
+ (!sysctl_protected_regular && S_ISREG(inode->i_mode)) ||
+ likely(!(dir->d_inode->i_mode & S_ISVTX)) ||
+ uid_eq(inode->i_uid, dir->d_inode->i_uid) ||
+ uid_eq(current_fsuid(), inode->i_uid))
+ return 0;
+
+ if (likely(dir->d_inode->i_mode & 0002) ||
+ (dir->d_inode->i_mode & 0020 &&
+ ((sysctl_protected_fifos >= 2 && S_ISFIFO(inode->i_mode)) ||
+ (sysctl_protected_regular >= 2 && S_ISREG(inode->i_mode))))) {
+ return -EACCES;
+ }
+ return 0;
+}
+
static __always_inline int
follow_link(struct path *link, struct nameidata *nd, void **p)
{
@@ -3057,9 +3098,15 @@ finish_open:
return error;
}
audit_inode(name, nd->path.dentry, 0);
- error = -EISDIR;
- if ((open_flag & O_CREAT) && d_is_dir(nd->path.dentry))
- goto out;
+ if (open_flag & O_CREAT) {
+ error = -EISDIR;
+ if (d_is_dir(nd->path.dentry))
+ goto out;
+ error = may_create_in_sticky(dir,
+ d_backing_inode(nd->path.dentry));
+ if (unlikely(error))
+ goto out;
+ }
error = -ENOTDIR;
if ((nd->flags & LOOKUP_DIRECTORY) && !d_can_lookup(nd->path.dentry))
goto out;
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -61,6 +61,8 @@ extern struct inodes_stat_t inodes_stat;
extern int leases_enable, lease_break_time;
extern int sysctl_protected_symlinks;
extern int sysctl_protected_hardlinks;
+extern int sysctl_protected_fifos;
+extern int sysctl_protected_regular;
struct buffer_head;
typedef int (get_block_t)(struct inode *inode, sector_t iblock,
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -1653,6 +1653,24 @@ static struct ctl_table fs_table[] = {
.extra2 = &one,
},
{
+ .procname = "protected_fifos",
+ .data = &sysctl_protected_fifos,
+ .maxlen = sizeof(int),
+ .mode = 0600,
+ .proc_handler = proc_dointvec_minmax,
+ .extra1 = &zero,
+ .extra2 = &two,
+ },
+ {
+ .procname = "protected_regular",
+ .data = &sysctl_protected_regular,
+ .maxlen = sizeof(int),
+ .mode = 0600,
+ .proc_handler = proc_dointvec_minmax,
+ .extra1 = &zero,
+ .extra2 = &two,
+ },
+ {
.procname = "suid_dumpable",
.data = &suid_dumpable,
.maxlen = sizeof(int),
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Johan Hovold <[email protected]>
commit 998912346c0da53a6dbb71fab3a138586b596b30 upstream.
Make sure to check that we have at least one endpoint before accessing
the endpoint array to avoid dereferencing a NULL-pointer on stream
start.
Note that these sanity checks are not redundant as the driver is mixing
looking up altsettings by index and by number, which need not coincide.
Fixes: 1876bb923c98 ("V4L/DVB (12079): gspca_ov519: add support for the ov511 bridge")
Fixes: b282d87332f5 ("V4L/DVB (12080): gspca_ov519: Fix ov518+ with OV7620AE (Trust spacecam 320)")
Cc: Hans de Goede <[email protected]>
Signed-off-by: Johan Hovold <[email protected]>
Signed-off-by: Hans Verkuil <[email protected]>
Signed-off-by: Mauro Carvalho Chehab <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
drivers/media/usb/gspca/ov519.c | 10 ++++++++++
1 file changed, 10 insertions(+)
--- a/drivers/media/usb/gspca/ov519.c
+++ b/drivers/media/usb/gspca/ov519.c
@@ -3497,6 +3497,11 @@ static void ov511_mode_init_regs(struct
return;
}
+ if (alt->desc.bNumEndpoints < 1) {
+ sd->gspca_dev.usb_err = -ENODEV;
+ return;
+ }
+
packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize);
reg_w(sd, R51x_FIFO_PSIZE, packet_size >> 5);
@@ -3622,6 +3627,11 @@ static void ov518_mode_init_regs(struct
return;
}
+ if (alt->desc.bNumEndpoints < 1) {
+ sd->gspca_dev.usb_err = -ENODEV;
+ return;
+ }
+
packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize);
ov518_reg_w32(sd, R51x_FIFO_PSIZE, packet_size & ~7, 2);
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Alberto Aguirre <[email protected]>
commit 17f08b0d9aafccdb10038ab6dbd9ddb6433c13e2 upstream.
The Axe-Fx II implicit feedback end point and the data sync endpoint
are in different interface descriptors. Add quirk to ensure a sync
endpoint is properly configured.
Signed-off-by: Alberto Aguirre <[email protected]>
Signed-off-by: Takashi Iwai <[email protected]>
[bwh: Backported to 3.16: adjust context]
Signed-off-by: Ben Hutchings <[email protected]>
---
sound/usb/pcm.c | 10 ++++++++++
1 file changed, 10 insertions(+)
--- a/sound/usb/pcm.c
+++ b/sound/usb/pcm.c
@@ -351,6 +351,15 @@ static int set_sync_ep_implicit_fb_quirk
alts = &iface->altsetting[1];
goto add_sync_ep;
+ case USB_ID(0x2466, 0x8003):
+ ep = 0x86;
+ iface = usb_ifnum_to_if(dev, 2);
+
+ if (!iface || iface->num_altsetting == 0)
+ return -EINVAL;
+
+ alts = &iface->altsetting[1];
+ goto add_sync_ep;
case USB_ID(0x1397, 0x0002):
ep = 0x81;
iface = usb_ifnum_to_if(dev, 1);
@@ -360,6 +369,7 @@ static int set_sync_ep_implicit_fb_quirk
alts = &iface->altsetting[1];
goto add_sync_ep;
+
}
if (attr == USB_ENDPOINT_SYNC_ASYNC &&
altsd->bInterfaceClass == USB_CLASS_VENDOR_SPEC &&
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Davidlohr Bueso <[email protected]>
commit cdea01b2bf98affb7e9c44530108a4a28535eee8 upstream.
This is really about simplifying the double xchg patterns into
a single cmpxchg, with the same logic. Other than the immediate
cleanup, there are some subtleties this change deals with:
(i) While the load of the old bt is fully ordered wrt everything,
ie:
old_bt = xchg(&q->blk_trace, bt); [barrier]
if (old_bt)
(void) xchg(&q->blk_trace, old_bt); [barrier]
blk_trace could still be changed between the xchg and the old_bt
load. Note that this description is merely theoretical and afaict
very small, but doing everything in a single context with cmpxchg
closes this potential race.
(ii) Ordering guarantees are obviously kept with cmpxchg.
(iii) Gets rid of the hacky-by-nature (void)xchg pattern.
Signed-off-by: Davidlohr Bueso <[email protected]>
eviewed-by: Jeff Moyer <[email protected]>
Signed-off-by: Jens Axboe <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
kernel/trace/blktrace.c | 16 +++++-----------
1 file changed, 5 insertions(+), 11 deletions(-)
--- a/kernel/trace/blktrace.c
+++ b/kernel/trace/blktrace.c
@@ -448,7 +448,7 @@ int do_blk_trace_setup(struct request_qu
struct block_device *bdev,
struct blk_user_trace_setup *buts)
{
- struct blk_trace *old_bt, *bt = NULL;
+ struct blk_trace *bt = NULL;
struct dentry *dir = NULL;
int ret, i;
@@ -532,11 +532,8 @@ int do_blk_trace_setup(struct request_qu
bt->trace_state = Blktrace_setup;
ret = -EBUSY;
- old_bt = xchg(&q->blk_trace, bt);
- if (old_bt) {
- (void) xchg(&q->blk_trace, old_bt);
+ if (cmpxchg(&q->blk_trace, NULL, bt))
goto err;
- }
if (atomic_inc_return(&blk_probes_ref) == 1)
blk_register_tracepoints();
@@ -1550,7 +1547,7 @@ static int blk_trace_remove_queue(struct
static int blk_trace_setup_queue(struct request_queue *q,
struct block_device *bdev)
{
- struct blk_trace *old_bt, *bt = NULL;
+ struct blk_trace *bt = NULL;
int ret = -ENOMEM;
bt = kzalloc(sizeof(*bt), GFP_KERNEL);
@@ -1566,12 +1563,9 @@ static int blk_trace_setup_queue(struct
blk_trace_setup_lba(bt, bdev);
- old_bt = xchg(&q->blk_trace, bt);
- if (old_bt != NULL) {
- (void)xchg(&q->blk_trace, old_bt);
- ret = -EBUSY;
+ ret = -EBUSY;
+ if (cmpxchg(&q->blk_trace, NULL, bt))
goto free_bt;
- }
if (atomic_inc_return(&blk_probes_ref) == 1)
blk_register_tracepoints();
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Dmitry Torokhov <[email protected]>
commit cb222aed03d798fc074be55e59d9a112338ee784 upstream.
If we happen to have a garbage in input device's keycode table with values
too big we'll end up doing clear_bit() with offset way outside of our
bitmaps, damaging other objects within an input device or even outside of
it. Let's add sanity checks to the returned old keycodes.
Reported-by: [email protected]
Reported-by: [email protected]
Link: https://lore.kernel.org/r/20191207212757.GA245964@dtor-ws
Signed-off-by: Dmitry Torokhov <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
drivers/input/input.c | 26 ++++++++++++++++----------
1 file changed, 16 insertions(+), 10 deletions(-)
--- a/drivers/input/input.c
+++ b/drivers/input/input.c
@@ -841,16 +841,18 @@ static int input_default_setkeycode(stru
}
}
- __clear_bit(*old_keycode, dev->keybit);
- __set_bit(ke->keycode, dev->keybit);
-
- for (i = 0; i < dev->keycodemax; i++) {
- if (input_fetch_keycode(dev, i) == *old_keycode) {
- __set_bit(*old_keycode, dev->keybit);
- break; /* Setting the bit twice is useless, so break */
+ if (*old_keycode <= KEY_MAX) {
+ __clear_bit(*old_keycode, dev->keybit);
+ for (i = 0; i < dev->keycodemax; i++) {
+ if (input_fetch_keycode(dev, i) == *old_keycode) {
+ __set_bit(*old_keycode, dev->keybit);
+ /* Setting the bit twice is useless, so break */
+ break;
+ }
}
}
+ __set_bit(ke->keycode, dev->keybit);
return 0;
}
@@ -906,9 +908,13 @@ int input_set_keycode(struct input_dev *
* Simulate keyup event if keycode is not present
* in the keymap anymore
*/
- if (test_bit(EV_KEY, dev->evbit) &&
- !is_event_supported(old_keycode, dev->keybit, KEY_MAX) &&
- __test_and_clear_bit(old_keycode, dev->key)) {
+ if (old_keycode > KEY_MAX) {
+ dev_warn(dev->dev.parent ?: &dev->dev,
+ "%s: got too big old keycode %#x\n",
+ __func__, old_keycode);
+ } else if (test_bit(EV_KEY, dev->evbit) &&
+ !is_event_supported(old_keycode, dev->keybit, KEY_MAX) &&
+ __test_and_clear_bit(old_keycode, dev->key)) {
struct input_value vals[] = {
{ EV_KEY, old_keycode, 0 },
input_value_sync
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Cong Wang <[email protected]>
commit 61678d28d4a45ef376f5d02a839cc37509ae9281 upstream.
syzbot reported an out-of-bound access in em_nbyte. As initially
analyzed by Eric, this is because em_nbyte sets its own em->datalen
in em_nbyte_change() other than the one specified by user, but this
value gets overwritten later by its caller tcf_em_validate().
We should leave em->datalen untouched to respect their choices.
I audit all the in-tree ematch users, all of those implement
->change() set em->datalen, so we can just avoid setting it twice
in this case.
Reported-and-tested-by: [email protected]
Reported-by: [email protected]
Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Cc: Eric Dumazet <[email protected]>
Signed-off-by: Cong Wang <[email protected]>
Reviewed-by: Eric Dumazet <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
[bwh: Backported to 3.16: adjust context]
Signed-off-by: Ben Hutchings <[email protected]>
---
net/sched/ematch.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/net/sched/ematch.c
+++ b/net/sched/ematch.c
@@ -266,12 +266,12 @@ static int tcf_em_validate(struct tcf_pr
}
em->data = (unsigned long) v;
}
+ em->datalen = data_len;
}
}
em->matchid = em_hdr->matchid;
em->flags = em_hdr->flags;
- em->datalen = data_len;
err = 0;
errout:
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Johan Hovold <[email protected]>
commit 86f3f4cd53707ceeec079b83205c8d3c756eca93 upstream.
Add missing endpoint sanity check to probe in order to prevent a
NULL-pointer dereference (or slab out-of-bounds access) when retrieving
the interrupt-endpoint bInterval on ndo_open() in case a device lacks
the expected endpoints.
Fixes: 40a82917b1d3 ("net/usb/r8152: enable interrupt transfer")
Cc: hayeswang <[email protected]>
Signed-off-by: Johan Hovold <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
drivers/net/usb/r8152.c | 3 +++
1 file changed, 3 insertions(+)
--- a/drivers/net/usb/r8152.c
+++ b/drivers/net/usb/r8152.c
@@ -3425,6 +3425,9 @@ static int rtl8152_probe(struct usb_inte
return -ENODEV;
}
+ if (intf->cur_altsetting->desc.bNumEndpoints < 3)
+ return -ENODEV;
+
usb_reset_device(udev);
netdev = alloc_etherdev(sizeof(struct r8152));
if (!netdev) {
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Dmitry Torokhov <[email protected]>
commit af59e717d5ff9c8dbf9bcc581c0dfb3b2a9c9030 upstream.
Instead of creating selected attributes after the device is created (and
after userspace potentially seen uevent), lets use attribute group
is_visible() method to control which attributes are shown. This will allow
us to create all attributes (except "pins" group, which will be taken care
of later) before userspace gets notified about new ptp class device.
Signed-off-by: Dmitry Torokhov <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
drivers/ptp/ptp_sysfs.c | 125 ++++++++++++++++++----------------------
1 file changed, 55 insertions(+), 70 deletions(-)
--- a/drivers/ptp/ptp_sysfs.c
+++ b/drivers/ptp/ptp_sysfs.c
@@ -46,27 +46,6 @@ PTP_SHOW_INT(n_periodic_outputs, n_per_o
PTP_SHOW_INT(n_programmable_pins, n_pins);
PTP_SHOW_INT(pps_available, pps);
-static struct attribute *ptp_attrs[] = {
- &dev_attr_clock_name.attr,
- &dev_attr_max_adjustment.attr,
- &dev_attr_n_alarms.attr,
- &dev_attr_n_external_timestamps.attr,
- &dev_attr_n_periodic_outputs.attr,
- &dev_attr_n_programmable_pins.attr,
- &dev_attr_pps_available.attr,
- NULL,
-};
-
-static const struct attribute_group ptp_group = {
- .attrs = ptp_attrs,
-};
-
-const struct attribute_group *ptp_groups[] = {
- &ptp_group,
- NULL,
-};
-
-
static ssize_t extts_enable_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
@@ -91,6 +70,7 @@ static ssize_t extts_enable_store(struct
out:
return err;
}
+static DEVICE_ATTR(extts_enable, 0220, NULL, extts_enable_store);
static ssize_t extts_fifo_show(struct device *dev,
struct device_attribute *attr, char *page)
@@ -124,6 +104,7 @@ out:
mutex_unlock(&ptp->tsevq_mux);
return cnt;
}
+static DEVICE_ATTR(fifo, 0444, extts_fifo_show, NULL);
static ssize_t period_store(struct device *dev,
struct device_attribute *attr,
@@ -151,6 +132,7 @@ static ssize_t period_store(struct devic
out:
return err;
}
+static DEVICE_ATTR(period, 0220, NULL, period_store);
static ssize_t pps_enable_store(struct device *dev,
struct device_attribute *attr,
@@ -177,6 +159,57 @@ static ssize_t pps_enable_store(struct d
out:
return err;
}
+static DEVICE_ATTR(pps_enable, 0220, NULL, pps_enable_store);
+
+static struct attribute *ptp_attrs[] = {
+ &dev_attr_clock_name.attr,
+
+ &dev_attr_max_adjustment.attr,
+ &dev_attr_n_alarms.attr,
+ &dev_attr_n_external_timestamps.attr,
+ &dev_attr_n_periodic_outputs.attr,
+ &dev_attr_n_programmable_pins.attr,
+ &dev_attr_pps_available.attr,
+
+ &dev_attr_extts_enable.attr,
+ &dev_attr_fifo.attr,
+ &dev_attr_period.attr,
+ &dev_attr_pps_enable.attr,
+ NULL
+};
+
+static umode_t ptp_is_attribute_visible(struct kobject *kobj,
+ struct attribute *attr, int n)
+{
+ struct device *dev = kobj_to_dev(kobj);
+ struct ptp_clock *ptp = dev_get_drvdata(dev);
+ struct ptp_clock_info *info = ptp->info;
+ umode_t mode = attr->mode;
+
+ if (attr == &dev_attr_extts_enable.attr ||
+ attr == &dev_attr_fifo.attr) {
+ if (!info->n_ext_ts)
+ mode = 0;
+ } else if (attr == &dev_attr_period.attr) {
+ if (!info->n_per_out)
+ mode = 0;
+ } else if (attr == &dev_attr_pps_enable.attr) {
+ if (!info->pps)
+ mode = 0;
+ }
+
+ return mode;
+}
+
+static const struct attribute_group ptp_group = {
+ .is_visible = ptp_is_attribute_visible,
+ .attrs = ptp_attrs,
+};
+
+const struct attribute_group *ptp_groups[] = {
+ &ptp_group,
+ NULL
+};
static int ptp_pin_name2index(struct ptp_clock *ptp, const char *name)
{
@@ -235,26 +268,11 @@ static ssize_t ptp_pin_store(struct devi
return count;
}
-static DEVICE_ATTR(extts_enable, 0220, NULL, extts_enable_store);
-static DEVICE_ATTR(fifo, 0444, extts_fifo_show, NULL);
-static DEVICE_ATTR(period, 0220, NULL, period_store);
-static DEVICE_ATTR(pps_enable, 0220, NULL, pps_enable_store);
-
int ptp_cleanup_sysfs(struct ptp_clock *ptp)
{
struct device *dev = ptp->dev;
struct ptp_clock_info *info = ptp->info;
- if (info->n_ext_ts) {
- device_remove_file(dev, &dev_attr_extts_enable);
- device_remove_file(dev, &dev_attr_fifo);
- }
- if (info->n_per_out)
- device_remove_file(dev, &dev_attr_period);
-
- if (info->pps)
- device_remove_file(dev, &dev_attr_pps_enable);
-
if (info->n_pins) {
sysfs_remove_group(&dev->kobj, &ptp->pin_attr_group);
kfree(ptp->pin_attr);
@@ -307,46 +325,13 @@ no_dev_attr:
int ptp_populate_sysfs(struct ptp_clock *ptp)
{
- struct device *dev = ptp->dev;
struct ptp_clock_info *info = ptp->info;
int err;
- if (info->n_ext_ts) {
- err = device_create_file(dev, &dev_attr_extts_enable);
- if (err)
- goto out1;
- err = device_create_file(dev, &dev_attr_fifo);
- if (err)
- goto out2;
- }
- if (info->n_per_out) {
- err = device_create_file(dev, &dev_attr_period);
- if (err)
- goto out3;
- }
- if (info->pps) {
- err = device_create_file(dev, &dev_attr_pps_enable);
- if (err)
- goto out4;
- }
if (info->n_pins) {
err = ptp_populate_pins(ptp);
if (err)
- goto out5;
+ return err;
}
return 0;
-out5:
- if (info->pps)
- device_remove_file(dev, &dev_attr_pps_enable);
-out4:
- if (info->n_per_out)
- device_remove_file(dev, &dev_attr_period);
-out3:
- if (info->n_ext_ts)
- device_remove_file(dev, &dev_attr_fifo);
-out2:
- if (info->n_ext_ts)
- device_remove_file(dev, &dev_attr_extts_enable);
-out1:
- return err;
}
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Sabrina Dubroca <[email protected]>
commit 6c8991f41546c3c472503dff1ea9daaddf9331c2 upstream.
ipv6_stub uses the ip6_dst_lookup function to allow other modules to
perform IPv6 lookups. However, this function skips the XFRM layer
entirely.
All users of ipv6_stub->ip6_dst_lookup use ip_route_output_flow (via the
ip_route_output_key and ip_route_output helpers) for their IPv4 lookups,
which calls xfrm_lookup_route(). This patch fixes this inconsistent
behavior by switching the stub to ip6_dst_lookup_flow, which also calls
xfrm_lookup_route().
This requires some changes in all the callers, as these two functions
take different arguments and have different return types.
Fixes: 5f81bd2e5d80 ("ipv6: export a stub for IPv6 symbols used by vxlan")
Reported-by: Xiumei Mu <[email protected]>
Signed-off-by: Sabrina Dubroca <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
[bwh: Backported to 3.16:
- Only vxlan uses this operation
- Neither ip6_dst_lookup() nor ip6_dst_lookup_flow() takes a struct net
pointer argument here
- Adjust filename, context]
Signed-off-by: Ben Hutchings <[email protected]>
---
--- a/drivers/net/vxlan.c
+++ b/drivers/net/vxlan.c
@@ -1929,7 +1929,8 @@ static void vxlan_xmit_one(struct sk_buf
fl6.saddr = vxlan->saddr.sin6.sin6_addr;
fl6.flowi6_proto = IPPROTO_UDP;
- if (ipv6_stub->ipv6_dst_lookup(sk, &ndst, &fl6)) {
+ ndst = ipv6_stub->ipv6_dst_lookup_flow(sk, &fl6, NULL);
+ if (unlikely(IS_ERR(ndst))) {
netdev_dbg(dev, "no route to %pI6\n",
&dst->sin6.sin6_addr);
dev->stats.tx_carrier_errors++;
--- a/include/net/addrconf.h
+++ b/include/net/addrconf.h
@@ -156,8 +156,9 @@ struct ipv6_stub {
const struct in6_addr *addr);
int (*ipv6_sock_mc_drop)(struct sock *sk, int ifindex,
const struct in6_addr *addr);
- int (*ipv6_dst_lookup)(struct sock *sk, struct dst_entry **dst,
- struct flowi6 *fl6);
+ struct dst_entry *(*ipv6_dst_lookup_flow)(struct sock *sk,
+ struct flowi6 *fl6,
+ const struct in6_addr *final_dst);
void (*udpv6_encap_enable)(void);
void (*ndisc_send_na)(struct net_device *dev, struct neighbour *neigh,
const struct in6_addr *daddr,
--- a/net/ipv6/af_inet6.c
+++ b/net/ipv6/af_inet6.c
@@ -820,7 +820,7 @@ static struct pernet_operations inet6_ne
static const struct ipv6_stub ipv6_stub_impl = {
.ipv6_sock_mc_join = ipv6_sock_mc_join,
.ipv6_sock_mc_drop = ipv6_sock_mc_drop,
- .ipv6_dst_lookup = ip6_dst_lookup,
+ .ipv6_dst_lookup_flow = ip6_dst_lookup_flow,
.udpv6_encap_enable = udpv6_encap_enable,
.ndisc_send_na = ndisc_send_na,
.nd_tbl = &nd_tbl,
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Linus Torvalds <[email protected]>
commit 2e90ca68b0d2f5548804f22f0dd61145516171e3 upstream.
Jordy Zomer reported a KASAN out-of-bounds read in the floppy driver in
wait_til_ready().
Which on the face of it can't happen, since as Willy Tarreau points out,
the function does no particular memory access. Except through the FDCS
macro, which just indexes a static allocation through teh current fdc,
which is always checked against N_FDC.
Except the checking happens after we've already assigned the value.
The floppy driver is a disgrace (a lot of it going back to my original
horrd "design"), and has no real maintainer. Nobody has the hardware,
and nobody really cares. But it still gets used in virtual environment
because it's one of those things that everybody supports.
The whole thing should be re-written, or at least parts of it should be
seriously cleaned up. The 'current fdc' index, which is used by the
FDCS macro, and which is often shadowed by a local 'fdc' variable, is a
prime example of how not to write code.
But because nobody has the hardware or the motivation, let's just fix up
the immediate problem with a nasty band-aid: test the fdc index before
actually assigning it to the static 'fdc' variable.
Reported-by: Jordy Zomer <[email protected]>
Cc: Willy Tarreau <[email protected]>
Cc: Dan Carpenter <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
drivers/block/floppy.c | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
--- a/drivers/block/floppy.c
+++ b/drivers/block/floppy.c
@@ -847,14 +847,17 @@ static void reset_fdc_info(int mode)
/* selects the fdc and drive, and enables the fdc's input/dma. */
static void set_fdc(int drive)
{
+ unsigned int new_fdc = fdc;
+
if (drive >= 0 && drive < N_DRIVE) {
- fdc = FDC(drive);
+ new_fdc = FDC(drive);
current_drive = drive;
}
- if (fdc != 1 && fdc != 0) {
+ if (new_fdc >= N_FDC) {
pr_info("bad fdc value\n");
return;
}
+ fdc = new_fdc;
set_dor(fdc, ~0, 8);
#if N_FDC > 1
set_dor(1 - fdc, ~8, 0);
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Lars Möllendorf <[email protected]>
commit 883f616530692d81cb70f8a32d85c0d2afc05f69 upstream.
Previous versions of `iio_compute_scan_bytes` only aligned each element
to its own length (i.e. its own natural alignment). Because multiple
consecutive sets of scan elements are buffered this does not work in
case the computed scan bytes do not align with the natural alignment of
the first scan element in the set.
This commit fixes this by aligning the scan bytes to the natural
alignment of the largest scan element in the set.
Fixes: 959d2952d124 ("staging:iio: make iio_sw_buffer_preenable much more general.")
Signed-off-by: Lars Möllendorf <[email protected]>
Reviewed-by: Lars-Peter Clausen <[email protected]>
Signed-off-by: Jonathan Cameron <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
[bwh: Backported to 3.16: adjust context]
Signed-off-by: Ben Hutchings <[email protected]>
---
drivers/iio/industrialio-buffer.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
--- a/drivers/iio/industrialio-buffer.c
+++ b/drivers/iio/industrialio-buffer.c
@@ -478,7 +478,7 @@ static int iio_compute_scan_bytes(struct
{
const struct iio_chan_spec *ch;
unsigned bytes = 0;
- int length, i;
+ int length, i, largest = 0;
/* How much space will the demuxed element take? */
for_each_set_bit(i, mask,
@@ -491,6 +491,7 @@ static int iio_compute_scan_bytes(struct
length = ch->scan_type.storagebits / 8;
bytes = ALIGN(bytes, length);
bytes += length;
+ largest = max(largest, length);
}
if (timestamp) {
ch = iio_find_channel_from_si(indio_dev,
@@ -502,7 +503,10 @@ static int iio_compute_scan_bytes(struct
length = ch->scan_type.storagebits / 8;
bytes = ALIGN(bytes, length);
bytes += length;
+ largest = max(largest, length);
}
+
+ bytes = ALIGN(bytes, largest);
return bytes;
}
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Jari Ruusu <[email protected]>
commit f5ae2ea6347a308cfe91f53b53682ce635497d0d upstream.
Intel Software Developer's Manual, volume 3, chapter 9.11.6 says:
"Note that the microcode update must be aligned on a 16-byte boundary
and the size of the microcode update must be 1-KByte granular"
When early-load Intel microcode is loaded from initramfs, userspace tool
'iucode_tool' has already 16-byte aligned those microcode bits in that
initramfs image. Image that was created something like this:
iucode_tool --write-earlyfw=FOO.cpio microcode-files...
However, when early-load Intel microcode is loaded from built-in
firmware BLOB using CONFIG_EXTRA_FIRMWARE= kernel config option, that
16-byte alignment is not guaranteed.
Fix this by forcing all built-in firmware BLOBs to 16-byte alignment.
[ If we end up having other firmware with much bigger alignment
requirements, we might need to introduce some method for the firmware
to specify it, this is the minimal "just increase the alignment a bit
to account for this one special case" patch - Linus ]
Signed-off-by: Jari Ruusu <[email protected]>
Cc: Borislav Petkov <[email protected]>
Cc: Fenghua Yu <[email protected]>
Cc: Luis Chamberlain <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
[bwh: Backported to 3.16: adjust filename, context, indentation]
Signed-off-by: Ben Hutchings <[email protected]>
---
firmware/Makefile | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/firmware/Makefile
+++ b/firmware/Makefile
@@ -156,7 +156,7 @@ quiet_cmd_fwbin = MK_FW $@
PROGBITS=$(if $(CONFIG_ARM),%,@)progbits; \
echo "/* Generated by firmware/Makefile */" > $@;\
echo " .section .rodata" >>$@;\
- echo " .p2align $${ASM_ALIGN}" >>$@;\
+ echo " .p2align 4" >>$@;\
echo "_fw_$${FWSTR}_bin:" >>$@;\
echo " .incbin \"$(2)\"" >>$@;\
echo "_fw_end:" >>$@;\
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Jeff Mahoney <[email protected]>
commit 1cbb1f454e5321e47fc1e6b233066c7ccc979d15 upstream.
We have reader helpers for most of the on-disk structures that use
an extent_buffer and pointer as offset into the buffer that are
read-only. We should mark them as const and, in turn, allow consumers
of these interfaces to mark the buffers const as well.
No impact on code, but serves as documentation that a buffer is intended
not to be modified.
Signed-off-by: Jeff Mahoney <[email protected]>
Signed-off-by: David Sterba <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
fs/btrfs/ctree.h | 128 +++++++++++++++++++++-------------------
fs/btrfs/extent_io.c | 24 ++++----
fs/btrfs/extent_io.h | 19 +++---
fs/btrfs/struct-funcs.c | 9 +--
4 files changed, 91 insertions(+), 89 deletions(-)
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -2138,7 +2138,7 @@ struct btrfs_ioctl_defrag_range_args {
#define BTRFS_INODE_ROOT_ITEM_INIT (1 << 31)
struct btrfs_map_token {
- struct extent_buffer *eb;
+ const struct extent_buffer *eb;
char *kaddr;
unsigned long offset;
};
@@ -2169,18 +2169,19 @@ static inline void btrfs_init_map_token
sizeof(((type *)0)->member)))
#define DECLARE_BTRFS_SETGET_BITS(bits) \
-u##bits btrfs_get_token_##bits(struct extent_buffer *eb, void *ptr, \
- unsigned long off, \
- struct btrfs_map_token *token); \
-void btrfs_set_token_##bits(struct extent_buffer *eb, void *ptr, \
+u##bits btrfs_get_token_##bits(const struct extent_buffer *eb, \
+ const void *ptr, unsigned long off, \
+ struct btrfs_map_token *token); \
+void btrfs_set_token_##bits(struct extent_buffer *eb, const void *ptr, \
unsigned long off, u##bits val, \
struct btrfs_map_token *token); \
-static inline u##bits btrfs_get_##bits(struct extent_buffer *eb, void *ptr, \
+static inline u##bits btrfs_get_##bits(const struct extent_buffer *eb, \
+ const void *ptr, \
unsigned long off) \
{ \
return btrfs_get_token_##bits(eb, ptr, off, NULL); \
} \
-static inline void btrfs_set_##bits(struct extent_buffer *eb, void *ptr, \
+static inline void btrfs_set_##bits(struct extent_buffer *eb, void *ptr,\
unsigned long off, u##bits val) \
{ \
btrfs_set_token_##bits(eb, ptr, off, val, NULL); \
@@ -2192,7 +2193,8 @@ DECLARE_BTRFS_SETGET_BITS(32)
DECLARE_BTRFS_SETGET_BITS(64)
#define BTRFS_SETGET_FUNCS(name, type, member, bits) \
-static inline u##bits btrfs_##name(struct extent_buffer *eb, type *s) \
+static inline u##bits btrfs_##name(const struct extent_buffer *eb, \
+ const type *s) \
{ \
BUILD_BUG_ON(sizeof(u##bits) != sizeof(((type *)0))->member); \
return btrfs_get_##bits(eb, s, offsetof(type, member)); \
@@ -2203,7 +2205,8 @@ static inline void btrfs_set_##name(stru
BUILD_BUG_ON(sizeof(u##bits) != sizeof(((type *)0))->member); \
btrfs_set_##bits(eb, s, offsetof(type, member), val); \
} \
-static inline u##bits btrfs_token_##name(struct extent_buffer *eb, type *s, \
+static inline u##bits btrfs_token_##name(const struct extent_buffer *eb,\
+ const type *s, \
struct btrfs_map_token *token) \
{ \
BUILD_BUG_ON(sizeof(u##bits) != sizeof(((type *)0))->member); \
@@ -2218,9 +2221,9 @@ static inline void btrfs_set_token_##nam
}
#define BTRFS_SETGET_HEADER_FUNCS(name, type, member, bits) \
-static inline u##bits btrfs_##name(struct extent_buffer *eb) \
+static inline u##bits btrfs_##name(const struct extent_buffer *eb) \
{ \
- type *p = page_address(eb->pages[0]); \
+ const type *p = page_address(eb->pages[0]); \
u##bits res = le##bits##_to_cpu(p->member); \
return res; \
} \
@@ -2232,7 +2235,7 @@ static inline void btrfs_set_##name(stru
}
#define BTRFS_SETGET_STACK_FUNCS(name, type, member, bits) \
-static inline u##bits btrfs_##name(type *s) \
+static inline u##bits btrfs_##name(const type *s) \
{ \
return le##bits##_to_cpu(s->member); \
} \
@@ -2558,7 +2561,7 @@ static inline unsigned long btrfs_node_k
sizeof(struct btrfs_key_ptr) * nr;
}
-void btrfs_node_key(struct extent_buffer *eb,
+void btrfs_node_key(const struct extent_buffer *eb,
struct btrfs_disk_key *disk_key, int nr);
static inline void btrfs_set_node_key(struct extent_buffer *eb,
@@ -2587,28 +2590,28 @@ static inline struct btrfs_item *btrfs_i
return (struct btrfs_item *)btrfs_item_nr_offset(nr);
}
-static inline u32 btrfs_item_end(struct extent_buffer *eb,
+static inline u32 btrfs_item_end(const struct extent_buffer *eb,
struct btrfs_item *item)
{
return btrfs_item_offset(eb, item) + btrfs_item_size(eb, item);
}
-static inline u32 btrfs_item_end_nr(struct extent_buffer *eb, int nr)
+static inline u32 btrfs_item_end_nr(const struct extent_buffer *eb, int nr)
{
return btrfs_item_end(eb, btrfs_item_nr(nr));
}
-static inline u32 btrfs_item_offset_nr(struct extent_buffer *eb, int nr)
+static inline u32 btrfs_item_offset_nr(const struct extent_buffer *eb, int nr)
{
return btrfs_item_offset(eb, btrfs_item_nr(nr));
}
-static inline u32 btrfs_item_size_nr(struct extent_buffer *eb, int nr)
+static inline u32 btrfs_item_size_nr(const struct extent_buffer *eb, int nr)
{
return btrfs_item_size(eb, btrfs_item_nr(nr));
}
-static inline void btrfs_item_key(struct extent_buffer *eb,
+static inline void btrfs_item_key(const struct extent_buffer *eb,
struct btrfs_disk_key *disk_key, int nr)
{
struct btrfs_item *item = btrfs_item_nr(nr);
@@ -2644,8 +2647,8 @@ BTRFS_SETGET_STACK_FUNCS(stack_dir_name_
BTRFS_SETGET_STACK_FUNCS(stack_dir_transid, struct btrfs_dir_item,
transid, 64);
-static inline void btrfs_dir_item_key(struct extent_buffer *eb,
- struct btrfs_dir_item *item,
+static inline void btrfs_dir_item_key(const struct extent_buffer *eb,
+ const struct btrfs_dir_item *item,
struct btrfs_disk_key *key)
{
read_eb_member(eb, item, struct btrfs_dir_item, location, key);
@@ -2653,7 +2656,7 @@ static inline void btrfs_dir_item_key(st
static inline void btrfs_set_dir_item_key(struct extent_buffer *eb,
struct btrfs_dir_item *item,
- struct btrfs_disk_key *key)
+ const struct btrfs_disk_key *key)
{
write_eb_member(eb, item, struct btrfs_dir_item, location, key);
}
@@ -2665,8 +2668,8 @@ BTRFS_SETGET_FUNCS(free_space_bitmaps, s
BTRFS_SETGET_FUNCS(free_space_generation, struct btrfs_free_space_header,
generation, 64);
-static inline void btrfs_free_space_key(struct extent_buffer *eb,
- struct btrfs_free_space_header *h,
+static inline void btrfs_free_space_key(const struct extent_buffer *eb,
+ const struct btrfs_free_space_header *h,
struct btrfs_disk_key *key)
{
read_eb_member(eb, h, struct btrfs_free_space_header, location, key);
@@ -2674,7 +2677,7 @@ static inline void btrfs_free_space_key(
static inline void btrfs_set_free_space_key(struct extent_buffer *eb,
struct btrfs_free_space_header *h,
- struct btrfs_disk_key *key)
+ const struct btrfs_disk_key *key)
{
write_eb_member(eb, h, struct btrfs_free_space_header, location, key);
}
@@ -2701,25 +2704,25 @@ static inline void btrfs_cpu_key_to_disk
disk->objectid = cpu_to_le64(cpu->objectid);
}
-static inline void btrfs_node_key_to_cpu(struct extent_buffer *eb,
- struct btrfs_key *key, int nr)
+static inline void btrfs_node_key_to_cpu(const struct extent_buffer *eb,
+ struct btrfs_key *key, int nr)
{
struct btrfs_disk_key disk_key;
btrfs_node_key(eb, &disk_key, nr);
btrfs_disk_key_to_cpu(key, &disk_key);
}
-static inline void btrfs_item_key_to_cpu(struct extent_buffer *eb,
- struct btrfs_key *key, int nr)
+static inline void btrfs_item_key_to_cpu(const struct extent_buffer *eb,
+ struct btrfs_key *key, int nr)
{
struct btrfs_disk_key disk_key;
btrfs_item_key(eb, &disk_key, nr);
btrfs_disk_key_to_cpu(key, &disk_key);
}
-static inline void btrfs_dir_item_key_to_cpu(struct extent_buffer *eb,
- struct btrfs_dir_item *item,
- struct btrfs_key *key)
+static inline void btrfs_dir_item_key_to_cpu(const struct extent_buffer *eb,
+ const struct btrfs_dir_item *item,
+ struct btrfs_key *key)
{
struct btrfs_disk_key disk_key;
btrfs_dir_item_key(eb, item, &disk_key);
@@ -2752,7 +2755,7 @@ BTRFS_SETGET_STACK_FUNCS(stack_header_nr
nritems, 32);
BTRFS_SETGET_STACK_FUNCS(stack_header_bytenr, struct btrfs_header, bytenr, 64);
-static inline int btrfs_header_flag(struct extent_buffer *eb, u64 flag)
+static inline int btrfs_header_flag(const struct extent_buffer *eb, u64 flag)
{
return (btrfs_header_flags(eb) & flag) == flag;
}
@@ -2771,7 +2774,7 @@ static inline int btrfs_clear_header_fla
return (flags & flag) == flag;
}
-static inline int btrfs_header_backref_rev(struct extent_buffer *eb)
+static inline int btrfs_header_backref_rev(const struct extent_buffer *eb)
{
u64 flags = btrfs_header_flags(eb);
return flags >> BTRFS_BACKREF_REV_SHIFT;
@@ -2791,12 +2794,12 @@ static inline unsigned long btrfs_header
return offsetof(struct btrfs_header, fsid);
}
-static inline unsigned long btrfs_header_chunk_tree_uuid(struct extent_buffer *eb)
+static inline unsigned long btrfs_header_chunk_tree_uuid(const struct extent_buffer *eb)
{
return offsetof(struct btrfs_header, chunk_tree_uuid);
}
-static inline int btrfs_is_leaf(struct extent_buffer *eb)
+static inline int btrfs_is_leaf(const struct extent_buffer *eb)
{
return btrfs_header_level(eb) == 0;
}
@@ -2830,12 +2833,12 @@ BTRFS_SETGET_STACK_FUNCS(root_stransid,
BTRFS_SETGET_STACK_FUNCS(root_rtransid, struct btrfs_root_item,
rtransid, 64);
-static inline bool btrfs_root_readonly(struct btrfs_root *root)
+static inline bool btrfs_root_readonly(const struct btrfs_root *root)
{
return (root->root_item.flags & cpu_to_le64(BTRFS_ROOT_SUBVOL_RDONLY)) != 0;
}
-static inline bool btrfs_root_dead(struct btrfs_root *root)
+static inline bool btrfs_root_dead(const struct btrfs_root *root)
{
return (root->root_item.flags & cpu_to_le64(BTRFS_ROOT_SUBVOL_DEAD)) != 0;
}
@@ -2892,51 +2895,51 @@ BTRFS_SETGET_STACK_FUNCS(backup_num_devi
/* struct btrfs_balance_item */
BTRFS_SETGET_FUNCS(balance_flags, struct btrfs_balance_item, flags, 64);
-static inline void btrfs_balance_data(struct extent_buffer *eb,
- struct btrfs_balance_item *bi,
+static inline void btrfs_balance_data(const struct extent_buffer *eb,
+ const struct btrfs_balance_item *bi,
struct btrfs_disk_balance_args *ba)
{
read_eb_member(eb, bi, struct btrfs_balance_item, data, ba);
}
static inline void btrfs_set_balance_data(struct extent_buffer *eb,
- struct btrfs_balance_item *bi,
- struct btrfs_disk_balance_args *ba)
+ struct btrfs_balance_item *bi,
+ const struct btrfs_disk_balance_args *ba)
{
write_eb_member(eb, bi, struct btrfs_balance_item, data, ba);
}
-static inline void btrfs_balance_meta(struct extent_buffer *eb,
- struct btrfs_balance_item *bi,
+static inline void btrfs_balance_meta(const struct extent_buffer *eb,
+ const struct btrfs_balance_item *bi,
struct btrfs_disk_balance_args *ba)
{
read_eb_member(eb, bi, struct btrfs_balance_item, meta, ba);
}
static inline void btrfs_set_balance_meta(struct extent_buffer *eb,
- struct btrfs_balance_item *bi,
- struct btrfs_disk_balance_args *ba)
+ struct btrfs_balance_item *bi,
+ const struct btrfs_disk_balance_args *ba)
{
write_eb_member(eb, bi, struct btrfs_balance_item, meta, ba);
}
-static inline void btrfs_balance_sys(struct extent_buffer *eb,
- struct btrfs_balance_item *bi,
+static inline void btrfs_balance_sys(const struct extent_buffer *eb,
+ const struct btrfs_balance_item *bi,
struct btrfs_disk_balance_args *ba)
{
read_eb_member(eb, bi, struct btrfs_balance_item, sys, ba);
}
static inline void btrfs_set_balance_sys(struct extent_buffer *eb,
- struct btrfs_balance_item *bi,
- struct btrfs_disk_balance_args *ba)
+ struct btrfs_balance_item *bi,
+ const struct btrfs_disk_balance_args *ba)
{
write_eb_member(eb, bi, struct btrfs_balance_item, sys, ba);
}
static inline void
btrfs_disk_balance_args_to_cpu(struct btrfs_balance_args *cpu,
- struct btrfs_disk_balance_args *disk)
+ const struct btrfs_disk_balance_args *disk)
{
memset(cpu, 0, sizeof(*cpu));
@@ -2954,7 +2957,7 @@ btrfs_disk_balance_args_to_cpu(struct bt
static inline void
btrfs_cpu_balance_args_to_disk(struct btrfs_disk_balance_args *disk,
- struct btrfs_balance_args *cpu)
+ const struct btrfs_balance_args *cpu)
{
memset(disk, 0, sizeof(*disk));
@@ -3022,7 +3025,7 @@ BTRFS_SETGET_STACK_FUNCS(super_magic, st
BTRFS_SETGET_STACK_FUNCS(super_uuid_tree_generation, struct btrfs_super_block,
uuid_tree_generation, 64);
-static inline int btrfs_super_csum_size(struct btrfs_super_block *s)
+static inline int btrfs_super_csum_size(const struct btrfs_super_block *s)
{
u16 t = btrfs_super_csum_type(s);
/*
@@ -3041,8 +3044,8 @@ static inline unsigned long btrfs_leaf_d
* this returns the address of the start of the last item,
* which is the stop of the leaf data stack
*/
-static inline unsigned int leaf_data_end(struct btrfs_root *root,
- struct extent_buffer *leaf)
+static inline unsigned int leaf_data_end(const struct btrfs_root *root,
+ const struct extent_buffer *leaf)
{
u32 nr = btrfs_header_nritems(leaf);
@@ -3067,7 +3070,7 @@ BTRFS_SETGET_STACK_FUNCS(stack_file_exte
struct btrfs_file_extent_item, compression, 8);
static inline unsigned long
-btrfs_file_extent_inline_start(struct btrfs_file_extent_item *e)
+btrfs_file_extent_inline_start(const struct btrfs_file_extent_item *e)
{
return (unsigned long)e + BTRFS_FILE_EXTENT_INLINE_DATA_START;
}
@@ -3101,8 +3104,9 @@ BTRFS_SETGET_FUNCS(file_extent_other_enc
* size of any extent headers. If a file is compressed on disk, this is
* the compressed size
*/
-static inline u32 btrfs_file_extent_inline_item_len(struct extent_buffer *eb,
- struct btrfs_item *e)
+static inline u32 btrfs_file_extent_inline_item_len(
+ const struct extent_buffer *eb,
+ struct btrfs_item *e)
{
return btrfs_item_size(eb, e) - BTRFS_FILE_EXTENT_INLINE_DATA_START;
}
@@ -3110,9 +3114,9 @@ static inline u32 btrfs_file_extent_inli
/* this returns the number of file bytes represented by the inline item.
* If an item is compressed, this is the uncompressed size
*/
-static inline u32 btrfs_file_extent_inline_len(struct extent_buffer *eb,
- int slot,
- struct btrfs_file_extent_item *fi)
+static inline u32 btrfs_file_extent_inline_len(const struct extent_buffer *eb,
+ int slot,
+ const struct btrfs_file_extent_item *fi)
{
struct btrfs_map_token token;
@@ -3134,8 +3138,8 @@ static inline u32 btrfs_file_extent_inli
/* btrfs_dev_stats_item */
-static inline u64 btrfs_dev_stats_value(struct extent_buffer *eb,
- struct btrfs_dev_stats_item *ptr,
+static inline u64 btrfs_dev_stats_value(const struct extent_buffer *eb,
+ const struct btrfs_dev_stats_item *ptr,
int index)
{
u64 val;
--- a/fs/btrfs/extent_io.c
+++ b/fs/btrfs/extent_io.c
@@ -5111,9 +5111,8 @@ unlock_exit:
return ret;
}
-void read_extent_buffer(struct extent_buffer *eb, void *dstv,
- unsigned long start,
- unsigned long len)
+void read_extent_buffer(const struct extent_buffer *eb, void *dstv,
+ unsigned long start, unsigned long len)
{
size_t cur;
size_t offset;
@@ -5142,9 +5141,9 @@ void read_extent_buffer(struct extent_bu
}
}
-int read_extent_buffer_to_user(struct extent_buffer *eb, void __user *dstv,
- unsigned long start,
- unsigned long len)
+int read_extent_buffer_to_user(const struct extent_buffer *eb,
+ void __user *dstv,
+ unsigned long start, unsigned long len)
{
size_t cur;
size_t offset;
@@ -5179,10 +5178,10 @@ int read_extent_buffer_to_user(struct ex
return ret;
}
-int map_private_extent_buffer(struct extent_buffer *eb, unsigned long start,
- unsigned long min_len, char **map,
- unsigned long *map_start,
- unsigned long *map_len)
+int map_private_extent_buffer(const struct extent_buffer *eb,
+ unsigned long start, unsigned long min_len,
+ char **map, unsigned long *map_start,
+ unsigned long *map_len)
{
size_t offset = start & (PAGE_CACHE_SIZE - 1);
char *kaddr;
@@ -5217,9 +5216,8 @@ int map_private_extent_buffer(struct ext
return 0;
}
-int memcmp_extent_buffer(struct extent_buffer *eb, const void *ptrv,
- unsigned long start,
- unsigned long len)
+int memcmp_extent_buffer(const struct extent_buffer *eb, const void *ptrv,
+ unsigned long start, unsigned long len)
{
size_t cur;
size_t offset;
--- a/fs/btrfs/extent_io.h
+++ b/fs/btrfs/extent_io.h
@@ -291,14 +291,13 @@ static inline void extent_buffer_get(str
atomic_inc(&eb->refs);
}
-int memcmp_extent_buffer(struct extent_buffer *eb, const void *ptrv,
- unsigned long start,
- unsigned long len);
-void read_extent_buffer(struct extent_buffer *eb, void *dst,
+int memcmp_extent_buffer(const struct extent_buffer *eb, const void *ptrv,
+ unsigned long start, unsigned long len);
+void read_extent_buffer(const struct extent_buffer *eb, void *dst,
unsigned long start,
unsigned long len);
-int read_extent_buffer_to_user(struct extent_buffer *eb, void __user *dst,
- unsigned long start,
+int read_extent_buffer_to_user(const struct extent_buffer *eb,
+ void __user *dst, unsigned long start,
unsigned long len);
void write_extent_buffer(struct extent_buffer *eb, const void *src,
unsigned long start, unsigned long len);
@@ -317,10 +316,10 @@ int set_extent_buffer_uptodate(struct ex
int clear_extent_buffer_uptodate(struct extent_buffer *eb);
int extent_buffer_uptodate(struct extent_buffer *eb);
int extent_buffer_under_io(struct extent_buffer *eb);
-int map_private_extent_buffer(struct extent_buffer *eb, unsigned long offset,
- unsigned long min_len, char **map,
- unsigned long *map_start,
- unsigned long *map_len);
+int map_private_extent_buffer(const struct extent_buffer *eb,
+ unsigned long offset, unsigned long min_len,
+ char **map, unsigned long *map_start,
+ unsigned long *map_len);
int extent_range_clear_dirty_for_io(struct inode *inode, u64 start, u64 end);
int extent_range_redirty_for_io(struct inode *inode, u64 start, u64 end);
int extent_clear_unlock_delalloc(struct inode *inode, u64 start, u64 end,
--- a/fs/btrfs/struct-funcs.c
+++ b/fs/btrfs/struct-funcs.c
@@ -50,8 +50,8 @@ static inline void put_unaligned_le8(u8
*/
#define DEFINE_BTRFS_SETGET_BITS(bits) \
-u##bits btrfs_get_token_##bits(struct extent_buffer *eb, void *ptr, \
- unsigned long off, \
+u##bits btrfs_get_token_##bits(const struct extent_buffer *eb, \
+ const void *ptr, unsigned long off, \
struct btrfs_map_token *token) \
{ \
unsigned long part_offset = (unsigned long)ptr; \
@@ -90,7 +90,8 @@ u##bits btrfs_get_token_##bits(struct ex
return res; \
} \
void btrfs_set_token_##bits(struct extent_buffer *eb, \
- void *ptr, unsigned long off, u##bits val, \
+ const void *ptr, unsigned long off, \
+ u##bits val, \
struct btrfs_map_token *token) \
{ \
unsigned long part_offset = (unsigned long)ptr; \
@@ -133,7 +134,7 @@ DEFINE_BTRFS_SETGET_BITS(16)
DEFINE_BTRFS_SETGET_BITS(32)
DEFINE_BTRFS_SETGET_BITS(64)
-void btrfs_node_key(struct extent_buffer *eb,
+void btrfs_node_key(const struct extent_buffer *eb,
struct btrfs_disk_key *disk_key, int nr)
{
unsigned long ptr = btrfs_node_key_ptr_offset(nr);
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Florian Westphal <[email protected]>
commit 212e7f56605ef9688d0846db60c6c6ec06544095 upstream.
An earlier commit (1b789577f655060d98d20e,
"netfilter: arp_tables: init netns pointer in xt_tgchk_param struct")
fixed missing net initialization for arptables, but turns out it was
incomplete. We can get a very similar struct net NULL deref during
error unwinding:
general protection fault: 0000 [#1] PREEMPT SMP KASAN
RIP: 0010:xt_rateest_put+0xa1/0x440 net/netfilter/xt_RATEEST.c:77
xt_rateest_tg_destroy+0x72/0xa0 net/netfilter/xt_RATEEST.c:175
cleanup_entry net/ipv4/netfilter/arp_tables.c:509 [inline]
translate_table+0x11f4/0x1d80 net/ipv4/netfilter/arp_tables.c:587
do_replace net/ipv4/netfilter/arp_tables.c:981 [inline]
do_arpt_set_ctl+0x317/0x650 net/ipv4/netfilter/arp_tables.c:1461
Also init the netns pointer in xt_tgdtor_param struct.
Fixes: add67461240c1d ("netfilter: add struct net * to target parameters")
Reported-by: [email protected]
Signed-off-by: Florian Westphal <[email protected]>
Signed-off-by: Pablo Neira Ayuso <[email protected]>
[bwh: Backported to 3.16:
- __arpt_unregister_table() has not been split out of
arpt_unregister_table()
- Add "net" parameter to arpt_unregister_table() and update its only
caller in arptable_filter.c]
Signed-off-by: Ben Hutchings <[email protected]>
---
--- a/include/linux/netfilter_arp/arp_tables.h
+++ b/include/linux/netfilter_arp/arp_tables.h
@@ -51,7 +51,7 @@ extern void *arpt_alloc_initial_table(co
extern struct xt_table *arpt_register_table(struct net *net,
const struct xt_table *table,
const struct arpt_replace *repl);
-extern void arpt_unregister_table(struct xt_table *table);
+extern void arpt_unregister_table(struct net *, struct xt_table *table);
extern unsigned int arpt_do_table(struct sk_buff *skb,
unsigned int hook,
const struct net_device *in,
--- a/net/ipv4/netfilter/arp_tables.c
+++ b/net/ipv4/netfilter/arp_tables.c
@@ -602,12 +602,13 @@ static inline int check_entry_size_and_h
return 0;
}
-static inline void cleanup_entry(struct arpt_entry *e)
+static void cleanup_entry(struct arpt_entry *e, struct net *net)
{
struct xt_tgdtor_param par;
struct xt_entry_target *t;
t = arpt_get_target(e);
+ par.net = net;
par.target = t->u.kernel.target;
par.targinfo = t->data;
par.family = NFPROTO_ARP;
@@ -706,7 +707,7 @@ static int translate_table(struct net *n
xt_entry_foreach(iter, entry0, newinfo->size) {
if (i-- == 0)
break;
- cleanup_entry(iter);
+ cleanup_entry(iter, net);
}
return ret;
}
@@ -1051,7 +1052,7 @@ static int __do_replace(struct net *net,
/* Decrease module usage counts and free resource */
loc_cpu_old_entry = oldinfo->entries[raw_smp_processor_id()];
xt_entry_foreach(iter, loc_cpu_old_entry, oldinfo->size)
- cleanup_entry(iter);
+ cleanup_entry(iter, net);
xt_free_table_info(oldinfo);
if (copy_to_user(counters_ptr, counters,
@@ -1118,7 +1119,7 @@ static int do_replace(struct net *net, c
free_newinfo_untrans:
xt_entry_foreach(iter, loc_cpu_entry, newinfo->size)
- cleanup_entry(iter);
+ cleanup_entry(iter, net);
free_newinfo:
xt_free_table_info(newinfo);
return ret;
@@ -1431,7 +1432,7 @@ static int compat_do_replace(struct net
free_newinfo_untrans:
xt_entry_foreach(iter, loc_cpu_entry, newinfo->size)
- cleanup_entry(iter);
+ cleanup_entry(iter, net);
free_newinfo:
xt_free_table_info(newinfo);
return ret;
@@ -1708,7 +1709,7 @@ out:
return ERR_PTR(ret);
}
-void arpt_unregister_table(struct xt_table *table)
+void arpt_unregister_table(struct net *net, struct xt_table *table)
{
struct xt_table_info *private;
void *loc_cpu_entry;
@@ -1720,7 +1721,7 @@ void arpt_unregister_table(struct xt_tab
/* Decrease module usage counts and free resources */
loc_cpu_entry = private->entries[raw_smp_processor_id()];
xt_entry_foreach(iter, loc_cpu_entry, private->size)
- cleanup_entry(iter);
+ cleanup_entry(iter, net);
if (private->number > private->initial_entries)
module_put(table_owner);
xt_free_table_info(private);
--- a/net/ipv4/netfilter/arptable_filter.c
+++ b/net/ipv4/netfilter/arptable_filter.c
@@ -54,7 +54,7 @@ static int __net_init arptable_filter_ne
static void __net_exit arptable_filter_net_exit(struct net *net)
{
- arpt_unregister_table(net->ipv4.arptable_filter);
+ arpt_unregister_table(net, net->ipv4.arptable_filter);
}
static struct pernet_operations arptable_filter_net_ops = {
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Takashi Iwai <[email protected]>
commit 60adcfde92fa40fcb2dbf7cc52f9b096e0cd109a upstream.
snd_seq_info_timer_read() reads the information of the timer assigned
for each queue, but it's done in a racy way which may lead to UAF as
spotted by syzkaller.
This patch applies the missing q->timer_mutex lock while accessing the
timer object as well as a slight code change to adapt the standard
coding style.
Reported-by: [email protected]
Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Takashi Iwai <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
sound/core/seq/seq_timer.c | 14 +++++++++-----
1 file changed, 9 insertions(+), 5 deletions(-)
--- a/sound/core/seq/seq_timer.c
+++ b/sound/core/seq/seq_timer.c
@@ -484,15 +484,19 @@ void snd_seq_info_timer_read(struct snd_
q = queueptr(idx);
if (q == NULL)
continue;
- if ((tmr = q->timer) == NULL ||
- (ti = tmr->timeri) == NULL) {
- queuefree(q);
- continue;
- }
+ mutex_lock(&q->timer_mutex);
+ tmr = q->timer;
+ if (!tmr)
+ goto unlock;
+ ti = tmr->timeri;
+ if (!ti)
+ goto unlock;
snd_iprintf(buffer, "Timer for queue %i : %s\n", q->queue, ti->timer->name);
resolution = snd_timer_resolution(ti) * tmr->ticks;
snd_iprintf(buffer, " Period time : %lu.%09lu\n", resolution / 1000000000, resolution % 1000000000);
snd_iprintf(buffer, " Skew : %u / %u\n", tmr->skew, tmr->skew_base);
+unlock:
+ mutex_unlock(&q->timer_mutex);
queuefree(q);
}
}
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Michał Mirosław <[email protected]>
commit 2a187d03352086e300daa2044051db00044cd171 upstream.
For SDHCIv3+ with programmable clock mode, minimal clock frequency is
still base clock / max(divider). Minimal programmable clock frequency is
always greater than minimal divided clock frequency. Without this patch,
SDHCI uses out-of-spec initial frequency when multiplier is big enough:
mmc1: mmc_rescan_try_freq: trying to init card at 468750 Hz
[for 480 MHz source clock divided by 1024]
The code in sdhci_calc_clk() already chooses a correct SDCLK clock mode.
Fixes: c3ed3877625f ("mmc: sdhci: add support for programmable clock mode")
Signed-off-by: Michał Mirosław <[email protected]>
Acked-by: Adrian Hunter <[email protected]>
Link: https://lore.kernel.org/r/ffb489519a446caffe7a0a05c4b9372bd52397bb.1579082031.git.mirq-linux@rere.qmqm.pl
Signed-off-by: Ulf Hansson <[email protected]>
[bwh: Backported to 3.16: adjust context]
Signed-off-by: Ben Hutchings <[email protected]>
---
drivers/mmc/host/sdhci.c | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -2945,11 +2945,13 @@ int sdhci_add_host(struct sdhci_host *ho
if (host->ops->get_min_clock)
mmc->f_min = host->ops->get_min_clock(host);
else if (host->version >= SDHCI_SPEC_300) {
- if (host->clk_mul) {
- mmc->f_min = (host->max_clk * host->clk_mul) / 1024;
+ if (host->clk_mul)
mmc->f_max = host->max_clk * host->clk_mul;
- } else
- mmc->f_min = host->max_clk / SDHCI_MAX_DIV_SPEC_300;
+ /*
+ * Divided Clock Mode minimum clock rate is always less than
+ * Programmable Clock Mode minimum clock rate.
+ */
+ mmc->f_min = host->max_clk / SDHCI_MAX_DIV_SPEC_300;
} else
mmc->f_min = host->max_clk / SDHCI_MAX_DIV_SPEC_200;
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Johan Hovold <[email protected]>
commit fdb838efa31e1ed9a13ae6ad0b64e30fdbd00570 upstream.
USB-serial drivers must not be unbound from their ports before the
corresponding USB driver is unbound from the parent interface so
suppress the bind and unbind attributes.
Unbinding a serial driver while it's port is open is a sure way to
trigger a crash as any driver state is released on unbind while port
hangup is handled on the parent USB interface level. Drivers for
multiport devices where ports share a resource such as an interrupt
endpoint also generally cannot handle individual ports going away.
Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Reviewed-by: Greg Kroah-Hartman <[email protected]>
Signed-off-by: Johan Hovold <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
drivers/usb/serial/usb-serial.c | 3 +++
1 file changed, 3 insertions(+)
--- a/drivers/usb/serial/usb-serial.c
+++ b/drivers/usb/serial/usb-serial.c
@@ -1337,6 +1337,9 @@ static int usb_serial_register(struct us
return -EINVAL;
}
+ /* Prevent individual ports from being unbound. */
+ driver->driver.suppress_bind_attrs = true;
+
usb_serial_operations_init(driver);
/* Add this device to our list of devices */
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Finn Thain <[email protected]>
commit e3885f576196ddfc670b3d53e745de96ffcb49ab upstream.
The driver accesses descriptor memory which is simultaneously accessed by
the chip, so the compiler must not be allowed to re-order CPU accesses.
sonic_buf_get() used 'volatile' to prevent that. sonic_buf_put() should
have done so too but was overlooked.
Fixes: efcce839360f ("[PATCH] macsonic/jazzsonic network drivers update")
Tested-by: Stan Johnson <[email protected]>
Signed-off-by: Finn Thain <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
drivers/net/ethernet/natsemi/sonic.h | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
--- a/drivers/net/ethernet/natsemi/sonic.h
+++ b/drivers/net/ethernet/natsemi/sonic.h
@@ -342,30 +342,30 @@ static void sonic_tx_timeout(struct net_
as far as we can tell. */
/* OpenBSD calls this "SWO". I'd like to think that sonic_buf_put()
is a much better name. */
-static inline void sonic_buf_put(void* base, int bitmode,
+static inline void sonic_buf_put(u16 *base, int bitmode,
int offset, __u16 val)
{
if (bitmode)
#ifdef __BIG_ENDIAN
- ((__u16 *) base + (offset*2))[1] = val;
+ __raw_writew(val, base + (offset * 2) + 1);
#else
- ((__u16 *) base + (offset*2))[0] = val;
+ __raw_writew(val, base + (offset * 2) + 0);
#endif
else
- ((__u16 *) base)[offset] = val;
+ __raw_writew(val, base + (offset * 1) + 0);
}
-static inline __u16 sonic_buf_get(void* base, int bitmode,
+static inline __u16 sonic_buf_get(u16 *base, int bitmode,
int offset)
{
if (bitmode)
#ifdef __BIG_ENDIAN
- return ((volatile __u16 *) base + (offset*2))[1];
+ return __raw_readw(base + (offset * 2) + 1);
#else
- return ((volatile __u16 *) base + (offset*2))[0];
+ return __raw_readw(base + (offset * 2) + 0);
#endif
else
- return ((volatile __u16 *) base)[offset];
+ return __raw_readw(base + (offset * 1) + 0);
}
/* Inlines that you should actually use for reading/writing DMA buffers */
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Eugenio Pérez <[email protected]>
commit 42d84c8490f9f0931786f1623191fcab397c3d64 upstream.
Doing so, we save one call to get data we already have in the struct.
Also, since there is no guarantee that getname use sockaddr_ll
parameter beyond its size, we add a little bit of security here.
It should do not do beyond MAX_ADDR_LEN, but syzbot found that
ax25_getname writes more (72 bytes, the size of full_sockaddr_ax25,
versus 20 + 32 bytes of sockaddr_ll + MAX_ADDR_LEN in syzbot repro).
Fixes: 3a4d5c94e9593 ("vhost_net: a kernel-level virtio server")
Reported-by: [email protected]
Signed-off-by: Eugenio Pérez <[email protected]>
Acked-by: Michael S. Tsirkin <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
[bwh: Backported to 3.16: Also delete "uaddr_len" variable]
Signed-off-by: Ben Hutchings <[email protected]>
---
--- a/drivers/vhost/net.c
+++ b/drivers/vhost/net.c
@@ -843,11 +843,7 @@ static int vhost_net_release(struct inod
static struct socket *get_raw_socket(int fd)
{
- struct {
- struct sockaddr_ll sa;
- char buf[MAX_ADDR_LEN];
- } uaddr;
- int uaddr_len = sizeof uaddr, r;
+ int r;
struct socket *sock = sockfd_lookup(fd, &r);
if (!sock)
@@ -859,12 +855,7 @@ static struct socket *get_raw_socket(int
goto err;
}
- r = sock->ops->getname(sock, (struct sockaddr *)&uaddr.sa,
- &uaddr_len, 0);
- if (r)
- goto err;
-
- if (uaddr.sa.sll_family != AF_PACKET) {
+ if (sock->sk->sk_family != AF_PACKET) {
r = -EPFNOSUPPORT;
goto err;
}
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Finn Thain <[email protected]>
commit 3f4b7e6a2be982fd8820a2b54d46dd9c351db899 upstream.
Make sure the SONIC's DMA engine is idle before altering the transmit
and receive descriptors. Add a helper for this as it will be needed
again.
Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Tested-by: Stan Johnson <[email protected]>
Signed-off-by: Finn Thain <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
drivers/net/ethernet/natsemi/sonic.c | 25 +++++++++++++++++++++++++
drivers/net/ethernet/natsemi/sonic.h | 3 +++
2 files changed, 28 insertions(+)
--- a/drivers/net/ethernet/natsemi/sonic.c
+++ b/drivers/net/ethernet/natsemi/sonic.c
@@ -103,6 +103,24 @@ static int sonic_open(struct net_device
return 0;
}
+/* Wait for the SONIC to become idle. */
+static void sonic_quiesce(struct net_device *dev, u16 mask)
+{
+ struct sonic_local * __maybe_unused lp = netdev_priv(dev);
+ int i;
+ u16 bits;
+
+ for (i = 0; i < 1000; ++i) {
+ bits = SONIC_READ(SONIC_CMD) & mask;
+ if (!bits)
+ return;
+ if (irqs_disabled() || in_interrupt())
+ udelay(20);
+ else
+ usleep_range(100, 200);
+ }
+ WARN_ONCE(1, "command deadline expired! 0x%04x\n", bits);
+}
/*
* Close the SONIC device
@@ -120,6 +138,9 @@ static int sonic_close(struct net_device
/*
* stop the SONIC, disable interrupts
*/
+ SONIC_WRITE(SONIC_CMD, SONIC_CR_RXDIS);
+ sonic_quiesce(dev, SONIC_CR_ALL);
+
SONIC_WRITE(SONIC_IMR, 0);
SONIC_WRITE(SONIC_ISR, 0x7fff);
SONIC_WRITE(SONIC_CMD, SONIC_CR_RST);
@@ -159,6 +180,9 @@ static void sonic_tx_timeout(struct net_
* put the Sonic into software-reset mode and
* disable all interrupts before releasing DMA buffers
*/
+ SONIC_WRITE(SONIC_CMD, SONIC_CR_RXDIS);
+ sonic_quiesce(dev, SONIC_CR_ALL);
+
SONIC_WRITE(SONIC_IMR, 0);
SONIC_WRITE(SONIC_ISR, 0x7fff);
SONIC_WRITE(SONIC_CMD, SONIC_CR_RST);
@@ -638,6 +662,7 @@ static int sonic_init(struct net_device
*/
SONIC_WRITE(SONIC_CMD, 0);
SONIC_WRITE(SONIC_CMD, SONIC_CR_RXDIS);
+ sonic_quiesce(dev, SONIC_CR_ALL);
/*
* initialize the receive resource area
--- a/drivers/net/ethernet/natsemi/sonic.h
+++ b/drivers/net/ethernet/natsemi/sonic.h
@@ -109,6 +109,9 @@
#define SONIC_CR_TXP 0x0002
#define SONIC_CR_HTX 0x0001
+#define SONIC_CR_ALL (SONIC_CR_LCAM | SONIC_CR_RRRA | \
+ SONIC_CR_RXEN | SONIC_CR_TXP)
+
/*
* SONIC data configuration bits
*/
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Johan Hovold <[email protected]>
commit e37d1aeda737a20b1846a91a3da3f8b0f00cf690 upstream.
Check for NULL port data in the shared interrupt and bulk completion
callbacks to avoid dereferencing a NULL pointer in case a device sends
data for a port device which isn't bound to a driver (e.g. due to a
malicious device having unexpected endpoints or after an allocation
failure on port probe).
Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Reviewed-by: Greg Kroah-Hartman <[email protected]>
Signed-off-by: Johan Hovold <[email protected]>
[bwh: Backported to 3.16: adjust context]
Signed-off-by: Ben Hutchings <[email protected]>
---
drivers/usb/serial/io_edgeport.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
--- a/drivers/usb/serial/io_edgeport.c
+++ b/drivers/usb/serial/io_edgeport.c
@@ -638,7 +638,7 @@ static void edge_interrupt_callback(stru
if (txCredits) {
port = edge_serial->serial->port[portNumber];
edge_port = usb_get_serial_port_data(port);
- if (edge_port->open) {
+ if (edge_port && edge_port->open) {
spin_lock(&edge_port->ep_lock);
edge_port->txCredits += txCredits;
spin_unlock(&edge_port->ep_lock);
@@ -1775,7 +1775,7 @@ static void process_rcvd_data(struct edg
port = edge_serial->serial->port[
edge_serial->rxPort];
edge_port = usb_get_serial_port_data(port);
- if (edge_port->open) {
+ if (edge_port && edge_port->open) {
dev_dbg(dev, "%s - Sending %d bytes to TTY for port %d\n",
__func__, rxLen,
edge_serial->rxPort);
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Zhang Xiaoxu <[email protected]>
commit 513dc792d6060d5ef572e43852683097a8420f56 upstream.
When syzkaller tests, there is a UAF:
BUG: KASan: use after free in vgacon_invert_region+0x9d/0x110 at addr
ffff880000100000
Read of size 2 by task syz-executor.1/16489
page:ffffea0000004000 count:0 mapcount:-127 mapping: (null)
index:0x0
page flags: 0xfffff00000000()
page dumped because: kasan: bad access detected
CPU: 1 PID: 16489 Comm: syz-executor.1 Not tainted
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS
rel-1.9.3-0-ge2fc41e-prebuilt.qemu-project.org 04/01/2014
Call Trace:
[<ffffffffb119f309>] dump_stack+0x1e/0x20
[<ffffffffb04af957>] kasan_report+0x577/0x950
[<ffffffffb04ae652>] __asan_load2+0x62/0x80
[<ffffffffb090f26d>] vgacon_invert_region+0x9d/0x110
[<ffffffffb0a39d95>] invert_screen+0xe5/0x470
[<ffffffffb0a21dcb>] set_selection+0x44b/0x12f0
[<ffffffffb0a3bfae>] tioclinux+0xee/0x490
[<ffffffffb0a1d114>] vt_ioctl+0xff4/0x2670
[<ffffffffb0a0089a>] tty_ioctl+0x46a/0x1a10
[<ffffffffb052db3d>] do_vfs_ioctl+0x5bd/0xc40
[<ffffffffb052e2f2>] SyS_ioctl+0x132/0x170
[<ffffffffb11c9b1b>] system_call_fastpath+0x22/0x27
Memory state around the buggy address:
ffff8800000fff00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00
ffff8800000fff80: 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00
>ffff880000100000: ff ff ff ff ff ff ff ff ff ff ff ff ff
ff ff ff
It can be reproduce in the linux mainline by the program:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <linux/vt.h>
struct tiocl_selection {
unsigned short xs; /* X start */
unsigned short ys; /* Y start */
unsigned short xe; /* X end */
unsigned short ye; /* Y end */
unsigned short sel_mode; /* selection mode */
};
#define TIOCL_SETSEL 2
struct tiocl {
unsigned char type;
unsigned char pad;
struct tiocl_selection sel;
};
int main()
{
int fd = 0;
const char *dev = "/dev/char/4:1";
struct vt_consize v = {0};
struct tiocl tioc = {0};
fd = open(dev, O_RDWR, 0);
v.v_rows = 3346;
ioctl(fd, VT_RESIZEX, &v);
tioc.type = TIOCL_SETSEL;
ioctl(fd, TIOCLINUX, &tioc);
return 0;
}
When resize the screen, update the 'vc->vc_size_row' to the new_row_size,
but when 'set_origin' in 'vgacon_set_origin', vgacon use 'vga_vram_base'
for 'vc_origin' and 'vc_visible_origin', not 'vc_screenbuf'. It maybe
smaller than 'vc_screenbuf'. When TIOCLINUX, use the new_row_size to calc
the offset, it maybe larger than the vga_vram_size in vgacon driver, then
bad access.
Also, if set an larger screenbuf firstly, then set an more larger
screenbuf, when copy old_origin to new_origin, a bad access may happen.
So, If the screen size larger than vga_vram, resize screen should be
failed. This alse fix CVE-2020-8649 and CVE-2020-8647.
Linus pointed out that overflow checking seems absent. We're saved by
the existing bounds checks in vc_do_resize() with rather strict
limits:
if (cols > VC_RESIZE_MAXCOL || lines > VC_RESIZE_MAXROW)
return -EINVAL;
Fixes: 0aec4867dca14 ("[PATCH] SVGATextMode fix")
Reference: CVE-2020-8647 and CVE-2020-8649
Reported-by: Hulk Robot <[email protected]>
Signed-off-by: Zhang Xiaoxu <[email protected]>
[danvet: augment commit message to point out overflow safety]
Signed-off-by: Daniel Vetter <[email protected]>
Link: https://patchwork.freedesktop.org/patch/msgid/[email protected]
Signed-off-by: Ben Hutchings <[email protected]>
---
drivers/video/console/vgacon.c | 3 +++
1 file changed, 3 insertions(+)
--- a/drivers/video/console/vgacon.c
+++ b/drivers/video/console/vgacon.c
@@ -1312,6 +1312,9 @@ static int vgacon_font_get(struct vc_dat
static int vgacon_resize(struct vc_data *c, unsigned int width,
unsigned int height, unsigned int user)
{
+ if ((width << 1) * height > vga_vram_size)
+ return -EINVAL;
+
if (width % 2 || width > screen_info.orig_video_cols ||
height > (screen_info.orig_video_lines * vga_default_font_height)/
c->vc_font.height)
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Eric Dumazet <[email protected]>
commit d9e15a2733067c9328fb56d98fe8e574fa19ec31 upstream.
As diagnosed by Florian :
If TCA_FQ_QUANTUM is set to 0x80000000, fq_deueue()
can loop forever in :
if (f->credit <= 0) {
f->credit += q->quantum;
goto begin;
}
... because f->credit is either 0 or -2147483648.
Let's limit TCA_FQ_QUANTUM to no more than 1 << 20 :
This max value should limit risks of breaking user setups
while fixing this bug.
Fixes: afe4fd062416 ("pkt_sched: fq: Fair Queue packet scheduler")
Signed-off-by: Eric Dumazet <[email protected]>
Diagnosed-by: Florian Westphal <[email protected]>
Reported-by: [email protected]
Signed-off-by: David S. Miller <[email protected]>
[bwh: Backported to 3.16: Drop call to NL_SET_ERR_MSG_MOD() as extack is
not supported.]
Signed-off-by: Ben Hutchings <[email protected]>
---
--- a/net/sched/sch_fq.c
+++ b/net/sched/sch_fq.c
@@ -690,7 +690,7 @@ static int fq_change(struct Qdisc *sch,
if (tb[TCA_FQ_QUANTUM]) {
u32 quantum = nla_get_u32(tb[TCA_FQ_QUANTUM]);
- if (quantum > 0)
+ if (quantum > 0 && quantum <= (1 << 20))
q->quantum = quantum;
else
err = -EINVAL;
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Jerónimo Borque <[email protected]>
commit 260e41ac4dd3e5acb90be624c03ba7f019615b75 upstream.
Add device-ids for the Motorola Solutions TETRA radios MTP3xxx series
and MTP85xx series
$ lsusb -vd 0cad:
Bus 001 Device 009: ID 0cad:9015 Motorola CGISS TETRA PEI interface
Device Descriptor:
bLength 18
bDescriptorType 1
bcdUSB 2.00
bDeviceClass 0
bDeviceSubClass 0
bDeviceProtocol 0
bMaxPacketSize0 64
idVendor 0x0cad Motorola CGISS
idProduct 0x9015
bcdDevice 24.16
iManufacturer 1
iProduct 2
iSerial 0
bNumConfigurations 1
Configuration Descriptor:
bLength 9
bDescriptorType 2
wTotalLength 0x0037
bNumInterfaces 2
bConfigurationValue 1
iConfiguration 3
bmAttributes 0x80
(Bus Powered)
MaxPower 500mA
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 0
bAlternateSetting 0
bNumEndpoints 2
bInterfaceClass 255 Vendor Specific Class
bInterfaceSubClass 0
bInterfaceProtocol 0
iInterface 0
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x81 EP 1 IN
bmAttributes 2
Transfer Type Bulk
Synch Type None
Usage Type Data
wMaxPacketSize 0x0040 1x 64 bytes
bInterval 0
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x01 EP 1 OUT
bmAttributes 2
Transfer Type Bulk
Synch Type None
Usage Type Data
wMaxPacketSize 0x0040 1x 64 bytes
bInterval 0
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 1
bAlternateSetting 0
bNumEndpoints 2
bInterfaceClass 255 Vendor Specific Class
bInterfaceSubClass 0
bInterfaceProtocol 0
iInterface 0
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x82 EP 2 IN
bmAttributes 2
Transfer Type Bulk
Synch Type None
Usage Type Data
wMaxPacketSize 0x0040 1x 64 bytes
bInterval 0
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x02 EP 2 OUT
bmAttributes 2
Transfer Type Bulk
Synch Type None
Usage Type Data
wMaxPacketSize 0x0040 1x 64 bytes
bInterval 0
Bus 001 Device 010: ID 0cad:9013 Motorola CGISS TETRA PEI interface
Device Descriptor:
bLength 18
bDescriptorType 1
bcdUSB 2.00
bDeviceClass 0
bDeviceSubClass 0
bDeviceProtocol 0
bMaxPacketSize0 64
idVendor 0x0cad Motorola CGISS
idProduct 0x9013
bcdDevice 24.16
iManufacturer 1
iProduct 2
iSerial 0
bNumConfigurations 1
Configuration Descriptor:
bLength 9
bDescriptorType 2
wTotalLength 0x0037
bNumInterfaces 2
bConfigurationValue 1
iConfiguration 3
bmAttributes 0x80
(Bus Powered)
MaxPower 500mA
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 0
bAlternateSetting 0
bNumEndpoints 2
bInterfaceClass 255 Vendor Specific Class
bInterfaceSubClass 0
bInterfaceProtocol 0
iInterface 0
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x81 EP 1 IN
bmAttributes 2
Transfer Type Bulk
Synch Type None
Usage Type Data
wMaxPacketSize 0x0200 1x 512 bytes
bInterval 0
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x01 EP 1 OUT
bmAttributes 2
Transfer Type Bulk
Synch Type None
Usage Type Data
wMaxPacketSize 0x0200 1x 512 bytes
bInterval 0
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 1
bAlternateSetting 0
bNumEndpoints 2
bInterfaceClass 255 Vendor Specific Class
bInterfaceSubClass 0
bInterfaceProtocol 0
iInterface 0
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x82 EP 2 IN
bmAttributes 2
Transfer Type Bulk
Synch Type None
Usage Type Data
wMaxPacketSize 0x0200 1x 512 bytes
bInterval 0
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x02 EP 2 OUT
bmAttributes 2
Transfer Type Bulk
Synch Type None
Usage Type Data
wMaxPacketSize 0x0200 1x 512 bytes
bInterval 0
Signed-off-by: Jerónimo Borque <[email protected]>
Signed-off-by: Johan Hovold <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
drivers/usb/serial/usb-serial-simple.c | 2 ++
1 file changed, 2 insertions(+)
--- a/drivers/usb/serial/usb-serial-simple.c
+++ b/drivers/usb/serial/usb-serial-simple.c
@@ -89,6 +89,8 @@ DEVICE(moto_modem, MOTO_IDS);
#define MOTOROLA_TETRA_IDS() \
{ USB_DEVICE(0x0cad, 0x9011) }, /* Motorola Solutions TETRA PEI */ \
{ USB_DEVICE(0x0cad, 0x9012) }, /* MTP6550 */ \
+ { USB_DEVICE(0x0cad, 0x9013) }, /* MTP3xxx */ \
+ { USB_DEVICE(0x0cad, 0x9015) }, /* MTP85xx */ \
{ USB_DEVICE(0x0cad, 0x9016) } /* TPG2200 */
DEVICE(motorola_tetra, MOTOROLA_TETRA_IDS);
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Suren Baghdasaryan <[email protected]>
commit 6d67b0290b4b84c477e6a2fc6e005e174d3c7786 upstream.
When ashmem file is mmapped, the resulting vma->vm_file points to the
backing shmem file with the generic fops that do not check ashmem
permissions like fops of ashmem do. If an mremap is done on the ashmem
region, then the permission checks will be skipped. Fix that by disallowing
mapping operation on the backing shmem file.
Reported-by: Jann Horn <[email protected]>
Signed-off-by: Suren Baghdasaryan <[email protected]>
Signed-off-by: Todd Kjos <[email protected]>
Reviewed-by: Joel Fernandes (Google) <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Greg Kroah-Hartman <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
drivers/staging/android/ashmem.c | 28 ++++++++++++++++++++++++++++
1 file changed, 28 insertions(+)
--- a/drivers/staging/android/ashmem.c
+++ b/drivers/staging/android/ashmem.c
@@ -351,8 +351,23 @@ static inline vm_flags_t calc_vm_may_fla
_calc_vm_trans(prot, PROT_EXEC, VM_MAYEXEC);
}
+static int ashmem_vmfile_mmap(struct file *file, struct vm_area_struct *vma)
+{
+ /* do not allow to mmap ashmem backing shmem file directly */
+ return -EPERM;
+}
+
+static unsigned long
+ashmem_vmfile_get_unmapped_area(struct file *file, unsigned long addr,
+ unsigned long len, unsigned long pgoff,
+ unsigned long flags)
+{
+ return current->mm->get_unmapped_area(file, addr, len, pgoff, flags);
+}
+
static int ashmem_mmap(struct file *file, struct vm_area_struct *vma)
{
+ static struct file_operations vmfile_fops;
struct ashmem_area *asma = file->private_data;
int ret = 0;
@@ -386,6 +401,19 @@ static int ashmem_mmap(struct file *file
goto out;
}
asma->file = vmfile;
+ /*
+ * override mmap operation of the vmfile so that it can't be
+ * remapped which would lead to creation of a new vma with no
+ * asma permission checks. Have to override get_unmapped_area
+ * as well to prevent VM_BUG_ON check for f_ops modification.
+ */
+ if (!vmfile_fops.mmap) {
+ vmfile_fops = *vmfile->f_op;
+ vmfile_fops.mmap = ashmem_vmfile_mmap;
+ vmfile_fops.get_unmapped_area =
+ ashmem_vmfile_get_unmapped_area;
+ }
+ vmfile->f_op = &vmfile_fops;
}
get_file(asma->file);
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Eric Dumazet <[email protected]>
commit 1f85e6267caca44b30c54711652b0726fadbb131 upstream.
Backport of commit fdfc5c8594c2 ("tcp: remove empty skb from
write queue in error cases") in linux-4.14 stable triggered
various bugs. One of them has been fixed in commit ba2ddb43f270
("tcp: Don't dequeue SYN/FIN-segments from write-queue"), but
we still have crashes in some occasions.
Root-cause is that when tcp_sendmsg() has allocated a fresh
skb and could not append a fragment before being blocked
in sk_stream_wait_memory(), tcp_write_xmit() might be called
and decide to send this fresh and empty skb.
Sending an empty packet is not only silly, it might have caused
many issues we had in the past with tp->packets_out being
out of sync.
Fixes: c65f7f00c587 ("[TCP]: Simplify SKB data portion allocation with NETIF_F_SG.")
Signed-off-by: Eric Dumazet <[email protected]>
Cc: Christoph Paasch <[email protected]>
Acked-by: Neal Cardwell <[email protected]>
Cc: Jason Baron <[email protected]>
Acked-by: Soheil Hassas Yeganeh <[email protected]>
Signed-off-by: Jakub Kicinski <[email protected]>
[bwh: Backported to 3.16: adjust context]
Signed-off-by: Ben Hutchings <[email protected]>
---
net/ipv4/tcp_output.c | 8 ++++++++
1 file changed, 8 insertions(+)
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -1992,6 +1992,14 @@ static bool tcp_write_xmit(struct sock *
unlikely(tso_fragment(sk, skb, limit, mss_now, gfp)))
break;
+ /* Argh, we hit an empty skb(), presumably a thread
+ * is sleeping in sendmsg()/sk_stream_wait_memory().
+ * We do not want to send a pure-ack packet and have
+ * a strange looking rtx queue with empty packet(s).
+ */
+ if (TCP_SKB_CB(skb)->end_seq == TCP_SKB_CB(skb)->seq)
+ break;
+
TCP_SKB_CB(skb)->when = tcp_time_stamp;
if (unlikely(tcp_transmit_skb(sk, skb, 1, gfp)))
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Eric Dumazet <[email protected]>
commit 1712b2fff8c682d145c7889d2290696647d82dab upstream.
I missed the fact that macvlan_broadcast() can be used both
in RX and TX.
skb_eth_hdr() makes only sense in TX paths, so we can not
use it blindly in macvlan_broadcast()
Fixes: 96cc4b69581d ("macvlan: do not assume mac_header is set in macvlan_broadcast()")
Signed-off-by: Eric Dumazet <[email protected]>
Reported-by: Jurgen Van Ham <[email protected]>
Tested-by: Matteo Croce <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
drivers/net/macvlan.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
--- a/drivers/net/macvlan.c
+++ b/drivers/net/macvlan.c
@@ -162,7 +162,7 @@ static void macvlan_broadcast(struct sk_
struct net_device *src,
enum macvlan_mode mode)
{
- const struct ethhdr *eth = skb_eth_hdr(skb);
+ const struct ethhdr *eth = eth_hdr(skb);
const struct macvlan_dev *vlan;
struct sk_buff *nskb;
unsigned int i;
@@ -345,10 +345,11 @@ static int macvlan_queue_xmit(struct sk_
const struct macvlan_dev *dest;
if (vlan->mode == MACVLAN_MODE_BRIDGE) {
- const struct ethhdr *eth = (void *)skb->data;
+ const struct ethhdr *eth = skb_eth_hdr(skb);
/* send to other bridge ports directly */
if (is_multicast_ether_addr(eth->h_dest)) {
+ skb_reset_mac_header(skb);
macvlan_broadcast(skb, port, dev, MACVLAN_MODE_BRIDGE);
goto xmit_world;
}
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Fabian Henneke <[email protected]>
commit 378b80370aa1fe50f9c48a3ac8af3e416e73b89f upstream.
Always return EPOLLOUT from hidraw_poll when a device is connected.
This is safe since writes are always possible (but will always block).
hidraw does not support non-blocking writes and instead always calls
blocking backend functions on write requests. Hence, so far, a call to
poll never returned EPOLLOUT, which confuses tools like socat.
Signed-off-by: Fabian Henneke <[email protected]>
In-reply-to: <CA+hv5qkyis03CgYTWeWX9cr0my-d2Oe+aZo+mjmWRXgjrGqyrw@mail.gmail.com>
Signed-off-by: Jiri Kosina <[email protected]>
[bwh: Backported to 3.16: s/EPOLL/POLL/]
Signed-off-by: Ben Hutchings <[email protected]>
---
drivers/hid/hidraw.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/hid/hidraw.c
+++ b/drivers/hid/hidraw.c
@@ -265,7 +265,7 @@ static unsigned int hidraw_poll(struct f
poll_wait(file, &list->hidraw->wait, wait);
if (list->head != list->tail)
- return POLLIN | POLLRDNORM;
+ return POLLIN | POLLRDNORM | POLLOUT;
if (!list->hidraw->exist)
return POLLERR | POLLHUP;
return 0;
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: James Bottomley <[email protected]>
commit 529244bd1afc102ab164429d338d310d5d65e60d upstream.
Doing an add/remove/add on a SCSI device in an enclosure leads to an oops
caused by poisoned values in the enclosure device list pointers. The
reason is because we are keeping the enclosure device across the enclosed
device add/remove/add but the current code is doing a
device_add/device_del/device_add on it. This is the wrong thing to do in
sysfs, so fix it by not doing a device_del on the enclosure device simply
because of a hot remove of the drive in the slot.
[mkp: added missing email addresses]
Fixes: 43d8eb9cfd0a ("[SCSI] ses: add support for enclosure component hot removal")
Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: James Bottomley <[email protected]>
Reported-by: Luo Jiaxing <[email protected]>
Tested-by: John Garry <[email protected]>
Signed-off-by: Martin K. Petersen <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
drivers/misc/enclosure.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
--- a/drivers/misc/enclosure.c
+++ b/drivers/misc/enclosure.c
@@ -364,10 +364,9 @@ int enclosure_remove_device(struct enclo
cdev = &edev->component[i];
if (cdev->dev == dev) {
enclosure_remove_links(cdev);
- device_del(&cdev->cdev);
put_device(dev);
cdev->dev = NULL;
- return device_add(&cdev->cdev);
+ return 0;
}
}
return -ENODEV;
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Kenneth Klette Jonassen <[email protected]>
commit 3725a269815ba6dbb415feddc47da5af7d1fac58 upstream.
Configuring fq with quantum 0 hangs the system, presumably because of a
non-interruptible infinite loop. Either way quantum 0 does not make sense.
Reproduce with:
sudo tc qdisc add dev lo root fq quantum 0 initial_quantum 0
ping 127.0.0.1
Signed-off-by: Kenneth Klette Jonassen <[email protected]>
Acked-by: Eric Dumazet <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
net/sched/sch_fq.c | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
--- a/net/sched/sch_fq.c
+++ b/net/sched/sch_fq.c
@@ -687,8 +687,14 @@ static int fq_change(struct Qdisc *sch,
if (tb[TCA_FQ_FLOW_PLIMIT])
q->flow_plimit = nla_get_u32(tb[TCA_FQ_FLOW_PLIMIT]);
- if (tb[TCA_FQ_QUANTUM])
- q->quantum = nla_get_u32(tb[TCA_FQ_QUANTUM]);
+ if (tb[TCA_FQ_QUANTUM]) {
+ u32 quantum = nla_get_u32(tb[TCA_FQ_QUANTUM]);
+
+ if (quantum > 0)
+ q->quantum = quantum;
+ else
+ err = -EINVAL;
+ }
if (tb[TCA_FQ_INITIAL_QUANTUM])
q->initial_quantum = nla_get_u32(tb[TCA_FQ_INITIAL_QUANTUM]);
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Will Deacon <[email protected]>
commit 68faa679b8be1a74e6663c21c3a9d25d32f1c079 upstream.
'chrdev_open()' calls 'cdev_get()' to obtain a reference to the
'struct cdev *' stashed in the 'i_cdev' field of the target inode
structure. If the pointer is NULL, then it is initialised lazily by
looking up the kobject in the 'cdev_map' and so the whole procedure is
protected by the 'cdev_lock' spinlock to serialise initialisation of
the shared pointer.
Unfortunately, it is possible for the initialising thread to fail *after*
installing the new pointer, for example if the subsequent '->open()' call
on the file fails. In this case, 'cdev_put()' is called, the reference
count on the kobject is dropped and, if nobody else has taken a reference,
the release function is called which finally clears 'inode->i_cdev' from
'cdev_purge()' before potentially freeing the object. The problem here
is that a racing thread can happily take the 'cdev_lock' and see the
non-NULL pointer in the inode, which can result in a refcount increment
from zero and a warning:
| ------------[ cut here ]------------
| refcount_t: addition on 0; use-after-free.
| WARNING: CPU: 2 PID: 6385 at lib/refcount.c:25 refcount_warn_saturate+0x6d/0xf0
| Modules linked in:
| CPU: 2 PID: 6385 Comm: repro Not tainted 5.5.0-rc2+ #22
| Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.12.0-1 04/01/2014
| RIP: 0010:refcount_warn_saturate+0x6d/0xf0
| Code: 05 55 9a 15 01 01 e8 9d aa c8 ff 0f 0b c3 80 3d 45 9a 15 01 00 75 ce 48 c7 c7 00 9c 62 b3 c6 08
| RSP: 0018:ffffb524c1b9bc70 EFLAGS: 00010282
| RAX: 0000000000000000 RBX: ffff9e9da1f71390 RCX: 0000000000000000
| RDX: ffff9e9dbbd27618 RSI: ffff9e9dbbd18798 RDI: ffff9e9dbbd18798
| RBP: 0000000000000000 R08: 000000000000095f R09: 0000000000000039
| R10: 0000000000000000 R11: ffffb524c1b9bb20 R12: ffff9e9da1e8c700
| R13: ffffffffb25ee8b0 R14: 0000000000000000 R15: ffff9e9da1e8c700
| FS: 00007f3b87d26700(0000) GS:ffff9e9dbbd00000(0000) knlGS:0000000000000000
| CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
| CR2: 00007fc16909c000 CR3: 000000012df9c000 CR4: 00000000000006e0
| DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
| DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
| Call Trace:
| kobject_get+0x5c/0x60
| cdev_get+0x2b/0x60
| chrdev_open+0x55/0x220
| ? cdev_put.part.3+0x20/0x20
| do_dentry_open+0x13a/0x390
| path_openat+0x2c8/0x1470
| do_filp_open+0x93/0x100
| ? selinux_file_ioctl+0x17f/0x220
| do_sys_open+0x186/0x220
| do_syscall_64+0x48/0x150
| entry_SYSCALL_64_after_hwframe+0x44/0xa9
| RIP: 0033:0x7f3b87efcd0e
| Code: 89 54 24 08 e8 a3 f4 ff ff 8b 74 24 0c 48 8b 3c 24 41 89 c0 44 8b 54 24 08 b8 01 01 00 00 89 f4
| RSP: 002b:00007f3b87d259f0 EFLAGS: 00000293 ORIG_RAX: 0000000000000101
| RAX: ffffffffffffffda RBX: 0000000000000000 RCX: 00007f3b87efcd0e
| RDX: 0000000000000000 RSI: 00007f3b87d25a80 RDI: 00000000ffffff9c
| RBP: 00007f3b87d25e90 R08: 0000000000000000 R09: 0000000000000000
| R10: 0000000000000000 R11: 0000000000000293 R12: 00007ffe188f504e
| R13: 00007ffe188f504f R14: 00007f3b87d26700 R15: 0000000000000000
| ---[ end trace 24f53ca58db8180a ]---
Since 'cdev_get()' can already fail to obtain a reference, simply move
it over to use 'kobject_get_unless_zero()' instead of 'kobject_get()',
which will cause the racing thread to return -ENXIO if the initialising
thread fails unexpectedly.
Cc: Hillf Danton <[email protected]>
Cc: Andrew Morton <[email protected]>
Cc: Al Viro <[email protected]>
Reported-by: [email protected]
Signed-off-by: Will Deacon <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Greg Kroah-Hartman <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
fs/char_dev.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/fs/char_dev.c
+++ b/fs/char_dev.c
@@ -348,7 +348,7 @@ static struct kobject *cdev_get(struct c
if (owner && !try_module_get(owner))
return NULL;
- kobj = kobject_get(&p->kobj);
+ kobj = kobject_get_unless_zero(&p->kobj);
if (!kobj)
module_put(owner);
return kobj;
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Mikulas Patocka <[email protected]>
commit ad6bf88a6c19a39fb3b0045d78ea880325dfcf15 upstream.
Logical block size has type unsigned short. That means that it can be at
most 32768. However, there are architectures that can run with 64k pages
(for example arm64) and on these architectures, it may be possible to
create block devices with 64k block size.
For exmaple (run this on an architecture with 64k pages):
Mount will fail with this error because it tries to read the superblock using 2-sector
access:
device-mapper: writecache: I/O is not aligned, sector 2, size 1024, block size 65536
EXT4-fs (dm-0): unable to read superblock
This patch changes the logical block size from unsigned short to unsigned
int to avoid the overflow.
Reviewed-by: Martin K. Petersen <[email protected]>
Reviewed-by: Ming Lei <[email protected]>
Signed-off-by: Mikulas Patocka <[email protected]>
Signed-off-by: Jens Axboe <[email protected]>
[bwh: Backported to 3.16: adjust context]
Signed-off-by: Ben Hutchings <[email protected]>
---
block/blk-settings.c | 2 +-
drivers/md/dm-snap-persistent.c | 2 +-
drivers/md/raid0.c | 2 +-
include/linux/blkdev.h | 8 ++++----
4 files changed, 7 insertions(+), 7 deletions(-)
--- a/block/blk-settings.c
+++ b/block/blk-settings.c
@@ -373,7 +373,7 @@ EXPORT_SYMBOL(blk_queue_max_segment_size
* storage device can address. The default of 512 covers most
* hardware.
**/
-void blk_queue_logical_block_size(struct request_queue *q, unsigned short size)
+void blk_queue_logical_block_size(struct request_queue *q, unsigned int size)
{
q->limits.logical_block_size = size;
--- a/drivers/md/dm-snap-persistent.c
+++ b/drivers/md/dm-snap-persistent.c
@@ -16,7 +16,7 @@
#include "dm-bufio.h"
#define DM_MSG_PREFIX "persistent snapshot"
-#define DM_CHUNK_SIZE_DEFAULT_SECTORS 32 /* 16KB */
+#define DM_CHUNK_SIZE_DEFAULT_SECTORS 32U /* 16KB */
#define DM_PREFETCH_CHUNKS 12
--- a/drivers/md/raid0.c
+++ b/drivers/md/raid0.c
@@ -88,7 +88,7 @@ static int create_strip_zones(struct mdd
char b[BDEVNAME_SIZE];
char b2[BDEVNAME_SIZE];
struct r0conf *conf = kzalloc(sizeof(*conf), GFP_KERNEL);
- unsigned short blksize = 512;
+ unsigned blksize = 512;
if (!conf)
return -ENOMEM;
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -284,6 +284,7 @@ struct queue_limits {
unsigned int max_sectors;
unsigned int max_segment_size;
unsigned int physical_block_size;
+ unsigned int logical_block_size;
unsigned int alignment_offset;
unsigned int io_min;
unsigned int io_opt;
@@ -292,7 +293,6 @@ struct queue_limits {
unsigned int discard_granularity;
unsigned int discard_alignment;
- unsigned short logical_block_size;
unsigned short max_segments;
unsigned short max_integrity_segments;
@@ -1017,7 +1017,7 @@ extern void blk_queue_max_discard_sector
unsigned int max_discard_sectors);
extern void blk_queue_max_write_same_sectors(struct request_queue *q,
unsigned int max_write_same_sectors);
-extern void blk_queue_logical_block_size(struct request_queue *, unsigned short);
+extern void blk_queue_logical_block_size(struct request_queue *, unsigned int);
extern void blk_queue_physical_block_size(struct request_queue *, unsigned int);
extern void blk_queue_alignment_offset(struct request_queue *q,
unsigned int alignment);
@@ -1232,7 +1232,7 @@ static inline unsigned int queue_max_seg
return q->limits.max_segment_size;
}
-static inline unsigned short queue_logical_block_size(struct request_queue *q)
+static inline unsigned queue_logical_block_size(struct request_queue *q)
{
int retval = 512;
@@ -1242,7 +1242,7 @@ static inline unsigned short queue_logic
return retval;
}
-static inline unsigned short bdev_logical_block_size(struct block_device *bdev)
+static inline unsigned int bdev_logical_block_size(struct block_device *bdev)
{
return queue_logical_block_size(bdev_get_queue(bdev));
}
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Johan Hovold <[email protected]>
commit 3018dd3fa114b13261e9599ddb5656ef97a1fa17 upstream.
Check for NULL port data in the control URB completion handlers to avoid
dereferencing a NULL pointer in the unlikely case where a port device
isn't bound to a driver (e.g. after an allocation failure on port
probe()).
Fixes: 0ca1268e109a ("USB Serial Keyspan: add support for USA-49WG & USA-28XG")
Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Reviewed-by: Greg Kroah-Hartman <[email protected]>
Signed-off-by: Johan Hovold <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
drivers/usb/serial/keyspan.c | 4 ++++
1 file changed, 4 insertions(+)
--- a/drivers/usb/serial/keyspan.c
+++ b/drivers/usb/serial/keyspan.c
@@ -962,6 +962,10 @@ static void usa67_glocont_callback(struc
for (i = 0; i < serial->num_ports; ++i) {
port = serial->port[i];
p_priv = usb_get_serial_port_data(port);
+ if (!p_priv)
+ continue;
+ if (!p_priv)
+ continue;
if (p_priv->resend_cont) {
dev_dbg(&port->dev, "%s - sending setup\n", __func__);
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Johan Hovold <[email protected]>
commit 6b32391ed675827f8425a414abbc6fbd54ea54fe upstream.
Make sure to use the current alternate setting when verifying the
interface descriptors to avoid binding to an invalid interface.
This in turn could cause the driver to misbehave or trigger a WARN() in
usb_submit_urb() that kernels with panic_on_warn set would choke on.
Fixes: bdb5c57f209c ("Input: add sur40 driver for Samsung SUR40 (aka MS Surface 2.0/Pixelsense)")
Signed-off-by: Johan Hovold <[email protected]>
Acked-by: Vladis Dronov <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Dmitry Torokhov <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
drivers/input/touchscreen/sur40.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/input/touchscreen/sur40.c
+++ b/drivers/input/touchscreen/sur40.c
@@ -357,7 +357,7 @@ static int sur40_probe(struct usb_interf
int error;
/* Check if we really have the right interface. */
- iface_desc = &interface->altsetting[0];
+ iface_desc = interface->cur_altsetting;
if (iface_desc->desc.bInterfaceClass != 0xFF)
return -ENODEV;
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Chen-Yu Tsai <[email protected]>
commit 52cc73e5404c7ba0cbfc50cb4c265108c84b3d5a upstream.
Allow all the RGMII modes to be used. This would allow us to represent
the hardware better in the device tree with RGMII_ID where in most
cases the PHY's internal delay for both RX and TX are used.
Fixes: af0bd4e9ba80 ("net: stmmac: sunxi platform extensions for GMAC in Allwinner A20 SoC's")
Signed-off-by: Chen-Yu Tsai <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
drivers/net/ethernet/stmicro/stmmac/dwmac-sunxi.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sunxi.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sunxi.c
@@ -78,7 +78,7 @@ static int sun7i_gmac_init(struct platfo
* rate, which then uses the auto-reparenting feature of the
* clock driver, and enabling/disabling the clock.
*/
- if (gmac->interface == PHY_INTERFACE_MODE_RGMII) {
+ if (phy_interface_mode_is_rgmii(gmac->interface)) {
clk_set_rate(gmac->tx_clk, SUN7I_GMAC_GMII_RGMII_RATE);
clk_prepare_enable(gmac->tx_clk);
gmac->clk_enabled = 1;
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Johan Hovold <[email protected]>
commit a8eeb74df5a6bdb214b2b581b14782c5f5a0cf83 upstream.
The driver was checking the number of endpoints of the first alternate
setting instead of the current one, something which could lead to the
driver binding to an invalid interface.
This in turn could cause the driver to misbehave or trigger a WARN() in
usb_submit_urb() that kernels with panic_on_warn set would choke on.
Fixes: 162f98dea487 ("Input: gtco - fix crash on detecting device without endpoints")
Signed-off-by: Johan Hovold <[email protected]>
Acked-by: Vladis Dronov <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Dmitry Torokhov <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
drivers/input/tablet/gtco.c | 10 +++-------
1 file changed, 3 insertions(+), 7 deletions(-)
--- a/drivers/input/tablet/gtco.c
+++ b/drivers/input/tablet/gtco.c
@@ -886,18 +886,14 @@ static int gtco_probe(struct usb_interfa
}
/* Sanity check that a device has an endpoint */
- if (usbinterface->altsetting[0].desc.bNumEndpoints < 1) {
+ if (usbinterface->cur_altsetting->desc.bNumEndpoints < 1) {
dev_err(&usbinterface->dev,
"Invalid number of endpoints\n");
error = -EINVAL;
goto err_free_urb;
}
- /*
- * The endpoint is always altsetting 0, we know this since we know
- * this device only has one interrupt endpoint
- */
- endpoint = &usbinterface->altsetting[0].endpoint[0].desc;
+ endpoint = &usbinterface->cur_altsetting->endpoint[0].desc;
/* Some debug */
dev_dbg(&usbinterface->dev, "gtco # interfaces: %d\n", usbinterface->num_altsetting);
@@ -984,7 +980,7 @@ static int gtco_probe(struct usb_interfa
input_dev->dev.parent = &usbinterface->dev;
/* Setup the URB, it will be posted later on open of input device */
- endpoint = &usbinterface->altsetting[0].endpoint[0].desc;
+ endpoint = &usbinterface->cur_altsetting->endpoint[0].desc;
usb_fill_int_urb(gtco->urbinfo,
gtco->usbdev,
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Al Viro <[email protected]>
commit 6404674acd596de41fd3ad5f267b4525494a891a upstream.
Brown paperbag time: fetching ->i_uid/->i_mode really should've been
done from nd->inode. I even suggested that, but the reason for that has
slipped through the cracks and I went for dir->d_inode instead - made
for more "obvious" patch.
Analysis:
- at the entry into do_last() and all the way to step_into(): dir (aka
nd->path.dentry) is known not to have been freed; so's nd->inode and
it's equal to dir->d_inode unless we are already doomed to -ECHILD.
inode of the file to get opened is not known.
- after step_into(): inode of the file to get opened is known; dir
might be pointing to freed memory/be negative/etc.
- at the call of may_create_in_sticky(): guaranteed to be out of RCU
mode; inode of the file to get opened is known and pinned; dir might
be garbage.
The last was the reason for the original patch. Except that at the
do_last() entry we can be in RCU mode and it is possible that
nd->path.dentry->d_inode has already changed under us.
In that case we are going to fail with -ECHILD, but we need to be
careful; nd->inode is pointing to valid struct inode and it's the same
as nd->path.dentry->d_inode in "won't fail with -ECHILD" case, so we
should use that.
Reported-by: "Rantala, Tommi T. (Nokia - FI/Espoo)" <[email protected]>
Reported-by: [email protected]
Wearing-brown-paperbag: Al Viro <[email protected]>
Fixes: d0cb50185ae9 ("do_last(): fetch directory ->i_mode and ->i_uid before it's too late")
Signed-off-by: Al Viro <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
fs/namei.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -2945,8 +2945,8 @@ static int do_last(struct nameidata *nd,
int *opened, struct filename *name)
{
struct dentry *dir = nd->path.dentry;
- kuid_t dir_uid = dir->d_inode->i_uid;
- umode_t dir_mode = dir->d_inode->i_mode;
+ kuid_t dir_uid = nd->inode->i_uid;
+ umode_t dir_mode = nd->inode->i_mode;
int open_flag = op->open_flag;
bool will_truncate = (open_flag & O_TRUNC) != 0;
bool got_write = false;
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Jiri Kosina <[email protected]>
commit 9e635c2851df6caee651e589fbf937b637973c91 upstream.
hidraw and uhid device nodes are always available for writing so we should
always report EPOLLOUT and EPOLLWRNORM bits, not only in the cases when
there is nothing to read.
Reported-by: Linus Torvalds <[email protected]>
Fixes: be54e7461ffdc ("HID: uhid: Fix returning EPOLLOUT from uhid_char_poll")
Fixes: 9f3b61dc1dd7b ("HID: hidraw: Fix returning EPOLLOUT from hidraw_poll")
Signed-off-by: Jiri Kosina <[email protected]>
[bwh: Backported to 3.16:
- Use unsigned int type instead of __poll_t
- s/EPOLL/POLL/g]
Signed-off-by: Ben Hutchings <[email protected]>
---
drivers/hid/hidraw.c | 7 ++++---
drivers/hid/uhid.c | 5 +++--
2 files changed, 7 insertions(+), 5 deletions(-)
--- a/drivers/hid/hidraw.c
+++ b/drivers/hid/hidraw.c
@@ -262,13 +262,14 @@ out:
static unsigned int hidraw_poll(struct file *file, poll_table *wait)
{
struct hidraw_list *list = file->private_data;
+ unsigned int mask = POLLOUT | POLLWRNORM; /* hidraw is always writable */
poll_wait(file, &list->hidraw->wait, wait);
if (list->head != list->tail)
- return POLLIN | POLLRDNORM;
+ mask |= POLLIN | POLLRDNORM;
if (!list->hidraw->exist)
- return POLLERR | POLLHUP;
- return POLLOUT | POLLWRNORM;
+ mask |= POLLERR | POLLHUP;
+ return mask;
}
static int hidraw_open(struct inode *inode, struct file *file)
--- a/drivers/hid/uhid.c
+++ b/drivers/hid/uhid.c
@@ -720,13 +720,14 @@ unlock:
static unsigned int uhid_char_poll(struct file *file, poll_table *wait)
{
struct uhid_device *uhid = file->private_data;
+ unsigned int mask = POLLOUT | POLLWRNORM; /* uhid is always writable */
poll_wait(file, &uhid->waitq, wait);
if (uhid->head != uhid->tail)
- return POLLIN | POLLRDNORM;
+ mask |= POLLIN | POLLRDNORM;
- return POLLOUT | POLLWRNORM;
+ return mask;
}
static const struct file_operations uhid_fops = {
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Johan Hovold <[email protected]>
commit 3111491fca4f01764e0c158c5e0f7ced808eef51 upstream.
The driver was checking the number of endpoints of the first alternate
setting instead of the current one, something which could lead to the
driver binding to an invalid interface.
This in turn could cause the driver to misbehave or trigger a WARN() in
usb_submit_urb() that kernels with panic_on_warn set would choke on.
Fixes: 8e20cf2bce12 ("Input: aiptek - fix crash on detecting device without endpoints")
Signed-off-by: Johan Hovold <[email protected]>
Acked-by: Vladis Dronov <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Dmitry Torokhov <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
drivers/input/tablet/aiptek.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
--- a/drivers/input/tablet/aiptek.c
+++ b/drivers/input/tablet/aiptek.c
@@ -1820,14 +1820,14 @@ aiptek_probe(struct usb_interface *intf,
input_set_abs_params(inputdev, ABS_WHEEL, AIPTEK_WHEEL_MIN, AIPTEK_WHEEL_MAX - 1, 0, 0);
/* Verify that a device really has an endpoint */
- if (intf->altsetting[0].desc.bNumEndpoints < 1) {
+ if (intf->cur_altsetting->desc.bNumEndpoints < 1) {
dev_err(&intf->dev,
"interface has %d endpoints, but must have minimum 1\n",
- intf->altsetting[0].desc.bNumEndpoints);
+ intf->cur_altsetting->desc.bNumEndpoints);
err = -EINVAL;
goto fail3;
}
- endpoint = &intf->altsetting[0].endpoint[0].desc;
+ endpoint = &intf->cur_altsetting->endpoint[0].desc;
/* Go set up our URB, which is called when the tablet receives
* input.
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Arnd Bergmann <[email protected]>
commit 42ec15ceaea74b5f7a621fc6686cbf69ca66c4cf upstream.
gcc -O3 warns that some local variables are not properly initialized:
drivers/scsi/fnic/vnic_dev.c: In function 'fnic_dev_hang_notify':
drivers/scsi/fnic/vnic_dev.c:511:16: error: 'a0' is used uninitialized in this function [-Werror=uninitialized]
vdev->args[0] = *a0;
~~~~~~~~~~~~~~^~~~~
drivers/scsi/fnic/vnic_dev.c:691:6: note: 'a0' was declared here
u64 a0, a1;
^~
drivers/scsi/fnic/vnic_dev.c:512:16: error: 'a1' is used uninitialized in this function [-Werror=uninitialized]
vdev->args[1] = *a1;
~~~~~~~~~~~~~~^~~~~
drivers/scsi/fnic/vnic_dev.c:691:10: note: 'a1' was declared here
u64 a0, a1;
^~
drivers/scsi/fnic/vnic_dev.c: In function 'fnic_dev_mac_addr':
drivers/scsi/fnic/vnic_dev.c:512:16: error: 'a1' is used uninitialized in this function [-Werror=uninitialized]
vdev->args[1] = *a1;
~~~~~~~~~~~~~~^~~~~
drivers/scsi/fnic/vnic_dev.c:698:10: note: 'a1' was declared here
u64 a0, a1;
^~
Apparently the code relies on the local variables occupying adjacent memory
locations in the same order, but this is of course not guaranteed.
Use an array of two u64 variables where needed to make it work correctly.
I suspect there is also an endianness bug here, but have not digged in deep
enough to be sure.
Fixes: 5df6d737dd4b ("[SCSI] fnic: Add new Cisco PCI-Express FCoE HBA")
Fixes: mmtom ("init/Kconfig: enable -O3 for all arches")
Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Arnd Bergmann <[email protected]>
Signed-off-by: Martin K. Petersen <[email protected]>
[bwh: Backported to 3.16: adjust context]
Signed-off-by: Ben Hutchings <[email protected]>
---
drivers/scsi/fnic/vnic_dev.c | 20 ++++++++++----------
1 file changed, 10 insertions(+), 10 deletions(-)
--- a/drivers/scsi/fnic/vnic_dev.c
+++ b/drivers/scsi/fnic/vnic_dev.c
@@ -445,26 +445,26 @@ int vnic_dev_soft_reset_done(struct vnic
int vnic_dev_hang_notify(struct vnic_dev *vdev)
{
- u64 a0, a1;
+ u64 a0 = 0, a1 = 0;
int wait = 1000;
return vnic_dev_cmd(vdev, CMD_HANG_NOTIFY, &a0, &a1, wait);
}
int vnic_dev_mac_addr(struct vnic_dev *vdev, u8 *mac_addr)
{
- u64 a0, a1;
+ u64 a[2] = {};
int wait = 1000;
int err, i;
for (i = 0; i < ETH_ALEN; i++)
mac_addr[i] = 0;
- err = vnic_dev_cmd(vdev, CMD_MAC_ADDR, &a0, &a1, wait);
+ err = vnic_dev_cmd(vdev, CMD_MAC_ADDR, &a[0], &a[1], wait);
if (err)
return err;
for (i = 0; i < ETH_ALEN; i++)
- mac_addr[i] = ((u8 *)&a0)[i];
+ mac_addr[i] = ((u8 *)&a)[i];
return 0;
}
@@ -489,15 +489,15 @@ void vnic_dev_packet_filter(struct vnic_
void vnic_dev_add_addr(struct vnic_dev *vdev, u8 *addr)
{
- u64 a0 = 0, a1 = 0;
+ u64 a[2] = {};
int wait = 1000;
int err;
int i;
for (i = 0; i < ETH_ALEN; i++)
- ((u8 *)&a0)[i] = addr[i];
+ ((u8 *)&a)[i] = addr[i];
- err = vnic_dev_cmd(vdev, CMD_ADDR_ADD, &a0, &a1, wait);
+ err = vnic_dev_cmd(vdev, CMD_ADDR_ADD, &a[0], &a[1], wait);
if (err)
printk(KERN_ERR
"Can't add addr [%02x:%02x:%02x:%02x:%02x:%02x], %d\n",
@@ -507,15 +507,15 @@ void vnic_dev_add_addr(struct vnic_dev *
void vnic_dev_del_addr(struct vnic_dev *vdev, u8 *addr)
{
- u64 a0 = 0, a1 = 0;
+ u64 a[2] = {};
int wait = 1000;
int err;
int i;
for (i = 0; i < ETH_ALEN; i++)
- ((u8 *)&a0)[i] = addr[i];
+ ((u8 *)&a)[i] = addr[i];
- err = vnic_dev_cmd(vdev, CMD_ADDR_DEL, &a0, &a1, wait);
+ err = vnic_dev_cmd(vdev, CMD_ADDR_DEL, &a[0], &a[1], wait);
if (err)
printk(KERN_ERR
"Can't del addr [%02x:%02x:%02x:%02x:%02x:%02x], %d\n",
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Finn Thain <[email protected]>
commit 9e311820f67e740f4fb8dcb82b4c4b5b05bdd1a5 upstream.
The SONIC can sometimes advance its rx buffer pointer (RRP register)
without advancing its rx descriptor pointer (CRDA register). As a result
the index of the current rx descriptor may not equal that of the current
rx buffer. The driver mistakenly assumes that they are always equal.
This assumption leads to incorrect packet lengths and possible packet
duplication. Avoid this by calling a new function to locate the buffer
corresponding to a given descriptor.
Fixes: efcce839360f ("[PATCH] macsonic/jazzsonic network drivers update")
Tested-by: Stan Johnson <[email protected]>
Signed-off-by: Finn Thain <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
drivers/net/ethernet/natsemi/sonic.c | 35 ++++++++++++++++++++++++----
drivers/net/ethernet/natsemi/sonic.h | 5 ++--
2 files changed, 33 insertions(+), 7 deletions(-)
--- a/drivers/net/ethernet/natsemi/sonic.c
+++ b/drivers/net/ethernet/natsemi/sonic.c
@@ -423,6 +423,21 @@ static irqreturn_t sonic_interrupt(int i
return IRQ_HANDLED;
}
+/* Return the array index corresponding to a given Receive Buffer pointer. */
+static int index_from_addr(struct sonic_local *lp, dma_addr_t addr,
+ unsigned int last)
+{
+ unsigned int i = last;
+
+ do {
+ i = (i + 1) & SONIC_RRS_MASK;
+ if (addr == lp->rx_laddr[i])
+ return i;
+ } while (i != last);
+
+ return -ENOENT;
+}
+
/*
* We have a good packet(s), pass it/them up the network stack.
*/
@@ -442,6 +457,16 @@ static void sonic_rx(struct net_device *
status = sonic_rda_get(dev, entry, SONIC_RD_STATUS);
if (status & SONIC_RCR_PRX) {
+ u32 addr = (sonic_rda_get(dev, entry,
+ SONIC_RD_PKTPTR_H) << 16) |
+ sonic_rda_get(dev, entry, SONIC_RD_PKTPTR_L);
+ int i = index_from_addr(lp, addr, entry);
+
+ if (i < 0) {
+ WARN_ONCE(1, "failed to find buffer!\n");
+ break;
+ }
+
/* Malloc up new buffer. */
new_skb = netdev_alloc_skb(dev, SONIC_RBSIZE + 2);
if (new_skb == NULL) {
@@ -463,7 +488,7 @@ static void sonic_rx(struct net_device *
/* now we have a new skb to replace it, pass the used one up the stack */
dma_unmap_single(lp->device, lp->rx_laddr[entry], SONIC_RBSIZE, DMA_FROM_DEVICE);
- used_skb = lp->rx_skb[entry];
+ used_skb = lp->rx_skb[i];
pkt_len = sonic_rda_get(dev, entry, SONIC_RD_PKTLEN);
skb_trim(used_skb, pkt_len);
used_skb->protocol = eth_type_trans(used_skb, dev);
@@ -472,13 +497,13 @@ static void sonic_rx(struct net_device *
lp->stats.rx_bytes += pkt_len;
/* and insert the new skb */
- lp->rx_laddr[entry] = new_laddr;
- lp->rx_skb[entry] = new_skb;
+ lp->rx_laddr[i] = new_laddr;
+ lp->rx_skb[i] = new_skb;
bufadr_l = (unsigned long)new_laddr & 0xffff;
bufadr_h = (unsigned long)new_laddr >> 16;
- sonic_rra_put(dev, entry, SONIC_RR_BUFADR_L, bufadr_l);
- sonic_rra_put(dev, entry, SONIC_RR_BUFADR_H, bufadr_h);
+ sonic_rra_put(dev, i, SONIC_RR_BUFADR_L, bufadr_l);
+ sonic_rra_put(dev, i, SONIC_RR_BUFADR_H, bufadr_h);
} else {
/* This should only happen, if we enable accepting broken packets. */
lp->stats.rx_errors++;
--- a/drivers/net/ethernet/natsemi/sonic.h
+++ b/drivers/net/ethernet/natsemi/sonic.h
@@ -273,8 +273,9 @@
#define SONIC_NUM_RDS SONIC_NUM_RRS /* number of receive descriptors */
#define SONIC_NUM_TDS 16 /* number of transmit descriptors */
-#define SONIC_RDS_MASK (SONIC_NUM_RDS-1)
-#define SONIC_TDS_MASK (SONIC_NUM_TDS-1)
+#define SONIC_RRS_MASK (SONIC_NUM_RRS - 1)
+#define SONIC_RDS_MASK (SONIC_NUM_RDS - 1)
+#define SONIC_TDS_MASK (SONIC_NUM_TDS - 1)
#define SONIC_RBSIZE 1520 /* size of one resource buffer */
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Johan Hovold <[email protected]>
commit 4d5ef53f75c22d28f490bcc5c771fcc610a9afa4 upstream.
Check for NULL port data in reset_resume() to avoid dereferencing a NULL
pointer in case the port device isn't bound to a driver (e.g. after a
failed control request at port probe).
Fixes: 1ded7ea47b88 ("USB: ch341 serial: fix port number changed after resume")
Reviewed-by: Greg Kroah-Hartman <[email protected]>
Signed-off-by: Johan Hovold <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
drivers/usb/serial/ch341.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
--- a/drivers/usb/serial/ch341.c
+++ b/drivers/usb/serial/ch341.c
@@ -571,9 +571,13 @@ static int ch341_tiocmget(struct tty_str
static int ch341_reset_resume(struct usb_serial *serial)
{
struct usb_serial_port *port = serial->port[0];
- struct ch341_private *priv = usb_get_serial_port_data(port);
+ struct ch341_private *priv;
int ret;
+ priv = usb_get_serial_port_data(port);
+ if (!priv)
+ return 0;
+
/* reconfigure ch341 serial port after bus-reset */
ch341_configure(serial->dev, priv);
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Finn Thain <[email protected]>
commit 865ad2f2201dc18685ba2686f13217f8b3a9c52c upstream.
The netif_stop_queue() call in sonic_send_packet() races with the
netif_wake_queue() call in sonic_interrupt(). This causes issues
like "NETDEV WATCHDOG: eth0 (macsonic): transmit queue 0 timed out".
Fix this by disabling interrupts when accessing tx_skb[] and next_tx.
Update a comment to clarify the synchronization properties.
Fixes: efcce839360f ("[PATCH] macsonic/jazzsonic network drivers update")
Tested-by: Stan Johnson <[email protected]>
Signed-off-by: Finn Thain <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
drivers/net/ethernet/natsemi/sonic.c | 49 ++++++++++++++++++++--------
drivers/net/ethernet/natsemi/sonic.h | 1 +
2 files changed, 36 insertions(+), 14 deletions(-)
--- a/drivers/net/ethernet/natsemi/sonic.c
+++ b/drivers/net/ethernet/natsemi/sonic.c
@@ -50,6 +50,8 @@ static int sonic_open(struct net_device
if (sonic_debug > 2)
printk("sonic_open: initializing sonic driver.\n");
+ spin_lock_init(&lp->lock);
+
for (i = 0; i < SONIC_NUM_RRS; i++) {
struct sk_buff *skb = netdev_alloc_skb(dev, SONIC_RBSIZE + 2);
if (skb == NULL) {
@@ -194,8 +196,6 @@ static void sonic_tx_timeout(struct net_
* wake the tx queue
* Concurrently with all of this, the SONIC is potentially writing to
* the status flags of the TDs.
- * Until some mutual exclusion is added, this code will not work with SMP. However,
- * MIPS Jazz machines and m68k Macs were all uni-processor machines.
*/
static int sonic_send_packet(struct sk_buff *skb, struct net_device *dev)
@@ -203,7 +203,8 @@ static int sonic_send_packet(struct sk_b
struct sonic_local *lp = netdev_priv(dev);
dma_addr_t laddr;
int length;
- int entry = lp->next_tx;
+ int entry;
+ unsigned long flags;
if (sonic_debug > 2)
printk("sonic_send_packet: skb=%p, dev=%p\n", skb, dev);
@@ -226,6 +227,10 @@ static int sonic_send_packet(struct sk_b
return NETDEV_TX_OK;
}
+ spin_lock_irqsave(&lp->lock, flags);
+
+ entry = lp->next_tx;
+
sonic_tda_put(dev, entry, SONIC_TD_STATUS, 0); /* clear status */
sonic_tda_put(dev, entry, SONIC_TD_FRAG_COUNT, 1); /* single fragment */
sonic_tda_put(dev, entry, SONIC_TD_PKTSIZE, length); /* length of packet */
@@ -235,10 +240,6 @@ static int sonic_send_packet(struct sk_b
sonic_tda_put(dev, entry, SONIC_TD_LINK,
sonic_tda_get(dev, entry, SONIC_TD_LINK) | SONIC_EOL);
- /*
- * Must set tx_skb[entry] only after clearing status, and
- * before clearing EOL and before stopping queue
- */
wmb();
lp->tx_len[entry] = length;
lp->tx_laddr[entry] = laddr;
@@ -263,6 +264,8 @@ static int sonic_send_packet(struct sk_b
SONIC_WRITE(SONIC_CMD, SONIC_CR_TXP);
+ spin_unlock_irqrestore(&lp->lock, flags);
+
return NETDEV_TX_OK;
}
@@ -275,9 +278,21 @@ static irqreturn_t sonic_interrupt(int i
struct net_device *dev = dev_id;
struct sonic_local *lp = netdev_priv(dev);
int status;
+ unsigned long flags;
+
+ /* The lock has two purposes. Firstly, it synchronizes sonic_interrupt()
+ * with sonic_send_packet() so that the two functions can share state.
+ * Secondly, it makes sonic_interrupt() re-entrant, as that is required
+ * by macsonic which must use two IRQs with different priority levels.
+ */
+ spin_lock_irqsave(&lp->lock, flags);
+
+ status = SONIC_READ(SONIC_ISR) & SONIC_IMR_DEFAULT;
+ if (!status) {
+ spin_unlock_irqrestore(&lp->lock, flags);
- if (!(status = SONIC_READ(SONIC_ISR) & SONIC_IMR_DEFAULT))
return IRQ_NONE;
+ }
do {
if (status & SONIC_INT_PKTRX) {
@@ -292,11 +307,12 @@ static irqreturn_t sonic_interrupt(int i
int td_status;
int freed_some = 0;
- /* At this point, cur_tx is the index of a TD that is one of:
- * unallocated/freed (status set & tx_skb[entry] clear)
- * allocated and sent (status set & tx_skb[entry] set )
- * allocated and not yet sent (status clear & tx_skb[entry] set )
- * still being allocated by sonic_send_packet (status clear & tx_skb[entry] clear)
+ /* The state of a Transmit Descriptor may be inferred
+ * from { tx_skb[entry], td_status } as follows.
+ * { clear, clear } => the TD has never been used
+ * { set, clear } => the TD was handed to SONIC
+ * { set, set } => the TD was handed back
+ * { clear, set } => the TD is available for re-use
*/
if (sonic_debug > 2)
@@ -398,7 +414,12 @@ static irqreturn_t sonic_interrupt(int i
/* load CAM done */
if (status & SONIC_INT_LCD)
SONIC_WRITE(SONIC_ISR, SONIC_INT_LCD); /* clear the interrupt */
- } while((status = SONIC_READ(SONIC_ISR) & SONIC_IMR_DEFAULT));
+
+ status = SONIC_READ(SONIC_ISR) & SONIC_IMR_DEFAULT;
+ } while (status);
+
+ spin_unlock_irqrestore(&lp->lock, flags);
+
return IRQ_HANDLED;
}
--- a/drivers/net/ethernet/natsemi/sonic.h
+++ b/drivers/net/ethernet/natsemi/sonic.h
@@ -320,6 +320,7 @@ struct sonic_local {
unsigned int next_tx; /* next free TD */
struct device *device; /* generic device */
struct net_device_stats stats;
+ spinlock_t lock;
};
#define TX_TIMEOUT (3 * HZ)
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: "Steven Rostedt (VMware)" <[email protected]>
commit b8299d362d0837ae39e87e9019ebe6b736e0f035 upstream.
On some archs with some configurations, MCOUNT_INSN_SIZE is not defined, and
this makes the stack tracer fail to compile. Just define it to zero in this
case.
Link: https://lore.kernel.org/r/202001020219.zvE3vsty%[email protected]
Fixes: 4df297129f622 ("tracing: Remove most or all of stack tracer stack size from stack_max_size")
Reported-by: kbuild test robot <[email protected]>
Signed-off-by: Steven Rostedt (VMware) <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
kernel/trace/trace_stack.c | 5 +++++
1 file changed, 5 insertions(+)
--- a/kernel/trace/trace_stack.c
+++ b/kernel/trace/trace_stack.c
@@ -182,6 +182,11 @@ check_stack(unsigned long ip, unsigned l
local_irq_restore(flags);
}
+/* Some archs may not define MCOUNT_INSN_SIZE */
+#ifndef MCOUNT_INSN_SIZE
+# define MCOUNT_INSN_SIZE 0
+#endif
+
static void
stack_trace_call(unsigned long ip, unsigned long parent_ip,
struct ftrace_ops *op, struct pt_regs *pt_regs)
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Luuk Paulussen <[email protected]>
commit cf3ca1877574a306c0207cbf7fdf25419d9229df upstream.
reg2volt returns the voltage that matches a given register value.
Converting this back the other way with volt2reg didn't return the same
register value because it used truncation instead of rounding.
This meant that values read from sysfs could not be written back to sysfs
to set back the same register value.
With this change, volt2reg will return the same value for every voltage
previously returned by reg2volt (for the set of possible input values)
Signed-off-by: Luuk Paulussen <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Guenter Roeck <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
drivers/hwmon/adt7475.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
--- a/drivers/hwmon/adt7475.c
+++ b/drivers/hwmon/adt7475.c
@@ -268,9 +268,10 @@ static inline u16 volt2reg(int channel,
long reg;
if (bypass_attn & (1 << channel))
- reg = (volt * 1024) / 2250;
+ reg = DIV_ROUND_CLOSEST(volt * 1024, 2250);
else
- reg = (volt * r[1] * 1024) / ((r[0] + r[1]) * 2250);
+ reg = DIV_ROUND_CLOSEST(volt * r[1] * 1024,
+ (r[0] + r[1]) * 2250);
return clamp_val(reg, 0, 1023) & (0xff << 2);
}
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Cong Wang <[email protected]>
commit c120959387efa51479056fd01dc90adfba7a590c upstream.
map->members is freed by ip_set_free() right before using it in
mtype_ext_cleanup() again. So we just have to move it down.
Reported-by: [email protected]
Fixes: 40cd63bf33b2 ("netfilter: ipset: Support extensions which need a per data destroy function")
Acked-by: Jozsef Kadlecsik <[email protected]>
Signed-off-by: Cong Wang <[email protected]>
Signed-off-by: Pablo Neira Ayuso <[email protected]>
[bwh: Backported to 3.16: adjust context]
Signed-off-by: Ben Hutchings <[email protected]>
---
net/netfilter/ipset/ip_set_bitmap_gen.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/net/netfilter/ipset/ip_set_bitmap_gen.h
+++ b/net/netfilter/ipset/ip_set_bitmap_gen.h
@@ -66,12 +66,12 @@ mtype_destroy(struct ip_set *set)
if (SET_WITH_TIMEOUT(set))
del_timer_sync(&map->gc);
- ip_set_free(map->members);
if (set->dsize) {
if (set->extensions & IPSET_EXT_DESTROY)
mtype_ext_cleanup(set);
ip_set_free(map->extensions);
}
+ ip_set_free(map->members);
kfree(map);
set->data = NULL;
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Johan Hovold <[email protected]>
commit 9715a43eea77e42678a1002623f2d9a78f5b81a1 upstream.
Check for NULL port data in the modem- and line-status handlers to avoid
dereferencing a NULL pointer in the unlikely case where a port device
isn't bound to a driver (e.g. after an allocation failure on port
probe).
Note that the other (stubbed) event handlers qt2_process_xmit_empty()
and qt2_process_flush() would need similar sanity checks in case they
are ever implemented.
Fixes: f7a33e608d9a ("USB: serial: add quatech2 usb to serial driver")
Reviewed-by: Greg Kroah-Hartman <[email protected]>
Signed-off-by: Johan Hovold <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
drivers/usb/serial/quatech2.c | 6 ++++++
1 file changed, 6 insertions(+)
--- a/drivers/usb/serial/quatech2.c
+++ b/drivers/usb/serial/quatech2.c
@@ -872,7 +872,10 @@ static void qt2_update_msr(struct usb_se
u8 newMSR = (u8) *ch;
unsigned long flags;
+ /* May be called from qt2_process_read_urb() for an unbound port. */
port_priv = usb_get_serial_port_data(port);
+ if (!port_priv)
+ return;
spin_lock_irqsave(&port_priv->lock, flags);
port_priv->shadowMSR = newMSR;
@@ -900,7 +903,10 @@ static void qt2_update_lsr(struct usb_se
unsigned long flags;
u8 newLSR = (u8) *ch;
+ /* May be called from qt2_process_read_urb() for an unbound port. */
port_priv = usb_get_serial_port_data(port);
+ if (!port_priv)
+ return;
if (newLSR & UART_LSR_BI)
newLSR &= (u8) (UART_LSR_OE | UART_LSR_BI);
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Johan Hovold <[email protected]>
commit 5e28055f340275a8616eee88ef19186631b4d136 upstream.
The driver was issuing synchronous uninterruptible control requests
without using a timeout. This could lead to the driver hanging
on open() or tiocmset() due to a malfunctioning (or malicious) device
until the device is physically disconnected.
The USB upper limit of five seconds per request should be more than
enough.
Fixes: 309a057932ab ("USB: opticon: add rts and cts support")
Cc: Martin Jansen <[email protected]>
Reviewed-by: Greg Kroah-Hartman <[email protected]>
Signed-off-by: Johan Hovold <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
drivers/usb/serial/opticon.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/usb/serial/opticon.c
+++ b/drivers/usb/serial/opticon.c
@@ -116,7 +116,7 @@ static int send_control_msg(struct usb_s
retval = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
requesttype,
USB_DIR_OUT|USB_TYPE_VENDOR|USB_RECIP_INTERFACE,
- 0, 0, buffer, 1, 0);
+ 0, 0, buffer, 1, USB_CTRL_SET_TIMEOUT);
kfree(buffer);
if (retval < 0)
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Al Viro <[email protected]>
commit d0cb50185ae942b03c4327be322055d622dc79f6 upstream.
may_create_in_sticky() call is done when we already have dropped the
reference to dir.
Fixes: 30aba6656f61e (namei: allow restricted O_CREAT of FIFOs and regular files)
Signed-off-by: Al Viro <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
fs/namei.c | 17 ++++++++++-------
1 file changed, 10 insertions(+), 7 deletions(-)
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -843,7 +843,8 @@ static int may_linkat(struct path *link)
* may_create_in_sticky - Check whether an O_CREAT open in a sticky directory
* should be allowed, or not, on files that already
* exist.
- * @dir: the sticky parent directory
+ * @dir_mode: mode bits of directory
+ * @dir_uid: owner of directory
* @inode: the inode of the file to open
*
* Block an O_CREAT open of a FIFO (or a regular file) when:
@@ -859,18 +860,18 @@ static int may_linkat(struct path *link)
*
* Returns 0 if the open is allowed, -ve on error.
*/
-static int may_create_in_sticky(struct dentry * const dir,
+static int may_create_in_sticky(umode_t dir_mode, kuid_t dir_uid,
struct inode * const inode)
{
if ((!sysctl_protected_fifos && S_ISFIFO(inode->i_mode)) ||
(!sysctl_protected_regular && S_ISREG(inode->i_mode)) ||
- likely(!(dir->d_inode->i_mode & S_ISVTX)) ||
- uid_eq(inode->i_uid, dir->d_inode->i_uid) ||
+ likely(!(dir_mode & S_ISVTX)) ||
+ uid_eq(inode->i_uid, dir_uid) ||
uid_eq(current_fsuid(), inode->i_uid))
return 0;
- if (likely(dir->d_inode->i_mode & 0002) ||
- (dir->d_inode->i_mode & 0020 &&
+ if (likely(dir_mode & 0002) ||
+ (dir_mode & 0020 &&
((sysctl_protected_fifos >= 2 && S_ISFIFO(inode->i_mode)) ||
(sysctl_protected_regular >= 2 && S_ISREG(inode->i_mode))))) {
return -EACCES;
@@ -2944,6 +2945,8 @@ static int do_last(struct nameidata *nd,
int *opened, struct filename *name)
{
struct dentry *dir = nd->path.dentry;
+ kuid_t dir_uid = dir->d_inode->i_uid;
+ umode_t dir_mode = dir->d_inode->i_mode;
int open_flag = op->open_flag;
bool will_truncate = (open_flag & O_TRUNC) != 0;
bool got_write = false;
@@ -3102,7 +3105,7 @@ finish_open:
error = -EISDIR;
if (d_is_dir(nd->path.dentry))
goto out;
- error = may_create_in_sticky(dir,
+ error = may_create_in_sticky(dir_mode, dir_uid,
d_backing_inode(nd->path.dentry));
if (unlikely(error))
goto out;
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Xiang Chen <[email protected]>
commit 465f4edaecc6c37f81349233e84d46246bcac11a upstream.
If an attached disk with protection information enabled is reformatted
to Type 0 the revalidation code does not clear the original protection
type and subsequent accesses will keep setting RDPROTECT/WRPROTECT.
Set the protection type to 0 if the disk reports PROT_EN=0 in READ
CAPACITY(16).
[mkp: commit desc]
Fixes: fe542396da73 ("[SCSI] sd: Ensure we correctly disable devices with unknown protection type")
Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Xiang Chen <[email protected]>
Signed-off-by: Martin K. Petersen <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
drivers/scsi/sd.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -1910,8 +1910,10 @@ static int sd_read_protection_type(struc
u8 type;
int ret = 0;
- if (scsi_device_protection(sdp) == 0 || (buffer[12] & 1) == 0)
+ if (scsi_device_protection(sdp) == 0 || (buffer[12] & 1) == 0) {
+ sdkp->protection_type = 0;
return ret;
+ }
type = ((buffer[12] >> 1) & 7) + 1; /* P_TYPE 0 = Type 1 */
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Johan Hovold <[email protected]>
commit ba9a103f40fc4a3ec7558ec9b0b97d4f92034249 upstream.
The driver was issuing synchronous uninterruptible control requests
without using a timeout. This could lead to the driver hanging on probe
due to a malfunctioning (or malicious) device until the device is
physically disconnected. While sleeping in probe the driver prevents
other devices connected to the same hub from being added to (or removed
from) the bus.
The USB upper limit of five seconds per request should be more than
enough.
Fixes: 99f83c9c9ac9 ("[PATCH] USB: add driver for Keyspan Digital Remote")
Signed-off-by: Johan Hovold <[email protected]>
Reviewed-by: Greg Kroah-Hartman <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Dmitry Torokhov <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
drivers/input/misc/keyspan_remote.c | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
--- a/drivers/input/misc/keyspan_remote.c
+++ b/drivers/input/misc/keyspan_remote.c
@@ -344,7 +344,8 @@ static int keyspan_setup(struct usb_devi
int retval = 0;
retval = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
- 0x11, 0x40, 0x5601, 0x0, NULL, 0, 0);
+ 0x11, 0x40, 0x5601, 0x0, NULL, 0,
+ USB_CTRL_SET_TIMEOUT);
if (retval) {
dev_dbg(&dev->dev, "%s - failed to set bit rate due to error: %d\n",
__func__, retval);
@@ -352,7 +353,8 @@ static int keyspan_setup(struct usb_devi
}
retval = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
- 0x44, 0x40, 0x0, 0x0, NULL, 0, 0);
+ 0x44, 0x40, 0x0, 0x0, NULL, 0,
+ USB_CTRL_SET_TIMEOUT);
if (retval) {
dev_dbg(&dev->dev, "%s - failed to set resume sensitivity due to error: %d\n",
__func__, retval);
@@ -360,7 +362,8 @@ static int keyspan_setup(struct usb_devi
}
retval = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
- 0x22, 0x40, 0x0, 0x0, NULL, 0, 0);
+ 0x22, 0x40, 0x0, 0x0, NULL, 0,
+ USB_CTRL_SET_TIMEOUT);
if (retval) {
dev_dbg(&dev->dev, "%s - failed to turn receive on due to error: %d\n",
__func__, retval);
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Alberto Aguirre <[email protected]>
commit 103e9625647ad74d201e26fb74afcd8479142a37 upstream.
Signed-off-by: Alberto Aguirre <[email protected]>
Signed-off-by: Takashi Iwai <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
sound/usb/pcm.c | 52 +++++++++++++++++++------------------------------
1 file changed, 20 insertions(+), 32 deletions(-)
--- a/sound/usb/pcm.c
+++ b/sound/usb/pcm.c
@@ -324,6 +324,7 @@ static int set_sync_ep_implicit_fb_quirk
struct usb_host_interface *alts;
struct usb_interface *iface;
unsigned int ep;
+ unsigned int ifnum;
/* Implicit feedback sync EPs consumers are always playback EPs */
if (subs->direction != SNDRV_PCM_STREAM_PLAYBACK)
@@ -333,44 +334,23 @@ static int set_sync_ep_implicit_fb_quirk
case USB_ID(0x0763, 0x2030): /* M-Audio Fast Track C400 */
case USB_ID(0x0763, 0x2031): /* M-Audio Fast Track C600 */
ep = 0x81;
- iface = usb_ifnum_to_if(dev, 3);
-
- if (!iface || iface->num_altsetting == 0)
- return -EINVAL;
-
- alts = &iface->altsetting[1];
- goto add_sync_ep;
- break;
+ ifnum = 3;
+ goto add_sync_ep_from_ifnum;
case USB_ID(0x0763, 0x2080): /* M-Audio FastTrack Ultra */
case USB_ID(0x0763, 0x2081):
ep = 0x81;
- iface = usb_ifnum_to_if(dev, 2);
-
- if (!iface || iface->num_altsetting == 0)
- return -EINVAL;
-
- alts = &iface->altsetting[1];
- goto add_sync_ep;
- case USB_ID(0x2466, 0x8003):
+ ifnum = 2;
+ goto add_sync_ep_from_ifnum;
+ case USB_ID(0x2466, 0x8003): /* Fractal Audio Axe-Fx II */
ep = 0x86;
- iface = usb_ifnum_to_if(dev, 2);
-
- if (!iface || iface->num_altsetting == 0)
- return -EINVAL;
-
- alts = &iface->altsetting[1];
- goto add_sync_ep;
- case USB_ID(0x1397, 0x0002):
+ ifnum = 2;
+ goto add_sync_ep_from_ifnum;
+ case USB_ID(0x1397, 0x0002): /* Behringer UFX1204 */
ep = 0x81;
- iface = usb_ifnum_to_if(dev, 1);
-
- if (!iface || iface->num_altsetting == 0)
- return -EINVAL;
-
- alts = &iface->altsetting[1];
- goto add_sync_ep;
-
+ ifnum = 1;
+ goto add_sync_ep_from_ifnum;
}
+
if (attr == USB_ENDPOINT_SYNC_ASYNC &&
altsd->bInterfaceClass == USB_CLASS_VENDOR_SPEC &&
altsd->bInterfaceProtocol == 2 &&
@@ -385,6 +365,14 @@ static int set_sync_ep_implicit_fb_quirk
/* No quirk */
return 0;
+add_sync_ep_from_ifnum:
+ iface = usb_ifnum_to_if(dev, ifnum);
+
+ if (!iface || iface->num_altsetting == 0)
+ return -EINVAL;
+
+ alts = &iface->altsetting[1];
+
add_sync_ep:
subs->sync_endpoint = snd_usb_add_endpoint(subs->stream->chip,
alts, ep, !subs->direction,
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Johan Hovold <[email protected]>
commit 3e4f8e21c4f27bcf30a48486b9dcc269512b79ff upstream.
Amend the endpoint-descriptor sanity checks to detect all duplicate
endpoint addresses in a configuration.
Commit 0a8fd1346254 ("USB: fix problems with duplicate endpoint
addresses") added a check for duplicate endpoint addresses within a
single alternate setting, but did not look for duplicate addresses in
other interfaces.
The current check would also not detect all duplicate addresses when one
endpoint is as a (bi-directional) control endpoint.
This specifically avoids overwriting the endpoint entries in struct
usb_device when enabling a duplicate endpoint, something which could
potentially lead to crashes or leaks, for example, when endpoints are
later disabled.
Signed-off-by: Johan Hovold <[email protected]>
Acked-by: Alan Stern <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Greg Kroah-Hartman <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
drivers/usb/core/config.c | 70 ++++++++++++++++++++++++++++++++-------
1 file changed, 58 insertions(+), 12 deletions(-)
--- a/drivers/usb/core/config.c
+++ b/drivers/usb/core/config.c
@@ -169,9 +169,58 @@ static const unsigned short super_speed_
[USB_ENDPOINT_XFER_INT] = 1024,
};
-static int usb_parse_endpoint(struct device *ddev, int cfgno, int inum,
- int asnum, struct usb_host_interface *ifp, int num_ep,
- unsigned char *buffer, int size)
+static bool endpoint_is_duplicate(struct usb_endpoint_descriptor *e1,
+ struct usb_endpoint_descriptor *e2)
+{
+ if (e1->bEndpointAddress == e2->bEndpointAddress)
+ return true;
+
+ if (usb_endpoint_xfer_control(e1) || usb_endpoint_xfer_control(e2)) {
+ if (usb_endpoint_num(e1) == usb_endpoint_num(e2))
+ return true;
+ }
+
+ return false;
+}
+
+/*
+ * Check for duplicate endpoint addresses in other interfaces and in the
+ * altsetting currently being parsed.
+ */
+static bool config_endpoint_is_duplicate(struct usb_host_config *config,
+ int inum, int asnum, struct usb_endpoint_descriptor *d)
+{
+ struct usb_endpoint_descriptor *epd;
+ struct usb_interface_cache *intfc;
+ struct usb_host_interface *alt;
+ int i, j, k;
+
+ for (i = 0; i < config->desc.bNumInterfaces; ++i) {
+ intfc = config->intf_cache[i];
+
+ for (j = 0; j < intfc->num_altsetting; ++j) {
+ alt = &intfc->altsetting[j];
+
+ if (alt->desc.bInterfaceNumber == inum &&
+ alt->desc.bAlternateSetting != asnum)
+ continue;
+
+ for (k = 0; k < alt->desc.bNumEndpoints; ++k) {
+ epd = &alt->endpoint[k].desc;
+
+ if (endpoint_is_duplicate(epd, d))
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+static int usb_parse_endpoint(struct device *ddev, int cfgno,
+ struct usb_host_config *config, int inum, int asnum,
+ struct usb_host_interface *ifp, int num_ep,
+ unsigned char *buffer, int size)
{
unsigned char *buffer0 = buffer;
struct usb_endpoint_descriptor *d;
@@ -208,13 +257,10 @@ static int usb_parse_endpoint(struct dev
goto skip_to_next_endpoint_or_interface_descriptor;
/* Check for duplicate endpoint addresses */
- for (i = 0; i < ifp->desc.bNumEndpoints; ++i) {
- if (ifp->endpoint[i].desc.bEndpointAddress ==
- d->bEndpointAddress) {
- dev_warn(ddev, "config %d interface %d altsetting %d has a duplicate endpoint with address 0x%X, skipping\n",
- cfgno, inum, asnum, d->bEndpointAddress);
- goto skip_to_next_endpoint_or_interface_descriptor;
- }
+ if (config_endpoint_is_duplicate(config, inum, asnum, d)) {
+ dev_warn(ddev, "config %d interface %d altsetting %d has a duplicate endpoint with address 0x%X, skipping\n",
+ cfgno, inum, asnum, d->bEndpointAddress);
+ goto skip_to_next_endpoint_or_interface_descriptor;
}
endpoint = &ifp->endpoint[ifp->desc.bNumEndpoints];
@@ -481,8 +527,8 @@ static int usb_parse_interface(struct de
if (((struct usb_descriptor_header *) buffer)->bDescriptorType
== USB_DT_INTERFACE)
break;
- retval = usb_parse_endpoint(ddev, cfgno, inum, asnum, alt,
- num_ep, buffer, size);
+ retval = usb_parse_endpoint(ddev, cfgno, config, inum, asnum,
+ alt, num_ep, buffer, size);
if (retval < 0)
return retval;
++n;
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Eric Dumazet <[email protected]>
commit eb8ef2a3c50092bb018077c047b8dba1ce0e78e3 upstream.
Both vlan_dev_change_flags() and vlan_dev_set_egress_priority()
can return an error. vlan_changelink() should not ignore them.
Fixes: 07b5b17e157b ("[VLAN]: Use rtnl_link API")
Signed-off-by: Eric Dumazet <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
net/8021q/vlan_netlink.c | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)
--- a/net/8021q/vlan_netlink.c
+++ b/net/8021q/vlan_netlink.c
@@ -92,11 +92,13 @@ static int vlan_changelink(struct net_de
struct ifla_vlan_flags *flags;
struct ifla_vlan_qos_mapping *m;
struct nlattr *attr;
- int rem;
+ int rem, err;
if (data[IFLA_VLAN_FLAGS]) {
flags = nla_data(data[IFLA_VLAN_FLAGS]);
- vlan_dev_change_flags(dev, flags->flags, flags->mask);
+ err = vlan_dev_change_flags(dev, flags->flags, flags->mask);
+ if (err)
+ return err;
}
if (data[IFLA_VLAN_INGRESS_QOS]) {
nla_for_each_nested(attr, data[IFLA_VLAN_INGRESS_QOS], rem) {
@@ -107,7 +109,9 @@ static int vlan_changelink(struct net_de
if (data[IFLA_VLAN_EGRESS_QOS]) {
nla_for_each_nested(attr, data[IFLA_VLAN_EGRESS_QOS], rem) {
m = nla_data(attr);
- vlan_dev_set_egress_priority(dev, m->from, m->to);
+ err = vlan_dev_set_egress_priority(dev, m->from, m->to);
+ if (err)
+ return err;
}
}
return 0;
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Suwan Kim <[email protected]>
commit aabb5b833872524eaf28f52187e5987984982264 upstream.
If a transaction error happens in vhci_recv_ret_submit(), event
handler closes connection and changes port status to kick hub_event.
Then hub tries to flush the endpoint URBs, but that causes infinite
loop between usb_hub_flush_endpoint() and vhci_urb_dequeue() because
"vhci_priv" in vhci_urb_dequeue() was already released by
vhci_recv_ret_submit() before a transmission error occurred. Thus,
vhci_urb_dequeue() terminates early and usb_hub_flush_endpoint()
continuously calls vhci_urb_dequeue().
The root cause of this issue is that vhci_recv_ret_submit()
terminates early without giving back URB when transaction error
occurs in vhci_recv_ret_submit(). That causes the error URB to still
be linked at endpoint list without “vhci_priv".
So, in the case of transaction error in vhci_recv_ret_submit(),
unlink URB from the endpoint, insert proper error code in
urb->status and give back URB.
Reported-by: Marek Marczykowski-Górecki <[email protected]>
Tested-by: Marek Marczykowski-Górecki <[email protected]>
Signed-off-by: Suwan Kim <[email protected]>
Acked-by: Shuah Khan <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Greg Kroah-Hartman <[email protected]>
[bwh: Backported to 3.16: adjust filename]
Signed-off-by: Ben Hutchings <[email protected]>
---
drivers/staging/usbip/vhci_rx.c | 13 +++++++++----
1 file changed, 9 insertions(+), 4 deletions(-)
--- a/drivers/staging/usbip/vhci_rx.c
+++ b/drivers/staging/usbip/vhci_rx.c
@@ -88,16 +88,21 @@ static void vhci_recv_ret_submit(struct
usbip_pack_pdu(pdu, urb, USBIP_RET_SUBMIT, 0);
/* recv transfer buffer */
- if (usbip_recv_xbuff(ud, urb) < 0)
- return;
+ if (usbip_recv_xbuff(ud, urb) < 0) {
+ urb->status = -EPROTO;
+ goto error;
+ }
/* recv iso_packet_descriptor */
- if (usbip_recv_iso(ud, urb) < 0)
- return;
+ if (usbip_recv_iso(ud, urb) < 0) {
+ urb->status = -EPROTO;
+ goto error;
+ }
/* restore the padding in iso packets */
usbip_pad_iso(ud, urb);
+error:
if (usbip_dbg_flag_vhci_rx)
usbip_dump_urb(urb);
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Jan Kara <[email protected]>
commit c70c176ff8c3ff0ac6ef9a831cd591ea9a66bd1a upstream.
Make the function available for outside use and fortify it against NULL
kobject.
CC: Greg Kroah-Hartman <[email protected]>
Reviewed-by: Bart Van Assche <[email protected]>
Acked-by: Tejun Heo <[email protected]>
Signed-off-by: Jan Kara <[email protected]>
Signed-off-by: Jens Axboe <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
include/linux/kobject.h | 2 ++
lib/kobject.c | 5 ++++-
2 files changed, 6 insertions(+), 1 deletion(-)
--- a/include/linux/kobject.h
+++ b/include/linux/kobject.h
@@ -107,6 +107,8 @@ extern int __must_check kobject_rename(s
extern int __must_check kobject_move(struct kobject *, struct kobject *);
extern struct kobject *kobject_get(struct kobject *kobj);
+extern struct kobject * __must_check kobject_get_unless_zero(
+ struct kobject *kobj);
extern void kobject_put(struct kobject *kobj);
extern const void *kobject_namespace(struct kobject *kobj);
--- a/lib/kobject.c
+++ b/lib/kobject.c
@@ -581,12 +581,15 @@ struct kobject *kobject_get(struct kobje
return kobj;
}
-static struct kobject * __must_check kobject_get_unless_zero(struct kobject *kobj)
+struct kobject * __must_check kobject_get_unless_zero(struct kobject *kobj)
{
+ if (!kobj)
+ return NULL;
if (!kref_get_unless_zero(&kobj->kref))
kobj = NULL;
return kobj;
}
+EXPORT_SYMBOL(kobject_get_unless_zero);
/*
* kobject_cleanup - free kobject resources.
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Takashi Iwai <[email protected]>
commit add9d56d7b3781532208afbff5509d7382fb6efe upstream.
The current PCM code doesn't initialize explicitly the buffers
allocated for PCM streams, hence it might leak some uninitialized
kernel data or previous stream contents by mmapping or reading the
buffer before actually starting the stream.
Since this is a common problem, this patch simply adds the clearance
of the buffer data at hw_params callback. Although this does only
zero-clear no matter which format is used, which doesn't mean the
silence for some formats, but it should be OK because the intention is
just to clear the previous data on the buffer.
Reported-by: Lionel Koenig <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Takashi Iwai <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
sound/core/pcm_native.c | 4 ++++
1 file changed, 4 insertions(+)
--- a/sound/core/pcm_native.c
+++ b/sound/core/pcm_native.c
@@ -459,6 +459,10 @@ static int snd_pcm_hw_params(struct snd_
while (runtime->boundary * 2 <= LONG_MAX - runtime->buffer_size)
runtime->boundary *= 2;
+ /* clear the buffer for avoiding possible kernel info leaks */
+ if (runtime->dma_area)
+ memset(runtime->dma_area, 0, runtime->dma_bytes);
+
snd_pcm_timer_resolution_change(substream);
snd_pcm_set_state(substream, SNDRV_PCM_STATE_SETUP);
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Radoslaw Tyl <[email protected]>
commit aa604651d523b1493988d0bf6710339f3ee60272 upstream.
Currently, though the FDB entry is added to VF, it does not appear in
RAR filters. VF driver only allows to add 10 entries. Attempting to add
another causes an error. This patch removes limitation and allows use of
all free RAR entries for the FDB if needed.
Fixes: 46ec20ff7d ("ixgbevf: Add macvlan support in the set rx mode op")
Signed-off-by: Radoslaw Tyl <[email protected]>
Acked-by: Paul Menzel <[email protected]>
Signed-off-by: Jeff Kirsher <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c | 5 -----
1 file changed, 5 deletions(-)
--- a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
+++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
@@ -1465,11 +1465,6 @@ static int ixgbevf_write_uc_addr_list(st
struct ixgbe_hw *hw = &adapter->hw;
int count = 0;
- if ((netdev_uc_count(netdev)) > 10) {
- pr_err("Too many unicast filters - No Space\n");
- return -ENOSPC;
- }
-
if (!netdev_uc_empty(netdev)) {
struct netdev_hw_addr *ha;
netdev_for_each_uc_addr(ha, netdev) {
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Wen Yang <[email protected]>
commit e31f7939c1c27faa5d0e3f14519eaf7c89e8a69d upstream.
The ftrace_profile->counter is unsigned long and
do_div truncates it to 32 bits, which means it can test
non-zero and be truncated to zero for division.
Fix this issue by using div64_ul() instead.
Link: http://lkml.kernel.org/r/[email protected]
Fixes: e330b3bcd8319 ("tracing: Show sample std dev in function profiling")
Fixes: 34886c8bc590f ("tracing: add average time in function to function profiler")
Signed-off-by: Wen Yang <[email protected]>
Signed-off-by: Steven Rostedt (VMware) <[email protected]>
[bwh: Backported to 3.16: adjust context]
Signed-off-by: Ben Hutchings <[email protected]>
---
kernel/trace/ftrace.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
--- a/kernel/trace/ftrace.c
+++ b/kernel/trace/ftrace.c
@@ -595,8 +595,7 @@ static int function_stat_show(struct seq
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
seq_printf(m, " ");
- avg = rec->time;
- do_div(avg, rec->counter);
+ avg = div64_ul(rec->time, rec->counter);
/* Sample standard deviation (s^2) */
if (rec->counter <= 1)
@@ -613,7 +612,8 @@ static int function_stat_show(struct seq
* Divide only 1000 for ns^2 -> us^2 conversion.
* trace_print_graph_duration will divide 1000 again.
*/
- do_div(stddev, rec->counter * (rec->counter - 1) * 1000);
+ stddev = div64_ul(stddev,
+ rec->counter * (rec->counter - 1) * 1000);
}
trace_seq_init(&s);
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Erkka Talvitie <[email protected]>
commit 64cc3f12d1c7dd054a215bc1ff9cc2abcfe35832 upstream.
When disconnecting a USB hub that has some child device(s) connected to it
(such as a USB mouse), then the stack tries to clear halt and
reset device(s) which are _already_ physically disconnected.
The issue has been reproduced with:
CPU: IMX6D5EYM10AD or MCIMX6D5EYM10AE.
SW: U-Boot 2019.07 and kernel 4.19.40.
CPU: HP Proliant Microserver Gen8.
SW: Linux version 4.2.3-300.fc23.x86_64
In this situation there will be error bit for MMF active yet the
CERR equals EHCI_TUNE_CERR + halt. Existing implementation
interprets this as a stall [1] (chapter 8.4.5).
The possible conditions when the MMF will be active + halt
can be found from [2] (Table 4-13).
Fix for the issue is to check whether MMF is active and PID Code is
IN before checking for the stall. If these conditions are true then
it is not a stall.
What happens after the fix is that when disconnecting a hub with
attached device(s) the situation is not interpret as a stall.
[1] [https://www.usb.org/document-library/usb-20-specification, usb_20.pdf]
[2] [https://www.intel.com/content/dam/www/public/us/en/documents/
technical-specifications/ehci-specification-for-usb.pdf]
Signed-off-by: Erkka Talvitie <[email protected]>
Reviewed-by: Alan Stern <[email protected]>
Link: https://lore.kernel.org/r/ef70941d5f349767f19c0ed26b0dd9eed8ad81bb.1576050523.git.erkka.talvitie@vincit.fi
Signed-off-by: Greg Kroah-Hartman <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
drivers/usb/host/ehci-q.c | 13 ++++++++++++-
1 file changed, 12 insertions(+), 1 deletion(-)
--- a/drivers/usb/host/ehci-q.c
+++ b/drivers/usb/host/ehci-q.c
@@ -40,6 +40,10 @@
/*-------------------------------------------------------------------------*/
+/* PID Codes that are used here, from EHCI specification, Table 3-16. */
+#define PID_CODE_IN 1
+#define PID_CODE_SETUP 2
+
/* fill a qtd, returning how much of the buffer we were able to queue up */
static int
@@ -199,7 +203,7 @@ static int qtd_copy_status (
int status = -EINPROGRESS;
/* count IN/OUT bytes, not SETUP (even short packets) */
- if (likely (QTD_PID (token) != 2))
+ if (likely(QTD_PID(token) != PID_CODE_SETUP))
urb->actual_length += length - QTD_LENGTH (token);
/* don't modify error codes */
@@ -215,6 +219,13 @@ static int qtd_copy_status (
if (token & QTD_STS_BABBLE) {
/* FIXME "must" disable babbling device's port too */
status = -EOVERFLOW;
+ /*
+ * When MMF is active and PID Code is IN, queue is halted.
+ * EHCI Specification, Table 4-13.
+ */
+ } else if ((token & QTD_STS_MMF) &&
+ (QTD_PID(token) == PID_CODE_IN)) {
+ status = -EPROTO;
/* CERR nonzero + halt --> stall */
} else if (QTD_CERR(token)) {
status = -EPIPE;
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Jian-Hong Pan <[email protected]>
commit 176a7fca81c5090a7240664e3002c106d296bf31 upstream.
Some of ASUS laptops like UX431FL keyboard backlight cannot be set to
brightness 0. According to ASUS' information, the brightness should be
0x80 ~ 0x83. This patch fixes it by following the logic.
Fixes: e9809c0b9670 ("asus-wmi: add keyboard backlight support")
Signed-off-by: Jian-Hong Pan <[email protected]>
Reviewed-by: Daniel Drake <[email protected]>
Signed-off-by: Andy Shevchenko <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
drivers/platform/x86/asus-wmi.c | 8 +-------
1 file changed, 1 insertion(+), 7 deletions(-)
--- a/drivers/platform/x86/asus-wmi.c
+++ b/drivers/platform/x86/asus-wmi.c
@@ -386,13 +386,7 @@ static void kbd_led_update(struct work_s
asus = container_of(work, struct asus_wmi, kbd_led_work);
- /*
- * bits 0-2: level
- * bit 7: light on/off
- */
- if (asus->kbd_led_wk > 0)
- ctrl_param = 0x80 | (asus->kbd_led_wk & 0x7F);
-
+ ctrl_param = 0x80 | (asus->kbd_led_wk & 0x7F);
asus_wmi_set_devstate(ASUS_WMI_DEVID_KBD_BACKLIGHT, ctrl_param, NULL);
}
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Filipe Manana <[email protected]>
commit 6609fee8897ac475378388238456c84298bff802 upstream.
When a tree mod log user no longer needs to use the tree it calls
btrfs_put_tree_mod_seq() to remove itself from the list of users and
delete all no longer used elements of the tree's red black tree, which
should be all elements with a sequence number less then our equals to
the caller's sequence number. However the logic is broken because it
can delete and free elements from the red black tree that have a
sequence number greater then the caller's sequence number:
1) At a point in time we have sequence numbers 1, 2, 3 and 4 in the
tree mod log;
2) The task which got assigned the sequence number 1 calls
btrfs_put_tree_mod_seq();
3) Sequence number 1 is deleted from the list of sequence numbers;
4) The current minimum sequence number is computed to be the sequence
number 2;
5) A task using sequence number 2 is at tree_mod_log_rewind() and gets
a pointer to one of its elements from the red black tree through
a call to tree_mod_log_search();
6) The task with sequence number 1 iterates the red black tree of tree
modification elements and deletes (and frees) all elements with a
sequence number less then or equals to 2 (the computed minimum sequence
number) - it ends up only leaving elements with sequence numbers of 3
and 4;
7) The task with sequence number 2 now uses the pointer to its element,
already freed by the other task, at __tree_mod_log_rewind(), resulting
in a use-after-free issue. When CONFIG_DEBUG_PAGEALLOC=y it produces
a trace like the following:
[16804.546854] general protection fault: 0000 [#1] PREEMPT SMP DEBUG_PAGEALLOC PTI
[16804.547451] CPU: 0 PID: 28257 Comm: pool Tainted: G W 5.4.0-rc8-btrfs-next-51 #1
[16804.548059] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.12.0-0-ga698c8995f-prebuilt.qemu.org 04/01/2014
[16804.548666] RIP: 0010:rb_next+0x16/0x50
(...)
[16804.550581] RSP: 0018:ffffb948418ef9b0 EFLAGS: 00010202
[16804.551227] RAX: 6b6b6b6b6b6b6b6b RBX: ffff90e0247f6600 RCX: 6b6b6b6b6b6b6b6b
[16804.551873] RDX: 0000000000000000 RSI: 0000000000000000 RDI: ffff90e0247f6600
[16804.552504] RBP: ffff90dffe0d4688 R08: 0000000000000001 R09: 0000000000000000
[16804.553136] R10: ffff90dffa4a0040 R11: 0000000000000000 R12: 000000000000002e
[16804.553768] R13: ffff90e0247f6600 R14: 0000000000001663 R15: ffff90dff77862b8
[16804.554399] FS: 00007f4b197ae700(0000) GS:ffff90e036a00000(0000) knlGS:0000000000000000
[16804.555039] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[16804.555683] CR2: 00007f4b10022000 CR3: 00000002060e2004 CR4: 00000000003606f0
[16804.556336] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
[16804.556968] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
[16804.557583] Call Trace:
[16804.558207] __tree_mod_log_rewind+0xbf/0x280 [btrfs]
[16804.558835] btrfs_search_old_slot+0x105/0xd00 [btrfs]
[16804.559468] resolve_indirect_refs+0x1eb/0xc70 [btrfs]
[16804.560087] ? free_extent_buffer.part.19+0x5a/0xc0 [btrfs]
[16804.560700] find_parent_nodes+0x388/0x1120 [btrfs]
[16804.561310] btrfs_check_shared+0x115/0x1c0 [btrfs]
[16804.561916] ? extent_fiemap+0x59d/0x6d0 [btrfs]
[16804.562518] extent_fiemap+0x59d/0x6d0 [btrfs]
[16804.563112] ? __might_fault+0x11/0x90
[16804.563706] do_vfs_ioctl+0x45a/0x700
[16804.564299] ksys_ioctl+0x70/0x80
[16804.564885] ? trace_hardirqs_off_thunk+0x1a/0x20
[16804.565461] __x64_sys_ioctl+0x16/0x20
[16804.566020] do_syscall_64+0x5c/0x250
[16804.566580] entry_SYSCALL_64_after_hwframe+0x49/0xbe
[16804.567153] RIP: 0033:0x7f4b1ba2add7
(...)
[16804.568907] RSP: 002b:00007f4b197adc88 EFLAGS: 00000246 ORIG_RAX: 0000000000000010
[16804.569513] RAX: ffffffffffffffda RBX: 00007f4b100210d8 RCX: 00007f4b1ba2add7
[16804.570133] RDX: 00007f4b100210d8 RSI: 00000000c020660b RDI: 0000000000000003
[16804.570726] RBP: 000055de05a6cfe0 R08: 0000000000000000 R09: 00007f4b197add44
[16804.571314] R10: 0000000000000000 R11: 0000000000000246 R12: 00007f4b197add48
[16804.571905] R13: 00007f4b197add40 R14: 00007f4b100210d0 R15: 00007f4b197add50
(...)
[16804.575623] ---[ end trace 87317359aad4ba50 ]---
Fix this by making btrfs_put_tree_mod_seq() skip deletion of elements that
have a sequence number equals to the computed minimum sequence number, and
not just elements with a sequence number greater then that minimum.
Fixes: bd989ba359f2ac ("Btrfs: add tree modification log functions")
Reviewed-by: Josef Bacik <[email protected]>
Signed-off-by: Filipe Manana <[email protected]>
Signed-off-by: David Sterba <[email protected]>
[bwh: Backported to 3.16: adjust context]
Signed-off-by: Ben Hutchings <[email protected]>
---
fs/btrfs/ctree.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/fs/btrfs/ctree.c
+++ b/fs/btrfs/ctree.c
@@ -418,7 +418,7 @@ void btrfs_put_tree_mod_seq(struct btrfs
for (node = rb_first(tm_root); node; node = next) {
next = rb_next(node);
tm = container_of(node, struct tree_mod_elem, node);
- if (tm->seq > min_seq)
+ if (tm->seq >= min_seq)
continue;
rb_erase(node, tm_root);
kfree(tm);
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Jan Kara <[email protected]>
commit 011278485ecc3cd2a3954b5d4c73101d919bf1fa upstream.
When doing delayed allocation, update of on-disk inode size is postponed
until IO submission time. However hole punch or zero range fallocate
calls can end up discarding the tail page cache page and thus on-disk
inode size would never be properly updated.
Make sure the on-disk inode size is updated before truncating page
cache.
Signed-off-by: Jan Kara <[email protected]>
Signed-off-by: Theodore Ts'o <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
fs/ext4/ext4.h | 3 +++
fs/ext4/extents.c | 5 +++++
fs/ext4/inode.c | 35 ++++++++++++++++++++++++++++++++++-
3 files changed, 42 insertions(+), 1 deletion(-)
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -2560,6 +2560,9 @@ static inline int ext4_update_inode_size
return changed;
}
+int ext4_update_disksize_before_punch(struct inode *inode, loff_t offset,
+ loff_t len);
+
struct ext4_group_info {
unsigned long bb_state;
struct rb_root bb_free_root;
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -4856,6 +4856,11 @@ static long ext4_zero_range(struct file
* released from page cache.
*/
down_write(&EXT4_I(inode)->i_mmap_sem);
+ ret = ext4_update_disksize_before_punch(inode, offset, len);
+ if (ret) {
+ up_write(&EXT4_I(inode)->i_mmap_sem);
+ goto out_dio;
+ }
/* Now release the pages and zero block aligned part of pages */
truncate_pagecache_range(inode, start, end - 1);
inode->i_mtime = inode->i_ctime = ext4_current_time(inode);
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -3652,6 +3652,35 @@ int ext4_can_truncate(struct inode *inod
}
/*
+ * We have to make sure i_disksize gets properly updated before we truncate
+ * page cache due to hole punching or zero range. Otherwise i_disksize update
+ * can get lost as it may have been postponed to submission of writeback but
+ * that will never happen after we truncate page cache.
+ */
+int ext4_update_disksize_before_punch(struct inode *inode, loff_t offset,
+ loff_t len)
+{
+ handle_t *handle;
+ loff_t size = i_size_read(inode);
+
+ WARN_ON(!mutex_is_locked(&inode->i_mutex));
+ if (offset > size || offset + len < size)
+ return 0;
+
+ if (EXT4_I(inode)->i_disksize >= size)
+ return 0;
+
+ handle = ext4_journal_start(inode, EXT4_HT_MISC, 1);
+ if (IS_ERR(handle))
+ return PTR_ERR(handle);
+ ext4_update_i_disksize(inode, size);
+ ext4_mark_inode_dirty(handle, inode);
+ ext4_journal_stop(handle);
+
+ return 0;
+}
+
+/*
* ext4_punch_hole: punches a hole in a file by releaseing the blocks
* associated with the given offset and length
*
@@ -3729,9 +3758,13 @@ int ext4_punch_hole(struct inode *inode,
last_block_offset = round_down((offset + length), sb->s_blocksize) - 1;
/* Now release the pages and zero block aligned part of pages*/
- if (last_block_offset > first_block_offset)
+ if (last_block_offset > first_block_offset) {
+ ret = ext4_update_disksize_before_punch(inode, offset, length);
+ if (ret)
+ goto out_dio;
truncate_pagecache_range(inode, first_block_offset,
last_block_offset);
+ }
if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS))
credits = ext4_writepage_trans_blocks(inode);
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Mao Wenan <[email protected]>
commit 6e1cdedcf0362fed3aedfe051d46bd7ee2a85fe1 upstream.
NETDEV_TX_BUSY really should only be used by drivers that call
netif_tx_stop_queue() at the wrong moment. If dma_map_single() is
failed to map tx DMA buffer, it might trigger an infinite loop.
This patch use NETDEV_TX_OK instead of NETDEV_TX_BUSY, and change
printk to pr_err_ratelimited.
Fixes: d9fb9f384292 ("*sonic/natsemi/ns83829: Move the National Semi-conductor drivers")
Signed-off-by: Mao Wenan <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
drivers/net/ethernet/natsemi/sonic.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
--- a/drivers/net/ethernet/natsemi/sonic.c
+++ b/drivers/net/ethernet/natsemi/sonic.c
@@ -221,9 +221,9 @@ static int sonic_send_packet(struct sk_b
laddr = dma_map_single(lp->device, skb->data, length, DMA_TO_DEVICE);
if (!laddr) {
- printk(KERN_ERR "%s: failed to map tx DMA buffer.\n", dev->name);
+ pr_err_ratelimited("%s: failed to map tx DMA buffer.\n", dev->name);
dev_kfree_skb(skb);
- return NETDEV_TX_BUSY;
+ return NETDEV_TX_OK;
}
sonic_tda_put(dev, entry, SONIC_TD_STATUS, 0); /* clear status */
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Jose Abreu <[email protected]>
commit b2f3a481c4cd62f78391b836b64c0a6e72b503d2 upstream.
XGMAC supports maximum MTU that can go to 16KB. Lets add this check in
the calculation of RX buffer size.
Fixes: 7ac6653a085b ("stmmac: Move the STMicroelectronics driver")
Signed-off-by: Jose Abreu <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -904,7 +904,9 @@ static int stmmac_set_bfsize(int mtu, in
{
int ret = bufsize;
- if (mtu >= BUF_SIZE_4KiB)
+ if (mtu >= BUF_SIZE_8KiB)
+ ret = BUF_SIZE_16KiB;
+ else if (mtu >= BUF_SIZE_4KiB)
ret = BUF_SIZE_8KiB;
else if (mtu >= BUF_SIZE_2KiB)
ret = BUF_SIZE_4KiB;
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Florian Westphal <[email protected]>
commit 22dad713b8a5ff488e07b821195270672f486eb2 upstream.
The set uadt functions assume lineno is never NULL, but it is in
case of ip_set_utest().
syzkaller managed to generate a netlink message that calls this with
LINENO attr present:
general protection fault: 0000 [#1] PREEMPT SMP KASAN
RIP: 0010:hash_mac4_uadt+0x1bc/0x470 net/netfilter/ipset/ip_set_hash_mac.c:104
Call Trace:
ip_set_utest+0x55b/0x890 net/netfilter/ipset/ip_set_core.c:1867
nfnetlink_rcv_msg+0xcf2/0xfb0 net/netfilter/nfnetlink.c:229
netlink_rcv_skb+0x177/0x450 net/netlink/af_netlink.c:2477
nfnetlink_rcv+0x1ba/0x460 net/netfilter/nfnetlink.c:563
pass a dummy lineno storage, its easier than patching all set
implementations.
This seems to be a day-0 bug.
Cc: Jozsef Kadlecsik <[email protected]>
Reported-by: [email protected]
Fixes: a7b4f989a6294 ("netfilter: ipset: IP set core support")
Signed-off-by: Florian Westphal <[email protected]>
Acked-by: Jozsef Kadlecsik <[email protected]>
Signed-off-by: Pablo Neira Ayuso <[email protected]>
[bwh: Backported to 3.16: adjust context]
Signed-off-by: Ben Hutchings <[email protected]>
---
net/netfilter/ipset/ip_set_core.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
--- a/net/netfilter/ipset/ip_set_core.c
+++ b/net/netfilter/ipset/ip_set_core.c
@@ -1549,6 +1549,7 @@ ip_set_utest(struct sock *ctnl, struct s
struct ip_set *set;
struct nlattr *tb[IPSET_ATTR_ADT_MAX+1] = {};
int ret = 0;
+ u32 lineno;
if (unlikely(protocol_failed(attr) ||
attr[IPSET_ATTR_SETNAME] == NULL ||
@@ -1565,7 +1566,7 @@ ip_set_utest(struct sock *ctnl, struct s
return -IPSET_ERR_PROTOCOL;
read_lock_bh(&set->lock);
- ret = set->variant->uadt(set, tb, IPSET_TEST, NULL, 0, 0);
+ ret = set->variant->uadt(set, tb, IPSET_TEST, &lineno, 0, 0);
read_unlock_bh(&set->lock);
/* Userspace can't trigger element to be re-added */
if (ret == -EAGAIN)
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Florian Westphal <[email protected]>
commit 1b789577f655060d98d20ed0c6f9fbd469d6ba63 upstream.
We get crash when the targets checkentry function tries to make
use of the network namespace pointer for arptables.
When the net pointer got added back in 2010, only ip/ip6/ebtables were
changed to initialize it, so arptables has this set to NULL.
This isn't a problem for normal arptables because no existing
arptables target has a checkentry function that makes use of par->net.
However, direct users of the setsockopt interface can provide any
target they want as long as its registered for ARP or UNPSEC protocols.
syzkaller managed to send a semi-valid arptables rule for RATEEST target
which is enough to trigger NULL deref:
kasan: GPF could be caused by NULL-ptr deref or user memory access
general protection fault: 0000 [#1] PREEMPT SMP KASAN
RIP: xt_rateest_tg_checkentry+0x11d/0xb40 net/netfilter/xt_RATEEST.c:109
[..]
xt_check_target+0x283/0x690 net/netfilter/x_tables.c:1019
check_target net/ipv4/netfilter/arp_tables.c:399 [inline]
find_check_entry net/ipv4/netfilter/arp_tables.c:422 [inline]
translate_table+0x1005/0x1d70 net/ipv4/netfilter/arp_tables.c:572
do_replace net/ipv4/netfilter/arp_tables.c:977 [inline]
do_arpt_set_ctl+0x310/0x640 net/ipv4/netfilter/arp_tables.c:1456
Fixes: add67461240c1d ("netfilter: add struct net * to target parameters")
Reported-by: [email protected]
Signed-off-by: Florian Westphal <[email protected]>
Acked-by: Cong Wang <[email protected]>
Signed-off-by: Pablo Neira Ayuso <[email protected]>
[bwh: Backported to 3.16: adjust context]
Signed-off-by: Ben Hutchings <[email protected]>
---
net/ipv4/netfilter/arp_tables.c | 27 ++++++++++++++++-----------
1 file changed, 16 insertions(+), 11 deletions(-)
--- a/net/ipv4/netfilter/arp_tables.c
+++ b/net/ipv4/netfilter/arp_tables.c
@@ -480,11 +480,12 @@ static int mark_source_chains(const stru
return 1;
}
-static inline int check_target(struct arpt_entry *e, const char *name)
+static int check_target(struct arpt_entry *e, struct net *net, const char *name)
{
struct xt_entry_target *t = arpt_get_target(e);
int ret;
struct xt_tgchk_param par = {
+ .net = net,
.table = name,
.entryinfo = e,
.target = t->u.kernel.target,
@@ -502,8 +503,9 @@ static inline int check_target(struct ar
return 0;
}
-static inline int
-find_check_entry(struct arpt_entry *e, const char *name, unsigned int size)
+static int
+find_check_entry(struct arpt_entry *e, struct net *net, const char *name,
+ unsigned int size)
{
struct xt_entry_target *t;
struct xt_target *target;
@@ -519,7 +521,7 @@ find_check_entry(struct arpt_entry *e, c
}
t->u.kernel.target = target;
- ret = check_target(e, name);
+ ret = check_target(e, net, name);
if (ret)
goto err;
return 0;
@@ -617,7 +619,9 @@ static inline void cleanup_entry(struct
/* Checks and translates the user-supplied table segment (held in
* newinfo).
*/
-static int translate_table(struct xt_table_info *newinfo, void *entry0,
+static int translate_table(struct net *net,
+ struct xt_table_info *newinfo,
+ void *entry0,
const struct arpt_replace *repl)
{
struct arpt_entry *iter;
@@ -692,7 +696,7 @@ static int translate_table(struct xt_tab
/* Finally, each sanity check must pass */
i = 0;
xt_entry_foreach(iter, entry0, newinfo->size) {
- ret = find_check_entry(iter, repl->name, repl->size);
+ ret = find_check_entry(iter, net, repl->name, repl->size);
if (ret != 0)
break;
++i;
@@ -1100,7 +1104,7 @@ static int do_replace(struct net *net, c
goto free_newinfo;
}
- ret = translate_table(newinfo, loc_cpu_entry, &tmp);
+ ret = translate_table(net, newinfo, loc_cpu_entry, &tmp);
if (ret != 0)
goto free_newinfo;
@@ -1287,7 +1291,8 @@ compat_copy_entry_from_user(struct compa
}
}
-static int translate_compat_table(struct xt_table_info **pinfo,
+static int translate_compat_table(struct net *net,
+ struct xt_table_info **pinfo,
void **pentry0,
const struct compat_arpt_replace *compatr)
{
@@ -1356,7 +1361,7 @@ static int translate_compat_table(struct
repl.num_counters = 0;
repl.counters = NULL;
repl.size = newinfo->size;
- ret = translate_table(newinfo, entry1, &repl);
+ ret = translate_table(net, newinfo, entry1, &repl);
if (ret)
goto free_newinfo;
@@ -1412,7 +1417,7 @@ static int compat_do_replace(struct net
goto free_newinfo;
}
- ret = translate_compat_table(&newinfo, &loc_cpu_entry, &tmp);
+ ret = translate_compat_table(net, &newinfo, &loc_cpu_entry, &tmp);
if (ret != 0)
goto free_newinfo;
@@ -1685,7 +1690,7 @@ struct xt_table *arpt_register_table(str
loc_cpu_entry = newinfo->entries[raw_smp_processor_id()];
memcpy(loc_cpu_entry, repl->entries, repl->size);
- ret = translate_table(newinfo, loc_cpu_entry, repl);
+ ret = translate_table(net, newinfo, loc_cpu_entry, repl);
duprintf("arpt_register_table: translate table gives %d\n", ret);
if (ret != 0)
goto out_free;
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Christophe Leroy <[email protected]>
commit 099bc4812f09155da77eeb960a983470249c9ce1 upstream.
Before commit 0366a1c70b89 ("powerpc/irq: Run softirqs off the top of
the irq stack"), check_stack_overflow() was called by do_IRQ(), before
switching to the irq stack.
In that commit, do_IRQ() was renamed __do_irq(), and is now executing
on the irq stack, so check_stack_overflow() has just become almost
useless.
Move check_stack_overflow() call in do_IRQ() to do the check while
still on the current stack.
Fixes: 0366a1c70b89 ("powerpc/irq: Run softirqs off the top of the irq stack")
Signed-off-by: Christophe Leroy <[email protected]>
Signed-off-by: Michael Ellerman <[email protected]>
Link: https://lore.kernel.org/r/e033aa8116ab12b7ca9a9c75189ad0741e3b9b5f.1575872340.git.christophe.leroy@c-s.fr
Signed-off-by: Ben Hutchings <[email protected]>
---
arch/powerpc/kernel/irq.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
--- a/arch/powerpc/kernel/irq.c
+++ b/arch/powerpc/kernel/irq.c
@@ -471,8 +471,6 @@ void __do_irq(struct pt_regs *regs)
trace_irq_entry(regs);
- check_stack_overflow();
-
/*
* Query the platform PIC for the interrupt & ack it.
*
@@ -504,6 +502,8 @@ void do_IRQ(struct pt_regs *regs)
irqtp = hardirq_ctx[raw_smp_processor_id()];
sirqtp = softirq_ctx[raw_smp_processor_id()];
+ check_stack_overflow();
+
/* Already there ? */
if (unlikely(curtp == irqtp || curtp == sirqtp)) {
__do_irq(regs);
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Marcel Holtmann <[email protected]>
commit 9f3b61dc1dd7b81e99e7ed23776bb64a35f39e1a upstream.
When polling a connected /dev/hidrawX device, it is useful to get the
EPOLLOUT when writing is possible. Since writing is possible as soon as
the device is connected, always return it.
Right now EPOLLOUT is only returned when there are also input reports
are available. This works if devices start sending reports when
connected, but some HID devices might need an output report first before
sending any input reports. This change will allow using EPOLLOUT here as
well.
Fixes: 378b80370aa1 ("hidraw: Return EPOLLOUT from hidraw_poll")
Signed-off-by: Marcel Holtmann <[email protected]>
Signed-off-by: Jiri Kosina <[email protected]>
[bwh: Backported to 3.16: s/EPOLL/POLL/g]
Signed-off-by: Ben Hutchings <[email protected]>
---
drivers/hid/hidraw.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
--- a/drivers/hid/hidraw.c
+++ b/drivers/hid/hidraw.c
@@ -265,10 +265,10 @@ static unsigned int hidraw_poll(struct f
poll_wait(file, &list->hidraw->wait, wait);
if (list->head != list->tail)
- return POLLIN | POLLRDNORM | POLLOUT;
+ return POLLIN | POLLRDNORM;
if (!list->hidraw->exist)
return POLLERR | POLLHUP;
- return 0;
+ return POLLOUT | POLLWRNORM;
}
static int hidraw_open(struct inode *inode, struct file *file)
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Paul Cercueil <[email protected]>
commit c80d0f4426c7fdc7efd6ae8d8b021dcfc89b4254 upstream.
The IRQ handler was passed a pointer to a struct dma_controller, but the
argument was then casted to a pointer to a struct musb_dma_controller.
Fixes: 427c4f333474 ("usb: struct device - replace bus_id with dev_name(), dev_set_name()")
Signed-off-by: Paul Cercueil <[email protected]>
Tested-by: Artur Rojek <[email protected]>
Signed-off-by: Bin Liu <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Greg Kroah-Hartman <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
drivers/usb/musb/musbhsdma.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/usb/musb/musbhsdma.c
+++ b/drivers/usb/musb/musbhsdma.c
@@ -396,7 +396,7 @@ struct dma_controller *dma_controller_cr
controller->controller.channel_abort = dma_channel_abort;
if (request_irq(irq, dma_controller_irq, 0,
- dev_name(musb->controller), &controller->controller)) {
+ dev_name(musb->controller), controller)) {
dev_err(dev, "request_irq %d failed!\n", irq);
dma_controller_destroy(&controller->controller);
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Florian Westphal <[email protected]>
commit fc6a5d0601c5ac1d02f283a46f60b87b2033e5ca upstream.
All of these conditions are not fatal and should have
been WARN_ONs from the get-go.
Convert them to WARN_ONs and bail out.
Signed-off-by: Florian Westphal <[email protected]>
Signed-off-by: Pablo Neira Ayuso <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
net/bridge/netfilter/ebtables.c | 27 ++++++++++++++++++---------
1 file changed, 18 insertions(+), 9 deletions(-)
--- a/net/bridge/netfilter/ebtables.c
+++ b/net/bridge/netfilter/ebtables.c
@@ -1603,7 +1603,8 @@ static int compat_match_to_user(struct e
int off = ebt_compat_match_offset(match, m->match_size);
compat_uint_t msize = m->match_size - off;
- BUG_ON(off >= m->match_size);
+ if (WARN_ON(off >= m->match_size))
+ return -EINVAL;
if (copy_to_user(cm->u.name, match->name,
strlen(match->name) + 1) || put_user(msize, &cm->match_size))
@@ -1630,7 +1631,8 @@ static int compat_target_to_user(struct
int off = xt_compat_target_offset(target);
compat_uint_t tsize = t->target_size - off;
- BUG_ON(off >= t->target_size);
+ if (WARN_ON(off >= t->target_size))
+ return -EINVAL;
if (copy_to_user(cm->u.name, target->name,
strlen(target->name) + 1) || put_user(tsize, &cm->match_size))
@@ -1858,7 +1860,8 @@ static int ebt_buf_add(struct ebt_entrie
if (state->buf_kern_start == NULL)
goto count_only;
- BUG_ON(state->buf_kern_offset + sz > state->buf_kern_len);
+ if (WARN_ON(state->buf_kern_offset + sz > state->buf_kern_len))
+ return -EINVAL;
memcpy(state->buf_kern_start + state->buf_kern_offset, data, sz);
@@ -1871,7 +1874,8 @@ static int ebt_buf_add_pad(struct ebt_en
{
char *b = state->buf_kern_start;
- BUG_ON(b && state->buf_kern_offset > state->buf_kern_len);
+ if (WARN_ON(b && state->buf_kern_offset > state->buf_kern_len))
+ return -EINVAL;
if (b != NULL && sz > 0)
memset(b + state->buf_kern_offset, 0, sz);
@@ -1949,8 +1953,10 @@ static int compat_mtw_from_user(struct c
pad = XT_ALIGN(size_kern) - size_kern;
if (pad > 0 && dst) {
- BUG_ON(state->buf_kern_len <= pad);
- BUG_ON(state->buf_kern_offset - (match_size + off) + size_kern > state->buf_kern_len - pad);
+ if (WARN_ON(state->buf_kern_len <= pad))
+ return -EINVAL;
+ if (WARN_ON(state->buf_kern_offset - (match_size + off) + size_kern > state->buf_kern_len - pad))
+ return -EINVAL;
memset(dst + size_kern, 0, pad);
}
return off + match_size;
@@ -2001,7 +2007,8 @@ static int ebt_size_mwt(struct compat_eb
if (ret < 0)
return ret;
- BUG_ON(ret < match32->match_size);
+ if (WARN_ON(ret < match32->match_size))
+ return -EINVAL;
growth += ret - match32->match_size;
growth += ebt_compat_entry_padsize();
@@ -2116,7 +2123,8 @@ static int size_entry_mwt(struct ebt_ent
startoff = state->buf_user_offset - startoff;
- BUG_ON(*total < startoff);
+ if (WARN_ON(*total < startoff))
+ return -EINVAL;
*total -= startoff;
return 0;
}
@@ -2246,7 +2254,8 @@ static int compat_do_replace(struct net
state.buf_kern_len = size64;
ret = compat_copy_entries(entries_tmp, tmp.entries_size, &state);
- BUG_ON(ret < 0); /* parses same data again */
+ if (WARN_ON(ret < 0))
+ goto out_unlock;
vfree(entries_tmp);
tmp.entries_size = size64;
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Amir Goldstein <[email protected]>
commit 98ca480a8f22fdbd768e3dad07024c8d4856576c upstream.
An ino is unsigned, so display it as such in /proc/locks.
Signed-off-by: Amir Goldstein <[email protected]>
Signed-off-by: Jeff Layton <[email protected]>
[bwh: Backported to 3.16: adjust context]
Signed-off-by: Ben Hutchings <[email protected]>
---
fs/locks.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/fs/locks.c
+++ b/fs/locks.c
@@ -2488,7 +2488,7 @@ static void lock_get_status(struct seq_f
inode->i_sb->s_id, inode->i_ino);
#else
/* userspace relies on this representation of dev_t ;-( */
- seq_printf(f, "%d %02x:%02x:%ld ", fl_pid,
+ seq_printf(f, "%d %02x:%02x:%lu ", fl_pid,
MAJOR(inode->i_sb->s_dev),
MINOR(inode->i_sb->s_dev), inode->i_ino);
#endif
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Florian Westphal <[email protected]>
commit e608f631f0ba5f1fc5ee2e260a3a35d13107cbfe upstream.
syzbot reported following splat:
BUG: KASAN: vmalloc-out-of-bounds in size_entry_mwt net/bridge/netfilter/ebtables.c:2063 [inline]
BUG: KASAN: vmalloc-out-of-bounds in compat_copy_entries+0x128b/0x1380 net/bridge/netfilter/ebtables.c:2155
Read of size 4 at addr ffffc900004461f4 by task syz-executor267/7937
CPU: 1 PID: 7937 Comm: syz-executor267 Not tainted 5.5.0-rc1-syzkaller #0
size_entry_mwt net/bridge/netfilter/ebtables.c:2063 [inline]
compat_copy_entries+0x128b/0x1380 net/bridge/netfilter/ebtables.c:2155
compat_do_replace+0x344/0x720 net/bridge/netfilter/ebtables.c:2249
compat_do_ebt_set_ctl+0x22f/0x27e net/bridge/netfilter/ebtables.c:2333
[..]
Because padding isn't considered during computation of ->buf_user_offset,
"total" is decremented by fewer bytes than it should.
Therefore, the first part of
if (*total < sizeof(*entry) || entry->next_offset < sizeof(*entry))
will pass, -- it should not have. This causes oob access:
entry->next_offset is past the vmalloced size.
Reject padding and check that computed user offset (sum of ebt_entry
structure plus all individual matches/watchers/targets) is same
value that userspace gave us as the offset of the next entry.
Reported-by: [email protected]
Fixes: 81e675c227ec ("netfilter: ebtables: add CONFIG_COMPAT support")
Signed-off-by: Florian Westphal <[email protected]>
Signed-off-by: Pablo Neira Ayuso <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
net/bridge/netfilter/ebtables.c | 33 ++++++++++++++++-----------------
1 file changed, 16 insertions(+), 17 deletions(-)
--- a/net/bridge/netfilter/ebtables.c
+++ b/net/bridge/netfilter/ebtables.c
@@ -1855,7 +1855,7 @@ static int ebt_buf_count(struct ebt_entr
}
static int ebt_buf_add(struct ebt_entries_buf_state *state,
- void *data, unsigned int sz)
+ const void *data, unsigned int sz)
{
if (state->buf_kern_start == NULL)
goto count_only;
@@ -1889,7 +1889,7 @@ enum compat_mwt {
EBT_COMPAT_TARGET,
};
-static int compat_mtw_from_user(struct compat_ebt_entry_mwt *mwt,
+static int compat_mtw_from_user(const struct compat_ebt_entry_mwt *mwt,
enum compat_mwt compat_mwt,
struct ebt_entries_buf_state *state,
const unsigned char *base)
@@ -1966,22 +1966,23 @@ static int compat_mtw_from_user(struct c
* return size of all matches, watchers or target, including necessary
* alignment and padding.
*/
-static int ebt_size_mwt(struct compat_ebt_entry_mwt *match32,
+static int ebt_size_mwt(const struct compat_ebt_entry_mwt *match32,
unsigned int size_left, enum compat_mwt type,
struct ebt_entries_buf_state *state, const void *base)
{
+ const char *buf = (const char *)match32;
int growth = 0;
- char *buf;
if (size_left == 0)
return 0;
- buf = (char *) match32;
-
- while (size_left >= sizeof(*match32)) {
+ do {
struct ebt_entry_match *match_kern;
int ret;
+ if (size_left < sizeof(*match32))
+ return -EINVAL;
+
match_kern = (struct ebt_entry_match *) state->buf_kern_start;
if (match_kern) {
char *tmp;
@@ -2018,22 +2019,18 @@ static int ebt_size_mwt(struct compat_eb
if (match_kern)
match_kern->match_size = ret;
- /* rule should have no remaining data after target */
- if (type == EBT_COMPAT_TARGET && size_left)
- return -EINVAL;
-
match32 = (struct compat_ebt_entry_mwt *) buf;
- }
+ } while (size_left);
return growth;
}
/* called for all ebt_entry structures. */
-static int size_entry_mwt(struct ebt_entry *entry, const unsigned char *base,
+static int size_entry_mwt(const struct ebt_entry *entry, const unsigned char *base,
unsigned int *total,
struct ebt_entries_buf_state *state)
{
- unsigned int i, j, startoff, new_offset = 0;
+ unsigned int i, j, startoff, next_expected_off, new_offset = 0;
/* stores match/watchers/targets & offset of next struct ebt_entry: */
unsigned int offsets[4];
unsigned int *offsets_update = NULL;
@@ -2121,11 +2118,13 @@ static int size_entry_mwt(struct ebt_ent
return ret;
}
- startoff = state->buf_user_offset - startoff;
+ next_expected_off = state->buf_user_offset - startoff;
+ if (next_expected_off != entry->next_offset)
+ return -EINVAL;
- if (WARN_ON(*total < startoff))
+ if (*total < entry->next_offset)
return -EINVAL;
- *total -= startoff;
+ *total -= entry->next_offset;
return 0;
}
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Xin Long <[email protected]>
commit be7a7729207797476b6666f046d765bdf9630407 upstream.
This patch is to fix a memleak caused by no place to free cmd->obj.chunk
for the unprocessed SCTP_CMD_REPLY. This issue occurs when failing to
process a cmd while there're still SCTP_CMD_REPLY cmds on the cmd seq
with an allocated chunk in cmd->obj.chunk.
So fix it by freeing cmd->obj.chunk for each SCTP_CMD_REPLY cmd left on
the cmd seq when any cmd returns error. While at it, also remove 'nomem'
label.
Reported-by: [email protected]
Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Signed-off-by: Xin Long <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
net/sctp/sm_sideeffect.c | 28 ++++++++++++++++++----------
1 file changed, 18 insertions(+), 10 deletions(-)
--- a/net/sctp/sm_sideeffect.c
+++ b/net/sctp/sm_sideeffect.c
@@ -1327,8 +1327,10 @@ static int sctp_cmd_interpreter(sctp_eve
/* Generate an INIT ACK chunk. */
new_obj = sctp_make_init_ack(asoc, chunk, GFP_ATOMIC,
0);
- if (!new_obj)
- goto nomem;
+ if (!new_obj) {
+ error = -ENOMEM;
+ break;
+ }
sctp_add_cmd_sf(commands, SCTP_CMD_REPLY,
SCTP_CHUNK(new_obj));
@@ -1350,7 +1352,8 @@ static int sctp_cmd_interpreter(sctp_eve
if (!new_obj) {
if (cmd->obj.chunk)
sctp_chunk_free(cmd->obj.chunk);
- goto nomem;
+ error = -ENOMEM;
+ break;
}
sctp_add_cmd_sf(commands, SCTP_CMD_REPLY,
SCTP_CHUNK(new_obj));
@@ -1397,8 +1400,10 @@ static int sctp_cmd_interpreter(sctp_eve
/* Generate a SHUTDOWN chunk. */
new_obj = sctp_make_shutdown(asoc, chunk);
- if (!new_obj)
- goto nomem;
+ if (!new_obj) {
+ error = -ENOMEM;
+ break;
+ }
sctp_add_cmd_sf(commands, SCTP_CMD_REPLY,
SCTP_CHUNK(new_obj));
break;
@@ -1727,11 +1732,17 @@ static int sctp_cmd_interpreter(sctp_eve
break;
}
- if (error)
+ if (error) {
+ cmd = sctp_next_cmd(commands);
+ while (cmd) {
+ if (cmd->verb == SCTP_CMD_REPLY)
+ sctp_chunk_free(cmd->obj.chunk);
+ cmd = sctp_next_cmd(commands);
+ }
break;
+ }
}
-out:
/* If this is in response to a received chunk, wait until
* we are done with the packet to open the queue so that we don't
* send multiple packets in response to a single request.
@@ -1742,8 +1753,5 @@ out:
} else if (local_cork)
error = sctp_outq_uncork(&asoc->outqueue);
return error;
-nomem:
- error = -ENOMEM;
- goto out;
}
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Eric Dumazet <[email protected]>
commit 96cc4b69581db68efc9749ef32e9cf8e0160c509 upstream.
Use of eth_hdr() in tx path is error prone.
Many drivers call skb_reset_mac_header() before using it,
but others do not.
Commit 6d1ccff62780 ("net: reset mac header in dev_start_xmit()")
attempted to fix this generically, but commit d346a3fae3ff
("packet: introduce PACKET_QDISC_BYPASS socket option") brought
back the macvlan bug.
Lets add a new helper, so that tx paths no longer have
to call skb_reset_mac_header() only to get a pointer
to skb->data.
Hopefully we will be able to revert 6d1ccff62780
("net: reset mac header in dev_start_xmit()") and save few cycles
in transmit fast path.
BUG: KASAN: use-after-free in __get_unaligned_cpu32 include/linux/unaligned/packed_struct.h:19 [inline]
BUG: KASAN: use-after-free in mc_hash drivers/net/macvlan.c:251 [inline]
BUG: KASAN: use-after-free in macvlan_broadcast+0x547/0x620 drivers/net/macvlan.c:277
Read of size 4 at addr ffff8880a4932401 by task syz-executor947/9579
CPU: 0 PID: 9579 Comm: syz-executor947 Not tainted 5.5.0-rc4-syzkaller #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+0x197/0x210 lib/dump_stack.c:118
print_address_description.constprop.0.cold+0xd4/0x30b mm/kasan/report.c:374
__kasan_report.cold+0x1b/0x41 mm/kasan/report.c:506
kasan_report+0x12/0x20 mm/kasan/common.c:639
__asan_report_load_n_noabort+0xf/0x20 mm/kasan/generic_report.c:145
__get_unaligned_cpu32 include/linux/unaligned/packed_struct.h:19 [inline]
mc_hash drivers/net/macvlan.c:251 [inline]
macvlan_broadcast+0x547/0x620 drivers/net/macvlan.c:277
macvlan_queue_xmit drivers/net/macvlan.c:520 [inline]
macvlan_start_xmit+0x402/0x77f drivers/net/macvlan.c:559
__netdev_start_xmit include/linux/netdevice.h:4447 [inline]
netdev_start_xmit include/linux/netdevice.h:4461 [inline]
dev_direct_xmit+0x419/0x630 net/core/dev.c:4079
packet_direct_xmit+0x1a9/0x250 net/packet/af_packet.c:240
packet_snd net/packet/af_packet.c:2966 [inline]
packet_sendmsg+0x260d/0x6220 net/packet/af_packet.c:2991
sock_sendmsg_nosec net/socket.c:639 [inline]
sock_sendmsg+0xd7/0x130 net/socket.c:659
__sys_sendto+0x262/0x380 net/socket.c:1985
__do_sys_sendto net/socket.c:1997 [inline]
__se_sys_sendto net/socket.c:1993 [inline]
__x64_sys_sendto+0xe1/0x1a0 net/socket.c:1993
do_syscall_64+0xfa/0x790 arch/x86/entry/common.c:294
entry_SYSCALL_64_after_hwframe+0x49/0xbe
RIP: 0033:0x442639
Code: 18 89 d0 c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 00 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 0f 83 5b 10 fc ff c3 66 2e 0f 1f 84 00 00 00 00
RSP: 002b:00007ffc13549e08 EFLAGS: 00000246 ORIG_RAX: 000000000000002c
RAX: ffffffffffffffda RBX: 0000000000000003 RCX: 0000000000442639
RDX: 000000000000000e RSI: 0000000020000080 RDI: 0000000000000003
RBP: 0000000000000004 R08: 0000000000000000 R09: 0000000000000000
R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000000
R13: 0000000000403bb0 R14: 0000000000000000 R15: 0000000000000000
Allocated by task 9389:
save_stack+0x23/0x90 mm/kasan/common.c:72
set_track mm/kasan/common.c:80 [inline]
__kasan_kmalloc mm/kasan/common.c:513 [inline]
__kasan_kmalloc.constprop.0+0xcf/0xe0 mm/kasan/common.c:486
kasan_kmalloc+0x9/0x10 mm/kasan/common.c:527
__do_kmalloc mm/slab.c:3656 [inline]
__kmalloc+0x163/0x770 mm/slab.c:3665
kmalloc include/linux/slab.h:561 [inline]
tomoyo_realpath_from_path+0xc5/0x660 security/tomoyo/realpath.c:252
tomoyo_get_realpath security/tomoyo/file.c:151 [inline]
tomoyo_path_perm+0x230/0x430 security/tomoyo/file.c:822
tomoyo_inode_getattr+0x1d/0x30 security/tomoyo/tomoyo.c:129
security_inode_getattr+0xf2/0x150 security/security.c:1222
vfs_getattr+0x25/0x70 fs/stat.c:115
vfs_statx_fd+0x71/0xc0 fs/stat.c:145
vfs_fstat include/linux/fs.h:3265 [inline]
__do_sys_newfstat+0x9b/0x120 fs/stat.c:378
__se_sys_newfstat fs/stat.c:375 [inline]
__x64_sys_newfstat+0x54/0x80 fs/stat.c:375
do_syscall_64+0xfa/0x790 arch/x86/entry/common.c:294
entry_SYSCALL_64_after_hwframe+0x49/0xbe
Freed by task 9389:
save_stack+0x23/0x90 mm/kasan/common.c:72
set_track mm/kasan/common.c:80 [inline]
kasan_set_free_info mm/kasan/common.c:335 [inline]
__kasan_slab_free+0x102/0x150 mm/kasan/common.c:474
kasan_slab_free+0xe/0x10 mm/kasan/common.c:483
__cache_free mm/slab.c:3426 [inline]
kfree+0x10a/0x2c0 mm/slab.c:3757
tomoyo_realpath_from_path+0x1a7/0x660 security/tomoyo/realpath.c:289
tomoyo_get_realpath security/tomoyo/file.c:151 [inline]
tomoyo_path_perm+0x230/0x430 security/tomoyo/file.c:822
tomoyo_inode_getattr+0x1d/0x30 security/tomoyo/tomoyo.c:129
security_inode_getattr+0xf2/0x150 security/security.c:1222
vfs_getattr+0x25/0x70 fs/stat.c:115
vfs_statx_fd+0x71/0xc0 fs/stat.c:145
vfs_fstat include/linux/fs.h:3265 [inline]
__do_sys_newfstat+0x9b/0x120 fs/stat.c:378
__se_sys_newfstat fs/stat.c:375 [inline]
__x64_sys_newfstat+0x54/0x80 fs/stat.c:375
do_syscall_64+0xfa/0x790 arch/x86/entry/common.c:294
entry_SYSCALL_64_after_hwframe+0x49/0xbe
The buggy address belongs to the object at ffff8880a4932000
which belongs to the cache kmalloc-4k of size 4096
The buggy address is located 1025 bytes inside of
4096-byte region [ffff8880a4932000, ffff8880a4933000)
The buggy address belongs to the page:
page:ffffea0002924c80 refcount:1 mapcount:0 mapping:ffff8880aa402000 index:0x0 compound_mapcount: 0
raw: 00fffe0000010200 ffffea0002846208 ffffea00028f3888 ffff8880aa402000
raw: 0000000000000000 ffff8880a4932000 0000000100000001 0000000000000000
page dumped because: kasan: bad access detected
Memory state around the buggy address:
ffff8880a4932300: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
ffff8880a4932380: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
>ffff8880a4932400: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
^
ffff8880a4932480: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
ffff8880a4932500: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
Fixes: b863ceb7ddce ("[NET]: Add macvlan driver")
Signed-off-by: Eric Dumazet <[email protected]>
Reported-by: syzbot <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
[bwh: Backported to 3.16: adjust context]
Signed-off-by: Ben Hutchings <[email protected]>
---
drivers/net/macvlan.c | 2 +-
include/linux/if_ether.h | 8 ++++++++
2 files changed, 9 insertions(+), 1 deletion(-)
--- a/drivers/net/macvlan.c
+++ b/drivers/net/macvlan.c
@@ -162,7 +162,7 @@ static void macvlan_broadcast(struct sk_
struct net_device *src,
enum macvlan_mode mode)
{
- const struct ethhdr *eth = eth_hdr(skb);
+ const struct ethhdr *eth = skb_eth_hdr(skb);
const struct macvlan_dev *vlan;
struct sk_buff *nskb;
unsigned int i;
--- a/include/linux/if_ether.h
+++ b/include/linux/if_ether.h
@@ -28,6 +28,14 @@ static inline struct ethhdr *eth_hdr(con
return (struct ethhdr *)skb_mac_header(skb);
}
+/* Prefer this version in TX path, instead of
+ * skb_reset_mac_header() + eth_hdr()
+ */
+static inline struct ethhdr *skb_eth_hdr(const struct sk_buff *skb)
+{
+ return (struct ethhdr *)skb->data;
+}
+
int eth_header_parse(const struct sk_buff *skb, unsigned char *haddr);
extern ssize_t sysfs_format_mac(char *buf, const unsigned char *addr, int len);
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Michael Straube <[email protected]>
commit 58dcc5bf4030cab548d5c98cd4cd3632a5444d5a upstream.
This device was added to the stand-alone driver on github.
Add it to the staging driver as well.
Link: https://github.com/lwfinger/rtl8188eu/commit/b9b537aa25a8
Signed-off-by: Michael Straube <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Greg Kroah-Hartman <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
drivers/staging/rtl8188eu/os_dep/usb_intf.c | 1 +
1 file changed, 1 insertion(+)
--- a/drivers/staging/rtl8188eu/os_dep/usb_intf.c
+++ b/drivers/staging/rtl8188eu/os_dep/usb_intf.c
@@ -61,6 +61,7 @@ static struct usb_device_id rtw_usb_id_t
{USB_DEVICE(0x2001, 0x3311)}, /* DLink GO-USB-N150 REV B1 */
{USB_DEVICE(0x2001, 0x331B)}, /* D-Link DWA-121 rev B1 */
{USB_DEVICE(0x2357, 0x010c)}, /* TP-Link TL-WN722N v2 */
+ {USB_DEVICE(0x2357, 0x0111)}, /* TP-Link TL-WN727N v5.21 */
{USB_DEVICE(0x0df6, 0x0076)}, /* Sitecom N150 v2 */
{USB_DEVICE(USB_VENDER_ID_REALTEK, 0xffef)}, /* Rosewill RNX-N150NUB */
{} /* Terminating entry */
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Eric Dumazet <[email protected]>
commit 5c9934b6767b16ba60be22ec3cbd4379ad64170d upstream.
We got another syzbot report [1] that tells us we must use
write_lock_irq()/write_unlock_irq() to avoid possible deadlock.
[1]
WARNING: inconsistent lock state
5.5.0-rc1-syzkaller #0 Not tainted
--------------------------------
inconsistent {HARDIRQ-ON-W} -> {IN-HARDIRQ-R} usage.
syz-executor826/9605 [HC1[1]:SC0[0]:HE0:SE1] takes:
ffffffff8a128718 (disc_data_lock){+-..}, at: sp_get.isra.0+0x1d/0xf0 drivers/net/ppp/ppp_synctty.c:138
{HARDIRQ-ON-W} state was registered at:
lock_acquire+0x190/0x410 kernel/locking/lockdep.c:4485
__raw_write_lock_bh include/linux/rwlock_api_smp.h:203 [inline]
_raw_write_lock_bh+0x33/0x50 kernel/locking/spinlock.c:319
sixpack_close+0x1d/0x250 drivers/net/hamradio/6pack.c:657
tty_ldisc_close.isra.0+0x119/0x1a0 drivers/tty/tty_ldisc.c:489
tty_set_ldisc+0x230/0x6b0 drivers/tty/tty_ldisc.c:585
tiocsetd drivers/tty/tty_io.c:2337 [inline]
tty_ioctl+0xe8d/0x14f0 drivers/tty/tty_io.c:2597
vfs_ioctl fs/ioctl.c:47 [inline]
file_ioctl fs/ioctl.c:545 [inline]
do_vfs_ioctl+0x977/0x14e0 fs/ioctl.c:732
ksys_ioctl+0xab/0xd0 fs/ioctl.c:749
__do_sys_ioctl fs/ioctl.c:756 [inline]
__se_sys_ioctl fs/ioctl.c:754 [inline]
__x64_sys_ioctl+0x73/0xb0 fs/ioctl.c:754
do_syscall_64+0xfa/0x790 arch/x86/entry/common.c:294
entry_SYSCALL_64_after_hwframe+0x49/0xbe
irq event stamp: 3946
hardirqs last enabled at (3945): [<ffffffff87c86e43>] __raw_spin_unlock_irq include/linux/spinlock_api_smp.h:168 [inline]
hardirqs last enabled at (3945): [<ffffffff87c86e43>] _raw_spin_unlock_irq+0x23/0x80 kernel/locking/spinlock.c:199
hardirqs last disabled at (3946): [<ffffffff8100675f>] trace_hardirqs_off_thunk+0x1a/0x1c arch/x86/entry/thunk_64.S:42
softirqs last enabled at (2658): [<ffffffff86a8b4df>] spin_unlock_bh include/linux/spinlock.h:383 [inline]
softirqs last enabled at (2658): [<ffffffff86a8b4df>] clusterip_netdev_event+0x46f/0x670 net/ipv4/netfilter/ipt_CLUSTERIP.c:222
softirqs last disabled at (2656): [<ffffffff86a8b22b>] spin_lock_bh include/linux/spinlock.h:343 [inline]
softirqs last disabled at (2656): [<ffffffff86a8b22b>] clusterip_netdev_event+0x1bb/0x670 net/ipv4/netfilter/ipt_CLUSTERIP.c:196
other info that might help us debug this:
Possible unsafe locking scenario:
CPU0
----
lock(disc_data_lock);
<Interrupt>
lock(disc_data_lock);
*** DEADLOCK ***
5 locks held by syz-executor826/9605:
#0: ffff8880a905e198 (&tty->legacy_mutex){+.+.}, at: tty_lock+0xc7/0x130 drivers/tty/tty_mutex.c:19
#1: ffffffff899a56c0 (rcu_read_lock){....}, at: mutex_spin_on_owner+0x0/0x330 kernel/locking/mutex.c:413
#2: ffff8880a496a2b0 (&(&i->lock)->rlock){-.-.}, at: spin_lock include/linux/spinlock.h:338 [inline]
#2: ffff8880a496a2b0 (&(&i->lock)->rlock){-.-.}, at: serial8250_interrupt+0x2d/0x1a0 drivers/tty/serial/8250/8250_core.c:116
#3: ffffffff8c104048 (&port_lock_key){-.-.}, at: serial8250_handle_irq.part.0+0x24/0x330 drivers/tty/serial/8250/8250_port.c:1823
#4: ffff8880a905e090 (&tty->ldisc_sem){++++}, at: tty_ldisc_ref+0x22/0x90 drivers/tty/tty_ldisc.c:288
stack backtrace:
CPU: 1 PID: 9605 Comm: syz-executor826 Not tainted 5.5.0-rc1-syzkaller #0
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011
Call Trace:
<IRQ>
__dump_stack lib/dump_stack.c:77 [inline]
dump_stack+0x197/0x210 lib/dump_stack.c:118
print_usage_bug.cold+0x327/0x378 kernel/locking/lockdep.c:3101
valid_state kernel/locking/lockdep.c:3112 [inline]
mark_lock_irq kernel/locking/lockdep.c:3309 [inline]
mark_lock+0xbb4/0x1220 kernel/locking/lockdep.c:3666
mark_usage kernel/locking/lockdep.c:3554 [inline]
__lock_acquire+0x1e55/0x4a00 kernel/locking/lockdep.c:3909
lock_acquire+0x190/0x410 kernel/locking/lockdep.c:4485
__raw_read_lock include/linux/rwlock_api_smp.h:149 [inline]
_raw_read_lock+0x32/0x50 kernel/locking/spinlock.c:223
sp_get.isra.0+0x1d/0xf0 drivers/net/ppp/ppp_synctty.c:138
sixpack_write_wakeup+0x25/0x340 drivers/net/hamradio/6pack.c:402
tty_wakeup+0xe9/0x120 drivers/tty/tty_io.c:536
tty_port_default_wakeup+0x2b/0x40 drivers/tty/tty_port.c:50
tty_port_tty_wakeup+0x57/0x70 drivers/tty/tty_port.c:387
uart_write_wakeup+0x46/0x70 drivers/tty/serial/serial_core.c:104
serial8250_tx_chars+0x495/0xaf0 drivers/tty/serial/8250/8250_port.c:1761
serial8250_handle_irq.part.0+0x2a2/0x330 drivers/tty/serial/8250/8250_port.c:1834
serial8250_handle_irq drivers/tty/serial/8250/8250_port.c:1820 [inline]
serial8250_default_handle_irq+0xc0/0x150 drivers/tty/serial/8250/8250_port.c:1850
serial8250_interrupt+0xf1/0x1a0 drivers/tty/serial/8250/8250_core.c:126
__handle_irq_event_percpu+0x15d/0x970 kernel/irq/handle.c:149
handle_irq_event_percpu+0x74/0x160 kernel/irq/handle.c:189
handle_irq_event+0xa7/0x134 kernel/irq/handle.c:206
handle_edge_irq+0x25e/0x8d0 kernel/irq/chip.c:830
generic_handle_irq_desc include/linux/irqdesc.h:156 [inline]
do_IRQ+0xde/0x280 arch/x86/kernel/irq.c:250
common_interrupt+0xf/0xf arch/x86/entry/entry_64.S:607
</IRQ>
RIP: 0010:cpu_relax arch/x86/include/asm/processor.h:685 [inline]
RIP: 0010:mutex_spin_on_owner+0x247/0x330 kernel/locking/mutex.c:579
Code: c3 be 08 00 00 00 4c 89 e7 e8 e5 06 59 00 4c 89 e0 48 c1 e8 03 42 80 3c 38 00 0f 85 e1 00 00 00 49 8b 04 24 a8 01 75 96 f3 90 <e9> 2f fe ff ff 0f 0b e8 0d 19 09 00 84 c0 0f 85 ff fd ff ff 48 c7
RSP: 0018:ffffc90001eafa20 EFLAGS: 00000246 ORIG_RAX: ffffffffffffffd7
RAX: 0000000000000000 RBX: ffff88809fd9e0c0 RCX: 1ffffffff13266dd
RDX: 0000000000000000 RSI: 0000000000000008 RDI: 0000000000000000
RBP: ffffc90001eafa60 R08: 1ffff11013d22898 R09: ffffed1013d22899
R10: ffffed1013d22898 R11: ffff88809e9144c7 R12: ffff8880a905e138
R13: ffff88809e9144c0 R14: 0000000000000000 R15: dffffc0000000000
mutex_optimistic_spin kernel/locking/mutex.c:673 [inline]
__mutex_lock_common kernel/locking/mutex.c:962 [inline]
__mutex_lock+0x32b/0x13c0 kernel/locking/mutex.c:1106
mutex_lock_nested+0x16/0x20 kernel/locking/mutex.c:1121
tty_lock+0xc7/0x130 drivers/tty/tty_mutex.c:19
tty_release+0xb5/0xe90 drivers/tty/tty_io.c:1665
__fput+0x2ff/0x890 fs/file_table.c:280
____fput+0x16/0x20 fs/file_table.c:313
task_work_run+0x145/0x1c0 kernel/task_work.c:113
exit_task_work include/linux/task_work.h:22 [inline]
do_exit+0x8e7/0x2ef0 kernel/exit.c:797
do_group_exit+0x135/0x360 kernel/exit.c:895
__do_sys_exit_group kernel/exit.c:906 [inline]
__se_sys_exit_group kernel/exit.c:904 [inline]
__x64_sys_exit_group+0x44/0x50 kernel/exit.c:904
do_syscall_64+0xfa/0x790 arch/x86/entry/common.c:294
entry_SYSCALL_64_after_hwframe+0x49/0xbe
RIP: 0033:0x43fef8
Code: Bad RIP value.
RSP: 002b:00007ffdb07d2338 EFLAGS: 00000246 ORIG_RAX: 00000000000000e7
RAX: ffffffffffffffda RBX: 0000000000000000 RCX: 000000000043fef8
RDX: 0000000000000000 RSI: 000000000000003c RDI: 0000000000000000
RBP: 00000000004bf730 R08: 00000000000000e7 R09: ffffffffffffffd0
R10: 00000000004002c8 R11: 0000000000000246 R12: 0000000000000001
R13: 00000000006d1180 R14: 0000000000000000 R15: 0000000000000000
Fixes: 6e4e2f811bad ("6pack,mkiss: fix lock inconsistency")
Signed-off-by: Eric Dumazet <[email protected]>
Reported-by: syzbot <[email protected]>
Cc: Arnd Bergmann <[email protected]>
Signed-off-by: Jakub Kicinski <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
drivers/net/hamradio/6pack.c | 4 ++--
drivers/net/hamradio/mkiss.c | 4 ++--
2 files changed, 4 insertions(+), 4 deletions(-)
--- a/drivers/net/hamradio/6pack.c
+++ b/drivers/net/hamradio/6pack.c
@@ -685,10 +685,10 @@ static void sixpack_close(struct tty_str
{
struct sixpack *sp;
- write_lock_bh(&disc_data_lock);
+ write_lock_irq(&disc_data_lock);
sp = tty->disc_data;
tty->disc_data = NULL;
- write_unlock_bh(&disc_data_lock);
+ write_unlock_irq(&disc_data_lock);
if (!sp)
return;
--- a/drivers/net/hamradio/mkiss.c
+++ b/drivers/net/hamradio/mkiss.c
@@ -811,10 +811,10 @@ static void mkiss_close(struct tty_struc
{
struct mkiss *ax;
- write_lock_bh(&disc_data_lock);
+ write_lock_irq(&disc_data_lock);
ax = tty->disc_data;
tty->disc_data = NULL;
- write_unlock_bh(&disc_data_lock);
+ write_unlock_irq(&disc_data_lock);
if (!ax)
return;
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Johan Hovold <[email protected]>
commit 1568c58d11a7c851bd09341aeefd6a1c308ac40d upstream.
The driver receives the active port number from the device, but never
made sure that the port number was valid. This could lead to a
NULL-pointer dereference or memory corruption in case a device sends
data for an invalid port.
Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Reviewed-by: Greg Kroah-Hartman <[email protected]>
Signed-off-by: Johan Hovold <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
drivers/usb/serial/io_edgeport.c | 12 +++++++-----
1 file changed, 7 insertions(+), 5 deletions(-)
--- a/drivers/usb/serial/io_edgeport.c
+++ b/drivers/usb/serial/io_edgeport.c
@@ -1666,7 +1666,8 @@ static void edge_break(struct tty_struct
static void process_rcvd_data(struct edgeport_serial *edge_serial,
unsigned char *buffer, __u16 bufferLength)
{
- struct device *dev = &edge_serial->serial->dev->dev;
+ struct usb_serial *serial = edge_serial->serial;
+ struct device *dev = &serial->dev->dev;
struct usb_serial_port *port;
struct edgeport_port *edge_port;
__u16 lastBufferLength;
@@ -1771,9 +1772,8 @@ static void process_rcvd_data(struct edg
/* spit this data back into the tty driver if this
port is open */
- if (rxLen) {
- port = edge_serial->serial->port[
- edge_serial->rxPort];
+ if (rxLen && edge_serial->rxPort < serial->num_ports) {
+ port = serial->port[edge_serial->rxPort];
edge_port = usb_get_serial_port_data(port);
if (edge_port && edge_port->open) {
dev_dbg(dev, "%s - Sending %d bytes to TTY for port %d\n",
@@ -1783,8 +1783,8 @@ static void process_rcvd_data(struct edg
rxLen);
edge_port->port->icount.rx += rxLen;
}
- buffer += rxLen;
}
+ buffer += rxLen;
break;
case EXPECT_HDR3: /* Expect 3rd byte of status header */
@@ -1819,6 +1819,8 @@ static void process_rcvd_status(struct e
__u8 code = edge_serial->rxStatusCode;
/* switch the port pointer to the one being currently talked about */
+ if (edge_serial->rxPort >= edge_serial->serial->num_ports)
+ return;
port = edge_serial->serial->port[edge_serial->rxPort];
edge_port = usb_get_serial_port_data(port);
if (edge_port == NULL) {
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Josef Bacik <[email protected]>
commit b35cf1f0bf1f2b0b193093338414b9bd63b29015 upstream.
The fstest btrfs/154 reports
[ 8675.381709] BTRFS: Transaction aborted (error -28)
[ 8675.383302] WARNING: CPU: 1 PID: 31900 at fs/btrfs/block-group.c:2038 btrfs_create_pending_block_groups+0x1e0/0x1f0 [btrfs]
[ 8675.390925] CPU: 1 PID: 31900 Comm: btrfs Not tainted 5.5.0-rc6-default+ #935
[ 8675.392780] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.12.0-59-gc9ba527-rebuilt.opensuse.org 04/01/2014
[ 8675.395452] RIP: 0010:btrfs_create_pending_block_groups+0x1e0/0x1f0 [btrfs]
[ 8675.402672] RSP: 0018:ffffb2090888fb00 EFLAGS: 00010286
[ 8675.404413] RAX: 0000000000000000 RBX: ffff92026dfa91c8 RCX: 0000000000000001
[ 8675.406609] RDX: 0000000000000000 RSI: ffffffff8e100899 RDI: ffffffff8e100971
[ 8675.408775] RBP: ffff920247c61660 R08: 0000000000000000 R09: 0000000000000000
[ 8675.410978] R10: 0000000000000000 R11: 0000000000000000 R12: 00000000ffffffe4
[ 8675.412647] R13: ffff92026db74000 R14: ffff920247c616b8 R15: ffff92026dfbc000
[ 8675.413994] FS: 00007fd5e57248c0(0000) GS:ffff92027d800000(0000) knlGS:0000000000000000
[ 8675.416146] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 8675.417833] CR2: 0000564aa51682d8 CR3: 000000006dcbc004 CR4: 0000000000160ee0
[ 8675.419801] Call Trace:
[ 8675.420742] btrfs_start_dirty_block_groups+0x355/0x480 [btrfs]
[ 8675.422600] btrfs_commit_transaction+0xc8/0xaf0 [btrfs]
[ 8675.424335] reset_balance_state+0x14a/0x190 [btrfs]
[ 8675.425824] btrfs_balance.cold+0xe7/0x154 [btrfs]
[ 8675.427313] ? kmem_cache_alloc_trace+0x235/0x2c0
[ 8675.428663] btrfs_ioctl_balance+0x298/0x350 [btrfs]
[ 8675.430285] btrfs_ioctl+0x466/0x2550 [btrfs]
[ 8675.431788] ? mem_cgroup_charge_statistics+0x51/0xf0
[ 8675.433487] ? mem_cgroup_commit_charge+0x56/0x400
[ 8675.435122] ? do_raw_spin_unlock+0x4b/0xc0
[ 8675.436618] ? _raw_spin_unlock+0x1f/0x30
[ 8675.438093] ? __handle_mm_fault+0x499/0x740
[ 8675.439619] ? do_vfs_ioctl+0x56e/0x770
[ 8675.441034] do_vfs_ioctl+0x56e/0x770
[ 8675.442411] ksys_ioctl+0x3a/0x70
[ 8675.443718] ? trace_hardirqs_off_thunk+0x1a/0x1c
[ 8675.445333] __x64_sys_ioctl+0x16/0x20
[ 8675.446705] do_syscall_64+0x50/0x210
[ 8675.448059] entry_SYSCALL_64_after_hwframe+0x49/0xbe
[ 8675.479187] BTRFS: error (device vdb) in btrfs_create_pending_block_groups:2038: errno=-28 No space left
We now use btrfs_can_overcommit() to see if we can flip a block group
read only. Before this would fail because we weren't taking into
account the usable un-allocated space for allocating chunks. With my
patches we were allowed to do the balance, which is technically correct.
The test is trying to start balance on degraded mount. So now we're
trying to allocate a chunk and cannot because we want to allocate a
RAID1 chunk, but there's only 1 device that's available for usage. This
results in an ENOSPC.
But we shouldn't even be making it this far, we don't have enough
devices to restripe. The problem is we're using btrfs_num_devices(),
that also includes missing devices. That's not actually what we want, we
need to use rw_devices.
The chunk_mutex is not needed here, rw_devices changes only in device
add, remove or replace, all are excluded by EXCL_OP mechanism.
Fixes: e4d8ec0f65b9 ("Btrfs: implement online profile changing")
Signed-off-by: Josef Bacik <[email protected]>
Reviewed-by: David Sterba <[email protected]>
[ add stacktrace, update changelog, drop chunk_mutex ]
Signed-off-by: David Sterba <[email protected]>
[bwh: Backported to 3.16: adjust context]
Signed-off-by: Ben Hutchings <[email protected]>
---
fs/btrfs/volumes.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -3248,7 +3248,11 @@ int btrfs_balance(struct btrfs_balance_c
}
}
- num_devices = fs_info->fs_devices->num_devices;
+ /*
+ * rw_devices will not change at the moment, device add/delete/replace
+ * are excluded by EXCL_OP
+ */
+ num_devices = fs_info->fs_devices->rw_devices;
btrfs_dev_replace_lock(&fs_info->dev_replace);
if (btrfs_dev_replace_is_ongoing(&fs_info->dev_replace)) {
BUG_ON(num_devices < 1);
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Jan Kara <[email protected]>
commit 17048e8a083fec7ad841d88ef0812707fbc7e39f upstream.
Currently ext4_alloc_file_blocks() was handling protection against
unlocked DIO. However we now need to sometimes call it under i_mmap_sem
and sometimes not and DIO protection ranks above it (although strictly
speaking this cannot currently create any deadlocks). Also
ext4_zero_range() was actually getting & releasing unlocked DIO
protection twice in some cases. Luckily it didn't introduce any real bug
but it was a land mine waiting to be stepped on. So move DIO protection
out from ext4_alloc_file_blocks() into the two callsites.
Signed-off-by: Jan Kara <[email protected]>
Signed-off-by: Theodore Ts'o <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
fs/ext4/extents.c | 21 ++++++++++-----------
1 file changed, 10 insertions(+), 11 deletions(-)
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -4707,10 +4707,6 @@ static int ext4_alloc_file_blocks(struct
if (len <= EXT_UNWRITTEN_MAX_LEN)
flags |= EXT4_GET_BLOCKS_NO_NORMALIZE;
- /* Wait all existing dio workers, newcomers will block on i_mutex */
- ext4_inode_block_unlocked_dio(inode);
- inode_dio_wait(inode);
-
/*
* credits to insert 1 extent into extent tree
*/
@@ -4760,8 +4756,6 @@ retry:
goto retry;
}
- ext4_inode_resume_unlocked_dio(inode);
-
return ret > 0 ? ret2 : ret;
}
@@ -4836,6 +4830,10 @@ static long ext4_zero_range(struct file
if (mode & FALLOC_FL_KEEP_SIZE)
flags |= EXT4_GET_BLOCKS_KEEP_SIZE;
+ /* Wait all existing dio workers, newcomers will block on i_mutex */
+ ext4_inode_block_unlocked_dio(inode);
+ inode_dio_wait(inode);
+
/* Preallocate the range including the unaligned edges */
if (partial_begin || partial_end) {
ret = ext4_alloc_file_blocks(file,
@@ -4844,7 +4842,7 @@ static long ext4_zero_range(struct file
round_down(offset, 1 << blkbits)) >> blkbits,
new_size, flags, mode);
if (ret)
- goto out_mutex;
+ goto out_dio;
}
@@ -4853,10 +4851,6 @@ static long ext4_zero_range(struct file
flags |= (EXT4_GET_BLOCKS_CONVERT_UNWRITTEN |
EXT4_EX_NOCACHE);
- /* Wait all existing dio workers, newcomers will block on i_mutex */
- ext4_inode_block_unlocked_dio(inode);
- inode_dio_wait(inode);
-
/*
* Prevent page faults from reinstantiating pages we have
* released from page cache.
@@ -4985,8 +4979,13 @@ long ext4_fallocate(struct file *file, i
goto out;
}
+ /* Wait all existing dio workers, newcomers will block on i_mutex */
+ ext4_inode_block_unlocked_dio(inode);
+ inode_dio_wait(inode);
+
ret = ext4_alloc_file_blocks(file, lblk, max_blocks, new_size,
flags, mode);
+ ext4_inode_resume_unlocked_dio(inode);
if (ret)
goto out;
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Johan Hovold <[email protected]>
commit 2f361cd9474ab2c4ab9ac8db20faf81e66c6279b upstream.
Make sure to always use the descriptors of the current alternate setting
to avoid future issues when accessing fields that may differ between
settings.
Signed-off-by: Johan Hovold <[email protected]>
Fixes: d08e973a77d1 ("can: gs_usb: Added support for the GS_USB CAN devices")
Signed-off-by: Marc Kleine-Budde <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
drivers/net/can/usb/gs_usb.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
--- a/drivers/net/can/usb/gs_usb.c
+++ b/drivers/net/can/usb/gs_usb.c
@@ -846,7 +846,7 @@ static int gs_usb_probe(struct usb_inter
GS_USB_BREQ_HOST_FORMAT,
USB_DIR_OUT|USB_TYPE_VENDOR|USB_RECIP_INTERFACE,
1,
- intf->altsetting[0].desc.bInterfaceNumber,
+ intf->cur_altsetting->desc.bInterfaceNumber,
hconf,
sizeof(*hconf),
1000);
@@ -869,7 +869,7 @@ static int gs_usb_probe(struct usb_inter
GS_USB_BREQ_DEVICE_CONFIG,
USB_DIR_IN|USB_TYPE_VENDOR|USB_RECIP_INTERFACE,
1,
- intf->altsetting[0].desc.bInterfaceNumber,
+ intf->cur_altsetting->desc.bInterfaceNumber,
dconf,
sizeof(*dconf),
1000);
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Lu Fengqi <[email protected]>
commit 5b7d687ad5913a56b6a8788435d7a53990b4176d upstream.
Although it is safe to call this on already released paths with no locks
held or extent buffers, removing the redundant btrfs_release_path is
reasonable.
Signed-off-by: Lu Fengqi <[email protected]>
Reviewed-by: David Sterba <[email protected]>
Signed-off-by: David Sterba <[email protected]>
[bwh: Backported to 3.16 as dependency of commit d49d3287e74f
"btrfs: fix invalid removal of root ref"]
Signed-off-by: Ben Hutchings <[email protected]>
---
fs/btrfs/inode.c | 1 -
1 file changed, 1 deletion(-)
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -4031,7 +4031,6 @@ int btrfs_unlink_subvol(struct btrfs_tra
leaf = path->nodes[0];
btrfs_item_key_to_cpu(leaf, &key, path->slots[0]);
- btrfs_release_path(path);
index = key.offset;
}
btrfs_release_path(path);
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Moni Shoua <[email protected]>
commit 4bf9715f184969dc703bde7be94919995024a6a9 upstream.
When device is being removed (e.g during VPI port link type change
from ETH to IB), tasks for gid table changes should not be executed.
Flush the current queue of tasks and block further tasks from entering the queue.
Signed-off-by: Moni Shoua <[email protected]>
Signed-off-by: Or Gerlitz <[email protected]>
Signed-off-by: Roland Dreier <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
drivers/infiniband/hw/mlx4/main.c | 9 +++++++++
1 file changed, 9 insertions(+)
--- a/drivers/infiniband/hw/mlx4/main.c
+++ b/drivers/infiniband/hw/mlx4/main.c
@@ -1395,6 +1395,9 @@ static void update_gids_task(struct work
int err;
struct mlx4_dev *dev = gw->dev->dev;
+ if (!gw->dev->ib_active)
+ return;
+
mailbox = mlx4_alloc_cmd_mailbox(dev);
if (IS_ERR(mailbox)) {
pr_warn("update gid table failed %ld\n", PTR_ERR(mailbox));
@@ -1425,6 +1428,9 @@ static void reset_gids_task(struct work_
int err;
struct mlx4_dev *dev = gw->dev->dev;
+ if (!gw->dev->ib_active)
+ return;
+
mailbox = mlx4_alloc_cmd_mailbox(dev);
if (IS_ERR(mailbox)) {
pr_warn("reset gid table failed\n");
@@ -2363,6 +2369,9 @@ static void mlx4_ib_remove(struct mlx4_d
struct mlx4_ib_dev *ibdev = ibdev_ptr;
int p;
+ ibdev->ib_active = false;
+ flush_workqueue(wq);
+
mlx4_ib_close_sriov(ibdev);
mlx4_ib_mad_cleanup(ibdev);
ib_unregister_device(&ibdev->ib_dev);
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Felipe Balbi <[email protected]>
commit 7ae622c978db6b2e28b4fced6ecd2a174492059d upstream.
This patch simply adds a new PCI Device ID
Signed-off-by: Felipe Balbi <[email protected]>
[bwh: Backported to 3.16:
- No properties support
- Adjust context, indentation]
Signed-off-by: Ben Hutchings <[email protected]>
---
drivers/usb/dwc3/dwc3-pci.c | 4 ++++
1 file changed, 4 insertions(+)
--- a/drivers/usb/dwc3/dwc3-pci.c
+++ b/drivers/usb/dwc3/dwc3-pci.c
@@ -37,6 +37,7 @@
#define PCI_DEVICE_ID_INTEL_BXT_M 0x1aaa
#define PCI_DEVICE_ID_INTEL_APL 0x5aaa
#define PCI_DEVICE_ID_INTEL_KBP 0xa2b0
+#define PCI_DEVICE_ID_INTEL_CMLH 0x02ee
#define PCI_DEVICE_ID_INTEL_GLK 0x31aa
#define PCI_DEVICE_ID_INTEL_CNPLP 0x9dee
#define PCI_DEVICE_ID_INTEL_CNPH 0xa36e
@@ -197,6 +198,7 @@ static const struct pci_device_id dwc3_p
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BSW), },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BYT), },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_MRFLD), },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_CMLH), },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SPTLP), },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SPTH), },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BXT), },
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Russell King <[email protected]>
commit d2ed49cf6c13e379c5819aa5ac20e1f9674ebc89 upstream.
When a PHY is probed, if the top bit is set, we end up requesting a
module with the string "mdio:-10101110000000100101000101010001" -
the top bit is printed to a signed -1 value. This leads to the module
not being loaded.
Fix the module format string and the macro generating the values for
it to ensure that we only print unsigned types and the top bit is
always 0/1. We correctly end up with
"mdio:10101110000000100101000101010001".
Fixes: 8626d3b43280 ("phylib: Support phy module autoloading")
Reviewed-by: Andrew Lunn <[email protected]>
Signed-off-by: Russell King <[email protected]>
Reviewed-by: Florian Fainelli <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
include/linux/mod_devicetable.h | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
--- a/include/linux/mod_devicetable.h
+++ b/include/linux/mod_devicetable.h
@@ -497,9 +497,9 @@ struct platform_device_id {
#define MDIO_MODULE_PREFIX "mdio:"
-#define MDIO_ID_FMT "%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d"
+#define MDIO_ID_FMT "%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u"
#define MDIO_ID_ARGS(_id) \
- (_id)>>31, ((_id)>>30) & 1, ((_id)>>29) & 1, ((_id)>>28) & 1, \
+ ((_id)>>31) & 1, ((_id)>>30) & 1, ((_id)>>29) & 1, ((_id)>>28) & 1, \
((_id)>>27) & 1, ((_id)>>26) & 1, ((_id)>>25) & 1, ((_id)>>24) & 1, \
((_id)>>23) & 1, ((_id)>>22) & 1, ((_id)>>21) & 1, ((_id)>>20) & 1, \
((_id)>>19) & 1, ((_id)>>18) & 1, ((_id)>>17) & 1, ((_id)>>16) & 1, \
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Josef Bacik <[email protected]>
commit 9bc574de590510eff899c3ca8dbaf013566b5efe upstream.
My fsstress modifications coupled with generic/475 uncovered a failure
to mount and replay the log if we hit a orphaned root. We do not want
to replay the log for an orphan root, but it's completely legitimate to
have an orphaned root with a log attached. Fix this by simply skipping
replaying the log. We still need to pin it's root node so that we do
not overwrite it while replaying other logs, as we re-read the log root
at every stage of the replay.
Reviewed-by: Filipe Manana <[email protected]>
Signed-off-by: Josef Bacik <[email protected]>
Signed-off-by: David Sterba <[email protected]>
[bwh: Backported to 3.16:
- Pass fs_info->extent_root, instead of fs_info, as first argument to
btrfs_pin_extent_for_log_replay()
- Adjust context]
Signed-off-by: Ben Hutchings <[email protected]>
---
--- a/fs/btrfs/tree-log.c
+++ b/fs/btrfs/tree-log.c
@@ -4583,9 +4583,29 @@ again:
wc.replay_dest = btrfs_read_fs_root_no_name(fs_info, &tmp_key);
if (IS_ERR(wc.replay_dest)) {
ret = PTR_ERR(wc.replay_dest);
+
+ /*
+ * We didn't find the subvol, likely because it was
+ * deleted. This is ok, simply skip this log and go to
+ * the next one.
+ *
+ * We need to exclude the root because we can't have
+ * other log replays overwriting this log as we'll read
+ * it back in a few more times. This will keep our
+ * block from being modified, and we'll just bail for
+ * each subsequent pass.
+ */
+ if (ret == -ENOENT)
+ ret = btrfs_pin_extent_for_log_replay(
+ fs_info->extent_root,
+ log->node->start,
+ log->node->len);
free_extent_buffer(log->node);
free_extent_buffer(log->commit_root);
kfree(log);
+
+ if (!ret)
+ goto next;
btrfs_error(fs_info, ret, "Couldn't read target root "
"for tree log recovery.");
goto error;
@@ -4600,7 +4620,6 @@ again:
path);
}
- key.offset = found_key.offset - 1;
wc.replay_dest->log_root = NULL;
free_extent_buffer(log->node);
free_extent_buffer(log->commit_root);
@@ -4608,9 +4627,10 @@ again:
if (ret)
goto error;
-
+next:
if (found_key.offset == 0)
break;
+ key.offset = found_key.offset - 1;
}
btrfs_release_path(path);
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Josef Bacik <[email protected]>
commit c7e54b5102bf3614cadb9ca32d7be73bad6cecf0 upstream.
We can just abort the transaction here, and in fact do that for every
other failure in this function except these two cases.
Reviewed-by: Filipe Manana <[email protected]>
Reviewed-by: Johannes Thumshirn <[email protected]>
Signed-off-by: Josef Bacik <[email protected]>
Reviewed-by: David Sterba <[email protected]>
Signed-off-by: David Sterba <[email protected]>
[bwh: Backported to 3.16:
- Add root as second argument to btrfs_abort_transaction()
- Adjust context]
Signed-off-by: Ben Hutchings <[email protected]>
---
fs/btrfs/ioctl.c | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
--- a/fs/btrfs/ioctl.c
+++ b/fs/btrfs/ioctl.c
@@ -580,12 +580,18 @@ static noinline int create_subvol(struct
btrfs_i_size_write(dir, dir->i_size + namelen * 2);
ret = btrfs_update_inode(trans, root, dir);
- BUG_ON(ret);
+ if (ret) {
+ btrfs_abort_transaction(trans, root, ret);
+ goto fail;
+ }
ret = btrfs_add_root_ref(trans, root->fs_info->tree_root,
objectid, root->root_key.objectid,
btrfs_ino(dir), index, name, namelen);
- BUG_ON(ret);
+ if (ret) {
+ btrfs_abort_transaction(trans, root, ret);
+ goto fail;
+ }
ret = btrfs_uuid_tree_add(trans, root->fs_info->uuid_root,
root_item.uuid, BTRFS_UUID_KEY_SUBVOL,
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Shengjiu Wang <[email protected]>
commit 556672d75ff486e0b6786056da624131679e0576 upstream.
According to user manual, it is required that FLL_LAMBDA > 0
in all cases (Integer and Franctional modes).
Fixes: 9a76f1ff6e29 ("ASoC: Add initial WM8962 CODEC driver")
Signed-off-by: Shengjiu Wang <[email protected]>
Acked-by: Charles Keepax <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Mark Brown <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
sound/soc/codecs/wm8962.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
--- a/sound/soc/codecs/wm8962.c
+++ b/sound/soc/codecs/wm8962.c
@@ -2795,7 +2795,7 @@ static int fll_factors(struct _fll_div *
if (target % Fref == 0) {
fll_div->theta = 0;
- fll_div->lambda = 0;
+ fll_div->lambda = 1;
} else {
gcd_fll = gcd(target, fratio * Fref);
@@ -2865,7 +2865,7 @@ static int wm8962_set_fll(struct snd_soc
return -EINVAL;
}
- if (fll_div.theta || fll_div.lambda)
+ if (fll_div.theta)
fll1 |= WM8962_FLL_FRAC;
/* Stop the FLL while we reconfigure */
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Josef Bacik <[email protected]>
commit ca1aa2818a53875cfdd175fb5e9a2984e997cce9 upstream.
If we fail to read the fs root corresponding with a reloc root we'll
just break out and free the reloc roots. But we remove our current
reloc_root from this list higher up, which means we'll leak this
reloc_root. Fix this by adding ourselves back to the reloc_roots list
so we are properly cleaned up.
Reviewed-by: Filipe Manana <[email protected]>
Reviewed-by: Johannes Thumshirn <[email protected]>
Signed-off-by: Josef Bacik <[email protected]>
Reviewed-by: David Sterba <[email protected]>
Signed-off-by: David Sterba <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
fs/btrfs/relocation.c | 1 +
1 file changed, 1 insertion(+)
--- a/fs/btrfs/relocation.c
+++ b/fs/btrfs/relocation.c
@@ -4449,6 +4449,7 @@ int btrfs_recover_relocation(struct btrf
reloc_root->root_key.offset);
if (IS_ERR(fs_root)) {
err = PTR_ERR(fs_root);
+ list_add_tail(&reloc_root->root_list, &reloc_roots);
goto out_free;
}
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Jim Mattson <[email protected]>
commit 396d2e878f92ec108e4293f1c77ea3bc90b414ff upstream.
The host reports support for the synthetic feature X86_FEATURE_SSBD
when any of the three following hardware features are set:
CPUID.(EAX=7,ECX=0):EDX.SSBD[bit 31]
CPUID.80000008H:EBX.AMD_SSBD[bit 24]
CPUID.80000008H:EBX.VIRT_SSBD[bit 25]
Either of the first two hardware features implies the existence of the
IA32_SPEC_CTRL MSR, but CPUID.80000008H:EBX.VIRT_SSBD[bit 25] does
not. Therefore, CPUID.(EAX=7,ECX=0):EDX.SSBD[bit 31] should only be
set in the guest if CPUID.(EAX=7,ECX=0):EDX.SSBD[bit 31] or
CPUID.80000008H:EBX.AMD_SSBD[bit 24] is set on the host.
Fixes: 0c54914d0c52a ("KVM: x86: use Intel speculation bugs and features as derived in generic x86 code")
Signed-off-by: Jim Mattson <[email protected]>
Reviewed-by: Jacob Xu <[email protected]>
Reviewed-by: Peter Shier <[email protected]>
Cc: Paolo Bonzini <[email protected]>
Reported-by: Eric Biggers <[email protected]>
Signed-off-by: Paolo Bonzini <[email protected]>
[bwh: Backported to 3.16: adjust indentation]
Signed-off-by: Ben Hutchings <[email protected]>
---
arch/x86/kvm/cpuid.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
--- a/arch/x86/kvm/cpuid.c
+++ b/arch/x86/kvm/cpuid.c
@@ -400,7 +400,8 @@ static inline int __do_cpuid_ent(struct
entry->edx |= F(SPEC_CTRL);
if (boot_cpu_has(X86_FEATURE_STIBP))
entry->edx |= F(INTEL_STIBP);
- if (boot_cpu_has(X86_FEATURE_SSBD))
+ if (boot_cpu_has(X86_FEATURE_SPEC_CTRL_SSBD) ||
+ boot_cpu_has(X86_FEATURE_AMD_SSBD))
entry->edx |= F(SPEC_CTRL_SSBD);
/*
* We emulate ARCH_CAPABILITIES in software even
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Dmitry Torokhov <[email protected]>
commit 4f3882177240a1f55e45a3d241d3121341bead78 upstream.
We should not be leaving half-mapped usages with potentially invalid
keycodes, as that may confuse hidinput_find_key() when the key is located
by index, which may end up feeding way too large keycode into the VT
keyboard handler and cause OOB write there:
BUG: KASAN: global-out-of-bounds in clear_bit include/asm-generic/bitops-instrumented.h:56 [inline]
BUG: KASAN: global-out-of-bounds in kbd_keycode drivers/tty/vt/keyboard.c:1411 [inline]
BUG: KASAN: global-out-of-bounds in kbd_event+0xe6b/0x3790 drivers/tty/vt/keyboard.c:1495
Write of size 8 at addr ffffffff89a1b2d8 by task syz-executor108/1722
...
kbd_keycode drivers/tty/vt/keyboard.c:1411 [inline]
kbd_event+0xe6b/0x3790 drivers/tty/vt/keyboard.c:1495
input_to_handler+0x3b6/0x4c0 drivers/input/input.c:118
input_pass_values.part.0+0x2e3/0x720 drivers/input/input.c:145
input_pass_values drivers/input/input.c:949 [inline]
input_set_keycode+0x290/0x320 drivers/input/input.c:954
evdev_handle_set_keycode_v2+0xc4/0x120 drivers/input/evdev.c:882
evdev_do_ioctl drivers/input/evdev.c:1150 [inline]
Reported-by: [email protected]
Signed-off-by: Dmitry Torokhov <[email protected]>
Tested-by: Benjamin Tissoires <[email protected]>
Signed-off-by: Jiri Kosina <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
drivers/hid/hid-input.c | 16 ++++++++++++----
1 file changed, 12 insertions(+), 4 deletions(-)
--- a/drivers/hid/hid-input.c
+++ b/drivers/hid/hid-input.c
@@ -947,9 +947,15 @@ static void hidinput_configure_usage(str
}
mapped:
- if (device->driver->input_mapped && device->driver->input_mapped(device,
- hidinput, field, usage, &bit, &max) < 0)
- goto ignore;
+ if (device->driver->input_mapped &&
+ device->driver->input_mapped(device, hidinput, field, usage,
+ &bit, &max) < 0) {
+ /*
+ * The driver indicated that no further generic handling
+ * of the usage is desired.
+ */
+ return;
+ }
set_bit(usage->type, input->evbit);
@@ -1008,9 +1014,11 @@ mapped:
set_bit(MSC_SCAN, input->mscbit);
}
-ignore:
return;
+ignore:
+ usage->type = 0;
+ usage->code = 0;
}
void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct hid_usage *usage, __s32 value)
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Felipe Balbi <[email protected]>
commit dbb0569de852fb4576d6f62078d515f989a181ca upstream.
This patch simply adds a new PCI Device ID
Signed-off-by: Felipe Balbi <[email protected]>
[bwh: Backported to 3.16:
- No properties support
- Adjust context, indentation]
Signed-off-by: Ben Hutchings <[email protected]>
---
drivers/usb/dwc3/dwc3-pci.c | 4 ++++
1 file changed, 4 insertions(+)
--- a/drivers/usb/dwc3/dwc3-pci.c
+++ b/drivers/usb/dwc3/dwc3-pci.c
@@ -42,6 +42,7 @@
#define PCI_DEVICE_ID_INTEL_CNPLP 0x9dee
#define PCI_DEVICE_ID_INTEL_CNPH 0xa36e
#define PCI_DEVICE_ID_INTEL_ICLLP 0x34ee
+#define PCI_DEVICE_ID_INTEL_EHLLP 0x4b7e
struct dwc3_pci {
struct device *dev;
@@ -209,6 +210,7 @@ static const struct pci_device_id dwc3_p
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_CNPLP), },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_CNPH), },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICLLP), },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_EHLLP), },
{ } /* Terminating Entry */
};
MODULE_DEVICE_TABLE(pci, dwc3_pci_id_table);
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Heikki Krogerus <[email protected]>
commit 84a2b61b6eb94036093531cdabc448dddfbae45a upstream.
Add PCI IDs for Intel Sunrise Point PCH.
Signed-off-by: Heikki Krogerus <[email protected]>
Signed-off-by: Felipe Balbi <[email protected]>
[bwh: Backported to 3.16: adjust context]
Signed-off-by: Ben Hutchings <[email protected]>
---
drivers/usb/dwc3/dwc3-pci.c | 4 ++++
1 file changed, 4 insertions(+)
--- a/drivers/usb/dwc3/dwc3-pci.c
+++ b/drivers/usb/dwc3/dwc3-pci.c
@@ -31,6 +31,8 @@
#define PCI_DEVICE_ID_INTEL_BYT 0x0f37
#define PCI_DEVICE_ID_INTEL_MRFLD 0x119e
#define PCI_DEVICE_ID_INTEL_BSW 0x22B7
+#define PCI_DEVICE_ID_INTEL_SPTLP 0x9d30
+#define PCI_DEVICE_ID_INTEL_SPTH 0xa130
struct dwc3_pci {
struct device *dev;
@@ -187,6 +189,8 @@ static const struct pci_device_id dwc3_p
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BSW), },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BYT), },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_MRFLD), },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SPTLP), },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SPTH), },
{ } /* Terminating Entry */
};
MODULE_DEVICE_TABLE(pci, dwc3_pci_id_table);
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Josef Bacik <[email protected]>
commit 714cd3e8cba6841220dce9063a7388a81de03825 upstream.
If we get an -ENOENT back from btrfs_uuid_iter_rem when iterating the
uuid tree we'll just continue and do btrfs_next_item(). However we've
done a btrfs_release_path() at this point and no longer have a valid
path. So increment the key and go back and do a normal search.
Reviewed-by: Filipe Manana <[email protected]>
Reviewed-by: Johannes Thumshirn <[email protected]>
Signed-off-by: Josef Bacik <[email protected]>
Reviewed-by: David Sterba <[email protected]>
Signed-off-by: David Sterba <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
fs/btrfs/uuid-tree.c | 2 ++
1 file changed, 2 insertions(+)
--- a/fs/btrfs/uuid-tree.c
+++ b/fs/btrfs/uuid-tree.c
@@ -333,6 +333,8 @@ again_search_slot:
}
if (ret < 0 && ret != -ENOENT)
goto out;
+ key.offset++;
+ goto again_search_slot;
}
item_size -= sizeof(subid_le);
offset += sizeof(subid_le);
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: David Hildenbrand <[email protected]>
commit 63341ab03706e11a31e3dd8ccc0fbc9beaf723f0 upstream.
In case we have to migrate a ballon page to a newpage of another zone, the
managed page count of both zones is wrong. Paired with memory offlining
(which will adjust the managed page count), we can trigger kernel crashes
and all kinds of different symptoms.
One way to reproduce:
1. Start a QEMU guest with 4GB, no NUMA
2. Hotplug a 1GB DIMM and online the memory to ZONE_NORMAL
3. Inflate the balloon to 1GB
4. Unplug the DIMM (be quick, otherwise unmovable data ends up on it)
5. Observe /proc/zoneinfo
Node 0, zone Normal
pages free 16810
min 24848885473806
low 18471592959183339
high 36918337032892872
spanned 262144
present 262144
managed 18446744073709533486
6. Do anything that requires some memory (e.g., inflate the balloon some
more). The OOM goes crazy and the system crashes
[ 238.324946] Out of memory: Killed process 537 (login) total-vm:27584kB, anon-rss:860kB, file-rss:0kB, shmem-rss:00
[ 238.338585] systemd invoked oom-killer: gfp_mask=0x100cca(GFP_HIGHUSER_MOVABLE), order=0, oom_score_adj=0
[ 238.339420] CPU: 0 PID: 1 Comm: systemd Tainted: G D W 5.4.0-next-20191204+ #75
[ 238.340139] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.12.0-59-gc9ba5276e321-prebuilt.qemu4
[ 238.341121] Call Trace:
[ 238.341337] dump_stack+0x8f/0xd0
[ 238.341630] dump_header+0x61/0x5ea
[ 238.341942] oom_kill_process.cold+0xb/0x10
[ 238.342299] out_of_memory+0x24d/0x5a0
[ 238.342625] __alloc_pages_slowpath+0xd12/0x1020
[ 238.343024] __alloc_pages_nodemask+0x391/0x410
[ 238.343407] pagecache_get_page+0xc3/0x3a0
[ 238.343757] filemap_fault+0x804/0xc30
[ 238.344083] ? ext4_filemap_fault+0x28/0x42
[ 238.344444] ext4_filemap_fault+0x30/0x42
[ 238.344789] __do_fault+0x37/0x1a0
[ 238.345087] __handle_mm_fault+0x104d/0x1ab0
[ 238.345450] handle_mm_fault+0x169/0x360
[ 238.345790] do_user_addr_fault+0x20d/0x490
[ 238.346154] do_page_fault+0x31/0x210
[ 238.346468] async_page_fault+0x43/0x50
[ 238.346797] RIP: 0033:0x7f47eba4197e
[ 238.347110] Code: Bad RIP value.
[ 238.347387] RSP: 002b:00007ffd7c0c1890 EFLAGS: 00010293
[ 238.347834] RAX: 0000000000000002 RBX: 000055d196a20a20 RCX: 00007f47eba4197e
[ 238.348437] RDX: 0000000000000033 RSI: 00007ffd7c0c18c0 RDI: 0000000000000004
[ 238.349047] RBP: 00007ffd7c0c1c20 R08: 0000000000000000 R09: 0000000000000033
[ 238.349660] R10: 00000000ffffffff R11: 0000000000000293 R12: 0000000000000001
[ 238.350261] R13: ffffffffffffffff R14: 0000000000000000 R15: 00007ffd7c0c18c0
[ 238.350878] Mem-Info:
[ 238.351085] active_anon:3121 inactive_anon:51 isolated_anon:0
[ 238.351085] active_file:12 inactive_file:7 isolated_file:0
[ 238.351085] unevictable:0 dirty:0 writeback:0 unstable:0
[ 238.351085] slab_reclaimable:5565 slab_unreclaimable:10170
[ 238.351085] mapped:3 shmem:111 pagetables:155 bounce:0
[ 238.351085] free:720717 free_pcp:2 free_cma:0
[ 238.353757] Node 0 active_anon:12484kB inactive_anon:204kB active_file:48kB inactive_file:28kB unevictable:0kB iss
[ 238.355979] Node 0 DMA free:11556kB min:36kB low:48kB high:60kB reserved_highatomic:0KB active_anon:152kB inactivB
[ 238.358345] lowmem_reserve[]: 0 2955 2884 2884 2884
[ 238.358761] Node 0 DMA32 free:2677864kB min:7004kB low:10028kB high:13052kB reserved_highatomic:0KB active_anon:0B
[ 238.361202] lowmem_reserve[]: 0 0 72057594037927865 72057594037927865 72057594037927865
[ 238.361888] Node 0 Normal free:193448kB min:99395541895224kB low:73886371836733356kB high:147673348131571488kB reB
[ 238.364765] lowmem_reserve[]: 0 0 0 0 0
[ 238.365101] Node 0 DMA: 7*4kB (U) 5*8kB (UE) 6*16kB (UME) 2*32kB (UM) 1*64kB (U) 2*128kB (UE) 3*256kB (UME) 2*512B
[ 238.366379] Node 0 DMA32: 0*4kB 1*8kB (U) 2*16kB (UM) 2*32kB (UM) 2*64kB (UM) 1*128kB (U) 1*256kB (U) 1*512kB (U)B
[ 238.367654] Node 0 Normal: 1985*4kB (UME) 1321*8kB (UME) 844*16kB (UME) 524*32kB (UME) 300*64kB (UME) 138*128kB (B
[ 238.369184] Node 0 hugepages_total=0 hugepages_free=0 hugepages_surp=0 hugepages_size=2048kB
[ 238.369915] 130 total pagecache pages
[ 238.370241] 0 pages in swap cache
[ 238.370533] Swap cache stats: add 0, delete 0, find 0/0
[ 238.370981] Free swap = 0kB
[ 238.371239] Total swap = 0kB
[ 238.371488] 1048445 pages RAM
[ 238.371756] 0 pages HighMem/MovableOnly
[ 238.372090] 306992 pages reserved
[ 238.372376] 0 pages cma reserved
[ 238.372661] 0 pages hwpoisoned
In another instance (older kernel), I was able to observe this
(negative page count :/):
[ 180.896971] Offlined Pages 32768
[ 182.667462] Offlined Pages 32768
[ 184.408117] Offlined Pages 32768
[ 186.026321] Offlined Pages 32768
[ 187.684861] Offlined Pages 32768
[ 189.227013] Offlined Pages 32768
[ 190.830303] Offlined Pages 32768
[ 190.833071] Built 1 zonelists, mobility grouping on. Total pages: -36920272750453009
In another instance (older kernel), I was no longer able to start any
process:
[root@vm ~]# [ 214.348068] Offlined Pages 32768
[ 215.973009] Offlined Pages 32768
cat /proc/meminfo
-bash: fork: Cannot allocate memory
[root@vm ~]# cat /proc/meminfo
-bash: fork: Cannot allocate memory
Fix it by properly adjusting the managed page count when migrating if
the zone changed. The managed page count of the zones now looks after
unplug of the DIMM (and after deflating the balloon) just like before
inflating the balloon (and plugging+onlining the DIMM).
We'll temporarily modify the totalram page count. If this ever becomes a
problem, we can fine tune by providing helpers that don't touch
the totalram pages (e.g., adjust_zone_managed_page_count()).
Please note that fixing up the managed page count is only necessary when
we adjusted the managed page count when inflating - only if we
don't have VIRTIO_BALLOON_F_DEFLATE_ON_OOM. With that feature, the
managed page count is not touched when inflating/deflating.
Reported-by: Yumei Huang <[email protected]>
Fixes: 3dcc0571cd64 ("mm: correctly update zone->managed_pages")
Cc: "Michael S. Tsirkin" <[email protected]>
Cc: Jason Wang <[email protected]>
Cc: Jiang Liu <[email protected]>
Cc: Andrew Morton <[email protected]>
Cc: Igor Mammedov <[email protected]>
Cc: [email protected]
Signed-off-by: David Hildenbrand <[email protected]>
Signed-off-by: Michael S. Tsirkin <[email protected]>
[bwh: Backported to 3.16: Deflate-on-OOM is not supported at all so don't
check that flag]
Signed-off-by: Ben Hutchings <[email protected]>
---
--- a/drivers/virtio/virtio_balloon.c
+++ b/drivers/virtio/virtio_balloon.c
@@ -403,6 +403,16 @@ static int virtballoon_migratepage(struc
get_page(newpage); /* balloon reference */
+ /*
+ * When we migrate a page to a different zone and adjusted the
+ * managed page count when inflating, we have to fixup the count of
+ * both involved zones.
+ */
+ if (page_zone(page) != page_zone(newpage)) {
+ adjust_managed_page_count(page, 1);
+ adjust_managed_page_count(newpage, -1);
+ }
+
/* balloon's page migration 1st step -- inflate "newpage" */
spin_lock_irqsave(&vb_dev_info->pages_lock, flags);
balloon_page_insert(newpage, mapping, &vb_dev_info->pages);
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Leo Yan <[email protected]>
commit 0e4f7f920a5c6bfe5e851e989f27b35a0cc7fb7e upstream.
As the commit 677fe555cbfb ("serial: imx: Fix recursive locking bug")
has mentioned the uart driver might cause recursive locking between
normal printing and the kernel debugging facilities (e.g. sysrq and
oops). In the commit it gave out suggestion for fixing recursive
locking issue: "The solution is to avoid locking in the sysrq case
and trylock in the oops_in_progress case."
This patch follows the suggestion (also used the exactly same code with
other serial drivers, e.g. amba-pl011.c) to fix the recursive locking
issue, this can avoid stuck caused by deadlock and print out log for
sysrq and oops.
Fixes: 04896a77a97b ("msm_serial: serial driver for MSM7K onboard serial peripheral.")
Signed-off-by: Leo Yan <[email protected]>
Reviewed-by: Jeffrey Hugo <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Greg Kroah-Hartman <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
drivers/tty/serial/msm_serial.c | 13 +++++++++++--
1 file changed, 11 insertions(+), 2 deletions(-)
--- a/drivers/tty/serial/msm_serial.c
+++ b/drivers/tty/serial/msm_serial.c
@@ -857,6 +857,7 @@ static void msm_console_write(struct con
struct msm_port *msm_port;
int num_newlines = 0;
bool replaced = false;
+ int locked = 1;
BUG_ON(co->index < 0 || co->index >= UART_NR);
@@ -869,7 +870,13 @@ static void msm_console_write(struct con
num_newlines++;
count += num_newlines;
- spin_lock(&port->lock);
+ if (port->sysrq)
+ locked = 0;
+ else if (oops_in_progress)
+ locked = spin_trylock(&port->lock);
+ else
+ spin_lock(&port->lock);
+
if (msm_port->is_uartdm)
reset_dm_count(port, count);
@@ -906,7 +913,9 @@ static void msm_console_write(struct con
msm_write(port, *bf, msm_port->is_uartdm ? UARTDM_TF : UART_TF);
i += num_chars;
}
- spin_unlock(&port->lock);
+
+ if (locked)
+ spin_unlock(&port->lock);
}
static int __init msm_console_setup(struct console *co, char *options)
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Heikki Krogerus <[email protected]>
commit 4491ed5042f0419b22a4b08331adb54af31e2caa upstream.
Intel Kabylake PCH has the same DWC3 than Intel
Sunrisepoint. Add the new ID to the supported devices.
Signed-off-by: Heikki Krogerus <[email protected]>
Signed-off-by: Felipe Balbi <[email protected]>
[bwh: Backported to 3.16: adjust context, indentation]
Signed-off-by: Ben Hutchings <[email protected]>
---
drivers/usb/dwc3/dwc3-pci.c | 2 ++
1 file changed, 2 insertions(+)
--- a/drivers/usb/dwc3/dwc3-pci.c
+++ b/drivers/usb/dwc3/dwc3-pci.c
@@ -36,6 +36,7 @@
#define PCI_DEVICE_ID_INTEL_BXT 0x0aaa
#define PCI_DEVICE_ID_INTEL_BXT_M 0x1aaa
#define PCI_DEVICE_ID_INTEL_APL 0x5aaa
+#define PCI_DEVICE_ID_INTEL_KBP 0xa2b0
struct dwc3_pci {
struct device *dev;
@@ -197,6 +198,7 @@ static const struct pci_device_id dwc3_p
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BXT), },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BXT_M), },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_APL), },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_KBP), },
{ } /* Terminating Entry */
};
MODULE_DEVICE_TABLE(pci, dwc3_pci_id_table);
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Josef Bacik <[email protected]>
commit 423a716cd7be16fb08690760691befe3be97d3fc upstream.
btrfs_del_root_ref() will simply WARN_ON() if the ref doesn't match in
any way, and then continue to delete the reference. This shouldn't
happen, we have these values because there's more to the reference than
the original root and the sub root. If any of these checks fail, return
-ENOENT.
Signed-off-by: Josef Bacik <[email protected]>
Reviewed-by: David Sterba <[email protected]>
Signed-off-by: David Sterba <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
fs/btrfs/root-tree.c | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
--- a/fs/btrfs/root-tree.c
+++ b/fs/btrfs/root-tree.c
@@ -373,11 +373,13 @@ again:
leaf = path->nodes[0];
ref = btrfs_item_ptr(leaf, path->slots[0],
struct btrfs_root_ref);
-
- WARN_ON(btrfs_root_ref_dirid(leaf, ref) != dirid);
- WARN_ON(btrfs_root_ref_name_len(leaf, ref) != name_len);
ptr = (unsigned long)(ref + 1);
- WARN_ON(memcmp_extent_buffer(leaf, name, ptr, name_len));
+ if ((btrfs_root_ref_dirid(leaf, ref) != dirid) ||
+ (btrfs_root_ref_name_len(leaf, ref) != name_len) ||
+ memcmp_extent_buffer(leaf, name, ptr, name_len)) {
+ err = -ENOENT;
+ goto out;
+ }
*sequence = btrfs_root_ref_sequence(leaf, ref);
ret = btrfs_del_item(trans, tree_root, path);
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Heikki Krogerus <[email protected]>
commit 1ffb4d5cc78a3a99109ff0808ce6915de07a0588 upstream.
BXT-M is a Intel Broxton SoC based platform with unique PCI ID.
Signed-off-by: Heikki Krogerus <[email protected]>
Signed-off-by: Felipe Balbi <[email protected]>
[bwh: Backported to 3.16: adjust context, indentation]
Signed-off-by: Ben Hutchings <[email protected]>
---
drivers/usb/dwc3/dwc3-pci.c | 2 ++
1 file changed, 2 insertions(+)
--- a/drivers/usb/dwc3/dwc3-pci.c
+++ b/drivers/usb/dwc3/dwc3-pci.c
@@ -34,6 +34,7 @@
#define PCI_DEVICE_ID_INTEL_SPTLP 0x9d30
#define PCI_DEVICE_ID_INTEL_SPTH 0xa130
#define PCI_DEVICE_ID_INTEL_BXT 0x0aaa
+#define PCI_DEVICE_ID_INTEL_BXT_M 0x1aaa
#define PCI_DEVICE_ID_INTEL_APL 0x5aaa
struct dwc3_pci {
@@ -194,6 +195,7 @@ static const struct pci_device_id dwc3_p
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SPTLP), },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SPTH), },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BXT), },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BXT_M), },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_APL), },
{ } /* Terminating Entry */
};
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Josef Bacik <[email protected]>
commit f72ff01df9cf5db25c76674cac16605992d15467 upstream.
Testing with the new fsstress uncovered a pretty nasty deadlock with
lookup and snapshot deletion.
Process A
unlink
-> final iput
-> inode_tree_del
-> synchronize_srcu(subvol_srcu)
Process B
btrfs_lookup <- srcu_read_lock() acquired here
-> btrfs_iget
-> find inode that has I_FREEING set
-> __wait_on_freeing_inode()
We're holding the srcu_read_lock() while doing the iget in order to make
sure our fs root doesn't go away, and then we are waiting for the inode
to finish freeing. However because the free'ing process is doing a
synchronize_srcu() we deadlock.
Fix this by dropping the synchronize_srcu() in inode_tree_del(). We
don't need people to stop accessing the fs root at this point, we're
only adding our empty root to the dead roots list.
A larger much more invasive fix is forthcoming to address how we deal
with fs roots, but this fixes the immediate problem.
Fixes: 76dda93c6ae2 ("Btrfs: add snapshot/subvolume destroy ioctl")
Signed-off-by: Josef Bacik <[email protected]>
Reviewed-by: David Sterba <[email protected]>
Signed-off-by: David Sterba <[email protected]>
[bwh: Backported to 3.16: No fs_info variable was used here]
Signed-off-by: Ben Hutchings <[email protected]>
---
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -5140,7 +5140,6 @@ static void inode_tree_del(struct inode
spin_unlock(&root->inode_lock);
if (empty && btrfs_root_refs(&root->root_item) == 0) {
- synchronize_srcu(&root->fs_info->subvol_srcu);
spin_lock(&root->inode_lock);
empty = RB_EMPTY_ROOT(&root->inode_tree);
spin_unlock(&root->inode_lock);
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Heikki Krogerus <[email protected]>
commit b4c580a43d520b7812c0fd064fbab929ce2f1da0 upstream.
PCI IDs for Broxton based platforms.
Signed-off-by: Heikki Krogerus <[email protected]>
Signed-off-by: Felipe Balbi <[email protected]>
[bwh: Backported to 3.16: adjust context, indentation]
Signed-off-by: Ben Hutchings <[email protected]>
---
drivers/usb/dwc3/dwc3-pci.c | 4 ++++
1 file changed, 4 insertions(+)
--- a/drivers/usb/dwc3/dwc3-pci.c
+++ b/drivers/usb/dwc3/dwc3-pci.c
@@ -33,6 +33,8 @@
#define PCI_DEVICE_ID_INTEL_BSW 0x22B7
#define PCI_DEVICE_ID_INTEL_SPTLP 0x9d30
#define PCI_DEVICE_ID_INTEL_SPTH 0xa130
+#define PCI_DEVICE_ID_INTEL_BXT 0x0aaa
+#define PCI_DEVICE_ID_INTEL_APL 0x5aaa
struct dwc3_pci {
struct device *dev;
@@ -191,6 +193,8 @@ static const struct pci_device_id dwc3_p
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_MRFLD), },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SPTLP), },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SPTH), },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BXT), },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_APL), },
{ } /* Terminating Entry */
};
MODULE_DEVICE_TABLE(pci, dwc3_pci_id_table);
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Johan Hovold <[email protected]>
commit 7c5a2df3367a2c4984f1300261345817d95b71f8 upstream.
Make sure to use the current alternate setting when looking up the
endpoints on epic devices to avoid binding to an invalid interface.
Failing to do so could cause the driver to misbehave or trigger a WARN()
in usb_submit_urb() that kernels with panic_on_warn set would choke on.
Fixes: 6e8cf7751f9f ("USB: add EPIC support to the io_edgeport driver")
Signed-off-by: Johan Hovold <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Greg Kroah-Hartman <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
drivers/usb/serial/io_edgeport.c | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
--- a/drivers/usb/serial/io_edgeport.c
+++ b/drivers/usb/serial/io_edgeport.c
@@ -2859,16 +2859,18 @@ static int edge_startup(struct usb_seria
response = 0;
if (edge_serial->is_epic) {
+ struct usb_host_interface *alt;
+
+ alt = serial->interface->cur_altsetting;
+
/* EPIC thing, set up our interrupt polling now and our read
* urb, so that the device knows it really is connected. */
interrupt_in_found = bulk_in_found = bulk_out_found = false;
- for (i = 0; i < serial->interface->altsetting[0]
- .desc.bNumEndpoints; ++i) {
+ for (i = 0; i < alt->desc.bNumEndpoints; ++i) {
struct usb_endpoint_descriptor *endpoint;
int buffer_size;
- endpoint = &serial->interface->altsetting[0].
- endpoint[i].desc;
+ endpoint = &alt->endpoint[i].desc;
buffer_size = usb_endpoint_maxp(endpoint);
if (!interrupt_in_found &&
(usb_endpoint_is_int_in(endpoint))) {
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Sudip Mukherjee <[email protected]>
commit 273f632912f1b24b642ba5b7eb5022e43a72f3b5 upstream.
If the serial device is disconnected and reconnected, it re-enumerates
properly but does not link it. fwiw, linking means just saving the port
index, so allow it always as there is no harm in saving the same value
again even if it tries to relink with the same port.
Fixes: fb2b90014d78 ("tty: link tty and port before configuring it as console")
Reported-by: Kenneth R. Crudup <[email protected]>
Signed-off-by: Sudip Mukherjee <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Greg Kroah-Hartman <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
drivers/tty/tty_port.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
--- a/drivers/tty/tty_port.c
+++ b/drivers/tty/tty_port.c
@@ -49,8 +49,7 @@ void tty_port_link_device(struct tty_por
{
if (WARN_ON(index >= driver->num))
return;
- if (!driver->ports[index])
- driver->ports[index] = port;
+ driver->ports[index] = port;
}
EXPORT_SYMBOL_GPL(tty_port_link_device);
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Mathias Nyman <[email protected]>
commit bd82873f23c9a6ad834348f8b83f3b6a5bca2c65 upstream.
spin_unlock_irqrestore() might be called with stale flags after
reading port status, possibly restoring interrupts to a incorrect
state.
If a usb2 port just finished resuming while the port status is read
the spin lock will be temporary released and re-acquired in a separate
function. The flags parameter is passed as value instead of a pointer,
not updating flags properly before the final spin_unlock_irqrestore()
is called.
Fixes: 8b3d45705e54 ("usb: Fix xHCI host issues on remote wakeup.")
Signed-off-by: Mathias Nyman <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Greg Kroah-Hartman <[email protected]>
Signed-off-by: Sasha Levin <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
drivers/usb/host/xhci-hub.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
--- a/drivers/usb/host/xhci-hub.c
+++ b/drivers/usb/host/xhci-hub.c
@@ -580,7 +580,7 @@ static u32 xhci_get_port_status(struct u
struct xhci_bus_state *bus_state,
__le32 __iomem **port_array,
u16 wIndex, u32 raw_port_status,
- unsigned long flags)
+ unsigned long *flags)
__releases(&xhci->lock)
__acquires(&xhci->lock)
{
@@ -670,12 +670,12 @@ static u32 xhci_get_port_status(struct u
xhci_set_link_state(xhci, port_array, wIndex,
XDEV_U0);
- spin_unlock_irqrestore(&xhci->lock, flags);
+ spin_unlock_irqrestore(&xhci->lock, *flags);
time_left = wait_for_completion_timeout(
&bus_state->rexit_done[wIndex],
msecs_to_jiffies(
XHCI_MAX_REXIT_TIMEOUT_MS));
- spin_lock_irqsave(&xhci->lock, flags);
+ spin_lock_irqsave(&xhci->lock, *flags);
if (time_left) {
slot_id = xhci_find_slot_id_by_port(hcd,
@@ -834,7 +834,7 @@ int xhci_hub_control(struct usb_hcd *hcd
break;
}
status = xhci_get_port_status(hcd, bus_state, port_array,
- wIndex, temp, flags);
+ wIndex, temp, &flags);
if (status == 0xffffffff)
goto error;
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Alan Cox <[email protected]>
commit 7d643664ea559b36188cae264047ce3c9bfec3a2 upstream.
The device controller is the same but it has different PCI ID. Add this new
ID to the driver's list of supported IDs.
Signed-off-by: Alan Cox <[email protected]>
Signed-off-by: Mika Westerberg <[email protected]>
Signed-off-by: Heikki Krogerus <[email protected]>
Signed-off-by: Felipe Balbi <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
drivers/usb/dwc3/dwc3-pci.c | 2 ++
1 file changed, 2 insertions(+)
--- a/drivers/usb/dwc3/dwc3-pci.c
+++ b/drivers/usb/dwc3/dwc3-pci.c
@@ -30,6 +30,7 @@
#define PCI_DEVICE_ID_SYNOPSYS_HAPSUSB3 0xabcd
#define PCI_DEVICE_ID_INTEL_BYT 0x0f37
#define PCI_DEVICE_ID_INTEL_MRFLD 0x119e
+#define PCI_DEVICE_ID_INTEL_BSW 0x22B7
struct dwc3_pci {
struct device *dev;
@@ -183,6 +184,7 @@ static const struct pci_device_id dwc3_p
PCI_DEVICE(PCI_VENDOR_ID_SYNOPSYS,
PCI_DEVICE_ID_SYNOPSYS_HAPSUSB3),
},
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BSW), },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BYT), },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_MRFLD), },
{ } /* Terminating Entry */
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Johan Hovold <[email protected]>
commit 3c11c4bed02b202e278c0f5c319ae435d7fb9815 upstream.
Make sure to use the current alternate setting when verifying the
interface descriptors to avoid binding to an invalid interface.
Failing to do so could cause the driver to misbehave or trigger a WARN()
in usb_submit_urb() that kernels with panic_on_warn set would choke on.
Fixes: 03270634e242 ("USB: Add ADU support for Ontrak ADU devices")
Signed-off-by: Johan Hovold <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Greg Kroah-Hartman <[email protected]>
[bwh: Backported to 3.16: adjust context]
Signed-off-by: Ben Hutchings <[email protected]>
---
drivers/usb/misc/adutux.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/usb/misc/adutux.c
+++ b/drivers/usb/misc/adutux.c
@@ -682,7 +682,7 @@ static int adu_probe(struct usb_interfac
init_waitqueue_head(&dev->read_wait);
init_waitqueue_head(&dev->write_wait);
- iface_desc = &interface->altsetting[0];
+ iface_desc = interface->cur_altsetting;
/* set up the endpoint information */
for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Johan Hovold <[email protected]>
commit 09068c1ad53fb077bdac288869dec2435420bdc4 upstream.
Make sure that the interrupt interface has an endpoint before trying to
access its endpoint descriptors to avoid dereferencing a NULL pointer.
The driver binds to the interrupt interface with interface number 0, but
must not assume that this interface or its current alternate setting are
the first entries in the corresponding configuration arrays.
Fixes: b72458a80c75 ("[PATCH] USB: Eagle and ADI 930 usb adsl modem driver")
Signed-off-by: Johan Hovold <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Greg Kroah-Hartman <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
drivers/usb/atm/ueagle-atm.c | 18 ++++++++++++------
1 file changed, 12 insertions(+), 6 deletions(-)
--- a/drivers/usb/atm/ueagle-atm.c
+++ b/drivers/usb/atm/ueagle-atm.c
@@ -2167,10 +2167,11 @@ resubmit:
/*
* Start the modem : init the data and start kernel thread
*/
-static int uea_boot(struct uea_softc *sc)
+static int uea_boot(struct uea_softc *sc, struct usb_interface *intf)
{
- int ret, size;
struct intr_pkt *intr;
+ int ret = -ENOMEM;
+ int size;
uea_enters(INS_TO_USBDEV(sc));
@@ -2195,6 +2196,11 @@ static int uea_boot(struct uea_softc *sc
if (UEA_CHIP_VERSION(sc) == ADI930)
load_XILINX_firmware(sc);
+ if (intf->cur_altsetting->desc.bNumEndpoints < 1) {
+ ret = -ENODEV;
+ goto err0;
+ }
+
intr = kmalloc(size, GFP_KERNEL);
if (!intr) {
uea_err(INS_TO_USBDEV(sc),
@@ -2211,8 +2217,7 @@ static int uea_boot(struct uea_softc *sc
usb_fill_int_urb(sc->urb_int, sc->usb_dev,
usb_rcvintpipe(sc->usb_dev, UEA_INTR_PIPE),
intr, size, uea_intr, sc,
- sc->usb_dev->actconfig->interface[0]->altsetting[0].
- endpoint[0].desc.bInterval);
+ intf->cur_altsetting->endpoint[0].desc.bInterval);
ret = usb_submit_urb(sc->urb_int, GFP_KERNEL);
if (ret < 0) {
@@ -2227,6 +2232,7 @@ static int uea_boot(struct uea_softc *sc
sc->kthread = kthread_create(uea_kthread, sc, "ueagle-atm");
if (IS_ERR(sc->kthread)) {
uea_err(INS_TO_USBDEV(sc), "failed to create thread\n");
+ ret = PTR_ERR(sc->kthread);
goto err2;
}
@@ -2241,7 +2247,7 @@ err1:
kfree(intr);
err0:
uea_leaves(INS_TO_USBDEV(sc));
- return -ENOMEM;
+ return ret;
}
/*
@@ -2604,7 +2610,7 @@ static int uea_bind(struct usbatm_data *
if (ret < 0)
goto error;
- ret = uea_boot(sc);
+ ret = uea_boot(sc, intf);
if (ret < 0)
goto error_rm_grp;
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Pengcheng Yang <[email protected]>
commit c9655008e7845bcfdaac10a1ed8554ec167aea88 upstream.
When we receive a D-SACK, where the sequence number satisfies:
undo_marker <= start_seq < end_seq <= prior_snd_una
we consider this is a valid D-SACK and tcp_is_sackblock_valid()
returns true, then this D-SACK is discarded as "old stuff",
but the variable first_sack_index is not marked as negative
in tcp_sacktag_write_queue().
If this D-SACK also carries a SACK that needs to be processed
(for example, the previous SACK segment was lost), this SACK
will be treated as a D-SACK in the following processing of
tcp_sacktag_write_queue(), which will eventually lead to
incorrect updates of undo_retrans and reordering.
Fixes: fd6dad616d4f ("[TCP]: Earlier SACK block verification & simplify access to them")
Signed-off-by: Pengcheng Yang <[email protected]>
Signed-off-by: Eric Dumazet <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
net/ipv4/tcp_input.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -1713,8 +1713,11 @@ tcp_sacktag_write_queue(struct sock *sk,
}
/* Ignore very old stuff early */
- if (!after(sp[used_sacks].end_seq, prior_snd_una))
+ if (!after(sp[used_sacks].end_seq, prior_snd_una)) {
+ if (i == 0)
+ first_sack_index = -1;
continue;
+ }
used_sacks++;
}
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Johan Hovold <[email protected]>
commit 59920635b89d74b9207ea803d5e91498d39e8b69 upstream.
Make sure to use the current alternate setting when verifying the
interface descriptors to avoid binding to an invalid interface.
Failing to do so could cause the driver to misbehave or trigger a WARN()
in usb_submit_urb() that kernels with panic_on_warn set would choke on.
Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Signed-off-by: Johan Hovold <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Greg Kroah-Hartman <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
drivers/usb/misc/idmouse.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/usb/misc/idmouse.c
+++ b/drivers/usb/misc/idmouse.c
@@ -342,7 +342,7 @@ static int idmouse_probe(struct usb_inte
int result;
/* check if we have gotten the data or the hid interface */
- iface_desc = &interface->altsetting[0];
+ iface_desc = interface->cur_altsetting;
if (iface_desc->desc.bInterfaceClass != 0x0A)
return -ENODEV;
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Josef Bacik <[email protected]>
commit 3da40c7b089810ac9cf2bb1e59633f619f3a7312 upstream.
At LSF we decided that if we truncate up from isize we shouldn't trim
fallocated blocks that were fallocated with KEEP_SIZE and are past the
new i_size. This patch fixes ext4 to do this.
[ Completely reworked patch so that i_disksize would actually get set
when truncating up. Also reworked the code for handling truncate so
that it's easier to handle. -- tytso ]
Signed-off-by: Josef Bacik <[email protected]>
Signed-off-by: Theodore Ts'o <[email protected]>
Reviewed-by: Lukas Czerner <[email protected]>
[bwh: Backported to 3.16 as dependency of commit ea3d7209ca01
"ext4: fix races between page faults and hole punching":
- Adjust context]
Signed-off-by: Ben Hutchings <[email protected]>
---
fs/ext4/inode.c | 38 ++++++++++++++++++--------------------
1 file changed, 18 insertions(+), 20 deletions(-)
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -4809,8 +4809,10 @@ int ext4_setattr(struct dentry *dentry,
ext4_journal_stop(handle);
}
- if (attr->ia_valid & ATTR_SIZE && attr->ia_size != inode->i_size) {
+ if (attr->ia_valid & ATTR_SIZE) {
handle_t *handle;
+ loff_t oldsize = inode->i_size;
+ int shrink = (attr->ia_size <= inode->i_size);
if (!(ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS))) {
struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
@@ -4818,24 +4820,26 @@ int ext4_setattr(struct dentry *dentry,
if (attr->ia_size > sbi->s_bitmap_maxbytes)
return -EFBIG;
}
+ if (!S_ISREG(inode->i_mode))
+ return -EINVAL;
if (IS_I_VERSION(inode) && attr->ia_size != inode->i_size)
inode_inc_iversion(inode);
- if (S_ISREG(inode->i_mode) &&
+ if (ext4_should_order_data(inode) &&
(attr->ia_size < inode->i_size)) {
- if (ext4_should_order_data(inode)) {
- error = ext4_begin_ordered_truncate(inode,
+ error = ext4_begin_ordered_truncate(inode,
attr->ia_size);
- if (error)
- goto err_out;
- }
+ if (error)
+ goto err_out;
+ }
+ if (attr->ia_size != inode->i_size) {
handle = ext4_journal_start(inode, EXT4_HT_INODE, 3);
if (IS_ERR(handle)) {
error = PTR_ERR(handle);
goto err_out;
}
- if (ext4_handle_valid(handle)) {
+ if (ext4_handle_valid(handle) && shrink) {
error = ext4_orphan_add(handle, inode);
orphan = 1;
}
@@ -4854,15 +4858,13 @@ int ext4_setattr(struct dentry *dentry,
up_write(&EXT4_I(inode)->i_data_sem);
ext4_journal_stop(handle);
if (error) {
- ext4_orphan_del(NULL, inode);
+ if (orphan)
+ ext4_orphan_del(NULL, inode);
goto err_out;
}
- } else {
- loff_t oldsize = inode->i_size;
-
- i_size_write(inode, attr->ia_size);
- pagecache_isize_extended(inode, oldsize, inode->i_size);
}
+ if (!shrink)
+ pagecache_isize_extended(inode, oldsize, inode->i_size);
/*
* Blocks are going to be removed from the inode. Wait
@@ -4882,13 +4884,9 @@ int ext4_setattr(struct dentry *dentry,
* in data=journal mode to make pages freeable.
*/
truncate_pagecache(inode, inode->i_size);
+ if (shrink)
+ ext4_truncate(inode);
}
- /*
- * We want to call ext4_truncate() even if attr->ia_size ==
- * inode->i_size for cases like truncation of fallocated space
- */
- if (attr->ia_valid & ATTR_SIZE)
- ext4_truncate(inode);
if (!rc) {
setattr_copy(inode, attr);
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Heikki Krogerus <[email protected]>
commit 682179592e48fa66056fbad1a86604be4992f885 upstream.
Intel Cannonlake PCH has the same DWC3 than Intel
Sunrisepoint. Add the new IDs to the supported devices.
Signed-off-by: Heikki Krogerus <[email protected]>
Signed-off-by: Felipe Balbi <[email protected]>
[bwh: Backported to 3.16: adjust context, indentation]
Signed-off-by: Ben Hutchings <[email protected]>
---
drivers/usb/dwc3/dwc3-pci.c | 4 ++++
1 file changed, 4 insertions(+)
--- a/drivers/usb/dwc3/dwc3-pci.c
+++ b/drivers/usb/dwc3/dwc3-pci.c
@@ -38,6 +38,8 @@
#define PCI_DEVICE_ID_INTEL_APL 0x5aaa
#define PCI_DEVICE_ID_INTEL_KBP 0xa2b0
#define PCI_DEVICE_ID_INTEL_GLK 0x31aa
+#define PCI_DEVICE_ID_INTEL_CNPLP 0x9dee
+#define PCI_DEVICE_ID_INTEL_CNPH 0xa36e
struct dwc3_pci {
struct device *dev;
@@ -201,6 +203,8 @@ static const struct pci_device_id dwc3_p
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_APL), },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_KBP), },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_GLK), },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_CNPLP), },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_CNPH), },
{ } /* Terminating Entry */
};
MODULE_DEVICE_TABLE(pci, dwc3_pci_id_table);
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Eryu Guan <[email protected]>
commit 911af577de4e444622d46500c1f9a37ab4335d3a upstream.
Commit 3da40c7b0898 ("ext4: only call ext4_truncate when size <= isize")
introduced a bug that c/mtime is not updated on truncate up.
Fix the issue by setting c/mtime explicitly in the truncate up case.
Note that ftruncate(2) is not affected, so you won't see this bug using
truncate(1) and xfs_io(1).
Signed-off-by: Zirong Lang <[email protected]>
Signed-off-by: Eryu Guan <[email protected]>
Signed-off-by: Theodore Ts'o <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
fs/ext4/inode.c | 8 ++++++++
1 file changed, 8 insertions(+)
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -4843,6 +4843,14 @@ int ext4_setattr(struct dentry *dentry,
error = ext4_orphan_add(handle, inode);
orphan = 1;
}
+ /*
+ * Update c/mtime on truncate up, ext4_truncate() will
+ * update c/mtime in shrink case below
+ */
+ if (!shrink) {
+ inode->i_mtime = ext4_current_time(inode);
+ inode->i_ctime = inode->i_mtime;
+ }
down_write(&EXT4_I(inode)->i_data_sem);
EXT4_I(inode)->i_disksize = attr->ia_size;
rc = ext4_mark_inode_dirty(handle, inode);
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Takashi Iwai <[email protected]>
commit cb04fc3b6b076f67d228a0b7d096c69ad486c09c upstream.
Introduce a timeout to dspio_clear_response_queue() so that it won't
be caught in an endless loop even if the hardware doesn't respond
properly.
Fixes: a73d511c4867 ("ALSA: hda/ca0132: Add unsol handler for DSP and jack detection")
Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Takashi Iwai <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
sound/pci/hda/patch_ca0132.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
--- a/sound/pci/hda/patch_ca0132.c
+++ b/sound/pci/hda/patch_ca0132.c
@@ -1271,13 +1271,14 @@ struct scp_msg {
static void dspio_clear_response_queue(struct hda_codec *codec)
{
+ unsigned long timeout = jiffies + msecs_to_jiffies(1000);
unsigned int dummy = 0;
- int status = -1;
+ int status;
/* clear all from the response queue */
do {
status = dspio_read(codec, &dummy);
- } while (status == 0);
+ } while (status == 0 && time_before(jiffies, timeout));
}
static int dspio_get_response_data(struct hda_codec *codec)
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Johan Hovold <[email protected]>
commit 73f8bda9b5dc1c69df2bc55c0cbb24461a6391a9 upstream.
Add a new device quirk that can be used to blacklist endpoints.
Since commit 3e4f8e21c4f2 ("USB: core: fix check for duplicate
endpoints") USB core ignores any duplicate endpoints found during
descriptor parsing.
In order to handle devices where the first interfaces with duplicate
endpoints are the ones that should have their endpoints ignored, we need
to add a blacklist.
Tested-by: edes <[email protected]>
Signed-off-by: Johan Hovold <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Greg Kroah-Hartman <[email protected]>
[bwh: Backported to 3.16: adjust context]
Signed-off-by: Ben Hutchings <[email protected]>
---
drivers/usb/core/config.c | 11 +++++++++++
drivers/usb/core/quirks.c | 32 ++++++++++++++++++++++++++++++++
drivers/usb/core/usb.h | 3 +++
include/linux/usb/quirks.h | 3 +++
4 files changed, 49 insertions(+)
--- a/drivers/usb/core/config.c
+++ b/drivers/usb/core/config.c
@@ -222,6 +222,7 @@ static int usb_parse_endpoint(struct dev
struct usb_host_interface *ifp, int num_ep,
unsigned char *buffer, int size)
{
+ struct usb_device *udev = to_usb_device(ddev);
unsigned char *buffer0 = buffer;
struct usb_endpoint_descriptor *d;
struct usb_host_endpoint *endpoint;
@@ -263,6 +264,16 @@ static int usb_parse_endpoint(struct dev
goto skip_to_next_endpoint_or_interface_descriptor;
}
+ /* Ignore blacklisted endpoints */
+ if (udev->quirks & USB_QUIRK_ENDPOINT_BLACKLIST) {
+ if (usb_endpoint_is_blacklisted(udev, ifp, d)) {
+ dev_warn(ddev, "config %d interface %d altsetting %d has a blacklisted endpoint with address 0x%X, skipping\n",
+ cfgno, inum, asnum,
+ d->bEndpointAddress);
+ goto skip_to_next_endpoint_or_interface_descriptor;
+ }
+ }
+
endpoint = &ifp->endpoint[ifp->desc.bNumEndpoints];
++ifp->desc.bNumEndpoints;
--- a/drivers/usb/core/quirks.c
+++ b/drivers/usb/core/quirks.c
@@ -318,6 +318,38 @@ static const struct usb_device_id usb_am
{ } /* terminating entry must be last */
};
+/*
+ * Entries for blacklisted endpoints that should be ignored when parsing
+ * configuration descriptors.
+ *
+ * Matched for devices with USB_QUIRK_ENDPOINT_BLACKLIST.
+ */
+static const struct usb_device_id usb_endpoint_blacklist[] = {
+ { }
+};
+
+bool usb_endpoint_is_blacklisted(struct usb_device *udev,
+ struct usb_host_interface *intf,
+ struct usb_endpoint_descriptor *epd)
+{
+ const struct usb_device_id *id;
+ unsigned int address;
+
+ for (id = usb_endpoint_blacklist; id->match_flags; ++id) {
+ if (!usb_match_device(udev, id))
+ continue;
+
+ if (!usb_match_one_id_intf(udev, intf, id))
+ continue;
+
+ address = id->driver_info;
+ if (address == epd->bEndpointAddress)
+ return true;
+ }
+
+ return false;
+}
+
static bool usb_match_any_interface(struct usb_device *udev,
const struct usb_device_id *id)
{
--- a/drivers/usb/core/usb.h
+++ b/drivers/usb/core/usb.h
@@ -29,6 +29,9 @@ extern int usb_deauthorize_device(struct
extern int usb_authorize_device(struct usb_device *);
extern void usb_detect_quirks(struct usb_device *udev);
extern void usb_detect_interface_quirks(struct usb_device *udev);
+extern bool usb_endpoint_is_blacklisted(struct usb_device *udev,
+ struct usb_host_interface *intf,
+ struct usb_endpoint_descriptor *epd);
extern int usb_remove_device(struct usb_device *udev);
extern int usb_get_device_descriptor(struct usb_device *dev,
--- a/include/linux/usb/quirks.h
+++ b/include/linux/usb/quirks.h
@@ -62,4 +62,7 @@
/* Hub needs extra delay after resetting its port. */
#define USB_QUIRK_HUB_SLOW_RESET BIT(14)
+/* device has blacklisted endpoints */
+#define USB_QUIRK_ENDPOINT_BLACKLIST BIT(15)
+
#endif /* __LINUX_USB_QUIRKS_H */
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Johan Hovold <[email protected]>
commit 53f35a39c3860baac1e5ca80bf052751cfb24a99 upstream.
Fix a general protection fault when accessing the endpoint descriptors
which could be triggered by a malicious device due to missing sanity
checks on the number of endpoints.
Reported-by: [email protected]
Fixes: 07dc1f9f2f80 ("[PATCH] isdn4linux: Siemens Gigaset drivers - M105 USB DECT adapter")
Cc: Hansjoerg Lipp <[email protected]>
Cc: Tilman Schmidt <[email protected]>
Signed-off-by: Johan Hovold <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Greg Kroah-Hartman <[email protected]>
[bwh: Backported to 3.16: adjust filename]
Signed-off-by: Ben Hutchings <[email protected]>
---
drivers/isdn/gigaset/usb-gigaset.c | 5 +++++
1 file changed, 5 insertions(+)
--- a/drivers/isdn/gigaset/usb-gigaset.c
+++ b/drivers/isdn/gigaset/usb-gigaset.c
@@ -693,6 +693,11 @@ static int gigaset_probe(struct usb_inte
return -ENODEV;
}
+ if (hostif->desc.bNumEndpoints < 2) {
+ dev_err(&interface->dev, "missing endpoints\n");
+ return -ENODEV;
+ }
+
dev_info(&udev->dev, "%s: Device matched ... !\n", __func__);
/* allocate memory for our device state and initialize it */
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Hangbin Liu <[email protected]>
commit 71130f29979c7c7956b040673e6b9d5643003176 upstream.
Before ip_tunnel_ecn_encap() and udp_tunnel_xmit_skb() we should filter
tos value by RT_TOS() instead of using config tos directly.
vxlan_get_route() would filter the tos to fl4.flowi4_tos but we didn't
return it back, as geneve_get_v4_rt() did. So we have to use RT_TOS()
directly in function ip_tunnel_ecn_encap().
Fixes: 206aaafcd279 ("VXLAN: Use IP Tunnels tunnel ENC encap API")
Fixes: 1400615d64cf ("vxlan: allow setting ipv6 traffic class")
Signed-off-by: Hangbin Liu <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
drivers/net/vxlan.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
--- a/drivers/net/vxlan.c
+++ b/drivers/net/vxlan.c
@@ -1904,7 +1904,7 @@ static void vxlan_xmit_one(struct sk_buf
return;
}
- tos = ip_tunnel_ecn_encap(tos, old_iph, skb);
+ tos = ip_tunnel_ecn_encap(RT_TOS(tos), old_iph, skb);
ttl = ttl ? : ip4_dst_hoplimit(&rt->dst);
err = vxlan_xmit_skb(vxlan->vn_sock, rt, skb,
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Johan Hovold <[email protected]>
commit ed9ed5a89acba51b82bdff61144d4e4a4245ec8a upstream.
Add missing endpoint-type sanity checks to probe.
This specifically prevents a warning in USB core on URB submission when
fuzzing USB descriptors.
Signed-off-by: Johan Hovold <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Greg Kroah-Hartman <[email protected]>
[bwh: Backported to 3.16: adjust filename]
Signed-off-by: Ben Hutchings <[email protected]>
---
drivers/isdn/gigaset/usb-gigaset.c | 12 ++++++++++++
1 file changed, 12 insertions(+)
--- a/drivers/isdn/gigaset/usb-gigaset.c
+++ b/drivers/isdn/gigaset/usb-gigaset.c
@@ -713,6 +713,12 @@ static int gigaset_probe(struct usb_inte
endpoint = &hostif->endpoint[0].desc;
+ if (!usb_endpoint_is_bulk_out(endpoint)) {
+ dev_err(&interface->dev, "missing bulk-out endpoint\n");
+ retval = -ENODEV;
+ goto error;
+ }
+
buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
ucs->bulk_out_size = buffer_size;
ucs->bulk_out_endpointAddr = endpoint->bEndpointAddress;
@@ -732,6 +738,12 @@ static int gigaset_probe(struct usb_inte
endpoint = &hostif->endpoint[1].desc;
+ if (!usb_endpoint_is_int_in(endpoint)) {
+ dev_err(&interface->dev, "missing int-in endpoint\n");
+ retval = -ENODEV;
+ goto error;
+ }
+
ucs->busy = 0;
ucs->read_urb = usb_alloc_urb(0, GFP_KERNEL);
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Johan Hovold <[email protected]>
commit c724f776f048538ecfdf53a52b7a522309f5c504 upstream.
Make sure to use the current alternate setting when verifying the
interface descriptors to avoid binding to an invalid interface.
Failing to do so could cause the driver to misbehave or trigger a WARN()
in usb_submit_urb() that kernels with panic_on_warn set would choke on.
Fixes: 2865d42c78a9 ("staging: r8712u: Add the new driver to the mainline kernel")
Signed-off-by: Johan Hovold <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Greg Kroah-Hartman <[email protected]>
[bwh: Backported to 3.16: adjust context]
Signed-off-by: Ben Hutchings <[email protected]>
---
drivers/staging/rtl8712/usb_intf.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/staging/rtl8712/usb_intf.c
+++ b/drivers/staging/rtl8712/usb_intf.c
@@ -269,7 +269,7 @@ static uint r8712_usb_dvobj_init(struct
pdev_desc = &pusbd->descriptor;
phost_conf = pusbd->actconfig;
pconf_desc = &phost_conf->desc;
- phost_iface = &pintf->altsetting[0];
+ phost_iface = pintf->cur_altsetting;
piface_desc = &phost_iface->desc;
pdvobjpriv->nr_endpoint = piface_desc->bNumEndpoints;
if (pusbd->speed == USB_SPEED_HIGH) {
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Marcel Holtmann <[email protected]>
commit be54e7461ffdc5809b67d2aeefc1ddc9a91470c7 upstream.
Always return EPOLLOUT from uhid_char_poll to allow polling /dev/uhid
for writable state.
Fixes: 1f9dec1e0164 ("HID: uhid: allow poll()'ing on uhid devices")
Signed-off-by: Marcel Holtmann <[email protected]>
Signed-off-by: Jiri Kosina <[email protected]>
[bwh: Backported to 3.16: s/EPOLL/POLL/g]
Signed-off-by: Ben Hutchings <[email protected]>
---
drivers/hid/uhid.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/hid/uhid.c
+++ b/drivers/hid/uhid.c
@@ -726,7 +726,7 @@ static unsigned int uhid_char_poll(struc
if (uhid->head != uhid->tail)
return POLLIN | POLLRDNORM;
- return 0;
+ return POLLOUT | POLLWRNORM;
}
static const struct file_operations uhid_fops = {
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Heikki Krogerus <[email protected]>
commit 3c3caae4cd6e122472efcf64759ff6392fb6bce2 upstream.
The original ID that was added for Comet Lake PCH was
actually for the -LP (low power) variant even though the
constant for it said CMLH. Changing that while at it.
Signed-off-by: Heikki Krogerus <[email protected]>
Acked-by: Felipe Balbi <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Greg Kroah-Hartman <[email protected]>
[bwh: Backported to 3.16:
- No properties support
- Adjust context, indentation]
Signed-off-by: Ben Hutchings <[email protected]>
---
drivers/usb/dwc3/dwc3-pci.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
--- a/drivers/usb/dwc3/dwc3-pci.c
+++ b/drivers/usb/dwc3/dwc3-pci.c
@@ -37,7 +37,8 @@
#define PCI_DEVICE_ID_INTEL_BXT_M 0x1aaa
#define PCI_DEVICE_ID_INTEL_APL 0x5aaa
#define PCI_DEVICE_ID_INTEL_KBP 0xa2b0
-#define PCI_DEVICE_ID_INTEL_CMLH 0x02ee
+#define PCI_DEVICE_ID_INTEL_CMLLP 0x02ee
+#define PCI_DEVICE_ID_INTEL_CMLH 0x06ee
#define PCI_DEVICE_ID_INTEL_GLK 0x31aa
#define PCI_DEVICE_ID_INTEL_CNPLP 0x9dee
#define PCI_DEVICE_ID_INTEL_CNPH 0xa36e
@@ -200,6 +201,7 @@ static const struct pci_device_id dwc3_p
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BSW), },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BYT), },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_MRFLD), },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_CMLLP), },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_CMLH), },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SPTLP), },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SPTH), },
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Heikki Krogerus <[email protected]>
commit 00908693c481f7298adf8cf4d2ff3dfbea8c375f upstream.
PCI IDs for Intel IceLake.
Signed-off-by: Heikki Krogerus <[email protected]>
Signed-off-by: Felipe Balbi <[email protected]>
[bwh: Backported to 3.16: adjust context, indentation]
Signed-off-by: Ben Hutchings <[email protected]>
---
drivers/usb/dwc3/dwc3-pci.c | 2 ++
1 file changed, 2 insertions(+)
--- a/drivers/usb/dwc3/dwc3-pci.c
+++ b/drivers/usb/dwc3/dwc3-pci.c
@@ -40,6 +40,7 @@
#define PCI_DEVICE_ID_INTEL_GLK 0x31aa
#define PCI_DEVICE_ID_INTEL_CNPLP 0x9dee
#define PCI_DEVICE_ID_INTEL_CNPH 0xa36e
+#define PCI_DEVICE_ID_INTEL_ICLLP 0x34ee
struct dwc3_pci {
struct device *dev;
@@ -205,6 +206,7 @@ static const struct pci_device_id dwc3_p
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_GLK), },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_CNPLP), },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_CNPH), },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICLLP), },
{ } /* Terminating Entry */
};
MODULE_DEVICE_TABLE(pci, dwc3_pci_id_table);
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Russell King <[email protected]>
commit 256efaea1fdc4e38970489197409a26125ee0aaa upstream.
gpiolib has a corner case with open drain outputs that are emulated.
When such outputs are outputting a logic 1, emulation will set the
hardware to input mode, which will cause gpiod_get_direction() to
report that it is in input mode. This is different from the behaviour
with a true open-drain output.
Unify the semantics here.
Suggested-by: Linus Walleij <[email protected]>
Signed-off-by: Russell King <[email protected]>
Signed-off-by: Bartosz Golaszewski <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
drivers/gpio/gpiolib.c | 8 ++++++++
1 file changed, 8 insertions(+)
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -273,6 +273,14 @@ int gpiod_get_direction(const struct gpi
chip = gpiod_to_chip(desc);
offset = gpio_chip_hwgpio(desc);
+ /*
+ * Open drain emulation using input mode may incorrectly report
+ * input here, fix that up.
+ */
+ if (test_bit(FLAG_OPEN_DRAIN, &desc->flags) &&
+ test_bit(FLAG_IS_OUT, &desc->flags))
+ return 0;
+
if (!chip->get_direction)
return status;
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Hou Tao <[email protected]>
commit 474e559567fa631dea8fb8407ab1b6090c903755 upstream.
We got the following warnings from thin_check during thin-pool setup:
$ thin_check /dev/vdb
examining superblock
examining devices tree
missing devices: [1, 84]
too few entries in btree_node: 41, expected at least 42 (block 138, max_entries = 126)
examining mapping tree
The phenomenon is the number of entries in one node of details_info tree is
less than (max_entries / 3). And it can be easily reproduced by the following
procedures:
$ new a thin pool
$ presume the max entries of details_info tree is 126
$ new 127 thin devices (e.g. 1~127) to make the root node being full
and then split
$ remove the first 43 (e.g. 1~43) thin devices to make the children
reblance repeatedly
$ stop the thin pool
$ thin_check
The root cause is that the B-tree removal procedure in __rebalance2()
doesn't guarantee the invariance: the minimal number of entries in
non-root node should be >= (max_entries / 3).
Simply fix the problem by increasing the rebalance threshold to
make sure the number of entries in each child will be greater
than or equal to (max_entries / 3 + 1), so no matter which
child is used for removal, the number will still be valid.
Signed-off-by: Hou Tao <[email protected]>
Acked-by: Joe Thornber <[email protected]>
Signed-off-by: Mike Snitzer <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
drivers/md/persistent-data/dm-btree-remove.c | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
--- a/drivers/md/persistent-data/dm-btree-remove.c
+++ b/drivers/md/persistent-data/dm-btree-remove.c
@@ -203,7 +203,13 @@ static void __rebalance2(struct dm_btree
struct btree_node *right = r->n;
uint32_t nr_left = le32_to_cpu(left->header.nr_entries);
uint32_t nr_right = le32_to_cpu(right->header.nr_entries);
- unsigned threshold = 2 * merge_threshold(left) + 1;
+ /*
+ * Ensure the number of entries in each child will be greater
+ * than or equal to (max_entries / 3 + 1), so no matter which
+ * child is used for removal, the number will still be not
+ * less than (max_entries / 3).
+ */
+ unsigned int threshold = 2 * (merge_threshold(left) + 1);
if (nr_left + nr_right < threshold) {
/*
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Christian Brauner <[email protected]>
commit 0b8d616fb5a8ffa307b1d3af37f55c15dae14f28 upstream.
When assiging and testing taskstats in taskstats_exit() there's a race
when setting up and reading sig->stats when a thread-group with more
than one thread exits:
write to 0xffff8881157bbe10 of 8 bytes by task 7951 on cpu 0:
taskstats_tgid_alloc kernel/taskstats.c:567 [inline]
taskstats_exit+0x6b7/0x717 kernel/taskstats.c:596
do_exit+0x2c2/0x18e0 kernel/exit.c:864
do_group_exit+0xb4/0x1c0 kernel/exit.c:983
get_signal+0x2a2/0x1320 kernel/signal.c:2734
do_signal+0x3b/0xc00 arch/x86/kernel/signal.c:815
exit_to_usermode_loop+0x250/0x2c0 arch/x86/entry/common.c:159
prepare_exit_to_usermode arch/x86/entry/common.c:194 [inline]
syscall_return_slowpath arch/x86/entry/common.c:274 [inline]
do_syscall_64+0x2d7/0x2f0 arch/x86/entry/common.c:299
entry_SYSCALL_64_after_hwframe+0x44/0xa9
read to 0xffff8881157bbe10 of 8 bytes by task 7949 on cpu 1:
taskstats_tgid_alloc kernel/taskstats.c:559 [inline]
taskstats_exit+0xb2/0x717 kernel/taskstats.c:596
do_exit+0x2c2/0x18e0 kernel/exit.c:864
do_group_exit+0xb4/0x1c0 kernel/exit.c:983
__do_sys_exit_group kernel/exit.c:994 [inline]
__se_sys_exit_group kernel/exit.c:992 [inline]
__x64_sys_exit_group+0x2e/0x30 kernel/exit.c:992
do_syscall_64+0xcf/0x2f0 arch/x86/entry/common.c:296
entry_SYSCALL_64_after_hwframe+0x44/0xa9
Fix this by using smp_load_acquire() and smp_store_release().
Reported-by: [email protected]
Fixes: 34ec12349c8a ("taskstats: cleanup ->signal->stats allocation")
Signed-off-by: Christian Brauner <[email protected]>
Acked-by: Marco Elver <[email protected]>
Reviewed-by: Will Deacon <[email protected]>
Reviewed-by: Andrea Parri <[email protected]>
Reviewed-by: Dmitry Vyukov <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Ben Hutchings <[email protected]>
---
kernel/taskstats.c | 30 +++++++++++++++++++-----------
1 file changed, 19 insertions(+), 11 deletions(-)
--- a/kernel/taskstats.c
+++ b/kernel/taskstats.c
@@ -591,25 +591,33 @@ static int taskstats_user_cmd(struct sk_
static struct taskstats *taskstats_tgid_alloc(struct task_struct *tsk)
{
struct signal_struct *sig = tsk->signal;
- struct taskstats *stats;
+ struct taskstats *stats_new, *stats;
- if (sig->stats || thread_group_empty(tsk))
- goto ret;
+ /* Pairs with smp_store_release() below. */
+ stats = smp_load_acquire(&sig->stats);
+ if (stats || thread_group_empty(tsk))
+ return stats;
/* No problem if kmem_cache_zalloc() fails */
- stats = kmem_cache_zalloc(taskstats_cache, GFP_KERNEL);
+ stats_new = kmem_cache_zalloc(taskstats_cache, GFP_KERNEL);
spin_lock_irq(&tsk->sighand->siglock);
- if (!sig->stats) {
- sig->stats = stats;
- stats = NULL;
+ stats = sig->stats;
+ if (!stats) {
+ /*
+ * Pairs with smp_store_release() above and order the
+ * kmem_cache_zalloc().
+ */
+ smp_store_release(&sig->stats, stats_new);
+ stats = stats_new;
+ stats_new = NULL;
}
spin_unlock_irq(&tsk->sighand->siglock);
- if (stats)
- kmem_cache_free(taskstats_cache, stats);
-ret:
- return sig->stats;
+ if (stats_new)
+ kmem_cache_free(taskstats_cache, stats_new);
+
+ return stats;
}
/* Send pid data out on exit */
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Dedy Lansky <[email protected]>
commit 30ca1aa536211f5ac3de0173513a7a99a98a97f3 upstream.
Make ieee80211_send_layer2_update() a common function so other drivers
can re-use it.
Signed-off-by: Dedy Lansky <[email protected]>
Signed-off-by: Johannes Berg <[email protected]>
[bwh: Backported to 3.16 as dependency of commit 3e493173b784
"mac80211: Do not send Layer 2 Update frame before authorization":
- Retain type-casting of skb_put() return value
- Adjust context]
Signed-off-by: Ben Hutchings <[email protected]>
---
include/net/cfg80211.h | 11 ++++++++++
net/mac80211/cfg.c | 48 ++----------------------------------------
net/wireless/util.c | 45 +++++++++++++++++++++++++++++++++++++++
3 files changed, 58 insertions(+), 46 deletions(-)
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -3627,6 +3627,17 @@ const u8 *cfg80211_find_vendor_ie(unsign
const u8 *ies, int len);
/**
+ * cfg80211_send_layer2_update - send layer 2 update frame
+ *
+ * @dev: network device
+ * @addr: STA MAC address
+ *
+ * Wireless drivers can use this function to update forwarding tables in bridge
+ * devices upon STA association.
+ */
+void cfg80211_send_layer2_update(struct net_device *dev, const u8 *addr);
+
+/**
* DOC: Regulatory enforcement infrastructure
*
* TODO
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -1196,50 +1196,6 @@ static int ieee80211_stop_ap(struct wiph
return 0;
}
-/* Layer 2 Update frame (802.2 Type 1 LLC XID Update response) */
-struct iapp_layer2_update {
- u8 da[ETH_ALEN]; /* broadcast */
- u8 sa[ETH_ALEN]; /* STA addr */
- __be16 len; /* 6 */
- u8 dsap; /* 0 */
- u8 ssap; /* 0 */
- u8 control;
- u8 xid_info[3];
-} __packed;
-
-static void ieee80211_send_layer2_update(struct sta_info *sta)
-{
- struct iapp_layer2_update *msg;
- struct sk_buff *skb;
-
- /* Send Level 2 Update Frame to update forwarding tables in layer 2
- * bridge devices */
-
- skb = dev_alloc_skb(sizeof(*msg));
- if (!skb)
- return;
- msg = (struct iapp_layer2_update *)skb_put(skb, sizeof(*msg));
-
- /* 802.2 Type 1 Logical Link Control (LLC) Exchange Identifier (XID)
- * Update response frame; IEEE Std 802.2-1998, 5.4.1.2.1 */
-
- eth_broadcast_addr(msg->da);
- memcpy(msg->sa, sta->sta.addr, ETH_ALEN);
- msg->len = htons(6);
- msg->dsap = 0;
- msg->ssap = 0x01; /* NULL LSAP, CR Bit: Response */
- msg->control = 0xaf; /* XID response lsb.1111F101.
- * F=0 (no poll command; unsolicited frame) */
- msg->xid_info[0] = 0x81; /* XID format identifier */
- msg->xid_info[1] = 1; /* LLC types/classes: Type 1 LLC */
- msg->xid_info[2] = 0; /* XID sender's receive window size (RW) */
-
- skb->dev = sta->sdata->dev;
- skb->protocol = eth_type_trans(skb, sta->sdata->dev);
- memset(skb->cb, 0, sizeof(skb->cb));
- netif_rx_ni(skb);
-}
-
static int sta_apply_auth_flags(struct ieee80211_local *local,
struct sta_info *sta,
u32 mask, u32 set)
@@ -1535,7 +1491,7 @@ static int ieee80211_add_station(struct
}
if (layer2_update)
- ieee80211_send_layer2_update(sta);
+ cfg80211_send_layer2_update(sta->sdata->dev, sta->sta.addr);
rcu_read_unlock();
@@ -1640,7 +1596,7 @@ static int ieee80211_change_station(stru
atomic_inc(&sta->sdata->bss->num_mcast_sta);
}
- ieee80211_send_layer2_update(sta);
+ cfg80211_send_layer2_update(sta->sdata->dev, sta->sta.addr);
}
err = sta_apply_parameters(local, sta, params);
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -1583,3 +1583,48 @@ EXPORT_SYMBOL(rfc1042_header);
const unsigned char bridge_tunnel_header[] __aligned(2) =
{ 0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8 };
EXPORT_SYMBOL(bridge_tunnel_header);
+
+/* Layer 2 Update frame (802.2 Type 1 LLC XID Update response) */
+struct iapp_layer2_update {
+ u8 da[ETH_ALEN]; /* broadcast */
+ u8 sa[ETH_ALEN]; /* STA addr */
+ __be16 len; /* 6 */
+ u8 dsap; /* 0 */
+ u8 ssap; /* 0 */
+ u8 control;
+ u8 xid_info[3];
+} __packed;
+
+void cfg80211_send_layer2_update(struct net_device *dev, const u8 *addr)
+{
+ struct iapp_layer2_update *msg;
+ struct sk_buff *skb;
+
+ /* Send Level 2 Update Frame to update forwarding tables in layer 2
+ * bridge devices */
+
+ skb = dev_alloc_skb(sizeof(*msg));
+ if (!skb)
+ return;
+ msg = (struct iapp_layer2_update *)skb_put(skb, sizeof(*msg));
+
+ /* 802.2 Type 1 Logical Link Control (LLC) Exchange Identifier (XID)
+ * Update response frame; IEEE Std 802.2-1998, 5.4.1.2.1 */
+
+ eth_broadcast_addr(msg->da);
+ ether_addr_copy(msg->sa, addr);
+ msg->len = htons(6);
+ msg->dsap = 0;
+ msg->ssap = 0x01; /* NULL LSAP, CR Bit: Response */
+ msg->control = 0xaf; /* XID response lsb.1111F101.
+ * F=0 (no poll command; unsolicited frame) */
+ msg->xid_info[0] = 0x81; /* XID format identifier */
+ msg->xid_info[1] = 1; /* LLC types/classes: Type 1 LLC */
+ msg->xid_info[2] = 0; /* XID sender's receive window size (RW) */
+
+ skb->dev = dev;
+ skb->protocol = eth_type_trans(skb, dev);
+ memset(skb->cb, 0, sizeof(skb->cb));
+ netif_rx_ni(skb);
+}
+EXPORT_SYMBOL(cfg80211_send_layer2_update);
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Mika Westerberg <[email protected]>
commit 39ce8150a079e3ae6ed9abf26d7918a558ef7c19 upstream.
There is a hardware issue in Intel Baytrail where concurrent GPIO register
access might result reads of 0xffffffff and writes might get dropped
completely.
Prevent this from happening by taking the serializing lock in all places
where it is possible that more than one thread might be accessing the
hardware concurrently.
Signed-off-by: Mika Westerberg <[email protected]>
Signed-off-by: Linus Walleij <[email protected]>
[bwh: Backported to 3.16: adjust filename]
Signed-off-by: Ben Hutchings <[email protected]>
---
drivers/pinctrl/pinctrl-baytrail.c | 21 ++++++++++++++++-----
1 file changed, 16 insertions(+), 5 deletions(-)
--- a/drivers/pinctrl/pinctrl-baytrail.c
+++ b/drivers/pinctrl/pinctrl-baytrail.c
@@ -194,6 +194,9 @@ static int byt_gpio_request(struct gpio_
struct byt_gpio *vg = to_byt_gpio(chip);
void __iomem *reg = byt_gpio_reg(chip, offset, BYT_CONF0_REG);
u32 value, gpio_mux;
+ unsigned long flags;
+
+ spin_lock_irqsave(&vg->lock, flags);
/*
* In most cases, func pin mux 000 means GPIO function.
@@ -207,18 +210,16 @@ static int byt_gpio_request(struct gpio_
value = readl(reg) & BYT_PIN_MUX;
gpio_mux = byt_get_gpio_mux(vg, offset);
if (WARN_ON(gpio_mux != value)) {
- unsigned long flags;
-
- spin_lock_irqsave(&vg->lock, flags);
value = readl(reg) & ~BYT_PIN_MUX;
value |= gpio_mux;
writel(value, reg);
- spin_unlock_irqrestore(&vg->lock, flags);
dev_warn(&vg->pdev->dev,
"pin %u forcibly re-configured as GPIO\n", offset);
}
+ spin_unlock_irqrestore(&vg->lock, flags);
+
pm_runtime_get(&vg->pdev->dev);
return 0;
@@ -266,7 +267,15 @@ static int byt_irq_type(struct irq_data
static int byt_gpio_get(struct gpio_chip *chip, unsigned offset)
{
void __iomem *reg = byt_gpio_reg(chip, offset, BYT_VAL_REG);
- return readl(reg) & BYT_LEVEL;
+ struct byt_gpio *vg = to_byt_gpio(chip);
+ unsigned long flags;
+ u32 val;
+
+ spin_lock_irqsave(&vg->lock, flags);
+ val = readl(reg);
+ spin_unlock_irqrestore(&vg->lock, flags);
+
+ return val & BYT_LEVEL;
}
static void byt_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
@@ -435,8 +444,10 @@ static void byt_irq_ack(struct irq_data
unsigned offset = irqd_to_hwirq(d);
void __iomem *reg;
+ spin_lock(&vg->lock);
reg = byt_gpio_reg(&vg->chip, offset, BYT_INT_STAT_REG);
writel(BIT(offset % 32), reg);
+ spin_unlock(&vg->lock);
}
static void byt_irq_unmask(struct irq_data *d)
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Goldwyn Rodrigues <[email protected]>
commit 7690e25302dc7d0cd42b349e746fe44b44a94f2b upstream.
One can crash dm-flakey by specifying more feature arguments than the
number of features supplied. Checking for null in arg_name avoids
this.
dmsetup create flakey-test --table "0 66076080 flakey /dev/sdb9 0 0 180 2 drop_writes"
Signed-off-by: Goldwyn Rodrigues <[email protected]>
Signed-off-by: Mike Snitzer <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
drivers/md/dm-flakey.c | 5 +++++
1 file changed, 5 insertions(+)
--- a/drivers/md/dm-flakey.c
+++ b/drivers/md/dm-flakey.c
@@ -69,6 +69,11 @@ static int parse_features(struct dm_arg_
arg_name = dm_shift_arg(as);
argc--;
+ if (!arg_name) {
+ ti->error = "Insufficient feature arguments";
+ return -EINVAL;
+ }
+
/*
* drop_writes
*/
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Alan Stern <[email protected]>
commit 8ec321e96e056de84022c032ffea253431a83c3c upstream.
The syzbot fuzzer found a slab-out-of-bounds bug in the HID report
handler. The bug was caused by a report descriptor which included a
field with size 12 bits and count 4899, for a total size of 7349
bytes.
The usbhid driver uses at most a single-page 4-KB buffer for reports.
In the test there wasn't any problem about overflowing the buffer,
since only one byte was received from the device. Rather, the bug
occurred when the HID core tried to extract the data from the report
fields, which caused it to try reading data beyond the end of the
allocated buffer.
This patch fixes the problem by rejecting any report whose total
length exceeds the HID_MAX_BUFFER_SIZE limit (minus one byte to allow
for a possible report index). In theory a device could have a report
longer than that, but if there was such a thing we wouldn't handle it
correctly anyway.
Reported-and-tested-by: [email protected]
Signed-off-by: Alan Stern <[email protected]>
Signed-off-by: Jiri Kosina <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
drivers/hid/hid-core.c | 6 ++++++
1 file changed, 6 insertions(+)
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -248,6 +248,12 @@ static int hid_add_field(struct hid_pars
offset = report->size;
report->size += parser->global.report_size * parser->global.report_count;
+ /* Total size check: Allow for possible report index byte */
+ if (report->size > (HID_MAX_BUFFER_SIZE - 1) << 3) {
+ hid_err(parser->device, "report is too long\n");
+ return -1;
+ }
+
if (!parser->local.usage_index) /* Ignore padding fields */
return 0;
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Eric Dumazet <[email protected]>
commit 5604285839aaedfb23ebe297799c6e558939334d upstream.
syzbot is kind enough to remind us we need to call skb_may_pull()
BUG: KMSAN: uninit-value in br_nf_forward_arp+0xe61/0x1230 net/bridge/br_netfilter_hooks.c:665
CPU: 1 PID: 11631 Comm: syz-executor.1 Not tainted 5.4.0-rc8-syzkaller #0
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011
Call Trace:
<IRQ>
__dump_stack lib/dump_stack.c:77 [inline]
dump_stack+0x1c9/0x220 lib/dump_stack.c:118
kmsan_report+0x128/0x220 mm/kmsan/kmsan_report.c:108
__msan_warning+0x64/0xc0 mm/kmsan/kmsan_instr.c:245
br_nf_forward_arp+0xe61/0x1230 net/bridge/br_netfilter_hooks.c:665
nf_hook_entry_hookfn include/linux/netfilter.h:135 [inline]
nf_hook_slow+0x18b/0x3f0 net/netfilter/core.c:512
nf_hook include/linux/netfilter.h:260 [inline]
NF_HOOK include/linux/netfilter.h:303 [inline]
__br_forward+0x78f/0xe30 net/bridge/br_forward.c:109
br_flood+0xef0/0xfe0 net/bridge/br_forward.c:234
br_handle_frame_finish+0x1a77/0x1c20 net/bridge/br_input.c:162
nf_hook_bridge_pre net/bridge/br_input.c:245 [inline]
br_handle_frame+0xfb6/0x1eb0 net/bridge/br_input.c:348
__netif_receive_skb_core+0x20b9/0x51a0 net/core/dev.c:4830
__netif_receive_skb_one_core net/core/dev.c:4927 [inline]
__netif_receive_skb net/core/dev.c:5043 [inline]
process_backlog+0x610/0x13c0 net/core/dev.c:5874
napi_poll net/core/dev.c:6311 [inline]
net_rx_action+0x7a6/0x1aa0 net/core/dev.c:6379
__do_softirq+0x4a1/0x83a kernel/softirq.c:293
do_softirq_own_stack+0x49/0x80 arch/x86/entry/entry_64.S:1091
</IRQ>
do_softirq kernel/softirq.c:338 [inline]
__local_bh_enable_ip+0x184/0x1d0 kernel/softirq.c:190
local_bh_enable+0x36/0x40 include/linux/bottom_half.h:32
rcu_read_unlock_bh include/linux/rcupdate.h:688 [inline]
__dev_queue_xmit+0x38e8/0x4200 net/core/dev.c:3819
dev_queue_xmit+0x4b/0x60 net/core/dev.c:3825
packet_snd net/packet/af_packet.c:2959 [inline]
packet_sendmsg+0x8234/0x9100 net/packet/af_packet.c:2984
sock_sendmsg_nosec net/socket.c:637 [inline]
sock_sendmsg net/socket.c:657 [inline]
__sys_sendto+0xc44/0xc70 net/socket.c:1952
__do_sys_sendto net/socket.c:1964 [inline]
__se_sys_sendto+0x107/0x130 net/socket.c:1960
__x64_sys_sendto+0x6e/0x90 net/socket.c:1960
do_syscall_64+0xb6/0x160 arch/x86/entry/common.c:291
entry_SYSCALL_64_after_hwframe+0x44/0xa9
RIP: 0033:0x45a679
Code: ad b6 fb ff c3 66 2e 0f 1f 84 00 00 00 00 00 66 90 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 0f 83 7b b6 fb ff c3 66 2e 0f 1f 84 00 00 00 00
RSP: 002b:00007f0a3c9e5c78 EFLAGS: 00000246 ORIG_RAX: 000000000000002c
RAX: ffffffffffffffda RBX: 0000000000000006 RCX: 000000000045a679
RDX: 000000000000000e RSI: 0000000020000200 RDI: 0000000000000003
RBP: 000000000075bf20 R08: 00000000200000c0 R09: 0000000000000014
R10: 0000000000000000 R11: 0000000000000246 R12: 00007f0a3c9e66d4
R13: 00000000004c8ec1 R14: 00000000004dfe28 R15: 00000000ffffffff
Uninit was created at:
kmsan_save_stack_with_flags mm/kmsan/kmsan.c:149 [inline]
kmsan_internal_poison_shadow+0x5c/0x110 mm/kmsan/kmsan.c:132
kmsan_slab_alloc+0x97/0x100 mm/kmsan/kmsan_hooks.c:86
slab_alloc_node mm/slub.c:2773 [inline]
__kmalloc_node_track_caller+0xe27/0x11a0 mm/slub.c:4381
__kmalloc_reserve net/core/skbuff.c:141 [inline]
__alloc_skb+0x306/0xa10 net/core/skbuff.c:209
alloc_skb include/linux/skbuff.h:1049 [inline]
alloc_skb_with_frags+0x18c/0xa80 net/core/skbuff.c:5662
sock_alloc_send_pskb+0xafd/0x10a0 net/core/sock.c:2244
packet_alloc_skb net/packet/af_packet.c:2807 [inline]
packet_snd net/packet/af_packet.c:2902 [inline]
packet_sendmsg+0x63a6/0x9100 net/packet/af_packet.c:2984
sock_sendmsg_nosec net/socket.c:637 [inline]
sock_sendmsg net/socket.c:657 [inline]
__sys_sendto+0xc44/0xc70 net/socket.c:1952
__do_sys_sendto net/socket.c:1964 [inline]
__se_sys_sendto+0x107/0x130 net/socket.c:1960
__x64_sys_sendto+0x6e/0x90 net/socket.c:1960
do_syscall_64+0xb6/0x160 arch/x86/entry/common.c:291
entry_SYSCALL_64_after_hwframe+0x44/0xa9
Fixes: c4e70a87d975 ("netfilter: bridge: rename br_netfilter.c to br_netfilter_hooks.c")
Signed-off-by: Eric Dumazet <[email protected]>
Reported-by: syzbot <[email protected]>
Reviewed-by: Florian Westphal <[email protected]>
Signed-off-by: Pablo Neira Ayuso <[email protected]>
[bwh: Backported to 3.16: adjust filename]
Signed-off-by: Ben Hutchings <[email protected]>
---
net/bridge/br_netfilter.c | 3 +++
1 file changed, 3 insertions(+)
--- a/net/bridge/br_netfilter.c
+++ b/net/bridge/br_netfilter.c
@@ -850,6 +850,9 @@ static unsigned int br_nf_forward_arp(co
nf_bridge_pull_encap_header(skb);
}
+ if (unlikely(!pskb_may_pull(skb, sizeof(struct arphdr))))
+ return NF_DROP;
+
if (arp_hdr(skb)->ar_pln != 4) {
if (IS_VLAN_ARP(skb))
nf_bridge_push_encap_header(skb);
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Geert Uytterhoeven <[email protected]>
commit d935bd50dd14a7714cbdba9a76435dbb56edb1ae upstream.
When a GPIO offset in a lookup table is out-of-range, the printed error
message (1) does not include the actual out-of-range value, and (2)
contains an off-by-one error in the upper bound.
Avoid user confusion by also printing the actual GPIO offset, and
correcting the upper bound of the range.
While at it, use "%u" for unsigned int.
Sample impact:
-requested GPIO 0 is out of range [0..32] for chip e6052000.gpio
+requested GPIO 0 (45) is out of range [0..31] for chip e6052000.gpio
Fixes: 2a3cf6a3599e9015 ("gpiolib: return -ENOENT if no GPIO mapping exists")
Signed-off-by: Geert Uytterhoeven <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Linus Walleij <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
drivers/gpio/gpiolib.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -2743,8 +2743,9 @@ static struct gpio_desc *gpiod_find(stru
if (chip->ngpio <= p->chip_hwnum) {
dev_err(dev,
- "requested GPIO %d is out of range [0..%d] for chip %s\n",
- idx, chip->ngpio, chip->label);
+ "requested GPIO %u (%u) is out of range [0..%u] for chip %s\n",
+ idx, p->chip_hwnum, chip->ngpio - 1,
+ chip->label);
return ERR_PTR(-EINVAL);
}
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Jouni Malinen <[email protected]>
commit 3e493173b7841259a08c5c8e5cbe90adb349da7e upstream.
The Layer 2 Update frame is used to update bridges when a station roams
to another AP even if that STA does not transmit any frames after the
reassociation. This behavior was described in IEEE Std 802.11F-2003 as
something that would happen based on MLME-ASSOCIATE.indication, i.e.,
before completing 4-way handshake. However, this IEEE trial-use
recommended practice document was published before RSN (IEEE Std
802.11i-2004) and as such, did not consider RSN use cases. Furthermore,
IEEE Std 802.11F-2003 was withdrawn in 2006 and as such, has not been
maintained amd should not be used anymore.
Sending out the Layer 2 Update frame immediately after association is
fine for open networks (and also when using SAE, FT protocol, or FILS
authentication when the station is actually authenticated by the time
association completes). However, it is not appropriate for cases where
RSN is used with PSK or EAP authentication since the station is actually
fully authenticated only once the 4-way handshake completes after
authentication and attackers might be able to use the unauthenticated
triggering of Layer 2 Update frame transmission to disrupt bridge
behavior.
Fix this by postponing transmission of the Layer 2 Update frame from
station entry addition to the point when the station entry is marked
authorized. Similarly, send out the VLAN binding update only if the STA
entry has already been authorized.
Signed-off-by: Jouni Malinen <[email protected]>
Reviewed-by: Johannes Berg <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
[bwh: Backported to 3.16: adjust context]
Signed-off-by: Ben Hutchings <[email protected]>
---
net/mac80211/cfg.c | 11 +++--------
net/mac80211/sta_info.c | 4 ++++
2 files changed, 7 insertions(+), 8 deletions(-)
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -1436,7 +1436,6 @@ static int ieee80211_add_station(struct
struct sta_info *sta;
struct ieee80211_sub_if_data *sdata;
int err;
- int layer2_update;
if (params->vlan) {
sdata = IEEE80211_DEV_TO_SUB_IF(params->vlan);
@@ -1481,18 +1480,12 @@ static int ieee80211_add_station(struct
if (!test_sta_flag(sta, WLAN_STA_TDLS_PEER))
rate_control_rate_init(sta);
- layer2_update = sdata->vif.type == NL80211_IFTYPE_AP_VLAN ||
- sdata->vif.type == NL80211_IFTYPE_AP;
-
err = sta_info_insert_rcu(sta);
if (err) {
rcu_read_unlock();
return err;
}
- if (layer2_update)
- cfg80211_send_layer2_update(sta->sdata->dev, sta->sta.addr);
-
rcu_read_unlock();
return 0;
@@ -1596,7 +1589,9 @@ static int ieee80211_change_station(stru
atomic_inc(&sta->sdata->bss->num_mcast_sta);
}
- cfg80211_send_layer2_update(sta->sdata->dev, sta->sta.addr);
+ if (sta->sta_state == IEEE80211_STA_AUTHORIZED)
+ cfg80211_send_layer2_update(sta->sdata->dev,
+ sta->sta.addr);
}
err = sta_apply_parameters(local, sta, params);
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -1666,6 +1666,10 @@ int sta_info_move_state(struct sta_info
atomic_inc(&sta->sdata->bss->num_mcast_sta);
set_bit(WLAN_STA_AUTHORIZED, &sta->_flags);
}
+ if (sta->sdata->vif.type == NL80211_IFTYPE_AP_VLAN ||
+ sta->sdata->vif.type == NL80211_IFTYPE_AP)
+ cfg80211_send_layer2_update(sta->sdata->dev,
+ sta->sta.addr);
break;
default:
break;
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Emiliano Ingrassia <[email protected]>
commit 1cd17f7f0def31e3695501c4f86cd3faf8489840 upstream.
Explicitly initialize URB structure urb_list field in usb_init_urb().
This field can be potentially accessed uninitialized and its
initialization is coherent with the usage of list_del_init() in
usb_hcd_unlink_urb_from_ep() and usb_giveback_urb_bh() and its
explicit initialization in usb_hcd_submit_urb() error path.
Signed-off-by: Emiliano Ingrassia <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Greg Kroah-Hartman <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
drivers/usb/core/urb.c | 1 +
1 file changed, 1 insertion(+)
--- a/drivers/usb/core/urb.c
+++ b/drivers/usb/core/urb.c
@@ -40,6 +40,7 @@ void usb_init_urb(struct urb *urb)
if (urb) {
memset(urb, 0, sizeof(*urb));
kref_init(&urb->kref);
+ INIT_LIST_HEAD(&urb->urb_list);
INIT_LIST_HEAD(&urb->anchor_list);
}
}
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Mika Westerberg <[email protected]>
commit 95f0972c7e4cbf3fc68160131c5ac2f033481d00 upstream.
If the pin is already configured as GPIO and it has any of the triggering
flags set, we may get spurious interrupts depending on the state of the
pin.
Prevent this by clearing the triggering flags on such pins. However, if the
pin is also configured as "direct IRQ" we leave the flags as is. Otherwise
it will prevent interrupts that are routed directly to IO-APIC.
Signed-off-by: Mika Westerberg <[email protected]>
Signed-off-by: Linus Walleij <[email protected]>
[bwh: Backported to 3.16:
- Add definition of BYT_DIRECT_IRQ_EN
- Adjust filename]
Signed-off-by: Ben Hutchings <[email protected]>
---
--- a/drivers/pinctrl/pinctrl-baytrail.c
+++ b/drivers/pinctrl/pinctrl-baytrail.c
@@ -44,6 +44,7 @@
/* BYT_CONF0_REG register bits */
#define BYT_IODEN BIT(31)
+#define BYT_DIRECT_IRQ_EN BIT(27)
#define BYT_TRIG_NEG BIT(26)
#define BYT_TRIG_POS BIT(25)
#define BYT_TRIG_LVL BIT(24)
@@ -160,6 +161,19 @@ static void __iomem *byt_gpio_reg(struct
return vg->reg_base + reg_offset + reg;
}
+static void byt_gpio_clear_triggering(struct byt_gpio *vg, unsigned offset)
+{
+ void __iomem *reg = byt_gpio_reg(&vg->chip, offset, BYT_CONF0_REG);
+ unsigned long flags;
+ u32 value;
+
+ spin_lock_irqsave(&vg->lock, flags);
+ value = readl(reg);
+ value &= ~(BYT_TRIG_POS | BYT_TRIG_NEG | BYT_TRIG_LVL);
+ writel(value, reg);
+ spin_unlock_irqrestore(&vg->lock, flags);
+}
+
static u32 byt_get_gpio_mux(struct byt_gpio *vg, unsigned offset)
{
/* SCORE pin 92-93 */
@@ -213,14 +227,8 @@ static int byt_gpio_request(struct gpio_
static void byt_gpio_free(struct gpio_chip *chip, unsigned offset)
{
struct byt_gpio *vg = to_byt_gpio(chip);
- void __iomem *reg = byt_gpio_reg(&vg->chip, offset, BYT_CONF0_REG);
- u32 value;
-
- /* clear interrupt triggering */
- value = readl(reg);
- value &= ~(BYT_TRIG_POS | BYT_TRIG_NEG | BYT_TRIG_LVL);
- writel(value, reg);
+ byt_gpio_clear_triggering(vg, offset);
pm_runtime_put(&vg->pdev->dev);
}
@@ -496,6 +504,21 @@ static void byt_gpio_irq_init_hw(struct
{
void __iomem *reg;
u32 base, value;
+ int i;
+
+ /*
+ * Clear interrupt triggers for all pins that are GPIOs and
+ * do not use direct IRQ mode. This will prevent spurious
+ * interrupts from misconfigured pins.
+ */
+ for (i = 0; i < vg->chip.ngpio; i++) {
+ value = readl(byt_gpio_reg(&vg->chip, i, BYT_CONF0_REG));
+ if ((value & BYT_PIN_MUX) == byt_get_gpio_mux(vg, i) &&
+ !(value & BYT_DIRECT_IRQ_EN)) {
+ byt_gpio_clear_triggering(vg, i);
+ dev_dbg(&vg->pdev->dev, "disabling GPIO %d\n", i);
+ }
+ }
/* clear interrupt status trigger registers */
for (base = 0; base < vg->chip.ngpio; base += 32) {
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Qu Wenruo <[email protected]>
commit 514c7dca85a0bf40be984dab0b477403a6db901f upstream.
A crafted btrfs image with incorrect chunk<->block group mapping will
trigger a lot of unexpected things as the mapping is essential.
Although the problem can be caught by block group item checker
added in "btrfs: tree-checker: Verify block_group_item", it's still not
sufficient. A sufficiently valid block group item can pass the check
added by the mentioned patch but could fail to match the existing chunk.
This patch will add extra block group -> chunk mapping check, to ensure
we have a completely matching (start, len, flags) chunk for each block
group at mount time.
Here we reuse the original helper find_first_block_group(), which is
already doing the basic bg -> chunk checks, adding further checks of the
start/len and type flags.
Link: https://bugzilla.kernel.org/show_bug.cgi?id=199837
Reported-by: Xu Wen <[email protected]>
Signed-off-by: Qu Wenruo <[email protected]>
Reviewed-by: Su Yue <[email protected]>
Reviewed-by: David Sterba <[email protected]>
Signed-off-by: David Sterba <[email protected]>
[bwh: Backported to 4.4: Use root->fs_info instead of fs_info]
Signed-off-by: Ben Hutchings <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
fs/btrfs/extent-tree.c | 28 +++++++++++++++++++++++++++-
1 file changed, 27 insertions(+), 1 deletion(-)
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -8556,6 +8556,8 @@ static int find_first_block_group(struct
int ret = 0;
struct btrfs_key found_key;
struct extent_buffer *leaf;
+ struct btrfs_block_group_item bg;
+ u64 flags;
int slot;
ret = btrfs_search_slot(NULL, root, key, path, 0, 0);
@@ -8590,8 +8592,32 @@ static int find_first_block_group(struct
"logical %llu len %llu found bg but no related chunk",
found_key.objectid, found_key.offset);
ret = -ENOENT;
+ } else if (em->start != found_key.objectid ||
+ em->len != found_key.offset) {
+ btrfs_err(root->fs_info,
+ "block group %llu len %llu mismatch with chunk %llu len %llu",
+ found_key.objectid, found_key.offset,
+ em->start, em->len);
+ ret = -EUCLEAN;
} else {
- ret = 0;
+ read_extent_buffer(leaf, &bg,
+ btrfs_item_ptr_offset(leaf, slot),
+ sizeof(bg));
+ flags = btrfs_block_group_flags(&bg) &
+ BTRFS_BLOCK_GROUP_TYPE_MASK;
+
+ if (flags != (em->map_lookup->type &
+ BTRFS_BLOCK_GROUP_TYPE_MASK)) {
+ btrfs_err(root->fs_info,
+"block group %llu len %llu type flags 0x%llx mismatch with chunk type flags 0x%llx",
+ found_key.objectid,
+ found_key.offset, flags,
+ (BTRFS_BLOCK_GROUP_TYPE_MASK &
+ em->map_lookup->type));
+ ret = -EUCLEAN;
+ } else {
+ ret = 0;
+ }
}
free_extent_map(em);
goto out;
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Dan Carpenter <[email protected]>
commit fee92f25777789d73e1936b91472e9c4644457c8 upstream.
On this error path we call qla4xxx_mem_free() and then the caller also
calls qla4xxx_free_adapter() which calls qla4xxx_mem_free(). It leads to a
couple double frees:
drivers/scsi/qla4xxx/ql4_os.c:8856 qla4xxx_probe_adapter() warn: 'ha->chap_dma_pool' double freed
drivers/scsi/qla4xxx/ql4_os.c:8856 qla4xxx_probe_adapter() warn: 'ha->fw_ddb_dma_pool' double freed
Fixes: afaf5a2d341d ("[SCSI] Initial Commit of qla4xxx")
Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Dan Carpenter <[email protected]>
Signed-off-by: Martin K. Petersen <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
drivers/scsi/qla4xxx/ql4_os.c | 1 -
1 file changed, 1 deletion(-)
--- a/drivers/scsi/qla4xxx/ql4_os.c
+++ b/drivers/scsi/qla4xxx/ql4_os.c
@@ -4269,7 +4269,6 @@ static int qla4xxx_mem_alloc(struct scsi
return QLA_SUCCESS;
mem_alloc_error_exit:
- qla4xxx_mem_free(ha);
return QLA_ERROR;
}
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Johan Hovold <[email protected]>
commit 74ca34118a0e05793935d804ccffcedd6eb56596 upstream.
Make sure to use the current alternate setting when verifying the
interface descriptors to avoid binding to an invalid interface.
Failing to do so could cause the driver to misbehave or trigger a WARN()
in usb_submit_urb() that kernels with panic_on_warn set would choke on.
Fixes: c2478d39076b ("staging: r8188eu: Add files for new driver - part 20")
Signed-off-by: Johan Hovold <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Greg Kroah-Hartman <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
drivers/staging/rtl8188eu/os_dep/usb_intf.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/staging/rtl8188eu/os_dep/usb_intf.c
+++ b/drivers/staging/rtl8188eu/os_dep/usb_intf.c
@@ -141,7 +141,7 @@ static struct dvobj_priv *usb_dvobj_init
phost_conf = pusbd->actconfig;
pconf_desc = &phost_conf->desc;
- phost_iface = &usb_intf->altsetting[0];
+ phost_iface = usb_intf->cur_altsetting;
piface_desc = &phost_iface->desc;
pdvobjpriv->NumInterfaces = pconf_desc->bNumInterfaces;
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Pete Zaitcev <[email protected]>
commit 19e6317d24c25ee737c65d1ffb7483bdda4bb54a upstream.
The problem arises because our read() function grabs a lock of the
circular buffer, finds something of interest, then invokes copy_to_user()
straight from the buffer, which in turn takes mm->mmap_sem. In the same
time, the callback mon_bin_vma_fault() is invoked under mm->mmap_sem.
It attempts to take the fetch lock and deadlocks.
This patch does away with protecting of our page list with any
semaphores, and instead relies on the kernel not close the device
while mmap is active in a process.
In addition, we prohibit re-sizing of a buffer while mmap is active.
This way, when (now unlocked) fault is processed, it works with the
page that is intended to be mapped-in, and not some other random page.
Note that this may have an ABI impact, but hopefully no legitimate
program is this wrong.
Signed-off-by: Pete Zaitcev <[email protected]>
Reported-by: [email protected]
Reviewed-by: Alan Stern <[email protected]>
Fixes: 46eb14a6e158 ("USB: fix usbmon BUG trigger")
Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Greg Kroah-Hartman <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
drivers/usb/mon/mon_bin.c | 32 +++++++++++++++++++++-----------
1 file changed, 21 insertions(+), 11 deletions(-)
--- a/drivers/usb/mon/mon_bin.c
+++ b/drivers/usb/mon/mon_bin.c
@@ -1034,12 +1034,18 @@ static long mon_bin_ioctl(struct file *f
mutex_lock(&rp->fetch_lock);
spin_lock_irqsave(&rp->b_lock, flags);
- mon_free_buff(rp->b_vec, rp->b_size/CHUNK_SIZE);
- kfree(rp->b_vec);
- rp->b_vec = vec;
- rp->b_size = size;
- rp->b_read = rp->b_in = rp->b_out = rp->b_cnt = 0;
- rp->cnt_lost = 0;
+ if (rp->mmap_active) {
+ mon_free_buff(vec, size/CHUNK_SIZE);
+ kfree(vec);
+ ret = -EBUSY;
+ } else {
+ mon_free_buff(rp->b_vec, rp->b_size/CHUNK_SIZE);
+ kfree(rp->b_vec);
+ rp->b_vec = vec;
+ rp->b_size = size;
+ rp->b_read = rp->b_in = rp->b_out = rp->b_cnt = 0;
+ rp->cnt_lost = 0;
+ }
spin_unlock_irqrestore(&rp->b_lock, flags);
mutex_unlock(&rp->fetch_lock);
}
@@ -1211,13 +1217,21 @@ mon_bin_poll(struct file *file, struct p
static void mon_bin_vma_open(struct vm_area_struct *vma)
{
struct mon_reader_bin *rp = vma->vm_private_data;
+ unsigned long flags;
+
+ spin_lock_irqsave(&rp->b_lock, flags);
rp->mmap_active++;
+ spin_unlock_irqrestore(&rp->b_lock, flags);
}
static void mon_bin_vma_close(struct vm_area_struct *vma)
{
+ unsigned long flags;
+
struct mon_reader_bin *rp = vma->vm_private_data;
+ spin_lock_irqsave(&rp->b_lock, flags);
rp->mmap_active--;
+ spin_unlock_irqrestore(&rp->b_lock, flags);
}
/*
@@ -1229,16 +1243,12 @@ static int mon_bin_vma_fault(struct vm_a
unsigned long offset, chunk_idx;
struct page *pageptr;
- mutex_lock(&rp->fetch_lock);
offset = vmf->pgoff << PAGE_SHIFT;
- if (offset >= rp->b_size) {
- mutex_unlock(&rp->fetch_lock);
+ if (offset >= rp->b_size)
return VM_FAULT_SIGBUS;
- }
chunk_idx = offset / CHUNK_SIZE;
pageptr = rp->b_vec[chunk_idx].pg;
get_page(pageptr);
- mutex_unlock(&rp->fetch_lock);
vmf->page = pageptr;
return 0;
}
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Mika Westerberg <[email protected]>
commit 31e4329f99062a06dca5a493bb4495a63b2dc6ba upstream.
Instead of handling everything in the driver's first level interrupt
handler, we can take advantage of already existing flow handlers that are
provided by the IRQ core.
This changes the functionality a bit also. Previously the driver looped
over pending interrupts in a single loop, restarting the loop if some
interrupt changed state. This caused problem with Lenovo Thinkpad 10
digitizer that it was not able to deassert the interrupt before the driver
disabled the interrupt for good (looplimit was exhausted).
Rework the interrupt handling logic a bit so that we provide proper mask,
ack and unmask operations in terms of Baytrail GPIO hardware and loop over
pending interrupts only once. If the interrupt remains asserted the first
level handler will be re-triggered automatically.
Signed-off-by: Mika Westerberg <[email protected]>
Signed-off-by: Linus Walleij <[email protected]>
[bwh: Backported to 3.16 as dependency of commit 39ce8150a079
"pinctrl: baytrail: Serialize all register access":
- Adjust filename, context]
Signed-off-by: Ben Hutchings <[email protected]>
---
drivers/pinctrl/pinctrl-baytrail.c | 100 +++++++++++++----------
1 file changed, 56 insertions(+), 44 deletions(-)
--- a/drivers/pinctrl/pinctrl-baytrail.c
+++ b/drivers/pinctrl/pinctrl-baytrail.c
@@ -251,23 +251,13 @@ static int byt_irq_type(struct irq_data
*/
value &= ~(BYT_TRIG_POS | BYT_TRIG_NEG | BYT_TRIG_LVL);
- switch (type) {
- case IRQ_TYPE_LEVEL_HIGH:
- value |= BYT_TRIG_LVL;
- case IRQ_TYPE_EDGE_RISING:
- value |= BYT_TRIG_POS;
- break;
- case IRQ_TYPE_LEVEL_LOW:
- value |= BYT_TRIG_LVL;
- case IRQ_TYPE_EDGE_FALLING:
- value |= BYT_TRIG_NEG;
- break;
- case IRQ_TYPE_EDGE_BOTH:
- value |= (BYT_TRIG_NEG | BYT_TRIG_POS);
- break;
- }
writel(value, reg);
+ if (type & IRQ_TYPE_EDGE_BOTH)
+ __irq_set_handler_locked(d->irq, handle_edge_irq);
+ else if (type & IRQ_TYPE_LEVEL_MASK)
+ __irq_set_handler_locked(d->irq, handle_level_irq);
+
spin_unlock_irqrestore(&vg->lock, flags);
return 0;
@@ -421,54 +411,75 @@ static void byt_gpio_irq_handler(unsigne
struct irq_data *data = irq_desc_get_irq_data(desc);
struct byt_gpio *vg = irq_data_get_irq_handler_data(data);
struct irq_chip *chip = irq_data_get_irq_chip(data);
- u32 base, pin, mask;
+ u32 base, pin;
void __iomem *reg;
- u32 pending;
+ unsigned long pending;
unsigned virq;
- int looplimit = 0;
/* check from GPIO controller which pin triggered the interrupt */
for (base = 0; base < vg->chip.ngpio; base += 32) {
-
reg = byt_gpio_reg(&vg->chip, base, BYT_INT_STAT_REG);
-
- while ((pending = readl(reg))) {
- pin = __ffs(pending);
- mask = BIT(pin);
- /* Clear before handling so we can't lose an edge */
- writel(mask, reg);
-
+ pending = readl(reg);
+ for_each_set_bit(pin, &pending, 32) {
virq = irq_find_mapping(vg->domain, base + pin);
generic_handle_irq(virq);
-
- /* In case bios or user sets triggering incorretly a pin
- * might remain in "interrupt triggered" state.
- */
- if (looplimit++ > 32) {
- dev_err(&vg->pdev->dev,
- "Gpio %d interrupt flood, disabling\n",
- base + pin);
-
- reg = byt_gpio_reg(&vg->chip, base + pin,
- BYT_CONF0_REG);
- mask = readl(reg);
- mask &= ~(BYT_TRIG_NEG | BYT_TRIG_POS |
- BYT_TRIG_LVL);
- writel(mask, reg);
- mask = readl(reg); /* flush */
- break;
- }
}
}
chip->irq_eoi(data);
}
+static void byt_irq_ack(struct irq_data *d)
+{
+ struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+ struct byt_gpio *vg = to_byt_gpio(gc);
+ unsigned offset = irqd_to_hwirq(d);
+ void __iomem *reg;
+
+ reg = byt_gpio_reg(&vg->chip, offset, BYT_INT_STAT_REG);
+ writel(BIT(offset % 32), reg);
+}
+
static void byt_irq_unmask(struct irq_data *d)
{
+ struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+ struct byt_gpio *vg = to_byt_gpio(gc);
+ unsigned offset = irqd_to_hwirq(d);
+ unsigned long flags;
+ void __iomem *reg;
+ u32 value;
+
+ spin_lock_irqsave(&vg->lock, flags);
+
+ reg = byt_gpio_reg(&vg->chip, offset, BYT_CONF0_REG);
+ value = readl(reg);
+
+ switch (irqd_get_trigger_type(d)) {
+ case IRQ_TYPE_LEVEL_HIGH:
+ value |= BYT_TRIG_LVL;
+ case IRQ_TYPE_EDGE_RISING:
+ value |= BYT_TRIG_POS;
+ break;
+ case IRQ_TYPE_LEVEL_LOW:
+ value |= BYT_TRIG_LVL;
+ case IRQ_TYPE_EDGE_FALLING:
+ value |= BYT_TRIG_NEG;
+ break;
+ case IRQ_TYPE_EDGE_BOTH:
+ value |= (BYT_TRIG_NEG | BYT_TRIG_POS);
+ break;
+ }
+
+ writel(value, reg);
+
+ spin_unlock_irqrestore(&vg->lock, flags);
}
static void byt_irq_mask(struct irq_data *d)
{
+ struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+ struct byt_gpio *vg = to_byt_gpio(gc);
+
+ byt_gpio_clear_triggering(vg, irqd_to_hwirq(d));
}
static int byt_irq_reqres(struct irq_data *d)
@@ -493,6 +504,7 @@ static void byt_irq_relres(struct irq_da
static struct irq_chip byt_irqchip = {
.name = "BYT-GPIO",
+ .irq_ack = byt_irq_ack,
.irq_mask = byt_irq_mask,
.irq_unmask = byt_irq_unmask,
.irq_set_type = byt_irq_type,
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Johan Hovold <[email protected]>
commit 84f60ca7b326ed8c08582417493982fe2573a9ad upstream.
The driver failed to initialise its receive-buffer pointer, something
which could lead to an illegal free on late probe errors.
Fix this by making sure to clear all driver data at allocation.
Fixes: 2032e2c2309d ("usb_gigaset: code cleanup")
Cc: Tilman Schmidt <[email protected]>
Signed-off-by: Johan Hovold <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Greg Kroah-Hartman <[email protected]>
[bwh: Backported to 3.16: adjust filename]
Signed-off-by: Ben Hutchings <[email protected]>
---
drivers/isdn/gigaset/usb-gigaset.c | 6 +-----
1 file changed, 1 insertion(+), 5 deletions(-)
--- a/drivers/isdn/gigaset/usb-gigaset.c
+++ b/drivers/isdn/gigaset/usb-gigaset.c
@@ -578,8 +578,7 @@ static int gigaset_initcshw(struct cards
{
struct usb_cardstate *ucs;
- cs->hw.usb = ucs =
- kmalloc(sizeof(struct usb_cardstate), GFP_KERNEL);
+ cs->hw.usb = ucs = kzalloc(sizeof(struct usb_cardstate), GFP_KERNEL);
if (!ucs) {
pr_err("out of memory\n");
return -ENOMEM;
@@ -591,9 +590,6 @@ static int gigaset_initcshw(struct cards
ucs->bchars[3] = 0;
ucs->bchars[4] = 0x11;
ucs->bchars[5] = 0x13;
- ucs->bulk_out_buffer = NULL;
- ucs->bulk_out_urb = NULL;
- ucs->read_urb = NULL;
tasklet_init(&cs->write_tasklet,
gigaset_modem_fill, (unsigned long) cs);
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: "Rafael J. Wysocki" <[email protected]>
commit b9ea0bae260f6aae546db224daa6ac1bd9d94b91 upstream.
Certain ACPI-enumerated devices represented as platform devices in
Linux, like fans, require special low-level power management handling
implemented by their drivers that is not in agreement with the ACPI
PM domain behavior. That leads to problems with managing ACPI fans
during system-wide suspend and resume.
For this reason, make acpi_dev_pm_attach() skip the affected devices
by adding a list of device IDs to avoid to it and putting the IDs of
the affected devices into that list.
Fixes: e5cc8ef31267 (ACPI / PM: Provide ACPI PM callback routines for subsystems)
Reported-by: Zhang Rui <[email protected]>
Tested-by: Todd Brandt <[email protected]>
Signed-off-by: Rafael J. Wysocki <[email protected]>
[bwh: Backported to 3.16: adjust context]
Signed-off-by: Ben Hutchings <[email protected]>
---
drivers/acpi/device_pm.c | 12 +++++++++++-
1 file changed, 11 insertions(+), 1 deletion(-)
--- a/drivers/acpi/device_pm.c
+++ b/drivers/acpi/device_pm.c
@@ -1041,9 +1041,19 @@ static struct dev_pm_domain acpi_general
*/
int acpi_dev_pm_attach(struct device *dev, bool power_on)
{
+ /*
+ * Skip devices whose ACPI companions match the device IDs below,
+ * because they require special power management handling incompatible
+ * with the generic ACPI PM domain.
+ */
+ static const struct acpi_device_id special_pm_ids[] = {
+ {"PNP0C0B", }, /* Generic ACPI fan */
+ {"INT3404", }, /* Fan */
+ {}
+ };
struct acpi_device *adev = ACPI_COMPANION(dev);
- if (!adev)
+ if (!adev || !acpi_match_device_ids(adev, special_pm_ids))
return -ENODEV;
if (dev->pm_domain)
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Mao Wenan <[email protected]>
commit b43d1f9f7067c6759b1051e8ecb84e82cef569fe upstream.
There is softlockup when using TPACKET_V3:
...
NMI watchdog: BUG: soft lockup - CPU#2 stuck for 60010ms!
(__irq_svc) from [<c0558a0c>] (_raw_spin_unlock_irqrestore+0x44/0x54)
(_raw_spin_unlock_irqrestore) from [<c027b7e8>] (mod_timer+0x210/0x25c)
(mod_timer) from [<c0549c30>]
(prb_retire_rx_blk_timer_expired+0x68/0x11c)
(prb_retire_rx_blk_timer_expired) from [<c027a7ac>]
(call_timer_fn+0x90/0x17c)
(call_timer_fn) from [<c027ab6c>] (run_timer_softirq+0x2d4/0x2fc)
(run_timer_softirq) from [<c021eaf4>] (__do_softirq+0x218/0x318)
(__do_softirq) from [<c021eea0>] (irq_exit+0x88/0xac)
(irq_exit) from [<c0240130>] (msa_irq_exit+0x11c/0x1d4)
(msa_irq_exit) from [<c0209cf0>] (handle_IPI+0x650/0x7f4)
(handle_IPI) from [<c02015bc>] (gic_handle_irq+0x108/0x118)
(gic_handle_irq) from [<c0558ee4>] (__irq_usr+0x44/0x5c)
...
If __ethtool_get_link_ksettings() is failed in
prb_calc_retire_blk_tmo(), msec and tmo will be zero, so tov_in_jiffies
is zero and the timer expire for retire_blk_timer is turn to
mod_timer(&pkc->retire_blk_timer, jiffies + 0),
which will trigger cpu usage of softirq is 100%.
Fixes: f6fb8f100b80 ("af-packet: TPACKET_V3 flexible buffer implementation.")
Tested-by: Xiao Jiangfeng <[email protected]>
Signed-off-by: Mao Wenan <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
net/packet/af_packet.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -608,7 +608,8 @@ static int prb_calc_retire_blk_tmo(struc
msec = 1;
div = speed / 1000;
}
- }
+ } else
+ return DEFAULT_PRB_RETIRE_TOV;
mbits = (blk_size_in_bytes * 8) / (1024 * 1024);
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Shaokun Zhang <[email protected]>
commit 761333f2f50ccc887aa9957ae829300262c0d15b upstream.
block_group_err shows the group system as a decimal value with a '0x'
prefix, which is somewhat misleading.
Fix it to print hexadecimal, as was intended.
Fixes: fce466eab7ac6 ("btrfs: tree-checker: Verify block_group_item")
Reviewed-by: Nikolay Borisov <[email protected]>
Reviewed-by: Qu Wenruo <[email protected]>
Signed-off-by: Shaokun Zhang <[email protected]>
Reviewed-by: David Sterba <[email protected]>
Signed-off-by: David Sterba <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
fs/btrfs/tree-checker.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/fs/btrfs/tree-checker.c
+++ b/fs/btrfs/tree-checker.c
@@ -399,7 +399,7 @@ static int check_block_group_item(struct
type != (BTRFS_BLOCK_GROUP_METADATA |
BTRFS_BLOCK_GROUP_DATA)) {
block_group_err(fs_info, leaf, slot,
-"invalid type, have 0x%llx (%lu bits set) expect either 0x%llx, 0x%llx, 0x%llu or 0x%llx",
+"invalid type, have 0x%llx (%lu bits set) expect either 0x%llx, 0x%llx, 0x%llx or 0x%llx",
type, hweight64(type),
BTRFS_BLOCK_GROUP_DATA, BTRFS_BLOCK_GROUP_METADATA,
BTRFS_BLOCK_GROUP_SYSTEM,
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Qu Wenruo <[email protected]>
commit 7ef49515fa6727cb4b6f2f5b0ffbc5fc20a9f8c6 upstream.
If a crafted image has missing block group items, it could cause
unexpected behavior and breaks the assumption of 1:1 chunk<->block group
mapping.
Although we have the block group -> chunk mapping check, we still need
chunk -> block group mapping check.
This patch will do extra check to ensure each chunk has its
corresponding block group.
Link: https://bugzilla.kernel.org/show_bug.cgi?id=199847
Reported-by: Xu Wen <[email protected]>
Signed-off-by: Qu Wenruo <[email protected]>
Reviewed-by: Gu Jinxiang <[email protected]>
Reviewed-by: David Sterba <[email protected]>
Signed-off-by: David Sterba <[email protected]>
[bwh: Backported to 4.4: adjust context]
Signed-off-by: Ben Hutchings <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
fs/btrfs/extent-tree.c | 58 +++++++++++++++++++++++++++++++++++++++++-
1 file changed, 57 insertions(+), 1 deletion(-)
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -8819,6 +8819,62 @@ btrfs_create_block_group_cache(struct bt
return cache;
}
+
+/*
+ * Iterate all chunks and verify that each of them has the corresponding block
+ * group
+ */
+static int check_chunk_block_group_mappings(struct btrfs_fs_info *fs_info)
+{
+ struct btrfs_mapping_tree *map_tree = &fs_info->mapping_tree;
+ struct extent_map *em;
+ struct btrfs_block_group_cache *bg;
+ u64 start = 0;
+ int ret = 0;
+
+ while (1) {
+ read_lock(&map_tree->map_tree.lock);
+ /*
+ * lookup_extent_mapping will return the first extent map
+ * intersecting the range, so setting @len to 1 is enough to
+ * get the first chunk.
+ */
+ em = lookup_extent_mapping(&map_tree->map_tree, start, 1);
+ read_unlock(&map_tree->map_tree.lock);
+ if (!em)
+ break;
+
+ bg = btrfs_lookup_block_group(fs_info, em->start);
+ if (!bg) {
+ btrfs_err(fs_info,
+ "chunk start=%llu len=%llu doesn't have corresponding block group",
+ em->start, em->len);
+ ret = -EUCLEAN;
+ free_extent_map(em);
+ break;
+ }
+ if (bg->key.objectid != em->start ||
+ bg->key.offset != em->len ||
+ (bg->flags & BTRFS_BLOCK_GROUP_TYPE_MASK) !=
+ (em->map_lookup->type & BTRFS_BLOCK_GROUP_TYPE_MASK)) {
+ btrfs_err(fs_info,
+"chunk start=%llu len=%llu flags=0x%llx doesn't match block group start=%llu len=%llu flags=0x%llx",
+ em->start, em->len,
+ em->map_lookup->type & BTRFS_BLOCK_GROUP_TYPE_MASK,
+ bg->key.objectid, bg->key.offset,
+ bg->flags & BTRFS_BLOCK_GROUP_TYPE_MASK);
+ ret = -EUCLEAN;
+ free_extent_map(em);
+ btrfs_put_block_group(bg);
+ break;
+ }
+ start = em->start + em->len;
+ free_extent_map(em);
+ btrfs_put_block_group(bg);
+ }
+ return ret;
+}
+
int btrfs_read_block_groups(struct btrfs_root *root)
{
struct btrfs_path *path;
@@ -8981,7 +9037,7 @@ int btrfs_read_block_groups(struct btrfs
}
init_global_block_rsv(info);
- ret = 0;
+ ret = check_chunk_block_group_mappings(info);
error:
btrfs_free_path(path);
return ret;
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Hans de Goede <[email protected]>
commit 40ecab551232972a39cdd8b6f17ede54a3fdb296 upstream.
Commit 39ce8150a079 ("pinctrl: baytrail: Serialize all register access")
added a spinlock around all register accesses because:
"There is a hardware issue in Intel Baytrail where concurrent GPIO register
access might result reads of 0xffffffff and writes might get dropped
completely."
Testing has shown that this does not catch all cases, there are still
2 problems remaining
1) The original fix uses a spinlock per byt_gpio device / struct,
additional testing has shown that this is not sufficient concurent
accesses to 2 different GPIO banks also suffer from the same problem.
This commit fixes this by moving to a single global lock.
2) The original fix did not add a lock around the register accesses in
the suspend/resume handling.
Since pinctrl-baytrail.c is using normal suspend/resume handlers,
interrupts are still enabled during suspend/resume handling. Nothing
should be using the GPIOs when they are being taken down, _but_ the
GPIOs themselves may still cause interrupts, which are likely to
use (read) the triggering GPIO. So we need to protect against
concurrent GPIO register accesses in the suspend/resume handlers too.
This commit fixes this by adding the missing spin_lock / unlock calls.
The 2 fixes together fix the Acer Switch 10 SW5-012 getting completely
confused after a suspend resume. The DSDT for this device has a bug
in its _LID method which reprograms the home and power button trigger-
flags requesting both high and low _level_ interrupts so the IRQs for
these 2 GPIOs continuously fire. This combined with the saving of
registers during suspend, triggers concurrent GPIO register accesses
resulting in saving 0xffffffff as pconf0 value during suspend and then
when restoring this on resume the pinmux settings get all messed up,
resulting in various I2C busses being stuck, the wifi no longer working
and often the tablet simply not coming out of suspend at all.
Fixes: 39ce8150a079 ("pinctrl: baytrail: Serialize all register access")
Signed-off-by: Hans de Goede <[email protected]>
Acked-by: Mika Westerberg <[email protected]>
Signed-off-by: Andy Shevchenko <[email protected]>
[bwh: Backported to 3.16:
- Drop changes in functions that don't exist here
- Delete local pointers to byt_gpio that become unused
- Adjust filename, context]
Signed-off-by: Ben Hutchings <[email protected]>
---
--- a/drivers/pinctrl/pinctrl-baytrail.c
+++ b/drivers/pinctrl/pinctrl-baytrail.c
@@ -140,13 +140,14 @@ struct byt_gpio {
struct gpio_chip chip;
struct irq_domain *domain;
struct platform_device *pdev;
- spinlock_t lock;
void __iomem *reg_base;
struct pinctrl_gpio_range *range;
};
#define to_byt_gpio(c) container_of(c, struct byt_gpio, chip)
+static DEFINE_RAW_SPINLOCK(byt_lock);
+
static void __iomem *byt_gpio_reg(struct gpio_chip *chip, unsigned offset,
int reg)
{
@@ -167,11 +168,11 @@ static void byt_gpio_clear_triggering(st
unsigned long flags;
u32 value;
- spin_lock_irqsave(&vg->lock, flags);
+ raw_spin_lock_irqsave(&byt_lock, flags);
value = readl(reg);
value &= ~(BYT_TRIG_POS | BYT_TRIG_NEG | BYT_TRIG_LVL);
writel(value, reg);
- spin_unlock_irqrestore(&vg->lock, flags);
+ raw_spin_unlock_irqrestore(&byt_lock, flags);
}
static u32 byt_get_gpio_mux(struct byt_gpio *vg, unsigned offset)
@@ -196,7 +197,7 @@ static int byt_gpio_request(struct gpio_
u32 value, gpio_mux;
unsigned long flags;
- spin_lock_irqsave(&vg->lock, flags);
+ raw_spin_lock_irqsave(&byt_lock, flags);
/*
* In most cases, func pin mux 000 means GPIO function.
@@ -218,7 +219,7 @@ static int byt_gpio_request(struct gpio_
"pin %u forcibly re-configured as GPIO\n", offset);
}
- spin_unlock_irqrestore(&vg->lock, flags);
+ raw_spin_unlock_irqrestore(&byt_lock, flags);
pm_runtime_get(&vg->pdev->dev);
@@ -244,7 +245,7 @@ static int byt_irq_type(struct irq_data
if (offset >= vg->chip.ngpio)
return -EINVAL;
- spin_lock_irqsave(&vg->lock, flags);
+ raw_spin_lock_irqsave(&byt_lock, flags);
value = readl(reg);
/* For level trigges the BYT_TRIG_POS and BYT_TRIG_NEG bits
@@ -259,7 +260,7 @@ static int byt_irq_type(struct irq_data
else if (type & IRQ_TYPE_LEVEL_MASK)
__irq_set_handler_locked(d->irq, handle_level_irq);
- spin_unlock_irqrestore(&vg->lock, flags);
+ raw_spin_unlock_irqrestore(&byt_lock, flags);
return 0;
}
@@ -267,25 +268,23 @@ static int byt_irq_type(struct irq_data
static int byt_gpio_get(struct gpio_chip *chip, unsigned offset)
{
void __iomem *reg = byt_gpio_reg(chip, offset, BYT_VAL_REG);
- struct byt_gpio *vg = to_byt_gpio(chip);
unsigned long flags;
u32 val;
- spin_lock_irqsave(&vg->lock, flags);
+ raw_spin_lock_irqsave(&byt_lock, flags);
val = readl(reg);
- spin_unlock_irqrestore(&vg->lock, flags);
+ raw_spin_unlock_irqrestore(&byt_lock, flags);
return val & BYT_LEVEL;
}
static void byt_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
{
- struct byt_gpio *vg = to_byt_gpio(chip);
void __iomem *reg = byt_gpio_reg(chip, offset, BYT_VAL_REG);
unsigned long flags;
u32 old_val;
- spin_lock_irqsave(&vg->lock, flags);
+ raw_spin_lock_irqsave(&byt_lock, flags);
old_val = readl(reg);
@@ -294,23 +293,22 @@ static void byt_gpio_set(struct gpio_chi
else
writel(old_val & ~BYT_LEVEL, reg);
- spin_unlock_irqrestore(&vg->lock, flags);
+ raw_spin_unlock_irqrestore(&byt_lock, flags);
}
static int byt_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
{
- struct byt_gpio *vg = to_byt_gpio(chip);
void __iomem *reg = byt_gpio_reg(chip, offset, BYT_VAL_REG);
unsigned long flags;
u32 value;
- spin_lock_irqsave(&vg->lock, flags);
+ raw_spin_lock_irqsave(&byt_lock, flags);
value = readl(reg) | BYT_DIR_MASK;
value &= ~BYT_INPUT_EN; /* active low */
writel(value, reg);
- spin_unlock_irqrestore(&vg->lock, flags);
+ raw_spin_unlock_irqrestore(&byt_lock, flags);
return 0;
}
@@ -318,12 +316,11 @@ static int byt_gpio_direction_input(stru
static int byt_gpio_direction_output(struct gpio_chip *chip,
unsigned gpio, int value)
{
- struct byt_gpio *vg = to_byt_gpio(chip);
void __iomem *reg = byt_gpio_reg(chip, gpio, BYT_VAL_REG);
unsigned long flags;
u32 reg_val;
- spin_lock_irqsave(&vg->lock, flags);
+ raw_spin_lock_irqsave(&byt_lock, flags);
reg_val = readl(reg) | BYT_DIR_MASK;
reg_val &= ~(BYT_OUTPUT_EN | BYT_INPUT_EN);
@@ -333,7 +330,7 @@ static int byt_gpio_direction_output(str
else
writel(reg_val & ~BYT_LEVEL, reg);
- spin_unlock_irqrestore(&vg->lock, flags);
+ raw_spin_unlock_irqrestore(&byt_lock, flags);
return 0;
}
@@ -345,7 +342,7 @@ static void byt_gpio_dbg_show(struct seq
unsigned long flags;
u32 conf0, val, offs;
- spin_lock_irqsave(&vg->lock, flags);
+ raw_spin_lock_irqsave(&byt_lock, flags);
for (i = 0; i < vg->chip.ngpio; i++) {
const char *pull_str = NULL;
@@ -406,7 +403,7 @@ static void byt_gpio_dbg_show(struct seq
seq_puts(s, "\n");
}
- spin_unlock_irqrestore(&vg->lock, flags);
+ raw_spin_unlock_irqrestore(&byt_lock, flags);
}
static int byt_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
@@ -444,10 +441,10 @@ static void byt_irq_ack(struct irq_data
unsigned offset = irqd_to_hwirq(d);
void __iomem *reg;
- spin_lock(&vg->lock);
+ raw_spin_lock(&byt_lock);
reg = byt_gpio_reg(&vg->chip, offset, BYT_INT_STAT_REG);
writel(BIT(offset % 32), reg);
- spin_unlock(&vg->lock);
+ raw_spin_unlock(&byt_lock);
}
static void byt_irq_unmask(struct irq_data *d)
@@ -459,7 +456,7 @@ static void byt_irq_unmask(struct irq_da
void __iomem *reg;
u32 value;
- spin_lock_irqsave(&vg->lock, flags);
+ raw_spin_lock_irqsave(&byt_lock, flags);
reg = byt_gpio_reg(&vg->chip, offset, BYT_CONF0_REG);
value = readl(reg);
@@ -482,7 +479,7 @@ static void byt_irq_unmask(struct irq_da
writel(value, reg);
- spin_unlock_irqrestore(&vg->lock, flags);
+ raw_spin_unlock_irqrestore(&byt_lock, flags);
}
static void byt_irq_mask(struct irq_data *d)
@@ -613,8 +610,6 @@ static int byt_gpio_probe(struct platfor
if (IS_ERR(vg->reg_base))
return PTR_ERR(vg->reg_base);
- spin_lock_init(&vg->lock);
-
gc = &vg->chip;
gc->label = dev_name(&pdev->dev);
gc->owner = THIS_MODULE;
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Vivek Goyal <[email protected]>
commit e80d1c805a3b2f0ad2081369be5dc5deedd5ee59 upstream.
Some of the device mapper targets override the error code returned by
dm_get_device() and return either -EINVAL or -ENXIO. There is nothing
gained by this override. It is better to propagate the returned error
code unchanged to caller.
This work was motivated by hitting an issue where the underlying device
was busy but -EINVAL was being returned. After this change we get
-EBUSY instead and it is easier to figure out the problem.
Signed-off-by: Vivek Goyal <[email protected]>
Signed-off-by: Mike Snitzer <[email protected]>
[bwh: Backported to 3.16: drop changes to dm-log-writes]
Signed-off-by: Ben Hutchings <[email protected]>
---
--- a/drivers/md/dm-crypt.c
+++ b/drivers/md/dm-crypt.c
@@ -1762,11 +1762,13 @@ static int crypt_ctr(struct dm_target *t
}
cc->iv_offset = tmpll;
- if (dm_get_device(ti, argv[3], dm_table_get_mode(ti->table), &cc->dev)) {
+ ret = dm_get_device(ti, argv[3], dm_table_get_mode(ti->table), &cc->dev);
+ if (ret) {
ti->error = "Device lookup failed";
goto bad;
}
+ ret = -EINVAL;
if (sscanf(argv[4], "%llu%c", &tmpll, &dummy) != 1) {
ti->error = "Invalid device sector";
goto bad;
--- a/drivers/md/dm-delay.c
+++ b/drivers/md/dm-delay.c
@@ -129,6 +129,7 @@ static int delay_ctr(struct dm_target *t
struct delay_c *dc;
unsigned long long tmpll;
char dummy;
+ int ret;
if (argc != 3 && argc != 6) {
ti->error = "requires exactly 3 or 6 arguments";
@@ -143,6 +144,7 @@ static int delay_ctr(struct dm_target *t
dc->reads = dc->writes = 0;
+ ret = -EINVAL;
if (sscanf(argv[1], "%llu%c", &tmpll, &dummy) != 1) {
ti->error = "Invalid device sector";
goto bad;
@@ -154,12 +156,14 @@ static int delay_ctr(struct dm_target *t
goto bad;
}
- if (dm_get_device(ti, argv[0], dm_table_get_mode(ti->table),
- &dc->dev_read)) {
+ ret = dm_get_device(ti, argv[0], dm_table_get_mode(ti->table),
+ &dc->dev_read);
+ if (ret) {
ti->error = "Device lookup failed";
goto bad;
}
+ ret = -EINVAL;
dc->dev_write = NULL;
if (argc == 3)
goto out;
@@ -175,13 +179,15 @@ static int delay_ctr(struct dm_target *t
goto bad_dev_read;
}
- if (dm_get_device(ti, argv[3], dm_table_get_mode(ti->table),
- &dc->dev_write)) {
+ ret = dm_get_device(ti, argv[3], dm_table_get_mode(ti->table),
+ &dc->dev_write);
+ if (ret) {
ti->error = "Write device lookup failed";
goto bad_dev_read;
}
out:
+ ret = -EINVAL;
dc->kdelayd_wq = alloc_workqueue("kdelayd", WQ_MEM_RECLAIM, 0);
if (!dc->kdelayd_wq) {
DMERR("Couldn't start kdelayd");
@@ -208,7 +214,7 @@ bad_dev_read:
dm_put_device(ti, dc->dev_read);
bad:
kfree(dc);
- return -EINVAL;
+ return ret;
}
static void delay_dtr(struct dm_target *ti)
--- a/drivers/md/dm-flakey.c
+++ b/drivers/md/dm-flakey.c
@@ -183,6 +183,7 @@ static int flakey_ctr(struct dm_target *
devname = dm_shift_arg(&as);
+ r = -EINVAL;
if (sscanf(dm_shift_arg(&as), "%llu%c", &tmpll, &dummy) != 1) {
ti->error = "Invalid device sector";
goto bad;
@@ -211,7 +212,8 @@ static int flakey_ctr(struct dm_target *
if (r)
goto bad;
- if (dm_get_device(ti, devname, dm_table_get_mode(ti->table), &fc->dev)) {
+ r = dm_get_device(ti, devname, dm_table_get_mode(ti->table), &fc->dev);
+ if (r) {
ti->error = "Device lookup failed";
goto bad;
}
@@ -224,7 +226,7 @@ static int flakey_ctr(struct dm_target *
bad:
kfree(fc);
- return -EINVAL;
+ return r;
}
static void flakey_dtr(struct dm_target *ti)
--- a/drivers/md/dm-linear.c
+++ b/drivers/md/dm-linear.c
@@ -30,6 +30,7 @@ static int linear_ctr(struct dm_target *
struct linear_c *lc;
unsigned long long tmp;
char dummy;
+ int ret;
if (argc != 2) {
ti->error = "Invalid argument count";
@@ -42,13 +43,15 @@ static int linear_ctr(struct dm_target *
return -ENOMEM;
}
+ ret = -EINVAL;
if (sscanf(argv[1], "%llu%c", &tmp, &dummy) != 1) {
ti->error = "dm-linear: Invalid device sector";
goto bad;
}
lc->start = tmp;
- if (dm_get_device(ti, argv[0], dm_table_get_mode(ti->table), &lc->dev)) {
+ ret = dm_get_device(ti, argv[0], dm_table_get_mode(ti->table), &lc->dev);
+ if (ret) {
ti->error = "dm-linear: Device lookup failed";
goto bad;
}
@@ -61,7 +64,7 @@ static int linear_ctr(struct dm_target *
bad:
kfree(lc);
- return -EINVAL;
+ return ret;
}
static void linear_dtr(struct dm_target *ti)
--- a/drivers/md/dm-raid1.c
+++ b/drivers/md/dm-raid1.c
@@ -923,16 +923,18 @@ static int get_mirror(struct mirror_set
{
unsigned long long offset;
char dummy;
+ int ret;
if (sscanf(argv[1], "%llu%c", &offset, &dummy) != 1) {
ti->error = "Invalid offset";
return -EINVAL;
}
- if (dm_get_device(ti, argv[0], dm_table_get_mode(ti->table),
- &ms->mirror[mirror].dev)) {
+ ret = dm_get_device(ti, argv[0], dm_table_get_mode(ti->table),
+ &ms->mirror[mirror].dev);
+ if (ret) {
ti->error = "Device lookup failure";
- return -ENXIO;
+ return ret;
}
ms->mirror[mirror].ms = ms;
--- a/drivers/md/dm-stripe.c
+++ b/drivers/md/dm-stripe.c
@@ -75,13 +75,15 @@ static int get_stripe(struct dm_target *
{
unsigned long long start;
char dummy;
+ int ret;
if (sscanf(argv[1], "%llu%c", &start, &dummy) != 1)
return -EINVAL;
- if (dm_get_device(ti, argv[0], dm_table_get_mode(ti->table),
- &sc->stripe[stripe].dev))
- return -ENXIO;
+ ret = dm_get_device(ti, argv[0], dm_table_get_mode(ti->table),
+ &sc->stripe[stripe].dev);
+ if (ret)
+ return ret;
sc->stripe[stripe].physical_start = start;
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Eric Dumazet <[email protected]>
commit 9e99bfefdbce2e23ef37487a3bcb4adf90a791d1 upstream.
1) syzbot reported an uninit-value in bond_neigh_setup() [1]
bond_neigh_setup() uses a temporary on-stack 'struct neigh_parms parms',
but only clears parms.neigh_setup field.
A stacked bonding device would then enter bond_neigh_setup()
and read garbage from parms->dev.
If we get really unlucky and garbage is matching @dev, then we
could recurse and eventually crash.
Let's make sure the whole structure is cleared to avoid surprises.
2) bond_neigh_setup() can be called while another cpu manipulates
the master device, removing or adding a slave.
We need at least rcu protection to prevent use-after-free.
Note: Prior code does not support a stack of bonding devices,
this patch does not attempt to fix this, and leave a comment instead.
[1]
BUG: KMSAN: uninit-value in bond_neigh_setup+0xa4/0x110 drivers/net/bonding/bond_main.c:3655
CPU: 0 PID: 11256 Comm: syz-executor.0 Not tainted 5.4.0-rc8-syzkaller #0
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011
Call Trace:
<IRQ>
__dump_stack lib/dump_stack.c:77 [inline]
dump_stack+0x1c9/0x220 lib/dump_stack.c:118
kmsan_report+0x128/0x220 mm/kmsan/kmsan_report.c:108
__msan_warning+0x57/0xa0 mm/kmsan/kmsan_instr.c:245
bond_neigh_setup+0xa4/0x110 drivers/net/bonding/bond_main.c:3655
bond_neigh_init+0x216/0x4b0 drivers/net/bonding/bond_main.c:3626
___neigh_create+0x169e/0x2c40 net/core/neighbour.c:613
__neigh_create+0xbd/0xd0 net/core/neighbour.c:674
ip6_finish_output2+0x149a/0x2670 net/ipv6/ip6_output.c:113
__ip6_finish_output+0x83d/0x8f0 net/ipv6/ip6_output.c:142
ip6_finish_output+0x2db/0x420 net/ipv6/ip6_output.c:152
NF_HOOK_COND include/linux/netfilter.h:294 [inline]
ip6_output+0x5d3/0x720 net/ipv6/ip6_output.c:175
dst_output include/net/dst.h:436 [inline]
NF_HOOK include/linux/netfilter.h:305 [inline]
mld_sendpack+0xebd/0x13d0 net/ipv6/mcast.c:1682
mld_send_cr net/ipv6/mcast.c:1978 [inline]
mld_ifc_timer_expire+0x116b/0x1680 net/ipv6/mcast.c:2477
call_timer_fn+0x232/0x530 kernel/time/timer.c:1404
expire_timers kernel/time/timer.c:1449 [inline]
__run_timers+0xd60/0x1270 kernel/time/timer.c:1773
run_timer_softirq+0x2d/0x50 kernel/time/timer.c:1786
__do_softirq+0x4a1/0x83a kernel/softirq.c:293
invoke_softirq kernel/softirq.c:375 [inline]
irq_exit+0x230/0x280 kernel/softirq.c:416
exiting_irq+0xe/0x10 arch/x86/include/asm/apic.h:536
smp_apic_timer_interrupt+0x48/0x70 arch/x86/kernel/apic/apic.c:1138
apic_timer_interrupt+0x2e/0x40 arch/x86/entry/entry_64.S:835
</IRQ>
RIP: 0010:kmsan_free_page+0x18d/0x1c0 mm/kmsan/kmsan_shadow.c:439
Code: 4c 89 ff 44 89 f6 e8 82 0d ee ff 65 ff 0d 9f 26 3b 60 65 8b 05 98 26 3b 60 85 c0 75 24 e8 5b f6 35 ff 4c 89 6d d0 ff 75 d0 9d <48> 83 c4 10 5b 41 5c 41 5d 41 5e 41 5f 5d c3 0f 0b 0f 0b 0f 0b 0f
RSP: 0018:ffffb328034af818 EFLAGS: 00000246 ORIG_RAX: ffffffffffffff13
RAX: 0000000000000000 RBX: ffffe2d7471f8360 RCX: 0000000000000000
RDX: ffffffffadea7000 RSI: 0000000000000004 RDI: ffff93496fcda104
RBP: ffffb328034af850 R08: ffff934a47e86d00 R09: ffff93496fc41900
R10: 0000000000000000 R11: 0000000000000000 R12: 0000000000000001
R13: 0000000000000246 R14: 0000000000000000 R15: ffffe2d7472225c0
free_pages_prepare mm/page_alloc.c:1138 [inline]
free_pcp_prepare mm/page_alloc.c:1230 [inline]
free_unref_page_prepare+0x1d9/0x770 mm/page_alloc.c:3025
free_unref_page mm/page_alloc.c:3074 [inline]
free_the_page mm/page_alloc.c:4832 [inline]
__free_pages+0x154/0x230 mm/page_alloc.c:4840
__vunmap+0xdac/0xf20 mm/vmalloc.c:2277
__vfree mm/vmalloc.c:2325 [inline]
vfree+0x7c/0x170 mm/vmalloc.c:2355
copy_entries_to_user net/ipv6/netfilter/ip6_tables.c:883 [inline]
get_entries net/ipv6/netfilter/ip6_tables.c:1041 [inline]
do_ip6t_get_ctl+0xfa4/0x1030 net/ipv6/netfilter/ip6_tables.c:1709
nf_sockopt net/netfilter/nf_sockopt.c:104 [inline]
nf_getsockopt+0x481/0x4e0 net/netfilter/nf_sockopt.c:122
ipv6_getsockopt+0x264/0x510 net/ipv6/ipv6_sockglue.c:1400
tcp_getsockopt+0x1c6/0x1f0 net/ipv4/tcp.c:3688
sock_common_getsockopt+0x13f/0x180 net/core/sock.c:3110
__sys_getsockopt+0x533/0x7b0 net/socket.c:2129
__do_sys_getsockopt net/socket.c:2144 [inline]
__se_sys_getsockopt+0xe1/0x100 net/socket.c:2141
__x64_sys_getsockopt+0x62/0x80 net/socket.c:2141
do_syscall_64+0xb6/0x160 arch/x86/entry/common.c:291
entry_SYSCALL_64_after_hwframe+0x44/0xa9
RIP: 0033:0x45d20a
Code: b8 34 01 00 00 0f 05 48 3d 01 f0 ff ff 0f 83 8d 8b fb ff c3 66 2e 0f 1f 84 00 00 00 00 00 66 90 49 89 ca b8 37 00 00 00 0f 05 <48> 3d 01 f0 ff ff 0f 83 6a 8b fb ff c3 66 0f 1f 84 00 00 00 00 00
RSP: 002b:0000000000a6f618 EFLAGS: 00000212 ORIG_RAX: 0000000000000037
RAX: ffffffffffffffda RBX: 0000000000a6f640 RCX: 000000000045d20a
RDX: 0000000000000041 RSI: 0000000000000029 RDI: 0000000000000003
RBP: 0000000000717cc0 R08: 0000000000a6f63c R09: 0000000000004000
R10: 0000000000a6f740 R11: 0000000000000212 R12: 0000000000000003
R13: 0000000000000000 R14: 0000000000000029 R15: 0000000000715b00
Local variable description: ----parms@bond_neigh_init
Variable was created at:
bond_neigh_init+0x8c/0x4b0 drivers/net/bonding/bond_main.c:3617
bond_neigh_init+0x8c/0x4b0 drivers/net/bonding/bond_main.c:3617
Fixes: 9918d5bf329d ("bonding: modify only neigh_parms owned by us")
Fixes: 234bcf8a499e ("net/bonding: correctly proxy slave neigh param setup ndo function")
Signed-off-by: Eric Dumazet <[email protected]>
Reported-by: syzbot <[email protected]>
Cc: Jay Vosburgh <[email protected]>
Cc: Veaceslav Falico <[email protected]>
Cc: Andy Gospodarek <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
drivers/net/bonding/bond_main.c | 31 +++++++++++++++++++++----------
1 file changed, 21 insertions(+), 10 deletions(-)
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -3421,24 +3421,35 @@ static int bond_neigh_init(struct neighb
const struct net_device_ops *slave_ops;
struct neigh_parms parms;
struct slave *slave;
- int ret;
+ int ret = 0;
- slave = bond_first_slave(bond);
+ rcu_read_lock();
+ slave = bond_first_slave_rcu(bond);
if (!slave)
- return 0;
+ goto out;
slave_ops = slave->dev->netdev_ops;
if (!slave_ops->ndo_neigh_setup)
- return 0;
+ goto out;
- parms.neigh_setup = NULL;
+ /* TODO: find another way [1] to implement this.
+ * Passing a zeroed structure is fragile,
+ * but at least we do not pass garbage.
+ *
+ * [1] One way would be that ndo_neigh_setup() never touch
+ * struct neigh_parms, but propagate the new neigh_setup()
+ * back to ___neigh_create() / neigh_parms_alloc()
+ */
+ memset(&parms, 0, sizeof(parms));
ret = slave_ops->ndo_neigh_setup(slave->dev, &parms);
- if (ret)
- return ret;
- if (!parms.neigh_setup)
- return 0;
+ if (ret)
+ goto out;
- return parms.neigh_setup(n);
+ if (parms.neigh_setup)
+ ret = parms.neigh_setup(n);
+out:
+ rcu_read_unlock();
+ return ret;
}
/*
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Mika Westerberg <[email protected]>
commit f8323b6bb2cc7d26941d4838dd4375952980a88a upstream.
Zotac ZBOX PI320, a Baytrail based mini-PC, has power button connected to a
GPIO pin and it is exposed to the operating system as Windows 8 button
array. This is implemented in Linux as a driver using gpio_keys.
However, BIOS on this particula machine forgot to mux the pin to be a GPIO
instead of native function, which results following message to be seen on
the console:
byt_gpio INT33FC:02: pin 16 cannot be used as GPIO.
This causes power button to not work as the driver was not able to request
the GPIO it needs.
So instead of completely preventing this we allow turning the pin as GPIO
but issue warning that something might be wrong.
Reported-by: Benjamin Adler <[email protected]>
Signed-off-by: Mika Westerberg <[email protected]>
Signed-off-by: Linus Walleij <[email protected]>
[bwh: Backported to 3.16: adjust filename]
Signed-off-by: Ben Hutchings <[email protected]>
---
drivers/pinctrl/pinctrl-baytrail.c | 35 +++++++++++++++---------
1 file changed, 22 insertions(+), 13 deletions(-)
--- a/drivers/pinctrl/pinctrl-baytrail.c
+++ b/drivers/pinctrl/pinctrl-baytrail.c
@@ -160,40 +160,49 @@ static void __iomem *byt_gpio_reg(struct
return vg->reg_base + reg_offset + reg;
}
-static bool is_special_pin(struct byt_gpio *vg, unsigned offset)
+static u32 byt_get_gpio_mux(struct byt_gpio *vg, unsigned offset)
{
/* SCORE pin 92-93 */
if (!strcmp(vg->range->name, BYT_SCORE_ACPI_UID) &&
offset >= 92 && offset <= 93)
- return true;
+ return 1;
/* SUS pin 11-21 */
if (!strcmp(vg->range->name, BYT_SUS_ACPI_UID) &&
offset >= 11 && offset <= 21)
- return true;
+ return 1;
- return false;
+ return 0;
}
static int byt_gpio_request(struct gpio_chip *chip, unsigned offset)
{
struct byt_gpio *vg = to_byt_gpio(chip);
void __iomem *reg = byt_gpio_reg(chip, offset, BYT_CONF0_REG);
- u32 value;
- bool special;
+ u32 value, gpio_mux;
/*
* In most cases, func pin mux 000 means GPIO function.
* But, some pins may have func pin mux 001 represents
- * GPIO function. Only allow user to export pin with
- * func pin mux preset as GPIO function by BIOS/FW.
+ * GPIO function.
+ *
+ * Because there are devices out there where some pins were not
+ * configured correctly we allow changing the mux value from
+ * request (but print out warning about that).
*/
value = readl(reg) & BYT_PIN_MUX;
- special = is_special_pin(vg, offset);
- if ((special && value != 1) || (!special && value)) {
- dev_err(&vg->pdev->dev,
- "pin %u cannot be used as GPIO.\n", offset);
- return -EINVAL;
+ gpio_mux = byt_get_gpio_mux(vg, offset);
+ if (WARN_ON(gpio_mux != value)) {
+ unsigned long flags;
+
+ spin_lock_irqsave(&vg->lock, flags);
+ value = readl(reg) & ~BYT_PIN_MUX;
+ value |= gpio_mux;
+ writel(value, reg);
+ spin_unlock_irqrestore(&vg->lock, flags);
+
+ dev_warn(&vg->pdev->dev,
+ "pin %u forcibly re-configured as GPIO\n", offset);
}
pm_runtime_get(&vg->pdev->dev);
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Gu Jinxiang <[email protected]>
commit 315409b0098fb2651d86553f0436b70502b29bb2 upstream.
Reported in https://bugzilla.kernel.org/show_bug.cgi?id=199839, with an
image that has an invalid chunk type but does not return an error.
Add chunk type check in btrfs_check_chunk_valid, to detect the wrong
type combinations.
Link: https://bugzilla.kernel.org/show_bug.cgi?id=199839
Reported-by: Xu Wen <[email protected]>
Reviewed-by: Qu Wenruo <[email protected]>
Signed-off-by: Gu Jinxiang <[email protected]>
Signed-off-by: David Sterba <[email protected]>
[bwh: Backported to 4.4: Use root->fs_info instead of fs_info]
Signed-off-by: Ben Hutchings <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
fs/btrfs/volumes.c | 28 ++++++++++++++++++++++++++++
1 file changed, 28 insertions(+)
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -5815,6 +5815,8 @@ static int btrfs_check_chunk_valid(struc
u16 num_stripes;
u16 sub_stripes;
u64 type;
+ u64 features;
+ bool mixed = false;
length = btrfs_chunk_length(leaf, chunk);
stripe_len = btrfs_chunk_stripe_len(leaf, chunk);
@@ -5855,6 +5857,32 @@ static int btrfs_check_chunk_valid(struc
btrfs_chunk_type(leaf, chunk));
return -EIO;
}
+
+ if ((type & BTRFS_BLOCK_GROUP_TYPE_MASK) == 0) {
+ btrfs_err(root->fs_info, "missing chunk type flag: 0x%llx", type);
+ return -EIO;
+ }
+
+ if ((type & BTRFS_BLOCK_GROUP_SYSTEM) &&
+ (type & (BTRFS_BLOCK_GROUP_METADATA | BTRFS_BLOCK_GROUP_DATA))) {
+ btrfs_err(root->fs_info,
+ "system chunk with data or metadata type: 0x%llx", type);
+ return -EIO;
+ }
+
+ features = btrfs_super_incompat_flags(root->fs_info->super_copy);
+ if (features & BTRFS_FEATURE_INCOMPAT_MIXED_GROUPS)
+ mixed = true;
+
+ if (!mixed) {
+ if ((type & BTRFS_BLOCK_GROUP_METADATA) &&
+ (type & BTRFS_BLOCK_GROUP_DATA)) {
+ btrfs_err(root->fs_info,
+ "mixed chunk type in non-mixed mode: 0x%llx", type);
+ return -EIO;
+ }
+ }
+
if ((type & BTRFS_BLOCK_GROUP_RAID10 && sub_stripes != 2) ||
(type & BTRFS_BLOCK_GROUP_RAID1 && num_stripes < 1) ||
(type & BTRFS_BLOCK_GROUP_RAID5 && num_stripes < 2) ||
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Arnd Bergmann <[email protected]>
commit 7cfad65297bfe0aa2996cd72d21c898aa84436d9 upstream.
The return value of sizeof() is of type size_t, so we must print it
using the %z format modifier rather than %l to avoid this warning
on some architectures:
fs/btrfs/tree-checker.c: In function 'check_dir_item':
fs/btrfs/tree-checker.c:273:50: error: format '%lu' expects argument of type 'long unsigned int', but argument 5 has type 'u32' {aka 'unsigned int'} [-Werror=format=]
Fixes: 005887f2e3e0 ("btrfs: tree-checker: Add checker for dir item")
Signed-off-by: Arnd Bergmann <[email protected]>
Reviewed-by: David Sterba <[email protected]>
Signed-off-by: David Sterba <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
fs/btrfs/tree-checker.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/fs/btrfs/tree-checker.c
+++ b/fs/btrfs/tree-checker.c
@@ -223,7 +223,7 @@ static int check_dir_item(struct btrfs_r
/* header itself should not cross item boundary */
if (cur + sizeof(*di) > item_size) {
dir_item_err(root, leaf, slot,
- "dir item header crosses item boundary, have %lu boundary %u",
+ "dir item header crosses item boundary, have %zu boundary %u",
cur + sizeof(*di), item_size);
return -EUCLEAN;
}
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Nikos Tsironis <[email protected]>
commit ecda7c0280e6b3398459dc589b9a41c1adb45529 upstream.
Add support for one pre-commit callback which is run right before the
metadata are committed.
This allows the thin provisioning target to run a callback before the
metadata are committed and is required by the next commit.
Signed-off-by: Nikos Tsironis <[email protected]>
Acked-by: Joe Thornber <[email protected]>
Signed-off-by: Mike Snitzer <[email protected]>
[bwh: Backported to 3.16:
- Open-code pmd_write_{lock_in_core,unlock}()
- Adjust context]
Signed-off-by: Ben Hutchings <[email protected]>
---
drivers/md/dm-thin-metadata.c | 29 +++++++++++++++++++++++++++++
drivers/md/dm-thin-metadata.h | 7 +++++++
2 files changed, 36 insertions(+)
--- a/drivers/md/dm-thin-metadata.c
+++ b/drivers/md/dm-thin-metadata.c
@@ -198,6 +198,15 @@ struct dm_pool_metadata {
bool fail_io:1;
/*
+ * Pre-commit callback.
+ *
+ * This allows the thin provisioning target to run a callback before
+ * the metadata are committed.
+ */
+ dm_pool_pre_commit_fn pre_commit_fn;
+ void *pre_commit_context;
+
+ /*
* Reading the space map roots can fail, so we read it into these
* buffers before the superblock is locked and updated.
*/
@@ -784,6 +793,14 @@ static int __commit_transaction(struct d
*/
BUILD_BUG_ON(sizeof(struct thin_disk_superblock) > 512);
+ if (pmd->pre_commit_fn) {
+ r = pmd->pre_commit_fn(pmd->pre_commit_context);
+ if (r < 0) {
+ DMERR("pre-commit callback failed");
+ return r;
+ }
+ }
+
r = __write_changed_details(pmd);
if (r < 0)
return r;
@@ -844,6 +861,8 @@ struct dm_pool_metadata *dm_pool_metadat
pmd->fail_io = false;
pmd->bdev = bdev;
pmd->data_block_size = data_block_size;
+ pmd->pre_commit_fn = NULL;
+ pmd->pre_commit_context = NULL;
r = __create_persistent_data_objects(pmd, format_device);
if (r) {
@@ -1789,6 +1808,16 @@ int dm_pool_register_metadata_threshold(
return r;
}
+void dm_pool_register_pre_commit_callback(struct dm_pool_metadata *pmd,
+ dm_pool_pre_commit_fn fn,
+ void *context)
+{
+ down_write(&pmd->root_lock);
+ pmd->pre_commit_fn = fn;
+ pmd->pre_commit_context = context;
+ up_write(&pmd->root_lock);
+}
+
int dm_pool_metadata_set_needs_check(struct dm_pool_metadata *pmd)
{
int r;
--- a/drivers/md/dm-thin-metadata.h
+++ b/drivers/md/dm-thin-metadata.h
@@ -213,6 +213,13 @@ int dm_pool_register_metadata_threshold(
int dm_pool_metadata_set_needs_check(struct dm_pool_metadata *pmd);
bool dm_pool_metadata_needs_check(struct dm_pool_metadata *pmd);
+/* Pre-commit callback */
+typedef int (*dm_pool_pre_commit_fn)(void *context);
+
+void dm_pool_register_pre_commit_callback(struct dm_pool_metadata *pmd,
+ dm_pool_pre_commit_fn fn,
+ void *context);
+
/*----------------------------------------------------------------*/
#endif
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Sven Eckelmann <[email protected]>
commit 4cc4a1708903f404d2ca0dfde30e71e052c6cbc9 upstream.
The distributed arp table is using a DHT to store and retrieve MAC address
information for an IP address. This is done using unicast messages to
selected peers. The potential peers are looked up using the IP address and
the VID.
While the IP address is always stored in big endian byte order, this is not
the case of the VID. It can (depending on the host system) either be big
endian or little endian. The host must therefore always convert it to big
endian to ensure that all devices calculate the same peers for the same
lookup data.
Fixes: be1db4f6615b ("batman-adv: make the Distributed ARP Table vlan aware")
Signed-off-by: Sven Eckelmann <[email protected]>
Signed-off-by: Simon Wunderlich <[email protected]>
[bwh: Backported to 3.16: adjust context]
Signed-off-by: Ben Hutchings <[email protected]>
---
net/batman-adv/distributed-arp-table.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
--- a/net/batman-adv/distributed-arp-table.c
+++ b/net/batman-adv/distributed-arp-table.c
@@ -207,9 +207,11 @@ static uint32_t batadv_hash_dat(const vo
{
uint32_t hash = 0;
const struct batadv_dat_entry *dat = data;
+ __be16 vid;
hash = batadv_hash_bytes(hash, &dat->ip, sizeof(dat->ip));
- hash = batadv_hash_bytes(hash, &dat->vid, sizeof(dat->vid));
+ vid = htons(dat->vid);
+ hash = batadv_hash_bytes(hash, &vid, sizeof(vid));
hash += (hash << 3);
hash ^= (hash >> 11);
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Eric Dumazet <[email protected]>
commit f394722fb0d0f701119368959d7cd0ecbc46363a upstream.
neigh_cleanup() has not been used for seven years, and was a wrong design.
Messing with shared pointer in bond_neigh_init() without proper
memory barriers would at least trigger syzbot complains eventually.
It is time to remove this stuff.
Fixes: b63b70d87741 ("IPoIB: Use a private hash table for path lookup in xmit path")
Signed-off-by: Eric Dumazet <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
[bwh: Backported to 3.16: adjust context]
Signed-off-by: Ben Hutchings <[email protected]>
---
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -3431,19 +3431,10 @@ static int bond_neigh_init(struct neighb
return 0;
parms.neigh_setup = NULL;
- parms.neigh_cleanup = NULL;
ret = slave_ops->ndo_neigh_setup(slave->dev, &parms);
if (ret)
return ret;
- /*
- * Assign slave's neigh_cleanup to neighbour in case cleanup is called
- * after the last slave has been detached. Assumes that all slaves
- * utilize the same neigh_cleanup (true at this writing as only user
- * is ipoib).
- */
- n->parms->neigh_cleanup = parms.neigh_cleanup;
-
if (!parms.neigh_setup)
return 0;
--- a/include/net/neighbour.h
+++ b/include/net/neighbour.h
@@ -71,7 +71,6 @@ struct neigh_parms {
struct net_device *dev;
struct neigh_parms *next;
int (*neigh_setup)(struct neighbour *);
- void (*neigh_cleanup)(struct neighbour *);
struct neigh_table *tbl;
void *sysctl_table;
--- a/net/core/neighbour.c
+++ b/net/core/neighbour.c
@@ -103,9 +103,6 @@ static int neigh_blackhole(struct neighb
static void neigh_cleanup_and_release(struct neighbour *neigh)
{
- if (neigh->parms->neigh_cleanup)
- neigh->parms->neigh_cleanup(neigh);
-
__neigh_notify(neigh, RTM_DELNEIGH, 0);
neigh_release(neigh);
}
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Qu Wenruo <[email protected]>
commit ad7b0368f33cffe67fecd302028915926e50ef7e upstream.
Add checker for dir item, for key types DIR_ITEM, DIR_INDEX and
XATTR_ITEM.
This checker does comprehensive checks for:
1) dir_item header and its data size
Against item boundary and maximum name/xattr length.
This part is mostly the same as old verify_dir_item().
2) dir_type
Against maximum file types, and against key type.
Since XATTR key should only have FT_XATTR dir item, and normal dir
item type should not have XATTR key.
The check between key->type and dir_type is newly introduced by this
patch.
3) name hash
For XATTR and DIR_ITEM key, key->offset is name hash (crc32c).
Check the hash of the name against the key to ensure it's correct.
The name hash check is only found in btrfs-progs before this patch.
Signed-off-by: Qu Wenruo <[email protected]>
Reviewed-by: Nikolay Borisov <[email protected]>
Reviewed-by: Su Yue <[email protected]>
Reviewed-by: David Sterba <[email protected]>
Signed-off-by: David Sterba <[email protected]>
[bwh: Backported to 4.4: BTRFS_MAX_XATTR_SIZE() takes a root instead of an
fs_info, and yields a value of type size_t instead of unsigned int]
Signed-off-by: Ben Hutchings <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
fs/btrfs/tree-checker.c | 141 ++++++++++++++++++++++++++++++++++++++++
1 file changed, 141 insertions(+)
--- a/fs/btrfs/tree-checker.c
+++ b/fs/btrfs/tree-checker.c
@@ -30,6 +30,7 @@
#include "tree-checker.h"
#include "disk-io.h"
#include "compression.h"
+#include "hash.h"
#define CORRUPT(reason, eb, root, slot) \
btrfs_crit(root->fs_info, \
@@ -176,6 +177,141 @@ static int check_csum_item(struct btrfs_
}
/*
+ * Customized reported for dir_item, only important new info is key->objectid,
+ * which represents inode number
+ */
+__printf(4, 5)
+static void dir_item_err(const struct btrfs_root *root,
+ const struct extent_buffer *eb, int slot,
+ const char *fmt, ...)
+{
+ struct btrfs_key key;
+ struct va_format vaf;
+ va_list args;
+
+ btrfs_item_key_to_cpu(eb, &key, slot);
+ va_start(args, fmt);
+
+ vaf.fmt = fmt;
+ vaf.va = &args;
+
+ btrfs_crit(root->fs_info,
+ "corrupt %s: root=%llu block=%llu slot=%d ino=%llu, %pV",
+ btrfs_header_level(eb) == 0 ? "leaf" : "node", root->objectid,
+ btrfs_header_bytenr(eb), slot, key.objectid, &vaf);
+ va_end(args);
+}
+
+static int check_dir_item(struct btrfs_root *root,
+ struct extent_buffer *leaf,
+ struct btrfs_key *key, int slot)
+{
+ struct btrfs_dir_item *di;
+ u32 item_size = btrfs_item_size_nr(leaf, slot);
+ u32 cur = 0;
+
+ di = btrfs_item_ptr(leaf, slot, struct btrfs_dir_item);
+ while (cur < item_size) {
+ char namebuf[max(BTRFS_NAME_LEN, XATTR_NAME_MAX)];
+ u32 name_len;
+ u32 data_len;
+ u32 max_name_len;
+ u32 total_size;
+ u32 name_hash;
+ u8 dir_type;
+
+ /* header itself should not cross item boundary */
+ if (cur + sizeof(*di) > item_size) {
+ dir_item_err(root, leaf, slot,
+ "dir item header crosses item boundary, have %lu boundary %u",
+ cur + sizeof(*di), item_size);
+ return -EUCLEAN;
+ }
+
+ /* dir type check */
+ dir_type = btrfs_dir_type(leaf, di);
+ if (dir_type >= BTRFS_FT_MAX) {
+ dir_item_err(root, leaf, slot,
+ "invalid dir item type, have %u expect [0, %u)",
+ dir_type, BTRFS_FT_MAX);
+ return -EUCLEAN;
+ }
+
+ if (key->type == BTRFS_XATTR_ITEM_KEY &&
+ dir_type != BTRFS_FT_XATTR) {
+ dir_item_err(root, leaf, slot,
+ "invalid dir item type for XATTR key, have %u expect %u",
+ dir_type, BTRFS_FT_XATTR);
+ return -EUCLEAN;
+ }
+ if (dir_type == BTRFS_FT_XATTR &&
+ key->type != BTRFS_XATTR_ITEM_KEY) {
+ dir_item_err(root, leaf, slot,
+ "xattr dir type found for non-XATTR key");
+ return -EUCLEAN;
+ }
+ if (dir_type == BTRFS_FT_XATTR)
+ max_name_len = XATTR_NAME_MAX;
+ else
+ max_name_len = BTRFS_NAME_LEN;
+
+ /* Name/data length check */
+ name_len = btrfs_dir_name_len(leaf, di);
+ data_len = btrfs_dir_data_len(leaf, di);
+ if (name_len > max_name_len) {
+ dir_item_err(root, leaf, slot,
+ "dir item name len too long, have %u max %u",
+ name_len, max_name_len);
+ return -EUCLEAN;
+ }
+ if (name_len + data_len > BTRFS_MAX_XATTR_SIZE(root)) {
+ dir_item_err(root, leaf, slot,
+ "dir item name and data len too long, have %u max %zu",
+ name_len + data_len,
+ BTRFS_MAX_XATTR_SIZE(root));
+ return -EUCLEAN;
+ }
+
+ if (data_len && dir_type != BTRFS_FT_XATTR) {
+ dir_item_err(root, leaf, slot,
+ "dir item with invalid data len, have %u expect 0",
+ data_len);
+ return -EUCLEAN;
+ }
+
+ total_size = sizeof(*di) + name_len + data_len;
+
+ /* header and name/data should not cross item boundary */
+ if (cur + total_size > item_size) {
+ dir_item_err(root, leaf, slot,
+ "dir item data crosses item boundary, have %u boundary %u",
+ cur + total_size, item_size);
+ return -EUCLEAN;
+ }
+
+ /*
+ * Special check for XATTR/DIR_ITEM, as key->offset is name
+ * hash, should match its name
+ */
+ if (key->type == BTRFS_DIR_ITEM_KEY ||
+ key->type == BTRFS_XATTR_ITEM_KEY) {
+ read_extent_buffer(leaf, namebuf,
+ (unsigned long)(di + 1), name_len);
+ name_hash = btrfs_name_hash(namebuf, name_len);
+ if (key->offset != name_hash) {
+ dir_item_err(root, leaf, slot,
+ "name hash mismatch with key, have 0x%016x expect 0x%016llx",
+ name_hash, key->offset);
+ return -EUCLEAN;
+ }
+ }
+ cur += total_size;
+ di = (struct btrfs_dir_item *)((void *)di + total_size);
+ }
+ return 0;
+}
+
+/*
* Common point to switch the item-specific validation.
*/
static int check_leaf_item(struct btrfs_root *root,
@@ -191,6 +327,11 @@ static int check_leaf_item(struct btrfs_
case BTRFS_EXTENT_CSUM_KEY:
ret = check_csum_item(root, leaf, key, slot);
break;
+ case BTRFS_DIR_ITEM_KEY:
+ case BTRFS_DIR_INDEX_KEY:
+ case BTRFS_XATTR_ITEM_KEY:
+ ret = check_dir_item(root, leaf, key, slot);
+ break;
}
return ret;
}
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Pablo Neira Ayuso <[email protected]>
commit 71df14b0ce094be46d105b5a3ededd83b8e779a0 upstream.
Do not assume userspace always sends us NFT_DATA_VALUE for bitwise and
cmp expressions. Although NFT_DATA_VERDICT does not make any sense, it
is still possible to handcraft a netlink message using this incorrect
data type.
Signed-off-by: Pablo Neira Ayuso <[email protected]>
[bwh: Backported to 3.16: adjust context]
Signed-off-by: Ben Hutchings <[email protected]>
---
net/netfilter/nft_bitwise.c | 19 ++++++++++++++-----
net/netfilter/nft_cmp.c | 12 ++++++++++--
2 files changed, 24 insertions(+), 7 deletions(-)
--- a/net/netfilter/nft_bitwise.c
+++ b/net/netfilter/nft_bitwise.c
@@ -86,16 +86,25 @@ static int nft_bitwise_init(const struct
err = nft_data_init(NULL, &priv->mask, &d1, tb[NFTA_BITWISE_MASK]);
if (err < 0)
return err;
- if (d1.len != priv->len)
- return -EINVAL;
+ if (d1.len != priv->len) {
+ err = -EINVAL;
+ goto err1;
+ }
err = nft_data_init(NULL, &priv->xor, &d2, tb[NFTA_BITWISE_XOR]);
if (err < 0)
- return err;
- if (d2.len != priv->len)
- return -EINVAL;
+ goto err1;
+ if (d2.len != priv->len) {
+ err = -EINVAL;
+ goto err2;
+ }
return 0;
+err2:
+ nft_data_uninit(&priv->xor, d2.type);
+err1:
+ nft_data_uninit(&priv->mask, d1.type);
+ return err;
}
static int nft_bitwise_dump(struct sk_buff *skb, const struct nft_expr *expr)
--- a/net/netfilter/nft_cmp.c
+++ b/net/netfilter/nft_cmp.c
@@ -201,10 +201,18 @@ nft_cmp_select_ops(const struct nft_ctx
if (err < 0)
return ERR_PTR(err);
+ if (desc.type != NFT_DATA_VALUE) {
+ err = -EINVAL;
+ goto err1;
+ }
+
if (desc.len <= sizeof(u32) && op == NFT_CMP_EQ)
return &nft_cmp_fast_ops;
- else
- return &nft_cmp_ops;
+
+ return &nft_cmp_ops;
+err1:
+ nft_data_uninit(&data, desc.type);
+ return ERR_PTR(-EINVAL);
}
static struct nft_expr_type nft_cmp_type __read_mostly = {
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Florian Westphal <[email protected]>
commit 18a110b022a5c02e7dc9f6109d0bd93e58ac6ebb upstream.
Curtis Taylor and Jon Maxwell reported and debugged a crash on 3.10
based kernel.
Crash occurs in ctnetlink_conntrack_events because net->nfnl socket is
NULL. The nfnl socket was set to NULL by netns destruction running on
another cpu.
The exiting network namespace calls the relevant destructors in the
following order:
1. ctnetlink_net_exit_batch
This nulls out the event callback pointer in struct netns.
2. nfnetlink_net_exit_batch
This nulls net->nfnl socket and frees it.
3. nf_conntrack_cleanup_net_list
This removes all remaining conntrack entries.
This is order is correct. The only explanation for the crash so ar is:
cpu1: conntrack is dying, eviction occurs:
-> nf_ct_delete()
-> nf_conntrack_event_report \
-> nf_conntrack_eventmask_report
-> notify->fcn() (== ctnetlink_conntrack_events).
cpu1: a. fetches rcu protected pointer to obtain ctnetlink event callback.
b. gets interrupted.
cpu2: runs netns exit handlers:
a runs ctnetlink destructor, event cb pointer set to NULL.
b runs nfnetlink destructor, nfnl socket is closed and set to NULL.
cpu1: c. resumes and trips over NULL net->nfnl.
Problem appears to be that ctnetlink_net_exit_batch only prevents future
callers of nf_conntrack_eventmask_report() from obtaining the callback.
It doesn't wait of other cpus that might have already obtained the
callbacks address.
I don't see anything in upstream kernels that would prevent similar
crash: We need to wait for all cpus to have exited the event callback.
Fixes: 9592a5c01e79dbc59eb56fa ("netfilter: ctnetlink: netns support")
Signed-off-by: Florian Westphal <[email protected]>
Signed-off-by: Pablo Neira Ayuso <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
net/netfilter/nf_conntrack_netlink.c | 3 +++
1 file changed, 3 insertions(+)
--- a/net/netfilter/nf_conntrack_netlink.c
+++ b/net/netfilter/nf_conntrack_netlink.c
@@ -3225,6 +3225,9 @@ static void __net_exit ctnetlink_net_exi
list_for_each_entry(net, net_exit_list, exit_list)
ctnetlink_net_exit(net);
+
+ /* wait for other cpus until they are done with ctnl_notifiers */
+ synchronize_rcu();
}
static struct pernet_operations ctnetlink_net_ops = {
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Qu Wenruo <[email protected]>
commit ba480dd4db9f1798541eb2d1c423fc95feee8d36 upstream.
A crafted image has empty root tree block, which will later cause NULL
pointer dereference.
The following trees should never be empty:
1) Tree root
Must contain at least root items for extent tree, device tree and fs
tree
2) Chunk tree
Or we can't even bootstrap as it contains the mapping.
3) Fs tree
At least inode item for top level inode (.).
4) Device tree
Dev extents for chunks
5) Extent tree
Must have corresponding extent for each chunk.
If any of them is empty, we are sure the fs is corrupted and no need to
mount it.
Link: https://bugzilla.kernel.org/show_bug.cgi?id=199847
Reported-by: Xu Wen <[email protected]>
Signed-off-by: Qu Wenruo <[email protected]>
Tested-by: Gu Jinxiang <[email protected]>
Reviewed-by: David Sterba <[email protected]>
Signed-off-by: David Sterba <[email protected]>
[bwh: Backported to 4.4: Pass root instead of fs_info to generic_err()]
Signed-off-by: Ben Hutchings <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
fs/btrfs/tree-checker.c | 15 ++++++++++++++-
1 file changed, 14 insertions(+), 1 deletion(-)
--- a/fs/btrfs/tree-checker.c
+++ b/fs/btrfs/tree-checker.c
@@ -456,9 +456,22 @@ static int check_leaf(struct btrfs_root
* skip this check for relocation trees.
*/
if (nritems == 0 && !btrfs_header_flag(leaf, BTRFS_HEADER_FLAG_RELOC)) {
+ u64 owner = btrfs_header_owner(leaf);
struct btrfs_root *check_root;
- key.objectid = btrfs_header_owner(leaf);
+ /* These trees must never be empty */
+ if (owner == BTRFS_ROOT_TREE_OBJECTID ||
+ owner == BTRFS_CHUNK_TREE_OBJECTID ||
+ owner == BTRFS_EXTENT_TREE_OBJECTID ||
+ owner == BTRFS_DEV_TREE_OBJECTID ||
+ owner == BTRFS_FS_TREE_OBJECTID ||
+ owner == BTRFS_DATA_RELOC_TREE_OBJECTID) {
+ generic_err(root, leaf, 0,
+ "invalid root, root %llu must never be empty",
+ owner);
+ return -EUCLEAN;
+ }
+ key.objectid = owner;
key.type = BTRFS_ROOT_ITEM_KEY;
key.offset = (u64)-1;
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Pavel Tatashin <[email protected]>
In entry_64.S we have code like this:
/* Unconditionally use kernel CR3 for do_nmi() */
/* %rax is saved above, so OK to clobber here */
ALTERNATIVE "jmp 2f", "movq %cr3, %rax", X86_FEATURE_KAISER
/* If PCID enabled, NOFLUSH now and NOFLUSH on return */
ALTERNATIVE "", "bts $63, %rax", X86_FEATURE_PCID
pushq %rax
/* mask off "user" bit of pgd address and 12 PCID bits: */
andq $(~(X86_CR3_PCID_ASID_MASK | KAISER_SHADOW_PGD_OFFSET)), %rax
movq %rax, %cr3
2:
/* paranoidentry do_nmi, 0; without TRACE_IRQS_OFF */
call do_nmi
With this instruction:
andq $(~(X86_CR3_PCID_ASID_MASK | KAISER_SHADOW_PGD_OFFSET)), %rax
We unconditionally switch from whatever our CR3 was to kernel page table.
But, in arch/x86/platform/efi/efi_64.c We temporarily set a different page
table, that does not have the kernel page table with 0x1000 offset from it.
Look in efi_thunk() and efi_thunk_set_virtual_address_map().
So, while CR3 points to the other page table, we get an NMI interrupt,
and clear 0x1000 from CR3, resulting in a bogus CR3 if the 0x1000 bit was
set.
The efi page table comes from realmode/rm/trampoline_64.S:
arch/x86/realmode/rm/trampoline_64.S
141 .bss
142 .balign PAGE_SIZE
143 GLOBAL(trampoline_pgd) .space PAGE_SIZE
Notice: alignment is PAGE_SIZE, so after applying KAISER_SHADOW_PGD_OFFSET
which equal to PAGE_SIZE, we can get a different page table.
But, even if we fix alignment, here the trampoline binary is later copied
into dynamically allocated memory in reserve_real_mode(), so we need to
fix that place as well.
Fixes: f9a1666f97b3 ("KAISER: Kernel Address Isolation")
Signed-off-by: Pavel Tatashin <[email protected]>
Reviewed-by: Steven Sistare <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
[bwh: Adjust the Fixes field for 3.16]
Signed-off-by: Ben Hutchings <[email protected]>
---
arch/x86/include/asm/kaiser.h | 10 ++++++++++
arch/x86/realmode/init.c | 4 +++-
arch/x86/realmode/rm/trampoline_64.S | 3 ++-
3 files changed, 15 insertions(+), 2 deletions(-)
--- a/arch/x86/include/asm/kaiser.h
+++ b/arch/x86/include/asm/kaiser.h
@@ -19,6 +19,16 @@
#define KAISER_SHADOW_PGD_OFFSET 0x1000
+#ifdef CONFIG_PAGE_TABLE_ISOLATION
+/*
+ * A page table address must have this alignment to stay the same when
+ * KAISER_SHADOW_PGD_OFFSET mask is applied
+ */
+#define KAISER_KERNEL_PGD_ALIGNMENT (KAISER_SHADOW_PGD_OFFSET << 1)
+#else
+#define KAISER_KERNEL_PGD_ALIGNMENT PAGE_SIZE
+#endif
+
#ifdef __ASSEMBLY__
#ifdef CONFIG_PAGE_TABLE_ISOLATION
--- a/arch/x86/realmode/init.c
+++ b/arch/x86/realmode/init.c
@@ -4,6 +4,7 @@
#include <asm/cacheflush.h>
#include <asm/pgtable.h>
#include <asm/realmode.h>
+#include <asm/kaiser.h>
struct real_mode_header *real_mode_header;
u32 *trampoline_cr4_features;
@@ -15,7 +16,8 @@ void __init reserve_real_mode(void)
size_t size = PAGE_ALIGN(real_mode_blob_end - real_mode_blob);
/* Has to be under 1M so we can execute real-mode AP code. */
- mem = memblock_find_in_range(0, 1<<20, size, PAGE_SIZE);
+ mem = memblock_find_in_range(0, 1 << 20, size,
+ KAISER_KERNEL_PGD_ALIGNMENT);
if (!mem)
panic("Cannot allocate trampoline\n");
--- a/arch/x86/realmode/rm/trampoline_64.S
+++ b/arch/x86/realmode/rm/trampoline_64.S
@@ -30,6 +30,7 @@
#include <asm/msr.h>
#include <asm/segment.h>
#include <asm/processor-flags.h>
+#include <asm/kaiser.h>
#include "realmode.h"
.text
@@ -139,7 +140,7 @@ tr_gdt:
tr_gdt_end:
.bss
- .balign PAGE_SIZE
+ .balign KAISER_KERNEL_PGD_ALIGNMENT
GLOBAL(trampoline_pgd) .space PAGE_SIZE
.balign 8
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Pablo Neira Ayuso <[email protected]>
commit 0d2c96af797ba149e559c5875c0151384ab6dd14 upstream.
Userspace might bogusly sent NFT_DATA_VERDICT in several netlink
attributes that assume NFT_DATA_VALUE. Moreover, make sure that error
path invokes nft_data_release() to decrement the reference count on the
chain object.
Fixes: 96518518cc41 ("netfilter: add nftables")
Fixes: 0f3cd9b36977 ("netfilter: nf_tables: add range expression")
Signed-off-by: Pablo Neira Ayuso <[email protected]>
[bwh: Backported to 3.16:
- Drop changes in nft_get_set_elem(), nft_range
- Call nft_data_uninit() instead of nft_data_release()
- Adjust context]
Signed-off-by: Ben Hutchings <[email protected]>
---
--- a/net/netfilter/nft_bitwise.c
+++ b/net/netfilter/nft_bitwise.c
@@ -86,7 +86,7 @@ static int nft_bitwise_init(const struct
err = nft_data_init(NULL, &priv->mask, &d1, tb[NFTA_BITWISE_MASK]);
if (err < 0)
return err;
- if (d1.len != priv->len) {
+ if (d1.type != NFT_DATA_VALUE || d1.len != priv->len) {
err = -EINVAL;
goto err1;
}
@@ -94,7 +94,7 @@ static int nft_bitwise_init(const struct
err = nft_data_init(NULL, &priv->xor, &d2, tb[NFTA_BITWISE_XOR]);
if (err < 0)
goto err1;
- if (d2.len != priv->len) {
+ if (d2.type != NFT_DATA_VALUE || d2.len != priv->len) {
err = -EINVAL;
goto err2;
}
--- a/net/netfilter/nft_cmp.c
+++ b/net/netfilter/nft_cmp.c
@@ -84,6 +84,12 @@ static int nft_cmp_init(const struct nft
if (desc.len > U8_MAX)
return -ERANGE;
+ if (desc.type != NFT_DATA_VALUE) {
+ err = -EINVAL;
+ nft_data_uninit(&priv->data, desc.type);
+ return err;
+ }
+
priv->len = desc.len;
return 0;
}
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Wei Yongjun <[email protected]>
commit bff7e067ee518f9ed7e1cbc63e4c9e01670d0b71 upstream.
Fix to return error code -EINVAL instead of 0, as is done elsewhere in
this function.
Fixes: e80d1c805a3b ("dm: do not override error code returned from dm_get_device()")
Signed-off-by: Wei Yongjun <[email protected]>
Signed-off-by: Mike Snitzer <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
drivers/md/dm-flakey.c | 2 ++
1 file changed, 2 insertions(+)
--- a/drivers/md/dm-flakey.c
+++ b/drivers/md/dm-flakey.c
@@ -200,11 +200,13 @@ static int flakey_ctr(struct dm_target *
if (!(fc->up_interval + fc->down_interval)) {
ti->error = "Total (up + down) interval is zero";
+ r = -EINVAL;
goto bad;
}
if (fc->up_interval + fc->down_interval < fc->up_interval) {
ti->error = "Interval overflow";
+ r = -EINVAL;
goto bad;
}
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Johannes Thumshirn <[email protected]>
commit 349ae63f40638a28c6fce52e8447c2d14b84cc0c upstream.
We recently had a customer issue with a corrupted filesystem. When
trying to mount this image btrfs panicked with a division by zero in
calc_stripe_length().
The corrupt chunk had a 'num_stripes' value of 1. calc_stripe_length()
takes this value and divides it by the number of copies the RAID profile
is expected to have to calculate the amount of data stripes. As a DUP
profile is expected to have 2 copies this division resulted in 1/2 = 0.
Later then the 'data_stripes' variable is used as a divisor in the
stripe length calculation which results in a division by 0 and thus a
kernel panic.
When encountering a filesystem with a DUP block group and a
'num_stripes' value unequal to 2, refuse mounting as the image is
corrupted and will lead to unexpected behaviour.
Code inspection showed a RAID1 block group has the same issues.
Fixes: e06cd3dd7cea ("Btrfs: add validadtion checks for chunk loading")
Reviewed-by: Qu Wenruo <[email protected]>
Reviewed-by: Nikolay Borisov <[email protected]>
Signed-off-by: Johannes Thumshirn <[email protected]>
Reviewed-by: David Sterba <[email protected]>
Signed-off-by: David Sterba <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
fs/btrfs/volumes.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -5884,10 +5884,10 @@ static int btrfs_check_chunk_valid(struc
}
if ((type & BTRFS_BLOCK_GROUP_RAID10 && sub_stripes != 2) ||
- (type & BTRFS_BLOCK_GROUP_RAID1 && num_stripes < 1) ||
+ (type & BTRFS_BLOCK_GROUP_RAID1 && num_stripes != 2) ||
(type & BTRFS_BLOCK_GROUP_RAID5 && num_stripes < 2) ||
(type & BTRFS_BLOCK_GROUP_RAID6 && num_stripes < 3) ||
- (type & BTRFS_BLOCK_GROUP_DUP && num_stripes > 2) ||
+ (type & BTRFS_BLOCK_GROUP_DUP && num_stripes != 2) ||
((type & BTRFS_BLOCK_GROUP_PROFILE_MASK) == 0 &&
num_stripes != 1)) {
btrfs_err(root->fs_info,
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Qu Wenruo <[email protected]>
commit 557ea5dd003d371536f6b4e8f7c8209a2b6fd4e3 upstream.
It's no doubt the comprehensive tree block checker will become larger,
so moving them into their own files is quite reasonable.
Signed-off-by: Qu Wenruo <[email protected]>
[ wording adjustments ]
Signed-off-by: David Sterba <[email protected]>
[bwh: Backported to 4.4:
- The moved code is slightly different
- Adjust context]
Signed-off-by: Ben Hutchings <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
fs/btrfs/Makefile | 2 +-
fs/btrfs/disk-io.c | 284 +-----------------------------------
fs/btrfs/tree-checker.c | 309 ++++++++++++++++++++++++++++++++++++++++
fs/btrfs/tree-checker.h | 26 ++++
4 files changed, 340 insertions(+), 281 deletions(-)
create mode 100644 fs/btrfs/tree-checker.c
create mode 100644 fs/btrfs/tree-checker.h
--- a/fs/btrfs/Makefile
+++ b/fs/btrfs/Makefile
@@ -9,7 +9,7 @@ btrfs-y += super.o ctree.o extent-tree.o
export.o tree-log.o free-space-cache.o zlib.o lzo.o \
compression.o delayed-ref.o relocation.o delayed-inode.o scrub.o \
reada.o backref.o ulist.o qgroup.o send.o dev-replace.o raid56.o \
- uuid-tree.o props.o hash.o
+ uuid-tree.o props.o hash.o tree-checker.o
btrfs-$(CONFIG_BTRFS_FS_POSIX_ACL) += acl.o
btrfs-$(CONFIG_BTRFS_FS_CHECK_INTEGRITY) += check-integrity.o
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -49,6 +49,7 @@
#include "raid56.h"
#include "sysfs.h"
#include "qgroup.h"
+#include "tree-checker.h"
#ifdef CONFIG_X86
#include <asm/cpufeature.h>
@@ -507,283 +508,6 @@ static int check_tree_block_fsid(struct
return ret;
}
-#define CORRUPT(reason, eb, root, slot) \
- btrfs_crit(root->fs_info, "corrupt %s, %s: block=%llu," \
- " root=%llu, slot=%d", \
- btrfs_header_level(eb) == 0 ? "leaf" : "node",\
- reason, btrfs_header_bytenr(eb), root->objectid, slot)
-
-static int check_extent_data_item(struct btrfs_root *root,
- struct extent_buffer *leaf,
- struct btrfs_key *key, int slot)
-{
- struct btrfs_file_extent_item *fi;
- u32 sectorsize = root->sectorsize;
- u32 item_size = btrfs_item_size_nr(leaf, slot);
-
- if (!IS_ALIGNED(key->offset, sectorsize)) {
- CORRUPT("unaligned key offset for file extent",
- leaf, root, slot);
- return -EUCLEAN;
- }
-
- fi = btrfs_item_ptr(leaf, slot, struct btrfs_file_extent_item);
-
- if (btrfs_file_extent_type(leaf, fi) > BTRFS_FILE_EXTENT_TYPES) {
- CORRUPT("invalid file extent type", leaf, root, slot);
- return -EUCLEAN;
- }
-
- /*
- * Support for new compression/encrption must introduce incompat flag,
- * and must be caught in open_ctree().
- */
- if (btrfs_file_extent_compression(leaf, fi) > BTRFS_COMPRESS_TYPES) {
- CORRUPT("invalid file extent compression", leaf, root, slot);
- return -EUCLEAN;
- }
- if (btrfs_file_extent_encryption(leaf, fi)) {
- CORRUPT("invalid file extent encryption", leaf, root, slot);
- return -EUCLEAN;
- }
- if (btrfs_file_extent_type(leaf, fi) == BTRFS_FILE_EXTENT_INLINE) {
- /* Inline extent must have 0 as key offset */
- if (key->offset) {
- CORRUPT("inline extent has non-zero key offset",
- leaf, root, slot);
- return -EUCLEAN;
- }
-
- /* Compressed inline extent has no on-disk size, skip it */
- if (btrfs_file_extent_compression(leaf, fi) !=
- BTRFS_COMPRESS_NONE)
- return 0;
-
- /* Uncompressed inline extent size must match item size */
- if (item_size != BTRFS_FILE_EXTENT_INLINE_DATA_START +
- btrfs_file_extent_ram_bytes(leaf, fi)) {
- CORRUPT("plaintext inline extent has invalid size",
- leaf, root, slot);
- return -EUCLEAN;
- }
- return 0;
- }
-
- /* Regular or preallocated extent has fixed item size */
- if (item_size != sizeof(*fi)) {
- CORRUPT(
- "regluar or preallocated extent data item size is invalid",
- leaf, root, slot);
- return -EUCLEAN;
- }
- if (!IS_ALIGNED(btrfs_file_extent_ram_bytes(leaf, fi), sectorsize) ||
- !IS_ALIGNED(btrfs_file_extent_disk_bytenr(leaf, fi), sectorsize) ||
- !IS_ALIGNED(btrfs_file_extent_disk_num_bytes(leaf, fi), sectorsize) ||
- !IS_ALIGNED(btrfs_file_extent_offset(leaf, fi), sectorsize) ||
- !IS_ALIGNED(btrfs_file_extent_num_bytes(leaf, fi), sectorsize)) {
- CORRUPT(
- "regular or preallocated extent data item has unaligned value",
- leaf, root, slot);
- return -EUCLEAN;
- }
-
- return 0;
-}
-
-static int check_csum_item(struct btrfs_root *root, struct extent_buffer *leaf,
- struct btrfs_key *key, int slot)
-{
- u32 sectorsize = root->sectorsize;
- u32 csumsize = btrfs_super_csum_size(root->fs_info->super_copy);
-
- if (key->objectid != BTRFS_EXTENT_CSUM_OBJECTID) {
- CORRUPT("invalid objectid for csum item", leaf, root, slot);
- return -EUCLEAN;
- }
- if (!IS_ALIGNED(key->offset, sectorsize)) {
- CORRUPT("unaligned key offset for csum item", leaf, root, slot);
- return -EUCLEAN;
- }
- if (!IS_ALIGNED(btrfs_item_size_nr(leaf, slot), csumsize)) {
- CORRUPT("unaligned csum item size", leaf, root, slot);
- return -EUCLEAN;
- }
- return 0;
-}
-
-/*
- * Common point to switch the item-specific validation.
- */
-static int check_leaf_item(struct btrfs_root *root,
- struct extent_buffer *leaf,
- struct btrfs_key *key, int slot)
-{
- int ret = 0;
-
- switch (key->type) {
- case BTRFS_EXTENT_DATA_KEY:
- ret = check_extent_data_item(root, leaf, key, slot);
- break;
- case BTRFS_EXTENT_CSUM_KEY:
- ret = check_csum_item(root, leaf, key, slot);
- break;
- }
- return ret;
-}
-
-static noinline int check_leaf(struct btrfs_root *root,
- struct extent_buffer *leaf)
-{
- /* No valid key type is 0, so all key should be larger than this key */
- struct btrfs_key prev_key = {0, 0, 0};
- struct btrfs_key key;
- u32 nritems = btrfs_header_nritems(leaf);
- int slot;
-
- /*
- * Extent buffers from a relocation tree have a owner field that
- * corresponds to the subvolume tree they are based on. So just from an
- * extent buffer alone we can not find out what is the id of the
- * corresponding subvolume tree, so we can not figure out if the extent
- * buffer corresponds to the root of the relocation tree or not. So skip
- * this check for relocation trees.
- */
- if (nritems == 0 && !btrfs_header_flag(leaf, BTRFS_HEADER_FLAG_RELOC)) {
- struct btrfs_root *check_root;
-
- key.objectid = btrfs_header_owner(leaf);
- key.type = BTRFS_ROOT_ITEM_KEY;
- key.offset = (u64)-1;
-
- check_root = btrfs_get_fs_root(root->fs_info, &key, false);
- /*
- * The only reason we also check NULL here is that during
- * open_ctree() some roots has not yet been set up.
- */
- if (!IS_ERR_OR_NULL(check_root)) {
- struct extent_buffer *eb;
-
- eb = btrfs_root_node(check_root);
- /* if leaf is the root, then it's fine */
- if (leaf != eb) {
- CORRUPT("non-root leaf's nritems is 0",
- leaf, check_root, 0);
- free_extent_buffer(eb);
- return -EUCLEAN;
- }
- free_extent_buffer(eb);
- }
- return 0;
- }
-
- if (nritems == 0)
- return 0;
-
- /*
- * Check the following things to make sure this is a good leaf, and
- * leaf users won't need to bother with similar sanity checks:
- *
- * 1) key order
- * 2) item offset and size
- * No overlap, no hole, all inside the leaf.
- * 3) item content
- * If possible, do comprehensive sanity check.
- * NOTE: All checks must only rely on the item data itself.
- */
- for (slot = 0; slot < nritems; slot++) {
- u32 item_end_expected;
- int ret;
-
- btrfs_item_key_to_cpu(leaf, &key, slot);
-
- /* Make sure the keys are in the right order */
- if (btrfs_comp_cpu_keys(&prev_key, &key) >= 0) {
- CORRUPT("bad key order", leaf, root, slot);
- return -EUCLEAN;
- }
-
- /*
- * Make sure the offset and ends are right, remember that the
- * item data starts at the end of the leaf and grows towards the
- * front.
- */
- if (slot == 0)
- item_end_expected = BTRFS_LEAF_DATA_SIZE(root);
- else
- item_end_expected = btrfs_item_offset_nr(leaf,
- slot - 1);
- if (btrfs_item_end_nr(leaf, slot) != item_end_expected) {
- CORRUPT("slot offset bad", leaf, root, slot);
- return -EUCLEAN;
- }
-
- /*
- * Check to make sure that we don't point outside of the leaf,
- * just incase all the items are consistent to eachother, but
- * all point outside of the leaf.
- */
- if (btrfs_item_end_nr(leaf, slot) >
- BTRFS_LEAF_DATA_SIZE(root)) {
- CORRUPT("slot end outside of leaf", leaf, root, slot);
- return -EUCLEAN;
- }
-
- /* Also check if the item pointer overlaps with btrfs item. */
- if (btrfs_item_nr_offset(slot) + sizeof(struct btrfs_item) >
- btrfs_item_ptr_offset(leaf, slot)) {
- CORRUPT("slot overlap with its data", leaf, root, slot);
- return -EUCLEAN;
- }
-
- /* Check if the item size and content meet other criteria */
- ret = check_leaf_item(root, leaf, &key, slot);
- if (ret < 0)
- return ret;
-
- prev_key.objectid = key.objectid;
- prev_key.type = key.type;
- prev_key.offset = key.offset;
- }
-
- return 0;
-}
-
-static int check_node(struct btrfs_root *root, struct extent_buffer *node)
-{
- unsigned long nr = btrfs_header_nritems(node);
- struct btrfs_key key, next_key;
- int slot;
- u64 bytenr;
- int ret = 0;
-
- if (nr == 0 || nr > BTRFS_NODEPTRS_PER_BLOCK(root)) {
- btrfs_crit(root->fs_info,
- "corrupt node: block %llu root %llu nritems %lu",
- node->start, root->objectid, nr);
- return -EIO;
- }
-
- for (slot = 0; slot < nr - 1; slot++) {
- bytenr = btrfs_node_blockptr(node, slot);
- btrfs_node_key_to_cpu(node, &key, slot);
- btrfs_node_key_to_cpu(node, &next_key, slot + 1);
-
- if (!bytenr) {
- CORRUPT("invalid item slot", node, root, slot);
- ret = -EIO;
- goto out;
- }
-
- if (btrfs_comp_cpu_keys(&key, &next_key) >= 0) {
- CORRUPT("bad key order", node, root, slot);
- ret = -EIO;
- goto out;
- }
- }
-out:
- return ret;
-}
-
static int btree_readpage_end_io_hook(struct btrfs_io_bio *io_bio,
u64 phy_offset, struct page *page,
u64 start, u64 end, int mirror)
@@ -851,12 +575,12 @@ static int btree_readpage_end_io_hook(st
* that we don't try and read the other copies of this block, just
* return -EIO.
*/
- if (found_level == 0 && check_leaf(root, eb)) {
+ if (found_level == 0 && btrfs_check_leaf(root, eb)) {
set_bit(EXTENT_BUFFER_CORRUPT, &eb->bflags);
ret = -EIO;
}
- if (found_level > 0 && check_node(root, eb))
+ if (found_level > 0 && btrfs_check_node(root, eb))
ret = -EIO;
if (!ret)
@@ -3978,7 +3702,7 @@ void btrfs_mark_buffer_dirty(struct exte
buf->len,
root->fs_info->dirty_metadata_batch);
#ifdef CONFIG_BTRFS_FS_CHECK_INTEGRITY
- if (btrfs_header_level(buf) == 0 && check_leaf(root, buf)) {
+ if (btrfs_header_level(buf) == 0 && btrfs_check_leaf(root, buf)) {
btrfs_print_leaf(root, buf);
ASSERT(0);
}
--- /dev/null
+++ b/fs/btrfs/tree-checker.c
@@ -0,0 +1,309 @@
+/*
+ * Copyright (C) Qu Wenruo 2017. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License v2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program.
+ */
+
+/*
+ * The module is used to catch unexpected/corrupted tree block data.
+ * Such behavior can be caused either by a fuzzed image or bugs.
+ *
+ * The objective is to do leaf/node validation checks when tree block is read
+ * from disk, and check *every* possible member, so other code won't
+ * need to checking them again.
+ *
+ * Due to the potential and unwanted damage, every checker needs to be
+ * carefully reviewed otherwise so it does not prevent mount of valid images.
+ */
+
+#include "ctree.h"
+#include "tree-checker.h"
+#include "disk-io.h"
+#include "compression.h"
+
+#define CORRUPT(reason, eb, root, slot) \
+ btrfs_crit(root->fs_info, \
+ "corrupt %s, %s: block=%llu, root=%llu, slot=%d", \
+ btrfs_header_level(eb) == 0 ? "leaf" : "node", \
+ reason, btrfs_header_bytenr(eb), root->objectid, slot)
+
+static int check_extent_data_item(struct btrfs_root *root,
+ struct extent_buffer *leaf,
+ struct btrfs_key *key, int slot)
+{
+ struct btrfs_file_extent_item *fi;
+ u32 sectorsize = root->sectorsize;
+ u32 item_size = btrfs_item_size_nr(leaf, slot);
+
+ if (!IS_ALIGNED(key->offset, sectorsize)) {
+ CORRUPT("unaligned key offset for file extent",
+ leaf, root, slot);
+ return -EUCLEAN;
+ }
+
+ fi = btrfs_item_ptr(leaf, slot, struct btrfs_file_extent_item);
+
+ if (btrfs_file_extent_type(leaf, fi) > BTRFS_FILE_EXTENT_TYPES) {
+ CORRUPT("invalid file extent type", leaf, root, slot);
+ return -EUCLEAN;
+ }
+
+ /*
+ * Support for new compression/encrption must introduce incompat flag,
+ * and must be caught in open_ctree().
+ */
+ if (btrfs_file_extent_compression(leaf, fi) > BTRFS_COMPRESS_TYPES) {
+ CORRUPT("invalid file extent compression", leaf, root, slot);
+ return -EUCLEAN;
+ }
+ if (btrfs_file_extent_encryption(leaf, fi)) {
+ CORRUPT("invalid file extent encryption", leaf, root, slot);
+ return -EUCLEAN;
+ }
+ if (btrfs_file_extent_type(leaf, fi) == BTRFS_FILE_EXTENT_INLINE) {
+ /* Inline extent must have 0 as key offset */
+ if (key->offset) {
+ CORRUPT("inline extent has non-zero key offset",
+ leaf, root, slot);
+ return -EUCLEAN;
+ }
+
+ /* Compressed inline extent has no on-disk size, skip it */
+ if (btrfs_file_extent_compression(leaf, fi) !=
+ BTRFS_COMPRESS_NONE)
+ return 0;
+
+ /* Uncompressed inline extent size must match item size */
+ if (item_size != BTRFS_FILE_EXTENT_INLINE_DATA_START +
+ btrfs_file_extent_ram_bytes(leaf, fi)) {
+ CORRUPT("plaintext inline extent has invalid size",
+ leaf, root, slot);
+ return -EUCLEAN;
+ }
+ return 0;
+ }
+
+ /* Regular or preallocated extent has fixed item size */
+ if (item_size != sizeof(*fi)) {
+ CORRUPT(
+ "regluar or preallocated extent data item size is invalid",
+ leaf, root, slot);
+ return -EUCLEAN;
+ }
+ if (!IS_ALIGNED(btrfs_file_extent_ram_bytes(leaf, fi), sectorsize) ||
+ !IS_ALIGNED(btrfs_file_extent_disk_bytenr(leaf, fi), sectorsize) ||
+ !IS_ALIGNED(btrfs_file_extent_disk_num_bytes(leaf, fi), sectorsize) ||
+ !IS_ALIGNED(btrfs_file_extent_offset(leaf, fi), sectorsize) ||
+ !IS_ALIGNED(btrfs_file_extent_num_bytes(leaf, fi), sectorsize)) {
+ CORRUPT(
+ "regular or preallocated extent data item has unaligned value",
+ leaf, root, slot);
+ return -EUCLEAN;
+ }
+
+ return 0;
+}
+
+static int check_csum_item(struct btrfs_root *root, struct extent_buffer *leaf,
+ struct btrfs_key *key, int slot)
+{
+ u32 sectorsize = root->sectorsize;
+ u32 csumsize = btrfs_super_csum_size(root->fs_info->super_copy);
+
+ if (key->objectid != BTRFS_EXTENT_CSUM_OBJECTID) {
+ CORRUPT("invalid objectid for csum item", leaf, root, slot);
+ return -EUCLEAN;
+ }
+ if (!IS_ALIGNED(key->offset, sectorsize)) {
+ CORRUPT("unaligned key offset for csum item", leaf, root, slot);
+ return -EUCLEAN;
+ }
+ if (!IS_ALIGNED(btrfs_item_size_nr(leaf, slot), csumsize)) {
+ CORRUPT("unaligned csum item size", leaf, root, slot);
+ return -EUCLEAN;
+ }
+ return 0;
+}
+
+/*
+ * Common point to switch the item-specific validation.
+ */
+static int check_leaf_item(struct btrfs_root *root,
+ struct extent_buffer *leaf,
+ struct btrfs_key *key, int slot)
+{
+ int ret = 0;
+
+ switch (key->type) {
+ case BTRFS_EXTENT_DATA_KEY:
+ ret = check_extent_data_item(root, leaf, key, slot);
+ break;
+ case BTRFS_EXTENT_CSUM_KEY:
+ ret = check_csum_item(root, leaf, key, slot);
+ break;
+ }
+ return ret;
+}
+
+int btrfs_check_leaf(struct btrfs_root *root, struct extent_buffer *leaf)
+{
+ struct btrfs_fs_info *fs_info = root->fs_info;
+ /* No valid key type is 0, so all key should be larger than this key */
+ struct btrfs_key prev_key = {0, 0, 0};
+ struct btrfs_key key;
+ u32 nritems = btrfs_header_nritems(leaf);
+ int slot;
+
+ /*
+ * Extent buffers from a relocation tree have a owner field that
+ * corresponds to the subvolume tree they are based on. So just from an
+ * extent buffer alone we can not find out what is the id of the
+ * corresponding subvolume tree, so we can not figure out if the extent
+ * buffer corresponds to the root of the relocation tree or not. So
+ * skip this check for relocation trees.
+ */
+ if (nritems == 0 && !btrfs_header_flag(leaf, BTRFS_HEADER_FLAG_RELOC)) {
+ struct btrfs_root *check_root;
+
+ key.objectid = btrfs_header_owner(leaf);
+ key.type = BTRFS_ROOT_ITEM_KEY;
+ key.offset = (u64)-1;
+
+ check_root = btrfs_get_fs_root(fs_info, &key, false);
+ /*
+ * The only reason we also check NULL here is that during
+ * open_ctree() some roots has not yet been set up.
+ */
+ if (!IS_ERR_OR_NULL(check_root)) {
+ struct extent_buffer *eb;
+
+ eb = btrfs_root_node(check_root);
+ /* if leaf is the root, then it's fine */
+ if (leaf != eb) {
+ CORRUPT("non-root leaf's nritems is 0",
+ leaf, check_root, 0);
+ free_extent_buffer(eb);
+ return -EUCLEAN;
+ }
+ free_extent_buffer(eb);
+ }
+ return 0;
+ }
+
+ if (nritems == 0)
+ return 0;
+
+ /*
+ * Check the following things to make sure this is a good leaf, and
+ * leaf users won't need to bother with similar sanity checks:
+ *
+ * 1) key ordering
+ * 2) item offset and size
+ * No overlap, no hole, all inside the leaf.
+ * 3) item content
+ * If possible, do comprehensive sanity check.
+ * NOTE: All checks must only rely on the item data itself.
+ */
+ for (slot = 0; slot < nritems; slot++) {
+ u32 item_end_expected;
+ int ret;
+
+ btrfs_item_key_to_cpu(leaf, &key, slot);
+
+ /* Make sure the keys are in the right order */
+ if (btrfs_comp_cpu_keys(&prev_key, &key) >= 0) {
+ CORRUPT("bad key order", leaf, root, slot);
+ return -EUCLEAN;
+ }
+
+ /*
+ * Make sure the offset and ends are right, remember that the
+ * item data starts at the end of the leaf and grows towards the
+ * front.
+ */
+ if (slot == 0)
+ item_end_expected = BTRFS_LEAF_DATA_SIZE(root);
+ else
+ item_end_expected = btrfs_item_offset_nr(leaf,
+ slot - 1);
+ if (btrfs_item_end_nr(leaf, slot) != item_end_expected) {
+ CORRUPT("slot offset bad", leaf, root, slot);
+ return -EUCLEAN;
+ }
+
+ /*
+ * Check to make sure that we don't point outside of the leaf,
+ * just in case all the items are consistent to each other, but
+ * all point outside of the leaf.
+ */
+ if (btrfs_item_end_nr(leaf, slot) >
+ BTRFS_LEAF_DATA_SIZE(root)) {
+ CORRUPT("slot end outside of leaf", leaf, root, slot);
+ return -EUCLEAN;
+ }
+
+ /* Also check if the item pointer overlaps with btrfs item. */
+ if (btrfs_item_nr_offset(slot) + sizeof(struct btrfs_item) >
+ btrfs_item_ptr_offset(leaf, slot)) {
+ CORRUPT("slot overlap with its data", leaf, root, slot);
+ return -EUCLEAN;
+ }
+
+ /* Check if the item size and content meet other criteria */
+ ret = check_leaf_item(root, leaf, &key, slot);
+ if (ret < 0)
+ return ret;
+
+ prev_key.objectid = key.objectid;
+ prev_key.type = key.type;
+ prev_key.offset = key.offset;
+ }
+
+ return 0;
+}
+
+int btrfs_check_node(struct btrfs_root *root, struct extent_buffer *node)
+{
+ unsigned long nr = btrfs_header_nritems(node);
+ struct btrfs_key key, next_key;
+ int slot;
+ u64 bytenr;
+ int ret = 0;
+
+ if (nr == 0 || nr > BTRFS_NODEPTRS_PER_BLOCK(root)) {
+ btrfs_crit(root->fs_info,
+ "corrupt node: block %llu root %llu nritems %lu",
+ node->start, root->objectid, nr);
+ return -EIO;
+ }
+
+ for (slot = 0; slot < nr - 1; slot++) {
+ bytenr = btrfs_node_blockptr(node, slot);
+ btrfs_node_key_to_cpu(node, &key, slot);
+ btrfs_node_key_to_cpu(node, &next_key, slot + 1);
+
+ if (!bytenr) {
+ CORRUPT("invalid item slot", node, root, slot);
+ ret = -EIO;
+ goto out;
+ }
+
+ if (btrfs_comp_cpu_keys(&key, &next_key) >= 0) {
+ CORRUPT("bad key order", node, root, slot);
+ ret = -EIO;
+ goto out;
+ }
+ }
+out:
+ return ret;
+}
--- /dev/null
+++ b/fs/btrfs/tree-checker.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) Qu Wenruo 2017. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License v2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program.
+ */
+
+#ifndef __BTRFS_TREE_CHECKER__
+#define __BTRFS_TREE_CHECKER__
+
+#include "ctree.h"
+#include "extent_io.h"
+
+int btrfs_check_leaf(struct btrfs_root *root, struct extent_buffer *leaf);
+int btrfs_check_node(struct btrfs_root *root, struct extent_buffer *node);
+
+#endif
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Qu Wenruo <[email protected]>
commit fce466eab7ac6baa9d2dcd88abcf945be3d4a089 upstream.
A crafted image with invalid block group items could make free space cache
code to cause panic.
We could detect such invalid block group item by checking:
1) Item size
Known fixed value.
2) Block group size (key.offset)
We have an upper limit on block group item (10G)
3) Chunk objectid
Known fixed value.
4) Type
Only 4 valid type values, DATA, METADATA, SYSTEM and DATA|METADATA.
No more than 1 bit set for profile type.
5) Used space
No more than the block group size.
This should allow btrfs to detect and refuse to mount the crafted image.
Link: https://bugzilla.kernel.org/show_bug.cgi?id=199849
Reported-by: Xu Wen <[email protected]>
Signed-off-by: Qu Wenruo <[email protected]>
Reviewed-by: Gu Jinxiang <[email protected]>
Reviewed-by: Nikolay Borisov <[email protected]>
Tested-by: Gu Jinxiang <[email protected]>
Reviewed-by: David Sterba <[email protected]>
Signed-off-by: David Sterba <[email protected]>
[bwh: Backported to 4.4:
- In check_leaf_item(), pass root->fs_info to check_block_group_item()
- Include <linux/sizes.h> (in ctree.h, to match upstream)
- Adjust context]
Signed-off-by: Ben Hutchings <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
[bwh: Backported to 3.16: adjust context]
Signed-off-by: Ben Hutchings <[email protected]>
---
fs/btrfs/ctree.h | 1 +
fs/btrfs/tree-checker.c | 100 ++++++++++++++++++++++++++++++++++++++++
fs/btrfs/volumes.c | 2 +-
fs/btrfs/volumes.h | 2 +
4 files changed, 104 insertions(+), 1 deletion(-)
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -34,6 +34,7 @@
#include <linux/pagemap.h>
#include <linux/btrfs.h>
#include <linux/workqueue.h>
+#include <linux/sizes.h>
#include "extent_io.h"
#include "extent_map.h"
#include "async-thread.h"
--- a/fs/btrfs/tree-checker.c
+++ b/fs/btrfs/tree-checker.c
@@ -31,6 +31,7 @@
#include "disk-io.h"
#include "compression.h"
#include "hash.h"
+#include "volumes.h"
#define CORRUPT(reason, eb, root, slot) \
btrfs_crit(root->fs_info, \
@@ -312,6 +313,102 @@ static int check_dir_item(struct btrfs_r
return 0;
}
+__printf(4, 5)
+__cold
+static void block_group_err(const struct btrfs_fs_info *fs_info,
+ const struct extent_buffer *eb, int slot,
+ const char *fmt, ...)
+{
+ struct btrfs_key key;
+ struct va_format vaf;
+ va_list args;
+
+ btrfs_item_key_to_cpu(eb, &key, slot);
+ va_start(args, fmt);
+
+ vaf.fmt = fmt;
+ vaf.va = &args;
+
+ btrfs_crit(fs_info,
+ "corrupt %s: root=%llu block=%llu slot=%d bg_start=%llu bg_len=%llu, %pV",
+ btrfs_header_level(eb) == 0 ? "leaf" : "node",
+ btrfs_header_owner(eb), btrfs_header_bytenr(eb), slot,
+ key.objectid, key.offset, &vaf);
+ va_end(args);
+}
+
+static int check_block_group_item(struct btrfs_fs_info *fs_info,
+ struct extent_buffer *leaf,
+ struct btrfs_key *key, int slot)
+{
+ struct btrfs_block_group_item bgi;
+ u32 item_size = btrfs_item_size_nr(leaf, slot);
+ u64 flags;
+ u64 type;
+
+ /*
+ * Here we don't really care about alignment since extent allocator can
+ * handle it. We care more about the size, as if one block group is
+ * larger than maximum size, it's must be some obvious corruption.
+ */
+ if (key->offset > BTRFS_MAX_DATA_CHUNK_SIZE || key->offset == 0) {
+ block_group_err(fs_info, leaf, slot,
+ "invalid block group size, have %llu expect (0, %llu]",
+ key->offset, BTRFS_MAX_DATA_CHUNK_SIZE);
+ return -EUCLEAN;
+ }
+
+ if (item_size != sizeof(bgi)) {
+ block_group_err(fs_info, leaf, slot,
+ "invalid item size, have %u expect %zu",
+ item_size, sizeof(bgi));
+ return -EUCLEAN;
+ }
+
+ read_extent_buffer(leaf, &bgi, btrfs_item_ptr_offset(leaf, slot),
+ sizeof(bgi));
+ if (btrfs_block_group_chunk_objectid(&bgi) !=
+ BTRFS_FIRST_CHUNK_TREE_OBJECTID) {
+ block_group_err(fs_info, leaf, slot,
+ "invalid block group chunk objectid, have %llu expect %llu",
+ btrfs_block_group_chunk_objectid(&bgi),
+ BTRFS_FIRST_CHUNK_TREE_OBJECTID);
+ return -EUCLEAN;
+ }
+
+ if (btrfs_block_group_used(&bgi) > key->offset) {
+ block_group_err(fs_info, leaf, slot,
+ "invalid block group used, have %llu expect [0, %llu)",
+ btrfs_block_group_used(&bgi), key->offset);
+ return -EUCLEAN;
+ }
+
+ flags = btrfs_block_group_flags(&bgi);
+ if (hweight64(flags & BTRFS_BLOCK_GROUP_PROFILE_MASK) > 1) {
+ block_group_err(fs_info, leaf, slot,
+"invalid profile flags, have 0x%llx (%lu bits set) expect no more than 1 bit set",
+ flags & BTRFS_BLOCK_GROUP_PROFILE_MASK,
+ hweight64(flags & BTRFS_BLOCK_GROUP_PROFILE_MASK));
+ return -EUCLEAN;
+ }
+
+ type = flags & BTRFS_BLOCK_GROUP_TYPE_MASK;
+ if (type != BTRFS_BLOCK_GROUP_DATA &&
+ type != BTRFS_BLOCK_GROUP_METADATA &&
+ type != BTRFS_BLOCK_GROUP_SYSTEM &&
+ type != (BTRFS_BLOCK_GROUP_METADATA |
+ BTRFS_BLOCK_GROUP_DATA)) {
+ block_group_err(fs_info, leaf, slot,
+"invalid type, have 0x%llx (%lu bits set) expect either 0x%llx, 0x%llx, 0x%llu or 0x%llx",
+ type, hweight64(type),
+ BTRFS_BLOCK_GROUP_DATA, BTRFS_BLOCK_GROUP_METADATA,
+ BTRFS_BLOCK_GROUP_SYSTEM,
+ BTRFS_BLOCK_GROUP_METADATA | BTRFS_BLOCK_GROUP_DATA);
+ return -EUCLEAN;
+ }
+ return 0;
+}
+
/*
* Common point to switch the item-specific validation.
*/
@@ -333,6 +430,9 @@ static int check_leaf_item(struct btrfs_
case BTRFS_XATTR_ITEM_KEY:
ret = check_dir_item(root, leaf, key, slot);
break;
+ case BTRFS_BLOCK_GROUP_ITEM_KEY:
+ ret = check_block_group_item(root->fs_info, leaf, key, slot);
+ break;
}
return ret;
}
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -4134,7 +4134,7 @@ static int __btrfs_alloc_chunk(struct bt
if (type & BTRFS_BLOCK_GROUP_DATA) {
max_stripe_size = 1024 * 1024 * 1024;
- max_chunk_size = 10 * max_stripe_size;
+ max_chunk_size = BTRFS_MAX_DATA_CHUNK_SIZE;
if (!devs_max)
devs_max = BTRFS_MAX_DEVS(info->chunk_root);
} else if (type & BTRFS_BLOCK_GROUP_METADATA) {
--- a/fs/btrfs/volumes.h
+++ b/fs/btrfs/volumes.h
@@ -24,6 +24,8 @@
#include <linux/btrfs.h>
#include "async-thread.h"
+#define BTRFS_MAX_DATA_CHUNK_SIZE (10ULL * SZ_1G)
+
#define BTRFS_STRIPE_LEN (64 * 1024)
struct buffer_head;
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Qu Wenruo <[email protected]>
commit c3267bbaa9cae09b62960eafe33ad19196803285 upstream.
Current check_leaf() function does a good job checking key order and
item offset/size.
However it only checks from slot 0 to the last but one slot, this is
good but makes later expansion hard.
So this refactoring iterates from slot 0 to the last slot.
For key comparison, it uses a key with all 0 as initial key, so all
valid keys should be larger than that.
And for item size/offset checks, it compares current item end with
previous item offset.
For slot 0, use leaf end as a special case.
This makes later item/key offset checks and item size checks easier to
be implemented.
Also, makes check_leaf() to return -EUCLEAN other than -EIO to indicate
error.
Signed-off-by: Qu Wenruo <[email protected]>
Reviewed-by: Nikolay Borisov <[email protected]>
Reviewed-by: David Sterba <[email protected]>
Signed-off-by: David Sterba <[email protected]>
[bwh: Backported to 4.4:
- BTRFS_LEAF_DATA_SIZE() takes a root rather than an fs_info
- Adjust context]
Signed-off-by: Ben Hutchings <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
fs/btrfs/disk-io.c | 50 +++++++++++++++++++++++++---------------------
1 file changed, 27 insertions(+), 23 deletions(-)
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -516,8 +516,9 @@ static int check_tree_block_fsid(struct
static noinline int check_leaf(struct btrfs_root *root,
struct extent_buffer *leaf)
{
+ /* No valid key type is 0, so all key should be larger than this key */
+ struct btrfs_key prev_key = {0, 0, 0};
struct btrfs_key key;
- struct btrfs_key leaf_key;
u32 nritems = btrfs_header_nritems(leaf);
int slot;
@@ -550,7 +551,7 @@ static noinline int check_leaf(struct bt
CORRUPT("non-root leaf's nritems is 0",
leaf, check_root, 0);
free_extent_buffer(eb);
- return -EIO;
+ return -EUCLEAN;
}
free_extent_buffer(eb);
}
@@ -560,28 +561,23 @@ static noinline int check_leaf(struct bt
if (nritems == 0)
return 0;
- /* Check the 0 item */
- if (btrfs_item_offset_nr(leaf, 0) + btrfs_item_size_nr(leaf, 0) !=
- BTRFS_LEAF_DATA_SIZE(root)) {
- CORRUPT("invalid item offset size pair", leaf, root, 0);
- return -EIO;
- }
-
/*
- * Check to make sure each items keys are in the correct order and their
- * offsets make sense. We only have to loop through nritems-1 because
- * we check the current slot against the next slot, which verifies the
- * next slot's offset+size makes sense and that the current's slot
- * offset is correct.
+ * Check the following things to make sure this is a good leaf, and
+ * leaf users won't need to bother with similar sanity checks:
+ *
+ * 1) key order
+ * 2) item offset and size
+ * No overlap, no hole, all inside the leaf.
*/
- for (slot = 0; slot < nritems - 1; slot++) {
- btrfs_item_key_to_cpu(leaf, &leaf_key, slot);
- btrfs_item_key_to_cpu(leaf, &key, slot + 1);
+ for (slot = 0; slot < nritems; slot++) {
+ u32 item_end_expected;
+
+ btrfs_item_key_to_cpu(leaf, &key, slot);
/* Make sure the keys are in the right order */
- if (btrfs_comp_cpu_keys(&leaf_key, &key) >= 0) {
+ if (btrfs_comp_cpu_keys(&prev_key, &key) >= 0) {
CORRUPT("bad key order", leaf, root, slot);
- return -EIO;
+ return -EUCLEAN;
}
/*
@@ -589,10 +585,14 @@ static noinline int check_leaf(struct bt
* item data starts at the end of the leaf and grows towards the
* front.
*/
- if (btrfs_item_offset_nr(leaf, slot) !=
- btrfs_item_end_nr(leaf, slot + 1)) {
+ if (slot == 0)
+ item_end_expected = BTRFS_LEAF_DATA_SIZE(root);
+ else
+ item_end_expected = btrfs_item_offset_nr(leaf,
+ slot - 1);
+ if (btrfs_item_end_nr(leaf, slot) != item_end_expected) {
CORRUPT("slot offset bad", leaf, root, slot);
- return -EIO;
+ return -EUCLEAN;
}
/*
@@ -603,8 +603,12 @@ static noinline int check_leaf(struct bt
if (btrfs_item_end_nr(leaf, slot) >
BTRFS_LEAF_DATA_SIZE(root)) {
CORRUPT("slot end outside of leaf", leaf, root, slot);
- return -EIO;
+ return -EUCLEAN;
}
+
+ prev_key.objectid = key.objectid;
+ prev_key.type = key.type;
+ prev_key.offset = key.offset;
}
return 0;
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Liu Bo <[email protected]>
commit 6fb37b756acce6d6e045f79c3764206033f617b4 upstream.
With btrfs-corrupt-block, one can drop one chunk item and mounting
will end up with a panic in btrfs_full_stripe_len().
This doesn't not remove the BUG_ON, but instead checks it a bit
earlier when we find the block group item.
Signed-off-by: Liu Bo <[email protected]>
Reviewed-by: David Sterba <[email protected]>
Signed-off-by: David Sterba <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
fs/btrfs/extent-tree.c | 17 ++++++++++++++++-
1 file changed, 16 insertions(+), 1 deletion(-)
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -8571,7 +8571,22 @@ static int find_first_block_group(struct
if (found_key.objectid >= key->objectid &&
found_key.type == BTRFS_BLOCK_GROUP_ITEM_KEY) {
- ret = 0;
+ struct extent_map_tree *em_tree;
+ struct extent_map *em;
+
+ em_tree = &root->fs_info->mapping_tree.map_tree;
+ read_lock(&em_tree->lock);
+ em = lookup_extent_mapping(em_tree, found_key.objectid,
+ found_key.offset);
+ read_unlock(&em_tree->lock);
+ if (!em) {
+ btrfs_err(root->fs_info,
+ "logical %llu len %llu found bg but no related chunk",
+ found_key.objectid, found_key.offset);
+ ret = -ENOENT;
+ } else {
+ ret = 0;
+ }
goto out;
}
path->slots[0]++;
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Mike Snitzer <[email protected]>
commit 299f6230bc6d0ccd5f95bb0fb865d80a9c7d5ccc upstream.
v4.8-rc3 commit 99f3c90d0d ("dm flakey: error READ bios during the
down_interval") overlooked the 'drop_writes' feature, which is meant to
allow reads to be issued rather than errored, during the down_interval.
Fixes: 99f3c90d0d ("dm flakey: error READ bios during the down_interval")
Reported-by: Qu Wenruo <[email protected]>
Signed-off-by: Mike Snitzer <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
drivers/md/dm-flakey.c | 27 ++++++++++++++++-----------
1 file changed, 16 insertions(+), 11 deletions(-)
--- a/drivers/md/dm-flakey.c
+++ b/drivers/md/dm-flakey.c
@@ -291,15 +291,13 @@ static int flakey_map(struct dm_target *
pb->bio_submitted = true;
/*
- * Map reads as normal only if corrupt_bio_byte set.
+ * Error reads if neither corrupt_bio_byte or drop_writes are set.
+ * Otherwise, flakey_end_io() will decide if the reads should be modified.
*/
if (bio_data_dir(bio) == READ) {
- /* If flags were specified, only corrupt those that match. */
- if (fc->corrupt_bio_byte && (fc->corrupt_bio_rw == READ) &&
- all_corrupt_bio_flags_match(bio, fc))
- goto map_bio;
- else
+ if (!fc->corrupt_bio_byte && !test_bit(DROP_WRITES, &fc->flags))
return -EIO;
+ goto map_bio;
}
/*
@@ -336,14 +334,21 @@ static int flakey_end_io(struct dm_targe
struct flakey_c *fc = ti->private;
struct per_bio_data *pb = dm_per_bio_data(bio, sizeof(struct per_bio_data));
- /*
- * Corrupt successful READs while in down state.
- */
if (!error && pb->bio_submitted && (bio_data_dir(bio) == READ)) {
- if (fc->corrupt_bio_byte)
+ if (fc->corrupt_bio_byte && (fc->corrupt_bio_rw == READ) &&
+ all_corrupt_bio_flags_match(bio, fc)) {
+ /*
+ * Corrupt successful matching READs while in down state.
+ */
corrupt_bio_data(bio, fc);
- else
+
+ } else if (!test_bit(DROP_WRITES, &fc->flags)) {
+ /*
+ * Error read during the down_interval if drop_writes
+ * wasn't configured.
+ */
return -EIO;
+ }
}
return error;
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Qu Wenruo <[email protected]>
commit 69fc6cbbac542c349b3d350d10f6e394c253c81d upstream.
[BUG]
If we run btrfs with CONFIG_BTRFS_FS_RUN_SANITY_TESTS=y, it will
instantly cause kernel panic like:
------
...
assertion failed: 0, file: fs/btrfs/disk-io.c, line: 3853
...
Call Trace:
btrfs_mark_buffer_dirty+0x187/0x1f0 [btrfs]
setup_items_for_insert+0x385/0x650 [btrfs]
__btrfs_drop_extents+0x129a/0x1870 [btrfs]
...
-----
[Cause]
Btrfs will call btrfs_check_leaf() in btrfs_mark_buffer_dirty() to check
if the leaf is valid with CONFIG_BTRFS_FS_RUN_SANITY_TESTS=y.
However quite some btrfs_mark_buffer_dirty() callers(*) don't really
initialize its item data but only initialize its item pointers, leaving
item data uninitialized.
This makes tree-checker catch uninitialized data as error, causing
such panic.
*: These callers include but not limited to
setup_items_for_insert()
btrfs_split_item()
btrfs_expand_item()
[Fix]
Add a new parameter @check_item_data to btrfs_check_leaf().
With @check_item_data set to false, item data check will be skipped and
fallback to old btrfs_check_leaf() behavior.
So we can still get early warning if we screw up item pointers, and
avoid false panic.
Cc: Filipe Manana <[email protected]>
Reported-by: Lakshmipathi.G <[email protected]>
Signed-off-by: Qu Wenruo <[email protected]>
Reviewed-by: Liu Bo <[email protected]>
Reviewed-by: David Sterba <[email protected]>
Signed-off-by: David Sterba <[email protected]>
[bwh: Backported to 4.4: adjust context]
Signed-off-by: Ben Hutchings <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
fs/btrfs/disk-io.c | 10 ++++++++--
fs/btrfs/tree-checker.c | 27 ++++++++++++++++++++++-----
fs/btrfs/tree-checker.h | 14 +++++++++++++-
3 files changed, 43 insertions(+), 8 deletions(-)
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -575,7 +575,7 @@ static int btree_readpage_end_io_hook(st
* that we don't try and read the other copies of this block, just
* return -EIO.
*/
- if (found_level == 0 && btrfs_check_leaf(root, eb)) {
+ if (found_level == 0 && btrfs_check_leaf_full(root, eb)) {
set_bit(EXTENT_BUFFER_CORRUPT, &eb->bflags);
ret = -EIO;
}
@@ -3702,7 +3702,13 @@ void btrfs_mark_buffer_dirty(struct exte
buf->len,
root->fs_info->dirty_metadata_batch);
#ifdef CONFIG_BTRFS_FS_CHECK_INTEGRITY
- if (btrfs_header_level(buf) == 0 && btrfs_check_leaf(root, buf)) {
+ /*
+ * Since btrfs_mark_buffer_dirty() can be called with item pointer set
+ * but item data not updated.
+ * So here we should only check item pointers, not item data.
+ */
+ if (btrfs_header_level(buf) == 0 &&
+ btrfs_check_leaf_relaxed(root, buf)) {
btrfs_print_leaf(root, buf);
ASSERT(0);
}
--- a/fs/btrfs/tree-checker.c
+++ b/fs/btrfs/tree-checker.c
@@ -195,7 +195,8 @@ static int check_leaf_item(struct btrfs_
return ret;
}
-int btrfs_check_leaf(struct btrfs_root *root, struct extent_buffer *leaf)
+static int check_leaf(struct btrfs_root *root, struct extent_buffer *leaf,
+ bool check_item_data)
{
struct btrfs_fs_info *fs_info = root->fs_info;
/* No valid key type is 0, so all key should be larger than this key */
@@ -299,10 +300,15 @@ int btrfs_check_leaf(struct btrfs_root *
return -EUCLEAN;
}
- /* Check if the item size and content meet other criteria */
- ret = check_leaf_item(root, leaf, &key, slot);
- if (ret < 0)
- return ret;
+ if (check_item_data) {
+ /*
+ * Check if the item size and content meet other
+ * criteria
+ */
+ ret = check_leaf_item(root, leaf, &key, slot);
+ if (ret < 0)
+ return ret;
+ }
prev_key.objectid = key.objectid;
prev_key.type = key.type;
@@ -312,6 +318,17 @@ int btrfs_check_leaf(struct btrfs_root *
return 0;
}
+int btrfs_check_leaf_full(struct btrfs_root *root, struct extent_buffer *leaf)
+{
+ return check_leaf(root, leaf, true);
+}
+
+int btrfs_check_leaf_relaxed(struct btrfs_root *root,
+ struct extent_buffer *leaf)
+{
+ return check_leaf(root, leaf, false);
+}
+
int btrfs_check_node(struct btrfs_root *root, struct extent_buffer *node)
{
unsigned long nr = btrfs_header_nritems(node);
--- a/fs/btrfs/tree-checker.h
+++ b/fs/btrfs/tree-checker.h
@@ -20,7 +20,19 @@
#include "ctree.h"
#include "extent_io.h"
-int btrfs_check_leaf(struct btrfs_root *root, struct extent_buffer *leaf);
+/*
+ * Comprehensive leaf checker.
+ * Will check not only the item pointers, but also every possible member
+ * in item data.
+ */
+int btrfs_check_leaf_full(struct btrfs_root *root, struct extent_buffer *leaf);
+
+/*
+ * Less strict leaf checker.
+ * Will only check item pointers, not reading item data.
+ */
+int btrfs_check_leaf_relaxed(struct btrfs_root *root,
+ struct extent_buffer *leaf);
int btrfs_check_node(struct btrfs_root *root, struct extent_buffer *node);
#endif
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Qu Wenruo <[email protected]>
commit 40c3c40947324d9f40bf47830c92c59a9bbadf4a upstream.
Add extra checks for item with EXTENT_DATA type. This checks the
following thing:
0) Key offset
All key offsets must be aligned to sectorsize.
Inline extent must have 0 for key offset.
1) Item size
Uncompressed inline file extent size must match item size.
(Compressed inline file extent has no information about its on-disk size.)
Regular/preallocated file extent size must be a fixed value.
2) Every member of regular file extent item
Including alignment for bytenr and offset, possible value for
compression/encryption/type.
3) Type/compression/encode must be one of the valid values.
This should be the most comprehensive and strict check in the context
of btrfs_item for EXTENT_DATA.
Signed-off-by: Qu Wenruo <[email protected]>
Reviewed-by: Nikolay Borisov <[email protected]>
Reviewed-by: David Sterba <[email protected]>
[ switch to BTRFS_FILE_EXTENT_TYPES, similar to what
BTRFS_COMPRESS_TYPES does ]
Signed-off-by: David Sterba <[email protected]>
[bwh: Backported to 4.4:
- Use root->sectorsize instead of root->fs_info->sectorsize
- Adjust filename]
Signed-off-by: Ben Hutchings <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
fs/btrfs/ctree.h | 1 +
fs/btrfs/disk-io.c | 103 +++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 104 insertions(+)
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -874,6 +874,7 @@ struct btrfs_balance_item {
#define BTRFS_FILE_EXTENT_INLINE 0
#define BTRFS_FILE_EXTENT_REG 1
#define BTRFS_FILE_EXTENT_PREALLOC 2
+#define BTRFS_FILE_EXTENT_TYPES 2
struct btrfs_file_extent_item {
/*
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -513,6 +513,100 @@ static int check_tree_block_fsid(struct
btrfs_header_level(eb) == 0 ? "leaf" : "node",\
reason, btrfs_header_bytenr(eb), root->objectid, slot)
+static int check_extent_data_item(struct btrfs_root *root,
+ struct extent_buffer *leaf,
+ struct btrfs_key *key, int slot)
+{
+ struct btrfs_file_extent_item *fi;
+ u32 sectorsize = root->sectorsize;
+ u32 item_size = btrfs_item_size_nr(leaf, slot);
+
+ if (!IS_ALIGNED(key->offset, sectorsize)) {
+ CORRUPT("unaligned key offset for file extent",
+ leaf, root, slot);
+ return -EUCLEAN;
+ }
+
+ fi = btrfs_item_ptr(leaf, slot, struct btrfs_file_extent_item);
+
+ if (btrfs_file_extent_type(leaf, fi) > BTRFS_FILE_EXTENT_TYPES) {
+ CORRUPT("invalid file extent type", leaf, root, slot);
+ return -EUCLEAN;
+ }
+
+ /*
+ * Support for new compression/encrption must introduce incompat flag,
+ * and must be caught in open_ctree().
+ */
+ if (btrfs_file_extent_compression(leaf, fi) > BTRFS_COMPRESS_TYPES) {
+ CORRUPT("invalid file extent compression", leaf, root, slot);
+ return -EUCLEAN;
+ }
+ if (btrfs_file_extent_encryption(leaf, fi)) {
+ CORRUPT("invalid file extent encryption", leaf, root, slot);
+ return -EUCLEAN;
+ }
+ if (btrfs_file_extent_type(leaf, fi) == BTRFS_FILE_EXTENT_INLINE) {
+ /* Inline extent must have 0 as key offset */
+ if (key->offset) {
+ CORRUPT("inline extent has non-zero key offset",
+ leaf, root, slot);
+ return -EUCLEAN;
+ }
+
+ /* Compressed inline extent has no on-disk size, skip it */
+ if (btrfs_file_extent_compression(leaf, fi) !=
+ BTRFS_COMPRESS_NONE)
+ return 0;
+
+ /* Uncompressed inline extent size must match item size */
+ if (item_size != BTRFS_FILE_EXTENT_INLINE_DATA_START +
+ btrfs_file_extent_ram_bytes(leaf, fi)) {
+ CORRUPT("plaintext inline extent has invalid size",
+ leaf, root, slot);
+ return -EUCLEAN;
+ }
+ return 0;
+ }
+
+ /* Regular or preallocated extent has fixed item size */
+ if (item_size != sizeof(*fi)) {
+ CORRUPT(
+ "regluar or preallocated extent data item size is invalid",
+ leaf, root, slot);
+ return -EUCLEAN;
+ }
+ if (!IS_ALIGNED(btrfs_file_extent_ram_bytes(leaf, fi), sectorsize) ||
+ !IS_ALIGNED(btrfs_file_extent_disk_bytenr(leaf, fi), sectorsize) ||
+ !IS_ALIGNED(btrfs_file_extent_disk_num_bytes(leaf, fi), sectorsize) ||
+ !IS_ALIGNED(btrfs_file_extent_offset(leaf, fi), sectorsize) ||
+ !IS_ALIGNED(btrfs_file_extent_num_bytes(leaf, fi), sectorsize)) {
+ CORRUPT(
+ "regular or preallocated extent data item has unaligned value",
+ leaf, root, slot);
+ return -EUCLEAN;
+ }
+
+ return 0;
+}
+
+/*
+ * Common point to switch the item-specific validation.
+ */
+static int check_leaf_item(struct btrfs_root *root,
+ struct extent_buffer *leaf,
+ struct btrfs_key *key, int slot)
+{
+ int ret = 0;
+
+ switch (key->type) {
+ case BTRFS_EXTENT_DATA_KEY:
+ ret = check_extent_data_item(root, leaf, key, slot);
+ break;
+ }
+ return ret;
+}
+
static noinline int check_leaf(struct btrfs_root *root,
struct extent_buffer *leaf)
{
@@ -568,9 +662,13 @@ static noinline int check_leaf(struct bt
* 1) key order
* 2) item offset and size
* No overlap, no hole, all inside the leaf.
+ * 3) item content
+ * If possible, do comprehensive sanity check.
+ * NOTE: All checks must only rely on the item data itself.
*/
for (slot = 0; slot < nritems; slot++) {
u32 item_end_expected;
+ int ret;
btrfs_item_key_to_cpu(leaf, &key, slot);
@@ -613,6 +711,11 @@ static noinline int check_leaf(struct bt
return -EUCLEAN;
}
+ /* Check if the item size and content meet other criteria */
+ ret = check_leaf_item(root, leaf, &key, slot);
+ if (ret < 0)
+ return ret;
+
prev_key.objectid = key.objectid;
prev_key.type = key.type;
prev_key.offset = key.offset;
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Liu Bo <[email protected]>
commit 3eb548ee3a8042d95ad81be254e67a5222c24e03 upstream.
During updating btree, we could push items between sibling
nodes/leaves, for leaves data sections starts reversely from
the end of the block while for nodes we only have key pairs
which are stored one by one from the start of the block.
So we could do try to push key pairs from one node to the next
node right in the tree, and after that, we update the node's
nritems to reflect the correct end while leaving the stale
content in the node. One may intentionally corrupt the fs
image and access the stale content by bumping the nritems and
causes various crashes.
This takes the in-memory @nritems as the correct one and
gets to memset the unused part of a btree node.
Signed-off-by: Liu Bo <[email protected]>
Reviewed-by: David Sterba <[email protected]>
Signed-off-by: David Sterba <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
fs/btrfs/extent_io.c | 11 +++++++++++
1 file changed, 11 insertions(+)
--- a/fs/btrfs/extent_io.c
+++ b/fs/btrfs/extent_io.c
@@ -3628,6 +3628,17 @@ static noinline_for_stack int write_one_
if (btrfs_header_owner(eb) == BTRFS_TREE_LOG_OBJECTID)
bio_flags = EXTENT_BIO_TREE_LOG;
+ /* set btree node beyond nritems with 0 to avoid stale content */
+ if (btrfs_header_level(eb) > 0) {
+ u32 nritems;
+ unsigned long end;
+
+ nritems = btrfs_header_nritems(eb);
+ end = btrfs_node_key_ptr_offset(nritems);
+
+ memset_extent_buffer(eb, 0, end, eb->len - end);
+ }
+
for (i = 0; i < num_pages; i++) {
struct page *p = eb->pages[i];
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Qu Wenruo <[email protected]>
commit 7f43d4affb2a254d421ab20b0cf65ac2569909fb upstream.
Function check_leaf() checks if any item pointer points outside of the
leaf, but it doesn't check if the pointer overlaps with the item itself.
Normally only the last item may be the victim, but adding such check is
never a bad idea anyway.
Signed-off-by: Qu Wenruo <[email protected]>
Reviewed-by: Nikolay Borisov <[email protected]>
Reviewed-by: David Sterba <[email protected]>
Signed-off-by: David Sterba <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
fs/btrfs/disk-io.c | 7 +++++++
1 file changed, 7 insertions(+)
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -606,6 +606,13 @@ static noinline int check_leaf(struct bt
return -EUCLEAN;
}
+ /* Also check if the item pointer overlaps with btrfs item. */
+ if (btrfs_item_nr_offset(slot) + sizeof(struct btrfs_item) >
+ btrfs_item_ptr_offset(leaf, slot)) {
+ CORRUPT("slot overlap with its data", leaf, root, slot);
+ return -EUCLEAN;
+ }
+
prev_key.objectid = key.objectid;
prev_key.type = key.type;
prev_key.offset = key.offset;
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Jeff Mahoney <[email protected]>
commit 95617d69326ce386c95e33db7aeb832b45ee9f8f upstream.
Overloading extent_map->bdev to struct map_lookup * might have started out
as a means to an end, but it's a pattern that's used all over the place
now. Let's get rid of the casting and just add a union instead.
Signed-off-by: Jeff Mahoney <[email protected]>
Signed-off-by: David Sterba <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
[bwh: Backported to 3.16: drop changes in
btrfs_start_trans_remove_block_group(),
btrfs_update_commit_device_bytes_used()]
Signed-off-by: Ben Hutchings <[email protected]>
---
--- a/fs/btrfs/dev-replace.c
+++ b/fs/btrfs/dev-replace.c
@@ -614,7 +614,7 @@ static void btrfs_dev_replace_update_dev
em = lookup_extent_mapping(em_tree, start, (u64)-1);
if (!em)
break;
- map = (struct map_lookup *)em->bdev;
+ map = em->map_lookup;
for (i = 0; i < map->num_stripes; i++)
if (srcdev == map->stripes[i].dev)
map->stripes[i].dev = tgtdev;
--- a/fs/btrfs/extent_map.c
+++ b/fs/btrfs/extent_map.c
@@ -76,7 +76,7 @@ void free_extent_map(struct extent_map *
WARN_ON(extent_map_in_tree(em));
WARN_ON(!list_empty(&em->list));
if (test_bit(EXTENT_FLAG_FS_MAPPING, &em->flags))
- kfree(em->bdev);
+ kfree(em->map_lookup);
kmem_cache_free(extent_map_cache, em);
}
}
--- a/fs/btrfs/extent_map.h
+++ b/fs/btrfs/extent_map.h
@@ -32,7 +32,15 @@ struct extent_map {
u64 block_len;
u64 generation;
unsigned long flags;
- struct block_device *bdev;
+ union {
+ struct block_device *bdev;
+
+ /*
+ * used for chunk mappings
+ * flags & EXTENT_FLAG_FS_MAPPING must be set
+ */
+ struct map_lookup *map_lookup;
+ };
atomic_t refs;
unsigned int compress_type;
struct list_head list;
--- a/fs/btrfs/scrub.c
+++ b/fs/btrfs/scrub.c
@@ -2637,7 +2637,7 @@ static noinline_for_stack int scrub_chun
if (!em)
return -EINVAL;
- map = (struct map_lookup *)em->bdev;
+ map = em->map_lookup;
if (em->start != chunk_offset)
goto out;
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -1047,7 +1047,7 @@ static int contains_pending_extent(struc
struct map_lookup *map;
int i;
- map = (struct map_lookup *)em->bdev;
+ map = em->map_lookup;
for (i = 0; i < map->num_stripes; i++) {
if (map->stripes[i].dev != device)
continue;
@@ -2533,7 +2533,7 @@ static int btrfs_relocate_chunk(struct b
BUG_ON(!em || em->start > chunk_offset ||
em->start + em->len < chunk_offset);
- map = (struct map_lookup *)em->bdev;
+ map = em->map_lookup;
for (i = 0; i < map->num_stripes; i++) {
ret = btrfs_free_dev_extent(trans, map->stripes[i].dev,
@@ -4322,7 +4322,7 @@ static int __btrfs_alloc_chunk(struct bt
goto error;
}
set_bit(EXTENT_FLAG_FS_MAPPING, &em->flags);
- em->bdev = (struct block_device *)map;
+ em->map_lookup = map;
em->start = start;
em->len = num_bytes;
em->block_start = 0;
@@ -4405,7 +4405,7 @@ int btrfs_finish_chunk_alloc(struct btrf
return -EINVAL;
}
- map = (struct map_lookup *)em->bdev;
+ map = em->map_lookup;
item_size = btrfs_chunk_item_size(map->num_stripes);
stripe_size = em->orig_block_len;
@@ -4547,7 +4547,7 @@ int btrfs_chunk_readonly(struct btrfs_ro
return 0;
}
- map = (struct map_lookup *)em->bdev;
+ map = em->map_lookup;
for (i = 0; i < map->num_stripes; i++) {
if (!map->stripes[i].dev->writeable) {
readonly = 1;
@@ -4613,7 +4613,7 @@ int btrfs_num_copies(struct btrfs_fs_inf
return 1;
}
- map = (struct map_lookup *)em->bdev;
+ map = em->map_lookup;
if (map->type & (BTRFS_BLOCK_GROUP_DUP | BTRFS_BLOCK_GROUP_RAID1))
ret = map->num_stripes;
else if (map->type & BTRFS_BLOCK_GROUP_RAID10)
@@ -4649,7 +4649,7 @@ unsigned long btrfs_full_stripe_len(stru
BUG_ON(!em);
BUG_ON(em->start > logical || em->start + em->len < logical);
- map = (struct map_lookup *)em->bdev;
+ map = em->map_lookup;
if (map->type & (BTRFS_BLOCK_GROUP_RAID5 |
BTRFS_BLOCK_GROUP_RAID6)) {
len = map->stripe_len * nr_data_stripes(map);
@@ -4672,7 +4672,7 @@ int btrfs_is_parity_mirror(struct btrfs_
BUG_ON(!em);
BUG_ON(em->start > logical || em->start + em->len < logical);
- map = (struct map_lookup *)em->bdev;
+ map = em->map_lookup;
if (map->type & (BTRFS_BLOCK_GROUP_RAID5 |
BTRFS_BLOCK_GROUP_RAID6))
ret = 1;
@@ -4794,7 +4794,7 @@ static int __btrfs_map_block(struct btrf
return -EINVAL;
}
- map = (struct map_lookup *)em->bdev;
+ map = em->map_lookup;
offset = logical - em->start;
stripe_len = map->stripe_len;
@@ -5321,7 +5321,7 @@ int btrfs_rmap_block(struct btrfs_mappin
free_extent_map(em);
return -EIO;
}
- map = (struct map_lookup *)em->bdev;
+ map = em->map_lookup;
length = em->len;
rmap_len = map->stripe_len;
@@ -5846,7 +5846,7 @@ static int read_one_chunk(struct btrfs_r
}
set_bit(EXTENT_FLAG_FS_MAPPING, &em->flags);
- em->bdev = (struct block_device *)map;
+ em->map_lookup = map;
em->start = logical;
em->len = length;
em->orig_start = 0;
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Filipe Manana <[email protected]>
commit f177d73949bf758542ca15a1c1945bd2e802cc65 upstream.
We can not simply use the owner field from an extent buffer's header to
get the id of the respective tree when the extent buffer is from a
relocation tree. When we create the root for a relocation tree we leave
(on purpose) the owner field with the same value as the subvolume's tree
root (we do this at ctree.c:btrfs_copy_root()). So we must ignore extent
buffers from relocation trees, which have the BTRFS_HEADER_FLAG_RELOC
flag set, because otherwise we will always consider the extent buffer
as not being the root of the tree (the root of original subvolume tree
is always different from the root of the respective relocation tree).
This lead to assertion failures when running with the integrity checker
enabled (CONFIG_BTRFS_FS_CHECK_INTEGRITY=y) such as the following:
[ 643.393409] BTRFS critical (device sdg): corrupt leaf, non-root leaf's nritems is 0: block=38506496, root=260, slot=0
[ 643.397609] BTRFS info (device sdg): leaf 38506496 total ptrs 0 free space 3995
[ 643.407075] assertion failed: 0, file: fs/btrfs/disk-io.c, line: 4078
[ 643.408425] ------------[ cut here ]------------
[ 643.409112] kernel BUG at fs/btrfs/ctree.h:3419!
[ 643.409773] invalid opcode: 0000 [#1] PREEMPT SMP
[ 643.410447] Modules linked in: dm_flakey dm_mod crc32c_generic btrfs xor raid6_pq ppdev psmouse acpi_cpufreq parport_pc evdev parport tpm_tis tpm_tis_core pcspkr serio_raw i2c_piix4 sg tpm i2c_core button processor loop autofs4 ext4 crc16 jbd2 mbcache sr_mod cdrom sd_mod ata_generic virtio_scsi ata_piix libata virtio_pci virtio_ring scsi_mod virtio e1000 floppy
[ 643.414356] CPU: 11 PID: 32726 Comm: btrfs Not tainted 4.8.0-rc8-btrfs-next-35+ #1
[ 643.414356] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.9.1-0-gb3ef39f-prebuilt.qemu-project.org 04/01/2014
[ 643.414356] task: ffff880145e95b00 task.stack: ffff88014826c000
[ 643.414356] RIP: 0010:[<ffffffffa0352759>] [<ffffffffa0352759>] assfail.constprop.41+0x1c/0x1e [btrfs]
[ 643.414356] RSP: 0018:ffff88014826fa28 EFLAGS: 00010292
[ 643.414356] RAX: 0000000000000039 RBX: ffff88014e2d7c38 RCX: 0000000000000001
[ 643.414356] RDX: ffff88023f4d2f58 RSI: ffffffff81806c63 RDI: 00000000ffffffff
[ 643.414356] RBP: ffff88014826fa28 R08: 0000000000000001 R09: 0000000000000000
[ 643.414356] R10: ffff88014826f918 R11: ffffffff82f3c5ed R12: ffff880172910000
[ 643.414356] R13: ffff880233992230 R14: ffff8801a68a3310 R15: fffffffffffffff8
[ 643.414356] FS: 00007f9ca305e8c0(0000) GS:ffff88023f4c0000(0000) knlGS:0000000000000000
[ 643.414356] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 643.414356] CR2: 00007f9ca3071000 CR3: 000000015d01b000 CR4: 00000000000006e0
[ 643.414356] Stack:
[ 643.414356] ffff88014826fa50 ffffffffa02d655a 000000000000000a ffff88014e2d7c38
[ 643.414356] 0000000000000000 ffff88014826faa8 ffffffffa02b72f3 ffff88014826fab8
[ 643.414356] 00ffffffa03228e4 0000000000000000 0000000000000000 ffff8801bbd4e000
[ 643.414356] Call Trace:
[ 643.414356] [<ffffffffa02d655a>] btrfs_mark_buffer_dirty+0xdf/0xe5 [btrfs]
[ 643.414356] [<ffffffffa02b72f3>] btrfs_copy_root+0x18a/0x1d1 [btrfs]
[ 643.414356] [<ffffffffa0322921>] create_reloc_root+0x72/0x1ba [btrfs]
[ 643.414356] [<ffffffffa03267c2>] btrfs_init_reloc_root+0x7b/0xa7 [btrfs]
[ 643.414356] [<ffffffffa02d9e44>] record_root_in_trans+0xdf/0xed [btrfs]
[ 643.414356] [<ffffffffa02db04e>] btrfs_record_root_in_trans+0x50/0x6a [btrfs]
[ 643.414356] [<ffffffffa030ad2b>] create_subvol+0x472/0x773 [btrfs]
[ 643.414356] [<ffffffffa030b406>] btrfs_mksubvol+0x3da/0x463 [btrfs]
[ 643.414356] [<ffffffffa030b406>] ? btrfs_mksubvol+0x3da/0x463 [btrfs]
[ 643.414356] [<ffffffff810781ac>] ? preempt_count_add+0x65/0x68
[ 643.414356] [<ffffffff811a6e97>] ? __mnt_want_write+0x62/0x77
[ 643.414356] [<ffffffffa030b55d>] btrfs_ioctl_snap_create_transid+0xce/0x187 [btrfs]
[ 643.414356] [<ffffffffa030b67d>] btrfs_ioctl_snap_create+0x67/0x81 [btrfs]
[ 643.414356] [<ffffffffa030ecfd>] btrfs_ioctl+0x508/0x20dd [btrfs]
[ 643.414356] [<ffffffff81293e39>] ? __this_cpu_preempt_check+0x13/0x15
[ 643.414356] [<ffffffff81155eca>] ? handle_mm_fault+0x976/0x9ab
[ 643.414356] [<ffffffff81091300>] ? arch_local_irq_save+0x9/0xc
[ 643.414356] [<ffffffff8119a2b0>] vfs_ioctl+0x18/0x34
[ 643.414356] [<ffffffff8119a8e8>] do_vfs_ioctl+0x581/0x600
[ 643.414356] [<ffffffff814b9552>] ? entry_SYSCALL_64_fastpath+0x5/0xa8
[ 643.414356] [<ffffffff81093fe9>] ? trace_hardirqs_on_caller+0x17b/0x197
[ 643.414356] [<ffffffff8119a9be>] SyS_ioctl+0x57/0x79
[ 643.414356] [<ffffffff814b9565>] entry_SYSCALL_64_fastpath+0x18/0xa8
[ 643.414356] [<ffffffff81091b08>] ? trace_hardirqs_off_caller+0x3f/0xaa
[ 643.414356] Code: 89 83 88 00 00 00 31 c0 5b 41 5c 41 5d 5d c3 55 89 f1 48 c7 c2 98 bc 35 a0 48 89 fe 48 c7 c7 05 be 35 a0 48 89 e5 e8 13 46 dd e0 <0f> 0b 55 89 f1 48 c7 c2 9f d3 35 a0 48 89 fe 48 c7 c7 7a d5 35
[ 643.414356] RIP [<ffffffffa0352759>] assfail.constprop.41+0x1c/0x1e [btrfs]
[ 643.414356] RSP <ffff88014826fa28>
[ 643.468267] ---[ end trace 6a1b3fb1a9d7d6e3 ]---
This can be easily reproduced by running xfstests with the integrity
checker enabled.
Fixes: 1ba98d086fe3 (Btrfs: detect corruption when non-root leaf has zero item)
Signed-off-by: Filipe Manana <[email protected]>
Reviewed-by: Liu Bo <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
fs/btrfs/disk-io.c | 13 ++++++++++++-
1 file changed, 12 insertions(+), 1 deletion(-)
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -521,7 +521,15 @@ static noinline int check_leaf(struct bt
u32 nritems = btrfs_header_nritems(leaf);
int slot;
- if (nritems == 0) {
+ /*
+ * Extent buffers from a relocation tree have a owner field that
+ * corresponds to the subvolume tree they are based on. So just from an
+ * extent buffer alone we can not find out what is the id of the
+ * corresponding subvolume tree, so we can not figure out if the extent
+ * buffer corresponds to the root of the relocation tree or not. So skip
+ * this check for relocation trees.
+ */
+ if (nritems == 0 && !btrfs_header_flag(leaf, BTRFS_HEADER_FLAG_RELOC)) {
struct btrfs_root *check_root;
key.objectid = btrfs_header_owner(leaf);
@@ -549,6 +557,9 @@ static noinline int check_leaf(struct bt
return 0;
}
+ if (nritems == 0)
+ return 0;
+
/* Check the 0 item */
if (btrfs_item_offset_nr(leaf, 0) + btrfs_item_size_nr(leaf, 0) !=
BTRFS_LEAF_DATA_SIZE(root)) {
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Liu Bo <[email protected]>
commit ef85b25e982b5bba1530b936e283ef129f02ab9d upstream.
This can only happen with CONFIG_BTRFS_FS_CHECK_INTEGRITY=y.
Commit 1ba98d0 ("Btrfs: detect corruption when non-root leaf has zero item")
assumes that a leaf is its root when leaf->bytenr == btrfs_root_bytenr(root),
however, we should not use btrfs_root_bytenr(root) since it's mainly got
updated during committing transaction. So the check can fail when doing
COW on this leaf while it is a root.
This changes to use "if (leaf == btrfs_root_node(root))" instead, just like
how we check whether leaf is a root in __btrfs_cow_block().
Fixes: 1ba98d086fe3 (Btrfs: detect corruption when non-root leaf has zero item)
Reported-by: Jeff Mahoney <[email protected]>
Signed-off-by: Liu Bo <[email protected]>
Reviewed-by: Filipe Manana <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
fs/btrfs/disk-io.c | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -533,13 +533,17 @@ static noinline int check_leaf(struct bt
* open_ctree() some roots has not yet been set up.
*/
if (!IS_ERR_OR_NULL(check_root)) {
+ struct extent_buffer *eb;
+
+ eb = btrfs_root_node(check_root);
/* if leaf is the root, then it's fine */
- if (leaf->start !=
- btrfs_root_bytenr(&check_root->root_item)) {
+ if (leaf != eb) {
CORRUPT("non-root leaf's nritems is 0",
- leaf, root, 0);
+ leaf, check_root, 0);
+ free_extent_buffer(eb);
return -EIO;
}
+ free_extent_buffer(eb);
}
return 0;
}
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Qu Wenruo <[email protected]>
commit f04b772bfc17f502703794f4d100d12155c1a1a9 upstream.
Enhance chunk validation:
1) Num_stripes
We already have such check but it's only in super block sys chunk
array.
Now check all on-disk chunks.
2) Chunk logical
It should be aligned to sector size.
This behavior should be *DOUBLE CHECKED* for 64K sector size like
PPC64 or AArch64.
Maybe we can found some hidden bugs.
3) Chunk length
Same as chunk logical, should be aligned to sector size.
4) Stripe length
It should be power of 2.
5) Chunk type
Any bit out of TYPE_MAS | PROFILE_MASK is invalid.
With all these much restrict rules, several fuzzed image reported in
mail list should no longer cause kernel panic.
Reported-by: Vegard Nossum <[email protected]>
Signed-off-by: Qu Wenruo <[email protected]>
Signed-off-by: Chris Mason <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
fs/btrfs/volumes.c | 33 ++++++++++++++++++++++++++++++++-
1 file changed, 32 insertions(+), 1 deletion(-)
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -5814,6 +5814,7 @@ static int read_one_chunk(struct btrfs_r
struct extent_map *em;
u64 logical;
u64 length;
+ u64 stripe_len;
u64 devid;
u8 uuid[BTRFS_UUID_SIZE];
int num_stripes;
@@ -5822,6 +5823,37 @@ static int read_one_chunk(struct btrfs_r
logical = key->offset;
length = btrfs_chunk_length(leaf, chunk);
+ stripe_len = btrfs_chunk_stripe_len(leaf, chunk);
+ num_stripes = btrfs_chunk_num_stripes(leaf, chunk);
+ /* Validation check */
+ if (!num_stripes) {
+ btrfs_err(root->fs_info, "invalid chunk num_stripes: %u",
+ num_stripes);
+ return -EIO;
+ }
+ if (!IS_ALIGNED(logical, root->sectorsize)) {
+ btrfs_err(root->fs_info,
+ "invalid chunk logical %llu", logical);
+ return -EIO;
+ }
+ if (!length || !IS_ALIGNED(length, root->sectorsize)) {
+ btrfs_err(root->fs_info,
+ "invalid chunk length %llu", length);
+ return -EIO;
+ }
+ if (!is_power_of_2(stripe_len)) {
+ btrfs_err(root->fs_info, "invalid chunk stripe length: %llu",
+ stripe_len);
+ return -EIO;
+ }
+ if (~(BTRFS_BLOCK_GROUP_TYPE_MASK | BTRFS_BLOCK_GROUP_PROFILE_MASK) &
+ btrfs_chunk_type(leaf, chunk)) {
+ btrfs_err(root->fs_info, "unrecognized chunk type: %llu",
+ ~(BTRFS_BLOCK_GROUP_TYPE_MASK |
+ BTRFS_BLOCK_GROUP_PROFILE_MASK) &
+ btrfs_chunk_type(leaf, chunk));
+ return -EIO;
+ }
read_lock(&map_tree->map_tree.lock);
em = lookup_extent_mapping(&map_tree->map_tree, logical, 1);
@@ -5838,7 +5870,6 @@ static int read_one_chunk(struct btrfs_r
em = alloc_extent_map();
if (!em)
return -ENOMEM;
- num_stripes = btrfs_chunk_num_stripes(leaf, chunk);
map = kmalloc(map_lookup_size(num_stripes), GFP_NOFS);
if (!map) {
free_extent_map(em);
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Liu Bo <[email protected]>
commit e06cd3dd7cea50e87663a88acdfdb7ac1c53a5ca upstream.
To prevent fuzzed filesystem images from panic the whole system,
we need various validation checks to refuse to mount such an image
if btrfs finds any invalid value during loading chunks, including
both sys_array and regular chunks.
Note that these checks may not be sufficient to cover all corner cases,
feel free to add more checks.
Reported-by: Vegard Nossum <[email protected]>
Reported-by: Quentin Casasnovas <[email protected]>
Reviewed-by: David Sterba <[email protected]>
Signed-off-by: Liu Bo <[email protected]>
Signed-off-by: David Sterba <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
fs/btrfs/volumes.c | 82 +++++++++++++++++++++++++++++++++++++---------
1 file changed, 67 insertions(+), 15 deletions(-)
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -5805,27 +5805,23 @@ struct btrfs_device *btrfs_alloc_device(
return dev;
}
-static int read_one_chunk(struct btrfs_root *root, struct btrfs_key *key,
- struct extent_buffer *leaf,
- struct btrfs_chunk *chunk)
+/* Return -EIO if any error, otherwise return 0. */
+static int btrfs_check_chunk_valid(struct btrfs_root *root,
+ struct extent_buffer *leaf,
+ struct btrfs_chunk *chunk, u64 logical)
{
- struct btrfs_mapping_tree *map_tree = &root->fs_info->mapping_tree;
- struct map_lookup *map;
- struct extent_map *em;
- u64 logical;
u64 length;
u64 stripe_len;
- u64 devid;
- u8 uuid[BTRFS_UUID_SIZE];
- int num_stripes;
- int ret;
- int i;
+ u16 num_stripes;
+ u16 sub_stripes;
+ u64 type;
- logical = key->offset;
length = btrfs_chunk_length(leaf, chunk);
stripe_len = btrfs_chunk_stripe_len(leaf, chunk);
num_stripes = btrfs_chunk_num_stripes(leaf, chunk);
- /* Validation check */
+ sub_stripes = btrfs_chunk_sub_stripes(leaf, chunk);
+ type = btrfs_chunk_type(leaf, chunk);
+
if (!num_stripes) {
btrfs_err(root->fs_info, "invalid chunk num_stripes: %u",
num_stripes);
@@ -5836,6 +5832,11 @@ static int read_one_chunk(struct btrfs_r
"invalid chunk logical %llu", logical);
return -EIO;
}
+ if (btrfs_chunk_sector_size(leaf, chunk) != root->sectorsize) {
+ btrfs_err(root->fs_info, "invalid chunk sectorsize %u",
+ btrfs_chunk_sector_size(leaf, chunk));
+ return -EIO;
+ }
if (!length || !IS_ALIGNED(length, root->sectorsize)) {
btrfs_err(root->fs_info,
"invalid chunk length %llu", length);
@@ -5847,13 +5848,54 @@ static int read_one_chunk(struct btrfs_r
return -EIO;
}
if (~(BTRFS_BLOCK_GROUP_TYPE_MASK | BTRFS_BLOCK_GROUP_PROFILE_MASK) &
- btrfs_chunk_type(leaf, chunk)) {
+ type) {
btrfs_err(root->fs_info, "unrecognized chunk type: %llu",
~(BTRFS_BLOCK_GROUP_TYPE_MASK |
BTRFS_BLOCK_GROUP_PROFILE_MASK) &
btrfs_chunk_type(leaf, chunk));
return -EIO;
}
+ if ((type & BTRFS_BLOCK_GROUP_RAID10 && sub_stripes != 2) ||
+ (type & BTRFS_BLOCK_GROUP_RAID1 && num_stripes < 1) ||
+ (type & BTRFS_BLOCK_GROUP_RAID5 && num_stripes < 2) ||
+ (type & BTRFS_BLOCK_GROUP_RAID6 && num_stripes < 3) ||
+ (type & BTRFS_BLOCK_GROUP_DUP && num_stripes > 2) ||
+ ((type & BTRFS_BLOCK_GROUP_PROFILE_MASK) == 0 &&
+ num_stripes != 1)) {
+ btrfs_err(root->fs_info,
+ "invalid num_stripes:sub_stripes %u:%u for profile %llu",
+ num_stripes, sub_stripes,
+ type & BTRFS_BLOCK_GROUP_PROFILE_MASK);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static int read_one_chunk(struct btrfs_root *root, struct btrfs_key *key,
+ struct extent_buffer *leaf,
+ struct btrfs_chunk *chunk)
+{
+ struct btrfs_mapping_tree *map_tree = &root->fs_info->mapping_tree;
+ struct map_lookup *map;
+ struct extent_map *em;
+ u64 logical;
+ u64 length;
+ u64 stripe_len;
+ u64 devid;
+ u8 uuid[BTRFS_UUID_SIZE];
+ int num_stripes;
+ int ret;
+ int i;
+
+ logical = key->offset;
+ length = btrfs_chunk_length(leaf, chunk);
+ stripe_len = btrfs_chunk_stripe_len(leaf, chunk);
+ num_stripes = btrfs_chunk_num_stripes(leaf, chunk);
+
+ ret = btrfs_check_chunk_valid(root, leaf, chunk, logical);
+ if (ret)
+ return ret;
read_lock(&map_tree->map_tree.lock);
em = lookup_extent_mapping(&map_tree->map_tree, logical, 1);
@@ -6070,6 +6112,7 @@ int btrfs_read_sys_array(struct btrfs_ro
u32 array_size;
u32 len = 0;
u32 cur_offset;
+ u64 type;
struct btrfs_key key;
sb = btrfs_find_create_tree_block(root, BTRFS_SUPER_INFO_OFFSET,
@@ -6130,6 +6173,15 @@ int btrfs_read_sys_array(struct btrfs_ro
ret = -EIO;
break;
}
+
+ type = btrfs_chunk_type(sb, chunk);
+ if ((type & BTRFS_BLOCK_GROUP_SYSTEM) == 0) {
+ btrfs_err(root->fs_info,
+ "invalid chunk type %llu in sys_array at offset %u",
+ type, cur_offset);
+ ret = -EIO;
+ break;
+ }
len = btrfs_chunk_item_size(num_stripes);
if (cur_offset + len > array_size)
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Liu Bo <[email protected]>
commit 1ba98d086fe3a14d6a31f2f66dbab70c45d00f63 upstream.
Right now we treat leaf which has zero item as a valid one
because we could have an empty tree, that is, a root that is
also a leaf without any item, however, in the same case but
when the leaf is not a root, we can end up with hitting the
BUG_ON(1) in btrfs_extend_item() called by
setup_inline_extent_backref().
This makes us check the situation as a corruption if leaf is
not its own root.
Signed-off-by: Liu Bo <[email protected]>
Reviewed-by: David Sterba <[email protected]>
Signed-off-by: David Sterba <[email protected]>
Signed-off-by: Chris Mason <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
fs/btrfs/disk-io.c | 23 ++++++++++++++++++++++-
1 file changed, 22 insertions(+), 1 deletion(-)
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -520,8 +520,29 @@ static noinline int check_leaf(struct bt
u32 nritems = btrfs_header_nritems(leaf);
int slot;
- if (nritems == 0)
+ if (nritems == 0) {
+ struct btrfs_root *check_root;
+
+ key.objectid = btrfs_header_owner(leaf);
+ key.type = BTRFS_ROOT_ITEM_KEY;
+ key.offset = (u64)-1;
+
+ check_root = btrfs_get_fs_root(root->fs_info, &key, false);
+ /*
+ * The only reason we also check NULL here is that during
+ * open_ctree() some roots has not yet been set up.
+ */
+ if (!IS_ERR_OR_NULL(check_root)) {
+ /* if leaf is the root, then it's fine */
+ if (leaf->start !=
+ btrfs_root_bytenr(&check_root->root_item)) {
+ CORRUPT("non-root leaf's nritems is 0",
+ leaf, root, 0);
+ return -EIO;
+ }
+ }
return 0;
+ }
/* Check the 0 item */
if (btrfs_item_offset_nr(leaf, 0) + btrfs_item_size_nr(leaf, 0) !=
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Liu Bo <[email protected]>
commit 053ab70f0604224c7893b43f9d9d5efa283580d6 upstream.
When btree node (level = 1) has nritems which equals to zero,
we can end up with panic due to insert_ptr()'s
BUG_ON(slot > nritems);
where slot is 1 and nritems is 0, as copy_for_split() calls
insert_ptr(.., path->slots[1] + 1, ...);
A invalid value results in the whole mess, this adds the check
for btree's node nritems so that we stop reading block when
when something is wrong.
Signed-off-by: Liu Bo <[email protected]>
Reviewed-by: David Sterba <[email protected]>
Signed-off-by: David Sterba <[email protected]>
Signed-off-by: Chris Mason <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
fs/btrfs/disk-io.c | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -594,6 +594,19 @@ static noinline int check_leaf(struct bt
return 0;
}
+static int check_node(struct btrfs_root *root, struct extent_buffer *node)
+{
+ unsigned long nr = btrfs_header_nritems(node);
+
+ if (nr == 0 || nr > BTRFS_NODEPTRS_PER_BLOCK(root)) {
+ btrfs_crit(root->fs_info,
+ "corrupt node: block %llu root %llu nritems %lu",
+ node->start, root->objectid, nr);
+ return -EIO;
+ }
+ return 0;
+}
+
static int btree_readpage_end_io_hook(struct btrfs_io_bio *io_bio,
u64 phy_offset, struct page *page,
u64 start, u64 end, int mirror)
@@ -666,6 +679,9 @@ static int btree_readpage_end_io_hook(st
ret = -EIO;
}
+ if (found_level > 0 && check_node(root, eb))
+ ret = -EIO;
+
if (!ret)
set_extent_buffer_uptodate(eb);
err:
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Liu Bo <[email protected]>
commit 02794222c4132ac003e7281fb71f4ec1645ffc87 upstream.
In a corrupted btrfs image, we can come across this BUG_ON and
get an unreponsive system, but if we return errors instead,
its caller can handle everything gracefully by aborting the current
transaction.
Signed-off-by: Liu Bo <[email protected]>
Signed-off-by: David Sterba <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
fs/btrfs/extent-tree.c | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -2258,7 +2258,13 @@ static int run_delayed_tree_ref(struct b
ins.type = BTRFS_EXTENT_ITEM_KEY;
}
- BUG_ON(node->ref_mod != 1);
+ if (node->ref_mod != 1) {
+ btrfs_err(root->fs_info,
+ "btree block(%llu) has %d references rather than 1: action %d ref_root %llu parent %llu",
+ node->bytenr, node->ref_mod, node->action, ref_root,
+ parent);
+ return -EIO;
+ }
if (node->action == BTRFS_ADD_DELAYED_REF && insert_reserved) {
BUG_ON(!extent_op || !extent_op->update_flags);
ret = alloc_reserved_tree_block(trans, root,
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Liu Bo <[email protected]>
commit 6b722c1747d533ac6d4df110dc8233db46918b65 upstream.
We need to check items in a node to make sure that we're reading
a valid one, otherwise we could get various crashes while processing
delayed_refs.
Signed-off-by: Liu Bo <[email protected]>
Reviewed-by: David Sterba <[email protected]>
Signed-off-by: David Sterba <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
fs/btrfs/disk-io.c | 32 ++++++++++++++++++++++++++++----
1 file changed, 28 insertions(+), 4 deletions(-)
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -508,9 +508,10 @@ static int check_tree_block_fsid(struct
}
#define CORRUPT(reason, eb, root, slot) \
- btrfs_crit(root->fs_info, "corrupt leaf, %s: block=%llu," \
- "root=%llu, slot=%d", reason, \
- btrfs_header_bytenr(eb), root->objectid, slot)
+ btrfs_crit(root->fs_info, "corrupt %s, %s: block=%llu," \
+ " root=%llu, slot=%d", \
+ btrfs_header_level(eb) == 0 ? "leaf" : "node",\
+ reason, btrfs_header_bytenr(eb), root->objectid, slot)
static noinline int check_leaf(struct btrfs_root *root,
struct extent_buffer *leaf)
@@ -601,6 +602,10 @@ static noinline int check_leaf(struct bt
static int check_node(struct btrfs_root *root, struct extent_buffer *node)
{
unsigned long nr = btrfs_header_nritems(node);
+ struct btrfs_key key, next_key;
+ int slot;
+ u64 bytenr;
+ int ret = 0;
if (nr == 0 || nr > BTRFS_NODEPTRS_PER_BLOCK(root)) {
btrfs_crit(root->fs_info,
@@ -608,7 +613,26 @@ static int check_node(struct btrfs_root
node->start, root->objectid, nr);
return -EIO;
}
- return 0;
+
+ for (slot = 0; slot < nr - 1; slot++) {
+ bytenr = btrfs_node_blockptr(node, slot);
+ btrfs_node_key_to_cpu(node, &key, slot);
+ btrfs_node_key_to_cpu(node, &next_key, slot + 1);
+
+ if (!bytenr) {
+ CORRUPT("invalid item slot", node, root, slot);
+ ret = -EIO;
+ goto out;
+ }
+
+ if (btrfs_comp_cpu_keys(&key, &next_key) >= 0) {
+ CORRUPT("bad key order", node, root, slot);
+ ret = -EIO;
+ goto out;
+ }
+ }
+out:
+ return ret;
}
static int btree_readpage_end_io_hook(struct btrfs_io_bio *io_bio,
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Josef Bacik <[email protected]>
commit 187ee58c62c1d0d238d3dc4835869d33e1869906 upstream.
We need to call free_extent_map() on the em we look up.
Signed-off-by: Josef Bacik <[email protected]>
Reviewed-by: Omar Sandoval <[email protected]>
Signed-off-by: David Sterba <[email protected]>
Signed-off-by: Chris Mason <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
fs/btrfs/extent-tree.c | 1 +
1 file changed, 1 insertion(+)
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -8587,6 +8587,7 @@ static int find_first_block_group(struct
} else {
ret = 0;
}
+ free_extent_map(em);
goto out;
}
path->slots[0]++;
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: David Sterba <[email protected]>
commit f5cdedd73fa71b74dcc42f2a11a5735d89ce7c4f upstream.
We can handle the special case of num_stripes == 0 directly inside
btrfs_read_sys_array. The BUG_ON in btrfs_chunk_item_size is there to
catch other unhandled cases where we fail to validate external data.
A crafted or corrupted image crashes at mount time:
BTRFS: device fsid 9006933e-2a9a-44f0-917f-514252aeec2c devid 1 transid 7 /dev/loop0
BTRFS info (device loop0): disk space caching is enabled
BUG: failure at fs/btrfs/ctree.h:337/btrfs_chunk_item_size()!
Kernel panic - not syncing: BUG!
CPU: 0 PID: 313 Comm: mount Not tainted 4.2.5-00657-ge047887-dirty #25
Stack:
637af890 60062489 602aeb2e 604192ba
60387961 00000011 637af8a0 6038a835
637af9c0 6038776b 634ef32b 00000000
Call Trace:
[<6001c86d>] show_stack+0xfe/0x15b
[<6038a835>] dump_stack+0x2a/0x2c
[<6038776b>] panic+0x13e/0x2b3
[<6020f099>] btrfs_read_sys_array+0x25d/0x2ff
[<601cfbbe>] open_ctree+0x192d/0x27af
[<6019c2c1>] btrfs_mount+0x8f5/0xb9a
[<600bc9a7>] mount_fs+0x11/0xf3
[<600d5167>] vfs_kern_mount+0x75/0x11a
[<6019bcb0>] btrfs_mount+0x2e4/0xb9a
[<600bc9a7>] mount_fs+0x11/0xf3
[<600d5167>] vfs_kern_mount+0x75/0x11a
[<600d710b>] do_mount+0xa35/0xbc9
[<600d7557>] SyS_mount+0x95/0xc8
[<6001e884>] handle_syscall+0x6b/0x8e
Reported-by: Jiri Slaby <[email protected]>
Reported-by: Vegard Nossum <[email protected]>
Signed-off-by: David Sterba <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
fs/btrfs/volumes.c | 8 ++++++++
1 file changed, 8 insertions(+)
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -6092,6 +6092,14 @@ int btrfs_read_sys_array(struct btrfs_ro
goto out_short_read;
num_stripes = btrfs_chunk_num_stripes(sb, chunk);
+ if (!num_stripes) {
+ printk(KERN_ERR
+ "BTRFS: invalid number of stripes %u in sys_array at offset %u\n",
+ num_stripes, cur_offset);
+ ret = -EIO;
+ break;
+ }
+
len = btrfs_chunk_item_size(num_stripes);
if (cur_offset + len > array_size)
goto out_short_read;
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: David Sterba <[email protected]>
commit e3540eab29e1b2260bc4b9b3979a49a00e3e3af8 upstream.
Verify that the sys_array has enough bytes to read the next item.
Signed-off-by: David Sterba <[email protected]>
Signed-off-by: Chris Mason <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
fs/btrfs/volumes.c | 26 +++++++++++++++++++++++---
1 file changed, 23 insertions(+), 3 deletions(-)
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -6071,20 +6071,34 @@ int btrfs_read_sys_array(struct btrfs_ro
while (cur_offset < array_size) {
disk_key = (struct btrfs_disk_key *)array_ptr;
+ len = sizeof(*disk_key);
+ if (cur_offset + len > array_size)
+ goto out_short_read;
+
btrfs_disk_key_to_cpu(&key, disk_key);
- len = sizeof(*disk_key);
array_ptr += len;
sb_array_offset += len;
cur_offset += len;
if (key.type == BTRFS_CHUNK_ITEM_KEY) {
chunk = (struct btrfs_chunk *)sb_array_offset;
+ /*
+ * At least one btrfs_chunk with one stripe must be
+ * present, exact stripe count check comes afterwards
+ */
+ len = btrfs_chunk_item_size(1);
+ if (cur_offset + len > array_size)
+ goto out_short_read;
+
+ num_stripes = btrfs_chunk_num_stripes(sb, chunk);
+ len = btrfs_chunk_item_size(num_stripes);
+ if (cur_offset + len > array_size)
+ goto out_short_read;
+
ret = read_one_chunk(root, &key, sb, chunk);
if (ret)
break;
- num_stripes = btrfs_chunk_num_stripes(sb, chunk);
- len = btrfs_chunk_item_size(num_stripes);
} else {
ret = -EIO;
break;
@@ -6095,6 +6109,12 @@ int btrfs_read_sys_array(struct btrfs_ro
}
free_extent_buffer(sb);
return ret;
+
+out_short_read:
+ printk(KERN_ERR "BTRFS: sys_array too short to read %u bytes at offset %u\n",
+ len, cur_offset);
+ free_extent_buffer(sb);
+ return -EIO;
}
int btrfs_read_chunk_tree(struct btrfs_root *root)
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: David Sterba <[email protected]>
commit 1ffb22cf8c322bbfea6b35fe23d025841b49fede upstream.
There's a pointer to buffer, integer offset and offset passed as
pointer, try to find matching names for them.
Signed-off-by: David Sterba <[email protected]>
Signed-off-by: Chris Mason <[email protected]>
[bwh: Backported to 3.16 as dependency of fixes to this function]
Signed-off-by: Ben Hutchings <[email protected]>
---
fs/btrfs/volumes.c | 31 ++++++++++++++++---------------
1 file changed, 16 insertions(+), 15 deletions(-)
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -6032,13 +6032,13 @@ int btrfs_read_sys_array(struct btrfs_ro
struct extent_buffer *sb;
struct btrfs_disk_key *disk_key;
struct btrfs_chunk *chunk;
- u8 *ptr;
- unsigned long sb_ptr;
+ u8 *array_ptr;
+ unsigned long sb_array_offset;
int ret = 0;
u32 num_stripes;
u32 array_size;
u32 len = 0;
- u32 cur;
+ u32 cur_offset;
struct btrfs_key key;
sb = btrfs_find_create_tree_block(root, BTRFS_SUPER_INFO_OFFSET,
@@ -6065,20 +6065,21 @@ int btrfs_read_sys_array(struct btrfs_ro
write_extent_buffer(sb, super_copy, 0, BTRFS_SUPER_INFO_SIZE);
array_size = btrfs_super_sys_array_size(super_copy);
- ptr = super_copy->sys_chunk_array;
- sb_ptr = offsetof(struct btrfs_super_block, sys_chunk_array);
- cur = 0;
+ array_ptr = super_copy->sys_chunk_array;
+ sb_array_offset = offsetof(struct btrfs_super_block, sys_chunk_array);
+ cur_offset = 0;
- while (cur < array_size) {
- disk_key = (struct btrfs_disk_key *)ptr;
+ while (cur_offset < array_size) {
+ disk_key = (struct btrfs_disk_key *)array_ptr;
btrfs_disk_key_to_cpu(&key, disk_key);
- len = sizeof(*disk_key); ptr += len;
- sb_ptr += len;
- cur += len;
+ len = sizeof(*disk_key);
+ array_ptr += len;
+ sb_array_offset += len;
+ cur_offset += len;
if (key.type == BTRFS_CHUNK_ITEM_KEY) {
- chunk = (struct btrfs_chunk *)sb_ptr;
+ chunk = (struct btrfs_chunk *)sb_array_offset;
ret = read_one_chunk(root, &key, sb, chunk);
if (ret)
break;
@@ -6088,9 +6089,9 @@ int btrfs_read_sys_array(struct btrfs_ro
ret = -EIO;
break;
}
- ptr += len;
- sb_ptr += len;
- cur += len;
+ array_ptr += len;
+ sb_array_offset += len;
+ cur_offset += len;
}
free_extent_buffer(sb);
return ret;
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Liu Bo <[email protected]>
commit 851cd173f06045816528176001cf82948282029c upstream.
This is an additional patch to
"Btrfs: memset to avoid stale content in btree node block".
This uses memset to initialize the unused space in a leaf to avoid
potential stale content, which may be incurred by pushing items
between sibling leaves.
Signed-off-by: Liu Bo <[email protected]>
Reviewed-by: David Sterba <[email protected]>
Signed-off-by: David Sterba <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
fs/btrfs/ctree.c | 14 --------------
fs/btrfs/ctree.h | 15 +++++++++++++++
fs/btrfs/extent_io.c | 18 +++++++++++++-----
3 files changed, 28 insertions(+), 19 deletions(-)
--- a/fs/btrfs/ctree.c
+++ b/fs/btrfs/ctree.c
@@ -1721,20 +1721,6 @@ int btrfs_realloc_node(struct btrfs_tran
return err;
}
-/*
- * The leaf data grows from end-to-front in the node.
- * this returns the address of the start of the last item,
- * which is the stop of the leaf data stack
- */
-static inline unsigned int leaf_data_end(struct btrfs_root *root,
- struct extent_buffer *leaf)
-{
- u32 nr = btrfs_header_nritems(leaf);
- if (nr == 0)
- return BTRFS_LEAF_DATA_SIZE(root);
- return btrfs_item_offset_nr(leaf, nr - 1);
-}
-
/*
* search for key in the extent_buffer. The items start at offset p,
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -3036,6 +3036,21 @@ static inline unsigned long btrfs_leaf_d
return offsetof(struct btrfs_leaf, items);
}
+/*
+ * The leaf data grows from end-to-front in the node.
+ * this returns the address of the start of the last item,
+ * which is the stop of the leaf data stack
+ */
+static inline unsigned int leaf_data_end(struct btrfs_root *root,
+ struct extent_buffer *leaf)
+{
+ u32 nr = btrfs_header_nritems(leaf);
+
+ if (nr == 0)
+ return BTRFS_LEAF_DATA_SIZE(root);
+ return btrfs_item_offset_nr(leaf, nr - 1);
+}
+
/* struct btrfs_file_extent_item */
BTRFS_SETGET_FUNCS(file_extent_type, struct btrfs_file_extent_item, type, 8);
BTRFS_SETGET_STACK_FUNCS(stack_file_extent_disk_bytenr,
--- a/fs/btrfs/extent_io.c
+++ b/fs/btrfs/extent_io.c
@@ -3617,8 +3617,10 @@ static noinline_for_stack int write_one_
struct block_device *bdev = fs_info->fs_devices->latest_bdev;
struct extent_io_tree *tree = &BTRFS_I(fs_info->btree_inode)->io_tree;
u64 offset = eb->start;
+ u32 nritems;
unsigned long i, num_pages;
unsigned long bio_flags = 0;
+ unsigned long start, end;
int rw = (epd->sync_io ? WRITE_SYNC : WRITE) | REQ_META;
int ret = 0;
@@ -3628,15 +3630,21 @@ static noinline_for_stack int write_one_
if (btrfs_header_owner(eb) == BTRFS_TREE_LOG_OBJECTID)
bio_flags = EXTENT_BIO_TREE_LOG;
- /* set btree node beyond nritems with 0 to avoid stale content */
+ /* set btree blocks beyond nritems with 0 to avoid stale content. */
+ nritems = btrfs_header_nritems(eb);
if (btrfs_header_level(eb) > 0) {
- u32 nritems;
- unsigned long end;
-
- nritems = btrfs_header_nritems(eb);
end = btrfs_node_key_ptr_offset(nritems);
memset_extent_buffer(eb, 0, end, eb->len - end);
+ } else {
+ /*
+ * leaf:
+ * header 0 1 2 .. N ... data_N .. data_2 data_1 data_0
+ */
+ start = btrfs_item_nr_offset(nritems);
+ end = btrfs_leaf_data(eb) +
+ leaf_data_end(fs_info->tree_root, eb);
+ memset_extent_buffer(eb, 0, start, end - start);
}
for (i = 0; i < num_pages; i++) {
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Qu Wenruo <[email protected]>
commit f556faa46eb4e96d0d0772e74ecf66781e132f72 upstream.
Although we have tree level check at tree read runtime, it's completely
based on its parent level.
We still need to do accurate level check to avoid invalid tree blocks
sneak into kernel space.
The check itself is simple, for leaf its level should always be 0.
For nodes its level should be in range [1, BTRFS_MAX_LEVEL - 1].
Signed-off-by: Qu Wenruo <[email protected]>
Reviewed-by: Su Yue <[email protected]>
Reviewed-by: David Sterba <[email protected]>
Signed-off-by: David Sterba <[email protected]>
[bwh: Backported to 4.4:
- Pass root instead of fs_info to generic_err()
- Adjust context]
Signed-off-by: Ben Hutchings <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
fs/btrfs/tree-checker.c | 14 ++++++++++++++
1 file changed, 14 insertions(+)
--- a/fs/btrfs/tree-checker.c
+++ b/fs/btrfs/tree-checker.c
@@ -447,6 +447,13 @@ static int check_leaf(struct btrfs_root
u32 nritems = btrfs_header_nritems(leaf);
int slot;
+ if (btrfs_header_level(leaf) != 0) {
+ generic_err(root, leaf, 0,
+ "invalid level for leaf, have %d expect 0",
+ btrfs_header_level(leaf));
+ return -EUCLEAN;
+ }
+
/*
* Extent buffers from a relocation tree have a owner field that
* corresponds to the subvolume tree they are based on. So just from an
@@ -589,9 +596,16 @@ int btrfs_check_node(struct btrfs_root *
unsigned long nr = btrfs_header_nritems(node);
struct btrfs_key key, next_key;
int slot;
+ int level = btrfs_header_level(node);
u64 bytenr;
int ret = 0;
+ if (level <= 0 || level >= BTRFS_MAX_LEVEL) {
+ generic_err(root, node, 0,
+ "invalid level for node, have %d expect [1, %d]",
+ level, BTRFS_MAX_LEVEL - 1);
+ return -EUCLEAN;
+ }
if (nr == 0 || nr > BTRFS_NODEPTRS_PER_BLOCK(root)) {
btrfs_crit(root->fs_info,
"corrupt node: root=%llu block=%llu, nritems too %s, have %lu expect range [1,%zu]",
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: David Sterba <[email protected]>
commit e2683fc9d219430f5b78889b50cde7f40efeba7b upstream.
I've noticed that the updated item checker stack consumption increased
dramatically in 542f5385e20cf97447 ("btrfs: tree-checker: Add checker
for dir item")
tree-checker.c:check_leaf +552 (176 -> 728)
The array is 255 bytes long, dynamic allocation would slow down the
sanity checks so it's more reasonable to keep it on-stack. Moving the
variable to the scope of use reduces the stack usage again
tree-checker.c:check_leaf -264 (728 -> 464)
Reviewed-by: Josef Bacik <[email protected]>
Reviewed-by: Qu Wenruo <[email protected]>
Signed-off-by: David Sterba <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
fs/btrfs/tree-checker.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
--- a/fs/btrfs/tree-checker.c
+++ b/fs/btrfs/tree-checker.c
@@ -212,7 +212,6 @@ static int check_dir_item(struct btrfs_r
di = btrfs_item_ptr(leaf, slot, struct btrfs_dir_item);
while (cur < item_size) {
- char namebuf[max(BTRFS_NAME_LEN, XATTR_NAME_MAX)];
u32 name_len;
u32 data_len;
u32 max_name_len;
@@ -295,6 +294,8 @@ static int check_dir_item(struct btrfs_r
*/
if (key->type == BTRFS_DIR_ITEM_KEY ||
key->type == BTRFS_XATTR_ITEM_KEY) {
+ char namebuf[max(BTRFS_NAME_LEN, XATTR_NAME_MAX)];
+
read_extent_buffer(leaf, namebuf,
(unsigned long)(di + 1), name_len);
name_hash = btrfs_name_hash(namebuf, name_len);
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Wang Shilong <[email protected]>
commit c01a5c074c0f6f85a3b02e39432b9e5576ab51de upstream.
inline data is stored from offset of @disk_bytenr in
struct btrfs_file_extent_item. So substracting total
size of struct btrfs_file_extent_item is wrong, fix it.
Signed-off-by: Wang Shilong <[email protected]>
Reviewed-by: David Sterba <[email protected]>
Signed-off-by: Chris Mason <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
fs/btrfs/ctree.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -394,7 +394,7 @@ struct btrfs_header {
#define BTRFS_LEAF_DATA_SIZE(r) (__BTRFS_LEAF_DATA_SIZE(r->leafsize))
#define BTRFS_MAX_INLINE_DATA_SIZE(r) (BTRFS_LEAF_DATA_SIZE(r) - \
sizeof(struct btrfs_item) - \
- sizeof(struct btrfs_file_extent_item))
+ offsetof(struct btrfs_file_extent_item, disk_bytenr))
#define BTRFS_MAX_XATTR_SIZE(r) (BTRFS_LEAF_DATA_SIZE(r) - \
sizeof(struct btrfs_item) -\
sizeof(struct btrfs_dir_item))
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: David Sterba <[email protected]>
commit 7ec20afbcb7b257aec82ea5d66e6b0b7499abaca upstream.
Use a common definition for the inline data start so we don't have to
open-code it and introduce bugs like "Btrfs: fix wrong max inline data
size limit" fixed.
Signed-off-by: David Sterba <[email protected]>
[bwh: Backported to 3.16 as dependency of various fixes: adjust context]
Signed-off-by: Ben Hutchings <[email protected]>
---
fs/btrfs/ctree.c | 3 +--
fs/btrfs/ctree.h | 16 ++++++++--------
2 files changed, 9 insertions(+), 10 deletions(-)
--- a/fs/btrfs/ctree.c
+++ b/fs/btrfs/ctree.c
@@ -4609,8 +4609,7 @@ void btrfs_truncate_item(struct btrfs_ro
ptr = btrfs_item_ptr_offset(leaf, slot);
memmove_extent_buffer(leaf, ptr,
(unsigned long)fi,
- offsetof(struct btrfs_file_extent_item,
- disk_bytenr));
+ BTRFS_FILE_EXTENT_INLINE_DATA_START);
}
}
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -392,9 +392,11 @@ struct btrfs_header {
sizeof(struct btrfs_key_ptr))
#define __BTRFS_LEAF_DATA_SIZE(bs) ((bs) - sizeof(struct btrfs_header))
#define BTRFS_LEAF_DATA_SIZE(r) (__BTRFS_LEAF_DATA_SIZE(r->leafsize))
+#define BTRFS_FILE_EXTENT_INLINE_DATA_START \
+ (offsetof(struct btrfs_file_extent_item, disk_bytenr))
#define BTRFS_MAX_INLINE_DATA_SIZE(r) (BTRFS_LEAF_DATA_SIZE(r) - \
sizeof(struct btrfs_item) - \
- offsetof(struct btrfs_file_extent_item, disk_bytenr))
+ BTRFS_FILE_EXTENT_INLINE_DATA_START)
#define BTRFS_MAX_XATTR_SIZE(r) (BTRFS_LEAF_DATA_SIZE(r) - \
sizeof(struct btrfs_item) -\
sizeof(struct btrfs_dir_item))
@@ -904,6 +906,8 @@ struct btrfs_file_extent_item {
/*
* disk space consumed by the extent, checksum blocks are included
* in these numbers
+ *
+ * At this offset in the structure, the inline extent data start.
*/
__le64 disk_bytenr;
__le64 disk_num_bytes;
@@ -3050,14 +3054,12 @@ BTRFS_SETGET_STACK_FUNCS(stack_file_exte
static inline unsigned long
btrfs_file_extent_inline_start(struct btrfs_file_extent_item *e)
{
- unsigned long offset = (unsigned long)e;
- offset += offsetof(struct btrfs_file_extent_item, disk_bytenr);
- return offset;
+ return (unsigned long)e + BTRFS_FILE_EXTENT_INLINE_DATA_START;
}
static inline u32 btrfs_file_extent_calc_inline_size(u32 datasize)
{
- return offsetof(struct btrfs_file_extent_item, disk_bytenr) + datasize;
+ return BTRFS_FILE_EXTENT_INLINE_DATA_START + datasize;
}
BTRFS_SETGET_FUNCS(file_extent_disk_bytenr, struct btrfs_file_extent_item,
@@ -3087,9 +3089,7 @@ BTRFS_SETGET_FUNCS(file_extent_other_enc
static inline u32 btrfs_file_extent_inline_item_len(struct extent_buffer *eb,
struct btrfs_item *e)
{
- unsigned long offset;
- offset = offsetof(struct btrfs_file_extent_item, disk_bytenr);
- return btrfs_item_size(eb, e) - offset;
+ return btrfs_item_size(eb, e) - BTRFS_FILE_EXTENT_INLINE_DATA_START;
}
/* this returns the number of file bytes represented by the inline item.
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Jan Kara <[email protected]>
commit 32ebffd3bbb4162da5ff88f9a35dd32d0a28ea70 upstream.
Current code implementing FALLOC_FL_COLLAPSE_RANGE and
FALLOC_FL_INSERT_RANGE is prone to races with buffered writes and page
faults. If buffered write or write via mmap manages to squeeze between
filemap_write_and_wait_range() and truncate_pagecache() in the fallocate
implementations, the written data is simply discarded by
truncate_pagecache() although it should have been shifted.
Fix the problem by moving filemap_write_and_wait_range() call inside
i_mutex and i_mmap_sem. That way we are protected against races with
both buffered writes and page faults.
Signed-off-by: Jan Kara <[email protected]>
Signed-off-by: Theodore Ts'o <[email protected]>
[bwh: Backported to 3.16: drop changes in ext4_insert_range()]
Signed-off-by: Ben Hutchings <[email protected]>
---
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -5453,21 +5453,7 @@ int ext4_collapse_range(struct inode *in
return ret;
}
- /*
- * Need to round down offset to be aligned with page size boundary
- * for page size > block size.
- */
- ioffset = round_down(offset, PAGE_SIZE);
-
- /* Write out all dirty pages */
- ret = filemap_write_and_wait_range(inode->i_mapping, ioffset,
- LLONG_MAX);
- if (ret)
- return ret;
-
- /* Take mutex lock */
mutex_lock(&inode->i_mutex);
-
/*
* There is no need to overlap collapse range with EOF, in which case
* it is effectively a truncate operation
@@ -5492,6 +5478,27 @@ int ext4_collapse_range(struct inode *in
* page cache.
*/
down_write(&EXT4_I(inode)->i_mmap_sem);
+ /*
+ * Need to round down offset to be aligned with page size boundary
+ * for page size > block size.
+ */
+ ioffset = round_down(offset, PAGE_SIZE);
+ /*
+ * Write tail of the last page before removed range since it will get
+ * removed from the page cache below.
+ */
+ ret = filemap_write_and_wait_range(inode->i_mapping, ioffset, offset);
+ if (ret)
+ goto out_mmap;
+ /*
+ * Write data that will be shifted to preserve them when discarding
+ * page cache below. We are also protected from pages becoming dirty
+ * by i_mmap_sem.
+ */
+ ret = filemap_write_and_wait_range(inode->i_mapping, offset + len,
+ LLONG_MAX);
+ if (ret)
+ goto out_mmap;
truncate_pagecache(inode, ioffset);
credits = ext4_writepage_trans_blocks(inode);
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Brian Norris <[email protected]>
commit 65b1aae0d9d5962faccc06bdb8e91a2a0b09451c upstream.
We called rcu_read_lock(), so we need to call rcu_read_unlock() before
we return.
Fixes: 3d94a4a8373b ("mwifiex: fix possible heap overflow in mwifiex_process_country_ie()")
Cc: huangwen <[email protected]>
Cc: Ganapathi Bhat <[email protected]>
Signed-off-by: Brian Norris <[email protected]>
Acked-by: Ganapathi Bhat <[email protected]>
Signed-off-by: Kalle Valo <[email protected]>
[bwh: Backported to 3.16: adjust filename, context]
Signed-off-by: Ben Hutchings <[email protected]>
---
drivers/net/wireless/mwifiex/sta_ioctl.c | 1 +
1 file changed, 1 insertion(+)
--- a/drivers/net/wireless/mwifiex/sta_ioctl.c
+++ b/drivers/net/wireless/mwifiex/sta_ioctl.c
@@ -226,6 +226,7 @@ static int mwifiex_process_country_ie(st
if (country_ie_len >
(IEEE80211_COUNTRY_STRING_LEN + MWIFIEX_MAX_TRIPLET_802_11D)) {
+ rcu_read_unlock();
wiphy_dbg(priv->wdev->wiphy,
"11D: country_ie_len overflow!, deauth AP\n");
return -EINVAL;
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Qu Wenruo <[email protected]>
commit 4b865cab96fe2a30ed512cf667b354bd291b3b0a upstream.
EXTENT_CSUM checker is a relatively easy one, only needs to check:
1) Objectid
Fixed to BTRFS_EXTENT_CSUM_OBJECTID
2) Key offset alignment
Must be aligned to sectorsize
3) Item size alignedment
Must be aligned to csum size
Signed-off-by: Qu Wenruo <[email protected]>
Reviewed-by: Nikolay Borisov <[email protected]>
Reviewed-by: David Sterba <[email protected]>
Signed-off-by: David Sterba <[email protected]>
[bwh: Backported to 4.4: Use root->sectorsize instead of
root->fs_info->sectorsize]
Signed-off-by: Ben Hutchings <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
fs/btrfs/disk-io.c | 24 ++++++++++++++++++++++++
1 file changed, 24 insertions(+)
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -590,6 +590,27 @@ static int check_extent_data_item(struct
return 0;
}
+static int check_csum_item(struct btrfs_root *root, struct extent_buffer *leaf,
+ struct btrfs_key *key, int slot)
+{
+ u32 sectorsize = root->sectorsize;
+ u32 csumsize = btrfs_super_csum_size(root->fs_info->super_copy);
+
+ if (key->objectid != BTRFS_EXTENT_CSUM_OBJECTID) {
+ CORRUPT("invalid objectid for csum item", leaf, root, slot);
+ return -EUCLEAN;
+ }
+ if (!IS_ALIGNED(key->offset, sectorsize)) {
+ CORRUPT("unaligned key offset for csum item", leaf, root, slot);
+ return -EUCLEAN;
+ }
+ if (!IS_ALIGNED(btrfs_item_size_nr(leaf, slot), csumsize)) {
+ CORRUPT("unaligned csum item size", leaf, root, slot);
+ return -EUCLEAN;
+ }
+ return 0;
+}
+
/*
* Common point to switch the item-specific validation.
*/
@@ -603,6 +624,9 @@ static int check_leaf_item(struct btrfs_
case BTRFS_EXTENT_DATA_KEY:
ret = check_extent_data_item(root, leaf, key, slot);
break;
+ case BTRFS_EXTENT_CSUM_KEY:
+ ret = check_csum_item(root, leaf, key, slot);
+ break;
}
return ret;
}
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Qu Wenruo <[email protected]>
commit bba4f29896c986c4cec17bc0f19f2ce644fceae1 upstream.
Use inline function to replace macro since we don't need
stringification.
(Macro still exists until all callers get updated)
And add more info about the error, and replace EIO with EUCLEAN.
For nr_items error, report if it's too large or too small, and output
the valid value range.
For node block pointer, added a new alignment checker.
For key order, also output the next key to make the problem more
obvious.
Signed-off-by: Qu Wenruo <[email protected]>
[ wording adjustments, unindented long strings ]
Signed-off-by: David Sterba <[email protected]>
[bwh: Backported to 4.4:
- Use root->sectorsize instead of root->fs_info->sectorsize
- BTRFS_NODEPTRS_PER_BLOCK() takes a root instead of an fs_info, and yields
a value of type size_t instead of unsigned int]
Signed-off-by: Ben Hutchings <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
fs/btrfs/tree-checker.c | 68 ++++++++++++++++++++++++++++++++++++-----
1 file changed, 61 insertions(+), 7 deletions(-)
--- a/fs/btrfs/tree-checker.c
+++ b/fs/btrfs/tree-checker.c
@@ -37,6 +37,46 @@
btrfs_header_level(eb) == 0 ? "leaf" : "node", \
reason, btrfs_header_bytenr(eb), root->objectid, slot)
+/*
+ * Error message should follow the following format:
+ * corrupt <type>: <identifier>, <reason>[, <bad_value>]
+ *
+ * @type: leaf or node
+ * @identifier: the necessary info to locate the leaf/node.
+ * It's recommened to decode key.objecitd/offset if it's
+ * meaningful.
+ * @reason: describe the error
+ * @bad_value: optional, it's recommened to output bad value and its
+ * expected value (range).
+ *
+ * Since comma is used to separate the components, only space is allowed
+ * inside each component.
+ */
+
+/*
+ * Append generic "corrupt leaf/node root=%llu block=%llu slot=%d: " to @fmt.
+ * Allows callers to customize the output.
+ */
+__printf(4, 5)
+static void generic_err(const struct btrfs_root *root,
+ const struct extent_buffer *eb, int slot,
+ const char *fmt, ...)
+{
+ struct va_format vaf;
+ va_list args;
+
+ va_start(args, fmt);
+
+ vaf.fmt = fmt;
+ vaf.va = &args;
+
+ btrfs_crit(root->fs_info,
+ "corrupt %s: root=%llu block=%llu slot=%d, %pV",
+ btrfs_header_level(eb) == 0 ? "leaf" : "node",
+ root->objectid, btrfs_header_bytenr(eb), slot, &vaf);
+ va_end(args);
+}
+
static int check_extent_data_item(struct btrfs_root *root,
struct extent_buffer *leaf,
struct btrfs_key *key, int slot)
@@ -282,9 +322,11 @@ int btrfs_check_node(struct btrfs_root *
if (nr == 0 || nr > BTRFS_NODEPTRS_PER_BLOCK(root)) {
btrfs_crit(root->fs_info,
- "corrupt node: block %llu root %llu nritems %lu",
- node->start, root->objectid, nr);
- return -EIO;
+"corrupt node: root=%llu block=%llu, nritems too %s, have %lu expect range [1,%zu]",
+ root->objectid, node->start,
+ nr == 0 ? "small" : "large", nr,
+ BTRFS_NODEPTRS_PER_BLOCK(root));
+ return -EUCLEAN;
}
for (slot = 0; slot < nr - 1; slot++) {
@@ -293,14 +335,26 @@ int btrfs_check_node(struct btrfs_root *
btrfs_node_key_to_cpu(node, &next_key, slot + 1);
if (!bytenr) {
- CORRUPT("invalid item slot", node, root, slot);
- ret = -EIO;
+ generic_err(root, node, slot,
+ "invalid NULL node pointer");
+ ret = -EUCLEAN;
+ goto out;
+ }
+ if (!IS_ALIGNED(bytenr, root->sectorsize)) {
+ generic_err(root, node, slot,
+ "unaligned pointer, have %llu should be aligned to %u",
+ bytenr, root->sectorsize);
+ ret = -EUCLEAN;
goto out;
}
if (btrfs_comp_cpu_keys(&key, &next_key) >= 0) {
- CORRUPT("bad key order", node, root, slot);
- ret = -EIO;
+ generic_err(root, node, slot,
+ "bad key order, current (%llu %u %llu) next (%llu %u %llu)",
+ key.objectid, key.type, key.offset,
+ next_key.objectid, next_key.type,
+ next_key.offset);
+ ret = -EUCLEAN;
goto out;
}
}
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Nicolai Stange <[email protected]>
commit c7bf1fb7ddca331780b9a733ae308737b39f1ad4 upstream.
Commit e5e884b42639 ("libertas: Fix two buffer overflows at parsing bss
descriptor") introduced a bounds check on the number of supplied rates to
lbs_ibss_join_existing().
Unfortunately, it introduced a return path from within a RCU read side
critical section without a corresponding rcu_read_unlock(). Fix this.
Fixes: e5e884b42639 ("libertas: Fix two buffer overflows at parsing bss descriptor")
Signed-off-by: Nicolai Stange <[email protected]>
Signed-off-by: Kalle Valo <[email protected]>
[bwh: Backported to 3.16: adjust filename]
Signed-off-by: Ben Hutchings <[email protected]>
---
drivers/net/wireless/libertas/cfg.c | 1 +
1 file changed, 1 insertion(+)
--- a/drivers/net/wireless/libertas/cfg.c
+++ b/drivers/net/wireless/libertas/cfg.c
@@ -1855,6 +1855,7 @@ static int lbs_ibss_join_existing(struct
rates_max = rates_eid[1];
if (rates_max > MAX_RATES) {
lbs_deb_join("invalid rates");
+ rcu_read_unlock();
goto out;
}
rates = cmd.bss.rates;
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Chao Yu <[email protected]>
commit 6565c182094f69e4ffdece337d395eb7ec760efc upstream.
Quoted from
commit 3da40c7b0898 ("ext4: only call ext4_truncate when size <= isize")
" At LSF we decided that if we truncate up from isize we shouldn't trim
fallocated blocks that were fallocated with KEEP_SIZE and are past the
new i_size. This patch fixes ext4 to do this. "
And generic/092 of fstest have covered this case for long time, however
is_quota_modification() didn't adjust based on that rule, so that in
below condition, we will lose to quota block change:
- fallocate blocks beyond EOF
- remount
- truncate(file_path, file_size)
Fix it.
Link: https://lore.kernel.org/r/[email protected]
Fixes: 3da40c7b0898 ("ext4: only call ext4_truncate when size <= isize")
Signed-off-by: Chao Yu <[email protected]>
Signed-off-by: Jan Kara <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
include/linux/quotaops.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/include/linux/quotaops.h
+++ b/include/linux/quotaops.h
@@ -21,7 +21,7 @@ static inline struct quota_info *sb_dqop
/* i_mutex must being held */
static inline bool is_quota_modification(struct inode *inode, struct iattr *ia)
{
- return (ia->ia_valid & ATTR_SIZE && ia->ia_size != inode->i_size) ||
+ return (ia->ia_valid & ATTR_SIZE) ||
(ia->ia_valid & ATTR_UID && !uid_eq(ia->ia_uid, inode->i_uid)) ||
(ia->ia_valid & ATTR_GID && !gid_eq(ia->ia_gid, inode->i_gid));
}
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Jan Kara <[email protected]>
commit ea3d7209ca01da209cda6f0dea8be9cc4b7a933b upstream.
Currently, page faults and hole punching are completely unsynchronized.
This can result in page fault faulting in a page into a range that we
are punching after truncate_pagecache_range() has been called and thus
we can end up with a page mapped to disk blocks that will be shortly
freed. Filesystem corruption will shortly follow. Note that the same
race is avoided for truncate by checking page fault offset against
i_size but there isn't similar mechanism available for punching holes.
Fix the problem by creating new rw semaphore i_mmap_sem in inode and
grab it for writing over truncate, hole punching, and other functions
removing blocks from extent tree and for read over page faults. We
cannot easily use i_data_sem for this since that ranks below transaction
start and we need something ranking above it so that it can be held over
the whole truncate / hole punching operation. Also remove various
workarounds we had in the code to reduce race window when page fault
could have created pages with stale mapping information.
Signed-off-by: Jan Kara <[email protected]>
Signed-off-by: Theodore Ts'o <[email protected]>
[bwh: Backported to 3.16:
- Drop changes in ext4_insert_range(), ext4_dax_*
- Adjust context]
Signed-off-by: Ben Hutchings <[email protected]>
---
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -937,6 +937,15 @@ struct ext4_inode_info {
* by other means, so we have i_data_sem.
*/
struct rw_semaphore i_data_sem;
+ /*
+ * i_mmap_sem is for serializing page faults with truncate / punch hole
+ * operations. We have to make sure that new page cannot be faulted in
+ * a section of the inode that is being punched. We cannot easily use
+ * i_data_sem for this since we need protection for the whole punch
+ * operation and i_data_sem ranks below transaction start so we have
+ * to occasionally drop it.
+ */
+ struct rw_semaphore i_mmap_sem;
struct inode vfs_inode;
struct jbd2_inode *jinode;
@@ -2205,6 +2214,7 @@ extern int ext4_chunk_trans_blocks(struc
extern int ext4_zero_partial_blocks(handle_t *handle, struct inode *inode,
loff_t lstart, loff_t lend);
extern int ext4_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf);
+extern int ext4_filemap_fault(struct vm_area_struct *vma, struct vm_fault *vmf);
extern qsize_t *ext4_get_reserved_space(struct inode *inode);
extern void ext4_da_update_reserve_space(struct inode *inode,
int used, int quota_claim);
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -4778,7 +4778,6 @@ static long ext4_zero_range(struct file
int partial_begin, partial_end;
loff_t start, end;
ext4_lblk_t lblk;
- struct address_space *mapping = inode->i_mapping;
unsigned int blkbits = inode->i_blkbits;
trace_ext4_zero_range(inode, offset, len, mode);
@@ -4794,17 +4793,6 @@ static long ext4_zero_range(struct file
}
/*
- * Write out all dirty pages to avoid race conditions
- * Then release them.
- */
- if (mapping->nrpages && mapping_tagged(mapping, PAGECACHE_TAG_DIRTY)) {
- ret = filemap_write_and_wait_range(mapping, offset,
- offset + len - 1);
- if (ret)
- return ret;
- }
-
- /*
* Round up offset. This is not fallocate, we neet to zero out
* blocks, so convert interior block aligned part of the range to
* unwritten and possibly manually zero out unaligned parts of the
@@ -4865,16 +4853,22 @@ static long ext4_zero_range(struct file
flags |= (EXT4_GET_BLOCKS_CONVERT_UNWRITTEN |
EXT4_EX_NOCACHE);
- /* Now release the pages and zero block aligned part of pages*/
- truncate_pagecache_range(inode, start, end - 1);
- inode->i_mtime = inode->i_ctime = ext4_current_time(inode);
-
/* Wait all existing dio workers, newcomers will block on i_mutex */
ext4_inode_block_unlocked_dio(inode);
inode_dio_wait(inode);
+ /*
+ * Prevent page faults from reinstantiating pages we have
+ * released from page cache.
+ */
+ down_write(&EXT4_I(inode)->i_mmap_sem);
+ /* Now release the pages and zero block aligned part of pages */
+ truncate_pagecache_range(inode, start, end - 1);
+ inode->i_mtime = inode->i_ctime = ext4_current_time(inode);
+
ret = ext4_alloc_file_blocks(file, lblk, max_blocks, new_size,
flags, mode);
+ up_write(&EXT4_I(inode)->i_mmap_sem);
if (ret)
goto out_dio;
}
@@ -5490,17 +5484,22 @@ int ext4_collapse_range(struct inode *in
goto out_mutex;
}
- truncate_pagecache(inode, ioffset);
-
/* Wait for existing dio to complete */
ext4_inode_block_unlocked_dio(inode);
inode_dio_wait(inode);
+ /*
+ * Prevent page faults from reinstantiating pages we have released from
+ * page cache.
+ */
+ down_write(&EXT4_I(inode)->i_mmap_sem);
+ truncate_pagecache(inode, ioffset);
+
credits = ext4_writepage_trans_blocks(inode);
handle = ext4_journal_start(inode, EXT4_HT_TRUNCATE, credits);
if (IS_ERR(handle)) {
ret = PTR_ERR(handle);
- goto out_dio;
+ goto out_mmap;
}
down_write(&EXT4_I(inode)->i_data_sem);
@@ -5540,7 +5539,8 @@ int ext4_collapse_range(struct inode *in
out_stop:
ext4_journal_stop(handle);
-out_dio:
+out_mmap:
+ up_write(&EXT4_I(inode)->i_mmap_sem);
ext4_inode_resume_unlocked_dio(inode);
out_mutex:
mutex_unlock(&inode->i_mutex);
--- a/fs/ext4/file.c
+++ b/fs/ext4/file.c
@@ -199,7 +199,7 @@ errout:
}
static const struct vm_operations_struct ext4_file_vm_ops = {
- .fault = filemap_fault,
+ .fault = ext4_filemap_fault,
.map_pages = filemap_map_pages,
.page_mkwrite = ext4_page_mkwrite,
};
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -3716,6 +3716,15 @@ int ext4_punch_hole(struct inode *inode,
}
+ /* Wait all existing dio workers, newcomers will block on i_mutex */
+ ext4_inode_block_unlocked_dio(inode);
+ inode_dio_wait(inode);
+
+ /*
+ * Prevent page faults from reinstantiating pages we have released from
+ * page cache.
+ */
+ down_write(&EXT4_I(inode)->i_mmap_sem);
first_block_offset = round_up(offset, sb->s_blocksize);
last_block_offset = round_down((offset + length), sb->s_blocksize) - 1;
@@ -3724,10 +3733,6 @@ int ext4_punch_hole(struct inode *inode,
truncate_pagecache_range(inode, first_block_offset,
last_block_offset);
- /* Wait all existing dio workers, newcomers will block on i_mutex */
- ext4_inode_block_unlocked_dio(inode);
- inode_dio_wait(inode);
-
if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS))
credits = ext4_writepage_trans_blocks(inode);
else
@@ -3773,11 +3778,6 @@ int ext4_punch_hole(struct inode *inode,
if (IS_SYNC(inode))
ext4_handle_sync(handle);
- /* Now release the pages again to reduce race window */
- if (last_block_offset > first_block_offset)
- truncate_pagecache_range(inode, first_block_offset,
- last_block_offset);
-
inode->i_mtime = inode->i_ctime = ext4_current_time(inode);
ext4_mark_inode_dirty(handle, inode);
if (ret >= 0)
@@ -3785,6 +3785,7 @@ int ext4_punch_hole(struct inode *inode,
out_stop:
ext4_journal_stop(handle);
out_dio:
+ up_write(&EXT4_I(inode)->i_mmap_sem);
ext4_inode_resume_unlocked_dio(inode);
out_mutex:
mutex_unlock(&inode->i_mutex);
@@ -4879,6 +4880,7 @@ int ext4_setattr(struct dentry *dentry,
} else
ext4_wait_for_tail_page_commit(inode);
}
+ down_write(&EXT4_I(inode)->i_mmap_sem);
/*
* Truncate pagecache after we've waited for commit
* in data=journal mode to make pages freeable.
@@ -4886,6 +4888,7 @@ int ext4_setattr(struct dentry *dentry,
truncate_pagecache(inode, inode->i_size);
if (shrink)
ext4_truncate(inode);
+ up_write(&EXT4_I(inode)->i_mmap_sem);
}
if (!rc) {
@@ -5338,6 +5341,8 @@ int ext4_page_mkwrite(struct vm_area_str
sb_start_pagefault(inode->i_sb);
file_update_time(vma->vm_file);
+ down_read(&EXT4_I(inode)->i_mmap_sem);
+
ret = ext4_convert_inline_data(inode);
if (ret)
goto out_ret;
@@ -5411,6 +5416,19 @@ retry_alloc:
out_ret:
ret = block_page_mkwrite_return(ret);
out:
+ up_read(&EXT4_I(inode)->i_mmap_sem);
sb_end_pagefault(inode->i_sb);
return ret;
}
+
+int ext4_filemap_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
+{
+ struct inode *inode = file_inode(vma->vm_file);
+ int err;
+
+ down_read(&EXT4_I(inode)->i_mmap_sem);
+ err = filemap_fault(vma, vmf);
+ up_read(&EXT4_I(inode)->i_mmap_sem);
+
+ return err;
+}
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -967,6 +967,7 @@ static void init_once(void *foo)
INIT_LIST_HEAD(&ei->i_orphan);
init_rwsem(&ei->xattr_sem);
init_rwsem(&ei->i_data_sem);
+ init_rwsem(&ei->i_mmap_sem);
inode_init_once(&ei->vfs_inode);
}
--- a/fs/ext4/truncate.h
+++ b/fs/ext4/truncate.h
@@ -10,8 +10,10 @@
*/
static inline void ext4_truncate_failed_write(struct inode *inode)
{
+ down_write(&EXT4_I(inode)->i_mmap_sem);
truncate_inode_pages(inode->i_mapping, inode->i_size);
ext4_truncate(inode);
+ up_write(&EXT4_I(inode)->i_mmap_sem);
}
/*
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Wen Huang <[email protected]>
commit e5e884b42639c74b5b57dc277909915c0aefc8bb upstream.
add_ie_rates() copys rates without checking the length
in bss descriptor from remote AP.when victim connects to
remote attacker, this may trigger buffer overflow.
lbs_ibss_join_existing() copys rates without checking the length
in bss descriptor from remote IBSS node.when victim connects to
remote attacker, this may trigger buffer overflow.
Fix them by putting the length check before performing copy.
This fix addresses CVE-2019-14896 and CVE-2019-14897.
This also fix build warning of mixed declarations and code.
Reported-by: kbuild test robot <[email protected]>
Signed-off-by: Wen Huang <[email protected]>
Signed-off-by: Kalle Valo <[email protected]>
[bwh: Backported to 3.16: adjust filename]
Signed-off-by: Ben Hutchings <[email protected]>
---
drivers/net/wireless/libertas/cfg.c | 8 ++++++++
1 file changed, 8 insertions(+)
--- a/drivers/net/wireless/libertas/cfg.c
+++ b/drivers/net/wireless/libertas/cfg.c
@@ -272,6 +272,10 @@ add_ie_rates(u8 *tlv, const u8 *ie, int
int hw, ap, ap_max = ie[1];
u8 hw_rate;
+ if (ap_max > MAX_RATES) {
+ lbs_deb_assoc("invalid rates\n");
+ return tlv;
+ }
/* Advance past IE header */
ie += 2;
@@ -1785,6 +1789,9 @@ static int lbs_ibss_join_existing(struct
struct cmd_ds_802_11_ad_hoc_join cmd;
u8 preamble = RADIO_PREAMBLE_SHORT;
int ret = 0;
+ int hw, i;
+ u8 rates_max;
+ u8 *rates;
lbs_deb_enter(LBS_DEB_CFG80211);
@@ -1845,9 +1852,12 @@ static int lbs_ibss_join_existing(struct
if (!rates_eid) {
lbs_add_rates(cmd.bss.rates);
} else {
- int hw, i;
- u8 rates_max = rates_eid[1];
- u8 *rates = cmd.bss.rates;
+ rates_max = rates_eid[1];
+ if (rates_max > MAX_RATES) {
+ lbs_deb_join("invalid rates");
+ goto out;
+ }
+ rates = cmd.bss.rates;
for (hw = 0; hw < ARRAY_SIZE(lbs_rates); hw++) {
u8 hw_rate = lbs_rates[hw].bitrate / 5;
for (i = 0; i < rates_max; i++) {
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Nicolai Stange <[email protected]>
commit 1754c4f60aaf1e17d886afefee97e94d7f27b4cb upstream.
Commit e5e884b42639 ("libertas: Fix two buffer overflows at parsing bss
descriptor") introduced a bounds check on the number of supplied rates to
lbs_ibss_join_existing() and made it to return on overflow.
However, the aforementioned commit doesn't set the return value accordingly
and thus, lbs_ibss_join_existing() would return with zero even though it
failed.
Make lbs_ibss_join_existing return -EINVAL in case the bounds check on the
number of supplied rates fails.
Fixes: e5e884b42639 ("libertas: Fix two buffer overflows at parsing bss descriptor")
Signed-off-by: Nicolai Stange <[email protected]>
Signed-off-by: Kalle Valo <[email protected]>
[bwh: Backported to 3.16: adjust filename]
Signed-off-by: Ben Hutchings <[email protected]>
---
drivers/net/wireless/libertas/cfg.c | 1 +
1 file changed, 1 insertion(+)
--- a/drivers/net/wireless/libertas/cfg.c
+++ b/drivers/net/wireless/libertas/cfg.c
@@ -1856,6 +1856,7 @@ static int lbs_ibss_join_existing(struct
if (rates_max > MAX_RATES) {
lbs_deb_join("invalid rates");
rcu_read_unlock();
+ ret = -EINVAL;
goto out;
}
rates = cmd.bss.rates;
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Avinash Patil <[email protected]>
commit 3c99832d74777c9ec5545a92450fac5d37b0d0e1 upstream.
Size of RSN IE buffer in driver is 254 while maximum size of received buffer
to be copied to RSN IE buffer can be 255. Add boundary check to copy maximum
of 254 bytes into RSN IE buffer.
Reported-by: Dan Carpenter <[email protected]>
Signed-off-by: Avinash Patil <[email protected]>
Signed-off-by: John W. Linville <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
drivers/net/wireless/mwifiex/tdls.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
--- a/drivers/net/wireless/mwifiex/tdls.c
+++ b/drivers/net/wireless/mwifiex/tdls.c
@@ -877,7 +877,9 @@ void mwifiex_process_tdls_action_frame(s
break;
case WLAN_EID_RSN:
memcpy((u8 *)&sta_ptr->tdls_cap.rsn_ie, pos,
- sizeof(struct ieee_types_header) + pos[1]);
+ sizeof(struct ieee_types_header) +
+ min_t(u8, pos[1], IEEE_MAX_IE_SIZE -
+ sizeof(struct ieee_types_header)));
break;
case WLAN_EID_QOS_CAPA:
sta_ptr->tdls_cap.qos_info = pos[2];
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: David Sterba <[email protected]>
commit fb85fc9a675738ee2746b51c3aedde944b18ca02 upstream.
It used to be more complex but now it's just a simple array access.
Signed-off-by: David Sterba <[email protected]>
[bwh: Backported to 3.16 as dependency of various fixes: adjust context]
Signed-off-by: Ben Hutchings <[email protected]>
---
fs/btrfs/extent_io.c | 55 +++++++++++++++++++++-----------------------
fs/btrfs/extent_io.h | 6 -----
2 files changed, 26 insertions(+), 35 deletions(-)
--- a/fs/btrfs/extent_io.c
+++ b/fs/btrfs/extent_io.c
@@ -2082,7 +2082,7 @@ int repair_eb_io_failure(struct btrfs_ro
return -EROFS;
for (i = 0; i < num_pages; i++) {
- struct page *p = extent_buffer_page(eb, i);
+ struct page *p = eb->pages[i];
ret = repair_io_failure(root->fs_info, start, PAGE_CACHE_SIZE,
start, p, mirror_num);
if (ret)
@@ -3558,7 +3558,7 @@ lock_extent_buffer_for_io(struct extent_
num_pages = num_extent_pages(eb->start, eb->len);
for (i = 0; i < num_pages; i++) {
- struct page *p = extent_buffer_page(eb, i);
+ struct page *p = eb->pages[i];
if (!trylock_page(p)) {
if (!flush) {
@@ -3629,7 +3629,7 @@ static noinline_for_stack int write_one_
bio_flags = EXTENT_BIO_TREE_LOG;
for (i = 0; i < num_pages; i++) {
- struct page *p = extent_buffer_page(eb, i);
+ struct page *p = eb->pages[i];
clear_page_dirty_for_io(p);
set_page_writeback(p);
@@ -3652,10 +3652,8 @@ static noinline_for_stack int write_one_
}
if (unlikely(ret)) {
- for (; i < num_pages; i++) {
- struct page *p = extent_buffer_page(eb, i);
- unlock_page(p);
- }
+ for (; i < num_pages; i++)
+ unlock_page(eb->pages[i]);
}
return ret;
@@ -4459,7 +4457,7 @@ static void btrfs_release_extent_buffer_
do {
index--;
- page = extent_buffer_page(eb, index);
+ page = eb->pages[index];
if (page && mapped) {
spin_lock(&page->mapping->private_lock);
/*
@@ -4641,7 +4639,8 @@ static void mark_extent_buffer_accessed(
num_pages = num_extent_pages(eb->start, eb->len);
for (i = 0; i < num_pages; i++) {
- struct page *p = extent_buffer_page(eb, i);
+ struct page *p = eb->pages[i];
+
if (p != accessed)
mark_page_accessed(p);
}
@@ -4810,7 +4809,7 @@ again:
*/
SetPageChecked(eb->pages[0]);
for (i = 1; i < num_pages; i++) {
- p = extent_buffer_page(eb, i);
+ p = eb->pages[i];
ClearPageChecked(p);
unlock_page(p);
}
@@ -4921,7 +4920,7 @@ void clear_extent_buffer_dirty(struct ex
num_pages = num_extent_pages(eb->start, eb->len);
for (i = 0; i < num_pages; i++) {
- page = extent_buffer_page(eb, i);
+ page = eb->pages[i];
if (!PageDirty(page))
continue;
@@ -4957,7 +4956,7 @@ int set_extent_buffer_dirty(struct exten
WARN_ON(!test_bit(EXTENT_BUFFER_TREE_REF, &eb->bflags));
for (i = 0; i < num_pages; i++)
- set_page_dirty(extent_buffer_page(eb, i));
+ set_page_dirty(eb->pages[i]);
return was_dirty;
}
@@ -4970,7 +4969,7 @@ int clear_extent_buffer_uptodate(struct
clear_bit(EXTENT_BUFFER_UPTODATE, &eb->bflags);
num_pages = num_extent_pages(eb->start, eb->len);
for (i = 0; i < num_pages; i++) {
- page = extent_buffer_page(eb, i);
+ page = eb->pages[i];
if (page)
ClearPageUptodate(page);
}
@@ -4986,7 +4985,7 @@ int set_extent_buffer_uptodate(struct ex
set_bit(EXTENT_BUFFER_UPTODATE, &eb->bflags);
num_pages = num_extent_pages(eb->start, eb->len);
for (i = 0; i < num_pages; i++) {
- page = extent_buffer_page(eb, i);
+ page = eb->pages[i];
SetPageUptodate(page);
}
return 0;
@@ -5026,7 +5025,7 @@ int read_extent_buffer_pages(struct exte
num_pages = num_extent_pages(eb->start, eb->len);
for (i = start_i; i < num_pages; i++) {
- page = extent_buffer_page(eb, i);
+ page = eb->pages[i];
if (wait == WAIT_NONE) {
if (!trylock_page(page))
goto unlock_exit;
@@ -5049,7 +5048,7 @@ int read_extent_buffer_pages(struct exte
eb->read_mirror = 0;
atomic_set(&eb->io_pages, num_reads);
for (i = start_i; i < num_pages; i++) {
- page = extent_buffer_page(eb, i);
+ page = eb->pages[i];
if (!PageUptodate(page)) {
ClearPageError(page);
err = __extent_read_full_page(tree, page,
@@ -5074,7 +5073,7 @@ int read_extent_buffer_pages(struct exte
return ret;
for (i = start_i; i < num_pages; i++) {
- page = extent_buffer_page(eb, i);
+ page = eb->pages[i];
wait_on_page_locked(page);
if (!PageUptodate(page))
ret = -EIO;
@@ -5085,7 +5084,7 @@ int read_extent_buffer_pages(struct exte
unlock_exit:
i = start_i;
while (locked_pages > 0) {
- page = extent_buffer_page(eb, i);
+ page = eb->pages[i];
i++;
unlock_page(page);
locked_pages--;
@@ -5111,7 +5110,7 @@ void read_extent_buffer(struct extent_bu
offset = (start_offset + start) & (PAGE_CACHE_SIZE - 1);
while (len > 0) {
- page = extent_buffer_page(eb, i);
+ page = eb->pages[i];
cur = min(len, (PAGE_CACHE_SIZE - offset));
kaddr = page_address(page);
@@ -5143,7 +5142,7 @@ int read_extent_buffer_to_user(struct ex
offset = (start_offset + start) & (PAGE_CACHE_SIZE - 1);
while (len > 0) {
- page = extent_buffer_page(eb, i);
+ page = eb->pages[i];
cur = min(len, (PAGE_CACHE_SIZE - offset));
kaddr = page_address(page);
@@ -5192,7 +5191,7 @@ int map_private_extent_buffer(struct ext
return -EINVAL;
}
- p = extent_buffer_page(eb, i);
+ p = eb->pages[i];
kaddr = page_address(p);
*map = kaddr + offset;
*map_len = PAGE_CACHE_SIZE - offset;
@@ -5218,7 +5217,7 @@ int memcmp_extent_buffer(struct extent_b
offset = (start_offset + start) & (PAGE_CACHE_SIZE - 1);
while (len > 0) {
- page = extent_buffer_page(eb, i);
+ page = eb->pages[i];
cur = min(len, (PAGE_CACHE_SIZE - offset));
@@ -5252,7 +5251,7 @@ void write_extent_buffer(struct extent_b
offset = (start_offset + start) & (PAGE_CACHE_SIZE - 1);
while (len > 0) {
- page = extent_buffer_page(eb, i);
+ page = eb->pages[i];
WARN_ON(!PageUptodate(page));
cur = min(len, PAGE_CACHE_SIZE - offset);
@@ -5282,7 +5281,7 @@ void memset_extent_buffer(struct extent_
offset = (start_offset + start) & (PAGE_CACHE_SIZE - 1);
while (len > 0) {
- page = extent_buffer_page(eb, i);
+ page = eb->pages[i];
WARN_ON(!PageUptodate(page));
cur = min(len, PAGE_CACHE_SIZE - offset);
@@ -5313,7 +5312,7 @@ void copy_extent_buffer(struct extent_bu
(PAGE_CACHE_SIZE - 1);
while (len > 0) {
- page = extent_buffer_page(dst, i);
+ page = dst->pages[i];
WARN_ON(!PageUptodate(page));
cur = min(len, (unsigned long)(PAGE_CACHE_SIZE - offset));
@@ -5391,8 +5390,7 @@ void memcpy_extent_buffer(struct extent_
cur = min_t(unsigned long, cur,
(unsigned long)(PAGE_CACHE_SIZE - dst_off_in_page));
- copy_pages(extent_buffer_page(dst, dst_i),
- extent_buffer_page(dst, src_i),
+ copy_pages(dst->pages[dst_i], dst->pages[src_i],
dst_off_in_page, src_off_in_page, cur);
src_offset += cur;
@@ -5438,8 +5436,7 @@ void memmove_extent_buffer(struct extent
cur = min_t(unsigned long, len, src_off_in_page + 1);
cur = min(cur, dst_off_in_page + 1);
- copy_pages(extent_buffer_page(dst, dst_i),
- extent_buffer_page(dst, src_i),
+ copy_pages(dst->pages[dst_i], dst->pages[src_i],
dst_off_in_page - cur + 1,
src_off_in_page - cur + 1, cur);
--- a/fs/btrfs/extent_io.h
+++ b/fs/btrfs/extent_io.h
@@ -286,12 +286,6 @@ static inline unsigned long num_extent_p
(start >> PAGE_CACHE_SHIFT);
}
-static inline struct page *extent_buffer_page(struct extent_buffer *eb,
- unsigned long i)
-{
- return eb->pages[i];
-}
-
static inline void extent_buffer_get(struct extent_buffer *eb)
{
atomic_inc(&eb->refs);
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Tom Lendacky <[email protected]>
commit f4e9b7af0cd58dd039a0fb2cd67d57cea4889abf upstream.
The size for the Microcode Patch Block (MPB) for an AMD family 17h
processor is 3200 bytes. Add a #define for fam17h so that it does
not default to 2048 bytes and fail a microcode load/update.
Signed-off-by: Tom Lendacky <[email protected]>
Signed-off-by: Thomas Gleixner <[email protected]>
Reviewed-by: Borislav Petkov <[email protected]>
Link: https://lkml.kernel.org/r/[email protected]
Signed-off-by: Ingo Molnar <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
---
arch/x86/kernel/cpu/microcode/amd.c | 4 ++++
1 file changed, 4 insertions(+)
--- a/arch/x86/kernel/cpu/microcode/amd.c
+++ b/arch/x86/kernel/cpu/microcode/amd.c
@@ -154,6 +154,7 @@ static unsigned int verify_patch_size(u8
#define F14H_MPB_MAX_SIZE 1824
#define F15H_MPB_MAX_SIZE 4096
#define F16H_MPB_MAX_SIZE 3458
+#define F17H_MPB_MAX_SIZE 3200
switch (family) {
case 0x14:
@@ -165,6 +166,9 @@ static unsigned int verify_patch_size(u8
case 0x16:
max_size = F16H_MPB_MAX_SIZE;
break;
+ case 0x17:
+ max_size = F17H_MPB_MAX_SIZE;
+ break;
default:
max_size = F1XH_MPB_MAX_SIZE;
break;
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: qize wang <[email protected]>
commit 1e58252e334dc3f3756f424a157d1b7484464c40 upstream.
mwifiex_process_tdls_action_frame() without checking
the incoming tdls infomation element's vality before use it,
this may cause multi heap buffer overflows.
Fix them by putting vality check before use it.
IE is TLV struct, but ht_cap and ht_oper aren’t TLV struct.
the origin marvell driver code is wrong:
memcpy(&sta_ptr->tdls_cap.ht_oper, pos,....
memcpy((u8 *)&sta_ptr->tdls_cap.ht_capb, pos,...
Fix the bug by changing pos(the address of IE) to
pos+2 ( the address of IE value ).
Signed-off-by: qize wang <[email protected]>
Signed-off-by: Kalle Valo <[email protected]>
[bwh: Backported to 3.16: adjust filename, context]
Signed-off-by: Ben Hutchings <[email protected]>
---
drivers/net/wireless/mwifiex/tdls.c | 70 +++++++++++++++++++--
1 file changed, 64 insertions(+), 6 deletions(-)
--- a/drivers/net/wireless/mwifiex/tdls.c
+++ b/drivers/net/wireless/mwifiex/tdls.c
@@ -847,59 +847,117 @@ void mwifiex_process_tdls_action_frame(s
switch (*pos) {
case WLAN_EID_SUPP_RATES:
+ if (pos[1] > 32)
+ return;
sta_ptr->tdls_cap.rates_len = pos[1];
for (i = 0; i < pos[1]; i++)
sta_ptr->tdls_cap.rates[i] = pos[i + 2];
break;
case WLAN_EID_EXT_SUPP_RATES:
+ if (pos[1] > 32)
+ return;
basic = sta_ptr->tdls_cap.rates_len;
+ if (pos[1] > 32 - basic)
+ return;
for (i = 0; i < pos[1]; i++)
sta_ptr->tdls_cap.rates[basic + i] = pos[i + 2];
sta_ptr->tdls_cap.rates_len += pos[1];
break;
case WLAN_EID_HT_CAPABILITY:
- memcpy((u8 *)&sta_ptr->tdls_cap.ht_capb, pos,
+ if (pos > end - sizeof(struct ieee80211_ht_cap) - 2)
+ return;
+ if (pos[1] != sizeof(struct ieee80211_ht_cap))
+ return;
+ /* copy the ie's value into ht_capb*/
+ memcpy((u8 *)&sta_ptr->tdls_cap.ht_capb, pos + 2,
sizeof(struct ieee80211_ht_cap));
sta_ptr->is_11n_enabled = 1;
break;
case WLAN_EID_HT_OPERATION:
- memcpy(&sta_ptr->tdls_cap.ht_oper, pos,
+ if (pos > end -
+ sizeof(struct ieee80211_ht_operation) - 2)
+ return;
+ if (pos[1] != sizeof(struct ieee80211_ht_operation))
+ return;
+ /* copy the ie's value into ht_oper*/
+ memcpy(&sta_ptr->tdls_cap.ht_oper, pos + 2,
sizeof(struct ieee80211_ht_operation));
break;
case WLAN_EID_BSS_COEX_2040:
+ if (pos > end - 3)
+ return;
+ if (pos[1] != 1)
+ return;
sta_ptr->tdls_cap.coex_2040 = pos[2];
break;
case WLAN_EID_EXT_CAPABILITY:
+ if (pos > end - sizeof(struct ieee_types_header))
+ return;
+ if (pos[1] < sizeof(struct ieee_types_header))
+ return;
+ if (pos[1] > 8)
+ return;
memcpy((u8 *)&sta_ptr->tdls_cap.extcap, pos,
sizeof(struct ieee_types_header) +
min_t(u8, pos[1], 8));
break;
case WLAN_EID_RSN:
+ if (pos > end - sizeof(struct ieee_types_header))
+ return;
+ if (pos[1] < sizeof(struct ieee_types_header))
+ return;
+ if (pos[1] > IEEE_MAX_IE_SIZE -
+ sizeof(struct ieee_types_header))
+ return;
memcpy((u8 *)&sta_ptr->tdls_cap.rsn_ie, pos,
sizeof(struct ieee_types_header) +
min_t(u8, pos[1], IEEE_MAX_IE_SIZE -
sizeof(struct ieee_types_header)));
break;
case WLAN_EID_QOS_CAPA:
+ if (pos > end - 3)
+ return;
+ if (pos[1] != 1)
+ return;
sta_ptr->tdls_cap.qos_info = pos[2];
break;
case WLAN_EID_VHT_OPERATION:
- if (priv->adapter->is_hw_11ac_capable)
- memcpy(&sta_ptr->tdls_cap.vhtoper, pos,
+ if (priv->adapter->is_hw_11ac_capable) {
+ if (pos > end -
+ sizeof(struct ieee80211_vht_operation) - 2)
+ return;
+ if (pos[1] !=
+ sizeof(struct ieee80211_vht_operation))
+ return;
+ /* copy the ie's value into vhtoper*/
+ memcpy(&sta_ptr->tdls_cap.vhtoper, pos + 2,
sizeof(struct ieee80211_vht_operation));
+ }
break;
case WLAN_EID_VHT_CAPABILITY:
if (priv->adapter->is_hw_11ac_capable) {
- memcpy((u8 *)&sta_ptr->tdls_cap.vhtcap, pos,
+ if (pos > end -
+ sizeof(struct ieee80211_vht_cap) - 2)
+ return;
+ if (pos[1] != sizeof(struct ieee80211_vht_cap))
+ return;
+ /* copy the ie's value into vhtcap*/
+ memcpy((u8 *)&sta_ptr->tdls_cap.vhtcap, pos + 2,
sizeof(struct ieee80211_vht_cap));
sta_ptr->is_11ac_enabled = 1;
}
break;
case WLAN_EID_AID:
- if (priv->adapter->is_hw_11ac_capable)
+ if (priv->adapter->is_hw_11ac_capable) {
+ if (pos > end - 4)
+ return;
+ if (pos[1] != 2)
+ return;
sta_ptr->tdls_cap.aid =
le16_to_cpu(*(__le16 *)(pos + 2));
+ }
+ break;
default:
break;
}
On Fri, Apr 24, 2020 at 1:03 AM Ben Hutchings <[email protected]> wrote:
> This is the start of the stable review cycle for the 3.16.83 release.
> There are 245 patches in this series, which will be posted as responses
> to this one. If anyone has any issues with these being applied, please
> let me know.
>
> Responses should be made by Tue Apr 28 18:00:00 UTC 2020.
> Anything received after that time might be too late.
Can you please add backports of the following patches? I asked for
that in <https://lore.kernel.org/stable/CAG48ez29d-JJOw8XMp1Z=7sDj8Kvmt+9KXC9-ux-0OBhUP02Xg@mail.gmail.com/>,
but I guess that fell through the cracks somehow.
8019ad13ef7f64be44d4f892af9c840179009254 "futex: Fix inode life-time issue"
8d67743653dce5a0e7aa500fcccb237cde7ad88e "futex: Unbreak futex hashing"
Can those still go into 3.16.83, or is it too late for that now?
On Fri, 2020-04-24 at 01:59 +0200, Jann Horn wrote:
> On Fri, Apr 24, 2020 at 1:03 AM Ben Hutchings <[email protected]> wrote:
> > This is the start of the stable review cycle for the 3.16.83 release.
> > There are 245 patches in this series, which will be posted as responses
> > to this one. If anyone has any issues with these being applied, please
> > let me know.
> >
> > Responses should be made by Tue Apr 28 18:00:00 UTC 2020.
> > Anything received after that time might be too late.
>
> Can you please add backports of the following patches? I asked for
> that in <https://lore.kernel.org/stable/CAG48ez29d-JJOw8XMp1Z=7sDj8Kvmt+9KXC9-ux-0OBhUP02Xg@mail.gmail.com/>;,
> but I guess that fell through the cracks somehow.
Sorry I forgot about this,
> 8019ad13ef7f64be44d4f892af9c840179009254 "futex: Fix inode life-time issue"
> 8d67743653dce5a0e7aa500fcccb237cde7ad88e "futex: Unbreak futex hashing"
>
> Can those still go into 3.16.83, or is it too late for that now?
I'll add them and send an -rc2.
Ben.
--
Ben Hutchings
Knowledge is power. France is bacon.
On Fri, Apr 24, 2020 at 12:07:15AM +0100, Ben Hutchings wrote:
> 3.16.83-rc1 review patch. If anyone has any objections, please let me know.
I do. This patch is currently known-buggy, see this thread:
https://www.openwall.com/lists/oss-security/2020/01/28/2
It is (partially) fixed with these newer commits in 5.5 and 5.5.2:
commit d0cb50185ae942b03c4327be322055d622dc79f6
Author: Al Viro <[email protected]>
Date: Sun Jan 26 09:29:34 2020 -0500
do_last(): fetch directory ->i_mode and ->i_uid before it's too late
may_create_in_sticky() call is done when we already have dropped the
reference to dir.
Fixes: 30aba6656f61e (namei: allow restricted O_CREAT of FIFOs and regular files)
Signed-off-by: Al Viro <[email protected]>
commit d76341d93dedbcf6ed5a08dfc8bce82d3e9a772b
Author: Al Viro <[email protected]>
Date: Sat Feb 1 16:26:45 2020 +0000
vfs: fix do_last() regression
commit 6404674acd596de41fd3ad5f267b4525494a891a upstream.
Brown paperbag time: fetching ->i_uid/->i_mode really should've been
done from nd->inode. I even suggested that, but the reason for that has
slipped through the cracks and I went for dir->d_inode instead - made
for more "obvious" patch.
Analysis:
- at the entry into do_last() and all the way to step_into(): dir (aka
nd->path.dentry) is known not to have been freed; so's nd->inode and
it's equal to dir->d_inode unless we are already doomed to -ECHILD.
inode of the file to get opened is not known.
- after step_into(): inode of the file to get opened is known; dir
might be pointing to freed memory/be negative/etc.
- at the call of may_create_in_sticky(): guaranteed to be out of RCU
mode; inode of the file to get opened is known and pinned; dir might
be garbage.
The last was the reason for the original patch. Except that at the
do_last() entry we can be in RCU mode and it is possible that
nd->path.dentry->d_inode has already changed under us.
In that case we are going to fail with -ECHILD, but we need to be
careful; nd->inode is pointing to valid struct inode and it's the same
as nd->path.dentry->d_inode in "won't fail with -ECHILD" case, so we
should use that.
Reported-by: "Rantala, Tommi T. (Nokia - FI/Espoo)" <[email protected]>
Reported-by: [email protected]
Wearing-brown-paperbag: Al Viro <[email protected]>
Cc: [email protected]
Fixes: d0cb50185ae9 ("do_last(): fetch directory ->i_mode and ->i_uid before it's too late")
Signed-off-by: Al Viro <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
At least inclusion of the above fixes is mandatory for any backports.
Also, I think no one has fixed the logic of may_create_in_sticky() so
that it wouldn't unintentionally apply the "protection" when the file
is neither a FIFO nor a regular file (something I found and mentioned in
the oss-security posting above).
> +/**
> + * may_create_in_sticky - Check whether an O_CREAT open in a sticky directory
> + * should be allowed, or not, on files that already
> + * exist.
> + * @dir: the sticky parent directory
> + * @inode: the inode of the file to open
> + *
> + * Block an O_CREAT open of a FIFO (or a regular file) when:
> + * - sysctl_protected_fifos (or sysctl_protected_regular) is enabled
> + * - the file already exists
> + * - we are in a sticky directory
> + * - we don't own the file
> + * - the owner of the directory doesn't own the file
> + * - the directory is world writable
> + * If the sysctl_protected_fifos (or sysctl_protected_regular) is set to 2
> + * the directory doesn't have to be world writable: being group writable will
> + * be enough.
> + *
> + * Returns 0 if the open is allowed, -ve on error.
> + */
> +static int may_create_in_sticky(struct dentry * const dir,
> + struct inode * const inode)
> +{
> + if ((!sysctl_protected_fifos && S_ISFIFO(inode->i_mode)) ||
> + (!sysctl_protected_regular && S_ISREG(inode->i_mode)) ||
> + likely(!(dir->d_inode->i_mode & S_ISVTX)) ||
> + uid_eq(inode->i_uid, dir->d_inode->i_uid) ||
> + uid_eq(current_fsuid(), inode->i_uid))
> + return 0;
> +
> + if (likely(dir->d_inode->i_mode & 0002) ||
> + (dir->d_inode->i_mode & 0020 &&
> + ((sysctl_protected_fifos >= 2 && S_ISFIFO(inode->i_mode)) ||
> + (sysctl_protected_regular >= 2 && S_ISREG(inode->i_mode))))) {
> + return -EACCES;
> + }
> + return 0;
> +}
I think the implementation of may_create_in_sticky() should be rewritten
such that it'd directly correspond to the textual description in the
comment above. As we've seen, trying to write the code "more optimally"
resulted in its logic actually being different from the description.
Meanwhile, I think backporting known-so-buggy code is a bad idea.
Alexander
On 4/23/20 4:03 PM, Ben Hutchings wrote:
> This is the start of the stable review cycle for the 3.16.83 release.
> There are 245 patches in this series, which will be posted as responses
> to this one. If anyone has any issues with these being applied, please
> let me know.
>
> Responses should be made by Tue Apr 28 18:00:00 UTC 2020.
> Anything received after that time might be too late.
>
For v3.16.82-245-g6e963df:
Build results:
total: 135 pass: 135 fail: 0
Qemu test results:
total: 233 pass: 233 fail: 0
Guenter
On Fri, 2020-04-24 at 15:52 +0200, Solar Designer wrote:
> On Fri, Apr 24, 2020 at 12:07:15AM +0100, Ben Hutchings wrote:
> > 3.16.83-rc1 review patch. If anyone has any objections, please let me know.
>
> I do. This patch is currently known-buggy, see this thread:
>
> https://www.openwall.com/lists/oss-security/2020/01/28/2
>
> It is (partially) fixed with these newer commits in 5.5 and 5.5.2:
>
> commit d0cb50185ae942b03c4327be322055d622dc79f6
> Author: Al Viro <[email protected]>
> Date: Sun Jan 26 09:29:34 2020 -0500
>
> do_last(): fetch directory ->i_mode and ->i_uid before it's too late
>
> may_create_in_sticky() call is done when we already have dropped the
> reference to dir.
>
> Fixes: 30aba6656f61e (namei: allow restricted O_CREAT of FIFOs and regular files)
> Signed-off-by: Al Viro <[email protected]>
>
> commit d76341d93dedbcf6ed5a08dfc8bce82d3e9a772b
> Author: Al Viro <[email protected]>
> Date: Sat Feb 1 16:26:45 2020 +0000
>
> vfs: fix do_last() regression
>
> commit 6404674acd596de41fd3ad5f267b4525494a891a upstream.
[...]
> At least inclusion of the above fixes is mandatory for any backports.
I know, and those are the next 2 patches in the series.
> Also, I think no one has fixed the logic of may_create_in_sticky() so
> that it wouldn't unintentionally apply the "protection" when the file
> is neither a FIFO nor a regular file (something I found and mentioned in
> the oss-security posting above).
[...]
> I think the implementation of may_create_in_sticky() should be rewritten
> such that it'd directly correspond to the textual description in the
> comment above. As we've seen, trying to write the code "more optimally"
> resulted in its logic actually being different from the description.
>
> Meanwhile, I think backporting known-so-buggy code is a bad idea.
I can see that it's not quite right, but does it matter in practice?
Directories and symlinks are handled separately; sockets can't be
opened anyway; block and character devices wonn't normally appear in a
sticky directory.
Ben.
--
Ben Hutchings
Knowledge is power. France is bacon.
On Fri, 2020-04-24 at 07:49 -0700, Guenter Roeck wrote:
> On 4/23/20 4:03 PM, Ben Hutchings wrote:
> > This is the start of the stable review cycle for the 3.16.83 release.
> > There are 245 patches in this series, which will be posted as responses
> > to this one. If anyone has any issues with these being applied, please
> > let me know.
> >
> > Responses should be made by Tue Apr 28 18:00:00 UTC 2020.
> > Anything received after that time might be too late.
> >
>
> For v3.16.82-245-g6e963df:
>
> Build results:
> total: 135 pass: 135 fail: 0
> Qemu test results:
> total: 233 pass: 233 fail: 0
Thanks for checking,
Ben.
--
Ben Hutchings
Knowledge is power. France is bacon.
This is the start of the stable review cycle for the 3.16.83 release.
There are 247 patches in this series, which will be posted as responses
to this one. If anyone has any issues with these being applied, please
let me know.
Responses should be made by Tue Apr 28 18:00:00 UTC 2020.
Anything received after that time might be too late.
All the patches have also been committed to the linux-3.16.y-rc branch of
https://git.kernel.org/pub/scm/linux/kernel/git/bwh/linux-stable-rc.git .
A shortlog and diffstat can be found below.
Ben.
-------------
Al Viro (2):
do_last(): fetch directory ->i_mode and ->i_uid before it's too late
[d0cb50185ae942b03c4327be322055d622dc79f6]
vfs: fix do_last() regression
[6404674acd596de41fd3ad5f267b4525494a891a]
Alan Cox (1):
usb: dwc3: pci: Add PCI ID for Intel Braswell
[7d643664ea559b36188cae264047ce3c9bfec3a2]
Alan Stern (1):
HID: Fix slab-out-of-bounds read in hid_field_extract
[8ec321e96e056de84022c032ffea253431a83c3c]
Alberto Aguirre (2):
ALSA: usb-audio: add implicit fb quirk for Axe-Fx II
[17f08b0d9aafccdb10038ab6dbd9ddb6433c13e2]
ALSA: usb-audio: simplify set_sync_ep_implicit_fb_quirk
[103e9625647ad74d201e26fb74afcd8479142a37]
Alex Sverdlin (1):
ARM: 8950/1: ftrace/recordmcount: filter relocation types
[927d780ee371d7e121cea4fc7812f6ef2cea461c]
Amir Goldstein (1):
locks: print unsigned ino in /proc/locks
[98ca480a8f22fdbd768e3dad07024c8d4856576c]
Ard Biesheuvel (1):
x86/efistub: Disable paging at mixed mode entry
[4911ee401b7ceff8f38e0ac597cbf503d71e690c]
Arnd Bergmann (2):
btrfs: tree-checker: use %zu format string for size_t
[7cfad65297bfe0aa2996cd72d21c898aa84436d9]
scsi: fnic: fix invalid stack access
[42ec15ceaea74b5f7a621fc6686cbf69ca66c4cf]
Avinash Patil (1):
mwifiex: fix probable memory corruption while processing TDLS frame
[3c99832d74777c9ec5545a92450fac5d37b0d0e1]
Brian Norris (1):
mwifiex: fix unbalanced locking in mwifiex_process_country_ie()
[65b1aae0d9d5962faccc06bdb8e91a2a0b09451c]
Cengiz Can (1):
blktrace: fix dereference after null check
[153031a301bb07194e9c37466cfce8eacb977621]
Chao Yu (1):
quota: fix wrong condition in is_quota_modification()
[6565c182094f69e4ffdece337d395eb7ec760efc]
Chen-Yu Tsai (1):
net: stmmac: dwmac-sunxi: Allow all RGMII modes
[52cc73e5404c7ba0cbfc50cb4c265108c84b3d5a]
Christian Brauner (1):
taskstats: fix data-race
[0b8d616fb5a8ffa307b1d3af37f55c15dae14f28]
Christophe Leroy (1):
powerpc/irq: fix stack overflow verification
[099bc4812f09155da77eeb960a983470249c9ce1]
Cong Wang (2):
net_sched: fix datalen for ematch
[61678d28d4a45ef376f5d02a839cc37509ae9281]
netfilter: fix a use-after-free in mtype_destroy()
[c120959387efa51479056fd01dc90adfba7a590c]
Dan Carpenter (1):
scsi: iscsi: qla4xxx: fix double free in probe
[fee92f25777789d73e1936b91472e9c4644457c8]
David Hildenbrand (1):
virtio-balloon: fix managed page counts when migrating pages between zones
[63341ab03706e11a31e3dd8ccc0fbc9beaf723f0]
David Sterba (6):
btrfs: add more checks to btrfs_read_sys_array
[e3540eab29e1b2260bc4b9b3979a49a00e3e3af8]
btrfs: cleanup, rename a few variables in btrfs_read_sys_array
[1ffb22cf8c322bbfea6b35fe23d025841b49fede]
btrfs: handle invalid num_stripes in sys_array
[f5cdedd73fa71b74dcc42f2a11a5735d89ce7c4f]
btrfs: kill extent_buffer_page helper
[fb85fc9a675738ee2746b51c3aedde944b18ca02]
btrfs: new define for the inline extent data start
[7ec20afbcb7b257aec82ea5d66e6b0b7499abaca]
btrfs: tree-check: reduce stack consumption in check_dir_item
[e2683fc9d219430f5b78889b50cde7f40efeba7b]
Davidlohr Bueso (1):
blktrace: re-write setting q->blk_trace
[cdea01b2bf98affb7e9c44530108a4a28535eee8]
Dedy Lansky (1):
cfg80211/mac80211: make ieee80211_send_layer2_update a public function
[30ca1aa536211f5ac3de0173513a7a99a98a97f3]
Dmitry Torokhov (5):
HID: hid-input: clear unmapped usages
[4f3882177240a1f55e45a3d241d3121341bead78]
Input: add safety guards to input_set_keycode()
[cb222aed03d798fc074be55e59d9a112338ee784]
ptp: create "pins" together with the rest of attributes
[85a66e55019583da1e0f18706b7a8281c9f6de5b]
ptp: do not explicitly set drvdata in ptp_clock_register()
[882f312dc0751c973db26478f07f082c584d16aa]
ptp: use is_visible method to hide unused attributes
[af59e717d5ff9c8dbf9bcc581c0dfb3b2a9c9030]
Emiliano Ingrassia (1):
usb: core: urb: fix URB structure initialization function
[1cd17f7f0def31e3695501c4f86cd3faf8489840]
Eric Dumazet (9):
6pack,mkiss: fix possible deadlock
[5c9934b6767b16ba60be22ec3cbd4379ad64170d]
bonding: fix bond_neigh_init()
[9e99bfefdbce2e23ef37487a3bcb4adf90a791d1]
macvlan: do not assume mac_header is set in macvlan_broadcast()
[96cc4b69581db68efc9749ef32e9cf8e0160c509]
macvlan: use skb_reset_mac_header() in macvlan_queue_xmit()
[1712b2fff8c682d145c7889d2290696647d82dab]
neighbour: remove neigh_cleanup() method
[f394722fb0d0f701119368959d7cd0ecbc46363a]
netfilter: bridge: make sure to pull arp header in br_nf_forward_arp()
[5604285839aaedfb23ebe297799c6e558939334d]
pkt_sched: fq: do not accept silly TCA_FQ_QUANTUM
[d9e15a2733067c9328fb56d98fe8e574fa19ec31]
tcp: do not send empty skb from tcp_write_xmit()
[1f85e6267caca44b30c54711652b0726fadbb131]
vlan: vlan_changelink() should propagate errors
[eb8ef2a3c50092bb018077c047b8dba1ce0e78e3]
Erkka Talvitie (1):
USB: EHCI: Do not return -EPIPE when hub is disconnected
[64cc3f12d1c7dd054a215bc1ff9cc2abcfe35832]
Eryu Guan (1):
ext4: update c/mtime on truncate up
[911af577de4e444622d46500c1f9a37ab4335d3a]
Eugenio Pérez (1):
vhost: Check docket sk_family instead of call getname
[42d84c8490f9f0931786f1623191fcab397c3d64]
Fabian Henneke (1):
hidraw: Return EPOLLOUT from hidraw_poll
[378b80370aa1fe50f9c48a3ac8af3e416e73b89f]
Felipe Balbi (3):
usb: dwc3: pci: Add Support for Intel Elkhart Lake Devices
[dbb0569de852fb4576d6f62078d515f989a181ca]
usb: dwc3: pci: add support for Comet Lake PCH ID
[7ae622c978db6b2e28b4fced6ecd2a174492059d]
usb: dwc3: pci: add support for TigerLake Devices
[b3649dee5fbb0f6585010e6e9313dfcbb075b22b]
Filipe Manana (3):
Btrfs: fix emptiness check for dirtied extent buffers at check_leaf()
[f177d73949bf758542ca15a1c1945bd2e802cc65]
Btrfs: fix infinite loop during nocow writeback due to race
[de7999afedff02c6631feab3ea726a0e8f8c3d40]
Btrfs: fix removal logic of the tree mod log that leads to use-after-free issues
[6609fee8897ac475378388238456c84298bff802]
Finn Thain (4):
net/sonic: Add mutual exclusion for accessing shared state
[865ad2f2201dc18685ba2686f13217f8b3a9c52c]
net/sonic: Fix receive buffer handling
[9e311820f67e740f4fb8dcb82b4c4b5b05bdd1a5]
net/sonic: Quiesce SONIC before re-initializing descriptor memory
[3f4b7e6a2be982fd8820a2b54d46dd9c351db899]
net/sonic: Use MMIO accessors
[e3885f576196ddfc670b3d53e745de96ffcb49ab]
Florian Faber (1):
can: mscan: mscan_rx_poll(): fix rx path lockup when returning from polling to irq mode
[2d77bd61a2927be8f4e00d9478fe6996c47e8d45]
Florian Westphal (6):
netfilter: arp_tables: init netns pointer in xt_tgchk_param struct
[1b789577f655060d98d20ed0c6f9fbd469d6ba63]
netfilter: arp_tables: init netns pointer in xt_tgdtor_param struct
[212e7f56605ef9688d0846db60c6c6ec06544095]
netfilter: ctnetlink: netns exit must wait for callbacks
[18a110b022a5c02e7dc9f6109d0bd93e58ac6ebb]
netfilter: ebtables: compat: reject all padding in matches/watchers
[e608f631f0ba5f1fc5ee2e260a3a35d13107cbfe]
netfilter: ebtables: convert BUG_ONs to WARN_ONs
[fc6a5d0601c5ac1d02f283a46f60b87b2033e5ca]
netfilter: ipset: avoid null deref when IPSET_ATTR_LINENO is present
[22dad713b8a5ff488e07b821195270672f486eb2]
Geert Uytterhoeven (1):
gpio: Fix error message on out-of-range GPIO in lookup table
[d935bd50dd14a7714cbdba9a76435dbb56edb1ae]
Goldwyn Rodrigues (1):
dm flakey: check for null arg_name in parse_features()
[7690e25302dc7d0cd42b349e746fe44b44a94f2b]
Gu Jinxiang (1):
btrfs: validate type when reading a chunk
[315409b0098fb2651d86553f0436b70502b29bb2]
Hangbin Liu (1):
vxlan: fix tos value before xmit
[71130f29979c7c7956b040673e6b9d5643003176]
Hans de Goede (2):
pinctrl: baytrail: Really serialize all register accesses
[40ecab551232972a39cdd8b6f17ede54a3fdb296]
platform/x86: hp-wmi: Make buffer for HPWMI_FEATURE2_QUERY 128 bytes
[133b2acee3871ae6bf123b8fe34be14464aa3d2c]
Heikki Krogerus (8):
usb: dwc3: pci: add ID for one more Intel Broxton platform
[1ffb4d5cc78a3a99109ff0808ce6915de07a0588]
usb: dwc3: pci: add ID for the Intel Comet Lake -H variant
[3c3caae4cd6e122472efcf64759ff6392fb6bce2]
usb: dwc3: pci: add Intel Cannonlake PCI IDs
[682179592e48fa66056fbad1a86604be4992f885]
usb: dwc3: pci: add Intel Gemini Lake PCI ID
[8f8983a5683623b62b339d159573f95a1fce44f3]
usb: dwc3: pci: add Intel Kabylake PCI ID
[4491ed5042f0419b22a4b08331adb54af31e2caa]
usb: dwc3: pci: add support for Intel Broxton SOC
[b4c580a43d520b7812c0fd064fbab929ce2f1da0]
usb: dwc3: pci: add support for Intel IceLake
[00908693c481f7298adf8cf4d2ff3dfbea8c375f]
usb: dwc3: pci: add support for Intel Sunrise Point PCH
[84a2b61b6eb94036093531cdabc448dddfbae45a]
Hou Tao (1):
dm btree: increase rebalance threshold in __rebalance2()
[474e559567fa631dea8fb8407ab1b6090c903755]
James Bottomley (1):
scsi: enclosure: Fix stale device oops with hot replug
[529244bd1afc102ab164429d338d310d5d65e60d]
Jan Kara (7):
blktrace: Protect q->blk_trace with RCU
[c780e86dd48ef6467a1146cf7d0fe1e05a635039]
ext4: check for directory entries too close to block end
[109ba779d6cca2d519c5dd624a3276d03e21948e]
ext4: fix races between buffered IO and collapse / insert range
[32ebffd3bbb4162da5ff88f9a35dd32d0a28ea70]
ext4: fix races between page faults and hole punching
[ea3d7209ca01da209cda6f0dea8be9cc4b7a933b]
ext4: fix races of writeback with punch hole and zero range
[011278485ecc3cd2a3954b5d4c73101d919bf1fa]
ext4: move unlocked dio protection from ext4_alloc_file_blocks()
[17048e8a083fec7ad841d88ef0812707fbc7e39f]
kobject: Export kobject_get_unless_zero()
[c70c176ff8c3ff0ac6ef9a831cd591ea9a66bd1a]
Jari Ruusu (1):
Fix built-in early-load Intel microcode alignment
[f5ae2ea6347a308cfe91f53b53682ce635497d0d]
Jeff Mahoney (2):
btrfs: cleanup, stop casting for extent_map->lookup everywhere
[95617d69326ce386c95e33db7aeb832b45ee9f8f]
btrfs: struct-funcs, constify readers
[1cbb1f454e5321e47fc1e6b233066c7ccc979d15]
Jerónimo Borque (1):
USB: serial: simple: Add Motorola Solutions TETRA MTP3xxx and MTP85xx
[260e41ac4dd3e5acb90be624c03ba7f019615b75]
Jian-Hong Pan (1):
platform/x86: asus-wmi: Fix keyboard brightness cannot be set to 0
[176a7fca81c5090a7240664e3002c106d296bf31]
Jim Mattson (1):
kvm: x86: Host feature SSBD doesn't imply guest feature SPEC_CTRL_SSBD
[396d2e878f92ec108e4293f1c77ea3bc90b414ff]
Jiri Kosina (1):
HID: hidraw, uhid: Always report EPOLLOUT
[9e635c2851df6caee651e589fbf937b637973c91]
Jiri Slaby (4):
vt: selection, close sel_buffer race
[07e6124a1a46b4b5a9b3cacc0c306b50da87abf5]
vt: selection, handle pending signals in paste_selection
[687bff0cd08f790d540cfb7b2349f0d876cdddec]
vt: selection, push console lock down
[4b70dd57a15d2f4685ac6e38056bad93e81e982f]
vt: selection, push sel_lock up
[e8c75a30a23c6ba63f4ef6895cbf41fd42f21aa2]
Johan Hovold (29):
ALSA: usb-audio: fix sync-ep altsetting sanity check
[5d1b71226dc4d44b4b65766fa9d74492f9d4587b]
Input: aiptek - fix endpoint sanity check
[3111491fca4f01764e0c158c5e0f7ced808eef51]
Input: gtco - fix endpoint sanity check
[a8eeb74df5a6bdb214b2b581b14782c5f5a0cf83]
Input: keyspan-remote - fix control-message timeouts
[ba9a103f40fc4a3ec7558ec9b0b97d4f92034249]
Input: sur40 - fix interface sanity checks
[6b32391ed675827f8425a414abbc6fbd54ea54fe]
USB: adutux: fix interface sanity check
[3c11c4bed02b202e278c0f5c319ae435d7fb9815]
USB: atm: ueagle-atm: add missing endpoint check
[09068c1ad53fb077bdac288869dec2435420bdc4]
USB: core: add endpoint-blacklist quirk
[73f8bda9b5dc1c69df2bc55c0cbb24461a6391a9]
USB: core: fix check for duplicate endpoints
[3e4f8e21c4f27bcf30a48486b9dcc269512b79ff]
USB: idmouse: fix interface sanity checks
[59920635b89d74b9207ea803d5e91498d39e8b69]
USB: quirks: blacklist duplicate ep on Sound Devices USBPre2
[bdd1b147b8026df0e4260b387026b251d888ed01]
USB: serial: ch341: handle unbound port at reset_resume
[4d5ef53f75c22d28f490bcc5c771fcc610a9afa4]
USB: serial: io_edgeport: add missing active-port sanity check
[1568c58d11a7c851bd09341aeefd6a1c308ac40d]
USB: serial: io_edgeport: fix epic endpoint lookup
[7c5a2df3367a2c4984f1300261345817d95b71f8]
USB: serial: io_edgeport: handle unbound ports on URB completion
[e37d1aeda737a20b1846a91a3da3f8b0f00cf690]
USB: serial: keyspan: handle unbound ports
[3018dd3fa114b13261e9599ddb5656ef97a1fa17]
USB: serial: opticon: fix control-message timeouts
[5e28055f340275a8616eee88ef19186631b4d136]
USB: serial: quatech2: handle unbound ports
[9715a43eea77e42678a1002623f2d9a78f5b81a1]
USB: serial: suppress driver bind attributes
[fdb838efa31e1ed9a13ae6ad0b64e30fdbd00570]
can: gs_usb: gs_usb_probe(): use descriptors of current altsetting
[2f361cd9474ab2c4ab9ac8db20faf81e66c6279b]
media: ov519: add missing endpoint sanity checks
[998912346c0da53a6dbb71fab3a138586b596b30]
media: stv06xx: add missing descriptor sanity checks
[485b06aadb933190f4bc44e006076bc27a23f205]
media: xirlink_cit: add missing descriptor sanity checks
[a246b4d547708f33ff4d4b9a7a5dbac741dc89d8]
r8152: add missing endpoint sanity check
[86f3f4cd53707ceeec079b83205c8d3c756eca93]
staging: gigaset: add endpoint-type sanity check
[ed9ed5a89acba51b82bdff61144d4e4a4245ec8a]
staging: gigaset: fix general protection fault on probe
[53f35a39c3860baac1e5ca80bf052751cfb24a99]
staging: gigaset: fix illegal free on probe errors
[84f60ca7b326ed8c08582417493982fe2573a9ad]
staging: rtl8188eu: fix interface sanity check
[74ca34118a0e05793935d804ccffcedd6eb56596]
staging: rtl8712: fix interface sanity check
[c724f776f048538ecfdf53a52b7a522309f5c504]
Johannes Thumshirn (1):
btrfs: ensure that a DUP or RAID1 block group has exactly two stripes
[349ae63f40638a28c6fce52e8447c2d14b84cc0c]
Jose Abreu (2):
net: stmmac: 16KB buffer must be 16 byte aligned
[8605131747e7e1fd8f6c9f97a00287aae2b2c640]
net: stmmac: Enable 16KB buffer size
[b2f3a481c4cd62f78391b836b64c0a6e72b503d2]
Josef Bacik (9):
Btrfs: fix em leak in find_first_block_group
[187ee58c62c1d0d238d3dc4835869d33e1869906]
btrfs: abort transaction after failed inode updates in create_subvol
[c7e54b5102bf3614cadb9ca32d7be73bad6cecf0]
btrfs: check rw_devices, not num_devices for balance
[b35cf1f0bf1f2b0b193093338414b9bd63b29015]
btrfs: do not call synchronize_srcu() in inode_tree_del
[f72ff01df9cf5db25c76674cac16605992d15467]
btrfs: do not delete mismatched root refs
[423a716cd7be16fb08690760691befe3be97d3fc]
btrfs: do not leak reloc root if we fail to read the fs root
[ca1aa2818a53875cfdd175fb5e9a2984e997cce9]
btrfs: handle ENOENT in btrfs_uuid_tree_iterate
[714cd3e8cba6841220dce9063a7388a81de03825]
btrfs: skip log replay on orphaned roots
[9bc574de590510eff899c3ca8dbaf013566b5efe]
ext4: only call ext4_truncate when size <= isize
[3da40c7b089810ac9cf2bb1e59633f619f3a7312]
Jouni Malinen (1):
mac80211: Do not send Layer 2 Update frame before authorization
[3e493173b7841259a08c5c8e5cbe90adb349da7e]
Kaitao Cheng (1):
kernel/trace: Fix do not unregister tracepoints when register sched_migrate_task fail
[50f9ad607ea891a9308e67b81f774c71736d1098]
Keiya Nobuta (1):
usb: core: hub: Improved device recognition on remote wakeup
[9c06ac4c83df6d6fbdbf7488fbad822b4002ba19]
Kenneth Klette Jonassen (1):
pkt_sched: fq: avoid hang when quantum 0
[3725a269815ba6dbb415feddc47da5af7d1fac58]
Lars Möllendorf (1):
iio: buffer: align the size of scan bytes to size of the largest element
[883f616530692d81cb70f8a32d85c0d2afc05f69]
Leo Yan (1):
tty: serial: msm_serial: Fix lockup for sysrq and oops
[0e4f7f920a5c6bfe5e851e989f27b35a0cc7fb7e]
Linus Torvalds (1):
floppy: check FDC index for errors before assigning it
[2e90ca68b0d2f5548804f22f0dd61145516171e3]
Liu Bo (9):
Btrfs: add validadtion checks for chunk loading
[e06cd3dd7cea50e87663a88acdfdb7ac1c53a5ca]
Btrfs: check btree node's nritems
[053ab70f0604224c7893b43f9d9d5efa283580d6]
Btrfs: check inconsistence between chunk and block group
[6fb37b756acce6d6e045f79c3764206033f617b4]
Btrfs: detect corruption when non-root leaf has zero item
[1ba98d086fe3a14d6a31f2f66dbab70c45d00f63]
Btrfs: fix BUG_ON in btrfs_mark_buffer_dirty
[ef85b25e982b5bba1530b936e283ef129f02ab9d]
Btrfs: improve check_node to avoid reading corrupted nodes
[6b722c1747d533ac6d4df110dc8233db46918b65]
Btrfs: kill BUG_ON in run_delayed_tree_ref
[02794222c4132ac003e7281fb71f4ec1645ffc87]
Btrfs: memset to avoid stale content in btree leaf
[851cd173f06045816528176001cf82948282029c]
Btrfs: memset to avoid stale content in btree node block
[3eb548ee3a8042d95ad81be254e67a5222c24e03]
Logan Gunthorpe (1):
chardev: add helper function to register char devs with a struct device
[233ed09d7fdacf592ee91e6c97ce5f4364fbe7c0]
Lu Fengqi (1):
btrfs: Remove redundant btrfs_release_path from btrfs_unlink_subvol
[5b7d687ad5913a56b6a8788435d7a53990b4176d]
Lukas Czerner (1):
ext4: wait for existing dio workers in ext4_alloc_file_blocks()
[0d306dcf86e8f065dff42a4a934ae9d99af35ba5]
Luuk Paulussen (1):
hwmon: (adt7475) Make volt2reg return same reg as reg2volt input
[cf3ca1877574a306c0207cbf7fdf25419d9229df]
Mao Wenan (2):
af_packet: set defaule value for tmo
[b43d1f9f7067c6759b1051e8ecb84e82cef569fe]
net: sonic: return NETDEV_TX_OK if failed to map buffer
[6e1cdedcf0362fed3aedfe051d46bd7ee2a85fe1]
Marcel Holtmann (2):
HID: hidraw: Fix returning EPOLLOUT from hidraw_poll
[9f3b61dc1dd7b81e99e7ed23776bb64a35f39e1a]
HID: uhid: Fix returning EPOLLOUT from uhid_char_poll
[be54e7461ffdc5809b67d2aeefc1ddc9a91470c7]
Mathias Nyman (2):
xhci: handle some XHCI_TRUST_TX_LENGTH quirks cases as default behaviour.
[7ff11162808cc2ec66353fc012c58bb449c892c3]
xhci: make sure interrupts are restored to correct state
[bd82873f23c9a6ad834348f8b83f3b6a5bca2c65]
Mauro Carvalho Chehab (3):
[media] media-device: dynamically allocate struct media_devnode
[a087ce704b802becbb4b0f2a20f2cb3f6911802e]
[media] media-devnode: fix namespace mess
[163f1e93e995048b894c5fc86a6034d16beed740]
[media] media-devnode: just return 0 instead of using a var
[8b37c6455fc8f43e0e95db2847284e618db6a4f8]
Max Kellermann (2):
[media] drivers/media/media-devnode: clear private_data before put_device()
[bf244f665d76d20312c80524689b32a752888838]
[media] media-devnode: add missing mutex lock in error handler
[88336e174645948da269e1812f138f727cd2896b]
Michael Straube (1):
staging: rtl8188eu: Add device code for TP-Link TL-WN727N v5.21
[58dcc5bf4030cab548d5c98cd4cd3632a5444d5a]
Michał Mirosław (1):
mmc: sdhci: fix minimum clock rate for v3 controller
[2a187d03352086e300daa2044051db00044cd171]
Mika Westerberg (4):
pinctrl: baytrail: Clear interrupt triggering from pins that are in GPIO mode
[95f0972c7e4cbf3fc68160131c5ac2f033481d00]
pinctrl: baytrail: Relax GPIO request rules
[f8323b6bb2cc7d26941d4838dd4375952980a88a]
pinctrl: baytrail: Rework interrupt handling
[31e4329f99062a06dca5a493bb4495a63b2dc6ba]
pinctrl: baytrail: Serialize all register access
[39ce8150a079e3ae6ed9abf26d7918a558ef7c19]
Mike Snitzer (1):
dm flakey: fix reads to be issued if drop_writes configured
[299f6230bc6d0ccd5f95bb0fb865d80a9c7d5ccc]
Mikulas Patocka (1):
block: fix an integer overflow in logical block size
[ad6bf88a6c19a39fb3b0045d78ea880325dfcf15]
Moni Shoua (1):
IB/mlx4: Avoid executing gid task when device is being removed
[4bf9715f184969dc703bde7be94919995024a6a9]
Nicolai Stange (2):
libertas: don't exit from lbs_ibss_join_existing() with RCU read lock held
[c7bf1fb7ddca331780b9a733ae308737b39f1ad4]
libertas: make lbs_ibss_join_existing() return error code on rates overflow
[1754c4f60aaf1e17d886afefee97e94d7f27b4cb]
Nikos Tsironis (1):
dm thin metadata: Add support for a pre-commit callback
[ecda7c0280e6b3398459dc589b9a41c1adb45529]
Pablo Neira Ayuso (2):
netfilter: nf_tables: missing sanitization in data from userspace
[71df14b0ce094be46d105b5a3ededd83b8e779a0]
netfilter: nf_tables: validate NFT_DATA_VALUE after nft_data_init()
[0d2c96af797ba149e559c5875c0151384ab6dd14]
Paolo Bonzini (1):
KVM: nVMX: Don't emulate instructions in guest mode
[07721feee46b4b248402133228235318199b05ec]
Parav Pandit (1):
IB/mlx4: Follow mirror sequence of device add during device removal
[89f988d93c62384758b19323c886db917a80c371]
Paul Cercueil (1):
usb: musb: dma: Correct parameter passed to IRQ handler
[c80d0f4426c7fdc7efd6ae8d8b021dcfc89b4254]
Pavel Tatashin (1):
x86/pti/efi: broken conversion from efi to kernel page table
[not upstream; fixes a bug specific to KAISER]
Pengcheng Yang (1):
tcp: fix "old stuff" D-SACK causing SACK to be treated as D-SACK
[c9655008e7845bcfdaac10a1ed8554ec167aea88]
Pete Zaitcev (1):
usb: mon: Fix a deadlock in usbmon between mmap and read
[19e6317d24c25ee737c65d1ffb7483bdda4bb54a]
Peter Hurley (1):
tty: vt: Fix !TASK_RUNNING diagnostic warning from paste_selection()
[61e86cc90af49cecef9c54ccea1f572fbcb695ac]
Peter Zijlstra (1):
futex: Fix inode life-time issue
[8019ad13ef7f64be44d4f892af9c840179009254]
Qize Wang (1):
mwifiex: Fix heap overflow in mmwifiex_process_tdls_action_frame()
[1e58252e334dc3f3756f424a157d1b7484464c40]
Qu Wenruo (14):
btrfs: Add checker for EXTENT_CSUM
[4b865cab96fe2a30ed512cf667b354bd291b3b0a]
btrfs: Add sanity check for EXTENT_DATA when reading out leaf
[40c3c40947324d9f40bf47830c92c59a9bbadf4a]
btrfs: Check if item pointer overlaps with the item itself
[7f43d4affb2a254d421ab20b0cf65ac2569909fb]
btrfs: Check that each block group has corresponding chunk at mount time
[514c7dca85a0bf40be984dab0b477403a6db901f]
btrfs: Enhance chunk validation check
[f04b772bfc17f502703794f4d100d12155c1a1a9]
btrfs: Move leaf and node validation checker to tree-checker.c
[557ea5dd003d371536f6b4e8f7c8209a2b6fd4e3]
btrfs: Refactor check_leaf function for later expansion
[c3267bbaa9cae09b62960eafe33ad19196803285]
btrfs: Verify that every chunk has corresponding block group at mount time
[7ef49515fa6727cb4b6f2f5b0ffbc5fc20a9f8c6]
btrfs: tree-checker: Add checker for dir item
[ad7b0368f33cffe67fecd302028915926e50ef7e]
btrfs: tree-checker: Check level for leaves and nodes
[f556faa46eb4e96d0d0772e74ecf66781e132f72]
btrfs: tree-checker: Detect invalid and empty essential trees
[ba480dd4db9f1798541eb2d1c423fc95feee8d36]
btrfs: tree-checker: Enhance btrfs_check_node output
[bba4f29896c986c4cec17bc0f19f2ce644fceae1]
btrfs: tree-checker: Fix false panic for sanity test
[69fc6cbbac542c349b3d350d10f6e394c253c81d]
btrfs: tree-checker: Verify block_group_item
[fce466eab7ac6baa9d2dcd88abcf945be3d4a089]
Radoslaw Tyl (1):
ixgbevf: Remove limit of 10 entries for unicast filter list
[aa604651d523b1493988d0bf6710339f3ee60272]
Rafael J. Wysocki (1):
ACPI: PM: Avoid attaching ACPI PM domain to certain devices
[b9ea0bae260f6aae546db224daa6ac1bd9d94b91]
Randy Dunlap (1):
mm: mempolicy: require at least one nodeid for MPOL_PREFERRED
[aa9f7d5172fac9bf1f09e678c35e287a40a7b7dd]
Richard Palethorpe (2):
can, slip: Protect tty->disc_data in write_wakeup and close with RCU
[0ace17d56824165c7f4c68785d6b58971db954dd]
slcan: Don't transmit uninitialized stack data in padding
[b9258a2cece4ec1f020715fe3554bc2e360f6264]
Russell King (2):
gpiolib: fix up emulated open drain outputs
[256efaea1fdc4e38970489197409a26125ee0aaa]
mod_devicetable: fix PHY module format
[d2ed49cf6c13e379c5819aa5ac20e1f9674ebc89]
Sabrina Dubroca (1):
net: ipv6_stub: use ip6_dst_lookup_flow instead of ip6_dst_lookup
[6c8991f41546c3c472503dff1ea9daaddf9331c2]
Salvatore Mesoraca (1):
namei: allow restricted O_CREAT of FIFOs and regular files
[30aba6656f61ed44cba445a3c0d38b296fa9e8f5]
Shaokun Zhang (1):
btrfs: tree-checker: Fix misleading group system information
[761333f2f50ccc887aa9957ae829300262c0d15b]
Shengjiu Wang (1):
ASoC: wm8962: fix lambda value
[556672d75ff486e0b6786056da624131679e0576]
Shuah Khan (3):
[media] media: Fix media_open() to clear filp->private_data in error leg
[d40ec6fdb0b03b7be4c7923a3da0e46bf943740a]
[media] media: fix media devnode ioctl/syscall and unregister race
[6f0dd24a084a17f9984dd49dffbf7055bf123993]
[media] media: fix use-after-free in cdev_put() when app exits after driver unbind
[5b28dde51d0ccc54cee70756e1800d70bed7114a]
Steven Rostedt (1):
tracing: Have stack tracer compile when MCOUNT_INSN_SIZE is not defined
[b8299d362d0837ae39e87e9019ebe6b736e0f035]
Sudip Mukherjee (2):
tty: always relink the port
[273f632912f1b24b642ba5b7eb5022e43a72f3b5]
tty: link tty and port before configuring it as console
[fb2b90014d782d80d7ebf663e50f96d8c507a73c]
Suren Baghdasaryan (1):
staging: android: ashmem: Disallow ashmem memory from being remapped
[6d67b0290b4b84c477e6a2fc6e005e174d3c7786]
Suwan Kim (1):
usbip: Fix error path of vhci_recv_ret_submit()
[aabb5b833872524eaf28f52187e5987984982264]
Sven Eckelmann (1):
batman-adv: Fix DAT candidate selection on little endian systems
[4cc4a1708903f404d2ca0dfde30e71e052c6cbc9]
Takashi Iwai (4):
ALSA: hda/ca0132 - Avoid endless loop
[cb04fc3b6b076f67d228a0b7d096c69ad486c09c]
ALSA: ice1724: Fix sleep-in-atomic in Infrasonic Quartet support code
[0aec96f5897ac16ad9945f531b4bef9a2edd2ebd]
ALSA: pcm: Avoid possible info leaks from PCM stream buffers
[add9d56d7b3781532208afbff5509d7382fb6efe]
ALSA: seq: Fix racy access for queue timer in proc read
[60adcfde92fa40fcb2dbf7cc52f9b096e0cd109a]
Thomas Gleixner (1):
futex: Unbreak futex hashing
[8d67743653dce5a0e7aa500fcccb237cde7ad88e]
Tom Lendacky (1):
x86/microcode/AMD: Add support for fam17h microcode loading
[f4e9b7af0cd58dd039a0fb2cd67d57cea4889abf]
Vivek Goyal (1):
dm: do not override error code returned from dm_get_device()
[e80d1c805a3b2f0ad2081369be5dc5deedd5ee59]
Vladis Dronov (2):
ptp: fix the race between the release of ptp_clock and cdev
[a33121e5487b424339636b25c35d3a180eaa5f5e]
ptp: free ptp device pin descriptors properly
[75718584cb3c64e6269109d4d54f888ac5a5fd15]
Wang Shilong (1):
Btrfs: fix wrong max inline data size limit
[c01a5c074c0f6f85a3b02e39432b9e5576ab51de]
Wei Yongjun (1):
dm flakey: return -EINVAL on interval bounds error in flakey_ctr()
[bff7e067ee518f9ed7e1cbc63e4c9e01670d0b71]
Wen Huang (1):
libertas: Fix two buffer overflows at parsing bss descriptor
[e5e884b42639c74b5b57dc277909915c0aefc8bb]
Wen Yang (1):
ftrace: Avoid potential division by zero in function profiler
[e31f7939c1c27faa5d0e3f14519eaf7c89e8a69d]
Will Deacon (1):
chardev: Avoid potential use-after-free in 'chrdev_open()'
[68faa679b8be1a74e6663c21c3a9d25d32f1c079]
Xiang Chen (1):
scsi: sd: Clear sdkp->protection_type if disk is reformatted without PI
[465f4edaecc6c37f81349233e84d46246bcac11a]
Xin Long (1):
sctp: free cmd->obj.chunk for the unprocessed SCTP_CMD_REPLY
[be7a7729207797476b6666f046d765bdf9630407]
YueHaibing (1):
ptp: Fix pass zero to ERR_PTR() in ptp_clock_register
[aea0a897af9e44c258e8ab9296fad417f1bc063a]
Zhang Xiaoxu (1):
vgacon: Fix a UAF in vgacon_invert_region
[513dc792d6060d5ef572e43852683097a8420f56]
Documentation/sysctl/fs.txt | 36 ++
Makefile | 4 +-
arch/powerpc/kernel/irq.c | 4 +-
arch/x86/boot/compressed/head_64.S | 5 +
arch/x86/include/asm/kaiser.h | 10 +
arch/x86/kernel/cpu/microcode/amd.c | 4 +
arch/x86/kvm/cpuid.c | 3 +-
arch/x86/kvm/vmx.c | 2 +-
arch/x86/realmode/init.c | 4 +-
arch/x86/realmode/rm/trampoline_64.S | 3 +-
block/blk-settings.c | 2 +-
drivers/acpi/device_pm.c | 12 +-
drivers/block/floppy.c | 7 +-
drivers/gpio/gpiolib.c | 13 +-
drivers/hid/hid-core.c | 6 +
drivers/hid/hid-input.c | 16 +-
drivers/hid/hidraw.c | 7 +-
drivers/hid/uhid.c | 5 +-
drivers/hwmon/adt7475.c | 5 +-
drivers/iio/industrialio-buffer.c | 6 +-
drivers/infiniband/hw/mlx4/main.c | 16 +-
drivers/input/input.c | 26 +-
drivers/input/misc/keyspan_remote.c | 9 +-
drivers/input/tablet/aiptek.c | 6 +-
drivers/input/tablet/gtco.c | 10 +-
drivers/input/touchscreen/sur40.c | 2 +-
drivers/isdn/gigaset/usb-gigaset.c | 23 +-
drivers/md/dm-crypt.c | 4 +-
drivers/md/dm-delay.c | 16 +-
drivers/md/dm-flakey.c | 40 +-
drivers/md/dm-linear.c | 7 +-
drivers/md/dm-raid1.c | 8 +-
drivers/md/dm-snap-persistent.c | 2 +-
drivers/md/dm-stripe.c | 8 +-
drivers/md/dm-thin-metadata.c | 29 +
drivers/md/dm-thin-metadata.h | 7 +
drivers/md/persistent-data/dm-btree-remove.c | 8 +-
drivers/md/raid0.c | 2 +-
drivers/media/media-device.c | 43 +-
drivers/media/media-devnode.c | 171 +++---
drivers/media/usb/gspca/ov519.c | 10 +
drivers/media/usb/gspca/stv06xx/stv06xx.c | 19 +-
drivers/media/usb/gspca/stv06xx/stv06xx_pb0100.c | 4 +
drivers/media/usb/gspca/xirlink_cit.c | 18 +-
drivers/media/usb/uvc/uvc_driver.c | 2 +-
drivers/misc/enclosure.c | 3 +-
drivers/mmc/host/sdhci.c | 10 +-
drivers/net/bonding/bond_main.c | 40 +-
drivers/net/can/mscan/mscan.c | 21 +-
drivers/net/can/slcan.c | 16 +-
drivers/net/can/usb/gs_usb.c | 4 +-
drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c | 5 -
drivers/net/ethernet/natsemi/sonic.c | 113 +++-
drivers/net/ethernet/natsemi/sonic.h | 25 +-
drivers/net/ethernet/stmicro/stmmac/common.h | 5 +-
drivers/net/ethernet/stmicro/stmmac/dwmac-sunxi.c | 2 +-
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 4 +-
drivers/net/hamradio/6pack.c | 4 +-
drivers/net/hamradio/mkiss.c | 4 +-
drivers/net/macvlan.c | 3 +-
drivers/net/slip/slip.c | 12 +-
drivers/net/usb/r8152.c | 3 +
drivers/net/vxlan.c | 5 +-
drivers/net/wireless/libertas/cfg.c | 18 +-
drivers/net/wireless/mwifiex/sta_ioctl.c | 1 +
drivers/net/wireless/mwifiex/tdls.c | 74 ++-
drivers/pinctrl/pinctrl-baytrail.c | 212 ++++---
drivers/platform/x86/asus-wmi.c | 8 +-
drivers/platform/x86/hp-wmi.c | 2 +-
drivers/ptp/ptp_clock.c | 42 +-
drivers/ptp/ptp_private.h | 9 +-
drivers/ptp/ptp_sysfs.c | 162 +++---
drivers/scsi/fnic/vnic_dev.c | 20 +-
drivers/scsi/qla4xxx/ql4_os.c | 1 -
drivers/scsi/sd.c | 4 +-
drivers/staging/android/ashmem.c | 28 +
drivers/staging/rtl8188eu/os_dep/usb_intf.c | 3 +-
drivers/staging/rtl8712/usb_intf.c | 2 +-
drivers/staging/usbip/vhci_rx.c | 13 +-
drivers/tty/serial/msm_serial.c | 13 +-
drivers/tty/serial/serial_core.c | 1 +
drivers/tty/vt/selection.c | 34 +-
drivers/tty/vt/vt.c | 2 -
drivers/usb/atm/ueagle-atm.c | 18 +-
drivers/usb/core/config.c | 77 ++-
drivers/usb/core/hub.c | 1 +
drivers/usb/core/quirks.c | 37 ++
drivers/usb/core/urb.c | 1 +
drivers/usb/core/usb.h | 3 +
drivers/usb/dwc3/dwc3-pci.c | 30 +
drivers/usb/host/ehci-q.c | 13 +-
drivers/usb/host/xhci-hub.c | 8 +-
drivers/usb/host/xhci-ring.c | 3 +-
drivers/usb/misc/adutux.c | 2 +-
drivers/usb/misc/idmouse.c | 2 +-
drivers/usb/mon/mon_bin.c | 32 +-
drivers/usb/musb/musbhsdma.c | 2 +-
drivers/usb/serial/ch341.c | 6 +-
drivers/usb/serial/io_edgeport.c | 26 +-
drivers/usb/serial/keyspan.c | 4 +
drivers/usb/serial/opticon.c | 2 +-
drivers/usb/serial/quatech2.c | 6 +
drivers/usb/serial/usb-serial-simple.c | 2 +
drivers/usb/serial/usb-serial.c | 3 +
drivers/vhost/net.c | 13 +-
drivers/video/console/vgacon.c | 3 +
drivers/virtio/virtio_balloon.c | 10 +
firmware/Makefile | 2 +-
fs/btrfs/Makefile | 2 +-
fs/btrfs/ctree.c | 19 +-
fs/btrfs/ctree.h | 157 +++---
fs/btrfs/dev-replace.c | 2 +-
fs/btrfs/disk-io.c | 80 +--
fs/btrfs/extent-tree.c | 110 +++-
fs/btrfs/extent_io.c | 98 ++--
fs/btrfs/extent_io.h | 25 +-
fs/btrfs/extent_map.c | 2 +-
fs/btrfs/extent_map.h | 10 +-
fs/btrfs/inode.c | 8 +-
fs/btrfs/ioctl.c | 10 +-
fs/btrfs/relocation.c | 1 +
fs/btrfs/root-tree.c | 10 +-
fs/btrfs/scrub.c | 2 +-
fs/btrfs/struct-funcs.c | 9 +-
fs/btrfs/tree-checker.c | 649 ++++++++++++++++++++++
fs/btrfs/tree-checker.h | 38 ++
fs/btrfs/tree-log.c | 24 +-
fs/btrfs/uuid-tree.c | 2 +
fs/btrfs/volumes.c | 206 +++++--
fs/btrfs/volumes.h | 2 +
fs/char_dev.c | 88 ++-
fs/ext4/dir.c | 5 +
fs/ext4/ext4.h | 13 +
fs/ext4/extents.c | 89 +--
fs/ext4/file.c | 2 +-
fs/ext4/inode.c | 117 +++-
fs/ext4/super.c | 1 +
fs/ext4/truncate.h | 2 +
fs/inode.c | 1 +
fs/locks.c | 2 +-
fs/namei.c | 56 +-
include/linux/blkdev.h | 10 +-
include/linux/blktrace_api.h | 6 +-
include/linux/cdev.h | 5 +
include/linux/fs.h | 3 +
include/linux/futex.h | 17 +-
include/linux/if_ether.h | 8 +
include/linux/kobject.h | 2 +
include/linux/mod_devicetable.h | 4 +-
include/linux/netfilter_arp/arp_tables.h | 2 +-
include/linux/posix-clock.h | 19 +-
include/linux/quotaops.h | 2 +-
include/linux/usb/quirks.h | 3 +
include/media/media-device.h | 5 +-
include/media/media-devnode.h | 32 +-
include/net/addrconf.h | 5 +-
include/net/cfg80211.h | 11 +
include/net/neighbour.h | 1 -
kernel/futex.c | 93 ++--
kernel/sysctl.c | 18 +
kernel/taskstats.c | 30 +-
kernel/time/posix-clock.c | 31 +-
kernel/trace/blktrace.c | 129 +++--
kernel/trace/ftrace.c | 6 +-
kernel/trace/trace_sched_wakeup.c | 4 +-
kernel/trace/trace_stack.c | 5 +
lib/kobject.c | 5 +-
mm/mempolicy.c | 6 +-
net/8021q/vlan_netlink.c | 10 +-
net/batman-adv/distributed-arp-table.c | 4 +-
net/bridge/br_netfilter.c | 3 +
net/bridge/netfilter/ebtables.c | 58 +-
net/core/neighbour.c | 3 -
net/ipv4/netfilter/arp_tables.c | 42 +-
net/ipv4/netfilter/arptable_filter.c | 2 +-
net/ipv4/tcp_input.c | 5 +-
net/ipv4/tcp_output.c | 8 +
net/ipv6/af_inet6.c | 2 +-
net/mac80211/cfg.c | 55 +-
net/mac80211/sta_info.c | 4 +
net/netfilter/ipset/ip_set_bitmap_gen.h | 2 +-
net/netfilter/ipset/ip_set_core.c | 3 +-
net/netfilter/nf_conntrack_netlink.c | 3 +
net/netfilter/nft_bitwise.c | 19 +-
net/netfilter/nft_cmp.c | 18 +-
net/packet/af_packet.c | 3 +-
net/sched/ematch.c | 2 +-
net/sched/sch_fq.c | 10 +-
net/sctp/sm_sideeffect.c | 28 +-
net/wireless/util.c | 45 ++
scripts/recordmcount.c | 17 +
sound/core/pcm_native.c | 4 +
sound/core/seq/seq_timer.c | 14 +-
sound/pci/hda/patch_ca0132.c | 5 +-
sound/pci/ice1712/ice1724.c | 9 +-
sound/soc/codecs/wm8962.c | 4 +-
sound/usb/pcm.c | 44 +-
197 files changed, 3378 insertions(+), 1230 deletions(-)
--
Ben Hutchings
Knowledge is power. France is bacon.
3.16.83-rc2 review patch. If anyone has any objections, please let me know.
------------------
From: Peter Zijlstra <[email protected]>
commit 8019ad13ef7f64be44d4f892af9c840179009254 upstream.
As reported by Jann, ihold() does not in fact guarantee inode
persistence. And instead of making it so, replace the usage of inode
pointers with a per boot, machine wide, unique inode identifier.
This sequence number is global, but shared (file backed) futexes are
rare enough that this should not become a performance issue.
Reported-by: Jann Horn <[email protected]>
Suggested-by: Linus Torvalds <[email protected]>
Signed-off-by: Peter Zijlstra (Intel) <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
[bwh: Backported to 3.16: Use atomic64_cmpxchg() instead of the
_relaxed() variant which we don't have]
Signed-off-by: Ben Hutchings <[email protected]>
---
fs/inode.c | 1 +
include/linux/fs.h | 1 +
include/linux/futex.h | 17 +++++----
kernel/futex.c | 89 ++++++++++++++++++++++++++-----------------
4 files changed, 65 insertions(+), 43 deletions(-)
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -131,6 +131,7 @@ int inode_init_always(struct super_block
inode->i_sb = sb;
inode->i_blkbits = sb->s_blocksize_bits;
inode->i_flags = 0;
+ atomic64_set(&inode->i_sequence, 0);
atomic_set(&inode->i_count, 1);
inode->i_op = &empty_iops;
inode->i_fop = &empty_fops;
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -570,6 +570,7 @@ struct inode {
struct rcu_head i_rcu;
};
u64 i_version;
+ atomic64_t i_sequence; /* see futex */
atomic_t i_count;
atomic_t i_dio_count;
atomic_t i_writecount;
--- a/include/linux/futex.h
+++ b/include/linux/futex.h
@@ -39,23 +39,26 @@ handle_futex_death(u32 __user *uaddr, st
union futex_key {
struct {
+ u64 i_seq;
unsigned long pgoff;
- struct inode *inode;
- int offset;
+ unsigned int offset;
} shared;
struct {
+ union {
+ struct mm_struct *mm;
+ u64 __tmp;
+ };
unsigned long address;
- struct mm_struct *mm;
- int offset;
+ unsigned int offset;
} private;
struct {
+ u64 ptr;
unsigned long word;
- void *ptr;
- int offset;
+ unsigned int offset;
} both;
};
-#define FUTEX_KEY_INIT (union futex_key) { .both = { .ptr = NULL } }
+#define FUTEX_KEY_INIT (union futex_key) { .both = { .ptr = 0ULL } }
#ifdef CONFIG_FUTEX
extern void exit_robust_list(struct task_struct *curr);
--- a/kernel/futex.c
+++ b/kernel/futex.c
@@ -338,7 +338,7 @@ static void get_futex_key_refs(union fut
switch (key->both.offset & (FUT_OFF_INODE|FUT_OFF_MMSHARED)) {
case FUT_OFF_INODE:
- ihold(key->shared.inode); /* implies MB (B) */
+ smp_mb(); /* explicit smp_mb(); (B) */
break;
case FUT_OFF_MMSHARED:
futex_get_mm(key); /* implies MB (B) */
@@ -362,7 +362,6 @@ static void drop_futex_key_refs(union fu
switch (key->both.offset & (FUT_OFF_INODE|FUT_OFF_MMSHARED)) {
case FUT_OFF_INODE:
- iput(key->shared.inode);
break;
case FUT_OFF_MMSHARED:
mmdrop(key->private.mm);
@@ -370,6 +369,46 @@ static void drop_futex_key_refs(union fu
}
}
+/*
+ * Generate a machine wide unique identifier for this inode.
+ *
+ * This relies on u64 not wrapping in the life-time of the machine; which with
+ * 1ns resolution means almost 585 years.
+ *
+ * This further relies on the fact that a well formed program will not unmap
+ * the file while it has a (shared) futex waiting on it. This mapping will have
+ * a file reference which pins the mount and inode.
+ *
+ * If for some reason an inode gets evicted and read back in again, it will get
+ * a new sequence number and will _NOT_ match, even though it is the exact same
+ * file.
+ *
+ * It is important that match_futex() will never have a false-positive, esp.
+ * for PI futexes that can mess up the state. The above argues that false-negatives
+ * are only possible for malformed programs.
+ */
+static u64 get_inode_sequence_number(struct inode *inode)
+{
+ static atomic64_t i_seq;
+ u64 old;
+
+ /* Does the inode already have a sequence number? */
+ old = atomic64_read(&inode->i_sequence);
+ if (likely(old))
+ return old;
+
+ for (;;) {
+ u64 new = atomic64_add_return(1, &i_seq);
+ if (WARN_ON_ONCE(!new))
+ continue;
+
+ old = atomic64_cmpxchg(&inode->i_sequence, 0, new);
+ if (old)
+ return old;
+ return new;
+ }
+}
+
/**
* get_futex_key() - Get parameters which are the keys for a futex
* @uaddr: virtual address of the futex
@@ -382,9 +421,15 @@ static void drop_futex_key_refs(union fu
*
* The key words are stored in *key on success.
*
- * For shared mappings, it's (page->index, file_inode(vma->vm_file),
- * offset_within_page). For private mappings, it's (uaddr, current->mm).
- * We can usually work out the index without swapping in the page.
+ * For shared mappings (when @fshared), the key is:
+ * ( inode->i_sequence, page->index, offset_within_page )
+ * [ also see get_inode_sequence_number() ]
+ *
+ * For private mappings (or when !@fshared), the key is:
+ * ( current->mm, address, 0 )
+ *
+ * This allows (cross process, where applicable) identification of the futex
+ * without keeping the page pinned for the duration of the FUTEX_WAIT.
*
* lock_page() might sleep, the caller should not hold a spinlock.
*/
@@ -545,8 +590,6 @@ again:
key->private.mm = mm;
key->private.address = address;
- get_futex_key_refs(key); /* implies smp_mb(); (B) */
-
} else {
struct inode *inode;
@@ -578,40 +621,14 @@ again:
goto again;
}
- /*
- * Take a reference unless it is about to be freed. Previously
- * this reference was taken by ihold under the page lock
- * pinning the inode in place so i_lock was unnecessary. The
- * only way for this check to fail is if the inode was
- * truncated in parallel which is almost certainly an
- * application bug. In such a case, just retry.
- *
- * We are not calling into get_futex_key_refs() in file-backed
- * cases, therefore a successful atomic_inc return below will
- * guarantee that get_futex_key() will still imply smp_mb(); (B).
- */
- if (!atomic_inc_not_zero(&inode->i_count)) {
- rcu_read_unlock();
- put_page(page_head);
-
- goto again;
- }
-
- /* Should be impossible but lets be paranoid for now */
- if (WARN_ON_ONCE(inode->i_mapping != mapping)) {
- err = -EFAULT;
- rcu_read_unlock();
- iput(inode);
-
- goto out;
- }
-
key->both.offset |= FUT_OFF_INODE; /* inode-based key */
- key->shared.inode = inode;
+ key->shared.i_seq = get_inode_sequence_number(inode);
key->shared.pgoff = basepage_index(page);
rcu_read_unlock();
}
+ get_futex_key_refs(key); /* implies smp_mb(); (B) */
+
out:
put_page(page_head);
return err;
3.16.83-rc2 review patch. If anyone has any objections, please let me know.
------------------
From: Thomas Gleixner <[email protected]>
commit 8d67743653dce5a0e7aa500fcccb237cde7ad88e upstream.
The recent futex inode life time fix changed the ordering of the futex key
union struct members, but forgot to adjust the hash function accordingly,
As a result the hashing omits the leading 64bit and even hashes beyond the
futex key causing a bad hash distribution which led to a ~100% performance
regression.
Hand in the futex key pointer instead of a random struct member and make
the size calculation based of the struct offset.
Fixes: 8019ad13ef7f ("futex: Fix inode life-time issue")
Reported-by: Rong Chen <[email protected]>
Decoded-by: Linus Torvalds <[email protected]>
Signed-off-by: Thomas Gleixner <[email protected]>
Tested-by: Rong Chen <[email protected]>
Link: https://lkml.kernel.org/r/[email protected]
Signed-off-by: Ben Hutchings <[email protected]>
Cc: Jann Horn <[email protected]>
---
kernel/futex.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
--- a/kernel/futex.c
+++ b/kernel/futex.c
@@ -309,9 +309,9 @@ static inline int hb_waiters_pending(str
*/
static struct futex_hash_bucket *hash_futex(union futex_key *key)
{
- u32 hash = jhash2((u32*)&key->both.word,
- (sizeof(key->both.word)+sizeof(key->both.ptr))/4,
+ u32 hash = jhash2((u32 *)key, offsetof(typeof(*key), both.offset) / 4,
key->both.offset);
+
return &futex_queues[hash & (futex_hashsize - 1)];
}
On Fri, Apr 24, 2020 at 04:51:31PM +0100, Ben Hutchings wrote:
> 3.16.83-rc2 review patch. If anyone has any objections, please let me know.
>
> ------------------
>
> From: Peter Zijlstra <[email protected]>
>
> commit 8019ad13ef7f64be44d4f892af9c840179009254 upstream.
Please do not forget:
8d67743653dc ("futex: Unbreak futex hashing")
which fixes this fix.
On Fri, 2020-04-24 at 17:56 +0200, Peter Zijlstra wrote:
> On Fri, Apr 24, 2020 at 04:51:31PM +0100, Ben Hutchings wrote:
> > 3.16.83-rc2 review patch. If anyone has any objections, please let me know.
> >
> > ------------------
> >
> > From: Peter Zijlstra <[email protected]>
> >
> > commit 8019ad13ef7f64be44d4f892af9c840179009254 upstream.
>
> Please do not forget:
>
> 8d67743653dc ("futex: Unbreak futex hashing")
>
> which fixes this fix.
I didn't, Jann reminded me to include both of them.
Ben.
--
Ben Hutchings
Knowledge is power. France is bacon.
On Fri, Apr 24, 2020 at 04:13:22PM +0100, Ben Hutchings wrote:
> On Fri, 2020-04-24 at 15:52 +0200, Solar Designer wrote:
> > On Fri, Apr 24, 2020 at 12:07:15AM +0100, Ben Hutchings wrote:
> > > 3.16.83-rc1 review patch. If anyone has any objections, please let me know.
> >
> > I do. This patch is currently known-buggy, see this thread:
> >
> > https://www.openwall.com/lists/oss-security/2020/01/28/2
> >
> > It is (partially) fixed with these newer commits in 5.5 and 5.5.2:
> >
> > commit d0cb50185ae942b03c4327be322055d622dc79f6
> > Author: Al Viro <[email protected]>
> > Date: Sun Jan 26 09:29:34 2020 -0500
> >
> > do_last(): fetch directory ->i_mode and ->i_uid before it's too late
> >
> > may_create_in_sticky() call is done when we already have dropped the
> > reference to dir.
> >
> > Fixes: 30aba6656f61e (namei: allow restricted O_CREAT of FIFOs and regular files)
> > Signed-off-by: Al Viro <[email protected]>
> >
> > commit d76341d93dedbcf6ed5a08dfc8bce82d3e9a772b
> > Author: Al Viro <[email protected]>
> > Date: Sat Feb 1 16:26:45 2020 +0000
> >
> > vfs: fix do_last() regression
> >
> > commit 6404674acd596de41fd3ad5f267b4525494a891a upstream.
> [...]
> > At least inclusion of the above fixes is mandatory for any backports.
>
> I know, and those are the next 2 patches in the series.
Ah, then no objections from me.
> > Also, I think no one has fixed the logic of may_create_in_sticky() so
> > that it wouldn't unintentionally apply the "protection" when the file
> > is neither a FIFO nor a regular file (something I found and mentioned in
> > the oss-security posting above).
> [...]
> > I think the implementation of may_create_in_sticky() should be rewritten
> > such that it'd directly correspond to the textual description in the
> > comment above. As we've seen, trying to write the code "more optimally"
> > resulted in its logic actually being different from the description.
> >
> > Meanwhile, I think backporting known-so-buggy code is a bad idea.
>
> I can see that it's not quite right, but does it matter in practice?
> Directories and symlinks are handled separately; sockets can't be
> opened anyway; block and character devices wonn't normally appear in a
> sticky directory.
Clearly, it doesn't matter all that much in practice - I'm not aware of
anyone having complained about it causing issues on their system.
I think it primarily mattered as an attack vector on the issue fixed
with Al's commits above.
I think we should nevertheless fix the code to match its intent and the
comment, but meanwhile this isn't a blocker for the backport.
Alexander
On 4/24/20 8:47 AM, Ben Hutchings wrote:
> This is the start of the stable review cycle for the 3.16.83 release.
> There are 247 patches in this series, which will be posted as responses
> to this one. If anyone has any issues with these being applied, please
> let me know.
>
> Responses should be made by Tue Apr 28 18:00:00 UTC 2020.
> Anything received after that time might be too late.
>
For v3.16.82-247-gffbdbb4fe113:
Build results:
total: 135 pass: 135 fail: 0
Qemu test results:
total: 233 pass: 233 fail: 0
Guenter
On Fri, 2020-04-24 at 10:48 -0700, Guenter Roeck wrote:
> On 4/24/20 8:47 AM, Ben Hutchings wrote:
> > This is the start of the stable review cycle for the 3.16.83 release.
> > There are 247 patches in this series, which will be posted as responses
> > to this one. If anyone has any issues with these being applied, please
> > let me know.
> >
> > Responses should be made by Tue Apr 28 18:00:00 UTC 2020.
> > Anything received after that time might be too late.
> >
>
> For v3.16.82-247-gffbdbb4fe113:
>
> Build results:
> total: 135 pass: 135 fail: 0
> Qemu test results:
> total: 233 pass: 233 fail: 0
Great, thanks for testing again.
Ben.
--
Ben Hutchings
Knowledge is power. France is bacon.