Merge tag 'v4.4.3'
authorHuang, Tao <huangtao@rock-chips.com>
Thu, 3 Mar 2016 11:46:53 +0000 (19:46 +0800)
committerHuang, Tao <huangtao@rock-chips.com>
Thu, 3 Mar 2016 11:46:53 +0000 (19:46 +0800)
This is the 4.4.3 stable release

1  2 
Makefile
arch/arm64/mm/dma-mapping.c
fs/proc/base.c
fs/proc/task_mmu.c
kernel/sys.c
mm/mlock.c
mm/mmap.c
security/commoncap.c

diff --combined Makefile
index dac1e9a647c745947914810d51bcdbaf05c53e8a,802be10c40c5ac7a0952da9b2c04411c219a18d9..83fade10cc5f26c1fc517691cb957aee4c0706c4
+++ b/Makefile
@@@ -1,6 -1,6 +1,6 @@@
  VERSION = 4
  PATCHLEVEL = 4
- SUBLEVEL = 2
+ SUBLEVEL = 3
  EXTRAVERSION =
  NAME = Blurry Fish Butt
  
@@@ -10,8 -10,6 +10,8 @@@
  # Comments in this file are targeted only to the developer, do not
  # expect to learn how to build the kernel reading this file.
  
 +SUBLEVEL = 0
 +
  # o Do not use make's built-in rules and variables
  #   (this increases performance and avoids hard-to-debug behaviour);
  # o Look for make include files relative to root of kernel src
@@@ -250,13 -248,7 +250,13 @@@ SUBARCH := $(shell uname -m | sed -e s/
  # "make" in the configured kernel build directory always uses that.
  # Default value for CROSS_COMPILE is not to prefix executables
  # Note: Some architectures assign CROSS_COMPILE in their arch/*/Makefile
 +ARCH          ?= arm64
  ARCH          ?= $(SUBARCH)
 +ifeq ($(ARCH),arm64)
 +ifneq ($(wildcard $(srctree)/../prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.9),)
 +CROSS_COMPILE ?= $(srctree)/../prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.9/bin/aarch64-linux-android-
 +endif
 +endif
  CROSS_COMPILE ?= $(CONFIG_CROSS_COMPILE:"%"=%)
  
  # Architecture as present in compile.h
@@@ -365,12 -357,6 +365,12 @@@ PERL             = per
  PYTHON                = python
  CHECK         = sparse
  
 +# Use the wrapper for the compiler. This wrapper scans for new
 +# warnings and causes the build to stop upon encountering them.
 +ifneq ($(wildcard $(srctree)/scripts/gcc-wrapper.py),)
 +CC            = $(srctree)/scripts/gcc-wrapper.py $(CROSS_COMPILE)gcc
 +endif
 +
  CHECKFLAGS     := -D__linux__ -Dlinux -D__STDC__ -Dunix -D__unix__ \
                  -Wbitwise -Wno-return-void $(CF)
  CFLAGS_MODULE   =
index 6ad554b01e953f9bfc49fae40c92353ac79c7f71,354144e3321843ec1e34993c5a0b37068053e1c9..ddfb97a299f2bf1e1e248bc2ded0779d644ce944
@@@ -170,7 -170,7 +170,7 @@@ static void *__dma_alloc(struct device 
        /* create a coherent mapping */
        page = virt_to_page(ptr);
        coherent_ptr = dma_common_contiguous_remap(page, size, VM_USERMAP,
 -                                                 prot, NULL);
 +                                                 prot, __builtin_return_address(0));
        if (!coherent_ptr)
                goto no_map;
  
@@@ -933,6 -933,10 +933,10 @@@ static int __init __iommu_dma_init(void
                ret = register_iommu_dma_ops_notifier(&platform_bus_type);
        if (!ret)
                ret = register_iommu_dma_ops_notifier(&amba_bustype);
+       /* handle devices queued before this arch_initcall */
+       if (!ret)
+               __iommu_attach_notifier(NULL, BUS_NOTIFY_ADD_DEVICE, NULL);
        return ret;
  }
  arch_initcall(__iommu_dma_init);
diff --combined fs/proc/base.c
index 3b6962c52965c01c163fa188564c828ede0bb077,b7de324bec1193dbb0d0eed756bcfbbb82e898ba..57df8a52e780c90d1fa433cf00146d03e174f09d
@@@ -403,7 -403,7 +403,7 @@@ static const struct file_operations pro
  static int proc_pid_auxv(struct seq_file *m, struct pid_namespace *ns,
                         struct pid *pid, struct task_struct *task)
  {
-       struct mm_struct *mm = mm_access(task, PTRACE_MODE_READ);
+       struct mm_struct *mm = mm_access(task, PTRACE_MODE_READ_FSCREDS);
        if (mm && !IS_ERR(mm)) {
                unsigned int nwords = 0;
                do {
@@@ -430,7 -430,8 +430,8 @@@ static int proc_pid_wchan(struct seq_fi
  
        wchan = get_wchan(task);
  
-       if (wchan && ptrace_may_access(task, PTRACE_MODE_READ) && !lookup_symbol_name(wchan, symname))
+       if (wchan && ptrace_may_access(task, PTRACE_MODE_READ_FSCREDS)
+                       && !lookup_symbol_name(wchan, symname))
                seq_printf(m, "%s", symname);
        else
                seq_putc(m, '0');
@@@ -444,7 -445,7 +445,7 @@@ static int lock_trace(struct task_struc
        int err = mutex_lock_killable(&task->signal->cred_guard_mutex);
        if (err)
                return err;
-       if (!ptrace_may_access(task, PTRACE_MODE_ATTACH)) {
+       if (!ptrace_may_access(task, PTRACE_MODE_ATTACH_FSCREDS)) {
                mutex_unlock(&task->signal->cred_guard_mutex);
                return -EPERM;
        }
@@@ -697,7 -698,7 +698,7 @@@ static int proc_fd_access_allowed(struc
         */
        task = get_proc_task(inode);
        if (task) {
-               allowed = ptrace_may_access(task, PTRACE_MODE_READ);
+               allowed = ptrace_may_access(task, PTRACE_MODE_READ_FSCREDS);
                put_task_struct(task);
        }
        return allowed;
@@@ -732,7 -733,7 +733,7 @@@ static bool has_pid_permissions(struct 
                return true;
        if (in_group_p(pid->pid_gid))
                return true;
-       return ptrace_may_access(task, PTRACE_MODE_READ);
+       return ptrace_may_access(task, PTRACE_MODE_READ_FSCREDS);
  }
  
  
@@@ -809,7 -810,7 +810,7 @@@ struct mm_struct *proc_mem_open(struct 
        struct mm_struct *mm = ERR_PTR(-ESRCH);
  
        if (task) {
-               mm = mm_access(task, mode);
+               mm = mm_access(task, mode | PTRACE_MODE_FSCREDS);
                put_task_struct(task);
  
                if (!IS_ERR_OR_NULL(mm)) {
@@@ -1856,7 -1857,7 +1857,7 @@@ static int map_files_d_revalidate(struc
        if (!task)
                goto out_notask;
  
-       mm = mm_access(task, PTRACE_MODE_READ);
+       mm = mm_access(task, PTRACE_MODE_READ_FSCREDS);
        if (IS_ERR_OR_NULL(mm))
                goto out;
  
@@@ -2007,7 -2008,7 +2008,7 @@@ static struct dentry *proc_map_files_lo
                goto out;
  
        result = -EACCES;
-       if (!ptrace_may_access(task, PTRACE_MODE_READ))
+       if (!ptrace_may_access(task, PTRACE_MODE_READ_FSCREDS))
                goto out_put_task;
  
        result = -ENOENT;
@@@ -2060,7 -2061,7 +2061,7 @@@ proc_map_files_readdir(struct file *fil
                goto out;
  
        ret = -EACCES;
-       if (!ptrace_may_access(task, PTRACE_MODE_READ))
+       if (!ptrace_may_access(task, PTRACE_MODE_READ_FSCREDS))
                goto out_put_task;
  
        ret = 0;
@@@ -2530,7 -2531,7 +2531,7 @@@ static int do_io_accounting(struct task
        if (result)
                return result;
  
-       if (!ptrace_may_access(task, PTRACE_MODE_READ)) {
+       if (!ptrace_may_access(task, PTRACE_MODE_READ_FSCREDS)) {
                result = -EACCES;
                goto out_unlock;
        }
@@@ -2793,8 -2794,8 +2794,8 @@@ static const struct pid_entry tgid_base
        ONE("cgroup",  S_IRUGO, proc_cgroup_show),
  #endif
        ONE("oom_score",  S_IRUGO, proc_oom_score),
 -      REG("oom_adj",    S_IRUGO|S_IWUSR, proc_oom_adj_operations),
 -      REG("oom_score_adj", S_IRUGO|S_IWUSR, proc_oom_score_adj_operations),
 +      REG("oom_adj",    S_IRUSR, proc_oom_adj_operations),
 +      REG("oom_score_adj", S_IRUSR, proc_oom_score_adj_operations),
  #ifdef CONFIG_AUDITSYSCALL
        REG("loginuid",   S_IWUSR|S_IRUGO, proc_loginuid_operations),
        REG("sessionid",  S_IRUGO, proc_sessionid_operations),
@@@ -3141,8 -3142,8 +3142,8 @@@ static const struct pid_entry tid_base_
        ONE("cgroup",  S_IRUGO, proc_cgroup_show),
  #endif
        ONE("oom_score", S_IRUGO, proc_oom_score),
 -      REG("oom_adj",   S_IRUGO|S_IWUSR, proc_oom_adj_operations),
 -      REG("oom_score_adj", S_IRUGO|S_IWUSR, proc_oom_score_adj_operations),
 +      REG("oom_adj",   S_IRUSR, proc_oom_adj_operations),
 +      REG("oom_score_adj", S_IRUSR, proc_oom_score_adj_operations),
  #ifdef CONFIG_AUDITSYSCALL
        REG("loginuid",  S_IWUSR|S_IRUGO, proc_loginuid_operations),
        REG("sessionid",  S_IRUGO, proc_sessionid_operations),
diff --combined fs/proc/task_mmu.c
index 91698054b965d56ea5b64cd82992a5ddf149527f,09cd3edde08a3b307cb3b4b9d0abc0ef354979a3..67aa7e63a5c169a0634ff94c3012be3aa4a9691f
@@@ -116,56 -116,6 +116,56 @@@ static void release_task_mempolicy(stru
  }
  #endif
  
 +static void seq_print_vma_name(struct seq_file *m, struct vm_area_struct *vma)
 +{
 +      const char __user *name = vma_get_anon_name(vma);
 +      struct mm_struct *mm = vma->vm_mm;
 +
 +      unsigned long page_start_vaddr;
 +      unsigned long page_offset;
 +      unsigned long num_pages;
 +      unsigned long max_len = NAME_MAX;
 +      int i;
 +
 +      page_start_vaddr = (unsigned long)name & PAGE_MASK;
 +      page_offset = (unsigned long)name - page_start_vaddr;
 +      num_pages = DIV_ROUND_UP(page_offset + max_len, PAGE_SIZE);
 +
 +      seq_puts(m, "[anon:");
 +
 +      for (i = 0; i < num_pages; i++) {
 +              int len;
 +              int write_len;
 +              const char *kaddr;
 +              long pages_pinned;
 +              struct page *page;
 +
 +              pages_pinned = get_user_pages(current, mm, page_start_vaddr,
 +                              1, 0, 0, &page, NULL);
 +              if (pages_pinned < 1) {
 +                      seq_puts(m, "<fault>]");
 +                      return;
 +              }
 +
 +              kaddr = (const char *)kmap(page);
 +              len = min(max_len, PAGE_SIZE - page_offset);
 +              write_len = strnlen(kaddr + page_offset, len);
 +              seq_write(m, kaddr + page_offset, write_len);
 +              kunmap(page);
 +              put_page(page);
 +
 +              /* if strnlen hit a null terminator then we're done */
 +              if (write_len != len)
 +                      break;
 +
 +              max_len -= len;
 +              page_offset = 0;
 +              page_start_vaddr += PAGE_SIZE;
 +      }
 +
 +      seq_putc(m, ']');
 +}
 +
  static void vma_stop(struct proc_maps_private *priv)
  {
        struct mm_struct *mm = priv->mm;
@@@ -401,12 -351,6 +401,12 @@@ show_map_vma(struct seq_file *m, struc
                                seq_pad(m, ' ');
                                seq_printf(m, "[stack:%d]", tid);
                        }
 +                      goto done;
 +              }
 +
 +              if (vma_get_anon_name(vma)) {
 +                      seq_pad(m, ' ');
 +                      seq_print_vma_name(m, vma);
                }
        }
  
@@@ -732,12 -676,6 +732,12 @@@ static int show_smap(struct seq_file *m
  
        show_map_vma(m, vma, is_pid);
  
 +      if (vma_get_anon_name(vma)) {
 +              seq_puts(m, "Name:           ");
 +              seq_print_vma_name(m, vma);
 +              seq_putc(m, '\n');
 +      }
 +
        seq_printf(m,
                   "Size:           %8lu kB\n"
                   "Rss:            %8lu kB\n"
@@@ -1535,18 -1473,19 +1535,19 @@@ static int gather_pte_stats(pmd_t *pmd
  static int gather_hugetlb_stats(pte_t *pte, unsigned long hmask,
                unsigned long addr, unsigned long end, struct mm_walk *walk)
  {
+       pte_t huge_pte = huge_ptep_get(pte);
        struct numa_maps *md;
        struct page *page;
  
-       if (!pte_present(*pte))
+       if (!pte_present(huge_pte))
                return 0;
  
-       page = pte_page(*pte);
+       page = pte_page(huge_pte);
        if (!page)
                return 0;
  
        md = walk->private;
-       gather_stats(page, md, pte_dirty(*pte), 1);
+       gather_stats(page, md, pte_dirty(huge_pte), 1);
        return 0;
  }
  
diff --combined kernel/sys.c
index 11333311cf1c5da8aab5c1eaceaaaee671468676,78947de6f9691e898adf3803ec59fded4a0a28da..b5a8e844a96887e2d4253536a5a45dd2a0ca296e
@@@ -41,8 -41,6 +41,8 @@@
  #include <linux/syscore_ops.h>
  #include <linux/version.h>
  #include <linux/ctype.h>
 +#include <linux/mm.h>
 +#include <linux/mempolicy.h>
  
  #include <linux/compat.h>
  #include <linux/syscalls.h>
@@@ -1855,11 -1853,13 +1855,13 @@@ static int prctl_set_mm_map(int opt, co
                user_auxv[AT_VECTOR_SIZE - 1] = AT_NULL;
        }
  
-       if (prctl_map.exe_fd != (u32)-1)
+       if (prctl_map.exe_fd != (u32)-1) {
                error = prctl_set_mm_exe_file(mm, prctl_map.exe_fd);
-       down_read(&mm->mmap_sem);
-       if (error)
-               goto out;
+               if (error)
+                       return error;
+       }
+       down_write(&mm->mmap_sem);
  
        /*
         * We don't validate if these members are pointing to
        if (prctl_map.auxv_size)
                memcpy(mm->saved_auxv, user_auxv, sizeof(user_auxv));
  
-       error = 0;
- out:
-       up_read(&mm->mmap_sem);
-       return error;
+       up_write(&mm->mmap_sem);
+       return 0;
  }
  #endif /* CONFIG_CHECKPOINT_RESTORE */
  
@@@ -1965,7 -1963,7 +1965,7 @@@ static int prctl_set_mm(int opt, unsign
  
        error = -EINVAL;
  
-       down_read(&mm->mmap_sem);
+       down_write(&mm->mmap_sem);
        vma = find_vma(mm, addr);
  
        prctl_map.start_code    = mm->start_code;
  
        error = 0;
  out:
-       up_read(&mm->mmap_sem);
+       up_write(&mm->mmap_sem);
        return error;
  }
  
@@@ -2074,158 -2072,10 +2074,158 @@@ static int prctl_get_tid_address(struc
  }
  #endif
  
 +#ifdef CONFIG_MMU
 +static int prctl_update_vma_anon_name(struct vm_area_struct *vma,
 +              struct vm_area_struct **prev,
 +              unsigned long start, unsigned long end,
 +              const char __user *name_addr)
 +{
 +      struct mm_struct *mm = vma->vm_mm;
 +      int error = 0;
 +      pgoff_t pgoff;
 +
 +      if (name_addr == vma_get_anon_name(vma)) {
 +              *prev = vma;
 +              goto out;
 +      }
 +
 +      pgoff = vma->vm_pgoff + ((start - vma->vm_start) >> PAGE_SHIFT);
 +      *prev = vma_merge(mm, *prev, start, end, vma->vm_flags, vma->anon_vma,
 +                              vma->vm_file, pgoff, vma_policy(vma),
 +                              vma->vm_userfaultfd_ctx, name_addr);
 +      if (*prev) {
 +              vma = *prev;
 +              goto success;
 +      }
 +
 +      *prev = vma;
 +
 +      if (start != vma->vm_start) {
 +              error = split_vma(mm, vma, start, 1);
 +              if (error)
 +                      goto out;
 +      }
 +
 +      if (end != vma->vm_end) {
 +              error = split_vma(mm, vma, end, 0);
 +              if (error)
 +                      goto out;
 +      }
 +
 +success:
 +      if (!vma->vm_file)
 +              vma->anon_name = name_addr;
 +
 +out:
 +      if (error == -ENOMEM)
 +              error = -EAGAIN;
 +      return error;
 +}
 +
 +static int prctl_set_vma_anon_name(unsigned long start, unsigned long end,
 +                      unsigned long arg)
 +{
 +      unsigned long tmp;
 +      struct vm_area_struct *vma, *prev;
 +      int unmapped_error = 0;
 +      int error = -EINVAL;
 +
 +      /*
 +       * If the interval [start,end) covers some unmapped address
 +       * ranges, just ignore them, but return -ENOMEM at the end.
 +       * - this matches the handling in madvise.
 +       */
 +      vma = find_vma_prev(current->mm, start, &prev);
 +      if (vma && start > vma->vm_start)
 +              prev = vma;
 +
 +      for (;;) {
 +              /* Still start < end. */
 +              error = -ENOMEM;
 +              if (!vma)
 +                      return error;
 +
 +              /* Here start < (end|vma->vm_end). */
 +              if (start < vma->vm_start) {
 +                      unmapped_error = -ENOMEM;
 +                      start = vma->vm_start;
 +                      if (start >= end)
 +                              return error;
 +              }
 +
 +              /* Here vma->vm_start <= start < (end|vma->vm_end) */
 +              tmp = vma->vm_end;
 +              if (end < tmp)
 +                      tmp = end;
 +
 +              /* Here vma->vm_start <= start < tmp <= (end|vma->vm_end). */
 +              error = prctl_update_vma_anon_name(vma, &prev, start, tmp,
 +                              (const char __user *)arg);
 +              if (error)
 +                      return error;
 +              start = tmp;
 +              if (prev && start < prev->vm_end)
 +                      start = prev->vm_end;
 +              error = unmapped_error;
 +              if (start >= end)
 +                      return error;
 +              if (prev)
 +                      vma = prev->vm_next;
 +              else    /* madvise_remove dropped mmap_sem */
 +                      vma = find_vma(current->mm, start);
 +      }
 +}
 +
 +static int prctl_set_vma(unsigned long opt, unsigned long start,
 +              unsigned long len_in, unsigned long arg)
 +{
 +      struct mm_struct *mm = current->mm;
 +      int error;
 +      unsigned long len;
 +      unsigned long end;
 +
 +      if (start & ~PAGE_MASK)
 +              return -EINVAL;
 +      len = (len_in + ~PAGE_MASK) & PAGE_MASK;
 +
 +      /* Check to see whether len was rounded up from small -ve to zero */
 +      if (len_in && !len)
 +              return -EINVAL;
 +
 +      end = start + len;
 +      if (end < start)
 +              return -EINVAL;
 +
 +      if (end == start)
 +              return 0;
 +
 +      down_write(&mm->mmap_sem);
 +
 +      switch (opt) {
 +      case PR_SET_VMA_ANON_NAME:
 +              error = prctl_set_vma_anon_name(start, end, arg);
 +              break;
 +      default:
 +              error = -EINVAL;
 +      }
 +
 +      up_write(&mm->mmap_sem);
 +
 +      return error;
 +}
 +#else /* CONFIG_MMU */
 +static int prctl_set_vma(unsigned long opt, unsigned long start,
 +              unsigned long len_in, unsigned long arg)
 +{
 +      return -EINVAL;
 +}
 +#endif
 +
  SYSCALL_DEFINE5(prctl, int, option, unsigned long, arg2, unsigned long, arg3,
                unsigned long, arg4, unsigned long, arg5)
  {
        struct task_struct *me = current;
 +      struct task_struct *tsk;
        unsigned char comm[sizeof(me->comm)];
        long error;
  
        case PR_GET_TID_ADDRESS:
                error = prctl_get_tid_address(me, (int __user **)arg2);
                break;
 +      case PR_SET_TIMERSLACK_PID:
 +              if (task_pid_vnr(current) != (pid_t)arg3 &&
 +                              !capable(CAP_SYS_NICE))
 +                      return -EPERM;
 +              rcu_read_lock();
 +              tsk = find_task_by_vpid((pid_t)arg3);
 +              if (tsk == NULL) {
 +                      rcu_read_unlock();
 +                      return -EINVAL;
 +              }
 +              get_task_struct(tsk);
 +              rcu_read_unlock();
 +              if (arg2 <= 0)
 +                      tsk->timer_slack_ns =
 +                              tsk->default_timer_slack_ns;
 +              else
 +                      tsk->timer_slack_ns = arg2;
 +              put_task_struct(tsk);
 +              error = 0;
 +              break;
        case PR_SET_CHILD_SUBREAPER:
                me->signal->is_child_subreaper = !!arg2;
                break;
        case PR_GET_FP_MODE:
                error = GET_FP_MODE(me);
                break;
 +      case PR_SET_VMA:
 +              error = prctl_set_vma(arg2, arg3, arg4, arg5);
 +              break;
        default:
                error = -EINVAL;
                break;
diff --combined mm/mlock.c
index a6617735f2f48e35d5bb7996fb9899ec72317aae,d6006b146fea38c0f897bbcb721dec70a189c92c..d843bc9d32ddb077aa4aadfb156a4e2017ee94d5
@@@ -172,7 -172,7 +172,7 @@@ static void __munlock_isolation_failed(
   */
  unsigned int munlock_vma_page(struct page *page)
  {
-       unsigned int nr_pages;
+       int nr_pages;
        struct zone *zone = page_zone(page);
  
        /* For try_to_munlock() and to serialize with page migration */
@@@ -512,7 -512,7 +512,7 @@@ static int mlock_fixup(struct vm_area_s
        pgoff = vma->vm_pgoff + ((start - vma->vm_start) >> PAGE_SHIFT);
        *prev = vma_merge(mm, *prev, start, end, newflags, vma->anon_vma,
                          vma->vm_file, pgoff, vma_policy(vma),
 -                        vma->vm_userfaultfd_ctx);
 +                        vma->vm_userfaultfd_ctx, vma_get_anon_name(vma));
        if (*prev) {
                vma = *prev;
                goto success;
diff --combined mm/mmap.c
index 2b11430087937f2ff8bdf21b6c5622531c9d09ab,455772a05e5416720babd944532004fe529be1fd..6c561acdca92730aaabd50926fd01b7fd9345fb3
+++ b/mm/mmap.c
  #define arch_rebalance_pgtables(addr, len)            (addr)
  #endif
  
 +#ifdef CONFIG_HAVE_ARCH_MMAP_RND_BITS
 +const int mmap_rnd_bits_min = CONFIG_ARCH_MMAP_RND_BITS_MIN;
 +const int mmap_rnd_bits_max = CONFIG_ARCH_MMAP_RND_BITS_MAX;
 +int mmap_rnd_bits __read_mostly = CONFIG_ARCH_MMAP_RND_BITS;
 +#endif
 +#ifdef CONFIG_HAVE_ARCH_MMAP_RND_COMPAT_BITS
 +const int mmap_rnd_compat_bits_min = CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MIN;
 +const int mmap_rnd_compat_bits_max = CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MAX;
 +int mmap_rnd_compat_bits __read_mostly = CONFIG_ARCH_MMAP_RND_COMPAT_BITS;
 +#endif
 +
 +
  static void unmap_region(struct mm_struct *mm,
                struct vm_area_struct *vma, struct vm_area_struct *prev,
                unsigned long start, unsigned long end);
@@@ -453,12 -441,16 +453,16 @@@ static void validate_mm(struct mm_struc
        struct vm_area_struct *vma = mm->mmap;
  
        while (vma) {
+               struct anon_vma *anon_vma = vma->anon_vma;
                struct anon_vma_chain *avc;
  
-               vma_lock_anon_vma(vma);
-               list_for_each_entry(avc, &vma->anon_vma_chain, same_vma)
-                       anon_vma_interval_tree_verify(avc);
-               vma_unlock_anon_vma(vma);
+               if (anon_vma) {
+                       anon_vma_lock_read(anon_vma);
+                       list_for_each_entry(avc, &vma->anon_vma_chain, same_vma)
+                               anon_vma_interval_tree_verify(avc);
+                       anon_vma_unlock_read(anon_vma);
+               }
                highest_address = vma->vm_end;
                vma = vma->vm_next;
                i++;
@@@ -933,8 -925,7 +937,8 @@@ again:                     remove_next = 1 + (end > next-
   */
  static inline int is_mergeable_vma(struct vm_area_struct *vma,
                                struct file *file, unsigned long vm_flags,
 -                              struct vm_userfaultfd_ctx vm_userfaultfd_ctx)
 +                              struct vm_userfaultfd_ctx vm_userfaultfd_ctx,
 +                              const char __user *anon_name)
  {
        /*
         * VM_SOFTDIRTY should not prevent from VMA merging, if we
                return 0;
        if (!is_mergeable_vm_userfaultfd_ctx(vma, vm_userfaultfd_ctx))
                return 0;
 +      if (vma_get_anon_name(vma) != anon_name)
 +              return 0;
        return 1;
  }
  
@@@ -986,10 -975,9 +990,10 @@@ static in
  can_vma_merge_before(struct vm_area_struct *vma, unsigned long vm_flags,
                     struct anon_vma *anon_vma, struct file *file,
                     pgoff_t vm_pgoff,
 -                   struct vm_userfaultfd_ctx vm_userfaultfd_ctx)
 +                   struct vm_userfaultfd_ctx vm_userfaultfd_ctx,
 +                   const char __user *anon_name)
  {
 -      if (is_mergeable_vma(vma, file, vm_flags, vm_userfaultfd_ctx) &&
 +      if (is_mergeable_vma(vma, file, vm_flags, vm_userfaultfd_ctx, anon_name) &&
            is_mergeable_anon_vma(anon_vma, vma->anon_vma, vma)) {
                if (vma->vm_pgoff == vm_pgoff)
                        return 1;
@@@ -1008,10 -996,9 +1012,10 @@@ static in
  can_vma_merge_after(struct vm_area_struct *vma, unsigned long vm_flags,
                    struct anon_vma *anon_vma, struct file *file,
                    pgoff_t vm_pgoff,
 -                  struct vm_userfaultfd_ctx vm_userfaultfd_ctx)
 +                  struct vm_userfaultfd_ctx vm_userfaultfd_ctx,
 +                  const char __user *anon_name)
  {
 -      if (is_mergeable_vma(vma, file, vm_flags, vm_userfaultfd_ctx) &&
 +      if (is_mergeable_vma(vma, file, vm_flags, vm_userfaultfd_ctx, anon_name) &&
            is_mergeable_anon_vma(anon_vma, vma->anon_vma, vma)) {
                pgoff_t vm_pglen;
                vm_pglen = vma_pages(vma);
  }
  
  /*
 - * Given a mapping request (addr,end,vm_flags,file,pgoff), figure out
 - * whether that can be merged with its predecessor or its successor.
 - * Or both (it neatly fills a hole).
 + * Given a mapping request (addr,end,vm_flags,file,pgoff,anon_name),
 + * figure out whether that can be merged with its predecessor or its
 + * successor.  Or both (it neatly fills a hole).
   *
   * In most cases - when called for mmap, brk or mremap - [addr,end) is
   * certain not to be mapped by the time vma_merge is called; but when
@@@ -1055,8 -1042,7 +1059,8 @@@ struct vm_area_struct *vma_merge(struc
                        unsigned long end, unsigned long vm_flags,
                        struct anon_vma *anon_vma, struct file *file,
                        pgoff_t pgoff, struct mempolicy *policy,
 -                      struct vm_userfaultfd_ctx vm_userfaultfd_ctx)
 +                      struct vm_userfaultfd_ctx vm_userfaultfd_ctx,
 +                      const char __user *anon_name)
  {
        pgoff_t pglen = (end - addr) >> PAGE_SHIFT;
        struct vm_area_struct *area, *next;
                        mpol_equal(vma_policy(prev), policy) &&
                        can_vma_merge_after(prev, vm_flags,
                                            anon_vma, file, pgoff,
 -                                          vm_userfaultfd_ctx)) {
 +                                          vm_userfaultfd_ctx,
 +                                          anon_name)) {
                /*
                 * OK, it can.  Can we now merge in the successor as well?
                 */
                                can_vma_merge_before(next, vm_flags,
                                                     anon_vma, file,
                                                     pgoff+pglen,
 -                                                   vm_userfaultfd_ctx) &&
 +                                                   vm_userfaultfd_ctx,
 +                                                   anon_name) &&
                                is_mergeable_anon_vma(prev->anon_vma,
                                                      next->anon_vma, NULL)) {
                                                        /* cases 1, 6 */
                        mpol_equal(policy, vma_policy(next)) &&
                        can_vma_merge_before(next, vm_flags,
                                             anon_vma, file, pgoff+pglen,
 -                                           vm_userfaultfd_ctx)) {
 +                                           vm_userfaultfd_ctx,
 +                                           anon_name)) {
                if (prev && addr < prev->vm_end)        /* case 4 */
                        err = vma_adjust(prev, prev->vm_start,
                                addr, prev->vm_pgoff, NULL);
@@@ -1602,7 -1585,7 +1606,7 @@@ unsigned long mmap_region(struct file *
         * Can we just expand an old mapping?
         */
        vma = vma_merge(mm, prev, addr, addr + len, vm_flags,
 -                      NULL, file, pgoff, NULL, NULL_VM_UFFD_CTX);
 +                      NULL, file, pgoff, NULL, NULL_VM_UFFD_CTX, NULL);
        if (vma)
                goto out;
  
@@@ -2168,32 -2151,27 +2172,27 @@@ static int acct_stack_growth(struct vm_
  int expand_upwards(struct vm_area_struct *vma, unsigned long address)
  {
        struct mm_struct *mm = vma->vm_mm;
-       int error;
+       int error = 0;
  
        if (!(vma->vm_flags & VM_GROWSUP))
                return -EFAULT;
  
-       /*
-        * We must make sure the anon_vma is allocated
-        * so that the anon_vma locking is not a noop.
-        */
+       /* Guard against wrapping around to address 0. */
+       if (address < PAGE_ALIGN(address+4))
+               address = PAGE_ALIGN(address+4);
+       else
+               return -ENOMEM;
+       /* We must make sure the anon_vma is allocated. */
        if (unlikely(anon_vma_prepare(vma)))
                return -ENOMEM;
-       vma_lock_anon_vma(vma);
  
        /*
         * vma->vm_start/vm_end cannot change under us because the caller
         * is required to hold the mmap_sem in read mode.  We need the
         * anon_vma lock to serialize against concurrent expand_stacks.
-        * Also guard against wrapping around to address 0.
         */
-       if (address < PAGE_ALIGN(address+4))
-               address = PAGE_ALIGN(address+4);
-       else {
-               vma_unlock_anon_vma(vma);
-               return -ENOMEM;
-       }
-       error = 0;
+       anon_vma_lock_write(vma->anon_vma);
  
        /* Somebody else might have raced and expanded it already */
        if (address > vma->vm_end) {
                                 * updates, but we only hold a shared mmap_sem
                                 * lock here, so we need to protect against
                                 * concurrent vma expansions.
-                                * vma_lock_anon_vma() doesn't help here, as
+                                * anon_vma_lock_write() doesn't help here, as
                                 * we don't guarantee that all growable vmas
                                 * in a mm share the same root anon vma.
                                 * So, we reuse mm->page_table_lock to guard
                        }
                }
        }
-       vma_unlock_anon_vma(vma);
+       anon_vma_unlock_write(vma->anon_vma);
        khugepaged_enter_vma_merge(vma, vma->vm_flags);
        validate_mm(mm);
        return error;
@@@ -2251,25 -2229,21 +2250,21 @@@ int expand_downwards(struct vm_area_str
        struct mm_struct *mm = vma->vm_mm;
        int error;
  
-       /*
-        * We must make sure the anon_vma is allocated
-        * so that the anon_vma locking is not a noop.
-        */
-       if (unlikely(anon_vma_prepare(vma)))
-               return -ENOMEM;
        address &= PAGE_MASK;
        error = security_mmap_addr(address);
        if (error)
                return error;
  
-       vma_lock_anon_vma(vma);
+       /* We must make sure the anon_vma is allocated. */
+       if (unlikely(anon_vma_prepare(vma)))
+               return -ENOMEM;
  
        /*
         * vma->vm_start/vm_end cannot change under us because the caller
         * is required to hold the mmap_sem in read mode.  We need the
         * anon_vma lock to serialize against concurrent expand_stacks.
         */
+       anon_vma_lock_write(vma->anon_vma);
  
        /* Somebody else might have raced and expanded it already */
        if (address < vma->vm_start) {
                                 * updates, but we only hold a shared mmap_sem
                                 * lock here, so we need to protect against
                                 * concurrent vma expansions.
-                                * vma_lock_anon_vma() doesn't help here, as
+                                * anon_vma_lock_write() doesn't help here, as
                                 * we don't guarantee that all growable vmas
                                 * in a mm share the same root anon vma.
                                 * So, we reuse mm->page_table_lock to guard
                        }
                }
        }
-       vma_unlock_anon_vma(vma);
+       anon_vma_unlock_write(vma->anon_vma);
        khugepaged_enter_vma_merge(vma, vma->vm_flags);
        validate_mm(mm);
        return error;
@@@ -2694,12 -2668,29 +2689,29 @@@ SYSCALL_DEFINE5(remap_file_pages, unsig
        if (!vma || !(vma->vm_flags & VM_SHARED))
                goto out;
  
-       if (start < vma->vm_start || start + size > vma->vm_end)
+       if (start < vma->vm_start)
                goto out;
  
-       if (pgoff == linear_page_index(vma, start)) {
-               ret = 0;
-               goto out;
+       if (start + size > vma->vm_end) {
+               struct vm_area_struct *next;
+               for (next = vma->vm_next; next; next = next->vm_next) {
+                       /* hole between vmas ? */
+                       if (next->vm_start != next->vm_prev->vm_end)
+                               goto out;
+                       if (next->vm_file != vma->vm_file)
+                               goto out;
+                       if (next->vm_flags != vma->vm_flags)
+                               goto out;
+                       if (start + size <= next->vm_end)
+                               break;
+               }
+               if (!next)
+                       goto out;
        }
  
        prot |= vma->vm_flags & VM_READ ? PROT_READ : 0;
        flags &= MAP_NONBLOCK;
        flags |= MAP_SHARED | MAP_FIXED | MAP_POPULATE;
        if (vma->vm_flags & VM_LOCKED) {
+               struct vm_area_struct *tmp;
                flags |= MAP_LOCKED;
                /* drop PG_Mlocked flag for over-mapped range */
-               munlock_vma_pages_range(vma, start, start + size);
+               for (tmp = vma; tmp->vm_start >= start + size;
+                               tmp = tmp->vm_next) {
+                       munlock_vma_pages_range(tmp,
+                                       max(tmp->vm_start, start),
+                                       min(tmp->vm_end, start + size));
+               }
        }
  
        file = get_file(vma->vm_file);
@@@ -2792,7 -2790,7 +2811,7 @@@ static unsigned long do_brk(unsigned lo
  
        /* Can we just expand an old private anonymous mapping? */
        vma = vma_merge(mm, prev, addr, addr + len, flags,
 -                      NULL, NULL, pgoff, NULL, NULL_VM_UFFD_CTX);
 +                      NULL, NULL, pgoff, NULL, NULL_VM_UFFD_CTX, NULL);
        if (vma)
                goto out;
  
@@@ -2950,7 -2948,7 +2969,7 @@@ struct vm_area_struct *copy_vma(struct 
                return NULL;    /* should never get here */
        new_vma = vma_merge(mm, prev, addr, addr + len, vma->vm_flags,
                            vma->anon_vma, vma->vm_file, pgoff, vma_policy(vma),
 -                          vma->vm_userfaultfd_ctx);
 +                          vma->vm_userfaultfd_ctx, vma_get_anon_name(vma));
        if (new_vma) {
                /*
                 * Source vma may have been merged into new_vma
diff --combined security/commoncap.c
index f035b84b3601a4d13b8e30a16396d5a85ab88a95,48071ed7c445d025fa4ae57c12f032bfa916521f..7fa251aea32f88d3bd50be9d06b890991d1eec9e
  #include <linux/binfmts.h>
  #include <linux/personality.h>
  
 +#ifdef CONFIG_ANDROID_PARANOID_NETWORK
 +#include <linux/android_aid.h>
 +#endif
 +
  /*
   * If a non-root user executes a setuid-root binary in
   * !secure(SECURE_NOROOT) mode, then we raise capabilities.
@@@ -77,13 -73,6 +77,13 @@@ int cap_capable(const struct cred *cred
  {
        struct user_namespace *ns = targ_ns;
  
 +#ifdef CONFIG_ANDROID_PARANOID_NETWORK
 +      if (cap == CAP_NET_RAW && in_egroup_p(AID_NET_RAW))
 +              return 0;
 +      if (cap == CAP_NET_ADMIN && in_egroup_p(AID_NET_ADMIN))
 +              return 0;
 +#endif
 +
        /* See if cred has the capability in the target user namespace
         * by examining the target user namespace and all of the target
         * user namespace's parents.
@@@ -148,12 -137,17 +148,17 @@@ int cap_ptrace_access_check(struct task
  {
        int ret = 0;
        const struct cred *cred, *child_cred;
+       const kernel_cap_t *caller_caps;
  
        rcu_read_lock();
        cred = current_cred();
        child_cred = __task_cred(child);
+       if (mode & PTRACE_MODE_FSCREDS)
+               caller_caps = &cred->cap_effective;
+       else
+               caller_caps = &cred->cap_permitted;
        if (cred->user_ns == child_cred->user_ns &&
-           cap_issubset(child_cred->cap_permitted, cred->cap_permitted))
+           cap_issubset(child_cred->cap_permitted, *caller_caps))
                goto out;
        if (ns_capable(child_cred->user_ns, CAP_SYS_PTRACE))
                goto out;