mirror of
https://github.com/torvalds/linux.git
synced 2026-11-07 06:17:02 +01:00
mm: Add copy_remote_mm_str()
copy_remote_vm_str() gets the target address space from a struct task_struct. This does not work for an address space that exists but is not yet associated with a task_struct, such as the mm held by struct linux_binprm during exec. Add copy_remote_mm_str(), which operates directly on a struct mm_struct. Use a common internal interface for the MMU and NOMMU implementations and define both public wrappers in mm/util.c. Preserve the existing copy_remote_vm_str() behavior, including handling zero-length requests before acquiring the task's mm. Signed-off-by: Anastasios Papagiannis <tasos.papagiannnis@gmail.com> Signed-off-by: Alexei Starovoitov <ast@kernel.org> Acked-by: Lorenzo Stoakes (ARM) <ljs@kernel.org> Acked-by: David Hildenbrand (Arm) <david@kernel.org> Link: https://patch.msgid.link/20260918131757.42802-2-tasos.papagiannnis@gmail.com
This commit is contained in:
parent
961b8946ac
commit
69d38c792c
|
|
@ -3325,10 +3325,10 @@ extern int access_process_vm(struct task_struct *tsk, unsigned long addr,
|
|||
extern int access_remote_vm(struct mm_struct *mm, unsigned long addr,
|
||||
void *buf, int len, unsigned int gup_flags);
|
||||
|
||||
#ifdef CONFIG_BPF_SYSCALL
|
||||
extern int copy_remote_vm_str(struct task_struct *tsk, unsigned long addr,
|
||||
void *buf, int len, unsigned int gup_flags);
|
||||
#endif
|
||||
int copy_remote_mm_str(struct mm_struct *mm, unsigned long addr,
|
||||
void *buf, int len, unsigned int gup_flags);
|
||||
int copy_remote_vm_str(struct task_struct *tsk, 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,
|
||||
|
|
|
|||
|
|
@ -25,6 +25,9 @@
|
|||
struct folio_batch;
|
||||
struct hstate;
|
||||
|
||||
int __copy_remote_mm_str(struct mm_struct *mm, unsigned long addr,
|
||||
void *buf, int len, unsigned int gup_flags);
|
||||
|
||||
struct huge_bootmem_page {
|
||||
struct list_head list;
|
||||
struct hstate *hstate;
|
||||
|
|
|
|||
43
mm/memory.c
43
mm/memory.c
|
|
@ -7326,13 +7326,12 @@ int access_process_vm(struct task_struct *tsk, unsigned long addr,
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(access_process_vm);
|
||||
|
||||
#ifdef CONFIG_BPF_SYSCALL
|
||||
/*
|
||||
* Copy a string from another process's address space as given in mm.
|
||||
* If there is any error return -EFAULT.
|
||||
*/
|
||||
static int __copy_remote_vm_str(struct mm_struct *mm, unsigned long addr,
|
||||
void *buf, int len, unsigned int gup_flags)
|
||||
int __copy_remote_mm_str(struct mm_struct *mm, unsigned long addr,
|
||||
void *buf, int len, unsigned int gup_flags)
|
||||
{
|
||||
void *old_buf = buf;
|
||||
int err = 0;
|
||||
|
|
@ -7408,44 +7407,6 @@ static int __copy_remote_vm_str(struct mm_struct *mm, unsigned long addr,
|
|||
return buf - old_buf;
|
||||
}
|
||||
|
||||
/**
|
||||
* copy_remote_vm_str - copy a string from another process's address space.
|
||||
* @tsk: the task of the target address space
|
||||
* @addr: start address to read from
|
||||
* @buf: destination buffer
|
||||
* @len: number of bytes to copy
|
||||
* @gup_flags: flags modifying lookup behaviour
|
||||
*
|
||||
* The caller must hold a reference on @mm.
|
||||
*
|
||||
* Return: number of bytes copied from @addr (source) to @buf (destination);
|
||||
* not including the trailing NUL. Always guaranteed to leave NUL-terminated
|
||||
* buffer. On any error, return -EFAULT.
|
||||
*/
|
||||
int copy_remote_vm_str(struct task_struct *tsk, unsigned long addr,
|
||||
void *buf, int len, unsigned int gup_flags)
|
||||
{
|
||||
struct mm_struct *mm;
|
||||
int ret;
|
||||
|
||||
if (unlikely(len == 0))
|
||||
return 0;
|
||||
|
||||
mm = get_task_mm(tsk);
|
||||
if (!mm) {
|
||||
*(char *)buf = '\0';
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
ret = __copy_remote_vm_str(mm, addr, buf, len, gup_flags);
|
||||
|
||||
mmput(mm);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(copy_remote_vm_str);
|
||||
#endif /* CONFIG_BPF_SYSCALL */
|
||||
|
||||
/*
|
||||
* Print the name of a VMA.
|
||||
*/
|
||||
|
|
|
|||
43
mm/nommu.c
43
mm/nommu.c
|
|
@ -1741,13 +1741,12 @@ int access_process_vm(struct task_struct *tsk, unsigned long addr, void *buf, in
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(access_process_vm);
|
||||
|
||||
#ifdef CONFIG_BPF_SYSCALL
|
||||
/*
|
||||
* Copy a string from another process's address space as given in mm.
|
||||
* If there is any error return -EFAULT.
|
||||
*/
|
||||
static int __copy_remote_vm_str(struct mm_struct *mm, unsigned long addr,
|
||||
void *buf, int len)
|
||||
int __copy_remote_mm_str(struct mm_struct *mm, unsigned long addr,
|
||||
void *buf, int len, unsigned int gup_flags)
|
||||
{
|
||||
unsigned long addr_end;
|
||||
struct vm_area_struct *vma;
|
||||
|
|
@ -1782,44 +1781,6 @@ static int __copy_remote_vm_str(struct mm_struct *mm, unsigned long addr,
|
|||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* copy_remote_vm_str - copy a string from another process's address space.
|
||||
* @tsk: the task of the target address space
|
||||
* @addr: start address to read from
|
||||
* @buf: destination buffer
|
||||
* @len: number of bytes to copy
|
||||
* @gup_flags: flags modifying lookup behaviour (unused)
|
||||
*
|
||||
* The caller must hold a reference on @mm.
|
||||
*
|
||||
* Return: number of bytes copied from @addr (source) to @buf (destination);
|
||||
* not including the trailing NUL. Always guaranteed to leave NUL-terminated
|
||||
* buffer. On any error, return -EFAULT.
|
||||
*/
|
||||
int copy_remote_vm_str(struct task_struct *tsk, unsigned long addr,
|
||||
void *buf, int len, unsigned int gup_flags)
|
||||
{
|
||||
struct mm_struct *mm;
|
||||
int ret;
|
||||
|
||||
if (unlikely(len == 0))
|
||||
return 0;
|
||||
|
||||
mm = get_task_mm(tsk);
|
||||
if (!mm) {
|
||||
*(char *)buf = '\0';
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
ret = __copy_remote_vm_str(mm, addr, buf, len);
|
||||
|
||||
mmput(mm);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(copy_remote_vm_str);
|
||||
#endif /* CONFIG_BPF_SYSCALL */
|
||||
|
||||
/**
|
||||
* nommu_shrink_inode_mappings - Shrink the shared mappings on an inode
|
||||
* @inode: The inode to check
|
||||
|
|
|
|||
60
mm/util.c
60
mm/util.c
|
|
@ -1061,6 +1061,66 @@ int get_cmdline(struct task_struct *task, char *buffer, int buflen)
|
|||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* copy_remote_mm_str - copy a string from a remote address space.
|
||||
* @mm: the remote address space
|
||||
* @addr: start address to read from
|
||||
* @buf: destination buffer
|
||||
* @len: number of bytes to copy
|
||||
* @gup_flags: flags modifying lookup behaviour
|
||||
*
|
||||
* The caller must hold a reference on @mm.
|
||||
*
|
||||
* Return: number of bytes copied from @addr (source) to @buf (destination),
|
||||
* not including the trailing NUL. If @len is zero, return 0 without accessing
|
||||
* @buf. Otherwise, @buf is always NUL-terminated. On any error, return
|
||||
* -EFAULT.
|
||||
*/
|
||||
int copy_remote_mm_str(struct mm_struct *mm, unsigned long addr,
|
||||
void *buf, int len, unsigned int gup_flags)
|
||||
{
|
||||
if (unlikely(len == 0))
|
||||
return 0;
|
||||
|
||||
return __copy_remote_mm_str(mm, addr, buf, len, gup_flags);
|
||||
}
|
||||
|
||||
/**
|
||||
* copy_remote_vm_str - copy a string from another process's address space.
|
||||
* @tsk: the task of the target address space
|
||||
* @addr: start address to read from
|
||||
* @buf: destination buffer
|
||||
* @len: number of bytes to copy
|
||||
* @gup_flags: flags modifying lookup behaviour
|
||||
*
|
||||
* Return: number of bytes copied from @addr (source) to @buf (destination),
|
||||
* not including the trailing NUL. If @len is zero, return 0 without accessing
|
||||
* @buf. Otherwise, @buf is always NUL-terminated. On any error, return
|
||||
* -EFAULT.
|
||||
*/
|
||||
int copy_remote_vm_str(struct task_struct *tsk, unsigned long addr,
|
||||
void *buf, int len, unsigned int gup_flags)
|
||||
{
|
||||
struct mm_struct *mm;
|
||||
int ret;
|
||||
|
||||
if (unlikely(len == 0))
|
||||
return 0;
|
||||
|
||||
mm = get_task_mm(tsk);
|
||||
if (!mm) {
|
||||
*(char *)buf = '\0';
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
ret = __copy_remote_mm_str(mm, addr, buf, len, gup_flags);
|
||||
|
||||
mmput(mm);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(copy_remote_vm_str);
|
||||
|
||||
int __weak memcmp_pages(struct page *page1, struct page *page2)
|
||||
{
|
||||
char *addr1, *addr2;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user