commit: 30df1463dcca885a96fc54a3cd8e82ad96d528e5 Author: Mike Pagano <mpagano <AT> gentoo <DOT> org> AuthorDate: Thu Sep 7 22:42:51 2017 +0000 Commit: Mike Pagano <mpagano <AT> gentoo <DOT> org> CommitDate: Thu Sep 7 22:42:51 2017 +0000 URL: https://gitweb.gentoo.org/proj/linux-patches.git/commit/?id=30df1463
Linux patch 4.9.48 0000_README | 4 + 1047_linux-4.9.48.patch | 476 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 480 insertions(+) diff --git a/0000_README b/0000_README index 9258add..da58adf 100644 --- a/0000_README +++ b/0000_README @@ -231,6 +231,10 @@ Patch: 1046_linux-4.9.47.patch From: http://www.kernel.org Desc: Linux 4.9.47 +Patch: 1047_linux-4.9.48.patch +From: http://www.kernel.org +Desc: Linux 4.9.48 + Patch: 1500_XATTR_USER_PREFIX.patch From: https://bugs.gentoo.org/show_bug.cgi?id=470644 Desc: Support for namespace user.pax.* on tmpfs. diff --git a/1047_linux-4.9.48.patch b/1047_linux-4.9.48.patch new file mode 100644 index 0000000..6975a16 --- /dev/null +++ b/1047_linux-4.9.48.patch @@ -0,0 +1,476 @@ +diff --git a/Makefile b/Makefile +index a0abbfc15a49..cfa188b427b1 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,6 +1,6 @@ + VERSION = 4 + PATCHLEVEL = 9 +-SUBLEVEL = 47 ++SUBLEVEL = 48 + EXTRAVERSION = + NAME = Roaring Lionus + +diff --git a/arch/alpha/include/asm/types.h b/arch/alpha/include/asm/types.h +index 4cb4b6d3452c..0bc66e1d3a7e 100644 +--- a/arch/alpha/include/asm/types.h ++++ b/arch/alpha/include/asm/types.h +@@ -1,6 +1,6 @@ + #ifndef _ALPHA_TYPES_H + #define _ALPHA_TYPES_H + +-#include <asm-generic/int-ll64.h> ++#include <uapi/asm/types.h> + + #endif /* _ALPHA_TYPES_H */ +diff --git a/arch/alpha/include/uapi/asm/types.h b/arch/alpha/include/uapi/asm/types.h +index 9fd3cd459777..8d1024d7be05 100644 +--- a/arch/alpha/include/uapi/asm/types.h ++++ b/arch/alpha/include/uapi/asm/types.h +@@ -9,8 +9,18 @@ + * need to be careful to avoid a name clashes. + */ + +-#ifndef __KERNEL__ ++/* ++ * This is here because we used to use l64 for alpha ++ * and we don't want to impact user mode with our change to ll64 ++ * in the kernel. ++ * ++ * However, some user programs are fine with this. They can ++ * flag __SANE_USERSPACE_TYPES__ to get int-ll64.h here. ++ */ ++#if !defined(__SANE_USERSPACE_TYPES__) && !defined(__KERNEL__) + #include <asm-generic/int-l64.h> ++#else ++#include <asm-generic/int-ll64.h> + #endif + + #endif /* _UAPI_ALPHA_TYPES_H */ +diff --git a/arch/arm/kvm/mmu.c b/arch/arm/kvm/mmu.c +index 0c060c5e844a..2206e0e00934 100644 +--- a/arch/arm/kvm/mmu.c ++++ b/arch/arm/kvm/mmu.c +@@ -837,7 +837,7 @@ void kvm_free_stage2_pgd(struct kvm *kvm) + spin_lock(&kvm->mmu_lock); + if (kvm->arch.pgd) { + unmap_stage2_range(kvm, 0, KVM_PHYS_SIZE); +- pgd = kvm->arch.pgd; ++ pgd = READ_ONCE(kvm->arch.pgd); + kvm->arch.pgd = NULL; + } + spin_unlock(&kvm->mmu_lock); +diff --git a/crypto/algif_skcipher.c b/crypto/algif_skcipher.c +index 28556fce4267..45af0fe00f33 100644 +--- a/crypto/algif_skcipher.c ++++ b/crypto/algif_skcipher.c +@@ -86,8 +86,13 @@ static void skcipher_free_async_sgls(struct skcipher_async_req *sreq) + } + sgl = sreq->tsg; + n = sg_nents(sgl); +- for_each_sg(sgl, sg, n, i) +- put_page(sg_page(sg)); ++ for_each_sg(sgl, sg, n, i) { ++ struct page *page = sg_page(sg); ++ ++ /* some SGs may not have a page mapped */ ++ if (page && page_ref_count(page)) ++ put_page(page); ++ } + + kfree(sreq->tsg); + } +diff --git a/drivers/gpu/drm/ttm/ttm_page_alloc.c b/drivers/gpu/drm/ttm/ttm_page_alloc.c +index a37de5db5731..ddd6badd0eee 100644 +--- a/drivers/gpu/drm/ttm/ttm_page_alloc.c ++++ b/drivers/gpu/drm/ttm/ttm_page_alloc.c +@@ -612,7 +612,7 @@ static void ttm_page_pool_fill_locked(struct ttm_page_pool *pool, + } else { + pr_err("Failed to fill pool (%p)\n", pool); + /* If we have any pages left put them to the pool. */ +- list_for_each_entry(p, &pool->list, lru) { ++ list_for_each_entry(p, &new_pages, lru) { + ++cpages; + } + list_splice(&new_pages, &pool->list); +diff --git a/drivers/i2c/busses/i2c-ismt.c b/drivers/i2c/busses/i2c-ismt.c +index f573448d2132..8477292e92c8 100644 +--- a/drivers/i2c/busses/i2c-ismt.c ++++ b/drivers/i2c/busses/i2c-ismt.c +@@ -341,8 +341,10 @@ static int ismt_process_desc(const struct ismt_desc *desc, + break; + case I2C_SMBUS_BLOCK_DATA: + case I2C_SMBUS_I2C_BLOCK_DATA: +- memcpy(&data->block[1], dma_buffer, desc->rxbytes); +- data->block[0] = desc->rxbytes; ++ if (desc->rxbytes != dma_buffer[0] + 1) ++ return -EMSGSIZE; ++ ++ memcpy(data->block, dma_buffer, desc->rxbytes); + break; + } + return 0; +diff --git a/drivers/irqchip/irq-mips-gic.c b/drivers/irqchip/irq-mips-gic.c +index c0178a122940..d74374f25392 100644 +--- a/drivers/irqchip/irq-mips-gic.c ++++ b/drivers/irqchip/irq-mips-gic.c +@@ -1115,8 +1115,11 @@ static int __init gic_of_init(struct device_node *node, + gic_len = resource_size(&res); + } + +- if (mips_cm_present()) ++ if (mips_cm_present()) { + write_gcr_gic_base(gic_base | CM_GCR_GIC_BASE_GICEN_MSK); ++ /* Ensure GIC region is enabled before trying to access it */ ++ __sync(); ++ } + gic_present = true; + + __gic_init(gic_base, gic_len, cpu_vec, 0, node); +diff --git a/drivers/net/wireless/ti/wl1251/main.c b/drivers/net/wireless/ti/wl1251/main.c +index bbf7604889b7..1c539c83e8cf 100644 +--- a/drivers/net/wireless/ti/wl1251/main.c ++++ b/drivers/net/wireless/ti/wl1251/main.c +@@ -1571,6 +1571,7 @@ struct ieee80211_hw *wl1251_alloc_hw(void) + + wl->state = WL1251_STATE_OFF; + mutex_init(&wl->mutex); ++ spin_lock_init(&wl->wl_lock); + + wl->tx_mgmt_frm_rate = DEFAULT_HW_GEN_TX_RATE; + wl->tx_mgmt_frm_mod = DEFAULT_HW_GEN_MODULATION_TYPE; +diff --git a/fs/ceph/addr.c b/fs/ceph/addr.c +index 900ffafb85ca..7b79a54a2789 100644 +--- a/fs/ceph/addr.c ++++ b/fs/ceph/addr.c +@@ -188,7 +188,7 @@ static int ceph_releasepage(struct page *page, gfp_t g) + /* + * read a single page, without unlocking it. + */ +-static int readpage_nounlock(struct file *filp, struct page *page) ++static int ceph_do_readpage(struct file *filp, struct page *page) + { + struct inode *inode = file_inode(filp); + struct ceph_inode_info *ci = ceph_inode(inode); +@@ -218,7 +218,7 @@ static int readpage_nounlock(struct file *filp, struct page *page) + + err = ceph_readpage_from_fscache(inode, page); + if (err == 0) +- goto out; ++ return -EINPROGRESS; + + dout("readpage inode %p file %p page %p index %lu\n", + inode, filp, page, page->index); +@@ -248,8 +248,11 @@ static int readpage_nounlock(struct file *filp, struct page *page) + + static int ceph_readpage(struct file *filp, struct page *page) + { +- int r = readpage_nounlock(filp, page); +- unlock_page(page); ++ int r = ceph_do_readpage(filp, page); ++ if (r != -EINPROGRESS) ++ unlock_page(page); ++ else ++ r = 0; + return r; + } + +@@ -1235,7 +1238,7 @@ static int ceph_update_writeable_page(struct file *file, + goto retry_locked; + r = writepage_nounlock(page, NULL); + if (r < 0) +- goto fail_nosnap; ++ goto fail_unlock; + goto retry_locked; + } + +@@ -1263,11 +1266,14 @@ static int ceph_update_writeable_page(struct file *file, + } + + /* we need to read it. */ +- r = readpage_nounlock(file, page); +- if (r < 0) +- goto fail_nosnap; ++ r = ceph_do_readpage(file, page); ++ if (r < 0) { ++ if (r == -EINPROGRESS) ++ return -EAGAIN; ++ goto fail_unlock; ++ } + goto retry_locked; +-fail_nosnap: ++fail_unlock: + unlock_page(page); + return r; + } +diff --git a/fs/ceph/cache.c b/fs/ceph/cache.c +index 5bc5d37b1217..a2d7997afd94 100644 +--- a/fs/ceph/cache.c ++++ b/fs/ceph/cache.c +@@ -240,13 +240,7 @@ void ceph_fscache_file_set_cookie(struct inode *inode, struct file *filp) + } + } + +-static void ceph_vfs_readpage_complete(struct page *page, void *data, int error) +-{ +- if (!error) +- SetPageUptodate(page); +-} +- +-static void ceph_vfs_readpage_complete_unlock(struct page *page, void *data, int error) ++static void ceph_readpage_from_fscache_complete(struct page *page, void *data, int error) + { + if (!error) + SetPageUptodate(page); +@@ -274,7 +268,7 @@ int ceph_readpage_from_fscache(struct inode *inode, struct page *page) + return -ENOBUFS; + + ret = fscache_read_or_alloc_page(ci->fscache, page, +- ceph_vfs_readpage_complete, NULL, ++ ceph_readpage_from_fscache_complete, NULL, + GFP_KERNEL); + + switch (ret) { +@@ -303,7 +297,7 @@ int ceph_readpages_from_fscache(struct inode *inode, + return -ENOBUFS; + + ret = fscache_read_or_alloc_pages(ci->fscache, mapping, pages, nr_pages, +- ceph_vfs_readpage_complete_unlock, ++ ceph_readpage_from_fscache_complete, + NULL, mapping_gfp_mask(mapping)); + + switch (ret) { +diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c +index 581712534c93..dd3e236d7a2b 100644 +--- a/fs/cifs/dir.c ++++ b/fs/cifs/dir.c +@@ -194,7 +194,7 @@ check_name(struct dentry *direntry, struct cifs_tcon *tcon) + int i; + + if (unlikely(direntry->d_name.len > +- tcon->fsAttrInfo.MaxPathNameComponentLength)) ++ le32_to_cpu(tcon->fsAttrInfo.MaxPathNameComponentLength))) + return -ENAMETOOLONG; + + if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS)) { +diff --git a/fs/cifs/smb2pdu.h b/fs/cifs/smb2pdu.h +index dc0d141f33e2..1e1449ad00e8 100644 +--- a/fs/cifs/smb2pdu.h ++++ b/fs/cifs/smb2pdu.h +@@ -84,8 +84,8 @@ + + #define NUMBER_OF_SMB2_COMMANDS 0x0013 + +-/* BB FIXME - analyze following length BB */ +-#define MAX_SMB2_HDR_SIZE 0x78 /* 4 len + 64 hdr + (2*24 wct) + 2 bct + 2 pad */ ++/* 4 len + 52 transform hdr + 64 hdr + 56 create rsp */ ++#define MAX_SMB2_HDR_SIZE 0x00b0 + + #define SMB2_PROTO_NUMBER cpu_to_le32(0x424d53fe) + #define SMB2_TRANSFORM_PROTO_NUM cpu_to_le32(0x424d53fd) +diff --git a/fs/eventpoll.c b/fs/eventpoll.c +index 10db91218933..3cbc30413add 100644 +--- a/fs/eventpoll.c ++++ b/fs/eventpoll.c +@@ -523,8 +523,13 @@ static void ep_remove_wait_queue(struct eppoll_entry *pwq) + wait_queue_head_t *whead; + + rcu_read_lock(); +- /* If it is cleared by POLLFREE, it should be rcu-safe */ +- whead = rcu_dereference(pwq->whead); ++ /* ++ * If it is cleared by POLLFREE, it should be rcu-safe. ++ * If we read NULL we need a barrier paired with ++ * smp_store_release() in ep_poll_callback(), otherwise ++ * we rely on whead->lock. ++ */ ++ whead = smp_load_acquire(&pwq->whead); + if (whead) + remove_wait_queue(whead, &pwq->wait); + rcu_read_unlock(); +@@ -1009,17 +1014,6 @@ static int ep_poll_callback(wait_queue_t *wait, unsigned mode, int sync, void *k + struct eventpoll *ep = epi->ep; + int ewake = 0; + +- if ((unsigned long)key & POLLFREE) { +- ep_pwq_from_wait(wait)->whead = NULL; +- /* +- * whead = NULL above can race with ep_remove_wait_queue() +- * which can do another remove_wait_queue() after us, so we +- * can't use __remove_wait_queue(). whead->lock is held by +- * the caller. +- */ +- list_del_init(&wait->task_list); +- } +- + spin_lock_irqsave(&ep->lock, flags); + + /* +@@ -1101,10 +1095,26 @@ static int ep_poll_callback(wait_queue_t *wait, unsigned mode, int sync, void *k + if (pwake) + ep_poll_safewake(&ep->poll_wait); + +- if (epi->event.events & EPOLLEXCLUSIVE) +- return ewake; ++ if (!(epi->event.events & EPOLLEXCLUSIVE)) ++ ewake = 1; ++ ++ if ((unsigned long)key & POLLFREE) { ++ /* ++ * If we race with ep_remove_wait_queue() it can miss ++ * ->whead = NULL and do another remove_wait_queue() after ++ * us, so we can't use __remove_wait_queue(). ++ */ ++ list_del_init(&wait->task_list); ++ /* ++ * ->whead != NULL protects us from the race with ep_free() ++ * or ep_remove(), ep_remove_wait_queue() takes whead->lock ++ * held by the caller. Once we nullify it, nothing protects ++ * ep/epi or even wait. ++ */ ++ smp_store_release(&ep_pwq_from_wait(wait)->whead, NULL); ++ } + +- return 1; ++ return ewake; + } + + /* +diff --git a/include/asm-generic/topology.h b/include/asm-generic/topology.h +index fc824e2828f3..5d2add1a6c96 100644 +--- a/include/asm-generic/topology.h ++++ b/include/asm-generic/topology.h +@@ -48,7 +48,11 @@ + #define parent_node(node) ((void)(node),0) + #endif + #ifndef cpumask_of_node +-#define cpumask_of_node(node) ((void)node, cpu_online_mask) ++ #ifdef CONFIG_NEED_MULTIPLE_NODES ++ #define cpumask_of_node(node) ((node) == 0 ? cpu_online_mask : cpu_none_mask) ++ #else ++ #define cpumask_of_node(node) ((void)node, cpu_online_mask) ++ #endif + #endif + #ifndef pcibus_to_node + #define pcibus_to_node(bus) ((void)(bus), -1) +diff --git a/kernel/cpuset.c b/kernel/cpuset.c +index 247afb108343..03a3a6e94eb9 100644 +--- a/kernel/cpuset.c ++++ b/kernel/cpuset.c +@@ -1905,6 +1905,7 @@ static struct cftype files[] = { + { + .name = "memory_pressure", + .read_u64 = cpuset_read_u64, ++ .private = FILE_MEMORY_PRESSURE, + }, + + { +diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c +index f9ec9add2164..a1de021dccba 100644 +--- a/kernel/events/uprobes.c ++++ b/kernel/events/uprobes.c +@@ -1254,8 +1254,6 @@ void uprobe_end_dup_mmap(void) + + void uprobe_dup_mmap(struct mm_struct *oldmm, struct mm_struct *newmm) + { +- newmm->uprobes_state.xol_area = NULL; +- + if (test_bit(MMF_HAS_UPROBES, &oldmm->flags)) { + set_bit(MMF_HAS_UPROBES, &newmm->flags); + /* unconditionally, dup_mmap() skips VM_DONTCOPY vmas */ +diff --git a/kernel/fork.c b/kernel/fork.c +index 50bf262cc427..9321b1ad3335 100644 +--- a/kernel/fork.c ++++ b/kernel/fork.c +@@ -745,6 +745,13 @@ static void mm_init_owner(struct mm_struct *mm, struct task_struct *p) + #endif + } + ++static void mm_init_uprobes_state(struct mm_struct *mm) ++{ ++#ifdef CONFIG_UPROBES ++ mm->uprobes_state.xol_area = NULL; ++#endif ++} ++ + static struct mm_struct *mm_init(struct mm_struct *mm, struct task_struct *p, + struct user_namespace *user_ns) + { +@@ -772,6 +779,7 @@ static struct mm_struct *mm_init(struct mm_struct *mm, struct task_struct *p, + #if defined(CONFIG_TRANSPARENT_HUGEPAGE) && !USE_SPLIT_PMD_PTLOCKS + mm->pmd_huge_pte = NULL; + #endif ++ mm_init_uprobes_state(mm); + + if (current->mm) { + mm->flags = current->mm->flags & MMF_INIT_MASK; +diff --git a/lib/mpi/mpicoder.c b/lib/mpi/mpicoder.c +index 5a0f75a3bf01..eead4b339466 100644 +--- a/lib/mpi/mpicoder.c ++++ b/lib/mpi/mpicoder.c +@@ -364,11 +364,11 @@ MPI mpi_read_raw_from_sgl(struct scatterlist *sgl, unsigned int nbytes) + } + + miter.consumed = lzeros; +- sg_miter_stop(&miter); + + nbytes -= lzeros; + nbits = nbytes * 8; + if (nbits > MAX_EXTERN_MPI_BITS) { ++ sg_miter_stop(&miter); + pr_info("MPI: mpi too large (%u bits)\n", nbits); + return NULL; + } +@@ -376,6 +376,8 @@ MPI mpi_read_raw_from_sgl(struct scatterlist *sgl, unsigned int nbytes) + if (nbytes > 0) + nbits -= count_leading_zeros(*buff) - (BITS_PER_LONG - 8); + ++ sg_miter_stop(&miter); ++ + nlimbs = DIV_ROUND_UP(nbytes, BYTES_PER_MPI_LIMB); + val = mpi_alloc(nlimbs); + if (!val) +diff --git a/mm/madvise.c b/mm/madvise.c +index 63a12162f4c6..55f30ec32e5b 100644 +--- a/mm/madvise.c ++++ b/mm/madvise.c +@@ -533,6 +533,8 @@ static long madvise_remove(struct vm_area_struct *vma, + static int madvise_hwpoison(int bhv, unsigned long start, unsigned long end) + { + struct page *p; ++ struct zone *zone; ++ + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + for (; start < end; start += PAGE_SIZE << +@@ -561,6 +563,11 @@ static int madvise_hwpoison(int bhv, unsigned long start, unsigned long end) + if (ret) + return ret; + } ++ ++ /* Ensure that all poisoned pages are removed from per-cpu lists */ ++ for_each_populated_zone(zone) ++ drain_all_pages(zone); ++ + return 0; + } + #endif +diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c +index e26b515f7794..8ce5711ea21b 100644 +--- a/net/xfrm/xfrm_policy.c ++++ b/net/xfrm/xfrm_policy.c +@@ -3308,9 +3308,15 @@ int xfrm_migrate(const struct xfrm_selector *sel, u8 dir, u8 type, + struct xfrm_state *x_new[XFRM_MAX_DEPTH]; + struct xfrm_migrate *mp; + ++ /* Stage 0 - sanity checks */ + if ((err = xfrm_migrate_check(m, num_migrate)) < 0) + goto out; + ++ if (dir >= XFRM_POLICY_MAX) { ++ err = -EINVAL; ++ goto out; ++ } ++ + /* Stage 1 - find policy */ + if ((pol = xfrm_migrate_policy_find(sel, dir, type, net)) == NULL) { + err = -ENOENT;