[PATCH] use ptrace_get_task_struct in various places
The ptrace_get_task_struct() helper that I added as part of the ptrace consolidation is useful in variety of places that currently opencode it. Switch them to the common helpers. Add a ptrace_traceme() helper that needs to be explicitly called, and simplify the ptrace_get_task_struct() interface. We don't need the request argument now, and we return the task_struct directly, using ERR_PTR() for error returns. It's a bit more code in the callers, but we have two sane routines that do one thing well now. Signed-off-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
This commit is contained in:
committed by
Linus Torvalds
parent
6b34350f49
commit
6b9c7ed848
@@ -265,30 +265,16 @@ do_sys_ptrace(long request, long pid, long addr, long data,
|
|||||||
lock_kernel();
|
lock_kernel();
|
||||||
DBG(DBG_MEM, ("request=%ld pid=%ld addr=0x%lx data=0x%lx\n",
|
DBG(DBG_MEM, ("request=%ld pid=%ld addr=0x%lx data=0x%lx\n",
|
||||||
request, pid, addr, data));
|
request, pid, addr, data));
|
||||||
ret = -EPERM;
|
|
||||||
if (request == PTRACE_TRACEME) {
|
if (request == PTRACE_TRACEME) {
|
||||||
/* are we already being traced? */
|
ret = ptrace_traceme();
|
||||||
if (current->ptrace & PT_PTRACED)
|
|
||||||
goto out_notsk;
|
|
||||||
ret = security_ptrace(current->parent, current);
|
|
||||||
if (ret)
|
|
||||||
goto out_notsk;
|
|
||||||
/* set the ptrace bit in the process ptrace flags. */
|
|
||||||
current->ptrace |= PT_PTRACED;
|
|
||||||
ret = 0;
|
|
||||||
goto out_notsk;
|
goto out_notsk;
|
||||||
}
|
}
|
||||||
if (pid == 1) /* you may not mess with init */
|
|
||||||
goto out_notsk;
|
|
||||||
|
|
||||||
ret = -ESRCH;
|
child = ptrace_get_task_struct(pid);
|
||||||
read_lock(&tasklist_lock);
|
if (IS_ERR(child)) {
|
||||||
child = find_task_by_pid(pid);
|
ret = PTR_ERR(child);
|
||||||
if (child)
|
|
||||||
get_task_struct(child);
|
|
||||||
read_unlock(&tasklist_lock);
|
|
||||||
if (!child)
|
|
||||||
goto out_notsk;
|
goto out_notsk;
|
||||||
|
}
|
||||||
|
|
||||||
if (request == PTRACE_ATTACH) {
|
if (request == PTRACE_ATTACH) {
|
||||||
ret = ptrace_attach(child);
|
ret = ptrace_attach(child);
|
||||||
|
@@ -1761,21 +1761,15 @@ sys32_ptrace (int request, pid_t pid, unsigned int addr, unsigned int data)
|
|||||||
|
|
||||||
lock_kernel();
|
lock_kernel();
|
||||||
if (request == PTRACE_TRACEME) {
|
if (request == PTRACE_TRACEME) {
|
||||||
ret = sys_ptrace(request, pid, addr, data);
|
ret = ptrace_traceme();
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = -ESRCH;
|
child = ptrace_get_task_struct(pid);
|
||||||
read_lock(&tasklist_lock);
|
if (IS_ERR(child)) {
|
||||||
child = find_task_by_pid(pid);
|
ret = PTR_ERR(child);
|
||||||
if (child)
|
|
||||||
get_task_struct(child);
|
|
||||||
read_unlock(&tasklist_lock);
|
|
||||||
if (!child)
|
|
||||||
goto out;
|
goto out;
|
||||||
ret = -EPERM;
|
}
|
||||||
if (pid == 1) /* no messing around with init! */
|
|
||||||
goto out_tsk;
|
|
||||||
|
|
||||||
if (request == PTRACE_ATTACH) {
|
if (request == PTRACE_ATTACH) {
|
||||||
ret = sys_ptrace(request, pid, addr, data);
|
ret = sys_ptrace(request, pid, addr, data);
|
||||||
|
@@ -1422,14 +1422,7 @@ sys_ptrace (long request, pid_t pid, unsigned long addr, unsigned long data)
|
|||||||
lock_kernel();
|
lock_kernel();
|
||||||
ret = -EPERM;
|
ret = -EPERM;
|
||||||
if (request == PTRACE_TRACEME) {
|
if (request == PTRACE_TRACEME) {
|
||||||
/* are we already being traced? */
|
ret = ptrace_traceme();
|
||||||
if (current->ptrace & PT_PTRACED)
|
|
||||||
goto out;
|
|
||||||
ret = security_ptrace(current->parent, current);
|
|
||||||
if (ret)
|
|
||||||
goto out;
|
|
||||||
current->ptrace |= PT_PTRACED;
|
|
||||||
ret = 0;
|
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -762,28 +762,16 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data)
|
|||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
lock_kernel();
|
lock_kernel();
|
||||||
ret = -EPERM;
|
|
||||||
if (request == PTRACE_TRACEME) {
|
if (request == PTRACE_TRACEME) {
|
||||||
/* are we already being traced? */
|
ret = ptrace_traceme();
|
||||||
if (current->ptrace & PT_PTRACED)
|
|
||||||
goto out;
|
|
||||||
/* set the ptrace bit in the process flags. */
|
|
||||||
current->ptrace |= PT_PTRACED;
|
|
||||||
ret = 0;
|
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
ret = -ESRCH;
|
|
||||||
read_lock(&tasklist_lock);
|
|
||||||
child = find_task_by_pid(pid);
|
|
||||||
if (child)
|
|
||||||
get_task_struct(child);
|
|
||||||
read_unlock(&tasklist_lock);
|
|
||||||
if (!child)
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
ret = -EPERM;
|
child = ptrace_get_task_struct(pid);
|
||||||
if (pid == 1) /* you may not mess with init */
|
if (IS_ERR(child)) {
|
||||||
|
ret = PTR_ERR(child);
|
||||||
goto out;
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
if (request == PTRACE_ATTACH) {
|
if (request == PTRACE_ATTACH) {
|
||||||
ret = ptrace_attach(child);
|
ret = ptrace_attach(child);
|
||||||
|
@@ -57,30 +57,16 @@ asmlinkage int sys32_ptrace(int request, int pid, int addr, int data)
|
|||||||
(unsigned long) data);
|
(unsigned long) data);
|
||||||
#endif
|
#endif
|
||||||
lock_kernel();
|
lock_kernel();
|
||||||
ret = -EPERM;
|
|
||||||
if (request == PTRACE_TRACEME) {
|
if (request == PTRACE_TRACEME) {
|
||||||
/* are we already being traced? */
|
ret = ptrace_traceme();
|
||||||
if (current->ptrace & PT_PTRACED)
|
|
||||||
goto out;
|
|
||||||
if ((ret = security_ptrace(current->parent, current)))
|
|
||||||
goto out;
|
|
||||||
/* set the ptrace bit in the process flags. */
|
|
||||||
current->ptrace |= PT_PTRACED;
|
|
||||||
ret = 0;
|
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
ret = -ESRCH;
|
|
||||||
read_lock(&tasklist_lock);
|
|
||||||
child = find_task_by_pid(pid);
|
|
||||||
if (child)
|
|
||||||
get_task_struct(child);
|
|
||||||
read_unlock(&tasklist_lock);
|
|
||||||
if (!child)
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
ret = -EPERM;
|
child = ptrace_get_task_struct(pid);
|
||||||
if (pid == 1) /* you may not mess with init */
|
if (IS_ERR(child)) {
|
||||||
goto out_tsk;
|
ret = PTR_ERR(child);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
if (request == PTRACE_ATTACH) {
|
if (request == PTRACE_ATTACH) {
|
||||||
ret = ptrace_attach(child);
|
ret = ptrace_attach(child);
|
||||||
|
@@ -45,33 +45,19 @@ long compat_sys_ptrace(int request, int pid, unsigned long addr,
|
|||||||
unsigned long data)
|
unsigned long data)
|
||||||
{
|
{
|
||||||
struct task_struct *child;
|
struct task_struct *child;
|
||||||
int ret = -EPERM;
|
int ret;
|
||||||
|
|
||||||
lock_kernel();
|
lock_kernel();
|
||||||
if (request == PTRACE_TRACEME) {
|
if (request == PTRACE_TRACEME) {
|
||||||
/* are we already being traced? */
|
ret = ptrace_traceme();
|
||||||
if (current->ptrace & PT_PTRACED)
|
|
||||||
goto out;
|
|
||||||
ret = security_ptrace(current->parent, current);
|
|
||||||
if (ret)
|
|
||||||
goto out;
|
|
||||||
/* set the ptrace bit in the process flags. */
|
|
||||||
current->ptrace |= PT_PTRACED;
|
|
||||||
ret = 0;
|
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
ret = -ESRCH;
|
|
||||||
read_lock(&tasklist_lock);
|
|
||||||
child = find_task_by_pid(pid);
|
|
||||||
if (child)
|
|
||||||
get_task_struct(child);
|
|
||||||
read_unlock(&tasklist_lock);
|
|
||||||
if (!child)
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
ret = -EPERM;
|
child = ptrace_get_task_struct(pid);
|
||||||
if (pid == 1) /* you may not mess with init */
|
if (IS_ERR(child)) {
|
||||||
goto out_tsk;
|
ret = PTR_ERR(child);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
if (request == PTRACE_ATTACH) {
|
if (request == PTRACE_ATTACH) {
|
||||||
ret = ptrace_attach(child);
|
ret = ptrace_attach(child);
|
||||||
|
@@ -712,35 +712,18 @@ sys_ptrace(long request, long pid, long addr, long data)
|
|||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
lock_kernel();
|
lock_kernel();
|
||||||
|
|
||||||
if (request == PTRACE_TRACEME) {
|
if (request == PTRACE_TRACEME) {
|
||||||
/* are we already being traced? */
|
ret = ptrace_traceme();
|
||||||
ret = -EPERM;
|
|
||||||
if (current->ptrace & PT_PTRACED)
|
|
||||||
goto out;
|
|
||||||
ret = security_ptrace(current->parent, current);
|
|
||||||
if (ret)
|
|
||||||
goto out;
|
|
||||||
/* set the ptrace bit in the process flags. */
|
|
||||||
current->ptrace |= PT_PTRACED;
|
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = -EPERM;
|
child = ptrace_get_task_struct(pid);
|
||||||
if (pid == 1) /* you may not mess with init */
|
if (IS_ERR(child)) {
|
||||||
goto out;
|
ret = PTR_ERR(child);
|
||||||
|
|
||||||
ret = -ESRCH;
|
|
||||||
read_lock(&tasklist_lock);
|
|
||||||
child = find_task_by_pid(pid);
|
|
||||||
if (child)
|
|
||||||
get_task_struct(child);
|
|
||||||
read_unlock(&tasklist_lock);
|
|
||||||
if (!child)
|
|
||||||
goto out;
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
ret = do_ptrace(child, request, addr, data);
|
ret = do_ptrace(child, request, addr, data);
|
||||||
|
|
||||||
put_task_struct(child);
|
put_task_struct(child);
|
||||||
out:
|
out:
|
||||||
unlock_kernel();
|
unlock_kernel();
|
||||||
|
@@ -286,40 +286,17 @@ asmlinkage void do_ptrace(struct pt_regs *regs)
|
|||||||
s, (int) request, (int) pid, addr, data, addr2);
|
s, (int) request, (int) pid, addr, data, addr2);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (request == PTRACE_TRACEME) {
|
if (request == PTRACE_TRACEME) {
|
||||||
int my_ret;
|
ret = ptrace_traceme();
|
||||||
|
|
||||||
/* are we already being traced? */
|
|
||||||
if (current->ptrace & PT_PTRACED) {
|
|
||||||
pt_error_return(regs, EPERM);
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
my_ret = security_ptrace(current->parent, current);
|
|
||||||
if (my_ret) {
|
|
||||||
pt_error_return(regs, -my_ret);
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* set the ptrace bit in the process flags. */
|
|
||||||
current->ptrace |= PT_PTRACED;
|
|
||||||
pt_succ_return(regs, 0);
|
pt_succ_return(regs, 0);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
#ifndef ALLOW_INIT_TRACING
|
|
||||||
if (pid == 1) {
|
|
||||||
/* Can't dork with init. */
|
|
||||||
pt_error_return(regs, EPERM);
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
read_lock(&tasklist_lock);
|
|
||||||
child = find_task_by_pid(pid);
|
|
||||||
if (child)
|
|
||||||
get_task_struct(child);
|
|
||||||
read_unlock(&tasklist_lock);
|
|
||||||
|
|
||||||
if (!child) {
|
child = ptrace_get_task_struct(pid);
|
||||||
pt_error_return(regs, ESRCH);
|
if (IS_ERR(child)) {
|
||||||
|
ret = PTR_ERR(child);
|
||||||
|
pt_error_return(regs, -ret);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -198,39 +198,15 @@ asmlinkage void do_ptrace(struct pt_regs *regs)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (request == PTRACE_TRACEME) {
|
if (request == PTRACE_TRACEME) {
|
||||||
int ret;
|
ret = ptrace_traceme();
|
||||||
|
|
||||||
/* are we already being traced? */
|
|
||||||
if (current->ptrace & PT_PTRACED) {
|
|
||||||
pt_error_return(regs, EPERM);
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
ret = security_ptrace(current->parent, current);
|
|
||||||
if (ret) {
|
|
||||||
pt_error_return(regs, -ret);
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* set the ptrace bit in the process flags. */
|
|
||||||
current->ptrace |= PT_PTRACED;
|
|
||||||
pt_succ_return(regs, 0);
|
pt_succ_return(regs, 0);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
#ifndef ALLOW_INIT_TRACING
|
|
||||||
if (pid == 1) {
|
|
||||||
/* Can't dork with init. */
|
|
||||||
pt_error_return(regs, EPERM);
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
read_lock(&tasklist_lock);
|
|
||||||
child = find_task_by_pid(pid);
|
|
||||||
if (child)
|
|
||||||
get_task_struct(child);
|
|
||||||
read_unlock(&tasklist_lock);
|
|
||||||
|
|
||||||
if (!child) {
|
child = ptrace_get_task_struct(pid);
|
||||||
pt_error_return(regs, ESRCH);
|
if (IS_ERR(child)) {
|
||||||
|
ret = PTR_ERR(child);
|
||||||
|
pt_error_return(regs, -ret);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -196,36 +196,6 @@ static int getreg32(struct task_struct *child, unsigned regno, u32 *val)
|
|||||||
|
|
||||||
#undef R32
|
#undef R32
|
||||||
|
|
||||||
static struct task_struct *find_target(int request, int pid, int *err)
|
|
||||||
{
|
|
||||||
struct task_struct *child;
|
|
||||||
|
|
||||||
*err = -EPERM;
|
|
||||||
if (pid == 1)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
*err = -ESRCH;
|
|
||||||
read_lock(&tasklist_lock);
|
|
||||||
child = find_task_by_pid(pid);
|
|
||||||
if (child)
|
|
||||||
get_task_struct(child);
|
|
||||||
read_unlock(&tasklist_lock);
|
|
||||||
if (child) {
|
|
||||||
*err = -EPERM;
|
|
||||||
if (child->pid == 1)
|
|
||||||
goto out;
|
|
||||||
*err = ptrace_check_attach(child, request == PTRACE_KILL);
|
|
||||||
if (*err < 0)
|
|
||||||
goto out;
|
|
||||||
return child;
|
|
||||||
}
|
|
||||||
out:
|
|
||||||
if (child)
|
|
||||||
put_task_struct(child);
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
asmlinkage long sys32_ptrace(long request, u32 pid, u32 addr, u32 data)
|
asmlinkage long sys32_ptrace(long request, u32 pid, u32 addr, u32 data)
|
||||||
{
|
{
|
||||||
struct task_struct *child;
|
struct task_struct *child;
|
||||||
@@ -254,9 +224,16 @@ asmlinkage long sys32_ptrace(long request, u32 pid, u32 addr, u32 data)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
child = find_target(request, pid, &ret);
|
if (request == PTRACE_TRACEME)
|
||||||
if (!child)
|
return ptrace_traceme();
|
||||||
return ret;
|
|
||||||
|
child = ptrace_get_task_struct(pid);
|
||||||
|
if (IS_ERR(child))
|
||||||
|
return PTR_ERR(child);
|
||||||
|
|
||||||
|
ret = ptrace_check_attach(child, request == PTRACE_KILL);
|
||||||
|
if (ret < 0)
|
||||||
|
goto out;
|
||||||
|
|
||||||
childregs = (struct pt_regs *)(child->thread.rsp0 - sizeof(struct pt_regs));
|
childregs = (struct pt_regs *)(child->thread.rsp0 - sizeof(struct pt_regs));
|
||||||
|
|
||||||
@@ -373,6 +350,7 @@ asmlinkage long sys32_ptrace(long request, u32 pid, u32 addr, u32 data)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
put_task_struct(child);
|
put_task_struct(child);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@@ -80,6 +80,8 @@
|
|||||||
|
|
||||||
|
|
||||||
extern long arch_ptrace(struct task_struct *child, long request, long addr, long data);
|
extern long arch_ptrace(struct task_struct *child, long request, long addr, long data);
|
||||||
|
extern struct task_struct *ptrace_get_task_struct(pid_t pid);
|
||||||
|
extern int ptrace_traceme(void);
|
||||||
extern int ptrace_readdata(struct task_struct *tsk, unsigned long src, char __user *dst, int len);
|
extern int ptrace_readdata(struct task_struct *tsk, unsigned long src, char __user *dst, int len);
|
||||||
extern int ptrace_writedata(struct task_struct *tsk, char __user *src, unsigned long dst, int len);
|
extern int ptrace_writedata(struct task_struct *tsk, char __user *src, unsigned long dst, int len);
|
||||||
extern int ptrace_attach(struct task_struct *tsk);
|
extern int ptrace_attach(struct task_struct *tsk);
|
||||||
|
@@ -408,20 +408,16 @@ int ptrace_request(struct task_struct *child, long request,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef __ARCH_SYS_PTRACE
|
/**
|
||||||
static int ptrace_get_task_struct(long request, long pid,
|
* ptrace_traceme -- helper for PTRACE_TRACEME
|
||||||
struct task_struct **childp)
|
*
|
||||||
|
* Performs checks and sets PT_PTRACED.
|
||||||
|
* Should be used by all ptrace implementations for PTRACE_TRACEME.
|
||||||
|
*/
|
||||||
|
int ptrace_traceme(void)
|
||||||
{
|
{
|
||||||
struct task_struct *child;
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
/*
|
|
||||||
* Callers use child == NULL as an indication to exit early even
|
|
||||||
* when the return value is 0, so make sure it is non-NULL here.
|
|
||||||
*/
|
|
||||||
*childp = NULL;
|
|
||||||
|
|
||||||
if (request == PTRACE_TRACEME) {
|
|
||||||
/*
|
/*
|
||||||
* Are we already being traced?
|
* Are we already being traced?
|
||||||
*/
|
*/
|
||||||
@@ -435,27 +431,39 @@ static int ptrace_get_task_struct(long request, long pid,
|
|||||||
*/
|
*/
|
||||||
current->ptrace |= PT_PTRACED;
|
current->ptrace |= PT_PTRACED;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ptrace_get_task_struct -- grab a task struct reference for ptrace
|
||||||
|
* @pid: process id to grab a task_struct reference of
|
||||||
|
*
|
||||||
|
* This function is a helper for ptrace implementations. It checks
|
||||||
|
* permissions and then grabs a task struct for use of the actual
|
||||||
|
* ptrace implementation.
|
||||||
|
*
|
||||||
|
* Returns the task_struct for @pid or an ERR_PTR() on failure.
|
||||||
|
*/
|
||||||
|
struct task_struct *ptrace_get_task_struct(pid_t pid)
|
||||||
|
{
|
||||||
|
struct task_struct *child;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* You may not mess with init
|
* Tracing init is not allowed.
|
||||||
*/
|
*/
|
||||||
if (pid == 1)
|
if (pid == 1)
|
||||||
return -EPERM;
|
return ERR_PTR(-EPERM);
|
||||||
|
|
||||||
ret = -ESRCH;
|
|
||||||
read_lock(&tasklist_lock);
|
read_lock(&tasklist_lock);
|
||||||
child = find_task_by_pid(pid);
|
child = find_task_by_pid(pid);
|
||||||
if (child)
|
if (child)
|
||||||
get_task_struct(child);
|
get_task_struct(child);
|
||||||
read_unlock(&tasklist_lock);
|
read_unlock(&tasklist_lock);
|
||||||
if (!child)
|
if (!child)
|
||||||
return -ESRCH;
|
return ERR_PTR(-ESRCH);
|
||||||
|
return child;
|
||||||
*childp = child;
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef __ARCH_SYS_PTRACE
|
||||||
asmlinkage long sys_ptrace(long request, long pid, long addr, long data)
|
asmlinkage long sys_ptrace(long request, long pid, long addr, long data)
|
||||||
{
|
{
|
||||||
struct task_struct *child;
|
struct task_struct *child;
|
||||||
@@ -465,9 +473,16 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data)
|
|||||||
* This lock_kernel fixes a subtle race with suid exec
|
* This lock_kernel fixes a subtle race with suid exec
|
||||||
*/
|
*/
|
||||||
lock_kernel();
|
lock_kernel();
|
||||||
ret = ptrace_get_task_struct(request, pid, &child);
|
if (request == PTRACE_TRACEME) {
|
||||||
if (!child)
|
ret = ptrace_traceme();
|
||||||
goto out;
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
child = ptrace_get_task_struct(pid);
|
||||||
|
if (IS_ERR(child)) {
|
||||||
|
ret = PTR_ERR(child);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
if (request == PTRACE_ATTACH) {
|
if (request == PTRACE_ATTACH) {
|
||||||
ret = ptrace_attach(child);
|
ret = ptrace_attach(child);
|
||||||
|
Reference in New Issue
Block a user