Hi Al, Christoph,
Here's a patch that implements a very basic set of COW credentials. It
compiles and links for x86_64 with EXT3, (V)FAT, NFS, AFS, SELinux and keyrings
all enabled. Most other filesystems are disabled, apart from things like proc.
It is not intended to completely cover the kernel at this point.Note that the keyrings cause a little bit of a problem as the thread, process
and session keyrings can all be installed on one task by another. Furthermore,
the session keyring can be changed by another task.Currently the cred struct shadows the actual keyring pointers, and current_cred
will update the extant cred pointer. I don't like this because it won't work
if the cred struct is being overridden. I can think of three ways of doing it:(1) Permit one process to change another process's cred struct. This means
that a process wishing to read its own creds must use RCU read to do so,
and a lock must be held when replacing the cred struct.(2) Explicitly update the cred struct on entry to syscalls that might want to
use it.(3) Count the number of stacked overrides, and suppress the update behaviour
if it's more than zero.Note that it might be possible to fill in the thread and process keyring
pointers on cred structs that have that pointer set to NULL. However, this
doesn't help for the session keyring pointer.David
---CRED: Introduce a COW credentials record
From: David Howells <dhowells@redhat.com>
Introduce a copy on write credentials record (struct cred). The fsuid, fsgid,
supplementary groups list and thread keyring move into it (DAC security). The
session and process keyrings are reflected in it, but don't primarily reside
there as they aren't per-thread.The LSM security information (MAC security) does *not* migrate from task_struct
at this point, but will be addressed by a later patch.task_struct then gains an RCU-governed pointer to the credentials as a
replacement to the members it lost.str...
Hi Al, Christoph,
Here's a new version of my credentials patch. It's still very basic, with
only Ext3, (V)FAT, NFS, AFS, SELinux and keyrings compiled in on an x86_64
arch kernel. The patched kernel compiles, links and runs.I've made the following major changes to the patch:
(1) System calls that might want to use the credentials call
update_current_cred() before calling into the VFS or whatever. This
allows the keyring pointers in the cred struct to be updated.(2) I've got rid of current_cred(), __current_cred() and the accessors for
current's fsuid, fsgid and group list. Instead you just use
current->cred->whatever. You don't need RCU to read the current threads
credentials as only you are permitted to change them.David
---
CRED: Introduce a COW credentials recordFrom: David Howells <dhowells@redhat.com>
Introduce a copy on write credentials record (struct cred). The fsuid, fsgid,
supplementary groups list move into it (DAC security). The session, process
and thread keyrings are reflected in it, but don't primarily reside there as
they aren't per-thread and occasionally need to be instantiated or replaced by
other threads or processes.The LSM security information (MAC security) does *not* migrate from task_struct
at this point, but will be addressed by a later patch.task_struct then gains an RCU-governed pointer to the credentials as a
replacement to the members it lost.struct file gains a pointer to (f_cred) and a reference on the cred struct that
the opener was using at the time the file was opened. This replaces f_uid and
f_gid.To alter the credentials record, a copy must be made. This copy may then be
altered and then the pointer in the task_struct redirected to it. From that
point on the new record should be considered immutable.In addition, the default setting of i_uid and i_gid to fsuid and fsgid has been
moved from the callers of new_inode() into new_inode() itself.Signed-off-by: David...
What about the process' capabilities? Shouldn't they also be part of a
credential?Cheers
Trond-
As should the LSM security blob, if appropriate.
What I don't really understand is what value is gained by this exercise.
Are the savings sufficiently significant to justify the effort?Casey Schaufler
casey@schaufler-ca.com
-
It is not about savings, but about new functionality. Basically, the
existence of reference-counted credentials will allow AFS and NFS to
cache that information and use it for deferred writes etc.Cheers
Trond-
And also make it easier for cachefiles and hopefully NFSd to override the
active security.There's a comment somewhere in, I think, the SunRPC code in the Linux kernel
bemoaning the lack of this very feature:-)David
-
Quite probably. The cred struct is not closed at this point. I certainly
would like to move some of the stuff hidden behind the security pointer in the
task struct, at least for the purpose of acting on things. For things that
act on the task, the task struct needs a resident label that controls that.David
-
Having thought about this some more, I've realised that this also doesn't work
if when one thread tries to alter another thread's creds that other thread'sSo, I think this has to be the best way to do things. It's the cleanest,
certainly and probably has the lowest overhead overall.This also means that I don't need that horrible __current_cred() function that
Linus so objects to (I do too).David
-
In sys_faccessat you temporarily allocate a cred object which is
discarded in the end. With a few more macro definitions you could
create a dup_cred variant which initialized an automatic variable of
type struct cred. This way the kmalloc/kfree pair would fall away.access is actually used frequently. For instance, ld.so uses it on
every startup as a quicker possibility to check for a file which
usually doesn't exist. So, speeding up access has some small effect
on performance. The resulting code might actually reduce the kernel
size a bit due to all the checks and calls which go away.
-
No, you can't. The filesystems sys_faccessat() then invokes are entitled to
take a reference to it - the SunRPC authentication stuff, for example - so youA better way would be to compare fsuid/fsgid to uid/gid and to just take an
extra ref on the incumbent cred object if they're the same, rather than always
allocating a new one. That, I suspect, would speed up 99.99% of the cases.David
-
Indeed. It's probably rare to have different values and for the case
I mentioned even more so since it happens before the first user code
gets executed.
-
That "current_cred" thing is really too ugly to live.
Why is it trying to make it look like a variable? That will just confuse
people, and/or make them think it's a cheap thing rather than some complex
function call.Also, why does the "__current_cred()" function have those illogical and
insane "#ifdef CONFIG_KEYS" things in it, when it cannot be used/work
sanely without it (and when the header file does a+#ifndef CONFIG_KEYS
+#define __current_cred() ({ current->cred; })
+#else
..anyway?)
IOW, this patch should be taken out and shot, for apparently actively
trying to obfuscate what the heck is going on.Linus
-
Like 'current' for instance?
static __always_inline struct task_struct *get_current(void)
{
return x86_read_percpu(current_task);
}Yes, I know it's silly.
One thing I was trying to do was make it possible to change how the cred
structure was accessed without having to keep going back and change a wholeIt's a 'test' patch, as you'll note from the subject, and not particularly
near completion. I'm interested in garnering useful comments, particularly on
the points of concern that I raised.I have no intention of asking you to merge it as it stands - I was hoping that
would be clear.David
-
"current" has solid *historical* reasons for being that way.
Namely: it actually *was* a variable. That worked fine for UP. It got
changed much much later.Also, even in modern times, "current" is optimized to hell and back, and
is often as cheap (or cheaper than) a global variable, so there is also no
subtle performance question.So using "current" as an excuse is not really valid. AT ALL.
Linus
-
| Parag Warudkar | BUG: soft lockup - CPU#1 stuck for 15s! [swapper:0] |
| Tarkan Erimer | Re: Dual-Licensing Linux Kernel with GPL V2 and GPL V3 |
| Greg Kroah-Hartman | [PATCH 010/196] Chinese: add translation of Codingstyle |
| Andrew Morton | -mm merge plans for 2.6.23 |
git: | |
| Gerrit Renker | [PATCH 24/37] dccp: Processing Confirm options |
| David Miller | Re: [PATCH] pkt_sched: Destroy gen estimators under rtnl_lock(). |
| Alexey Dobriyan | Re: [GIT]: Networking |
| david | Re: iptables very slow after commit 784544739a25c30637397ace5489eeb6e15d7d49 |
