Marcus Brinkmann | 4 Nov 2002 14:23
Picon
Favicon

PID of client requirements

Hi,

in a couple of places, notably POSIX record file locking and POSIX shared
memory (or semaphores, sorry, I forgot), we need the PID of the client.

Thomas said before that it is good enough to let the client report its PID
in the RPC.  I think the argument was something like that only POSIX
programs are required to behave correctly, and that all POSIX programs will
use the C library, which will do the right thing and provide the current PID
of the calling process in the RPC.

It is clear that all POSIX programs will behave correctly given that
semantic.  What is not clear to me is if this is safe against malicious
abuse.

Let's start with an example.  Imagine a privileged program that relies on the
GETLK function to see what the current holder of a lock is and which kills
that process in some situations.  Then everybody who could take the lock would
be able to have any process (including the root filesystem etc) killed just by
providing the PID of that process when getting the lock.  The ability to take
a shared lock requires only read permission.  Now, one could say that if you
rely on locking, you should not leak any read or write permission to the
lockfile, and it seems that programs are generally careful enough about
that.  Here is an example:

ulysses:/tmp# ls -l /var/lib/dpkg/lock
-rw-r-----    1 root     root            0 2002-10-08 20:50 /var/lib/dpkg/lock

The general question is:  Are there any potential security concerns about having
the caller provide the PID?  The above example is surely safe, because no
(Continue reading)

Thomas Bushnell, BSG | 4 Nov 2002 19:12

Re: PID of client requirements

Marcus Brinkmann <Marcus.Brinkmann <at> ruhr-uni-bochum.de> writes:

> It is clear that all POSIX programs will behave correctly given that
> semantic.  What is not clear to me is if this is safe against malicious
> abuse.
> 
> Let's start with an example.  Imagine a privileged program that
> relies on the GETLK function to see what the current holder of a
> lock is and which kills that process in some situations.  Then
> everybody who could take the lock would be able to have any process
> (including the root filesystem etc) killed just by providing the PID
> of that process when getting the lock.  

Trusting the user to provide his pid is only half of the job when
signals are concerned.  The second thing needed is a signal
authorization port which the user requests from the server, and which
the server will provide in the signal message.  See, for example, how
this works for terminals.

> The general question is: Are there any potential security concerns
> about having the caller provide the PID?  The above example is
> surely safe, because no untrusted party should have read or write
> permission.  This seems to be generally true for record locks.  I
> have not investigated the other application (shared memory and/or
> semaphores) where PID knowledge is required.  Has anybody?

You are right to be thinking about this.  
Neal H. Walfield | 5 Nov 2002 04:38
Favicon

Re: PID of client requirements

> Trusting the user to provide his pid is only half of the job when
> signals are concerned.  The second thing needed is a signal
> authorization port which the user requests from the server, and which
> the server will provide in the signal message.  See, for example, how
> this works for terminals.

Ahem, I think you are missing the point.  We are assuming two
processes: a manager and a rogue.  The rogue process locks the file
supplying a fake pid and then blocks.  The manager process sees that
the file is locked for "too long" (define liberally) and kills the
locking process--or rather, what it thinks is the locking process.  If
the manager is running as root, this could be anyone.
Thomas Bushnell, BSG | 5 Nov 2002 05:58

Re: PID of client requirements

neal <at> cs.uml.edu (Neal H. Walfield) writes:

> > Trusting the user to provide his pid is only half of the job when
> > signals are concerned.  The second thing needed is a signal
> > authorization port which the user requests from the server, and which
> > the server will provide in the signal message.  See, for example, how
> > this works for terminals.
> 
> Ahem, I think you are missing the point.  We are assuming two
> processes: a manager and a rogue.  The rogue process locks the file
> supplying a fake pid and then blocks.  The manager process sees that
> the file is locked for "too long" (define liberally) and kills the
> locking process--or rather, what it thinks is the locking process.  If
> the manager is running as root, this could be anyone.

How does the manager kill the process?  It isn't necessarily
running as root.  It had better work whether running as root or not.

I can think of two ways:

Way One: It sends a signal.  To make this work, use the same trick as
term. 

Way Two: It calls task_terminate.  To make this work, require the
locking task to provide its own task port when acquiring the lock.

However, way two is unacceptible, because users cannot be required to
trust file servers.

I would suggest neither Way One nor Way Two, and go for something
(Continue reading)

Marcus Brinkmann | 5 Nov 2002 12:34
Picon
Favicon

Re: PID of client requirements

On Mon, Nov 04, 2002 at 08:58:47PM -0800, Thomas Bushnell, BSG wrote:
> How does the manager kill the process?  It isn't necessarily
> running as root.  It had better work whether running as root or not.
> 
> I can think of two ways:
> 
> Way One: It sends a signal.  To make this work, use the same trick as
> term. 
> 
> Way Two: It calls task_terminate.  To make this work, require the
> locking task to provide its own task port when acquiring the lock.
> 
> 
> However, way two is unacceptible, because users cannot be required to
> trust file servers.
> 
> I would suggest neither Way One nor Way Two, and go for something
> else:
> 
> If the manager sees that the lock is locked too long, it sends a
> message to the task and forcibly releases the lock.  The process whose
> lock has been broken can do what it likes (including, for example,
> terminate).

You are indeed missing the point.  I am not talking at all about how to do
such things cleanly and nicely.  My example was deliberately arbitrary, but
carefully set up around the following assumptions:

1. The manager program lives entirely in the POSIX world and doesn't know
   about the Hurd at all.
(Continue reading)

Thomas Bushnell, BSG | 7 Nov 2002 00:52

Re: PID of client requirements

Marcus Brinkmann <Marcus.Brinkmann <at> ruhr-uni-bochum.de> writes:

> You are indeed missing the point.  I am not talking at all about how to do
> such things cleanly and nicely.  My example was deliberately arbitrary, but
> carefully set up around the following assumptions:
> 
> 1. The manager program lives entirely in the POSIX world and doesn't know
>    about the Hurd at all.
> 2. The rogue task lives in the Hurd world and knows about such dirty tricks
>    like that the PID can be set to anything.
> 
> A POSIX program would not send messages, it would just use kill().  It could
> rely on the information provided by GETLK that the process ID is valid and
> always equals the process ID of the process having the lock, because that is
> what the standard says.  

Ok, so the manager program is not something *we* are writing, but
something that people commonly do write, using only Posix facilities,
for particular cases, and in which they rely on this facility?

> In the Hurd world, the rogue process could insert the PID of the root
> filesystem, leading to a desaster.  So a small bug in the POSIX world would
> be a grave bug in the Hurd implementation.

I think I see now.  

> Now, the above locking example is not the ideal example, in that it relies
> on a bug in the first place to illustrate the problem.  Lock files should
> not be readable or writable to untrusted users.  But that is only the best
> example I came up with so far.  I am worried that there are similar or worse
(Continue reading)

Marcus Brinkmann | 7 Nov 2002 04:03
Picon
Favicon

Re: PID of client requirements

On Wed, Nov 06, 2002 at 03:52:40PM -0800, Thomas Bushnell, BSG wrote:
> Ok, so the manager program is not something *we* are writing, but
> something that people commonly do write, using only Posix facilities,
> for particular cases, and in which they rely on this facility?

Yes.

> Such cases, it seems to me, mean that we probably do need some kind of
> PID validation.  I'm not sure what the right strategy is, but I'll try
> and think of some.

Ok.  Please do :)  We all will try, too, and maybe we can cook something up. 
Something like a PID authentication port to proc might do it (and proc needs
to implement something like the auth protocol).

Thanks,
Marcus

--

-- 
`Rhubarb is no Egyptian god.' GNU      http://www.gnu.org    marcus <at> gnu.org
Marcus Brinkmann              The Hurd http://www.gnu.org/software/hurd/
Marcus.Brinkmann <at> ruhr-uni-bochum.de
http://www.marcus-brinkmann.de/
Thomas Bushnell, BSG | 8 Nov 2002 00:41

Re: PID of client requirements

Marcus Brinkmann <Marcus.Brinkmann <at> ruhr-uni-bochum.de> writes:

> Ok.  Please do :)  We all will try, too, and maybe we can cook something up. 
> Something like a PID authentication port to proc might do it (and proc needs
> to implement something like the auth protocol).

Something like this is quite right, I think.  But I hope I can think
of something a little simpler.  Still, if not, then not, and we know
that the auth protocol strategy does work.
Roland McGrath | 8 Nov 2002 02:41

Re: PID of client requirements

> Something like this is quite right, I think.  But I hope I can think
> of something a little simpler.  Still, if not, then not, and we know
> that the auth protocol strategy does work.

I think I have convinced myself that the issues are precisely identical for
PIDs and UIDs.  That is, POSIX.1 says what you can expect to see, and a
POSIX.1 program can thus be written (and, we can bet, eventually will) so
that spoofing these values can constitute an exploit of that program.

So, if something simpler than the auth handshake suffices for providing
trustable PIDs, then it suffices for trustable UIDs and GIDs too.
Marcus Brinkmann | 18 Nov 2002 15:26
Picon
Favicon

new interfaces io_close, io_reidentify, file_record_lock

Hi,

these are the new interfaces I am proposing as a first draft to prepare
POSIX record file locking and shared memory.  There has been some discussion
in the past, but I want to summarize the critical points why the interfaces
look the way they do.

io_close

* We need an optional io_close to synchronize a user with various events
  in the server related to closing a file descriptor.
* io_close needs to be interruptible.
* io_close does not need to be restartable, as the state of the FD after the
  interruption is unspecified by POSIX.  The easiest thing for us is to finish
  the close in the client and server asynchronously.  The client should drop
  the fd entry and return EBADF (because that is the error the user would get
  if he tried to restart, and we are not allowed to return EINTR if
  we are supposed to restart).  The server asynchronously completes the
  deallocation of the send right (ie, the destruction of the object).  In
  any case, this is only an issue for blocking close operations, like
  SO_LINGER sockets.
* The above means that we need a special client stub for libhurduser, but no
  special server stub.

io_reidentify, proc_user_identify, proc_server_identify

* We need a way to identify the iouser by its PID for POSIX record file
  locking and shared memory.  It's natural to have an auth like protocol in
  proc.
* The process_t process port in proc can be used by the user to call
(Continue reading)


Gmane