2002-08-26 13:29:14

by Zheng Jian-Ming

[permalink] [raw]
Subject: problems with changing UID/GID

Hi.

POSIX states that the credentials (uid, gid, capabilities, etc.) are
process-wide. So when one thread within the process changes some part
of the credentials, all threads see the change.

But, the credentials are per-task in Linux, so it's possible to have
two tasks in a process running under different UIDs.

It may have problems when we change UID/GID in one task within the
thread group.

How to deal with it? Will Linux kernel move credentials into a shared
structure?

Thank you.

--
Best Regards,


2002-08-26 13:40:48

by Alan

[permalink] [raw]
Subject: Re: problems with changing UID/GID

On Mon, 2002-08-26 at 14:30, Zheng Jian-Ming wrote:
> POSIX states that the credentials (uid, gid, capabilities, etc.) are
> process-wide. So when one thread within the process changes some part
> of the credentials, all threads see the change.

For POSIX threads yes, for sane threading environments thats actually a
real pain in the backside. Currently its up to the pthreads userspace to
do the emulation itself.

> But, the credentials are per-task in Linux, so it's possible to have
> two tasks in a process running under different UIDs.

Really useful isnt it

There are other reasons for wanting refcounted credential structures (eg
NFS writeback) so it may well be that once those go in for other reasons
it makes sense to provide an option to do shared credentials for
threaded apps. It is however nontrivial and you might want to see how
your other systems respond to things like a file open on a slow device
while a second thread is strobing the uid between two values. Does it
change uid mid syscall, does it get the permissions checks right if so ?

Its non trivial stuff, if not plain crazy to implement a literal
interpretation of (eg does a write fail half way if you change userid in
another thread ?)


2002-08-26 14:54:39

by Thunder from the hill

[permalink] [raw]
Subject: Re: problems with changing UID/GID

Hi,

On Mon, 26 Aug 2002, Zheng Jian-Ming wrote:
> POSIX states that the credentials (uid, gid, capabilities, etc.) are
> process-wide. So when one thread within the process changes some part
> of the credentials, all threads see the change.
>
> But, the credentials are per-task in Linux, so it's possible to have
> two tasks in a process running under different UIDs.
>
> It may have problems when we change UID/GID in one task within the
> thread group.
>
> How to deal with it? Will Linux kernel move credentials into a shared
> structure?

There was some piece of work on that, done by Dave McCracken. But it
lately had this "little security hole you could drive a big yellow truck
with flashlights on through" problem...

I personally like the task->cred->cr_uid, etc. approach. Helps a lot.

Thunder
--
--./../...-/. -.--/---/..-/.-./..././.-../..-. .---/..-/.../- .-
--/../-./..-/-/./--..-- ../.----./.-../.-.. --./../...-/. -.--/---/..-
.- -/---/--/---/.-./.-./---/.--/.-.-.-
--./.-/-.../.-./.././.-../.-.-.-

2002-08-26 17:11:48

by Alan

[permalink] [raw]
Subject: Re: problems with changing UID/GID

On Mon, 2002-08-26 at 15:58, Thunder from the hill wrote:
> I personally like the task->cred->cr_uid, etc. approach. Helps a lot.

It changes the whole semantics of every security test in Linux, and
breaks most of them totally. Our syscalls know the uid is constant
during the call

2002-08-26 17:27:59

by Thunder from the hill

[permalink] [raw]
Subject: Re: problems with changing UID/GID

Hi,

On 26 Aug 2002, Alan Cox wrote:
> > I personally like the task->cred->cr_uid, etc. approach. Helps a lot.
>
> It changes the whole semantics of every security test in Linux, and
> breaks most of them totally. Our syscalls know the uid is constant
> during the call

I didn't say it's a must -- for now.

Thunder
--
--./../...-/. -.--/---/..-/.-./..././.-../..-. .---/..-/.../- .-
--/../-./..-/-/./--..-- ../.----./.-../.-.. --./../...-/. -.--/---/..-
.- -/---/--/---/.-./.-./---/.--/.-.-.-
--./.-/-.../.-./.././.-../.-.-.-

2002-08-26 18:43:09

by Trond Myklebust

[permalink] [raw]
Subject: Re: problems with changing UID/GID

>>>>> " " == Alan Cox <[email protected]> writes:

> On Mon, 2002-08-26 at 15:58, Thunder from the hill wrote:
>> I personally like the task->cred->cr_uid, etc. approach. Helps
>> a lot.

> It changes the whole semantics of every security test in Linux,
> and breaks most of them totally. Our syscalls know the uid is
> constant during the call

Right. Most people appear to prefer to make a lunge straight for
CLONE_CRED.

One of the first steps should rather be to build up support for a
copy-on-write BSD-style 'ucred' struct that can be passed around the
VFS.
Without the latter there is no way to ensure that the compound VFS
operations such as, say, lookup(), followed by a call to permission()
followed by a call to dentry_open(), ->readpage(), etc. all use the
same creds. This they *have* to do irrespective of whether or not the
process is using CLONE_CRED, or you might end up using one set of
privileges for the security checks and a different set for the actual
file/device ops...

Once those VFS changes have been done and audited, then one can start
to add support for 'pcreds' a.k.a. process credentials and then
finally CLONE_CRED...

Cheers,
Trond

2002-08-27 00:28:47

by Luca Barbieri

[permalink] [raw]
Subject: Re: problems with changing UID/GID

On Mon, 2002-08-26 at 19:16, Alan Cox wrote:
> On Mon, 2002-08-26 at 15:58, Thunder from the hill wrote:
> > I personally like the task->cred->cr_uid, etc. approach. Helps a lot.
>
> It changes the whole semantics of every security test in Linux, and
> breaks most of them totally. Our syscalls know the uid is constant
> during the call
This is easily fixable by having a shared structure separate from the
private one and propagating modifications only when entering kernel
mode.
If we combine the syscall-trace and cred-propagation checks this can be
done without overhead in the common case (but needs care to avoid
races).

This is similar to what user space would do but faster and transparent.

(BTW, I don't plan to code this myself)


Attachments:
signature.asc (189.00 B)
This is a digitally signed message part

2002-08-27 07:50:10

by Chris Wedgwood

[permalink] [raw]
Subject: Re: problems with changing UID/GID

On Mon, Aug 26, 2002 at 06:16:59PM +0100, Alan Cox wrote:

It changes the whole semantics of every security test in Linux,
and breaks most of them totally. Our syscalls know the uid is
constant during the call

Could we not (eventually) have CLONE_CREDs and then lock using
task->cred->lock or whatever? Or might there be cases where this will
deadlock? It does mean set[eu]id will have to wait of other threads
and IO to complete... no matter how long that takes, but other than
might it be reasonable?



--cw

2002-08-27 15:38:56

by Thunder from the hill

[permalink] [raw]
Subject: Re: problems with changing UID/GID

Hi,

On Tue, 27 Aug 2002, Chris Wedgwood wrote:
> Could we not (eventually) have CLONE_CREDs and then lock using
> task->cred->lock or whatever? Or might there be cases where this will
> deadlock? It does mean set[eu]id will have to wait of other threads
> and IO to complete... no matter how long that takes, but other than
> might it be reasonable?

I don't think this is cool. I mean, think of how many times we use it, who
will eat the overhead? Basically everyone. (And BTW, if we can't even
afford one lock per module, how could we efford one jock per job? There
are definitely more.)

Takes time and space...

Care to comment?

Thunder
--
--./../...-/. -.--/---/..-/.-./..././.-../..-. .---/..-/.../- .-
--/../-./..-/-/./--..-- ../.----./.-../.-.. --./../...-/. -.--/---/..-
.- -/---/--/---/.-./.-./---/.--/.-.-.-
--./.-/-.../.-./.././.-../.-.-.-

2002-08-27 18:07:49

by Chris Wedgwood

[permalink] [raw]
Subject: Re: problems with changing UID/GID

On Tue, Aug 27, 2002 at 09:42:27AM -0600, Thunder from the hill wrote:

I don't think this is cool. I mean, think of how many times we use
it, who will eat the overhead?

We use it almost never... a few times per process at most. And the
overhead will be nonexistent except in cases where the caller has to
wait on the lock --- and in those cases it seems totally reasonable
they *should* have to wait.

Basically everyone. (And BTW, if we can't even afford one lock per
module, how could we efford one jock per job? There are definitely
more.)

I'm not sure what you mean here.




--cw

2002-08-27 19:04:05

by Thunder from the hill

[permalink] [raw]
Subject: Re: problems with changing UID/GID

Hi,

On Tue, 27 Aug 2002, Chris Wedgwood wrote:
> On Tue, Aug 27, 2002 at 09:42:27AM -0600, Thunder from the hill wrote:
>
> I don't think this is cool. I mean, think of how many times we use
> it, who will eat the overhead?
>
> We use it almost never... a few times per process at most. And the
> overhead will be nonexistent except in cases where the caller has to
> wait on the lock --- and in those cases it seems totally reasonable they
> *should* have to wait.

And how do you protect a caller from having to wait for the lock? You'd
need a lock count here, where you can only change the credentials when the
count is zero. But when will that ever be?

And btw, the count bumping/downing does cost. We need to do that sensibly.

Thunder
--
--./../...-/. -.--/---/..-/.-./..././.-../..-. .---/..-/.../- .-
--/../-./..-/-/./--..-- ../.----./.-../.-.. --./../...-/. -.--/---/..-
.- -/---/--/---/.-./.-./---/.--/.-.-.-
--./.-/-.../.-./.././.-../.-.-.-

2002-08-27 19:31:31

by Trond Myklebust

[permalink] [raw]
Subject: Re: problems with changing UID/GID

>>>>> " " == Chris Wedgwood <[email protected]> writes:

> On Mon, Aug 26, 2002 at 06:16:59PM +0100, Alan Cox wrote:
> It changes the whole semantics of every security test in
> Linux, and breaks most of them totally. Our syscalls know
> the uid is constant during the call

> Could we not (eventually) have CLONE_CREDs and then lock using
> task->cred->lock or whatever? Or might there be cases where
> this will deadlock? It does mean set[eu]id will have to wait
> of other threads and IO to complete... no matter how long that
> takes, but other than might it be reasonable?

Locking does absolutely nothing for the problem of checking file
access with one set of credentials, and then doing the subsequent file
operation with another set of credentials.

->permission(), ->lookup(), ->create(), ->read(), etc.. may all sleep,
giving some alternate thread ample time to change uid/gid/... behind
your back.

Cheers,
Trond

2002-08-27 19:56:06

by Chris Wedgwood

[permalink] [raw]
Subject: Re: problems with changing UID/GID

On Tue, Aug 27, 2002 at 01:08:04PM -0600, Thunder from the hill wrote:

And how do you protect a caller from having to wait for the lock?

You don't. If they have to wait, then they wait.

You'd need a lock count here, where you can only change the
credentials when the count is zero. But when will that ever be?

It depends... for most non-threaded applications, immediately... for
threaded applications with lots of (day) disk IO, it could be
indefinite.

And btw, the count bumping/downing does cost.

Almost immeasurable. [sg]et[eu]id doesn't get called that often.



--cw

2002-08-27 19:56:55

by Chris Wedgwood

[permalink] [raw]
Subject: Re: problems with changing UID/GID

On Tue, Aug 27, 2002 at 09:35:10PM +0200, Trond Myklebust wrote:

Locking does absolutely nothing for the problem of checking file
access with one set of credentials, and then doing the subsequent file
operation with another set of credentials.

Can we not lock creds at the syscall level? Ick... shoot me for saying
this :)



--cw

2002-08-27 20:22:21

by Thunder from the hill

[permalink] [raw]
Subject: Re: problems with changing UID/GID

Hi,

On Tue, 27 Aug 2002, Chris Wedgwood wrote:
> And how do you protect a caller from having to wait for the lock?
>
> You don't. If they have to wait, then they wait.

That leads to the case that we can only run one process of a credential
sharing group at once. I don't think we need to make it look so bad.
Particularly bad when we have one default credential per user, which would
be the logical step. Solution? Don't share credentials...

Look, that's what you're proposing.

> You'd need a lock count here, where you can only change the
> credentials when the count is zero. But when will that ever be?
>
> It depends... for most non-threaded applications, immediately... for
> threaded applications with lots of (day) disk IO, it could be
> indefinite.

Not exactly.

Process 1 kicks a syscall() -> 1
Process 2 kicks a syscall() -> 2
Process 3 kicks a syscall() -> 3
Process 2 ends syscall() -> 2
Process 4 kicks a syscall() -> 3
Process 1 ends syscall() -> 2
Process 2 kicks syscall() -> 3
Process 5 kicks syscall() -> 4
...

> Almost immeasurable. [sg]et[eu]id doesn't get called that often.

Syscalls do.

Thunder
--
--./../...-/. -.--/---/..-/.-./..././.-../..-. .---/..-/.../- .-
--/../-./..-/-/./--..-- ../.----./.-../.-.. --./../...-/. -.--/---/..-
.- -/---/--/---/.-./.-./---/.--/.-.-.-
--./.-/-.../.-./.././.-../.-.-.-

2002-08-27 20:48:40

by Chris Wedgwood

[permalink] [raw]
Subject: Re: problems with changing UID/GID

On Tue, Aug 27, 2002 at 02:25:08PM -0600, Thunder from the hill wrote:

> Almost immeasurable. [sg]et[eu]id doesn't get called that
> often.

Syscalls do.

And they will almost never have to wait, perhaps spin for a few cycles
in the case of lock contention. The only time a syscall will wait for
extended periods of time will be setuid and friends.



--cw

2002-08-27 21:17:05

by Mike Touloumtzis

[permalink] [raw]
Subject: Re: problems with changing UID/GID

On Mon, Aug 26, 2002 at 02:45:51PM +0100, Alan Cox wrote:
> On Mon, 2002-08-26 at 14:30, Zheng Jian-Ming wrote:
>
> > But, the credentials are per-task in Linux, so it's possible to have
> > two tasks in a process running under different UIDs.
>
> Really useful isnt it
>
> There are other reasons for wanting refcounted credential structures (eg
> NFS writeback) so it may well be that once those go in for other reasons
> it makes sense to provide an option to do shared credentials for
> threaded apps. It is however nontrivial and you might want to see how
> your other systems respond to things like a file open on a slow device
> while a second thread is strobing the uid between two values. Does it
> change uid mid syscall, does it get the permissions checks right if so ?
>
> Its non trivial stuff, if not plain crazy to implement a literal
> interpretation of (eg does a write fail half way if you change userid in
> another thread ?)

Does POSIX really require that granularity of change? Would an
implementation which, say, stored all credentials per-thread/task
and only picked up changes from other threads at kernel entry/exit
not be in spec? That seems like a lower overhead solution than
locking all access to UIDs.

miket

2002-08-27 22:04:49

by Trond Myklebust

[permalink] [raw]
Subject: Re: problems with changing UID/GID

On Tuesday 27 August 2002 22:01, Chris Wedgwood wrote:
> On Tue, Aug 27, 2002 at 09:35:10PM +0200, Trond Myklebust wrote:
>
> Locking does absolutely nothing for the problem of checking file
> access with one set of credentials, and then doing the subsequent file
> operation with another set of credentials.
>
> Can we not lock creds at the syscall level? Ick... shoot me for saying
> this :)

Ick indeed... That sounds pretty nasty now that we have SMP and preemptive
kernels.

I've restarted work on the alternative: putting basic BSD ucreds + VFS changes
in first. It's a lot of work, but I think it will be worth it.

FYI a BSD ucred is basically a structure of the form

struct ucred {
int counter; /* Reference counter */
uid_t uid; /* task->fsuid */
gid_t gid; /* task->fsgid */
int ngroups; /* task->ngroups */
gid_t *groups; /* task->groups */
};

The reference counter + the copy-on-write rule allows you to share it around
to other parts of the kernel (struct file, low level filesystems, ...). By
copy-on-write I mean that once it has been shared, nobody is allowed to
change the values of the data structures (except the reference counter).

Means that you don't need any form of locking for this structure apart from
perhaps in those rare CLONE_CRED instances when you are actually changing the
shared ucred in the task_struct for all the threads.

Cheers,
Trond

2002-08-28 11:49:30

by Florian Weimer

[permalink] [raw]
Subject: Re: problems with changing UID/GID

Alan Cox <[email protected]> writes:

>> But, the credentials are per-task in Linux, so it's possible to have
>> two tasks in a process running under different UIDs.
>
> Really useful isnt it

And not supported by GNU libc, neither officially nor by the current
implementation. :-(

I'd really like to have an explicit parameter for all these process
attributes (the credentials, chroot, maybe something else I'm missing
here; some kind of handle is probably required). chroot() on open()
wouldn't have to require privileges, so it could help web servers
quite a bit.

Some day, I'm going to implement something like this in userspace
(using a privileged daemon and file descriptor passing). But
performance will be horrible.

--
Florian Weimer [email protected]
University of Stuttgart http://CERT.Uni-Stuttgart.DE/people/fw/
RUS-CERT fax +49-711-685-5898

2002-08-28 13:54:43

by Alan

[permalink] [raw]
Subject: Re: problems with changing UID/GID

On Wed, 2002-08-28 at 12:51, Florian Weimer wrote:
> Alan Cox <[email protected]> writes:
>
> >> But, the credentials are per-task in Linux, so it's possible to have
> >> two tasks in a process running under different UIDs.
> >
> > Really useful isnt it
>
> And not supported by GNU libc, neither officially nor by the current
> implementation. :-(

Its supported by clone() and programs using clone directly, not by the
legacy pthreads interface

2002-08-28 14:20:13

by Dave McCracken

[permalink] [raw]
Subject: Re: problems with changing UID/GID


--On Wednesday, August 28, 2002 12:09:03 AM +0200 Trond Myklebust
<[email protected]> wrote:

> FYI a BSD ucred is basically a structure of the form
>
> struct ucred {
> int counter; /* Reference counter */
> uid_t uid; /* task->fsuid */
> gid_t gid; /* task->fsgid */
> int ngroups; /* task->ngroups */
> gid_t *groups; /* task->groups */
> };

Shouldn't the Linux cred structure include the capabilities, as well? What
about places that want to see both uid and euid? Shouldn't euid/egid also
be in the structure? I realize that for file operations they're not
strictly necessary, but we should make the structure useful across all
parts of the kernel that want to see credentials.

BTW, you've convinced me that your approach is the right way to go. I'll
make another stab at CLONE_CRED after the VFS changes are made, which will
make it a 2.7 item, I'm sure.

Dave McCracken

======================================================================
Dave McCracken IBM Linux Base Kernel Team 1-512-838-3059
[email protected] T/L 678-3059

2002-08-28 18:27:17

by Trond Myklebust

[permalink] [raw]
Subject: Re: problems with changing UID/GID

>>>>> " " == Dave McCracken <[email protected]> writes:

> Shouldn't the Linux cred structure include the capabilities, as
> well? What about places that want to see both uid and euid?
> Shouldn't euid/egid also be in the structure? I realize that
> for file operations they're not strictly necessary, but we
> should make the structure useful across all parts of the kernel
> that want to see credentials.

The BSD approach is to split out the user credentials, since they are
used all over the place in the filesystems, and often need to be
cached. The uid, euid, ... are kept in a reference-counted 'process'
credential of the form

struct pcred {
struct ucred *ucred;
uid_t uid, euid, suid;
gid_t gid, egid, sgid;
int count;
};

In Linux, we should probably also include the capabilities as part of
the pcred. They sort of fall outside the BSD model, so it's hard to
tell exactly where they belong...
That said, I'm motivated to move away from thinking that they belong
in the ucred, by the fact that capabilities contain information about
whether or not you are allowed to change those user credentials. That
just doesn't fit with the idea of copy on write.

> BTW, you've convinced me that your approach is the right way to
> go. I'll make another stab at CLONE_CRED after the VFS changes
> are made, which will make it a 2.7 item, I'm sure.

Great. As I said, I've resumed working on the ucred stuff. Expect the
first patches to be announced for 2.5.x soon. The first few patches
are ready, I just need to test them with a post-2.5.32 kernel (as soon
as I find one that will actually boot on my laptop even without the
patches applied).

Note: If you'd like to take a peek at what I've got (and help me with
some feedback), see the directory

http://www.fys.uio.no/~trondmy/src/2.5.32-alpha

Cheers,
Trond

2002-08-28 20:55:41

by Dave McCracken

[permalink] [raw]
Subject: Re: problems with changing UID/GID


--On Wednesday, August 28, 2002 08:30:53 PM +0200 Trond Myklebust
<[email protected]> wrote:

> The BSD approach is to split out the user credentials, since they are
> used all over the place in the filesystems, and often need to be
> cached. The uid, euid, ... are kept in a reference-counted 'process'
> credential of the form

I like that approach, if you really think it's a good idea to have a
separate structure for the subset needed for IO. I'm not clear why it'd be
a bad idea to have one structure and the IO subsystem would only use the
parts it cares about, but you've clearly thought about it more than I have,
so I'll take your word for it.

I looked through your patches. It looks like you're on the right track,
generally. I am a little concerned about some of the current_get*/set*
functions. I'm not entirely convinced there aren't race conditions in
them, but I need to think harder on it.

Dave McCracken

======================================================================
Dave McCracken IBM Linux Base Kernel Team 1-512-838-3059
[email protected] T/L 678-3059

2002-08-28 23:16:28

by Trond Myklebust

[permalink] [raw]
Subject: Re: problems with changing UID/GID

>>>>> " " == Dave McCracken <[email protected]> writes:

> I looked through your patches. It looks like you're on the
> right track, generally. I am a little concerned about some of
> the current_get*/set* functions. I'm not entirely convinced
> there aren't race conditions in them, but I need to think
> harder on it.

Oh, in the current incarnation there are definitely races
w.r.t. CLONE_CRED. The objective of these 3 patches is, however, just
to introduce the basic ucred to the kernel, so that we can get on with
work on the needed VFS changes. Once that process is completed, we
will hopefully just be doing a single current_getucred() per syscall
(and then passing the resulting ucred down to the filesystem layers).

Note: I just updated the original patches with fixed versions that
eliminate a couple of stupid bugs (a couple of automatic
search+replace cases that were screwed). With these fixes, the 2.5.32
kernel boots fine, and appears to be working normally.

Cheers,
Trond