diff -Nru a/fs/proc/base.c b/fs/proc/base.c --- a/fs/proc/base.c Tue Apr 22 10:21:00 2003 +++ b/fs/proc/base.c Mon Jul 14 13:10:30 2003 @@ -124,20 +124,56 @@ return result; } +#define MAY_PTRACE(task) \ + (task == current || \ + (task->p_pptr == current && \ + (task->ptrace & PT_PTRACED) && task->state == TASK_STOPPED)) + +static int may_ptrace_attach(struct task_struct *task) +{ + int retval = 0; + + task_lock(task); + + if (((current->uid != task->euid) || + (current->uid != task->suid) || + (current->uid != task->uid) || + (current->gid != task->egid) || + (current->gid != task->sgid) || + (!cap_issubset(task->cap_permitted, current->cap_permitted)) || + (current->gid != task->gid)) && !capable(CAP_SYS_PTRACE)) + goto out; + rmb(); + if (!is_dumpable(task) && !capable(CAP_SYS_PTRACE)) + goto out; + + retval = 1; + +out: + task_unlock(task); + return retval; +} + static int proc_pid_environ(struct task_struct *task, char * buffer) { struct mm_struct *mm; int res = 0; + + if (!may_ptrace_attach(task)) + return -ESRCH; + task_lock(task); mm = task->mm; if (mm) atomic_inc(&mm->mm_users); task_unlock(task); if (mm) { - int len = mm->env_end - mm->env_start; + unsigned int len = mm->env_end - mm->env_start; if (len > PAGE_SIZE) len = PAGE_SIZE; res = access_process_vm(task, mm->env_start, buffer, len, 0); + if (!may_ptrace_attach(task)) + res = -ESRCH; mmput(mm); } return res; @@ -328,10 +364,6 @@ read: proc_info_read, }; -#define MAY_PTRACE(p) \ -(p==current||(p->p_pptr==current&&(p->ptrace & PT_PTRACED)&&p->state==TASK_STOPPED)) - - static int mem_open(struct inode* inode, struct file* file) { file->private_data = (void*)((long)current->self_exec_id); @@ -347,8 +379,7 @@ int copied = 0; struct mm_struct *mm; - - if (!MAY_PTRACE(task)) + if (!MAY_PTRACE(task) || !may_ptrace_attach(task)) return -ESRCH; page = (char *)__get_free_page(GFP_USER); @@ -370,14 +401,13 @@ copied = -EIO; goto out_free; } - while (count > 0) { int this_len, retval; this_len = (count > PAGE_SIZE) ? PAGE_SIZE : count; retval = access_process_vm(task, src, page, this_len, 0); - if (!retval) { + if (!retval || !MAY_PTRACE(task) || !may_ptrace_attach(task)) { if (!copied) copied = -EIO; break; @@ -411,7 +441,7 @@ struct task_struct *task = file->f_dentry->d_inode->u.proc_i.task; unsigned long dst = *ppos; - if (!MAY_PTRACE(task)) + if (!MAY_PTRACE(task) || !may_ptrace_attach(task)) return -ESRCH; page = (char *)__get_free_page(GFP_USER); diff -Nru a/fs/proc/proc_misc.c b/fs/proc/proc_misc.c --- a/fs/proc/proc_misc.c Fri Mar 28 18:11:31 2003 +++ b/fs/proc/proc_misc.c Mon Jul 14 13:10:30 2003 @@ -423,9 +423,9 @@ int count, int *eof, void *data) { extern char saved_command_line[]; - int len; + int len = 0; - len = snprintf(page, count, "%s\n", saved_command_line); + proc_sprintf(page, &off, &len, "%s\n", saved_command_line); return proc_calc_metrics(page, start, off, count, eof, len); } @@ -495,7 +495,8 @@ buf++; p++; count--; read++; } pnt = (char *)prof_buffer + p - sizeof(unsigned int); - copy_to_user(buf,(void *)pnt,count); + if (copy_to_user(buf,(void *)pnt,count)) + return -EFAULT; read += count; *ppos += read; return read;