2019-05-27 09:55:01 +03:00
|
|
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
2011-01-20 19:38:33 +03:00
|
|
|
/* 32-bit compatibility syscall for 64-bit systems
|
2005-04-17 02:20:36 +04:00
|
|
|
*
|
[PATCH] Keys: Make request-key create an authorisation key
The attached patch makes the following changes:
(1) There's a new special key type called ".request_key_auth".
This is an authorisation key for when one process requests a key and
another process is started to construct it. This type of key cannot be
created by the user; nor can it be requested by kernel services.
Authorisation keys hold two references:
(a) Each refers to a key being constructed. When the key being
constructed is instantiated the authorisation key is revoked,
rendering it of no further use.
(b) The "authorising process". This is either:
(i) the process that called request_key(), or:
(ii) if the process that called request_key() itself had an
authorisation key in its session keyring, then the authorising
process referred to by that authorisation key will also be
referred to by the new authorisation key.
This means that the process that initiated a chain of key requests
will authorise the lot of them, and will, by default, wind up with
the keys obtained from them in its keyrings.
(2) request_key() creates an authorisation key which is then passed to
/sbin/request-key in as part of a new session keyring.
(3) When request_key() is searching for a key to hand back to the caller, if
it comes across an authorisation key in the session keyring of the
calling process, it will also search the keyrings of the process
specified therein and it will use the specified process's credentials
(fsuid, fsgid, groups) to do that rather than the calling process's
credentials.
This allows a process started by /sbin/request-key to find keys belonging
to the authorising process.
(4) A key can be read, even if the process executing KEYCTL_READ doesn't have
direct read or search permission if that key is contained within the
keyrings of a process specified by an authorisation key found within the
calling process's session keyring, and is searchable using the
credentials of the authorising process.
This allows a process started by /sbin/request-key to read keys belonging
to the authorising process.
(5) The magic KEY_SPEC_*_KEYRING key IDs when passed to KEYCTL_INSTANTIATE or
KEYCTL_NEGATE will specify a keyring of the authorising process, rather
than the process doing the instantiation.
(6) One of the process keyrings can be nominated as the default to which
request_key() should attach new keys if not otherwise specified. This is
done with KEYCTL_SET_REQKEY_KEYRING and one of the KEY_REQKEY_DEFL_*
constants. The current setting can also be read using this call.
(7) request_key() is partially interruptible. If it is waiting for another
process to finish constructing a key, it can be interrupted. This permits
a request-key cycle to be broken without recourse to rebooting.
Signed-Off-By: David Howells <dhowells@redhat.com>
Signed-Off-By: Benoit Boissinot <benoit.boissinot@ens-lyon.org>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2005-06-24 09:00:56 +04:00
|
|
|
* Copyright (C) 2004-5 Red Hat, Inc. All Rights Reserved.
|
2005-04-17 02:20:36 +04:00
|
|
|
* Written by David Howells (dhowells@redhat.com)
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <linux/syscalls.h>
|
|
|
|
#include <linux/keyctl.h>
|
|
|
|
#include <linux/compat.h>
|
2011-03-07 18:06:20 +03:00
|
|
|
#include <linux/slab.h>
|
2005-04-17 02:20:36 +04:00
|
|
|
#include "internal.h"
|
|
|
|
|
|
|
|
/*
|
2011-01-20 19:38:33 +03:00
|
|
|
* The key control system call, 32-bit compatibility version for 64-bit archs
|
2005-04-17 02:20:36 +04:00
|
|
|
*/
|
2014-03-03 19:34:41 +04:00
|
|
|
COMPAT_SYSCALL_DEFINE5(keyctl, u32, option,
|
|
|
|
u32, arg2, u32, arg3, u32, arg4, u32, arg5)
|
2005-04-17 02:20:36 +04:00
|
|
|
{
|
|
|
|
switch (option) {
|
|
|
|
case KEYCTL_GET_KEYRING_ID:
|
|
|
|
return keyctl_get_keyring_ID(arg2, arg3);
|
|
|
|
|
|
|
|
case KEYCTL_JOIN_SESSION_KEYRING:
|
|
|
|
return keyctl_join_session_keyring(compat_ptr(arg2));
|
|
|
|
|
|
|
|
case KEYCTL_UPDATE:
|
|
|
|
return keyctl_update_key(arg2, compat_ptr(arg3), arg4);
|
|
|
|
|
|
|
|
case KEYCTL_REVOKE:
|
|
|
|
return keyctl_revoke_key(arg2);
|
|
|
|
|
|
|
|
case KEYCTL_DESCRIBE:
|
|
|
|
return keyctl_describe_key(arg2, compat_ptr(arg3), arg4);
|
|
|
|
|
|
|
|
case KEYCTL_CLEAR:
|
|
|
|
return keyctl_keyring_clear(arg2);
|
|
|
|
|
|
|
|
case KEYCTL_LINK:
|
|
|
|
return keyctl_keyring_link(arg2, arg3);
|
|
|
|
|
|
|
|
case KEYCTL_UNLINK:
|
|
|
|
return keyctl_keyring_unlink(arg2, arg3);
|
|
|
|
|
|
|
|
case KEYCTL_SEARCH:
|
|
|
|
return keyctl_keyring_search(arg2, compat_ptr(arg3),
|
|
|
|
compat_ptr(arg4), arg5);
|
|
|
|
|
|
|
|
case KEYCTL_READ:
|
|
|
|
return keyctl_read_key(arg2, compat_ptr(arg3), arg4);
|
|
|
|
|
|
|
|
case KEYCTL_CHOWN:
|
|
|
|
return keyctl_chown_key(arg2, arg3, arg4);
|
|
|
|
|
|
|
|
case KEYCTL_SETPERM:
|
|
|
|
return keyctl_setperm_key(arg2, arg3);
|
|
|
|
|
|
|
|
case KEYCTL_INSTANTIATE:
|
|
|
|
return keyctl_instantiate_key(arg2, compat_ptr(arg3), arg4,
|
|
|
|
arg5);
|
|
|
|
|
|
|
|
case KEYCTL_NEGATE:
|
|
|
|
return keyctl_negate_key(arg2, arg3, arg4);
|
|
|
|
|
[PATCH] Keys: Make request-key create an authorisation key
The attached patch makes the following changes:
(1) There's a new special key type called ".request_key_auth".
This is an authorisation key for when one process requests a key and
another process is started to construct it. This type of key cannot be
created by the user; nor can it be requested by kernel services.
Authorisation keys hold two references:
(a) Each refers to a key being constructed. When the key being
constructed is instantiated the authorisation key is revoked,
rendering it of no further use.
(b) The "authorising process". This is either:
(i) the process that called request_key(), or:
(ii) if the process that called request_key() itself had an
authorisation key in its session keyring, then the authorising
process referred to by that authorisation key will also be
referred to by the new authorisation key.
This means that the process that initiated a chain of key requests
will authorise the lot of them, and will, by default, wind up with
the keys obtained from them in its keyrings.
(2) request_key() creates an authorisation key which is then passed to
/sbin/request-key in as part of a new session keyring.
(3) When request_key() is searching for a key to hand back to the caller, if
it comes across an authorisation key in the session keyring of the
calling process, it will also search the keyrings of the process
specified therein and it will use the specified process's credentials
(fsuid, fsgid, groups) to do that rather than the calling process's
credentials.
This allows a process started by /sbin/request-key to find keys belonging
to the authorising process.
(4) A key can be read, even if the process executing KEYCTL_READ doesn't have
direct read or search permission if that key is contained within the
keyrings of a process specified by an authorisation key found within the
calling process's session keyring, and is searchable using the
credentials of the authorising process.
This allows a process started by /sbin/request-key to read keys belonging
to the authorising process.
(5) The magic KEY_SPEC_*_KEYRING key IDs when passed to KEYCTL_INSTANTIATE or
KEYCTL_NEGATE will specify a keyring of the authorising process, rather
than the process doing the instantiation.
(6) One of the process keyrings can be nominated as the default to which
request_key() should attach new keys if not otherwise specified. This is
done with KEYCTL_SET_REQKEY_KEYRING and one of the KEY_REQKEY_DEFL_*
constants. The current setting can also be read using this call.
(7) request_key() is partially interruptible. If it is waiting for another
process to finish constructing a key, it can be interrupted. This permits
a request-key cycle to be broken without recourse to rebooting.
Signed-Off-By: David Howells <dhowells@redhat.com>
Signed-Off-By: Benoit Boissinot <benoit.boissinot@ens-lyon.org>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2005-06-24 09:00:56 +04:00
|
|
|
case KEYCTL_SET_REQKEY_KEYRING:
|
|
|
|
return keyctl_set_reqkey_keyring(arg2);
|
|
|
|
|
2006-01-08 12:02:43 +03:00
|
|
|
case KEYCTL_SET_TIMEOUT:
|
|
|
|
return keyctl_set_timeout(arg2, arg3);
|
|
|
|
|
2006-01-08 12:02:47 +03:00
|
|
|
case KEYCTL_ASSUME_AUTHORITY:
|
|
|
|
return keyctl_assume_authority(arg2);
|
|
|
|
|
2008-04-29 12:01:26 +04:00
|
|
|
case KEYCTL_GET_SECURITY:
|
|
|
|
return keyctl_get_security(arg2, compat_ptr(arg3), arg4);
|
|
|
|
|
KEYS: Add a keyctl to install a process's session keyring on its parent [try #6]
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>
2009-09-02 12:14:21 +04:00
|
|
|
case KEYCTL_SESSION_TO_PARENT:
|
|
|
|
return keyctl_session_to_parent();
|
|
|
|
|
2011-03-07 18:06:09 +03:00
|
|
|
case KEYCTL_REJECT:
|
|
|
|
return keyctl_reject_key(arg2, arg3, arg4, arg5);
|
|
|
|
|
2011-03-07 18:06:20 +03:00
|
|
|
case KEYCTL_INSTANTIATE_IOV:
|
2020-09-25 07:51:46 +03:00
|
|
|
return keyctl_instantiate_key_iov(arg2, compat_ptr(arg3), arg4,
|
|
|
|
arg5);
|
2011-03-07 18:06:20 +03:00
|
|
|
|
2012-05-11 13:56:56 +04:00
|
|
|
case KEYCTL_INVALIDATE:
|
|
|
|
return keyctl_invalidate_key(arg2);
|
|
|
|
|
2013-09-24 13:35:19 +04:00
|
|
|
case KEYCTL_GET_PERSISTENT:
|
|
|
|
return keyctl_get_persistent(arg2, arg3);
|
|
|
|
|
2016-04-12 21:54:58 +03:00
|
|
|
case KEYCTL_DH_COMPUTE:
|
2016-08-19 21:39:09 +03:00
|
|
|
return compat_keyctl_dh_compute(compat_ptr(arg2),
|
|
|
|
compat_ptr(arg3),
|
|
|
|
arg4, compat_ptr(arg5));
|
2016-04-12 21:54:58 +03:00
|
|
|
|
2017-03-02 03:44:09 +03:00
|
|
|
case KEYCTL_RESTRICT_KEYRING:
|
|
|
|
return keyctl_restrict_keyring(arg2, compat_ptr(arg3),
|
|
|
|
compat_ptr(arg4));
|
|
|
|
|
KEYS: Provide keyctls to drive the new key type ops for asymmetric keys [ver #2]
Provide five keyctl functions that permit userspace to make use of the new
key type ops for accessing and driving asymmetric keys.
(*) Query an asymmetric key.
long keyctl(KEYCTL_PKEY_QUERY,
key_serial_t key, unsigned long reserved,
struct keyctl_pkey_query *info);
Get information about an asymmetric key. The information is returned
in the keyctl_pkey_query struct:
__u32 supported_ops;
A bit mask of flags indicating which ops are supported. This is
constructed from a bitwise-OR of:
KEYCTL_SUPPORTS_{ENCRYPT,DECRYPT,SIGN,VERIFY}
__u32 key_size;
The size in bits of the key.
__u16 max_data_size;
__u16 max_sig_size;
__u16 max_enc_size;
__u16 max_dec_size;
The maximum sizes in bytes of a blob of data to be signed, a signature
blob, a blob to be encrypted and a blob to be decrypted.
reserved must be set to 0. This is intended for future use to hand
over one or more passphrases needed unlock a key.
If successful, 0 is returned. If the key is not an asymmetric key,
EOPNOTSUPP is returned.
(*) Encrypt, decrypt, sign or verify a blob using an asymmetric key.
long keyctl(KEYCTL_PKEY_ENCRYPT,
const struct keyctl_pkey_params *params,
const char *info,
const void *in,
void *out);
long keyctl(KEYCTL_PKEY_DECRYPT,
const struct keyctl_pkey_params *params,
const char *info,
const void *in,
void *out);
long keyctl(KEYCTL_PKEY_SIGN,
const struct keyctl_pkey_params *params,
const char *info,
const void *in,
void *out);
long keyctl(KEYCTL_PKEY_VERIFY,
const struct keyctl_pkey_params *params,
const char *info,
const void *in,
const void *in2);
Use an asymmetric key to perform a public-key cryptographic operation
a blob of data.
The parameter block pointed to by params contains a number of integer
values:
__s32 key_id;
__u32 in_len;
__u32 out_len;
__u32 in2_len;
For a given operation, the in and out buffers are used as follows:
Operation ID in,in_len out,out_len in2,in2_len
======================= =============== =============== ===========
KEYCTL_PKEY_ENCRYPT Raw data Encrypted data -
KEYCTL_PKEY_DECRYPT Encrypted data Raw data -
KEYCTL_PKEY_SIGN Raw data Signature -
KEYCTL_PKEY_VERIFY Raw data - Signature
info is a string of key=value pairs that supply supplementary
information.
The __spare space in the parameter block must be set to 0. This is
intended, amongst other things, to allow the passing of passphrases
required to unlock a key.
If successful, encrypt, decrypt and sign all return the amount of data
written into the output buffer. Verification returns 0 on success.
Signed-off-by: David Howells <dhowells@redhat.com>
Tested-by: Marcel Holtmann <marcel@holtmann.org>
Reviewed-by: Marcel Holtmann <marcel@holtmann.org>
Reviewed-by: Denis Kenzior <denkenz@gmail.com>
Tested-by: Denis Kenzior <denkenz@gmail.com>
Signed-off-by: James Morris <james.morris@microsoft.com>
2018-10-09 19:46:59 +03:00
|
|
|
case KEYCTL_PKEY_QUERY:
|
|
|
|
if (arg3 != 0)
|
|
|
|
return -EINVAL;
|
|
|
|
return keyctl_pkey_query(arg2,
|
|
|
|
compat_ptr(arg4),
|
|
|
|
compat_ptr(arg5));
|
|
|
|
|
|
|
|
case KEYCTL_PKEY_ENCRYPT:
|
|
|
|
case KEYCTL_PKEY_DECRYPT:
|
|
|
|
case KEYCTL_PKEY_SIGN:
|
|
|
|
return keyctl_pkey_e_d_s(option,
|
|
|
|
compat_ptr(arg2), compat_ptr(arg3),
|
|
|
|
compat_ptr(arg4), compat_ptr(arg5));
|
|
|
|
|
|
|
|
case KEYCTL_PKEY_VERIFY:
|
|
|
|
return keyctl_pkey_verify(compat_ptr(arg2), compat_ptr(arg3),
|
|
|
|
compat_ptr(arg4), compat_ptr(arg5));
|
|
|
|
|
2019-05-20 23:51:50 +03:00
|
|
|
case KEYCTL_MOVE:
|
|
|
|
return keyctl_keyring_move(arg2, arg3, arg4, arg5);
|
|
|
|
|
2019-05-30 16:53:10 +03:00
|
|
|
case KEYCTL_CAPABILITIES:
|
|
|
|
return keyctl_capabilities(compat_ptr(arg2), arg3);
|
|
|
|
|
watch_queue: Add a key/keyring notification facility
Add a key/keyring change notification facility whereby notifications about
changes in key and keyring content and attributes can be received.
Firstly, an event queue needs to be created:
pipe2(fds, O_NOTIFICATION_PIPE);
ioctl(fds[1], IOC_WATCH_QUEUE_SET_SIZE, 256);
then a notification can be set up to report notifications via that queue:
struct watch_notification_filter filter = {
.nr_filters = 1,
.filters = {
[0] = {
.type = WATCH_TYPE_KEY_NOTIFY,
.subtype_filter[0] = UINT_MAX,
},
},
};
ioctl(fds[1], IOC_WATCH_QUEUE_SET_FILTER, &filter);
keyctl_watch_key(KEY_SPEC_SESSION_KEYRING, fds[1], 0x01);
After that, records will be placed into the queue when events occur in
which keys are changed in some way. Records are of the following format:
struct key_notification {
struct watch_notification watch;
__u32 key_id;
__u32 aux;
} *n;
Where:
n->watch.type will be WATCH_TYPE_KEY_NOTIFY.
n->watch.subtype will indicate the type of event, such as
NOTIFY_KEY_REVOKED.
n->watch.info & WATCH_INFO_LENGTH will indicate the length of the
record.
n->watch.info & WATCH_INFO_ID will be the second argument to
keyctl_watch_key(), shifted.
n->key will be the ID of the affected key.
n->aux will hold subtype-dependent information, such as the key
being linked into the keyring specified by n->key in the case of
NOTIFY_KEY_LINKED.
Note that it is permissible for event records to be of variable length -
or, at least, the length may be dependent on the subtype. Note also that
the queue can be shared between multiple notifications of various types.
Signed-off-by: David Howells <dhowells@redhat.com>
Reviewed-by: James Morris <jamorris@linux.microsoft.com>
2020-01-14 20:07:11 +03:00
|
|
|
case KEYCTL_WATCH_KEY:
|
|
|
|
return keyctl_watch_key(arg2, arg3, arg4);
|
|
|
|
|
2005-04-17 02:20:36 +04:00
|
|
|
default:
|
|
|
|
return -EOPNOTSUPP;
|
|
|
|
}
|
2011-01-20 19:38:27 +03:00
|
|
|
}
|