2020-09-01 16:16:27

by Sumit Semwal

[permalink] [raw]
Subject: [PATCH v7 0/3] Anonymous VMA naming patches

Version v4 of these patches was sent by Colin Cross a long time ago [1]
and [2]. At the time, these patches were not merged, and it looks like they
just fell off the radar since.

In our efforts to run Android on mainline kernels, we realised that since past
some time, this patchset is needed for Android to boot, hence I am re-posting
it to try and get these discussed and hopefully merged.

I have rebased these for v5.9-rc3 and fixed minor updates as required.

---
v6: Rebased to v5.9-rc3 and addressed review comments:
- added missing callers in fs/userfaultd.c
- simplified the union
- use the new access_remote_vm_locked() in show_map_vma() since that
already holds mmap_lock
v7: fixed randconfig build failure when CONFIG_ADVISE_SYSCALLS isn't defined

Colin Cross (2):
mm: rearrange madvise code to allow for reuse
mm: add a field to store names for private anonymous memory

Sumit Semwal (1):
mm: memory: Add access_remote_vm_locked variant

Documentation/filesystems/proc.rst | 2 +
fs/proc/task_mmu.c | 24 +-
fs/userfaultfd.c | 7 +-
include/linux/mm.h | 14 +-
include/linux/mm_types.h | 25 +-
include/uapi/linux/prctl.h | 3 +
kernel/sys.c | 32 +++
mm/interval_tree.c | 2 +-
mm/madvise.c | 356 +++++++++++++++++------------
mm/memory.c | 49 +++-
mm/mempolicy.c | 3 +-
mm/mlock.c | 2 +-
mm/mmap.c | 38 +--
mm/mprotect.c | 2 +-
14 files changed, 381 insertions(+), 178 deletions(-)

--
2.28.0


2020-09-01 16:16:43

by Sumit Semwal

[permalink] [raw]
Subject: [PATCH v7 2/3] mm: memory: Add access_remote_vm_locked variant

This allows accessing a remote vm while the mmap_lock is already
held by the caller.

While adding support for anonymous vma naming, show_map_vma()
needs to access the remote vm to get the name of the anonymous vma.
Since show_map_vma() already holds the mmap_lock, so this _locked
variant was required.

Signed-off-by: Sumit Semwal <[email protected]>
---
include/linux/mm.h | 2 ++
mm/memory.c | 49 ++++++++++++++++++++++++++++++++++++++++------
2 files changed, 45 insertions(+), 6 deletions(-)

diff --git a/include/linux/mm.h b/include/linux/mm.h
index ca6e6a81576b..e9212c0bb5ac 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -1708,6 +1708,8 @@ extern int access_remote_vm(struct mm_struct *mm, unsigned long addr,
void *buf, int len, unsigned int gup_flags);
extern int __access_remote_vm(struct task_struct *tsk, struct mm_struct *mm,
unsigned long addr, void *buf, int len, unsigned int gup_flags);
+extern int access_remote_vm_locked(struct mm_struct *mm, unsigned long addr,
+ void *buf, int len, unsigned int gup_flags);

long get_user_pages_remote(struct mm_struct *mm,
unsigned long start, unsigned long nr_pages,
diff --git a/mm/memory.c b/mm/memory.c
index 602f4283122f..207be99390e9 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -4726,17 +4726,17 @@ EXPORT_SYMBOL_GPL(generic_access_phys);
/*
* Access another process' address space as given in mm. If non-NULL, use the
* given task for page fault accounting.
+ * This variant assumes that the mmap_lock is already held by the caller, so
+ * doesn't take the mmap_lock.
*/
-int __access_remote_vm(struct task_struct *tsk, struct mm_struct *mm,
- unsigned long addr, void *buf, int len, unsigned int gup_flags)
+int __access_remote_vm_locked(struct task_struct *tsk, struct mm_struct *mm,
+ unsigned long addr, void *buf, int len,
+ unsigned int gup_flags)
{
struct vm_area_struct *vma;
void *old_buf = buf;
int write = gup_flags & FOLL_WRITE;

- if (mmap_read_lock_killable(mm))
- return 0;
-
/* ignore errors, just check how much was successfully transferred */
while (len) {
int bytes, ret, offset;
@@ -4785,9 +4785,46 @@ int __access_remote_vm(struct task_struct *tsk, struct mm_struct *mm,
buf += bytes;
addr += bytes;
}
+ return buf - old_buf;
+}
+
+/*
+ * Access another process' address space as given in mm. If non-NULL, use the
+ * given task for page fault accounting.
+ */
+int __access_remote_vm(struct task_struct *tsk, struct mm_struct *mm,
+ unsigned long addr, void *buf, int len, unsigned int gup_flags)
+{
+ int ret;
+
+ if (mmap_read_lock_killable(mm))
+ return 0;
+
+ ret = __access_remote_vm_locked(tsk, mm, addr, buf, len, gup_flags);
mmap_read_unlock(mm);

- return buf - old_buf;
+ return ret;
+}
+
+/**
+ * access_remote_vm_locked - access another process' address space, without
+ * taking the mmap_lock. This allows nested calls from callers that already have
+ * taken the lock.
+ *
+ * @mm: the mm_struct of the target address space
+ * @addr: start address to access
+ * @buf: source or destination buffer
+ * @len: number of bytes to transfer
+ * @gup_flags: flags modifying lookup behaviour
+ *
+ * The caller must hold a reference on @mm, as well as hold the mmap_lock
+ *
+ * Return: number of bytes copied from source to destination.
+ */
+int access_remote_vm_locked(struct mm_struct *mm, unsigned long addr, void *buf,
+ int len, unsigned int gup_flags)
+{
+ return __access_remote_vm_locked(NULL, mm, addr, buf, len, gup_flags);
}

/**
--
2.28.0