summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Pagano <mpagano@gentoo.org>2017-09-07 18:42:51 -0400
committerMike Pagano <mpagano@gentoo.org>2017-09-07 18:42:51 -0400
commit30df1463dcca885a96fc54a3cd8e82ad96d528e5 (patch)
tree9e65537b216b090f5c37c2e15dcc0b89d309ba05
parentLinux patch 4.9.47 (diff)
downloadlinux-patches-30df1463dcca885a96fc54a3cd8e82ad96d528e5.tar.gz
linux-patches-30df1463dcca885a96fc54a3cd8e82ad96d528e5.tar.bz2
linux-patches-30df1463dcca885a96fc54a3cd8e82ad96d528e5.zip
Linux patch 4.9.484.9-49
-rw-r--r--0000_README4
-rw-r--r--1047_linux-4.9.48.patch476
2 files changed, 480 insertions, 0 deletions
diff --git a/0000_README b/0000_README
index 9258add9..da58adfe 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 00000000..6975a161
--- /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;