2005-05-04 15:40:39

by Serge van den Boom

[permalink] [raw]
Subject: /proc/$PID/mem rationale

Hi,

Could someone explain the reasoning behind these two design decisions
regarding /proc/$PID/mem?
- You can only read() from this file from a process which is attached to
the file's process through ptrace(). Why this requirement?
The following command line could be rather useful, but the ptrace()
requirement prevents this from working:
dd if=/proc/$SOME_PID/mem bs=1 seek=$ADDRESS
- You can only read() from the mem file from the process that open()ed it.
Even if the ptrace() requirement were dropped, you wouldn't be able
to do something like the following command because of this:
dd bs=1 seek=$ADDRESS < /proc/$SOME_PID/mem
The usefulness of this may be limited, but I haven't been able to find
any reason not to allow such actions.

I would appreciate it if you could CC me in replies.

Cheers,

Serge van den Boom



2005-05-04 17:30:08

by Valdis Klētnieks

[permalink] [raw]
Subject: Re: /proc/$PID/mem rationale

On Wed, 04 May 2005 17:40:31 +0200, Serge van den Boom said:

> Could someone explain the reasoning behind these two design decisions
> regarding /proc/$PID/mem?
> - You can only read() from this file from a process which is attached to
> the file's process through ptrace(). Why this requirement?
> The following command line could be rather useful, but the ptrace()
> requirement prevents this from working:
> dd if=/proc/$SOME_PID/mem bs=1 seek=$ADDRESS

It's prohibited *because* it could be rather useful - to a hacker. It's an
issue of information leakage - there are some corner cases where the permissions
on /proc/PID/mem would appear to allow a read, but you don't in fact want to
allow it (for the full list, look at the ptrace() code and the tests it makes
for things like euid != uid and so on). There's a bunch of race conditions
in there too.

> - You can only read() from the mem file from the process that open()ed it.
> Even if the ptrace() requirement were dropped, you wouldn't be able
> to do something like the following command because of this:
> dd bs=1 seek=$ADDRESS < /proc/$SOME_PID/mem

Same reasons. ptrace() is able to make some checks and set some bits that
read() isn't allowed anywhere near (in particular, ptrace() can *stop* a process
so it can't race - read() can't do that.)



Attachments:
(No filename) (226.00 B)

2005-05-05 07:15:58

by Serge van den Boom

[permalink] [raw]
Subject: Re: /proc/$PID/mem rationale

On Wed, 4 May 2005 [email protected] wrote:
> On Wed, 04 May 2005 17:40:31 +0200, Serge van den Boom said:
> > - You can only read() from this file from a process which is attached to
> > the file's process through ptrace(). Why this requirement?
> > The following command line could be rather useful, but the ptrace()
> > requirement prevents this from working:
> > dd if=/proc/$SOME_PID/mem bs=1 seek=$ADDRESS
> It's prohibited *because* it could be rather useful - to a hacker. It's an
> issue of information leakage - there are some corner cases where the
> permissions on /proc/PID/mem would appear to allow a read, but you don't in
> fact want to allow it (for the full list, look at the ptrace() code and the
> tests it makes for things like euid != uid and so on). There's a bunch of
> race conditions in there too.
Actually, mem_read(), the read handler for the "mem" file, calls
may_ptrace_attach(), which makes exactly the same checks as ptrace_attach().
In fact, mem_read() makes these checks each time it is called, while if
you were to use ptrace() to read data, these checks would be made only
at PTRACE_ATTACH, and not at PTRACE_PEEKDATA.
The only security that mem_read() gets from checking whether the process
is tracing the child seems to be as an indicator that some checks have
been done in the past. But these are exactly the checks that are being done
again right after this tracing check.
I don't see how that's going to affect any race conditions.


> > - You can only read() from the mem file from the process that open()ed it.
> > Even if the ptrace() requirement were dropped, you wouldn't be able
> > to do something like the following command because of this:
> > dd bs=1 seek=$ADDRESS < /proc/$SOME_PID/mem
> Same reasons. ptrace() is able to make some checks and set some bits that
> read() isn't allowed anywhere near (in particular, ptrace() can *stop* a
> process so it can't race - read() can't do that.)
This question isn't about requiring the child being traced by the reader
or not. I'm asking why the process that opens the "mem" file needs to be
the one that does the reading. There are no special checks being done
when the file is opened.

As for stopping the child process: if that's necessary, then it looks like
there's a race condition present as it is. Because as far as I can tell,
there's nothing preventing a process from sending a SIGCONT to the child
process while the mem_read() is going on.


Please CC me in replies again.

Cheers,

Serge