Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1524498 > unrolled thread
| Started by | ebiederm@xmission.com (Eric W. Biederman) |
|---|---|
| First post | 2016-11-17 18:10 +0100 |
| Last post | 2016-11-19 19:50 +0100 |
| Articles | 20 on this page of 25 — 4 participants |
Back to article view | Back to linux.kernel
This discussion starts older than the indexed window; earlier articles aren't shown. The article labeled Started by
below is the oldest one visible, not the original post.
[REVIEW][PATCH 0/3] Fixing ptrace vs exec vs userns interactions ebiederm@xmission.com (Eric W. Biederman) - 2016-11-17 18:10 +0100
[REVIEW][PATCH 1/3] ptrace: Capture the ptracer's creds not PT_PTRACE_CAP ebiederm@xmission.com (Eric W. Biederman) - 2016-11-17 18:20 +0100
Re: [REVIEW][PATCH 1/3] ptrace: Capture the ptracer's creds not PT_PTRACE_CAP Kees Cook <keescook@chromium.org> - 2016-11-18 00:20 +0100
Re: [REVIEW][PATCH 1/3] ptrace: Capture the ptracer's creds not PT_PTRACE_CAP ebiederm@xmission.com (Eric W. Biederman) - 2016-11-18 20:00 +0100
Re: [REVIEW][PATCH 1/3] ptrace: Capture the ptracer's creds not PT_PTRACE_CAP Andy Lutomirski <luto@amacapital.net> - 2016-11-18 00:30 +0100
Re: [REVIEW][PATCH 1/3] ptrace: Capture the ptracer's creds not PT_PTRACE_CAP ebiederm@xmission.com (Eric W. Biederman) - 2016-11-18 00:50 +0100
[REVIEW][PATCH 3/3] exec: Ensure mm->user_ns contains the execed files ebiederm@xmission.com (Eric W. Biederman) - 2016-11-17 18:20 +0100
[REVIEW][PATCH 2/3] exec: Don't allow ptracing an exec of an unreadable file ebiederm@xmission.com (Eric W. Biederman) - 2016-11-17 18:20 +0100
Re: [REVIEW][PATCH 2/3] exec: Don't allow ptracing an exec of an unreadable file Willy Tarreau <w@1wt.eu> - 2016-11-17 21:50 +0100
Re: [REVIEW][PATCH 2/3] exec: Don't allow ptracing an exec of an unreadable file Kees Cook <keescook@chromium.org> - 2016-11-17 22:10 +0100
Re: [REVIEW][PATCH 2/3] exec: Don't allow ptracing an exec of an unreadable file Willy Tarreau <w@1wt.eu> - 2016-11-17 22:40 +0100
Re: [REVIEW][PATCH 2/3] exec: Don't allow ptracing an exec of an unreadable file ebiederm@xmission.com (Eric W. Biederman) - 2016-11-17 23:00 +0100
[REVIEW][PATCH 2/3] ptrace: Don't allow accessing an undumpable mm ebiederm@xmission.com (Eric W. Biederman) - 2016-11-18 00:00 +0100
Re: [REVIEW][PATCH 2/3] ptrace: Don't allow accessing an undumpable mm Kees Cook <keescook@chromium.org> - 2016-11-18 00:20 +0100
Re: [REVIEW][PATCH 2/3] exec: Don't allow ptracing an exec of an unreadable file Andy Lutomirski <luto@amacapital.net> - 2016-11-18 00:30 +0100
Re: [REVIEW][PATCH 2/3] exec: Don't allow ptracing an exec of an unreadable file Andy Lutomirski <luto@amacapital.net> - 2016-11-18 00:40 +0100
Re: [REVIEW][PATCH 2/3] exec: Don't allow ptracing an exec of an unreadable file ebiederm@xmission.com (Eric W. Biederman) - 2016-11-18 01:00 +0100
Re: [REVIEW][PATCH 2/3] exec: Don't allow ptracing an exec of an unreadable file Andy Lutomirski <luto@amacapital.net> - 2016-11-18 01:20 +0100
Re: [REVIEW][PATCH 2/3] exec: Don't allow ptracing an exec of an unreadable file ebiederm@xmission.com (Eric W. Biederman) - 2016-11-18 01:40 +0100
Re: [REVIEW][PATCH 0/3] Fixing ptrace vs exec vs userns interactions Willy Tarreau <w@1wt.eu> - 2016-11-19 08:20 +0100
Re: [REVIEW][PATCH 0/3] Fixing ptrace vs exec vs userns interactions Willy Tarreau <w@1wt.eu> - 2016-11-19 10:30 +0100
Re: [REVIEW][PATCH 0/3] Fixing ptrace vs exec vs userns interactions Willy Tarreau <w@1wt.eu> - 2016-11-19 10:40 +0100
Re: [REVIEW][PATCH 0/3] Fixing ptrace vs exec vs userns interactions ebiederm@xmission.com (Eric W. Biederman) - 2016-11-19 19:50 +0100
Re: [REVIEW][PATCH 0/3] Fixing ptrace vs exec vs userns interactions ebiederm@xmission.com (Eric W. Biederman) - 2016-11-19 19:40 +0100
Re: [REVIEW][PATCH 0/3] Fixing ptrace vs exec vs userns interactions ebiederm@xmission.com (Eric W. Biederman) - 2016-11-19 19:50 +0100
Page 1 of 2 [1] 2 Next page →
| From | ebiederm@xmission.com (Eric W. Biederman) |
|---|---|
| Date | 2016-11-17 18:10 +0100 |
| Subject | [REVIEW][PATCH 0/3] Fixing ptrace vs exec vs userns interactions |
| Message-ID | <sEyme-3v8-89@gated-at.bofh.it> |
With everyone heading to Kernel Summit and Plumbers I put this set of
patches down temporarily. Now is the time to take it back up and to
make certain I am not missing something stupid in this set of patches.
There are other issues in this area as well, but these are the pieces
that I can see clearly, and have tested fixes for.
Andy as to your criticism about using strace sudo I can't possibly see
how that is effective or useful. Under strace sudo won't run as root
today, and will immediately exit because it is not root. Furthermore
the only place I can find non-readable executables is people hardening
suid root executables so they are more difficult to trace. So I
definitely think we should honor the unix permissions and people's
expressed wishes.
Eric W. Biederman (3):
ptrace: Capture the ptracer's creds not PT_PTRACE_CAP
exec: Don't allow ptracing an exec of an unreadable file
exec: Ensure mm->user_ns contains the execed files
fs/exec.c | 26 +++++++++++++++++++++++---
include/linux/capability.h | 2 ++
include/linux/ptrace.h | 1 -
include/linux/sched.h | 1 +
kernel/capability.c | 36 ++++++++++++++++++++++++++++++++++--
kernel/ptrace.c | 12 +++++++-----
6 files changed, 67 insertions(+), 11 deletions(-)
[toc] | [next] | [standalone]
| From | ebiederm@xmission.com (Eric W. Biederman) |
|---|---|
| Date | 2016-11-17 18:20 +0100 |
| Subject | [REVIEW][PATCH 1/3] ptrace: Capture the ptracer's creds not PT_PTRACE_CAP |
| Message-ID | <sEyvU-3yz-25@gated-at.bofh.it> |
| In reply to | #1524498 |
When the flag PT_PTRACE_CAP was added the PTRACE_TRACEME path was
overlooked. This can result in incorrect behavior when an application
like strace traces an exec of a setuid executable.
Further PT_PTRACE_CAP does not have enough information for making good
security decisions as it does not report which user namespace the
capability is in. This has already allowed one mistake through
insufficient granulariy.
I found this issue when I was testing another corner case of exec and
discovered that I could not get strace to set PT_PTRACE_CAP even when
running strace as root with a full set of caps.
This change fixes the above issue with strace allowing stracing as
root a setuid executable without disabling setuid. More fundamentaly
this change allows what is allowable at all times, by using the correct
information in it's decision.
Cc: stable@vger.kernel.org
Fixes: 4214e42f96d4 ("v2.4.9.11 -> v2.4.9.12")
Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
---
fs/exec.c | 2 +-
include/linux/capability.h | 1 +
include/linux/ptrace.h | 1 -
include/linux/sched.h | 1 +
kernel/capability.c | 20 ++++++++++++++++++++
kernel/ptrace.c | 12 +++++++-----
6 files changed, 30 insertions(+), 7 deletions(-)
diff --git a/fs/exec.c b/fs/exec.c
index 6fcfb3f7b137..fdec760bfac3 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -1401,7 +1401,7 @@ static void check_unsafe_exec(struct linux_binprm *bprm)
unsigned n_fs;
if (p->ptrace) {
- if (p->ptrace & PT_PTRACE_CAP)
+ if (ptracer_capable(p, current_user_ns()))
bprm->unsafe |= LSM_UNSAFE_PTRACE_CAP;
else
bprm->unsafe |= LSM_UNSAFE_PTRACE;
diff --git a/include/linux/capability.h b/include/linux/capability.h
index dbc21c719ce6..d6088e2a7668 100644
--- a/include/linux/capability.h
+++ b/include/linux/capability.h
@@ -242,6 +242,7 @@ static inline bool ns_capable_noaudit(struct user_namespace *ns, int cap)
#endif /* CONFIG_MULTIUSER */
extern bool capable_wrt_inode_uidgid(const struct inode *inode, int cap);
extern bool file_ns_capable(const struct file *file, struct user_namespace *ns, int cap);
+extern bool ptracer_capable(struct task_struct *tsk, struct user_namespace *ns);
/* audit system wants to get cap info from files as well */
extern int get_vfs_caps_from_disk(const struct dentry *dentry, struct cpu_vfs_cap_data *cpu_caps);
diff --git a/include/linux/ptrace.h b/include/linux/ptrace.h
index 504c98a278d4..e13bfdf7f314 100644
--- a/include/linux/ptrace.h
+++ b/include/linux/ptrace.h
@@ -19,7 +19,6 @@
#define PT_SEIZED 0x00010000 /* SEIZE used, enable new behavior */
#define PT_PTRACED 0x00000001
#define PT_DTRACE 0x00000002 /* delayed trace (used on m68k, i386) */
-#define PT_PTRACE_CAP 0x00000004 /* ptracer can follow suid-exec */
#define PT_OPT_FLAG_SHIFT 3
/* PT_TRACE_* event enable flags */
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 348f51b0ec92..8fe58255d219 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -1656,6 +1656,7 @@ struct task_struct {
struct list_head cpu_timers[3];
/* process credentials */
+ const struct cred __rcu *ptracer_cred; /* Tracer's dredentials at attach */
const struct cred __rcu *real_cred; /* objective and real subjective task
* credentials (COW) */
const struct cred __rcu *cred; /* effective (overridable) subjective task
diff --git a/kernel/capability.c b/kernel/capability.c
index 00411c82dac5..dfa0e4528b0b 100644
--- a/kernel/capability.c
+++ b/kernel/capability.c
@@ -473,3 +473,23 @@ bool capable_wrt_inode_uidgid(const struct inode *inode, int cap)
kgid_has_mapping(ns, inode->i_gid);
}
EXPORT_SYMBOL(capable_wrt_inode_uidgid);
+
+/**
+ * ptracer_capable - Determine if the ptracer holds CAP_SYS_PTRACE in the namespace
+ * @tsk: The task that may be ptraced
+ * @ns: The user namespace to search for CAP_SYS_PTRACE in
+ *
+ * Return true if the task that is ptracing the current task had CAP_SYS_PTRACE
+ * in the specified user namespace.
+ */
+bool ptracer_capable(struct task_struct *tsk, struct user_namespace *ns)
+{
+ int ret = 0; /* An absent tracer adds no restrictions */
+ const struct cred *cred;
+ rcu_read_lock();
+ cred = rcu_dereference(tsk->ptracer_cred);
+ if (cred)
+ ret = security_capable_noaudit(cred, ns, CAP_SYS_PTRACE);
+ rcu_read_unlock();
+ return (ret == 0);
+}
diff --git a/kernel/ptrace.c b/kernel/ptrace.c
index 44a25a1e6e83..982505497680 100644
--- a/kernel/ptrace.c
+++ b/kernel/ptrace.c
@@ -39,6 +39,9 @@ void __ptrace_link(struct task_struct *child, struct task_struct *new_parent)
BUG_ON(!list_empty(&child->ptrace_entry));
list_add(&child->ptrace_entry, &new_parent->ptraced);
child->parent = new_parent;
+ rcu_read_lock();
+ child->ptracer_cred = get_cred(__task_cred(new_parent));
+ rcu_read_unlock();
}
/**
@@ -71,12 +74,16 @@ void __ptrace_link(struct task_struct *child, struct task_struct *new_parent)
*/
void __ptrace_unlink(struct task_struct *child)
{
+ const struct cred *old_cred;
BUG_ON(!child->ptrace);
clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
child->parent = child->real_parent;
list_del_init(&child->ptrace_entry);
+ old_cred = child->ptracer_cred;
+ child->ptracer_cred = NULL;
+ put_cred(old_cred);
spin_lock(&child->sighand->siglock);
child->ptrace = 0;
@@ -326,11 +333,6 @@ static int ptrace_attach(struct task_struct *task, long request,
task_lock(task);
retval = __ptrace_may_access(task, PTRACE_MODE_ATTACH_REALCREDS);
- if (!retval) {
- struct mm_struct *mm = task->mm;
- if (mm && ns_capable(mm->user_ns, CAP_SYS_PTRACE))
- flags |= PT_PTRACE_CAP;
- }
task_unlock(task);
if (retval)
goto unlock_creds;
--
2.10.1
[toc] | [prev] | [next] | [standalone]
| From | Kees Cook <keescook@chromium.org> |
|---|---|
| Date | 2016-11-18 00:20 +0100 |
| Subject | Re: [REVIEW][PATCH 1/3] ptrace: Capture the ptracer's creds not PT_PTRACE_CAP |
| Message-ID | <sEE8i-7lb-15@gated-at.bofh.it> |
| In reply to | #1524521 |
On Thu, Nov 17, 2016 at 9:05 AM, Eric W. Biederman
<ebiederm@xmission.com> wrote:
>
> When the flag PT_PTRACE_CAP was added the PTRACE_TRACEME path was
> overlooked. This can result in incorrect behavior when an application
> like strace traces an exec of a setuid executable.
>
> Further PT_PTRACE_CAP does not have enough information for making good
> security decisions as it does not report which user namespace the
> capability is in. This has already allowed one mistake through
> insufficient granulariy.
>
> I found this issue when I was testing another corner case of exec and
> discovered that I could not get strace to set PT_PTRACE_CAP even when
> running strace as root with a full set of caps.
>
> This change fixes the above issue with strace allowing stracing as
> root a setuid executable without disabling setuid. More fundamentaly
> this change allows what is allowable at all times, by using the correct
> information in it's decision.
>
> Cc: stable@vger.kernel.org
> Fixes: 4214e42f96d4 ("v2.4.9.11 -> v2.4.9.12")
> Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
> ---
> [...]
> diff --git a/include/linux/sched.h b/include/linux/sched.h
> index 348f51b0ec92..8fe58255d219 100644
> --- a/include/linux/sched.h
> +++ b/include/linux/sched.h
> @@ -1656,6 +1656,7 @@ struct task_struct {
> struct list_head cpu_timers[3];
>
> /* process credentials */
> + const struct cred __rcu *ptracer_cred; /* Tracer's dredentials at attach */
Typo: credentials.
-Kees
--
Kees Cook
Nexus Security
[toc] | [prev] | [next] | [standalone]
| From | ebiederm@xmission.com (Eric W. Biederman) |
|---|---|
| Date | 2016-11-18 20:00 +0100 |
| Subject | Re: [REVIEW][PATCH 1/3] ptrace: Capture the ptracer's creds not PT_PTRACE_CAP |
| Message-ID | <sEWye-2tW-37@gated-at.bofh.it> |
| In reply to | #1524872 |
Kees Cook <keescook@chromium.org> writes:
> On Thu, Nov 17, 2016 at 9:05 AM, Eric W. Biederman
> <ebiederm@xmission.com> wrote:
>>
>> When the flag PT_PTRACE_CAP was added the PTRACE_TRACEME path was
>> overlooked. This can result in incorrect behavior when an application
>> like strace traces an exec of a setuid executable.
>>
>> Further PT_PTRACE_CAP does not have enough information for making good
>> security decisions as it does not report which user namespace the
>> capability is in. This has already allowed one mistake through
>> insufficient granulariy.
>>
>> I found this issue when I was testing another corner case of exec and
>> discovered that I could not get strace to set PT_PTRACE_CAP even when
>> running strace as root with a full set of caps.
>>
>> This change fixes the above issue with strace allowing stracing as
>> root a setuid executable without disabling setuid. More fundamentaly
>> this change allows what is allowable at all times, by using the correct
>> information in it's decision.
>>
>> Cc: stable@vger.kernel.org
>> Fixes: 4214e42f96d4 ("v2.4.9.11 -> v2.4.9.12")
>> Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
>> ---
>> [...]
>> diff --git a/include/linux/sched.h b/include/linux/sched.h
>> index 348f51b0ec92..8fe58255d219 100644
>> --- a/include/linux/sched.h
>> +++ b/include/linux/sched.h
>> @@ -1656,6 +1656,7 @@ struct task_struct {
>> struct list_head cpu_timers[3];
>>
>> /* process credentials */
>> + const struct cred __rcu *ptracer_cred; /* Tracer's dredentials at attach */
>
> Typo: credentials.
Thank you, fixed.
Eric
[toc] | [prev] | [next] | [standalone]
| From | Andy Lutomirski <luto@amacapital.net> |
|---|---|
| Date | 2016-11-18 00:30 +0100 |
| Subject | Re: [REVIEW][PATCH 1/3] ptrace: Capture the ptracer's creds not PT_PTRACE_CAP |
| Message-ID | <sEEhX-7on-7@gated-at.bofh.it> |
| In reply to | #1524521 |
On Thu, Nov 17, 2016 at 9:05 AM, Eric W. Biederman
<ebiederm@xmission.com> wrote:
>
> When the flag PT_PTRACE_CAP was added the PTRACE_TRACEME path was
> overlooked. This can result in incorrect behavior when an application
> like strace traces an exec of a setuid executable.
>
> Further PT_PTRACE_CAP does not have enough information for making good
> security decisions as it does not report which user namespace the
> capability is in. This has already allowed one mistake through
> insufficient granulariy.
>
> I found this issue when I was testing another corner case of exec and
> discovered that I could not get strace to set PT_PTRACE_CAP even when
> running strace as root with a full set of caps.
>
> This change fixes the above issue with strace allowing stracing as
> root a setuid executable without disabling setuid. More fundamentaly
> this change allows what is allowable at all times, by using the correct
> information in it's decision.
>
> Cc: stable@vger.kernel.org
> Fixes: 4214e42f96d4 ("v2.4.9.11 -> v2.4.9.12")
> Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
> ---
> fs/exec.c | 2 +-
> include/linux/capability.h | 1 +
> include/linux/ptrace.h | 1 -
> include/linux/sched.h | 1 +
> kernel/capability.c | 20 ++++++++++++++++++++
> kernel/ptrace.c | 12 +++++++-----
> 6 files changed, 30 insertions(+), 7 deletions(-)
>
> diff --git a/fs/exec.c b/fs/exec.c
> index 6fcfb3f7b137..fdec760bfac3 100644
> --- a/fs/exec.c
> +++ b/fs/exec.c
> @@ -1401,7 +1401,7 @@ static void check_unsafe_exec(struct linux_binprm *bprm)
> unsigned n_fs;
>
> if (p->ptrace) {
> - if (p->ptrace & PT_PTRACE_CAP)
> + if (ptracer_capable(p, current_user_ns()))
IIRC PT_PTRACE_CAP was added to prevent TOCTOU races. What prevents
that type of race now? For that matter, what guarantees that we've
already switched to new creds here and will continue to do so in the
future?
--Andy
[toc] | [prev] | [next] | [standalone]
| From | ebiederm@xmission.com (Eric W. Biederman) |
|---|---|
| Date | 2016-11-18 00:50 +0100 |
| Subject | Re: [REVIEW][PATCH 1/3] ptrace: Capture the ptracer's creds not PT_PTRACE_CAP |
| Message-ID | <sEEBk-7vt-13@gated-at.bofh.it> |
| In reply to | #1524877 |
Andy Lutomirski <luto@amacapital.net> writes:
> On Thu, Nov 17, 2016 at 9:05 AM, Eric W. Biederman
> <ebiederm@xmission.com> wrote:
>>
>> When the flag PT_PTRACE_CAP was added the PTRACE_TRACEME path was
>> overlooked. This can result in incorrect behavior when an application
>> like strace traces an exec of a setuid executable.
>>
>> Further PT_PTRACE_CAP does not have enough information for making good
>> security decisions as it does not report which user namespace the
>> capability is in. This has already allowed one mistake through
>> insufficient granulariy.
>>
>> I found this issue when I was testing another corner case of exec and
>> discovered that I could not get strace to set PT_PTRACE_CAP even when
>> running strace as root with a full set of caps.
>>
>> This change fixes the above issue with strace allowing stracing as
>> root a setuid executable without disabling setuid. More fundamentaly
>> this change allows what is allowable at all times, by using the correct
>> information in it's decision.
>>
>> Cc: stable@vger.kernel.org
>> Fixes: 4214e42f96d4 ("v2.4.9.11 -> v2.4.9.12")
>> Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
>> ---
>> fs/exec.c | 2 +-
>> include/linux/capability.h | 1 +
>> include/linux/ptrace.h | 1 -
>> include/linux/sched.h | 1 +
>> kernel/capability.c | 20 ++++++++++++++++++++
>> kernel/ptrace.c | 12 +++++++-----
>> 6 files changed, 30 insertions(+), 7 deletions(-)
>>
>> diff --git a/fs/exec.c b/fs/exec.c
>> index 6fcfb3f7b137..fdec760bfac3 100644
>> --- a/fs/exec.c
>> +++ b/fs/exec.c
>> @@ -1401,7 +1401,7 @@ static void check_unsafe_exec(struct linux_binprm *bprm)
>> unsigned n_fs;
>>
>> if (p->ptrace) {
>> - if (p->ptrace & PT_PTRACE_CAP)
>> + if (ptracer_capable(p, current_user_ns()))
>
> IIRC PT_PTRACE_CAP was added to prevent TOCTOU races. What prevents
> that type of race now? For that matter, what guarantees that we've
> already switched to new creds here and will continue to do so in the
> future?
Because instead of capturing a single bit we now capture tracers
entire credentials in tsk->ptracer_cred. As such tsk->ptracer_cred
never changes except when ptracing begins or ends, and we remain
safe for TOCTOU races.
We do hold cred_guard_mutex here so that guarantees we get a new
ptracer. So the worst that can happen here is our tracer detaches
and ptracer_capable will uncondintionally return true.
Eric
[toc] | [prev] | [next] | [standalone]
| From | ebiederm@xmission.com (Eric W. Biederman) |
|---|---|
| Date | 2016-11-17 18:20 +0100 |
| Subject | [REVIEW][PATCH 3/3] exec: Ensure mm->user_ns contains the execed files |
| Message-ID | <sEyvU-3yz-27@gated-at.bofh.it> |
| In reply to | #1524498 |
When the user namespace support was merged the need to prevent
ptrace from revealing the contents of an unreadable executable
was overlooked.
Correct this oversight by ensuring that the executed file
or files are in mm->user_ns, by adjusting mm->user_ns.
Use the new function privileged_wrt_inode_uidgid to see if
the executable is a member of the user namespace, and as such
if having CAP_SYS_PTRACE in the user namespace should allow
tracing the executable. If not update mm->user_ns to
the parent user namespace until an appropriate parent is found.
Cc: stable@vger.kernel.org
Reported-by: Jann Horn <jann@thejh.net>
Fixes: 9e4a36ece652 ("userns: Fail exec for suid and sgid binaries with ids outside our user namespace.")
Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
---
fs/exec.c | 16 +++++++++++++++-
include/linux/capability.h | 1 +
kernel/capability.c | 16 ++++++++++++++--
3 files changed, 30 insertions(+), 3 deletions(-)
diff --git a/fs/exec.c b/fs/exec.c
index de107f74e055..4ce5d68d6f5b 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -1275,8 +1275,22 @@ EXPORT_SYMBOL(flush_old_exec);
void would_dump(struct linux_binprm *bprm, struct file *file)
{
- if (inode_permission(file_inode(file), MAY_READ) < 0)
+ struct inode *inode = file_inode(file);
+ if (inode_permission(inode, MAY_READ) < 0) {
+ struct user_namespace *old, *user_ns;
bprm->interp_flags |= BINPRM_FLAGS_ENFORCE_NONDUMP;
+
+ /* Ensure mm->user_ns contains the executable */
+ user_ns = old = bprm->mm->user_ns;
+ while ((user_ns != &init_user_ns) &&
+ !privileged_wrt_inode_uidgid(user_ns, inode))
+ user_ns = user_ns->parent;
+
+ if (old != user_ns) {
+ bprm->mm->user_ns = get_user_ns(user_ns);
+ put_user_ns(old);
+ }
+ }
}
EXPORT_SYMBOL(would_dump);
diff --git a/include/linux/capability.h b/include/linux/capability.h
index d6088e2a7668..6ffb67e10c06 100644
--- a/include/linux/capability.h
+++ b/include/linux/capability.h
@@ -240,6 +240,7 @@ static inline bool ns_capable_noaudit(struct user_namespace *ns, int cap)
return true;
}
#endif /* CONFIG_MULTIUSER */
+extern bool privileged_wrt_inode_uidgid(struct user_namespace *ns, const struct inode *inode);
extern bool capable_wrt_inode_uidgid(const struct inode *inode, int cap);
extern bool file_ns_capable(const struct file *file, struct user_namespace *ns, int cap);
extern bool ptracer_capable(struct task_struct *tsk, struct user_namespace *ns);
diff --git a/kernel/capability.c b/kernel/capability.c
index dfa0e4528b0b..4984e1f552eb 100644
--- a/kernel/capability.c
+++ b/kernel/capability.c
@@ -457,6 +457,19 @@ bool file_ns_capable(const struct file *file, struct user_namespace *ns,
EXPORT_SYMBOL(file_ns_capable);
/**
+ * privileged_wrt_inode_uidgid - Do capabilities in the namespace work over the inode?
+ * @ns: The user namespace in question
+ * @inode: The inode in question
+ *
+ * Return true if the inode uid and gid are within the namespace.
+ */
+bool privileged_wrt_inode_uidgid(struct user_namespace *ns, const struct inode *inode)
+{
+ return kuid_has_mapping(ns, inode->i_uid) &&
+ kgid_has_mapping(ns, inode->i_gid);
+}
+
+/**
* capable_wrt_inode_uidgid - Check nsown_capable and uid and gid mapped
* @inode: The inode in question
* @cap: The capability in question
@@ -469,8 +482,7 @@ bool capable_wrt_inode_uidgid(const struct inode *inode, int cap)
{
struct user_namespace *ns = current_user_ns();
- return ns_capable(ns, cap) && kuid_has_mapping(ns, inode->i_uid) &&
- kgid_has_mapping(ns, inode->i_gid);
+ return ns_capable(ns, cap) && privileged_wrt_inode_uidgid(ns, inode);
}
EXPORT_SYMBOL(capable_wrt_inode_uidgid);
--
2.10.1
[toc] | [prev] | [next] | [standalone]
| From | ebiederm@xmission.com (Eric W. Biederman) |
|---|---|
| Date | 2016-11-17 18:20 +0100 |
| Subject | [REVIEW][PATCH 2/3] exec: Don't allow ptracing an exec of an unreadable file |
| Message-ID | <sEyvV-3yz-73@gated-at.bofh.it> |
| In reply to | #1524498 |
It is the reasonable expectation that if an executable file is not
readable there will be no way for a user without special privileges to
read the file. This is enforced in ptrace_attach but if we are
already attached there is no enforcement if a readonly executable
is exec'd.
Therefore do the simple thing and if there is a non-dumpable
executable that we are tracing without privilege fail to exec it.
Fixes: v1.0
Cc: stable@vger.kernel.org
Reported-by: Andy Lutomirski <luto@amacapital.net>
Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
---
fs/exec.c | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/fs/exec.c b/fs/exec.c
index fdec760bfac3..de107f74e055 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -1230,6 +1230,11 @@ int flush_old_exec(struct linux_binprm * bprm)
{
int retval;
+ /* Fail if the tracer can't read the executable */
+ if ((bprm->interp_flags & BINPRM_FLAGS_ENFORCE_NONDUMP) &&
+ !ptracer_capable(current, bprm->mm->user_ns))
+ return -EPERM;
+
/*
* Make sure we have a private signal table and that
* we are unassociated from the previous thread group.
@@ -1301,7 +1306,6 @@ void setup_new_exec(struct linux_binprm * bprm)
!gid_eq(bprm->cred->gid, current_egid())) {
current->pdeath_signal = 0;
} else {
- would_dump(bprm, bprm->file);
if (bprm->interp_flags & BINPRM_FLAGS_ENFORCE_NONDUMP)
set_dumpable(current->mm, suid_dumpable);
}
@@ -1736,6 +1740,8 @@ static int do_execveat_common(int fd, struct filename *filename,
if (retval < 0)
goto out;
+ would_dump(bprm, bprm->file);
+
retval = exec_binprm(bprm);
if (retval < 0)
goto out;
--
2.10.1
[toc] | [prev] | [next] | [standalone]
| From | Willy Tarreau <w@1wt.eu> |
|---|---|
| Date | 2016-11-17 21:50 +0100 |
| Subject | Re: [REVIEW][PATCH 2/3] exec: Don't allow ptracing an exec of an unreadable file |
| Message-ID | <sEBN8-5Dy-15@gated-at.bofh.it> |
| In reply to | #1524539 |
On Thu, Nov 17, 2016 at 11:08:22AM -0600, Eric W. Biederman wrote: > > It is the reasonable expectation that if an executable file is not > readable there will be no way for a user without special privileges to > read the file. This is enforced in ptrace_attach but if we are > already attached there is no enforcement if a readonly executable > is exec'd. I'm really scared by this Eric. At least you want to make it a hardening option that can be disabled at run time, otherwise it can easily break a lot of userspace : admin@aloha:~$ ll /bin/bash /bin/coreutils /bin/ls /usr/bin/telnet -r-xr-x--x 1 root adm 549272 Oct 28 16:25 /bin/bash -rwx--x--x 1 root adm 765624 Oct 28 16:27 /bin/coreutils lrwxrwxrwx 1 root root 9 Oct 28 16:27 /bin/ls -> coreutils -r-xr-x--x 1 root adm 70344 Oct 28 16:34 /usr/bin/telnet And I've not invented it, I've being taught to do this more than 20 years ago and been doing this since on any slightly hardened server just because in pratice it's efficient at stopping quite a bunch of rootkits which require to copy and modify your executables. Sure they could get the contents using ptrace, but using cp is much more common than ptrace in scripts and that works. This has prooven quite efficient in field at stopping some rootkits several times over the last two decades and I know I'm not the only one to do it. In fact I *never* install an executable with read permissions for users if there's no need for random users to copy it. Does it mean that nobody should be able to see why their favorite utility doesn't work anymore ? Not in my opinion, at least not by default. So here I fear that we'll break strace at many places where strace precisely matters to debug things. However I'd love to have this feature controlled by a sysctl (to enforce it by default where possible). Thanks, Willy
[toc] | [prev] | [next] | [standalone]
| From | Kees Cook <keescook@chromium.org> |
|---|---|
| Date | 2016-11-17 22:10 +0100 |
| Subject | Re: [REVIEW][PATCH 2/3] exec: Don't allow ptracing an exec of an unreadable file |
| Message-ID | <sEC6t-5ZL-1@gated-at.bofh.it> |
| In reply to | #1524808 |
On Thu, Nov 17, 2016 at 12:47 PM, Willy Tarreau <w@1wt.eu> wrote: > On Thu, Nov 17, 2016 at 11:08:22AM -0600, Eric W. Biederman wrote: >> >> It is the reasonable expectation that if an executable file is not >> readable there will be no way for a user without special privileges to >> read the file. This is enforced in ptrace_attach but if we are >> already attached there is no enforcement if a readonly executable >> is exec'd. > > I'm really scared by this Eric. At least you want to make it a hardening > option that can be disabled at run time, otherwise it can easily break a > lot of userspace : > > admin@aloha:~$ ll /bin/bash /bin/coreutils /bin/ls /usr/bin/telnet > -r-xr-x--x 1 root adm 549272 Oct 28 16:25 /bin/bash > -rwx--x--x 1 root adm 765624 Oct 28 16:27 /bin/coreutils > lrwxrwxrwx 1 root root 9 Oct 28 16:27 /bin/ls -> coreutils > -r-xr-x--x 1 root adm 70344 Oct 28 16:34 /usr/bin/telnet > > And I've not invented it, I've being taught to do this more than 20 > years ago and been doing this since on any slightly hardened server > just because in pratice it's efficient at stopping quite a bunch of > rootkits which require to copy and modify your executables. Sure > they could get the contents using ptrace, but using cp is much more > common than ptrace in scripts and that works. This has prooven quite > efficient in field at stopping some rootkits several times over the > last two decades and I know I'm not the only one to do it. In fact > I *never* install an executable with read permissions for users if > there's no need for random users to copy it. Does it mean that > nobody should be able to see why their favorite utility doesn't > work anymore ? Not in my opinion, at least not by default. > > So here I fear that we'll break strace at many places where strace > precisely matters to debug things. > > However I'd love to have this feature controlled by a sysctl (to > enforce it by default where possible). I'm not opposed to a sysctl for this. Regardless, I think we need to embrace this idea now, though, since we'll soon end up with architectures that enforce executable-only memory, in which case ptrace will again fail. Almost better to get started here and then not have more surprises later. -Kees -- Kees Cook Nexus Security
[toc] | [prev] | [next] | [standalone]
| From | Willy Tarreau <w@1wt.eu> |
|---|---|
| Date | 2016-11-17 22:40 +0100 |
| Subject | Re: [REVIEW][PATCH 2/3] exec: Don't allow ptracing an exec of an unreadable file |
| Message-ID | <sECzw-6bD-7@gated-at.bofh.it> |
| In reply to | #1524810 |
On Thu, Nov 17, 2016 at 01:07:33PM -0800, Kees Cook wrote: > I'm not opposed to a sysctl for this. Regardless, I think we need to > embrace this idea now, though, since we'll soon end up with > architectures that enforce executable-only memory, in which case > ptrace will again fail. Almost better to get started here and then not > have more surprises later. Also that makes me realize that by far the largest use case of ptrace is strace and that strace needs very little capabilities. I guess that most users would be fine with having only pointers and not contents for addresses or read/write of data, as they have on some other OSes, when the process is not readable. But in my opinion when a process is executable we should be able to trace its execution (even without memory read access). Willy
[toc] | [prev] | [next] | [standalone]
| From | ebiederm@xmission.com (Eric W. Biederman) |
|---|---|
| Date | 2016-11-17 23:00 +0100 |
| Subject | Re: [REVIEW][PATCH 2/3] exec: Don't allow ptracing an exec of an unreadable file |
| Message-ID | <sECSS-6iy-5@gated-at.bofh.it> |
| In reply to | #1524825 |
Willy Tarreau <w@1wt.eu> writes: > On Thu, Nov 17, 2016 at 01:07:33PM -0800, Kees Cook wrote: >> I'm not opposed to a sysctl for this. Regardless, I think we need to >> embrace this idea now, though, since we'll soon end up with >> architectures that enforce executable-only memory, in which case >> ptrace will again fail. Almost better to get started here and then not >> have more surprises later. > > Also that makes me realize that by far the largest use case of ptrace > is strace and that strace needs very little capabilities. I guess that > most users would be fine with having only pointers and not contents > for addresses or read/write of data, as they have on some other OSes, > when the process is not readable. But in my opinion when a process > is executable we should be able to trace its execution (even without > memory read access). Given all of this I will respin this series with a replacement patch that adds a permission check ion the path where ptrace calls access_process_vm. I avoided it because the patch is a bit larger and with full ptrace control is much better at leaking information. Even if you can't read the data. But ptrace works even if it won't give you the memory based arguments to system calls anymore. Eric
[toc] | [prev] | [next] | [standalone]
| From | ebiederm@xmission.com (Eric W. Biederman) |
|---|---|
| Date | 2016-11-18 00:00 +0100 |
| Subject | [REVIEW][PATCH 2/3] ptrace: Don't allow accessing an undumpable mm |
| Message-ID | <sEDOW-6Zj-5@gated-at.bofh.it> |
| In reply to | #1524836 |
It is the reasonable expectation that if an executable file is not
readable there will be no way for a user without special privileges to
read the file. This is enforced in ptrace_attach but if ptrace
is already attached before exec there is no enforcement for read-only
executables.
As the only way to read such an mm is through access_process_vm
spin a variant called ptrace_access_vm that will fail if the
target process is not being ptraced by the current process, or
the current process did not have sufficient privileges when ptracing
began to read the target processes mm.
In the ptrace implementations replace access_process_vm by
ptrace_access_vm. There remain several ptrace sites that still use
access_process_vm as they are reading the target executables
instructions (for kernel consumption) or register stacks. As such it
does not appear necessary to add a permission check to those calls.
This bug has always existed in Linux.
Fixes: v1.0
Cc: stable@vger.kernel.org
Reported-by: Andy Lutomirski <luto@amacapital.net>
Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
---
arch/alpha/kernel/ptrace.c | 2 +-
arch/blackfin/kernel/ptrace.c | 4 ++--
arch/cris/arch-v32/kernel/ptrace.c | 2 +-
arch/ia64/kernel/ptrace.c | 2 +-
arch/mips/kernel/ptrace32.c | 4 ++--
arch/powerpc/kernel/ptrace32.c | 4 ++--
include/linux/mm.h | 2 ++
include/linux/ptrace.h | 3 +++
kernel/ptrace.c | 41 ++++++++++++++++++++++++++++++++------
mm/memory.c | 2 +-
mm/nommu.c | 2 +-
11 files changed, 51 insertions(+), 17 deletions(-)
diff --git a/arch/alpha/kernel/ptrace.c b/arch/alpha/kernel/ptrace.c
index d9ee81769899..619d8b4bc890 100644
--- a/arch/alpha/kernel/ptrace.c
+++ b/arch/alpha/kernel/ptrace.c
@@ -281,7 +281,7 @@ long arch_ptrace(struct task_struct *child, long request,
/* When I and D space are separate, these will need to be fixed. */
case PTRACE_PEEKTEXT: /* read word at location addr. */
case PTRACE_PEEKDATA:
- copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
+ copied = ptrace_access_vm(child, addr, &tmp, sizeof(tmp), 0);
ret = -EIO;
if (copied != sizeof(tmp))
break;
diff --git a/arch/blackfin/kernel/ptrace.c b/arch/blackfin/kernel/ptrace.c
index 8b8fe671b1a6..7d8ece6a93fb 100644
--- a/arch/blackfin/kernel/ptrace.c
+++ b/arch/blackfin/kernel/ptrace.c
@@ -270,7 +270,7 @@ long arch_ptrace(struct task_struct *child, long request,
switch (bfin_mem_access_type(addr, to_copy)) {
case BFIN_MEM_ACCESS_CORE:
case BFIN_MEM_ACCESS_CORE_ONLY:
- copied = access_process_vm(child, addr, &tmp,
+ copied = ptrace_access_vm(child, addr, &tmp,
to_copy, 0);
if (copied)
break;
@@ -323,7 +323,7 @@ long arch_ptrace(struct task_struct *child, long request,
switch (bfin_mem_access_type(addr, to_copy)) {
case BFIN_MEM_ACCESS_CORE:
case BFIN_MEM_ACCESS_CORE_ONLY:
- copied = access_process_vm(child, addr, &data,
+ copied = ptrace_access_vm(child, addr, &data,
to_copy, 1);
break;
case BFIN_MEM_ACCESS_DMA:
diff --git a/arch/cris/arch-v32/kernel/ptrace.c b/arch/cris/arch-v32/kernel/ptrace.c
index f085229cf870..04251c6cb5f9 100644
--- a/arch/cris/arch-v32/kernel/ptrace.c
+++ b/arch/cris/arch-v32/kernel/ptrace.c
@@ -147,7 +147,7 @@ long arch_ptrace(struct task_struct *child, long request,
/* The trampoline page is globally mapped, no page table to traverse.*/
tmp = *(unsigned long*)addr;
} else {
- copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
+ copied = ptrace_access_vm(child, addr, &tmp, sizeof(tmp), 0);
if (copied != sizeof(tmp))
break;
diff --git a/arch/ia64/kernel/ptrace.c b/arch/ia64/kernel/ptrace.c
index 6f54d511cc50..4c46672f3ac1 100644
--- a/arch/ia64/kernel/ptrace.c
+++ b/arch/ia64/kernel/ptrace.c
@@ -1156,7 +1156,7 @@ arch_ptrace (struct task_struct *child, long request,
case PTRACE_PEEKTEXT:
case PTRACE_PEEKDATA:
/* read word at location addr */
- if (access_process_vm(child, addr, &data, sizeof(data), 0)
+ if (ptrace_access_vm(child, addr, &data, sizeof(data), 0)
!= sizeof(data))
return -EIO;
/* ensure return value is not mistaken for error code */
diff --git a/arch/mips/kernel/ptrace32.c b/arch/mips/kernel/ptrace32.c
index 283b5a1967d1..114b577c5a51 100644
--- a/arch/mips/kernel/ptrace32.c
+++ b/arch/mips/kernel/ptrace32.c
@@ -69,7 +69,7 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
if (get_user(addrOthers, (u32 __user * __user *) (unsigned long) addr) != 0)
break;
- copied = access_process_vm(child, (u64)addrOthers, &tmp,
+ copied = ptrace_access_vm(child, (u64)addrOthers, &tmp,
sizeof(tmp), 0);
if (copied != sizeof(tmp))
break;
@@ -178,7 +178,7 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
if (get_user(addrOthers, (u32 __user * __user *) (unsigned long) addr) != 0)
break;
ret = 0;
- if (access_process_vm(child, (u64)addrOthers, &data,
+ if (ptrace_access_vm(child, (u64)addrOthers, &data,
sizeof(data), 1) == sizeof(data))
break;
ret = -EIO;
diff --git a/arch/powerpc/kernel/ptrace32.c b/arch/powerpc/kernel/ptrace32.c
index f52b7db327c8..2e4f01dc9d64 100644
--- a/arch/powerpc/kernel/ptrace32.c
+++ b/arch/powerpc/kernel/ptrace32.c
@@ -73,7 +73,7 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
if (get_user(addrOthers, (u32 __user * __user *)addr) != 0)
break;
- copied = access_process_vm(child, (u64)addrOthers, &tmp,
+ copied = ptrace_access_vm(child, (u64)addrOthers, &tmp,
sizeof(tmp), 0);
if (copied != sizeof(tmp))
break;
@@ -178,7 +178,7 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
if (get_user(addrOthers, (u32 __user * __user *)addr) != 0)
break;
ret = 0;
- if (access_process_vm(child, (u64)addrOthers, &tmp,
+ if (ptrace_access_vm(child, (u64)addrOthers, &tmp,
sizeof(tmp), 1) == sizeof(tmp))
break;
ret = -EIO;
diff --git a/include/linux/mm.h b/include/linux/mm.h
index e9caec6a51e9..f49727403cce 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -1269,6 +1269,8 @@ static inline int fixup_user_fault(struct task_struct *tsk,
extern int access_process_vm(struct task_struct *tsk, unsigned long addr, void *buf, int len, int write);
extern int access_remote_vm(struct mm_struct *mm, unsigned long addr,
void *buf, int len, int write);
+extern int __access_remote_vm(struct task_struct *tsk, struct mm_struct *mm,
+ unsigned long addr, void *buf, int len, int write);
long __get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
unsigned long start, unsigned long nr_pages,
diff --git a/include/linux/ptrace.h b/include/linux/ptrace.h
index e13bfdf7f314..7ef2f2b0a02e 100644
--- a/include/linux/ptrace.h
+++ b/include/linux/ptrace.h
@@ -8,6 +8,9 @@
#include <linux/pid_namespace.h> /* For task_active_pid_ns. */
#include <uapi/linux/ptrace.h>
+extern int ptrace_access_vm(struct task_struct *tsk, unsigned long addr,
+ void *buf, int len, int write);
+
/*
* Ptrace flags
*
diff --git a/kernel/ptrace.c b/kernel/ptrace.c
index 982505497680..20288a3b3796 100644
--- a/kernel/ptrace.c
+++ b/kernel/ptrace.c
@@ -27,6 +27,35 @@
#include <linux/cn_proc.h>
#include <linux/compat.h>
+/*
+ * Access another process' address space via ptrace.
+ * Source/target buffer must be kernel space,
+ * Do not walk the page table directly, use get_user_pages
+ */
+int ptrace_access_vm(struct task_struct *tsk, unsigned long addr,
+ void *buf, int len, int write)
+{
+ struct mm_struct *mm;
+ int ret;
+
+ mm = get_task_mm(tsk);
+ if (!mm)
+ return 0;
+
+ if (!tsk->ptrace ||
+ (current != tsk->parent) ||
+ ((get_dumpable(mm) != SUID_DUMP_USER) &&
+ !ptracer_capable(tsk, mm->user_ns))) {
+ mmput(mm);
+ return 0;
+ }
+
+ ret = __access_remote_vm(tsk, mm, addr, buf, len, write);
+ mmput(mm);
+
+ return ret;
+}
+
/*
* ptrace a task: make the debugger its new parent and
@@ -535,7 +564,7 @@ int ptrace_readdata(struct task_struct *tsk, unsigned long src, char __user *dst
int this_len, retval;
this_len = (len > sizeof(buf)) ? sizeof(buf) : len;
- retval = access_process_vm(tsk, src, buf, this_len, 0);
+ retval = ptrace_access_vm(tsk, src, buf, this_len, 0);
if (!retval) {
if (copied)
break;
@@ -562,7 +591,7 @@ int ptrace_writedata(struct task_struct *tsk, char __user *src, unsigned long ds
this_len = (len > sizeof(buf)) ? sizeof(buf) : len;
if (copy_from_user(buf, src, this_len))
return -EFAULT;
- retval = access_process_vm(tsk, dst, buf, this_len, 1);
+ retval = ptrace_access_vm(tsk, dst, buf, this_len, 1);
if (!retval) {
if (copied)
break;
@@ -1125,7 +1154,7 @@ int generic_ptrace_peekdata(struct task_struct *tsk, unsigned long addr,
unsigned long tmp;
int copied;
- copied = access_process_vm(tsk, addr, &tmp, sizeof(tmp), 0);
+ copied = ptrace_access_vm(tsk, addr, &tmp, sizeof(tmp), 0);
if (copied != sizeof(tmp))
return -EIO;
return put_user(tmp, (unsigned long __user *)data);
@@ -1136,7 +1165,7 @@ int generic_ptrace_pokedata(struct task_struct *tsk, unsigned long addr,
{
int copied;
- copied = access_process_vm(tsk, addr, &data, sizeof(data), 1);
+ copied = ptrace_access_vm(tsk, addr, &data, sizeof(data), 1);
return (copied == sizeof(data)) ? 0 : -EIO;
}
@@ -1153,7 +1182,7 @@ int compat_ptrace_request(struct task_struct *child, compat_long_t request,
switch (request) {
case PTRACE_PEEKTEXT:
case PTRACE_PEEKDATA:
- ret = access_process_vm(child, addr, &word, sizeof(word), 0);
+ ret = ptrace_access_vm(child, addr, &word, sizeof(word), 0);
if (ret != sizeof(word))
ret = -EIO;
else
@@ -1162,7 +1191,7 @@ int compat_ptrace_request(struct task_struct *child, compat_long_t request,
case PTRACE_POKETEXT:
case PTRACE_POKEDATA:
- ret = access_process_vm(child, addr, &data, sizeof(data), 1);
+ ret = ptrace_access_vm(child, addr, &data, sizeof(data), 1);
ret = (ret != sizeof(data) ? -EIO : 0);
break;
diff --git a/mm/memory.c b/mm/memory.c
index fc1987dfd8cc..87bed1520690 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -3868,7 +3868,7 @@ EXPORT_SYMBOL_GPL(generic_access_phys);
* Access another process' address space as given in mm. If non-NULL, use the
* given task for page fault accounting.
*/
-static int __access_remote_vm(struct task_struct *tsk, struct mm_struct *mm,
+int __access_remote_vm(struct task_struct *tsk, struct mm_struct *mm,
unsigned long addr, void *buf, int len, int write)
{
struct vm_area_struct *vma;
diff --git a/mm/nommu.c b/mm/nommu.c
index 95daf81a4855..281d5adda9ef 100644
--- a/mm/nommu.c
+++ b/mm/nommu.c
@@ -1816,7 +1816,7 @@ void filemap_map_pages(struct fault_env *fe,
}
EXPORT_SYMBOL(filemap_map_pages);
-static int __access_remote_vm(struct task_struct *tsk, struct mm_struct *mm,
+int __access_remote_vm(struct task_struct *tsk, struct mm_struct *mm,
unsigned long addr, void *buf, int len, int write)
{
struct vm_area_struct *vma;
--
2.10.1
[toc] | [prev] | [next] | [standalone]
| From | Kees Cook <keescook@chromium.org> |
|---|---|
| Date | 2016-11-18 00:20 +0100 |
| Subject | Re: [REVIEW][PATCH 2/3] ptrace: Don't allow accessing an undumpable mm |
| Message-ID | <sEE8i-7lb-7@gated-at.bofh.it> |
| In reply to | #1524865 |
On Thu, Nov 17, 2016 at 2:50 PM, Eric W. Biederman <ebiederm@xmission.com> wrote: > > It is the reasonable expectation that if an executable file is not > readable there will be no way for a user without special privileges to > read the file. This is enforced in ptrace_attach but if ptrace > is already attached before exec there is no enforcement for read-only > executables. Given the corner cases being fixed here, it might make sense to add some simple tests to tools/testing/sefltests/ptrace/ to validate these changes and avoid future regressions. Regardless, it'll be nice to have this fixed. :) -Kees -- Kees Cook Nexus Security
[toc] | [prev] | [next] | [standalone]
| From | Andy Lutomirski <luto@amacapital.net> |
|---|---|
| Date | 2016-11-18 00:30 +0100 |
| Subject | Re: [REVIEW][PATCH 2/3] exec: Don't allow ptracing an exec of an unreadable file |
| Message-ID | <sEEhX-7on-15@gated-at.bofh.it> |
| In reply to | #1524810 |
On Thu, Nov 17, 2016 at 1:07 PM, Kees Cook <keescook@chromium.org> wrote: > On Thu, Nov 17, 2016 at 12:47 PM, Willy Tarreau <w@1wt.eu> wrote: >> On Thu, Nov 17, 2016 at 11:08:22AM -0600, Eric W. Biederman wrote: >>> >>> It is the reasonable expectation that if an executable file is not >>> readable there will be no way for a user without special privileges to >>> read the file. This is enforced in ptrace_attach but if we are >>> already attached there is no enforcement if a readonly executable >>> is exec'd. >> >> I'm really scared by this Eric. At least you want to make it a hardening >> option that can be disabled at run time, otherwise it can easily break a >> lot of userspace : >> >> admin@aloha:~$ ll /bin/bash /bin/coreutils /bin/ls /usr/bin/telnet >> -r-xr-x--x 1 root adm 549272 Oct 28 16:25 /bin/bash >> -rwx--x--x 1 root adm 765624 Oct 28 16:27 /bin/coreutils >> lrwxrwxrwx 1 root root 9 Oct 28 16:27 /bin/ls -> coreutils >> -r-xr-x--x 1 root adm 70344 Oct 28 16:34 /usr/bin/telnet >> >> And I've not invented it, I've being taught to do this more than 20 >> years ago and been doing this since on any slightly hardened server >> just because in pratice it's efficient at stopping quite a bunch of >> rootkits which require to copy and modify your executables. Sure >> they could get the contents using ptrace, but using cp is much more >> common than ptrace in scripts and that works. This has prooven quite >> efficient in field at stopping some rootkits several times over the >> last two decades and I know I'm not the only one to do it. In fact >> I *never* install an executable with read permissions for users if >> there's no need for random users to copy it. Does it mean that >> nobody should be able to see why their favorite utility doesn't >> work anymore ? Not in my opinion, at least not by default. >> >> So here I fear that we'll break strace at many places where strace >> precisely matters to debug things. >> >> However I'd love to have this feature controlled by a sysctl (to >> enforce it by default where possible). > > I'm not opposed to a sysctl for this. Regardless, I think we need to > embrace this idea now, though, since we'll soon end up with > architectures that enforce executable-only memory, in which case > ptrace will again fail. Almost better to get started here and then not > have more surprises later. That won't be a problem because exec-only memory is going to need to allow ptrace to read it anyway. --Andy
[toc] | [prev] | [next] | [standalone]
| From | Andy Lutomirski <luto@amacapital.net> |
|---|---|
| Date | 2016-11-18 00:40 +0100 |
| Subject | Re: [REVIEW][PATCH 2/3] exec: Don't allow ptracing an exec of an unreadable file |
| Message-ID | <sEErD-7rZ-7@gated-at.bofh.it> |
| In reply to | #1524539 |
On Thu, Nov 17, 2016 at 9:08 AM, Eric W. Biederman
<ebiederm@xmission.com> wrote:
>
> It is the reasonable expectation that if an executable file is not
> readable there will be no way for a user without special privileges to
> read the file. This is enforced in ptrace_attach but if we are
> already attached there is no enforcement if a readonly executable
> is exec'd.
>
> Therefore do the simple thing and if there is a non-dumpable
> executable that we are tracing without privilege fail to exec it.
>
> Fixes: v1.0
> Cc: stable@vger.kernel.org
> Reported-by: Andy Lutomirski <luto@amacapital.net>
> Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
> ---
> fs/exec.c | 8 +++++++-
> 1 file changed, 7 insertions(+), 1 deletion(-)
>
> diff --git a/fs/exec.c b/fs/exec.c
> index fdec760bfac3..de107f74e055 100644
> --- a/fs/exec.c
> +++ b/fs/exec.c
> @@ -1230,6 +1230,11 @@ int flush_old_exec(struct linux_binprm * bprm)
> {
> int retval;
>
> + /* Fail if the tracer can't read the executable */
> + if ((bprm->interp_flags & BINPRM_FLAGS_ENFORCE_NONDUMP) &&
> + !ptracer_capable(current, bprm->mm->user_ns))
> + return -EPERM;
> +
At the very least, I think that BINPRM_FLAGS_ENFORCE_NONDUMP needs to
check capable_wrt_inode_uidgid too. Otherwise we risk breaking:
$ gcc whatever.c
$ chmod 400 a.out
$ strace a.out
[toc] | [prev] | [next] | [standalone]
| From | ebiederm@xmission.com (Eric W. Biederman) |
|---|---|
| Date | 2016-11-18 01:00 +0100 |
| Subject | Re: [REVIEW][PATCH 2/3] exec: Don't allow ptracing an exec of an unreadable file |
| Message-ID | <sEEKZ-7yT-9@gated-at.bofh.it> |
| In reply to | #1524886 |
Andy Lutomirski <luto@amacapital.net> writes:
> On Thu, Nov 17, 2016 at 9:08 AM, Eric W. Biederman
> <ebiederm@xmission.com> wrote:
>>
>> It is the reasonable expectation that if an executable file is not
>> readable there will be no way for a user without special privileges to
>> read the file. This is enforced in ptrace_attach but if we are
>> already attached there is no enforcement if a readonly executable
>> is exec'd.
>>
>> Therefore do the simple thing and if there is a non-dumpable
>> executable that we are tracing without privilege fail to exec it.
>>
>> Fixes: v1.0
>> Cc: stable@vger.kernel.org
>> Reported-by: Andy Lutomirski <luto@amacapital.net>
>> Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
>> ---
>> fs/exec.c | 8 +++++++-
>> 1 file changed, 7 insertions(+), 1 deletion(-)
>>
>> diff --git a/fs/exec.c b/fs/exec.c
>> index fdec760bfac3..de107f74e055 100644
>> --- a/fs/exec.c
>> +++ b/fs/exec.c
>> @@ -1230,6 +1230,11 @@ int flush_old_exec(struct linux_binprm * bprm)
>> {
>> int retval;
>>
>> + /* Fail if the tracer can't read the executable */
>> + if ((bprm->interp_flags & BINPRM_FLAGS_ENFORCE_NONDUMP) &&
>> + !ptracer_capable(current, bprm->mm->user_ns))
>> + return -EPERM;
>> +
>
> At the very least, I think that BINPRM_FLAGS_ENFORCE_NONDUMP needs to
> check capable_wrt_inode_uidgid too. Otherwise we risk breaking:
>
> $ gcc whatever.c
> $ chmod 400 a.out
> $ strace a.out
It is an invariant that if you have caps in mm->user_ns you will
also be capable_write_inode_uidgid of all files that a process exec's.
My third patch winds up changing mm->user_ns to maintain this invariant.
It is also true that Willy convinced me while this check is trivial it
will break historic uses so I have replaced this patch with:
"ptrace: Don't allow accessing an undumpable mm.
Eric
[toc] | [prev] | [next] | [standalone]
| From | Andy Lutomirski <luto@amacapital.net> |
|---|---|
| Date | 2016-11-18 01:20 +0100 |
| Subject | Re: [REVIEW][PATCH 2/3] exec: Don't allow ptracing an exec of an unreadable file |
| Message-ID | <sEF4l-7Yr-5@gated-at.bofh.it> |
| In reply to | #1524899 |
On Thu, Nov 17, 2016 at 3:55 PM, Eric W. Biederman
<ebiederm@xmission.com> wrote:
> Andy Lutomirski <luto@amacapital.net> writes:
>
>> On Thu, Nov 17, 2016 at 9:08 AM, Eric W. Biederman
>> <ebiederm@xmission.com> wrote:
>>>
>>> It is the reasonable expectation that if an executable file is not
>>> readable there will be no way for a user without special privileges to
>>> read the file. This is enforced in ptrace_attach but if we are
>>> already attached there is no enforcement if a readonly executable
>>> is exec'd.
>>>
>>> Therefore do the simple thing and if there is a non-dumpable
>>> executable that we are tracing without privilege fail to exec it.
>>>
>>> Fixes: v1.0
>>> Cc: stable@vger.kernel.org
>>> Reported-by: Andy Lutomirski <luto@amacapital.net>
>>> Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
>>> ---
>>> fs/exec.c | 8 +++++++-
>>> 1 file changed, 7 insertions(+), 1 deletion(-)
>>>
>>> diff --git a/fs/exec.c b/fs/exec.c
>>> index fdec760bfac3..de107f74e055 100644
>>> --- a/fs/exec.c
>>> +++ b/fs/exec.c
>>> @@ -1230,6 +1230,11 @@ int flush_old_exec(struct linux_binprm * bprm)
>>> {
>>> int retval;
>>>
>>> + /* Fail if the tracer can't read the executable */
>>> + if ((bprm->interp_flags & BINPRM_FLAGS_ENFORCE_NONDUMP) &&
>>> + !ptracer_capable(current, bprm->mm->user_ns))
>>> + return -EPERM;
>>> +
>>
>> At the very least, I think that BINPRM_FLAGS_ENFORCE_NONDUMP needs to
>> check capable_wrt_inode_uidgid too. Otherwise we risk breaking:
>>
>> $ gcc whatever.c
>> $ chmod 400 a.out
>> $ strace a.out
>
> It is an invariant that if you have caps in mm->user_ns you will
> also be capable_write_inode_uidgid of all files that a process exec's.
I meant to check whether you *are* the owner, too.
>
> My third patch winds up changing mm->user_ns to maintain this invariant.
>
> It is also true that Willy convinced me while this check is trivial it
> will break historic uses so I have replaced this patch with:
> "ptrace: Don't allow accessing an undumpable mm.
I think that's better.
>
> Eric
>
>
--
Andy Lutomirski
AMA Capital Management, LLC
[toc] | [prev] | [next] | [standalone]
| From | ebiederm@xmission.com (Eric W. Biederman) |
|---|---|
| Date | 2016-11-18 01:40 +0100 |
| Subject | Re: [REVIEW][PATCH 2/3] exec: Don't allow ptracing an exec of an unreadable file |
| Message-ID | <sEFnH-84w-5@gated-at.bofh.it> |
| In reply to | #1524917 |
Andy Lutomirski <luto@amacapital.net> writes:
> On Thu, Nov 17, 2016 at 3:55 PM, Eric W. Biederman
> <ebiederm@xmission.com> wrote:
>> Andy Lutomirski <luto@amacapital.net> writes:
>>
>>> On Thu, Nov 17, 2016 at 9:08 AM, Eric W. Biederman
>>> <ebiederm@xmission.com> wrote:
>>>>
>>>> It is the reasonable expectation that if an executable file is not
>>>> readable there will be no way for a user without special privileges to
>>>> read the file. This is enforced in ptrace_attach but if we are
>>>> already attached there is no enforcement if a readonly executable
>>>> is exec'd.
>>>>
>>>> Therefore do the simple thing and if there is a non-dumpable
>>>> executable that we are tracing without privilege fail to exec it.
>>>>
>>>> Fixes: v1.0
>>>> Cc: stable@vger.kernel.org
>>>> Reported-by: Andy Lutomirski <luto@amacapital.net>
>>>> Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
>>>> ---
>>>> fs/exec.c | 8 +++++++-
>>>> 1 file changed, 7 insertions(+), 1 deletion(-)
>>>>
>>>> diff --git a/fs/exec.c b/fs/exec.c
>>>> index fdec760bfac3..de107f74e055 100644
>>>> --- a/fs/exec.c
>>>> +++ b/fs/exec.c
>>>> @@ -1230,6 +1230,11 @@ int flush_old_exec(struct linux_binprm * bprm)
>>>> {
>>>> int retval;
>>>>
>>>> + /* Fail if the tracer can't read the executable */
>>>> + if ((bprm->interp_flags & BINPRM_FLAGS_ENFORCE_NONDUMP) &&
>>>> + !ptracer_capable(current, bprm->mm->user_ns))
>>>> + return -EPERM;
>>>> +
>>>
>>> At the very least, I think that BINPRM_FLAGS_ENFORCE_NONDUMP needs to
>>> check capable_wrt_inode_uidgid too. Otherwise we risk breaking:
>>>
>>> $ gcc whatever.c
>>> $ chmod 400 a.out
>>> $ strace a.out
>>
>> It is an invariant that if you have caps in mm->user_ns you will
>> also be capable_write_inode_uidgid of all files that a process exec's.
>
> I meant to check whether you *are* the owner, too.
I don't follow. BINPRM_FLAGS_ENFORCE_NONDUMP is only set if
the caller of exec does not have inode_permission(inode, MAY_READ).
Which in your example would have guaranteed that
BINPRM_FLAGS_ENFORCE_NONDUMP would have be unset.
The ptracer_capable thing is only asking in this instance if we can
ignore the nondumpable status because we have CAP_SYS_PTRACE over
a user namespace that includes all of the files that would_dump
was called on (mm->user_ns).
ptrace_access_vm in the replacement patch has essentially the same
permission check. It is just at PTRACE_PEEKTEXT, PTRACE_PEEKDATA,
PTRACE_POKETEXT, or PTRACE_POKEDATA time.
So I am curious if you are seeing something that is worth fixing.
>> My third patch winds up changing mm->user_ns to maintain this invariant.
>>
>> It is also true that Willy convinced me while this check is trivial it
>> will break historic uses so I have replaced this patch with:
>> "ptrace: Don't allow accessing an undumpable mm.
>
> I think that's better.
Eric
[toc] | [prev] | [next] | [standalone]
| From | Willy Tarreau <w@1wt.eu> |
|---|---|
| Date | 2016-11-19 08:20 +0100 |
| Message-ID | <sF86o-1NG-81@gated-at.bofh.it> |
| In reply to | #1524498 |
Hi Eric, On Thu, Nov 17, 2016 at 11:02:47AM -0600, Eric W. Biederman wrote: > > With everyone heading to Kernel Summit and Plumbers I put this set of > patches down temporarily. Now is the time to take it back up and to > make certain I am not missing something stupid in this set of patches. I couldn't get your patch set to apply to any of the kernels I tried, I manually adjusted some parts but the second one has too many rejects. What kernel should I apply this to ? Or maybe some preliminary patches are needed ? Thanks, Willy
[toc] | [prev] | [next] | [standalone]
Page 1 of 2 [1] 2 Next page →
Back to top | Article view | linux.kernel
csiph-web