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>
This commit is contained in:
@@ -1026,6 +1026,63 @@ The keyctl syscall functions are:
|
||||
written into the output buffer. Verification returns 0 on success.
|
||||
|
||||
|
||||
* Watch a key or keyring for changes::
|
||||
|
||||
long keyctl(KEYCTL_WATCH_KEY, key_serial_t key, int queue_fd,
|
||||
const struct watch_notification_filter *filter);
|
||||
|
||||
This will set or remove a watch for changes on the specified key or
|
||||
keyring.
|
||||
|
||||
"key" is the ID of the key to be watched.
|
||||
|
||||
"queue_fd" is a file descriptor referring to an open "/dev/watch_queue"
|
||||
which manages the buffer into which notifications will be delivered.
|
||||
|
||||
"filter" is either NULL to remove a watch or a filter specification to
|
||||
indicate what events are required from the key.
|
||||
|
||||
See Documentation/watch_queue.rst for more information.
|
||||
|
||||
Note that only one watch may be emplaced for any particular { key,
|
||||
queue_fd } combination.
|
||||
|
||||
Notification records look like::
|
||||
|
||||
struct key_notification {
|
||||
struct watch_notification watch;
|
||||
__u32 key_id;
|
||||
__u32 aux;
|
||||
};
|
||||
|
||||
In this, watch::type will be "WATCH_TYPE_KEY_NOTIFY" and subtype will be
|
||||
one of::
|
||||
|
||||
NOTIFY_KEY_INSTANTIATED
|
||||
NOTIFY_KEY_UPDATED
|
||||
NOTIFY_KEY_LINKED
|
||||
NOTIFY_KEY_UNLINKED
|
||||
NOTIFY_KEY_CLEARED
|
||||
NOTIFY_KEY_REVOKED
|
||||
NOTIFY_KEY_INVALIDATED
|
||||
NOTIFY_KEY_SETATTR
|
||||
|
||||
Where these indicate a key being instantiated/rejected, updated, a link
|
||||
being made in a keyring, a link being removed from a keyring, a keyring
|
||||
being cleared, a key being revoked, a key being invalidated or a key
|
||||
having one of its attributes changed (user, group, perm, timeout,
|
||||
restriction).
|
||||
|
||||
If a watched key is deleted, a basic watch_notification will be issued
|
||||
with "type" set to WATCH_TYPE_META and "subtype" set to
|
||||
watch_meta_removal_notification. The watchpoint ID will be set in the
|
||||
"info" field.
|
||||
|
||||
This needs to be configured by enabling:
|
||||
|
||||
"Provide key/keyring change notifications" (KEY_NOTIFICATIONS)
|
||||
|
||||
|
||||
Kernel Services
|
||||
===============
|
||||
|
||||
|
Reference in New Issue
Block a user