Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 12 Nov 2001 14:50:41 -0800
From:      Terry Lambert <tlambert2@mindspring.com>
To:        Robert Watson <rwatson@FreeBSD.org>
Cc:        freebsd-arch@FreeBSD.org
Subject:   Re: cur{thread/proc}, or not.
Message-ID:  <3BF05241.74F895EF@mindspring.com>
References:  <Pine.NEB.3.96L.1011111101234.11566A-100000@fledge.watson.org>

next in thread | previous in thread | raw e-mail | index | archive | help
Robert Watson wrote:
> There are a number of uses of curproc in the netinet code, used to
> retrieve credentials for authorization somewhere down the stack, when no
> proc or thread pointer has been passed down.

I think that the majority of the netinet code can be handled
by using the socket credential, instead of the process
credential.


> With the eventual addition
> of td->td_ucred, it will be desirable to use the credential for the
> current thread, rather than the proc, which will require locking to use.

I think locking credential instances is bad.

The real question you want to answer is whether or not the
credential instance that was used to acquire a socket should
be used continuously from there on out (i.e. it is a grant),
or whether it should change when the process credential
changes (i.e. it is a lease).  You seem to be arguing for a
lease.  I would argue for a grant.

One issue is that there are cases where write permission is
tested before each write.  There are also cases, where you
obtain a privileged socket, and then relinquish privileges
after obtaining it; such cases are explicitly modelled on a
grant model rather than a lease model.

The point is that if the credentials are granted, then a
change in credential is not a change of the credential itself,
but is instead a copy-on-write proposition.  In other words,
credentials, once granted, are priviledge stable.

If this is the case, then they are written when they are
instanced, cloned before they are modified (indeed, it seems
that the clone/modify operation must be made atomic), and
thus are never written once instanced -- only destroyed on
the 1->0 reference transition.

If so, then no locking is required, since the LCK CMPXCHG can
be utilized to do atomic increment and decrement on the
reference counting, without needing locks.


> As I
> understand it, use of curproc was branded 'undesirable' at some point in
> the semi-distant past, and since that time, a reference to 'proc' has been
> passed down the stack.  With a change to KSE, this has been translated to
> references the thread, but the issue remains the same.  This comes up in
> particular because I have a tree where I have propagated the thread
> pointer down if_ioctl in the network stack: the normal ioctl call carries
> a thread pointer now, but when it is translated into if_ioctl by the
> network stack, that pointer is lost.  This raises the question: should we
> (in practice) be adding process or thread pointers to many more of the
> function arguments, or should we switch to using curproc/curthread
> instead.

The "curproc" undesirability stems primarily from credentials
enforcement during interrupt processing.  I think that this is
not an insurmountable issue, but I would argue that these are
more appropriate for object credentials, where the objects in
question are not threads or processes.

For example, if we were to process incoming TCP connections up
through the "accept" code at interrupt time, one might naievely
assume that, since the current socket code down through the
accept processing code off the queue filled in at NETISR seems
to require a proc credential, that it is therefore necessary to
have a proc credential at interrupt time in order to do this
processing.

The answer is that this is a false assumption, and is predicated
on historical code, and nothing more.

Specifically, if I need a credential for a newly accepted socket
that I am now creating, I can add a reference to the listen socket
credential -- I //do not need// a process credential in order to
do an accept.

There is a lot of this type of fuzzy thinking, asking "how can I
propagate the process credential that I used to use for this
operation down to the underlying code?", when the real question
should be "what is the appropriate credential to use for this
operation, and is the process credential really what I want to
use in this case?".


I think it's possible to get rid of most of the process credential
references -- and therefore, most of the proc references -- at all
points below the /sys/kern/uipc_socket*.c level.


> I don't pretend to have a grasp of all the issues here, so the purpose of
> this message is to raise the issues so that I can understand them.  I have
> a tree where I've eliminated many references to curproc; however, I'm now
> wondering if it wouldn't simply be more useful to eliminate many of the
> references to struct proc in the function arguments, and use curproc
> instead, and add references to ucred (and related ref-counted structures)
> as needed for delegation types of situations.  In particular, that would
> suggest the following changes:

I think this is the wrong direction, but if you wanted to do this,
I think that you would need to put the cur* symbols into the per
CPU private pages.  This is problematic in the extreme, because it
means that you must set these values each time going down, in order
to be able to substitute a per CPU global for the stack reference.

I think this is a bad thing, in general, and will lead only to
trouble later.

I would much rather that the credentials be object referenced off
of non-process, non-thread objects, based on whatever the correct
scoping really is, for the security model you want to enforce.  My
"accept" example is only one of a class of changes that could
facilitate this.


-- Terry

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-arch" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?3BF05241.74F895EF>