mirror of
https://github.com/torvalds/linux.git
synced 2024-12-01 08:31:37 +00:00
f7e47677e3
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>
166 lines
4.0 KiB
C
166 lines
4.0 KiB
C
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
/* 32-bit compatibility syscall for 64-bit systems
|
|
*
|
|
* Copyright (C) 2004-5 Red Hat, Inc. All Rights Reserved.
|
|
* Written by David Howells (dhowells@redhat.com)
|
|
*/
|
|
|
|
#include <linux/syscalls.h>
|
|
#include <linux/keyctl.h>
|
|
#include <linux/compat.h>
|
|
#include <linux/slab.h>
|
|
#include "internal.h"
|
|
|
|
/*
|
|
* Instantiate a key with the specified compatibility multipart payload and
|
|
* link the key into the destination keyring if one is given.
|
|
*
|
|
* The caller must have the appropriate instantiation permit set for this to
|
|
* work (see keyctl_assume_authority). No other permissions are required.
|
|
*
|
|
* If successful, 0 will be returned.
|
|
*/
|
|
static long compat_keyctl_instantiate_key_iov(
|
|
key_serial_t id,
|
|
const struct compat_iovec __user *_payload_iov,
|
|
unsigned ioc,
|
|
key_serial_t ringid)
|
|
{
|
|
struct iovec iovstack[UIO_FASTIOV], *iov = iovstack;
|
|
struct iov_iter from;
|
|
long ret;
|
|
|
|
if (!_payload_iov)
|
|
ioc = 0;
|
|
|
|
ret = compat_import_iovec(WRITE, _payload_iov, ioc,
|
|
ARRAY_SIZE(iovstack), &iov,
|
|
&from);
|
|
if (ret < 0)
|
|
return ret;
|
|
|
|
ret = keyctl_instantiate_key_common(id, &from, ringid);
|
|
kfree(iov);
|
|
return ret;
|
|
}
|
|
|
|
/*
|
|
* The key control system call, 32-bit compatibility version for 64-bit archs
|
|
*/
|
|
COMPAT_SYSCALL_DEFINE5(keyctl, u32, option,
|
|
u32, arg2, u32, arg3, u32, arg4, u32, arg5)
|
|
{
|
|
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);
|
|
|
|
case KEYCTL_SET_REQKEY_KEYRING:
|
|
return keyctl_set_reqkey_keyring(arg2);
|
|
|
|
case KEYCTL_SET_TIMEOUT:
|
|
return keyctl_set_timeout(arg2, arg3);
|
|
|
|
case KEYCTL_ASSUME_AUTHORITY:
|
|
return keyctl_assume_authority(arg2);
|
|
|
|
case KEYCTL_GET_SECURITY:
|
|
return keyctl_get_security(arg2, compat_ptr(arg3), arg4);
|
|
|
|
case KEYCTL_SESSION_TO_PARENT:
|
|
return keyctl_session_to_parent();
|
|
|
|
case KEYCTL_REJECT:
|
|
return keyctl_reject_key(arg2, arg3, arg4, arg5);
|
|
|
|
case KEYCTL_INSTANTIATE_IOV:
|
|
return compat_keyctl_instantiate_key_iov(
|
|
arg2, compat_ptr(arg3), arg4, arg5);
|
|
|
|
case KEYCTL_INVALIDATE:
|
|
return keyctl_invalidate_key(arg2);
|
|
|
|
case KEYCTL_GET_PERSISTENT:
|
|
return keyctl_get_persistent(arg2, arg3);
|
|
|
|
case KEYCTL_DH_COMPUTE:
|
|
return compat_keyctl_dh_compute(compat_ptr(arg2),
|
|
compat_ptr(arg3),
|
|
arg4, compat_ptr(arg5));
|
|
|
|
case KEYCTL_RESTRICT_KEYRING:
|
|
return keyctl_restrict_keyring(arg2, compat_ptr(arg3),
|
|
compat_ptr(arg4));
|
|
|
|
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));
|
|
|
|
case KEYCTL_MOVE:
|
|
return keyctl_keyring_move(arg2, arg3, arg4, arg5);
|
|
|
|
case KEYCTL_CAPABILITIES:
|
|
return keyctl_capabilities(compat_ptr(arg2), arg3);
|
|
|
|
case KEYCTL_WATCH_KEY:
|
|
return keyctl_watch_key(arg2, arg3, arg4);
|
|
|
|
default:
|
|
return -EOPNOTSUPP;
|
|
}
|
|
}
|