bfs: add sanity check at bfs_fill_super()
Subsystems (14)
Sasha Levin
maintainerPATCH 1/26 bfs: add sanity check at bfs_fill_super()
From: Tetsuo Handa <[email protected]>
[ Upstream commit 9f2df09a33aa2c76ce6385d382693f98d7f2f07e ]
syzbot is reporting too large memory allocation at bfs_fill_super() [1]. Since file system image is corrupted such that bfs_sb->s_start == 0, bfs_fill_super() is trying to allocate 8MB of continuous memory. Fix this by adding a sanity check on bfs_sb->s_start, __GFP_NOWARN and printf().
[1] https://syzkaller.appspot.com/bug?id=16a87c236b951351374a84c8a32f40edbc034e96
--- fs/bfs/inode.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-)
fs/bfs/inode.c +6 -3
@@ -350,7 +350,8 @@ static int bfs_fill_super(struct super_block *s, void *data, int silent) s->s_magic =BFS_MAGIC ; -if (le32_to_cpu (bfs_sb->s_start) >le32_to_cpu (bfs_sb->s_end)) { +if (le32_to_cpu (bfs_sb->s_start) >le32_to_cpu (bfs_sb->s_end) || +le32_to_cpu (bfs_sb->s_start) <BFS_BSIZE ) {printf ("Superblock is corrupted\n" ); goto out1; }
@@ -359,9 +360,11 @@ static int bfs_fill_super(struct super_block *s, void *data, int silent)sizeof (struct bfs_inode ) +BFS_ROOT_INO -1 ; imap_len = (info->si_lasti /8 ) +1 ; - info->si_imap =kzalloc (imap_len,GFP_KERNEL ); -if (!info->si_imap) + info->si_imap =kzalloc (imap_len,GFP_KERNEL | __GFP_NOWARN); +if (!info->si_imap) { +printf ("Cannot allocate %u bytes\n" , imap_len); goto out1; + }for (i =0 ; i <BFS_ROOT_INO ; i++)set_bit (i, info->si_imap);
Signature · 1 line
2.17.1
Sasha Levin
maintainerPATCH 2/26 cifs: don't dereference smb_file_target before null check
From: Colin Ian King <[email protected]>
[ Upstream commit 8c6c9bed8773375b1d54ccca2911ec892c59db5d ]
There is a null check on dst_file->private data which suggests it can be potentially null. However, before this check, pointer smb_file_target is derived from dst_file->private and dereferenced in the call to tlink_tcon, hence there is a potential null pointer deference.
Fix this by assigning smb_file_target and target_tcon after the null pointer sanity checks.
Detected by CoverityScan, CID#1475302 ("Dereference before null check")
--- fs/cifs/cifsfs.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-)
fs/cifs/cifsfs.c +5 -2
@@ -933,8 +933,8 @@ static int cifs_clone_file_range(struct file *src_file, loff_t off,struct inode *src_inode =file_inode (src_file);struct inode *target_inode =file_inode (dst_file);struct cifsFileInfo *smb_file_src = src_file->private_data; -struct cifsFileInfo *smb_file_target = dst_file->private_data; -struct cifs_tcon *target_tcon =tlink_tcon (smb_file_target->tlink); +struct cifsFileInfo *smb_file_target; +struct cifs_tcon *target_tcon;unsigned int xid;int rc;
@@ -948,6 +948,9 @@ static int cifs_clone_file_range(struct file *src_file, loff_t off, goto out; } + smb_file_target = dst_file->private_data; + target_tcon =tlink_tcon (smb_file_target->tlink); +/* * Note: cifs case is easier than btrfs since server responsible for * checks for proper open modes and file type and if it wants
Signature · 1 line
2.17.1
Sasha Levin
maintainerPATCH 3/26 cifs: fix return value for cifs_listxattr
In reply to Sasha LevinFrom: Ronnie Sahlberg <[email protected]>
[ Upstream commit 0c5d6cb6643f48ad3775322f3ebab6c7eb67484e ]
If the application buffer was too small to fit all the names we would still count the number of bytes and return this for listxattr. This would then trigger a BUG in usercopy.c
Fix the computation of the size so that we return -ERANGE correctly when the buffer is too small.
This fixes the kernel BUG for xfstest generic/377
--- fs/cifs/smb2ops.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-)
fs/cifs/smb2ops.c +6 -5
@@ -441,6 +441,7 @@ move_smb2_ea_to_cifs(char *dst, size_t dst_size,int rc =0 ;unsigned int ea_name_len = ea_name ?strlen (ea_name) :0 ;char *name, *value; +size_t buf_size = dst_size;size_t name_len, value_len, user_name_len;while (src_size >0 ) {
@@ -476,9 +477,10 @@ move_smb2_ea_to_cifs(char *dst, size_t dst_size,/* 'user.' plus a terminating null */ user_name_len =5 +1 + name_len; - rc += user_name_len; - -if (dst_size >= user_name_len) { +if (buf_size ==0 ) { +/* skip copy - calc size only */ + rc += user_name_len; + }else if (dst_size >= user_name_len) { dst_size -= user_name_len;memcpy (dst,"user." ,5 ); dst +=5 ;
@@ -486,8 +488,7 @@ move_smb2_ea_to_cifs(char *dst, size_t dst_size, dst += name_len; *dst =0 ; ++dst; - }else if (dst_size ==0 ) { -/* skip copy - calc size only */ + rc += user_name_len; }else {/* stop before overrun buffer */ rc = -ERANGE ;
Signature · 1 line
2.17.1
Sasha Levin
maintainerPATCH 4/26 arm64: kprobe: make page to RO mode when allocate it
In reply to Sasha LevinFrom: Anders Roxell <[email protected]>
[ Upstream commit 966866892cf89d606544bca22d584ba2ef9ec208 ]
Commit 1404d6f13e47 ("arm64: dump: Add checking for writable and exectuable pages") has successfully identified code that leaves a page with W+X permissions.
[ 3.245140] arm64/mm: Found insecure W+X mapping at address (____ptrval____)/0xffff000000d90000 [ 3.245771] WARNING: CPU: 0 PID: 1 at ../arch/arm64/mm/dump.c:232 note_page+0x410/0x420 [ 3.246141] Modules linked in: [ 3.246653] CPU: 0 PID: 1 Comm: swapper/0 Not tainted 4.19.0-rc5-next-20180928-00001-ge70ae259b853-dirty #62 [ 3.247008] Hardware name: linux,dummy-virt (DT) [ 3.247347] pstate: 80000005 (Nzcv daif -PAN -UAO) [ 3.247623] pc : note_page+0x410/0x420 [ 3.247898] lr : note_page+0x410/0x420 [ 3.248071] sp : ffff00000804bcd0 [ 3.248254] x29: ffff00000804bcd0 x28: ffff000009274000 [ 3.248578] x27: ffff00000921a000 x26: ffff80007dfff000 [ 3.248845] x25: ffff0000093f5000 x24: ffff000009526f6a [ 3.249109] x23: 0000000000000004 x22: ffff000000d91000 [ 3.249396] x21: ffff000000d90000 x20: 0000000000000000 [ 3.249661] x19: ffff00000804bde8 x18: 0000000000000400 [ 3.249924] x17: 0000000000000000 x16: 0000000000000000 [ 3.250271] x15: ffffffffffffffff x14: 295f5f5f5f6c6176 [ 3.250594] x13: 7274705f5f5f5f28 x12: 2073736572646461 [ 3.250941] x11: 20746120676e6970 x10: 70616d20582b5720 [ 3.251252] x9 : 6572756365736e69 x8 : 3039643030303030 [ 3.251519] x7 : 306666666678302f x6 : ffff0000095467b2 [ 3.251802] x5 : 0000000000000000 x4 : 0000000000000000 [ 3.252060] x3 : 0000000000000000 x2 : ffffffffffffffff [ 3.252323] x1 : 4d151327adc50b00 x0 : 0000000000000000 [ 3.252664] Call trace: [ 3.252953] note_page+0x410/0x420 [ 3.253186] walk_pgd+0x12c/0x238 [ 3.253417] ptdump_check_wx+0x68/0xf8 [ 3.253637] mark_rodata_ro+0x68/0x98 [ 3.253847] kernel_init+0x38/0x160 [ 3.254103] ret_from_fork+0x10/0x18
kprobes allocates a writable executable page with module_alloc() in order to store executable code.
Reworked to that when allocate a page it sets mode RO. Inspired by commit 63fef14fc98a ("kprobes/x86: Make insn buffer always ROX and use text_poke()").
--- arch/arm64/kernel/probes/kprobes.c | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-)
arch/arm64/kernel/probes/kprobes.c +20 -7
@@ -23,7 +23,9 @@#include <linux/slab.h> #include <linux/stop_machine.h> #include <linux/sched/debug.h> +#include <linux/set_memory.h> #include <linux/stringify.h> +#include <linux/vmalloc.h> #include <asm/traps.h> #include <asm/ptrace.h> #include <asm/cacheflush.h>
@@ -42,10 +44,21 @@ DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk);static void __kprobes post_kprobe_handler (struct kprobe_ctlblk *,struct pt_regs *); +static int __kprobes patch_text (kprobe_opcode_t *addr,u32 opcode) +{ +void *addrs[1 ]; +u32 insns[1 ]; + + addrs[0 ] = addr; + insns[0 ] = opcode; + +return aarch64_insn_patch_text (addrs, insns,1 ); +} +static void __kprobes arch_prepare_ss_slot (struct kprobe *p) {/* prepare insn slot */ - p->ainsn.api.insn[0 ] =cpu_to_le32 (p->opcode); +patch_text (p->ainsn.api.insn, p->opcode); flush_icache_range((uintptr_t) (p->ainsn.api.insn), (uintptr_t) (p->ainsn.api.insn) +
@@ -118,15 +131,15 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p)return 0 ; } -static int __kprobes patch_text (kprobe_opcode_t *addr,u32 opcode) +void *alloc_insn_page (void ) { -void *addrs[1 ]; -u32 insns[1 ]; +void *page; - addrs[0 ] = (void *)addr; - insns[0 ] = (u32 )opcode; + page =vmalloc_exec (PAGE_SIZE ); +if (page) +set_memory_ro ((unsigned long )page,1 ); -return aarch64_insn_patch_text (addrs, insns,1 ); +return page; }/* arm kprobe: install breakpoint in text */
Signature · 1 line
2.17.1
Sasha Levin
maintainerPATCH 5/26 nvme-pci: fix conflicting p2p resource adds
In reply to Sasha LevinFrom: Keith Busch <[email protected]>
[ Upstream commit 9fe5c59ff6a1e5e26a39b75489a1420e7eaaf0b1 ]
The nvme pci driver had been adding its CMB resource to the P2P DMA subsystem everytime on on a controller reset. This results in the following warning:
------------[ cut here ]------------
nvme 0000:00:03.0: Conflicting mapping in same section
WARNING: CPU: 7 PID: 81 at kernel/memremap.c:155 devm_memremap_pages+0xa6/0x380
...
Call Trace:
pci_p2pdma_add_resource+0x153/0x370
nvme_reset_work+0x28c/0x17b1 [nvme]
? add_timer+0x107/0x1e0
? dequeue_entity+0x81/0x660
? dequeue_entity+0x3b0/0x660
? pick_next_task_fair+0xaf/0x610
? __switch_to+0xbc/0x410
process_one_work+0x1cf/0x350
worker_thread+0x215/0x3d0
? process_one_work+0x350/0x350
kthread+0x107/0x120
? kthread_park+0x80/0x80
ret_from_fork+0x1f/0x30
---[ end trace f7ea76ac6ee72727 ]---
nvme nvme0: failed to register the CMBThis patch fixes this by registering the CMB with P2P only once.
--- drivers/nvme/host/pci.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
drivers/nvme/host/pci.c +4 -1
@@ -1546,6 +1546,9 @@ static void __iomem *nvme_map_cmb(struct nvme_dev *dev)void __iomem *cmb;int bar; +if (dev->cmb_size) +return ; + dev->cmbsz =readl (dev->bar +NVME_REG_CMBSZ );if (!(NVME_CMB_SZ (dev->cmbsz)))return NULL ;
@@ -2032,7 +2035,6 @@ static void nvme_pci_disable(struct nvme_dev *dev) {struct pci_dev *pdev =to_pci_dev (dev->dev); -nvme_release_cmb (dev);pci_free_irq_vectors (pdev);if (pci_is_enabled (pdev)) {
@@ -2432,6 +2434,7 @@ static void nvme_remove(struct pci_dev *pdev)nvme_stop_ctrl (&dev->ctrl);nvme_remove_namespaces (&dev->ctrl);nvme_dev_disable (dev, true); +nvme_release_cmb (dev);nvme_free_host_mem (dev);nvme_dev_remove_admin (dev);nvme_free_queues (dev,0 );
Signature · 1 line
2.17.1
Sasha Levin
maintainerPATCH 6/26 ixgbe: fix MAC anti-spoofing filter after VFLR
In reply to Sasha LevinFrom: Radoslaw Tyl <[email protected]>
[ Upstream commit 6702185c1ffec3421181b5e24491e3fac920cb61 ]
This change resolves a driver bug where the driver is logging a message that says "Spoofed packets detected". This can occur on the PF (host) when a VF has VLAN+MACVLAN enabled and is re-started with a different MAC address.
MAC and VLAN anti-spoofing filters are to be enabled together.
--- drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c +3 -1
@@ -760,8 +760,10 @@ static inline void ixgbe_vf_reset_event(struct ixgbe_adapter *adapter, u32 vf)ixgbe_set_vmvir (adapter, vfinfo->pf_vlan, adapter->default_up, vf); -if (vfinfo->spoofchk_enabled) +if (vfinfo->spoofchk_enabled) { hw->mac.ops.set_vlan_anti_spoofing (hw, true, vf); + hw->mac.ops.set_mac_anti_spoofing (hw, true, vf); + } }/* reset multicast table array for vf */
Signature · 1 line
2.17.1
Sasha Levin
maintainerPATCH 7/26 mm: Fix warning in insert_pfn()
In reply to Sasha LevinFrom: Jan Kara <[email protected]>
[ Upstream commit f2c57d91b0d96aa13ccff4e3b178038f17b00658 ]
In DAX mode a write pagefault can race with write(2) in the following way:
CPU0 CPU1
write fault for mapped zero page (hole)dax_iomap_rw()
iomap_apply()
xfs_file_iomap_begin()
- allocates blocks
dax_iomap_actor()
invalidate_inode_pages2_range()
- invalidates radix tree entries in given range dax_iomap_pte_fault() grab_mapping_entry()
- no entry found, creates empty
...
xfs_file_iomap_begin()
- finds already allocated block
...
vmf_insert_mixed_mkwrite()
- WARNs and does nothing because there is still zero page mapped in PTE
unmap_mapping_pages()
This race results in WARN_ON from insert_pfn() and is occasionally triggered by fstest generic/344. Note that the race is otherwise harmless as before write(2) on CPU0 is finished, we will invalidate page tables properly and thus user of mmap will see modified data from write(2) from that point on. So just restrict the warning only to the case when the PFN in PTE is not zero page.
--- mm/memory.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-)
mm/memory.c +7 -2
@@ -1804,10 +1804,15 @@ static int insert_pfn(struct vm_area_struct *vma, unsigned long addr,* in may not match the PFN we have mapped if the * mapped PFN is a writeable COW page. In the mkwrite * case we are creating a writable PTE for a shared -* mapping and we expect the PFNs to match. +* mapping and we expect the PFNs to match. If they +* don't match, we are likely racing with block +* allocation and mapping invalidation so just skip the +* update. */ -if (WARN_ON_ONCE (pte_pfn (*pte) !=pfn_t_to_pfn (pfn))) +if (pte_pfn (*pte) !=pfn_t_to_pfn (pfn)) { +WARN_ON_ONCE (!is_zero_pfn (pte_pfn (*pte))); goto out_unlock; + } entry = *pte; goto out_mkwrite; }else
Signature · 1 line
2.17.1
Sasha Levin
maintainerPATCH 8/26 mm/memory_hotplug: make add_memory() take the device_hotplug_lock
In reply to Sasha LevinFrom: David Hildenbrand <[email protected]>
[ Upstream commit 8df1d0e4a265f25dc1e7e7624ccdbcb4a6630c89 ]
add_memory() currently does not take the device_hotplug_lock, however is aleady called under the lock from
arch/powerpc/platforms/pseries/hotplug-memory.c drivers/acpi/acpi_memhotplug.c
to synchronize against CPU hot-remove and similar.
In general, we should hold the device_hotplug_lock when adding memory to synchronize against online/offline request (e.g. from user space) - which already resulted in lock inversions due to device_lock() and mem_hotplug_lock - see 30467e0b3be ("mm, hotplug: fix concurrent memory hot-add deadlock"). add_memory()/add_memory_resource() will create memory block devices, so this really feels like the right thing to do.
Holding the device_hotplug_lock makes sure that a memory block device can really only be accessed (e.g. via .online/.state) from user space, once the memory has been fully added to the system.
The lock is not held yet in
drivers/xen/balloon.c arch/powerpc/platforms/powernv/memtrace.c drivers/s390/char/sclp_cmd.c drivers/hv/hv_balloon.c
So, let's either use the locked variants or take the lock.
Don't export add_memory_resource(), as it once was exported to be used by XEN, which is never built as a module. If somebody requires it, we also have to export a locked variant (as device_hotplug_lock is never exported).
--- .../platforms/pseries/hotplug-memory.c | 2 +- drivers/acpi/acpi_memhotplug.c | 2 +- drivers/base/memory.c | 9 ++++++-- drivers/xen/balloon.c | 3 +++ include/linux/memory_hotplug.h | 1 + mm/memory_hotplug.c | 22 ++++++++++++++++--- 6 files changed, 32 insertions(+), 7 deletions(-)
arch/powerpc/platforms/pseries/hotplug-memory.c +1 -1
@@ -784,7 +784,7 @@ static int dlpar_add_lmb(struct of_drconf_cell *lmb) nid =memory_add_physaddr_to_nid (lmb->base_addr);/* Add the memory */ - rc =add_memory (nid, lmb->base_addr, block_sz); + rc =__add_memory (nid, lmb->base_addr, block_sz);if (rc) {dlpar_remove_device_tree_lmb (lmb);return rc;
drivers/acpi/acpi_memhotplug.c +1 -1
@@ -228,7 +228,7 @@ static int acpi_memory_enable_device(struct acpi_memory_device *mem_device)if (node <0 ) node =memory_add_physaddr_to_nid (info->start_addr); - result =add_memory (node, info->start_addr, info->length); + result =__add_memory (node, info->start_addr, info->length);/* * If the memory block has been used by the kernel, add_memory()
drivers/base/memory.c +7 -2
@@ -517,15 +517,20 @@ memory_probe_store(struct device *dev, struct device_attribute *attr,if (phys_addr & ((pages_per_block <<PAGE_SHIFT ) -1 ))return -EINVAL ; + ret =lock_device_hotplug_sysfs (); +if (ret) + goto out; + nid =memory_add_physaddr_to_nid (phys_addr); - ret =add_memory (nid, phys_addr, -MIN_MEMORY_BLOCK_SIZE * sections_per_block); + ret =__add_memory (nid, phys_addr, +MIN_MEMORY_BLOCK_SIZE * sections_per_block);if (ret) goto out; ret = count; out: +unlock_device_hotplug ();return ret; }
drivers/xen/balloon.c +3 -0
@@ -401,7 +401,10 @@ static enum bp_state reserve_additional_memory(void)* callers drop the mutex before trying again. */ mutex_unlock (&balloon_mutex); +/* add_memory_resource() requires the device_hotplug lock */ +lock_device_hotplug (); rc =add_memory_resource (nid, resource, memhp_auto_online); +unlock_device_hotplug ();mutex_lock (&balloon_mutex);if (rc) {
include/linux/memory_hotplug.h +1 -0
@@ -316,6 +316,7 @@ static inline void remove_memory(int nid, u64 start, u64 size) {}extern int walk_memory_range (unsigned long start_pfn,unsigned long end_pfn,void *arg,int (*func)(struct memory_block *,void *)); +extern int __add_memory (int nid,u64 start,u64 size);extern int add_memory (int nid,u64 start,u64 size);extern int add_memory_resource (int nid,struct resource *resource,bool online);extern int arch_add_memory (int nid,u64 start,u64 size,bool want_memblock);
mm/memory_hotplug.c +19 -3
@@ -1109,7 +1109,12 @@ static int online_memory_block(struct memory_block *mem, void *arg)return device_online (&mem->dev); } -/* we are OK calling __meminit stuff here - we have CONFIG_MEMORY_HOTPLUG */ +/* +* NOTE: The caller must call lock_device_hotplug() to serialize hotplug +* and online/offline operations (triggered e.g. by sysfs). +* +* we are OK calling __meminit stuff here - we have CONFIG_MEMORY_HOTPLUG +*/ int __ref add_memory_resource (int nid,struct resource *res,bool online) {u64 start, size;
@@ -1202,9 +1207,9 @@ int __ref add_memory_resource(int nid, struct resource *res, bool online)mem_hotplug_done ();return ret; } -EXPORT_SYMBOL_GPL (add_memory_resource); -int __ref add_memory (int nid,u64 start,u64 size) +/* requires device_hotplug_lock, see add_memory_resource() */ +int __ref __add_memory (int nid,u64 start,u64 size) {struct resource *res;int ret;
@@ -1218,6 +1223,17 @@ int __ref add_memory(int nid, u64 start, u64 size)release_memory_resource (res);return ret; } + +int add_memory (int nid,u64 start,u64 size) +{ +int rc; + +lock_device_hotplug (); + rc =__add_memory (nid, start, size); +unlock_device_hotplug (); + +return rc; +}EXPORT_SYMBOL_GPL (add_memory);#ifdef CONFIG_MEMORY_HOTREMOVE
Signature · 1 line
2.17.1
Sasha Levin
maintainerPATCH 9/26 reiserfs: propagate errors from fill_with_dentries() properly
In reply to Sasha LevinFrom: Jann Horn <[email protected]>
[ Upstream commit b10298d56c9623f9b173f19959732d3184b35f4f ]
fill_with_dentries() failed to propagate errors up to reiserfs_for_each_xattr() properly. Plumb them through.
Note that reiserfs_for_each_xattr() is only used by reiserfs_delete_xattrs() and reiserfs_chown_xattrs(). The result of reiserfs_delete_xattrs() is discarded anyway, the only difference there is whether a warning is printed to dmesg. The result of reiserfs_chown_xattrs() does matter because it can block chowning of the file to which the xattrs belong; but either way, the resulting state can have misaligned ownership, so my patch doesn't improve things greatly.
Credit for making me look at this code goes to Al Viro, who pointed out that the ->actor calling convention is suboptimal and should be changed.
--- fs/reiserfs/xattr.c | 7 +++++++ 1 file changed, 7 insertions(+)
fs/reiserfs/xattr.c +7 -0
@@ -185,6 +185,7 @@ struct reiserfs_dentry_buf {struct dir_context ctx;struct dentry *xadir;int count; +int err;struct dentry *dentries[8 ]; };
@@ -207,6 +208,7 @@ fill_with_dentries(struct dir_context *ctx, const char *name, int namelen, dentry =lookup_one_len (name, dbuf->xadir, namelen);if (IS_ERR (dentry)) { + dbuf->err =PTR_ERR (dentry);return PTR_ERR (dentry); }else if (d_really_is_negative (dentry)) {/* A directory entry exists, but no file? */
@@ -215,6 +217,7 @@ fill_with_dentries(struct dir_context *ctx, const char *name, int namelen,"not found for file %pd.\n" , dentry, dbuf->xadir);dput (dentry); + dbuf->err = -EIO ;return -EIO ; }
@@ -262,6 +265,10 @@ static int reiserfs_for_each_xattr(struct inode *inode, err =reiserfs_readdir_inode (d_inode (dir), &buf.ctx);if (err)break ; +if (buf.err) { + err = buf.err; +break ; + }if (!buf.count)break ;for (i =0 ; !err && i < buf.count && buf.dentries[i]; i++) {
Signature · 1 line
2.17.1
Sasha Levin
maintainerPATCH 10/26 hfs: prevent btree data loss on root split
In reply to Sasha LevinFrom: Ernesto A. Fernández <[email protected]>
[ Upstream commit d057c036672f33d43a5f7344acbb08cf3a8a0c09 ]
This bug is triggered whenever hfs_brec_update_parent() needs to split the root node. The height of the btree is not increased, which leaves the new node orphaned and its records lost. It is not possible for this to happen on a valid hfs filesystem because the index nodes have fixed length keys.
For reasons I ignore, the hfs module does have support for a number of hfsplus features. A corrupt btree header may report variable length keys and trigger this bug, so it's better to fix it.
--- fs/hfs/brec.c | 4 ++++ 1 file changed, 4 insertions(+)
fs/hfs/brec.c +4 -0
@@ -425,6 +425,10 @@ static int hfs_brec_update_parent(struct hfs_find_data *fd)if (new_node) {__be32 cnid; +if (!new_node->parent) { +hfs_btree_inc_height (tree); + new_node->parent = tree->root; + } fd->bnode =hfs_bnode_find (tree, new_node->parent);/* create index key and entry */ hfs_bnode_read_key (new_node, fd->search_key,14 );
Signature · 1 line
2.17.1
Sasha Levin
maintainerPATCH 11/26 hfsplus: prevent btree data loss on root split
In reply to Sasha LevinFrom: Ernesto A. Fernández <[email protected]>
[ Upstream commit 0a3021d4f5295aa073c7bf5c5e4de60a2e292578 ]
Creating, renaming or deleting a file may cause catalog corruption and data loss. This bug is randomly triggered by xfstests generic/027, but here is a faster reproducer:
truncate -s 50M fs.iso
mkfs.hfsplus fs.iso
mount fs.iso /mnt
i=100
while [ $i -le 150 ]; do
touch /mnt/$i &>/dev/null
((++i))
done
i=100
while [ $i -le 150 ]; do
mv /mnt/$i /mnt/$(perl -e "print $i x82") &>/dev/null
((++i))
done
umount /mnt
fsck.hfsplus -n fs.isoThe bug is triggered whenever hfs_brec_update_parent() needs to split the root node. The height of the btree is not increased, which leaves the new node orphaned and its records lost.
--- fs/hfsplus/brec.c | 4 ++++ 1 file changed, 4 insertions(+)
fs/hfsplus/brec.c +4 -0
@@ -428,6 +428,10 @@ static int hfs_brec_update_parent(struct hfs_find_data *fd)if (new_node) {__be32 cnid; +if (!new_node->parent) { +hfs_btree_inc_height (tree); + new_node->parent = tree->root; + } fd->bnode =hfs_bnode_find (tree, new_node->parent);/* create index key and entry */ hfs_bnode_read_key (new_node, fd->search_key,14 );
Signature · 1 line
2.17.1
Sasha Levin
maintainerPATCH 12/26 um: Give start_idle_thread() a return code
In reply to Sasha LevinFrom: Richard Weinberger <[email protected]>
[ Upstream commit 7ff1e34bbdc15acab823b1ee4240e94623d50ee8 ]
Fixes:arch/um/os-Linux/skas/process.c:613:1: warning: control reaches end of non-void function [-Wreturn-type]
longjmp() never returns but gcc still warns that the end of the function can be reached.
Add a return code and debug aid to detect this impossible case.
--- arch/um/os-Linux/skas/process.c | 5 +++++ 1 file changed, 5 insertions(+)
arch/um/os-Linux/skas/process.c +5 -0
@@ -610,6 +610,11 @@ int start_idle_thread(void *stack, jmp_buf *switch_buf)fatal_sigsegv (); }longjmp (*switch_buf,1 ); + +/* unreachable */ +printk (UM_KERN_ERR "impossible long jump!" ); +fatal_sigsegv (); +return 0 ; }void initial_thread_cb_skas (void (*proc)(void *),void *arg)
Signature · 1 line
2.17.1
Sasha Levin
maintainerPATCH 13/26 drm/edid: Add 6 bpc quirk for BOE panel.
In reply to Sasha LevinFrom: "Lee, Shawn C" <[email protected]>
[ Upstream commit 922dceff8dc1fb4dafc9af78139ba65671408103 ]
BOE panel (ID: 0x0771) that reports "DFP 1.x compliant TMDS". But it's 6bpc panel only instead of 8 bpc.
Add panel ID to edid quirk list and set 6 bpc as default to work around this issue.
--- drivers/gpu/drm/drm_edid.c | 3 +++ 1 file changed, 3 insertions(+)
drivers/gpu/drm/drm_edid.c +3 -0
@@ -120,6 +120,9 @@ static const struct edid_quirk {/* SDC panel of Lenovo B50-80 reports 8 bpc, but is a 6 bpc panel */ { "SDC", 0x3652, EDID_QUIRK_FORCE_6BPC }, +/* BOE model 0x0771 reports 8 bpc, but is a 6 bpc panel */ + { "BOE", 0x0771, EDID_QUIRK_FORCE_6BPC }, +/* Belinea 10 15 55 */ { "MAX", 1516, EDID_QUIRK_PREFER_LARGE_60 }, { "MAX", 0x77e, EDID_QUIRK_PREFER_LARGE_60 },
Signature · 1 line
2.17.1
Sasha Levin
maintainerPATCH 14/26 platform/x86: intel_telemetry: report debugfs failure
In reply to Sasha LevinFrom: Rajneesh Bhardwaj <[email protected]>
[ Upstream commit 8d98b1ef368feeb7720b8b9b6f3bd93f2ad892bc ]
On some Goldmont based systems such as ASRock J3455M the BIOS may not enable the IPC1 device that provides access to the PMC and PUNIT. In such scenarios, the IOSS and PSS resources from the platform device can not be obtained and result in a invalid telemetry_plt_config which is an internal data structure that holds platform config and is maintained by the telemetry platform driver.
This is also applicable to the platforms where the BIOS supports IPC1 device under debug configurations but IPC1 is disabled by user or the policy.
This change allows user to know the reason for not seeing entries under /sys/kernel/debug/telemetry/* when there is no apparent failure at boot.
Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=198779
--- drivers/platform/x86/intel_telemetry_debugfs.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-)
drivers/platform/x86/intel_telemetry_debugfs.c +6 -2
@@ -968,12 +968,16 @@ static int __init telemetry_debugfs_init(void) debugfs_conf = (struct telemetry_debugfs_conf *)id->driver_data; err =telemetry_pltconfig_valid (); -if (err <0 ) +if (err <0 ) { +pr_info ("Invalid pltconfig, ensure IPC1 device is enabled in BIOS\n" );return -ENODEV ; + } err =telemetry_debugfs_check_evts (); -if (err <0 ) +if (err <0 ) { +pr_info ("telemetry_debugfs_check_evts failed\n" );return -EINVAL ; + }register_pm_notifier (&pm_notifier);
Signature · 1 line
2.17.1
Sasha Levin
maintainerPATCH 15/26 clk: fixed-rate: fix of_node_get-put imbalance
In reply to Sasha LevinFrom: Alan Tull <[email protected]>
[ Upstream commit 52091c256bdcad0d01e2852a63f19cd2cce6af96 ]
When the fixed rate clock is created by devicetree, of_clk_add_provider is called. Add a call to of_clk_del_provider in the remove function to balance it out.
--- drivers/clk/clk-fixed-rate.c | 1 + 1 file changed, 1 insertion(+)
drivers/clk/clk-fixed-rate.c +1 -0
@@ -200,6 +200,7 @@ static int of_fixed_clk_remove(struct platform_device *pdev) {struct clk *clk =platform_get_drvdata (pdev); +of_clk_del_provider (pdev->dev.of_node);clk_unregister_fixed_rate (clk);return 0 ;
Signature · 1 line
2.17.1
Sasha Levin
maintainerPATCH 16/26 perf symbols: Set PLT entry/header sizes properly on Sparc
In reply to Sasha LevinFrom: David Miller <[email protected]>
[ Upstream commit d6afa561e1471ccfdaf7191230c0c59a37e45a5b ]
Using the sh_entsize for both values isn't correct. It happens to be correct on x86...
For both 32-bit and 64-bit sparc, there are four PLT entries in the PLT section.
--- tools/perf/util/symbol-elf.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-)
tools/perf/util/symbol-elf.c +11 -1
@@ -338,7 +338,17 @@ int dso__synthesize_plt_symbols(struct dso *dso, struct symsrc *ss, struct map * plt_entry_size =16 ;break ; -default :/* FIXME: s390/alpha/mips/parisc/poperpc/sh/sparc/xtensa need to be checked */ +case EM_SPARC : + plt_header_size =48 ; + plt_entry_size =12 ; +break ; + +case EM_SPARCV9 : + plt_header_size =128 ; + plt_entry_size =32 ; +break ; + +default :/* FIXME: s390/alpha/mips/parisc/poperpc/sh/xtensa need to be checked */ plt_header_size = shdr_plt.sh_entsize; plt_entry_size = shdr_plt.sh_entsize;break ;
Signature · 1 line
2.17.1
Sasha Levin
maintainerPATCH 17/26 fs/exofs: fix potential memory leak in mount option parsing
In reply to Sasha LevinFrom: Chengguang Xu <[email protected]>
[ Upstream commit 515f1867addaba49c1c6ac73abfaffbc192c1db4 ]
There are some cases can cause memory leak when parsing option 'osdname'.
--- fs/exofs/super.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
fs/exofs/super.c +4 -1
@@ -100,6 +100,7 @@ static int parse_options(char *options, struct exofs_mountopt *opts) token =match_token (p, tokens, args);switch (token) {case Opt_name: +kfree (opts->dev_name); opts->dev_name =match_strdup (&args[0 ]);if (unlikely (!opts->dev_name)) {EXOFS_ERR ("Error allocating dev_name" );
@@ -863,8 +864,10 @@ static struct dentry *exofs_mount(struct file_system_type *type,int ret; ret =parse_options (data, &opts); -if (ret) +if (ret) { +kfree (opts.dev_name);return ERR_PTR (ret); + }if (!opts.dev_name) opts.dev_name = dev_name;
Signature · 1 line
2.17.1
Sasha Levin
maintainerPATCH 18/26 clk: samsung: exynos5420: Enable PERIS clocks for suspend
In reply to Sasha LevinFrom: Marek Szyprowski <[email protected]>
[ Upstream commit b33228029d842269e17bba591609e83ed422005d ]
Ensure that clocks for core SoC modules (including TZPC0..9 modules) are enabled for suspend/resume cycle. This fixes suspend/resume support on Exynos5422-based Odroid XU3/XU4 boards.
--- drivers/clk/samsung/clk-exynos5420.c | 1 + 1 file changed, 1 insertion(+)
drivers/clk/samsung/clk-exynos5420.c +1 -0
@@ -280,6 +280,7 @@ static const struct samsung_clk_reg_dump exynos5420_set_clksrc[] = { { .offset = GATE_BUS_TOP, .value = 0xffffffff, }, { .offset = GATE_BUS_DISP1, .value = 0xffffffff, }, { .offset = GATE_IP_PERIC, .value = 0xffffffff, }, + { .offset = GATE_IP_PERIS, .value = 0xffffffff, }, }; static int exynos5420_clk_suspend(void)
Signature · 1 line
2.17.1
Sasha Levin
maintainerPATCH 19/26 apparmor: Fix uninitialized value in aa_split_fqname
In reply to Sasha LevinFrom: Zubin Mithra <[email protected]>
[ Upstream commit 250f2da49cb8e582215a65c03f50e8ddf5cd119c ]
Syzkaller reported a OOB-read with the stacktrace below. This occurs inside __aa_lookupn_ns as n is not initialized. n is obtained from aa_splitn_fqname. In cases where name is invalid, aa_splitn_fqname returns without initializing ns_name and ns_len.
Fix this by always initializing ns_name and ns_len.
__dump_stack lib/dump_stack.c:77 [inline] dump_stack+0x1c4/0x2b4 lib/dump_stack.c:113 print_address_description.cold.8+0x9/0x1ff mm/kasan/report.c:256 kasan_report_error mm/kasan/report.c:354 [inline] kasan_report.cold.9+0x242/0x309 mm/kasan/report.c:412 __asan_report_load1_noabort+0x14/0x20 mm/kasan/report.c:430 memcmp+0xe3/0x160 lib/string.c:861 strnstr+0x4b/0x70 lib/string.c:934 __aa_lookupn_ns+0xc1/0x570 security/apparmor/policy_ns.c:209 aa_lookupn_ns+0x88/0x1e0 security/apparmor/policy_ns.c:240 aa_fqlookupn_profile+0x1b9/0x1010 security/apparmor/policy.c:468 fqlookupn_profile+0x80/0xc0 security/apparmor/label.c:1844 aa_label_strn_parse+0xa3a/0x1230 security/apparmor/label.c:1908 aa_label_parse+0x42/0x50 security/apparmor/label.c:1943 aa_change_profile+0x513/0x3510 security/apparmor/domain.c:1362 apparmor_setprocattr+0xaa4/0x1150 security/apparmor/lsm.c:658 security_setprocattr+0x66/0xc0 security/security.c:1298 proc_pid_attr_write+0x301/0x540 fs/proc/base.c:2555 __vfs_write+0x119/0x9f0 fs/read_write.c:485 vfs_write+0x1fc/0x560 fs/read_write.c:549 ksys_write+0x101/0x260 fs/read_write.c:598 __do_sys_write fs/read_write.c:610 [inline] __se_sys_write fs/read_write.c:607 [inline] __x64_sys_write+0x73/0xb0 fs/read_write.c:607 do_syscall_64+0x1b9/0x820 arch/x86/entry/common.c:290 entry_SYSCALL_64_after_hwframe+0x49/0xbe
--- security/apparmor/lib.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
security/apparmor/lib.c +4 -2
@@ -90,10 +90,12 @@ const char *aa_splitn_fqname(const char *fqname, size_t n, const char **ns_name,const char *end = fqname + n;const char *name =skipn_spaces (fqname, n); -if (!name) -return NULL ; *ns_name =NULL ; *ns_len =0 ; + +if (!name) +return NULL ; +if (name[0 ] ==':' ) {char *split =strnchr (&name[1 ], end - &name[1 ],':' ); *ns_name =skipn_spaces (&name[1 ], end - &name[1 ]);
Signature · 1 line
2.17.1
Sasha Levin
maintainerPATCH 20/26 x86/earlyprintk: Add a force option for pciserial device
In reply to Sasha LevinFrom: Feng Tang <[email protected]>
[ Upstream commit d2266bbfa9e3e32e3b642965088ca461bd24a94f ]
The "pciserial" earlyprintk variant helps much on many modern x86 platforms, but unfortunately there are still some platforms with PCI UART devices which have the wrong PCI class code. In that case, the current class code check does not allow for them to be used for logging.
Add a sub-option "force" which overrides the class code check and thus the use of such device can be enforced.
[ bp: massage formulations. ]
--- .../admin-guide/kernel-parameters.txt | 6 +++- arch/x86/kernel/early_printk.c | 29 ++++++++++++------- 2 files changed, 24 insertions(+), 11 deletions(-)
Documentation/admin-guide/kernel-parameters.txt +5 -1
@@ -1011,7 +1011,7 @@ earlyprintk=serial[,0x...[,baudrate]] earlyprintk=ttySn[,baudrate] earlyprintk=dbgp[debugController#] - earlyprintk=pciserial,bus:device.function[,baudrate] + earlyprintk=pciserial[,force],bus:device.function[,baudrate] earlyprintk=xdbc[xhciController#] earlyprintk is useful when the kernel crashes before
@@ -1043,6 +1043,10 @@ The sclp output can only be used on s390. + The optional "force" to "pciserial" enables use of a + PCI device even when its classcode is not of the + UART class. + edac_report= [HW,EDAC] Control how to report EDAC event Format: {"on" | "off" | "force"} on: enable EDAC to report H/W event. May be overridden
arch/x86/kernel/early_printk.c +19 -10
@@ -213,8 +213,9 @@ static unsigned int mem32_serial_in(unsigned long addr, int offset)* early_pci_serial_init() * * This function is invoked when the early_printk param starts with "pciserial" -* The rest of the param should be ",B:D.F,baud" where B, D & F describe the -* location of a PCI device that must be a UART device. +* The rest of the param should be "[force],B:D.F,baud", where B, D & F describe +* the location of a PCI device that must be a UART device. "force" is optional +* and overrides the use of an UART device with a wrong PCI class code. */ static __init void early_pci_serial_init (char *s) {
@@ -224,17 +225,23 @@ static __init void early_pci_serial_init(char *s)u32 classcode, bar0;u16 cmdreg;char *e; +int force =0 ; - -/* -* First, part the param to get the BDF values -*/ if (*s ==',' ) ++s;if (*s ==0 )return ; +/* Force the use of an UART device with wrong class code */ +if (!strncmp (s,"force," ,6 )) { + force =1 ; + s +=6 ; + } + +/* +* Part the param to get the BDF values +*/ bus = (u8 )simple_strtoul (s, &e,16 ); s = e;if (*s !=':' )
@@ -253,7 +260,7 @@ static __init void early_pci_serial_init(char *s) s++;/* -* Second, find the device from the BDF +* Find the device from the BDF */ cmdreg =read_pci_config (bus, slot, func,PCI_COMMAND ); classcode =read_pci_config (bus, slot, func,PCI_CLASS_REVISION );
@@ -264,8 +271,10 @@ static __init void early_pci_serial_init(char *s)*/ if (((classcode >>16 !=PCI_CLASS_COMMUNICATION_MODEM ) && (classcode >>16 !=PCI_CLASS_COMMUNICATION_SERIAL )) || - (((classcode >>8 ) &0xff ) !=0x02 ))/* 16550 I/F at BAR0 */ -return ; + (((classcode >>8 ) &0xff ) !=0x02 ))/* 16550 I/F at BAR0 */ { +if (!force) +return ; + }/* * Determine if it is IO or memory mapped
@@ -289,7 +298,7 @@ static __init void early_pci_serial_init(char *s) }/* -* Lastly, initialize the hardware +* Initialize the hardware */ if (*s) {if (strcmp (s,"nocfg" ) ==0 )
Signature · 1 line
2.17.1
Sasha Levin
maintainerPATCH 21/26 platform/x86: acerhdf: Add BIOS entry for Gateway LT31 v1.3307
In reply to Sasha LevinFrom: Paul Gortmaker <[email protected]>
[ Upstream commit 684238d79ad85c5e19a71bb5818e77e329912fbc ]
To fix:
acerhdf: unknown (unsupported) BIOS version Gateway /LT31 /v1.3307 , please report, aborting!
As can be seen in the context, the BIOS registers haven't changed in the previous versions, so the assumption is they won't have changed in this last update for this somewhat older platform either.
--- drivers/platform/x86/acerhdf.c | 1 + 1 file changed, 1 insertion(+)
drivers/platform/x86/acerhdf.c +1 -0
@@ -233,6 +233,7 @@ static const struct bios_settings bios_tbl[] = { {"Gateway", "LT31", "v1.3201", 0x55, 0x58, {0x9e, 0x00}, 0}, {"Gateway", "LT31", "v1.3302", 0x55, 0x58, {0x9e, 0x00}, 0}, {"Gateway", "LT31", "v1.3303t", 0x55, 0x58, {0x9e, 0x00}, 0}, + {"Gateway", "LT31", "v1.3307", 0x55, 0x58, {0x9e, 0x00}, 0},/* Packard Bell */ {"Packard Bell", "DOA150", "v0.3104", 0x55, 0x58, {0x21, 0x00}, 0}, {"Packard Bell", "DOA150", "v0.3105", 0x55, 0x58, {0x20, 0x00}, 0},
Signature · 1 line
2.17.1
Sasha Levin
maintainerPATCH 22/26 arm64: percpu: Initialize ret in the default case
In reply to Sasha LevinFrom: Nathan Chancellor <[email protected]>
[ Upstream commit b5bb425871186303e6936fa2581521bdd1964a58 ]
Clang warns that if the default case is taken, ret will be uninitialized.
./arch/arm64/include/asm/percpu.h:196:2: warning: variable 'ret' is used uninitialized whenever switch default is taken [-Wsometimes-uninitialized]
default:
^~~~~~~
./arch/arm64/include/asm/percpu.h:200:9: note: uninitialized use occurs
here
return ret;
^~~
./arch/arm64/include/asm/percpu.h:157:19: note: initialize the variable
'ret' to silence this warning
unsigned long ret, loop;
^
= 0This warning appears several times while building the erofs filesystem. While it's not strictly wrong, the BUILD_BUG will prevent this from becoming a true problem. Initialize ret to 0 in the default case right before the BUILD_BUG to silence all of these warnings.
--- arch/arm64/include/asm/percpu.h | 3 +++ 1 file changed, 3 insertions(+)
arch/arm64/include/asm/percpu.h +3 -0
@@ -93,6 +93,7 @@ static inline unsigned long __percpu_##op(void *ptr, \ : [val] "Ir" (val)); \break ; \default : \ + ret =0 ; \BUILD_BUG (); \ } \ \
@@ -122,6 +123,7 @@ static inline unsigned long __percpu_read(void *ptr, int size) ret =READ_ONCE (*(u64 *)ptr);break ;default : + ret =0 ;BUILD_BUG (); }
@@ -191,6 +193,7 @@ static inline unsigned long __percpu_xchg(void *ptr, unsigned long val, : [val] "r" (val));break ;default : + ret =0 ;BUILD_BUG (); }
Signature · 1 line
2.17.1
Sasha Levin
maintainerPATCH 23/26 mm/vmstat.c: assert that vmstat_text is in sync with stat_items_size
In reply to Sasha LevinFrom: Jann Horn <[email protected]>
[ Upstream commit f0ecf25a093fc0589f0a6bc4c1ea068bbb67d220 ]
Having two gigantic arrays that must manually be kept in sync, including ifdefs, isn't exactly robust. To make it easier to catch such issues in the future, add a BUILD_BUG_ON().
--- mm/vmstat.c | 2 ++ 1 file changed, 2 insertions(+)
mm/vmstat.c +2 -0
@@ -1630,6 +1630,8 @@ static void *vmstat_start(struct seq_file *m, loff_t *pos) stat_items_size +=sizeof (struct vm_event_state );#endif +BUILD_BUG_ON (stat_items_size != +ARRAY_SIZE (vmstat_text) *sizeof (unsigned long )); v =kmalloc (stat_items_size,GFP_KERNEL ); m->private = v;if (!v)
Signature · 1 line
2.17.1
Sasha Levin
maintainerPATCH 24/26 userfaultfd: allow get_mempolicy(MPOL_F_NODE|MPOL_F_ADDR) to trigger userfaults
In reply to Sasha LevinFrom: Andrea Arcangeli <[email protected]>
[ Upstream commit 3b9aadf7278d16d7bed4d5d808501065f70898d8 ]
get_mempolicy(MPOL_F_NODE|MPOL_F_ADDR) called a get_user_pages that would not be waiting for userfaults before failing and it would hit on a SIGBUS instead. Using get_user_pages_locked/unlocked instead will allow get_mempolicy to allow userfaults to resolve the fault and fill the hole, before grabbing the node id of the page.
If the user calls get_mempolicy() with MPOL_F_ADDR | MPOL_F_NODE for an address inside an area managed by uffd and there is no page at that address, the page allocation from within get_mempolicy() will fail because get_user_pages() does not allow for page fault retry required for uffd; the user will get SIGBUS.
With this patch, the page fault will be resolved by the uffd and the get_mempolicy() will continue normally.
Background:
Via code review, previously the syscall would have returned -EFAULT (vm_fault_to_errno), now it will block and wait for an userfault (if it's waken before the fault is resolved it'll still -EFAULT).
This way get_mempolicy will give a chance to an "unaware" app to be compliant with userfaults.
The reason this visible change is that becoming "userfault compliant" cannot regress anything: all other syscalls including read(2)/write(2) had to become "userfault compliant" long time ago (that's one of the things userfaultfd can do that PROT_NONE and trapping segfaults can't).
So this is just one more syscall that become "userfault compliant" like all other major ones already were.
This has been happening on virtio-bridge dpdk process which just called get_mempolicy on the guest space post live migration, but before the memory had a chance to be migrated to destination.
I didn't run an strace to be able to show the -EFAULT going away, but I've the confirmation of the below debug aid information (only visible with CONFIG_DEBUG_VM=y) going away with the patch:
[20116.371461] FAULT_FLAG_ALLOW_RETRY missing 0
[20116.371464] CPU: 1 PID: 13381 Comm: vhost-events Not tainted 4.17.12-200.fc28.x86_64 #1
[20116.371465] Hardware name: LENOVO 20FAS2BN0A/20FAS2BN0A, BIOS N1CET54W (1.22 ) 02/10/2017
[20116.371466] Call Trace:
[20116.371473] dump_stack+0x5c/0x80
[20116.371476] handle_userfault.cold.37+0x1b/0x22
[20116.371479] ? remove_wait_queue+0x20/0x60
[20116.371481] ? poll_freewait+0x45/0xa0
[20116.371483] ? do_sys_poll+0x31c/0x520
[20116.371485] ? radix_tree_lookup_slot+0x1e/0x50
[20116.371488] shmem_getpage_gfp+0xce7/0xe50
[20116.371491] ? page_add_file_rmap+0x1a/0x2c0
[20116.371493] shmem_fault+0x78/0x1e0
[20116.371495] ? filemap_map_pages+0x3a1/0x450
[20116.371498] __do_fault+0x1f/0xc0
[20116.371500] __handle_mm_fault+0xe2e/0x12f0
[20116.371502] handle_mm_fault+0xda/0x200
[20116.371504] __get_user_pages+0x238/0x790
[20116.371506] get_user_pages+0x3e/0x50
[20116.371510] kernel_get_mempolicy+0x40b/0x700
[20116.371512] ? vfs_write+0x170/0x1a0
[20116.371515] __x64_sys_get_mempolicy+0x21/0x30
[20116.371517] do_syscall_64+0x5b/0x160
[20116.371520] entry_SYSCALL_64_after_hwframe+0x44/0xa9The above harmless debug message (not a kernel crash, just a dump_stack()) is shown with CONFIG_DEBUG_VM=y to more quickly identify and improve kernel spots that may have to become "userfaultfd compliant" like this one (without having to run an strace and search for syscall misbehavior). Spots like the above are more closer to a kernel bug for the non-cooperative usages that Mike focuses on, than for for dpdk qemu-cooperative usages that reproduced it, but it's still nicer to get this fixed for dpdk too.
The part of the patch that caused me to think is only the implementation issue of mpol_get, but it looks like it should work safe no matter the kind of mempolicy structure that is (the default static policy also starts at 1 so it'll go to 2 and back to 1 without crashing everything at 0).
[[email protected]: changelog addition]
http://lkml.kernel.org/r/20180904073718.GA26916@rapoport-lnx
--- mm/mempolicy.c | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-)
mm/mempolicy.c +19 -5
@@ -821,16 +821,19 @@ static void get_policy_nodemask(struct mempolicy *p, nodemask_t *nodes) } } -static int lookup_node (unsigned long addr) +static int lookup_node (struct mm_struct *mm,unsigned long addr) {struct page *p;int err; - err =get_user_pages (addr &PAGE_MASK ,1 ,0 , &p,NULL ); +int locked =1 ; + err =get_user_pages_locked (addr &PAGE_MASK ,1 ,0 , &p, &locked);if (err >=0 ) { err =page_to_nid (p);put_page (p); } +if (locked) +up_read (&mm->mmap_sem);return err; }
@@ -841,7 +844,7 @@ static long do_get_mempolicy(int *policy, nodemask_t *nmask,int err;struct mm_struct *mm = current->mm;struct vm_area_struct *vma =NULL ; -struct mempolicy *pol = current->mempolicy; +struct mempolicy *pol = current->mempolicy, *pol_refcount =NULL ;if (flags & ~(unsigned long )(MPOL_F_NODE |MPOL_F_ADDR |MPOL_F_MEMS_ALLOWED ))
@@ -881,7 +884,16 @@ static long do_get_mempolicy(int *policy, nodemask_t *nmask,if (flags &MPOL_F_NODE ) {if (flags &MPOL_F_ADDR ) { - err =lookup_node (addr); +/* +* Take a refcount on the mpol, lookup_node() +* wil drop the mmap_sem, so after calling +* lookup_node() only "pol" remains valid, "vma" +* is stale. +*/ + pol_refcount = pol; + vma =NULL ; +mpol_get (pol); + err =lookup_node (mm, addr);if (err <0 ) goto out; *policy = err;
@@ -916,7 +928,9 @@ static long do_get_mempolicy(int *policy, nodemask_t *nmask, out:mpol_cond_put (pol);if (vma) -up_read (¤t->mm->mmap_sem); +up_read (&mm->mmap_sem); +if (pol_refcount) +mpol_put (pol_refcount);return err; }
Signature · 1 line
2.17.1
Sasha Levin
maintainerPATCH 25/26 mm: don't miss the last page because of round-off error
In reply to Sasha LevinFrom: Roman Gushchin <[email protected]>
[ Upstream commit 68600f623d69da428c6163275f97ca126e1a8ec5 ]
I've noticed, that dying memory cgroups are often pinned in memory by a single pagecache page. Even under moderate memory pressure they sometimes stayed in such state for a long time. That looked strange.
My investigation showed that the problem is caused by applying the LRU pressure balancing math:
scan = div64_u64(scan * fraction[lru], denominator),
where
denominator = fraction[anon] + fraction[file] + 1.
Because fraction[lru] is always less than denominator, if the initial scan size is 1, the result is always 0.
This means the last page is not scanned and has
no chances to be reclaimed.
Fix this by rounding up the result of the division.
In practice this change significantly improves the speed of dying cgroups reclaim.
--- include/linux/math64.h | 3 +++ mm/vmscan.c | 6 ++++-- 2 files changed, 7 insertions(+), 2 deletions(-)
include/linux/math64.h +3 -0
@@ -254,4 +254,7 @@ static inline u64 mul_u64_u32_div(u64 a, u32 mul, u32 divisor) }#endif /* mul_u64_u32_div */ +#define DIV64_U64_ROUND_UP (ll, d) \ + ({ u64 _tmp = (d); div64_u64((ll) + _tmp - 1, _tmp); }) +#endif /* _LINUX_MATH64_H */
mm/vmscan.c +4 -2
@@ -2367,9 +2367,11 @@ static void get_scan_count(struct lruvec *lruvec, struct mem_cgroup *memcg,/* * Scan types proportional to swappiness and * their relative recent reclaim efficiency. +* Make sure we don't miss the last page +* because of a round-off error. */ - scan =div64_u64 (scan * fraction[file], - denominator); + scan =DIV64_U64_ROUND_UP (scan * fraction[file], + denominator);break ;case SCAN_FILE :case SCAN_ANON :
Signature · 1 line
2.17.1
Sasha Levin
maintainerPATCH 26/26 mm: don't warn about large allocations for slab
In reply to Sasha LevinFrom: Dmitry Vyukov <[email protected]>
[ Upstream commit 61448479a9f2c954cde0cfe778cb6bec5d0a748d ]
Slub does not call kmalloc_slab() for sizes > KMALLOC_MAX_CACHE_SIZE, instead it falls back to kmalloc_large().
For slab KMALLOC_MAX_CACHE_SIZE == KMALLOC_MAX_SIZE and it calls kmalloc_slab() for all allocations relying on NULL return value for over-sized allocations.
This inconsistency leads to unwanted warnings from kmalloc_slab() for over-sized allocations for slab. Returning NULL for failed allocations is the expected behavior.
Make slub and slab code consistent by checking size > KMALLOC_MAX_CACHE_SIZE in slab before calling kmalloc_slab().
While we are here also fix the check in kmalloc_slab(). We should check against KMALLOC_MAX_CACHE_SIZE rather than KMALLOC_MAX_SIZE. It all kinda worked because for slab the constants are the same, and slub always checks the size against KMALLOC_MAX_CACHE_SIZE before kmalloc_slab(). But if we get there with size > KMALLOC_MAX_CACHE_SIZE anyhow bad things will happen. For example, in case of a newly introduced bug in slub code.
Also move the check in kmalloc_slab() from function entry to the size > 192 case. This partially compensates for the additional check in slab code and makes slub code a bit faster (at least theoretically).
Also drop __GFP_NOWARN in the warning check. This warning means a bug in slab code itself, user-passed flags have nothing to do with it.
Nothing of this affects slob.
--- mm/slab.c | 4 ++++ mm/slab_common.c | 12 ++++++------ 2 files changed, 10 insertions(+), 6 deletions(-)
mm/slab.c +4 -0
@@ -3670,6 +3670,8 @@ __do_kmalloc_node(size_t size, gfp_t flags, int node, unsigned long caller)struct kmem_cache *cachep;void *ret; +if (unlikely (size >KMALLOC_MAX_CACHE_SIZE )) +return NULL ; cachep =kmalloc_slab (size, flags);if (unlikely (ZERO_OR_NULL_PTR (cachep)))return cachep;
@@ -3705,6 +3707,8 @@ static __always_inline void *__do_kmalloc(size_t size, gfp_t flags,struct kmem_cache *cachep;void *ret; +if (unlikely (size >KMALLOC_MAX_CACHE_SIZE )) +return NULL ; cachep =kmalloc_slab (size, flags);if (unlikely (ZERO_OR_NULL_PTR (cachep)))return cachep;
mm/slab_common.c +6 -6
@@ -971,18 +971,18 @@ struct kmem_cache *kmalloc_slab(size_t size, gfp_t flags) {int index; -if (unlikely (size >KMALLOC_MAX_SIZE )) { -WARN_ON_ONCE (!(flags & __GFP_NOWARN)); -return NULL ; - } -if (size <=192 ) {if (!size)return ZERO_SIZE_PTR ; index = size_index[size_index_elem (size)]; - }else + }else { +if (unlikely (size >KMALLOC_MAX_CACHE_SIZE )) { +WARN_ON (1 ); +return NULL ; + } index =fls (size -1 ); + }#ifdef CONFIG_ZONE_DMA if (unlikely ((flags &GFP_DMA )))
Signature · 1 line
2.17.1