mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-11-01 08:58:07 +00:00
ee18d64c1f
Add a keyctl to install a process's session keyring onto its parent. This replaces the parent's session keyring. Because the COW credential code does not permit one process to change another process's credentials directly, the change is deferred until userspace next starts executing again. Normally this will be after a wait*() syscall. To support this, three new security hooks have been provided: cred_alloc_blank() to allocate unset security creds, cred_transfer() to fill in the blank security creds and key_session_to_parent() - which asks the LSM if the process may replace its parent's session keyring. The replacement may only happen if the process has the same ownership details as its parent, and the process has LINK permission on the session keyring, and the session keyring is owned by the process, and the LSM permits it. Note that this requires alteration to each architecture's notify_resume path. This has been done for all arches barring blackfin, m68k* and xtensa, all of which need assembly alteration to support TIF_NOTIFY_RESUME. This allows the replacement to be performed at the point the parent process resumes userspace execution. This allows the userspace AFS pioctl emulation to fully emulate newpag() and the VIOCSETTOK and VIOCSETTOK2 pioctls, all of which require the ability to alter the parent process's PAG membership. However, since kAFS doesn't use PAGs per se, but rather dumps the keys into the session keyring, the session keyring of the parent must be replaced if, for example, VIOCSETTOK is passed the newpag flag. This can be tested with the following program: #include <stdio.h> #include <stdlib.h> #include <keyutils.h> #define KEYCTL_SESSION_TO_PARENT 18 #define OSERROR(X, S) do { if ((long)(X) == -1) { perror(S); exit(1); } } while(0) int main(int argc, char **argv) { key_serial_t keyring, key; long ret; keyring = keyctl_join_session_keyring(argv[1]); OSERROR(keyring, "keyctl_join_session_keyring"); key = add_key("user", "a", "b", 1, keyring); OSERROR(key, "add_key"); ret = keyctl(KEYCTL_SESSION_TO_PARENT); OSERROR(ret, "KEYCTL_SESSION_TO_PARENT"); return 0; } Compiled and linked with -lkeyutils, you should see something like: [dhowells@andromeda ~]$ keyctl show Session Keyring -3 --alswrv 4043 4043 keyring: _ses 355907932 --alswrv 4043 -1 \_ keyring: _uid.4043 [dhowells@andromeda ~]$ /tmp/newpag [dhowells@andromeda ~]$ keyctl show Session Keyring -3 --alswrv 4043 4043 keyring: _ses 1055658746 --alswrv 4043 4043 \_ user: a [dhowells@andromeda ~]$ /tmp/newpag hello [dhowells@andromeda ~]$ keyctl show Session Keyring -3 --alswrv 4043 4043 keyring: hello 340417692 --alswrv 4043 4043 \_ user: a Where the test program creates a new session keyring, sticks a user key named 'a' into it and then installs it on its parent. Signed-off-by: David Howells <dhowells@redhat.com> Signed-off-by: James Morris <jmorris@namei.org>
57 lines
2.7 KiB
C
57 lines
2.7 KiB
C
/* keyctl.h: keyctl command IDs
|
|
*
|
|
* Copyright (C) 2004, 2008 Red Hat, Inc. All Rights Reserved.
|
|
* Written by David Howells (dhowells@redhat.com)
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version
|
|
* 2 of the License, or (at your option) any later version.
|
|
*/
|
|
|
|
#ifndef _LINUX_KEYCTL_H
|
|
#define _LINUX_KEYCTL_H
|
|
|
|
/* special process keyring shortcut IDs */
|
|
#define KEY_SPEC_THREAD_KEYRING -1 /* - key ID for thread-specific keyring */
|
|
#define KEY_SPEC_PROCESS_KEYRING -2 /* - key ID for process-specific keyring */
|
|
#define KEY_SPEC_SESSION_KEYRING -3 /* - key ID for session-specific keyring */
|
|
#define KEY_SPEC_USER_KEYRING -4 /* - key ID for UID-specific keyring */
|
|
#define KEY_SPEC_USER_SESSION_KEYRING -5 /* - key ID for UID-session keyring */
|
|
#define KEY_SPEC_GROUP_KEYRING -6 /* - key ID for GID-specific keyring */
|
|
#define KEY_SPEC_REQKEY_AUTH_KEY -7 /* - key ID for assumed request_key auth key */
|
|
#define KEY_SPEC_REQUESTOR_KEYRING -8 /* - key ID for request_key() dest keyring */
|
|
|
|
/* request-key default keyrings */
|
|
#define KEY_REQKEY_DEFL_NO_CHANGE -1
|
|
#define KEY_REQKEY_DEFL_DEFAULT 0
|
|
#define KEY_REQKEY_DEFL_THREAD_KEYRING 1
|
|
#define KEY_REQKEY_DEFL_PROCESS_KEYRING 2
|
|
#define KEY_REQKEY_DEFL_SESSION_KEYRING 3
|
|
#define KEY_REQKEY_DEFL_USER_KEYRING 4
|
|
#define KEY_REQKEY_DEFL_USER_SESSION_KEYRING 5
|
|
#define KEY_REQKEY_DEFL_GROUP_KEYRING 6
|
|
#define KEY_REQKEY_DEFL_REQUESTOR_KEYRING 7
|
|
|
|
/* keyctl commands */
|
|
#define KEYCTL_GET_KEYRING_ID 0 /* ask for a keyring's ID */
|
|
#define KEYCTL_JOIN_SESSION_KEYRING 1 /* join or start named session keyring */
|
|
#define KEYCTL_UPDATE 2 /* update a key */
|
|
#define KEYCTL_REVOKE 3 /* revoke a key */
|
|
#define KEYCTL_CHOWN 4 /* set ownership of a key */
|
|
#define KEYCTL_SETPERM 5 /* set perms on a key */
|
|
#define KEYCTL_DESCRIBE 6 /* describe a key */
|
|
#define KEYCTL_CLEAR 7 /* clear contents of a keyring */
|
|
#define KEYCTL_LINK 8 /* link a key into a keyring */
|
|
#define KEYCTL_UNLINK 9 /* unlink a key from a keyring */
|
|
#define KEYCTL_SEARCH 10 /* search for a key in a keyring */
|
|
#define KEYCTL_READ 11 /* read a key or keyring's contents */
|
|
#define KEYCTL_INSTANTIATE 12 /* instantiate a partially constructed key */
|
|
#define KEYCTL_NEGATE 13 /* negate a partially constructed key */
|
|
#define KEYCTL_SET_REQKEY_KEYRING 14 /* set default request-key keyring */
|
|
#define KEYCTL_SET_TIMEOUT 15 /* set key timeout */
|
|
#define KEYCTL_ASSUME_AUTHORITY 16 /* assume request_key() authorisation */
|
|
#define KEYCTL_GET_SECURITY 17 /* get key security label */
|
|
#define KEYCTL_SESSION_TO_PARENT 18 /* apply session keyring to parent process */
|
|
|
|
#endif /* _LINUX_KEYCTL_H */
|