Messages in this thread | ![/](/images/icornerl.gif) | | From | David Howells <> | Subject | Alternative to PAGs | Date | Thu, 15 May 2003 15:15:49 +0100 |
| |
Hi Linus,
Okay, starting with a clean slate and writing PAGs off as a bad idea, how about trying to work out what is required first? As I see it:
THE REQUIREMENTS ================
(1) Credentials/tokens/keys/whatever are held in a "keyring".
(2) A keyring is destroyed when the last reference goes away (kernel resources are precious, though it may be possible to store credentials in swapspace somehow).
(3) Every user has to have a default keyring that is created the first time they log in [Linus demands this].
(4) A user has to be able to override the default keyring, such that they can, for instance, perform operations on a remote filesystem with a different credential.
(5) A user has to be able to run a program with a reduced set of credentials.
(6) A process must be able to pass a subset of its credentials to a second, already running process so that the second process can perform some service on its behalf.
This gets tricky if the service process is performing services for a number of processes simultaneously, each of which has its own set of credentials.
(7) A process should be able to discard any credential it has access to, particularly in conjunction with (6).
(8) It must be possible to withdraw a credential.
(9) The credentials governing access to a file must be associated with a struct file, not with the process context currently accessing a file.
(10) A struct file will gain its credentials at the time it is opened.
POSSIBLE EXTENSIONS ===================
(11) Threads should perhaps share a common set of credentials, but be able to adjust them on a per-thread basis (see (6)).
(12) A SUID process should add the credentials it gains from its new user ID to those it inherited from its original context.
(13) There's one place Win32 has an advantage, I think: calls for setting up handles (files, mutexes, etc) take security context parameters.
I think "groups" specific keyrings and arbitrary joinable keyrings are superfluous (that's what ACLs are for) and a systems maintenance nightmare, so I haven't included them.
SUGGESTED IMPLEMENTATION ========================
As far as implementation goes, perhaps each task_struct and each file should point to a stack of keyrings:
+------+ | | +--------------------->| USER | | | | | +------+ | +------+ +------+ +------+ +------+ | | | | | | | | | TASK |----->| SUID |---->| PRIV |---->| USER | | | | | | | | | +------+ +------+ +------+ +------+ ^ ^ +------+ | | | | | | | FILE |---------+ | | | | +------+ | | +------+ | | | | | FILE |----------------------+ | | ^ +------+ | | +------+ +------+ +------+ | | | | | | | TASK |----->| FILE |----------------->| USER | | | | | | | +------+ +------+ +------+
The keyrings in the stack would then be refcounted, and the next pointers would be immutable.
struct keyring { struct keyring *next; struct keyring *conjunction; struct list_head keys; atomic_t usage; int type; #define KEYRING_USER 0 #define KEYRING_PRIVATE 1 #define KEYRING_SUID 2 #define KEYRING_FD 3 };
struct key { struct list_head link; atomic_t usage; int type; #define KEY_POSITIVE 0 #define KEY_NEGATIVE 1 void *credential; };
And then add the following syscalls:
(*) auth_clear_stack(int completely)
Totally clear a process's stack (either completely or of everything but the user credentials).
(*) auth_add_cred(const char *fs, const char *domain, void *data);
Add a new credential to the TOS keyring. The key would be negative if data is NULL.
(*) auth_push_empty()
Push an empty keyring onto this process's stack.
(*) auth_push_fdcreds(int fd)
Push the credentials associated with fd onto the stack as a preferred alternative.
(*) auth_pop()
Pop the top credential off of the stack.
David - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
| ![\](/images/icornerr.gif) |