diff options
| -rw-r--r-- | fs/proc/base.c | 26 | ||||
| -rw-r--r-- | kernel/ptrace.c | 20 |
2 files changed, 23 insertions, 23 deletions
diff --git a/fs/proc/base.c b/fs/proc/base.c index f38da6bda269..773469703c62 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c | |||
| @@ -536,29 +536,15 @@ static int proc_fd_access_allowed(struct inode *inode) | |||
| 536 | { | 536 | { |
| 537 | struct task_struct *task; | 537 | struct task_struct *task; |
| 538 | int allowed = 0; | 538 | int allowed = 0; |
| 539 | /* Allow access to a task's file descriptors if either we may | 539 | /* Allow access to a task's file descriptors if it is us or we |
| 540 | * use ptrace attach to the process and find out that | 540 | * may use ptrace attach to the process and find out that |
| 541 | * information, or if the task cannot possibly be ptraced | 541 | * information. |
| 542 | * allow access if we have the proper capability. | ||
| 543 | */ | 542 | */ |
| 544 | task = get_proc_task(inode); | 543 | task = get_proc_task(inode); |
| 545 | if (task == current) | 544 | if (task) { |
| 546 | allowed = 1; | 545 | allowed = ptrace_may_attach(task); |
| 547 | if (task && !allowed) { | ||
| 548 | int alive; | ||
| 549 | |||
| 550 | task_lock(task); | ||
| 551 | alive = !!task->mm; | ||
| 552 | task_unlock(task); | ||
| 553 | if (alive) | ||
| 554 | /* For a living task obey ptrace_may_attach */ | ||
| 555 | allowed = ptrace_may_attach(task); | ||
| 556 | else | ||
| 557 | /* For a special task simply check the capability */ | ||
| 558 | allowed = capable(CAP_SYS_PTRACE); | ||
| 559 | } | ||
| 560 | if (task) | ||
| 561 | put_task_struct(task); | 546 | put_task_struct(task); |
| 547 | } | ||
| 562 | return allowed; | 548 | return allowed; |
| 563 | } | 549 | } |
| 564 | 550 | ||
diff --git a/kernel/ptrace.c b/kernel/ptrace.c index 921c22ad16e4..6252d2fa2bf3 100644 --- a/kernel/ptrace.c +++ b/kernel/ptrace.c | |||
| @@ -120,8 +120,18 @@ int ptrace_check_attach(struct task_struct *child, int kill) | |||
| 120 | 120 | ||
| 121 | static int may_attach(struct task_struct *task) | 121 | static int may_attach(struct task_struct *task) |
| 122 | { | 122 | { |
| 123 | if (!task->mm) | 123 | /* May we inspect the given task? |
| 124 | return -EPERM; | 124 | * This check is used both for attaching with ptrace |
| 125 | * and for allowing access to sensitive information in /proc. | ||
| 126 | * | ||
| 127 | * ptrace_attach denies several cases that /proc allows | ||
| 128 | * because setting up the necessary parent/child relationship | ||
| 129 | * or halting the specified task is impossible. | ||
| 130 | */ | ||
| 131 | int dumpable = 0; | ||
| 132 | /* Don't let security modules deny introspection */ | ||
| 133 | if (task == current) | ||
| 134 | return 0; | ||
| 125 | if (((current->uid != task->euid) || | 135 | if (((current->uid != task->euid) || |
| 126 | (current->uid != task->suid) || | 136 | (current->uid != task->suid) || |
| 127 | (current->uid != task->uid) || | 137 | (current->uid != task->uid) || |
| @@ -130,7 +140,9 @@ static int may_attach(struct task_struct *task) | |||
| 130 | (current->gid != task->gid)) && !capable(CAP_SYS_PTRACE)) | 140 | (current->gid != task->gid)) && !capable(CAP_SYS_PTRACE)) |
| 131 | return -EPERM; | 141 | return -EPERM; |
| 132 | smp_rmb(); | 142 | smp_rmb(); |
| 133 | if (!task->mm->dumpable && !capable(CAP_SYS_PTRACE)) | 143 | if (task->mm) |
| 144 | dumpable = task->mm->dumpable; | ||
| 145 | if (!dumpable && !capable(CAP_SYS_PTRACE)) | ||
| 134 | return -EPERM; | 146 | return -EPERM; |
| 135 | 147 | ||
| 136 | return security_ptrace(current, task); | 148 | return security_ptrace(current, task); |
| @@ -176,6 +188,8 @@ repeat: | |||
| 176 | goto repeat; | 188 | goto repeat; |
| 177 | } | 189 | } |
| 178 | 190 | ||
| 191 | if (!task->mm) | ||
| 192 | goto bad; | ||
| 179 | /* the same process cannot be attached many times */ | 193 | /* the same process cannot be attached many times */ |
| 180 | if (task->ptrace & PT_PTRACED) | 194 | if (task->ptrace & PT_PTRACED) |
| 181 | goto bad; | 195 | goto bad; |
