Skip to content

Commit

Permalink
mm/migrate: avoid possible unnecessary process right check in kernel_…
Browse files Browse the repository at this point in the history
…move_pages()

There is no need to check if this process has the right to modify the
specified process when they are same.  And we could also skip the security
hook call if a process is modifying its own pages.  Add helper function to
handle these.

Suggested-by: Matthew Wilcox <[email protected]>
Signed-off-by: Hongxiang Lou <[email protected]>
Signed-off-by: Miaohe Lin <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Cc: Christopher Lameter <[email protected]>
Link: https://lkml.kernel.org/r/[email protected]
Signed-off-by: Linus Torvalds <[email protected]>
  • Loading branch information
MiaoheLin authored and torvalds committed Oct 18, 2020
1 parent 203e6e5 commit 4dc200c
Showing 1 changed file with 43 additions and 28 deletions.
71 changes: 43 additions & 28 deletions mm/migrate.c
Original file line number Diff line number Diff line change
Expand Up @@ -1864,33 +1864,27 @@ static int do_pages_stat(struct mm_struct *mm, unsigned long nr_pages,
return nr_pages ? -EFAULT : 0;
}

/*
* Move a list of pages in the address space of the currently executing
* process.
*/
static int kernel_move_pages(pid_t pid, unsigned long nr_pages,
const void __user * __user *pages,
const int __user *nodes,
int __user *status, int flags)
static struct mm_struct *find_mm_struct(pid_t pid, nodemask_t *mem_nodes)
{
struct task_struct *task;
struct mm_struct *mm;
int err;
nodemask_t task_nodes;

/* Check flags */
if (flags & ~(MPOL_MF_MOVE|MPOL_MF_MOVE_ALL))
return -EINVAL;

if ((flags & MPOL_MF_MOVE_ALL) && !capable(CAP_SYS_NICE))
return -EPERM;
/*
* There is no need to check if current process has the right to modify
* the specified process when they are same.
*/
if (!pid) {
mmget(current->mm);
*mem_nodes = cpuset_mems_allowed(current);
return current->mm;
}

/* Find the mm_struct */
rcu_read_lock();
task = pid ? find_task_by_vpid(pid) : current;
task = find_task_by_vpid(pid);
if (!task) {
rcu_read_unlock();
return -ESRCH;
return ERR_PTR(-ESRCH);
}
get_task_struct(task);

Expand All @@ -1900,22 +1894,47 @@ static int kernel_move_pages(pid_t pid, unsigned long nr_pages,
*/
if (!ptrace_may_access(task, PTRACE_MODE_READ_REALCREDS)) {
rcu_read_unlock();
err = -EPERM;
mm = ERR_PTR(-EPERM);
goto out;
}
rcu_read_unlock();

err = security_task_movememory(task);
if (err)
mm = ERR_PTR(security_task_movememory(task));
if (IS_ERR(mm))
goto out;

task_nodes = cpuset_mems_allowed(task);
*mem_nodes = cpuset_mems_allowed(task);
mm = get_task_mm(task);
out:
put_task_struct(task);

if (!mm)
mm = ERR_PTR(-EINVAL);
return mm;
}

/*
* Move a list of pages in the address space of the currently executing
* process.
*/
static int kernel_move_pages(pid_t pid, unsigned long nr_pages,
const void __user * __user *pages,
const int __user *nodes,
int __user *status, int flags)
{
struct mm_struct *mm;
int err;
nodemask_t task_nodes;

/* Check flags */
if (flags & ~(MPOL_MF_MOVE|MPOL_MF_MOVE_ALL))
return -EINVAL;

if ((flags & MPOL_MF_MOVE_ALL) && !capable(CAP_SYS_NICE))
return -EPERM;

mm = find_mm_struct(pid, &task_nodes);
if (IS_ERR(mm))
return PTR_ERR(mm);

if (nodes)
err = do_pages_move(mm, task_nodes, nr_pages, pages,
nodes, status, flags);
Expand All @@ -1924,10 +1943,6 @@ static int kernel_move_pages(pid_t pid, unsigned long nr_pages,

mmput(mm);
return err;

out:
put_task_struct(task);
return err;
}

SYSCALL_DEFINE6(move_pages, pid_t, pid, unsigned long, nr_pages,
Expand Down

0 comments on commit 4dc200c

Please sign in to comment.