l4-hurd
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: fork, trivial confinement, constructor


From: Bas Wijnen
Subject: Re: fork, trivial confinement, constructor
Date: Wed, 14 Jun 2006 10:43:02 +0200
User-agent: Mutt/1.5.11+cvs20060403

For people who have read the page, I've changed the "fork vs others" part a
bit to explain about capabilities.  In unix, dropping all file descriptors at
fork doesn't add a lot of security, because the new process can open all of
them again (except anonymous pipes, and special pipes or sockets which allow
only one connection and then stop listening).

On Tue, Jun 13, 2006 at 11:24:31PM -0400, Eric Northup wrote:
> On Tue, 2006-06-13 at 18:12, Bas Wijnen wrote:
> 
> > The last part of it however, is comparing trivial confinement to the
> > constructor.  As it says, this list has not reached consensus about it.
> > It's probably a good idea if that happens, which is why I'm bringing it
> > up.  The part I wrote can be used as a starting point.  For the lazy
> > readers, I'll quote it here (if you don't understand from the context what
> > the letters mean, go read the whole thing):
> > 
> >             The difference between trivial confinement and the constructor
> >             is one of control. With trivial confinement, P is in full
> >             control of the process.
> 
> Also, P's parent, and P's parent's parent, ..., are all in full
> control.

Obviously, this is a recursive property indeed.  I'll clarify that.

> >             The constructor is explicitly designed to allow this type of
> >             control by the programmer (or system administrator) over the
> >             user.
> 
> I find this statement to be misleading.
> 
> The constructor is designed to allow two *programs* (which might be
> mistrusting of each other) to compose some of their authorities and
> form a third program.  *Either* of the two parent programs can also
> decide not to allow the construction if the resulting program would be
> unconfined, so the protection is symmetric, rather than one-sided.

No, it is not symmetric.  It is true that P2 (the instantiator) can choose not
to perform the construction.  But it's an all-or-nothing deal.  On the other
hand, P1 is in full control.  There is no negotiation possible.  P1 offers a
deal, P2 either accepts or rejects it.  The confinement check only means that
P2 is a bit better informed about the deal, it doesn't actually change the
principle.  This means P1 is in full control over the new process (although if
confined not using remote control, it still defines what code it's running),
while P2 can only choose to reject it, which is similar to "turning off
javascript" in a browser.  For many people it simply isn't an option, because
they (think they) need the functionality.

> This is a statement about programs, not about humans; I am not at all
> concerned with programs' freedom.

I fully agree with you there.  However, this is also about humans.  Some
programs are direct agents of the user.  If the user wants to use a program to
do things (such as debugging), then those programs must be able to do it.

It is possible to think out constructions which allow user freedom, but not
program freedom.  Those constructs would be just as acceptable for the Hurd.
However, I think the trivial confinement method is very elegant because no
special case is needed for the user.  This means code simplicity, which is
also valuable.

> I believe that the constructor is compatible with preserving freedom
> for humans; if it turns out not to be, then those are bugs in the
> design and they should be fixed.

The constructor can be used (by the system administrator/installer) in a way
that preserves user freedom.  This is correct.  However, it is also very easy
to set up the system in a way which severely limits user freedom.  Unless
there's a very good reason to do this, I'd prefer to avoid that.

You seem to need a reason for excluding the constructor from the design.  I
need a reason for including it.  And I haven't found a convincing one so far.
I'm not saying the constructor is always evil.  I'm just saying it doesn't
(seem to) bring any features (that I want) that aren't possible without it.
However, it does bring risks of oppressing administrators.  I don't want to
take those risks unless there're significant benefits in return.

> >             In the Hurd we want to enable the user to do these sort of
> >             things.  We specifically don't want the administrator to use
> >             such control.  So we do not need to provide the means for it
> >             in our system. (Note that not using a constructor doesn't
> >             actually guarantee that this kind of control is impossible.)
> 
> I understand that there are many freedoms which the HURD's design must
> be able to protect.  But I think that, by using an overly simple
> example, some other important considerations were missed.
> 
> Consider UNIX systems.  If the process being run has the set-UID bit,
> then the parent process P does not have the right to debug the child.

Actually, if you look at setuid, in UNIX the child runs on resources provided
by the system, not the user.  When a process starts such a program, it isn't
actually the parent.  The process just calls a system service (by calling exec
on the file system node) as a result of which the system spawns a new process
(and kills the caller).  The parent (the system) is in a position to debug it,
but it chooses not to.  This same principle can work using trivial
confinement.  If opaque memory donations are possible (and trivial confinement
doesn't actually prevent them), it can work in exactly the same way.

However, all this isn't what the page is about.  Whether or not opaque
donations are possible is orthogonal to the mechanism used for process
instantiation.  For that reason, I wrote some things about the assumptions
(which I didn't quote before).

In the introduction:
        This comparison is about a simple situation: there is a parent process
        P, which wants to spawn a child process C.  We assume that P holds
        capabilities A and B.  The end result should be that C holds a copy of
        A, but not of B.

And in the constructor explanation:
        P1 sends a message to the meta-constructor M (a constructor to create
        new constructors) sending it the code image for the child (and due to
        the limitation of this discussion, no initial capabilities).

In other words, this isn't about setuid programs.  It's about the default
procedure used for "normal" process instantiation, where P provides all the
capabilities that C gets.  We've been talking about the more complex situation
quite a bit already.  I'd be happy with a consensus on that as well, but I
don't think it'll happen soon.  It'll certainly take longer if we confuse this
(simpler) discussion with those complications. :-)

> Now, let me be clear: I am not suggesting that the HURD should encourage
> system administrators to be overly restrictive of their users' freedoms*.
> And I definitely agree that the HURD should not support DRM.  But it is
> important to not throw the baby (usable security) out with the bathwater
> (DRM, unreasonable restrictions of users freedom, etc).

I fully agree.  However, as said above, that's not what this discussion is
about.  Whether or not we need a constructor for "complicated" cases such as
setuid is a different discussion.  This is about the default method for
process instantiation.  I do not see a reason to use a constructor for that.

> *I see no problem with, for example, imposing quotas, or preventing a
> user from harming other users, even though such measures might be
> considered restrictions of freedom.

Of course.  We should not (always) give the freedom to limit other people's
freedom.  That's the BSD/GPL discussion.  I think I know which side the Hurd
will choose. :-)

> >             Therefore I am not so convinced that we want a constructor. It
> >             gets in the way of debugging, for example, and it doesn't
> >             really give any gain.
> 
> The question of how to permit convenient debugging, without
> accidentally introducing security vulnerabilities is (as far as I am
> aware) a rather under-explored problem space.

I am not so informed about the field that I know about the explorations
either.

> Many designs are possible; the one I'm about to propose is just a suggestion
> to start discussion.

Good, thanks. :-)

> It seems to me that a reasonable policy would be that a program should
> be able to get a debug capability to a "victim" program if:
> -The program can provide capabilities to the space bank and CPU
> schedule from which the victim is running.
>    AND
> -The program can provide copies of all the capabilities that were
> packaged into the victim's constructor by the meta-constructor.

Conceptually this would work, I suppose.  However, it means we need to
complicate the system with all these checks.  The nice thing about trivial
confinement is that it is very simple, and provides everything we want
(AFAICS).  If we want a more complex system (such as this one, or the
constructor without this addition), there must be a reason that it is actually
better in some respect.  Otherwise the simpler solution is preferrable.

> Also, if the program has received additional capabilities, while
> running, from the powerbox or through drag-and-drop, then the powerbox
> should ensure that the (human) user approves.

This is true irrespective of how the process in instantiated.  It also follows
from "awareness" (and, strictly speaking, "security") as defined by Marcus in
the "requirements for the user".

> So, if I'm running on a system where parent programs have the unlimited
> authority to debug their children, then I'd have to stop using Emacs'
> shell features.

So you're saying that because emacs is insecure (in that it allows itself to
be taken over by its children), we should be insecure as well?  I don't quite
see your point.  Obviously emacs will have to be changed to use these security
features (not sure how hard that is).  As long as it isn't, using it is a
security risk, irrespective of what system it runs on.

Not that the risk is any bigger than using any program on UNIX.  And at least
currently that's obviously acceptable. :-)  But that's something I want to
change.  This will mean some programs, particularly the ones with plugin
systems, need modifications to use all the new features.

Thanks,
Bas

-- 
I encourage people to send encrypted e-mail (see http://www.gnupg.org).
If you have problems reading my e-mail, use a better reader.
Please send the central message of e-mails as plain text
   in the message body, not as HTML and definitely not as MS Word.
Please do not use the MS Word format for attachments either.
For more information, see http://129.125.47.90/e-mail.html

Attachment: signature.asc
Description: Digital signature


reply via email to

[Prev in Thread] Current Thread [Next in Thread]