diff options
author | David Howells <dhowells@redhat.com> | 2020-07-07 16:56:53 +0100 |
---|---|---|
committer | David Howells <dhowells@redhat.com> | 2020-07-07 16:56:53 +0100 |
commit | f3095f4901820d31cc5600ee46949bcdb246b3fa (patch) | |
tree | 43f12abc498a8e06f137a328662ceca15e781ec9 | |
parent | d00ed3599d5fccf81eac32eada0c1b33e67ba973 (diff) | |
download | keyutils-f3095f4901820d31cc5600ee46949bcdb246b3fa.tar.gz |
Revert "Add a notification facility for watching for key changes"
This reverts commit 1aafbdcf1d60c5c9eb34fe404f9a9195c8ea415e which was from
the wrong branch and expects /dev/watch_queue to be available.
Signed-off-by: David Howells <dhowells@redhat.com>
-rw-r--r-- | Makefile | 8 | ||||
-rw-r--r-- | keyctl.c | 13 | ||||
-rw-r--r-- | keyctl.h | 13 | ||||
-rw-r--r-- | keyctl_watch.c | 499 | ||||
-rw-r--r-- | keyutils.c | 5 | ||||
-rw-r--r-- | keyutils.h | 3 | ||||
-rw-r--r-- | man/keyctl.1 | 92 | ||||
-rw-r--r-- | man/keyctl.3 | 2 | ||||
-rw-r--r-- | man/keyctl_watch_key.3 | 206 | ||||
-rw-r--r-- | tests/prepare.inc.sh | 1 | ||||
-rw-r--r-- | version.lds | 2 | ||||
-rw-r--r-- | watch_queue.h | 128 |
12 files changed, 9 insertions, 963 deletions
@@ -150,11 +150,9 @@ endif %.o: %.c keyutils.h Makefile $(CC) $(CPPFLAGS) $(CFLAGS) -o $@ -c $< -keyctl: keyctl.o keyctl_testing.o keyctl_watch.o $(LIB_DEPENDENCY) - $(CC) -L. $(CFLAGS) $(LDFLAGS) $(RPATH) -o $@ \ - keyctl.o keyctl_testing.o keyctl_watch.o -lkeyutils -keyctl.o keyctl_testing.o keyctl_watch.o: keyctl.h -keyctl_watch.o: watch_queue.h +keyctl: keyctl.o keyctl_testing.o $(LIB_DEPENDENCY) + $(CC) -L. $(CFLAGS) $(LDFLAGS) $(RPATH) -o $@ keyctl.o keyctl_testing.o -lkeyutils +keyctl.o keyctl_testing.o: keyctl.h request-key: request-key.o $(LIB_DEPENDENCY) $(CC) -L. $(CFLAGS) $(LDFLAGS) $(RPATH) -o $@ $< -lkeyutils @@ -139,16 +139,14 @@ static const struct command commands[] = { { act_keyctl_timeout, "timeout", "<key> <timeout>" }, { act_keyctl_unlink, "unlink", "<key> [<keyring>]" }, { act_keyctl_update, "update", "[-x] <key> <data>" }, - { act_keyctl_watch, "watch", "<key>" }, - { act_keyctl_watch_add, "watch_add", "<fd> <key>" }, - { act_keyctl_watch_rm, "watch_rm", "<fd> <key>" }, - { act_keyctl_watch_session, "watch_session", "[-n <name>] <notifylog> <gclog> <fd> <prog> [<arg1> <arg2> ...]" }, - { act_keyctl_watch_sync, "watch_sync", "<fd>" }, { act_keyctl_test, "--test", "..." }, { NULL, NULL, NULL } }; static int dump_key_tree(key_serial_t keyring, const char *name, int hex_key_IDs); +static void format(void) __attribute__((noreturn)); +void error(const char *msg) __attribute__((noreturn)); +static key_serial_t get_key_id(char *arg); static void *read_file(const char *name, size_t *_size); static uid_t myuid; @@ -229,7 +227,7 @@ void do_command(int argc, char **argv, /* * display command format information */ -void format(void) +static void format(void) { const struct command *cmd; @@ -2290,7 +2288,6 @@ static const struct capability_def capabilities[] = { { "move_key", 0, KEYCTL_CAPS0_MOVE }, { "ns_keyring_name", 1, KEYCTL_CAPS1_NS_KEYRING_NAME }, { "ns_key_tag", 1, KEYCTL_CAPS1_NS_KEY_TAG }, - { "notify", 1, KEYCTL_CAPS1_NOTIFICATIONS }, {} }; @@ -2335,7 +2332,7 @@ static void act_keyctl_supports(int argc, char *argv[]) /* * parse a key identifier */ -key_serial_t get_key_id(char *arg) +static key_serial_t get_key_id(char *arg) { key_serial_t id; char *end; @@ -21,20 +21,9 @@ struct command { * keyctl.c */ extern nr void do_command(int, char **, const struct command *, const char *); -extern nr void format(void) __attribute__((noreturn)); -extern nr void error(const char *) __attribute__((noreturn)); -extern key_serial_t get_key_id(char *); +extern nr void error(const char *); /* * keyctl_testing.c */ extern nr void act_keyctl_test(int, char *[]); - -/* - * keyctl_watch.c - */ -extern nr void act_keyctl_watch(int , char *[]); -extern nr void act_keyctl_watch_add(int , char *[]); -extern nr void act_keyctl_watch_rm(int , char *[]); -extern nr void act_keyctl_watch_session(int , char *[]); -extern nr void act_keyctl_watch_sync(int , char *[]); diff --git a/keyctl_watch.c b/keyctl_watch.c deleted file mode 100644 index 191fe51..0000000 --- a/keyctl_watch.c +++ /dev/null @@ -1,499 +0,0 @@ -/* Key watching facility. - * - * Copyright (C) 2019 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 Licence - * as published by the Free Software Foundation; either version - * 2 of the Licence, or (at your option) any later version. - */ - -#define _GNU_SOURCE -#include <stdbool.h> -#include <stdio.h> -#include <stdlib.h> -#include <stdint.h> -#include <stdarg.h> -#include <string.h> -#include <signal.h> -#include <unistd.h> -#include <fcntl.h> -#include <ctype.h> -#include <errno.h> -#include <poll.h> -#include <getopt.h> -#include <sys/mman.h> -#include <sys/wait.h> -#include "keyutils.h" -#include <limits.h> -#include "keyctl.h" -#include "watch_queue.h" - -#define BUF_SIZE 4 - -static int consumer_stop; -static pid_t pid_con = -1, pid_cmd = -1; -static key_serial_t session; -static int watch_fd; -static int debug; - -static inline bool after_eq(unsigned int a, unsigned int b) -{ - return (signed int)(a - b) >= 0; -} - -static void consumer_term(int sig) -{ - consumer_stop = 1; -} - -static void saw_key_change(FILE *log, struct watch_notification *n) -{ - struct key_notification *k = (struct key_notification *)n; - unsigned int len = (n->info & WATCH_INFO_LENGTH) >> WATCH_INFO_LENGTH__SHIFT; - - if (len != sizeof(struct key_notification) / WATCH_LENGTH_GRANULARITY) - return; - - switch (n->subtype) { - case NOTIFY_KEY_INSTANTIATED: - fprintf(log, "%u inst\n", k->key_id); - break; - case NOTIFY_KEY_UPDATED: - fprintf(log, "%u upd\n", k->key_id); - break; - case NOTIFY_KEY_LINKED: - fprintf(log, "%u link %u\n", k->key_id, k->aux); - break; - case NOTIFY_KEY_UNLINKED: - fprintf(log, "%u unlk %u\n", k->key_id, k->aux); - break; - case NOTIFY_KEY_CLEARED: - fprintf(log, "%u clr\n", k->key_id); - break; - case NOTIFY_KEY_REVOKED: - fprintf(log, "%u rev\n", k->key_id); - break; - case NOTIFY_KEY_INVALIDATED: - fprintf(log, "%u inv\n", k->key_id); - break; - case NOTIFY_KEY_SETATTR: - fprintf(log, "%u attr\n", k->key_id); - break; - } -} - -/* - * Handle removal notification. - */ -static void saw_removal_notification(FILE *gc, struct watch_notification *n) -{ - key_serial_t key = 0; - unsigned int wp, l; - - l = (n->info & WATCH_INFO_LENGTH) >> WATCH_INFO_LENGTH__SHIFT; - l <<= WATCH_LENGTH_GRANULARITY; - wp = (n->info & WATCH_INFO_ID) >> WATCH_INFO_ID__SHIFT; - - if (l >= sizeof(struct watch_notification_removal)) { - struct watch_notification_removal *r = (void *)n; - key = r->id; - } - - fprintf(gc, "%u gc\n", key); - if (wp == 1) - exit(0); -} - -/* - * Consume and display events. - */ -static __attribute__((noreturn)) -int consumer(FILE *log, FILE *gc, int fd, struct watch_queue_buffer *buf) -{ - struct watch_notification *n; - struct pollfd p[1]; - unsigned int head, tail, mask = buf->meta.mask; - - setlinebuf(log); - setlinebuf(gc); - signal(SIGTERM, consumer_term); - - do { - if (!consumer_stop) { - p[0].fd = fd; - p[0].events = POLLIN | POLLERR; - p[0].revents = 0; - - if (poll(p, 1, -1) == -1) { - if (errno == EINTR) - continue; - error("poll"); - } - } - - while (head = __atomic_load_n(&buf->meta.head, __ATOMIC_ACQUIRE), - tail = buf->meta.tail, - tail != head - ) { - n = &buf->slots[tail & mask]; - if (debug) - fprintf(stderr, - "NOTIFY[%08x-%08x] ty=%06x:%02x i=%08x\n", - head, tail, n->type, n->subtype, n->info); - - if ((n->info & WATCH_INFO_LENGTH) == 0) { - fprintf(stderr, "Zero-length watch record\n"); - exit(4); - } - - switch (n->type) { - case WATCH_TYPE_META: - switch (n->subtype) { - case WATCH_META_REMOVAL_NOTIFICATION: - saw_removal_notification(gc, n); - break; - } - break; - case WATCH_TYPE_KEY_NOTIFY: - saw_key_change(log, n); - break; - } - - tail += (n->info & WATCH_INFO_LENGTH) >> WATCH_INFO_LENGTH__SHIFT; - __atomic_store_n(&buf->meta.tail, tail, __ATOMIC_RELEASE); - } - } while (!consumer_stop); - - fprintf(log, "Monitoring terminated\n"); - if (gc != log) - fprintf(gc, "Monitoring terminated\n"); - exit(0); -} - -static struct watch_notification_filter filter = { - .nr_filters = 1, - .__reserved = 0, - .filters = { - [0] = { - .type = WATCH_TYPE_KEY_NOTIFY, - .subtype_filter[0] = UINT_MAX, - }, - }, -}; - -/* - * Open the watch device and allocate a buffer. - */ -static int open_watch(struct watch_queue_buffer **_buf) -{ - struct watch_queue_buffer *buf; - size_t page_size; - int fd; - - fd = open("/dev/watch_queue", O_RDWR); - if (fd == -1) - error("/dev/watch_queue"); - - if (ioctl(fd, IOC_WATCH_QUEUE_SET_SIZE, BUF_SIZE) == -1) - error("/dev/watch_queue(size)"); - - if (ioctl(fd, IOC_WATCH_QUEUE_SET_FILTER, &filter) == -1) - error("/dev/watch_queue(filter)"); - - page_size = sysconf(_SC_PAGESIZE); - buf = mmap(NULL, BUF_SIZE * page_size, PROT_READ | PROT_WRITE, - MAP_SHARED, fd, 0); - if (buf == MAP_FAILED) - error("mmap"); - - *_buf = buf; - return fd; -} - -/* - * Watch a key or keyring for changes. - */ -void act_keyctl_watch(int argc, char *argv[]) -{ - struct watch_queue_buffer *buf; - key_serial_t key; - int wfd; - - if (argc != 2) - format(); - - key = get_key_id(argv[1]); - wfd = open_watch(&buf); - - if (keyctl_watch_key(key, wfd, 0x01) == -1) - error("keyctl_watch_key"); - - consumer(stdout, stdout, wfd, buf); -} - -/* - * Add a watch on a key to the monitor created by watch_session. - */ -void act_keyctl_watch_add(int argc, char *argv[]) -{ - key_serial_t key; - int fd; - - if (argc != 3) - format(); - - fd = atoi(argv[1]); - key = get_key_id(argv[2]); - - if (keyctl_watch_key(key, fd, 0x02) == -1) - error("keyctl_watch_key"); - exit(0); -} - -/* - * Remove a watch on a key from the monitor created by watch_session. - */ -void act_keyctl_watch_rm(int argc, char *argv[]) -{ - key_serial_t key; - int fd; - - if (argc != 3) - format(); - - fd = atoi(argv[1]); - key = get_key_id(argv[2]); - - if (keyctl_watch_key(key, fd, -1) == -1) - error("keyctl_watch_key"); - exit(0); -} - -static void exit_cleanup(void) -{ - pid_t me = getpid(); - int w; - - if (me != pid_cmd && me != pid_con) { - keyctl_watch_key(session, watch_fd, -1); - if (pid_cmd != -1) { - kill(pid_cmd, SIGTERM); - waitpid(pid_cmd, &w, 0); - } - if (pid_con != -1) { - kill(pid_con, SIGTERM); - waitpid(pid_con, &w, 0); - } - } -} - -static void run_command(int argc, char *argv[], int wfd) -{ - char buf[16]; - - pid_cmd = fork(); - if (pid_cmd == -1) - error("fork"); - if (pid_cmd != 0) - return; - - pid_cmd = -1; - pid_con = -1; - - sprintf(buf, "%u", wfd); - setenv("KEYCTL_WATCH_FD", buf, true); - - /* run the standard shell if no arguments */ - if (argc == 0) { - const char *q = getenv("SHELL"); - if (!q) - q = "/bin/sh"; - execl(q, q, NULL); - error(q); - } - - /* run the command specified */ - execvp(argv[0], argv); - error(argv[0]); -} - -/* - * Open a logfiles. - */ -static FILE *open_logfile(const char *logfile) -{ - unsigned int flags; - FILE *log; - int lfd; - - log = fopen(logfile, "a"); - if (!log) - error(logfile); - - lfd = fileno(log); - flags = fcntl(lfd, F_GETFD); - if (flags == -1) - error("F_GETFD"); - if (fcntl(lfd, F_SETFD, flags | FD_CLOEXEC) == -1) - error("F_SETFD"); - - return log; -} - -/* - * Set up a new session keyring with a monitor that is exposed on an explicit - * file descriptor in the program that it starts. - */ -void act_keyctl_watch_session(int argc, char *argv[]) -{ - struct watch_queue_buffer *buf; - const char *session_name = NULL; - const char *logfile, *gcfile, *target_fd; - unsigned int flags; - pid_t pid; - FILE *log, *gc; - int wfd, tfd, opt, w, e = 0, e2 = 0; - - while (opt = getopt(argc, argv, "+dn:"), - opt != -1) { - switch (opt) { - case 'd': - debug = 1; - break; - case 'n': - session_name = optarg; - break; - default: - fprintf(stderr, "Unknown option\n"); - exit(2); - } - } - - argv += optind; - argc -= optind; - - if (argc < 4) - format(); - - logfile = argv[0]; - gcfile = argv[1]; - target_fd = argv[2]; - tfd = atoi(target_fd); - if (tfd < 3 || tfd > 9) { - fprintf(stderr, "The target fd must be between 3 and 9\n"); - exit(2); - } - - wfd = open_watch(&buf); - if (wfd != tfd) { - if (dup2(wfd, tfd) == -1) - error("dup2"); - close(wfd); - wfd = tfd; - } - watch_fd = wfd; - - atexit(exit_cleanup); - - /* We want the fd to be inherited across a fork. */ - flags = fcntl(wfd, F_GETFD); - if (flags == -1) - error("F_GETFD"); - if (fcntl(wfd, F_SETFD, flags & ~FD_CLOEXEC) == -1) - error("F_SETFD"); - - log = open_logfile(logfile); - gc = open_logfile(gcfile); - - pid_con = fork(); - if (pid_con == -1) - error("fork"); - if (pid_con == 0) { - pid_cmd = -1; - pid_con = -1; - consumer(log, gc, wfd, buf); - } - - /* Create a new session keyring and watch it. */ - session = keyctl_join_session_keyring(session_name); - if (session == -1) - error("keyctl_join_session_keyring"); - - if (keyctl_watch_key(session, wfd, 0x01) == -1) - error("keyctl_watch_key/session"); - - fprintf(stderr, "Joined session keyring: %d\n", session); - - /* Start the command and then wait for it to finish and the - * notification consumer to clean up. - */ - run_command(argc - 3, argv + 3, wfd); - close(wfd); - wfd = -1; - - while (pid = wait(&w), - pid != -1) { - if (pid == pid_cmd) { - if (pid_con != -1) - kill(pid_con, SIGTERM); - if (WIFEXITED(w)) { - e2 = WEXITSTATUS(w); - pid_cmd = -1; - } else if (WIFSIGNALED(w)) { - e2 = WTERMSIG(w) + 128; - pid_cmd = -1; - } else if (WIFSTOPPED(w)) { - raise(WSTOPSIG(w)); - } - } else if (pid == pid_con) { - if (pid_cmd != -1) - kill(pid_cmd, SIGTERM); - if (WIFEXITED(w)) { - e = WEXITSTATUS(w); - pid_con = -1; - } else if (WIFSIGNALED(w)) { - e = WTERMSIG(w) + 128; - pid_con = -1; - } - } - } - - if (e == 0) - e = e2; - exit(e); -} - -/* - * Wait for monitoring to synchronise. - */ -void act_keyctl_watch_sync(int argc, char *argv[]) -{ - struct watch_queue_buffer *buf; - //unsigned int head, tail; - size_t page_size; - int wfd; - - if (argc != 2) - format(); - - wfd = atoi(argv[1]); - - /* We only need to see the first page. */ - page_size = sysconf(_SC_PAGESIZE); - buf = mmap(NULL, 1 * page_size, PROT_READ | PROT_WRITE, - MAP_SHARED, wfd, 0); - if (buf == MAP_FAILED) - error("mmap"); - -#if 0 - head = __atomic_load_n(&buf->meta.head, __ATOMIC_RELAXED); - - while (tail = __atomic_load_n(&buf->meta.tail, __ATOMIC_RELAXED), - !after_eq(tail, head) - ) - usleep(10000); -#endif - exit(0); -} @@ -385,11 +385,6 @@ long keyctl_capabilities(unsigned char *buffer, size_t buflen) return sizeof(unsigned char); } -long keyctl_watch_key(key_serial_t id, int watch_queue_fd, int watch_id) -{ - return keyctl(KEYCTL_WATCH_KEY, id, watch_queue_fd, watch_id); -} - /*****************************************************************************/ /* * fetch key description into an allocated buffer @@ -112,7 +112,6 @@ typedef uint32_t key_perm_t; #define KEYCTL_RESTRICT_KEYRING 29 /* Restrict keys allowed to link to a keyring */ #define KEYCTL_MOVE 30 /* Move keys between keyrings */ #define KEYCTL_CAPABILITIES 31 /* Find capabilities of keyrings subsystem */ -#define KEYCTL_WATCH_KEY 32 /* Watch a key or ring of keys for changes */ /* keyctl structures */ struct keyctl_dh_params { @@ -169,7 +168,6 @@ struct keyctl_pkey_params { #define KEYCTL_CAPS0_MOVE 0x80 /* KEYCTL_MOVE supported */ #define KEYCTL_CAPS1_NS_KEYRING_NAME 0x01 /* Keyring names are per-user_namespace */ #define KEYCTL_CAPS1_NS_KEY_TAG 0x02 /* Key indexing can include a namespace tag */ -#define KEYCTL_CAPS1_NOTIFICATIONS 0x04 /* Keys generate watchable notifications */ /* * syscall wrappers @@ -257,7 +255,6 @@ extern long keyctl_move(key_serial_t id, key_serial_t to_ringid, unsigned int flags); extern long keyctl_capabilities(unsigned char *buffer, size_t buflen); -extern long keyctl_watch_key(key_serial_t id, int watch_queue_fd, int watch_id); /* * utilities diff --git a/man/keyctl.1 b/man/keyctl.1 index f18f92d..2f545bd 100644 --- a/man/keyctl.1 +++ b/man/keyctl.1 @@ -114,15 +114,6 @@ keyctl \- key management facility control \fBkeyctl\fR pkey_sign <key> <pass> <datafile> [k=v]* ><sigfile> .br \fBkeyctl\fR pkey_decrypt <key> <pass> <datafile> <sigfile> [k=v]* -.br -\fBkeyctl\fR watch <key> -.br -\fBkeyctl\fR watch_add <fd> <key> -.br -\fBkeyctl\fR watch_rm <fd> <key> -.br -\fBkeyctl\fR watch_session [-n <name>] \\ - <notifylog> <gclog> <fd> <prog> [<arg1> <arg2> ...] .SH DESCRIPTION This program is used to control the key management facility in various ways using a variety of subcommands. @@ -953,89 +944,6 @@ keyctl pkey_verify $k 0 foo.hash foo.sig enc=pkcs1 hash=sha256 .PP See asymmetric-key(7) for more information. -.SS Change notifications -\fBkeyctl\fR watch <key> -.br -\fBkeyctl\fR watch_session [-n <name>] \\ - <notifylog> <gclog> <fd> <prog> [<arg1> <arg2> ...] -\fBkeyctl\fR watch_add <fd> <key> -.br -\fBkeyctl\fR watch_rm <fd> <key> -.br -.PP -The -.B watch -command watches a single key, printing notifications to stdout until the key -is destroyed. -.PP -The output of the command looks like: -.PP -.RS -.nf -.RI < keyid "> <" event "> [<" aux ">]" -.fi -.RE -.PP -Where -.I keyid -is the primary subject of the notification, -.I op -is the event and -.I aux -is the secondary key if there is one (such as link where the primary key is -the keyring secondary key is the key being linked in to it). For example: -.PP -.RS -.nf -255913279 link 340681059 -255913279 clr -.fi -.RE -.PP -An additional notication is generated when a key being watched is garbage -collected, e.g.: -.PP -.RS -.nf -255913279 gc -.fi -.RE -.PP -The -.B watch_session -command creates a new session keyring, with name -.I name -if given, watches it for notifications and runs program -.I prog -with it. The program is given the specified arguments. -.PP -A second process is forked off to monitor the notifications. The output from -that is directed to the files -.I notifylog -for most notifications and -.I gclog -for key removal notifications (which are asynchronous and may be deferred). -.PP -The -.BR watch_queue (7) -device is exported to the program attached to fd number -.IR fd . -This can be passed by the other two commands. -.PP -The -.B watch_add -command adds a watch on -.I key -to the -.B watch_queue -attached to -.I fd -as exported by watch_session and the -.B watch_rm -caommand removes it. A watch_queue can handle multiple keys and even non-keys -sources as well. - - .SH ERRORS There are a number of common errors returned by this program: diff --git a/man/keyctl.3 b/man/keyctl.3 index fda0363..cb0449c 100644 --- a/man/keyctl.3 +++ b/man/keyctl.3 @@ -104,8 +104,6 @@ and then telling the linker it should link in the library: .BR keyctl_unlink (3) .br .BR keyctl_update (3) -.br -.BR keyctl_watch_key (3) .\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" .SH UTILITY FUNCTIONS .BR find_key_by_type_and_name (3) diff --git a/man/keyctl_watch_key.3 b/man/keyctl_watch_key.3 deleted file mode 100644 index 044b7a3..0000000 --- a/man/keyctl_watch_key.3 +++ /dev/null @@ -1,206 +0,0 @@ -.\" -.\" Copyright (C) 2019 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. -.\" -.TH KEYCTL_GRANT_PERMISSION 3 "28 Aug 2019" Linux "Linux Key Management Calls" -.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" -.SH NAME -keyctl_watch_key \- Watch for changes to a key -.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" -.SH SYNOPSIS -.nf -.B #include <keyutils.h> -.sp -.BI "long keyctl_watch_key(key_serial_t " key , -.BI " int " watch_queue_fd -.BI " int " watch_id ");" -.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" -.SH DESCRIPTION -.BR keyctl_watch_key () -sets or removes a watch on -.IR key . -.PP -.I watch_id -specifies the ID for a watch that will be included in notification messages. -It can be between 0 and 255 to add a key; it should be -1 to remove a key. -.PP -.I watch_queue_fd -is a file descriptor attached to a watch_queue device instance. Multiple -openings of a device provide separate instances. Each device instance can -only have one watch on any particular key. -.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" -.SS Notification Record -.PP -Key-specific notification messages that the kernel emits into the buffer have -the following format: -.PP -.in +4n -.EX -struct key_notification { - struct watch_notification watch; - __u32 key_id; - __u32 aux; -}; -.EE -.in -.PP -The -.I watch.type -field will be set to -.B WATCH_TYPE_KEY_NOTIFY -and the -.I watch.subtype -field will contain one of the following constants, indicating the event that -occurred and the watch_id passed to keyctl_watch_key() will be placed in -.I watch.info -in the ID field. The following events are defined: -.TP -.B NOTIFY_KEY_INSTANTIATED -This indicates that a watched key got instantiated or negatively instantiated. -.I key_id -indicates the key that was instantiated and -.I aux -is unused. -.TP -.B NOTIFY_KEY_UPDATED -This indicates that a watched key got updated or instantiated by update. -.I key_id -indicates the key that was updated and -.I aux -is unused. -.TP -.B NOTIFY_KEY_LINKED -This indicates that a key got linked into a watched keyring. -.I key_id -indicates the keyring that was modified -.I aux -indicates the key that was added. -.TP -.B NOTIFY_KEY_UNLINKED -This indicates that a key got unlinked from a watched keyring. -.I key_id -indicates the keyring that was modified -.I aux -indicates the key that was removed. -.TP -.B NOTIFY_KEY_CLEARED -This indicates that a watched keyring got cleared. -.I key_id -indicates the keyring that was cleared and -.I aux -is unused. -.TP -.B NOTIFY_KEY_REVOKED -This indicates that a watched key got revoked. -.I key_id -indicates the key that was revoked and -.I aux -is unused. -.TP -.B NOTIFY_KEY_INVALIDATED -This indicates that a watched key got invalidated. -.I key_id -indicates the key that was invalidated and -.I aux -is unused. -.TP -.B NOTIFY_KEY_SETATTR -This indicates that a watched key had its attributes (owner, group, -permissions, timeout) modified. -.I key_id -indicates the key that was modified and -.I aux -is unused. -.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" -.SS Removal Notification -When a watched key is garbage collected, all of its watches are automatically -destroyed and a notification is delivered to each watcher. This will normally -be an extended notification of the form: -.PP -.in +4n -.EX -struct watch_notification_removal { - struct watch_notification watch; - __u64 id; -}; -.EE -.in -.PP -The -.I watch.type -field will be set to -.B WATCH_TYPE_META -and the -.I watch.subtype -field will contain -.BR WATCH_META_REMOVAL_NOTIFICATION . -If the extended notification is given, then the length will be 2 units, -otherwise it will be 1 and only the header will be present. -.PP -The watch_id passed to -.IR keyctl_watch_key () -will be placed in -.I watch.info -in the ID field. -.PP -If the extension is present, -.I id -will be set to the ID of the destroyed key. -.PP -.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" -.SH RETURN VALUE -On success -.BR keyctl_watch_key () -returns -.B 0 . -On error, the value -.B -1 -will be returned and -.I errno -will have been set to an appropriate error. -.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" -.SH ERRORS -.TP -.B ENOKEY -The specified key does not exist. -.TP -.B EKEYEXPIRED -The specified key has expired. -.TP -.B EKEYREVOKED -The specified key has been revoked. -.TP -.B EACCES -The named key exists, but does not grant -.B view -permission to the calling process. -.TP -.B EBUSY -The specified key already has a watch on it for that device instance (add -only). -.TP -.B EBADSLT -The specified key doesn't have a watch on it (removal only). -.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" -.SH LINKING -This is a library function that can be found in -.IR libkeyutils . -When linking, -.B \-lkeyutils -should be specified to the linker. -.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" -.SH SEE ALSO -.ad l -.nh -.BR keyctl (1), -.BR add_key (2), -.BR keyctl (2), -.BR request_key (2), -.BR keyctl (3), -.BR keyrings (7), -.BR keyutils (7) diff --git a/tests/prepare.inc.sh b/tests/prepare.inc.sh index a306ed0..448e42b 100644 --- a/tests/prepare.inc.sh +++ b/tests/prepare.inc.sh @@ -74,7 +74,6 @@ have_key_invalidate=0 have_big_key_type=0 have_dh_compute=0 have_restrict_keyring=0 -have_notify=0 if keyctl supports capabilities >&/dev/null then diff --git a/version.lds b/version.lds index 6c34adf..2a6e142 100644 --- a/version.lds +++ b/version.lds @@ -100,7 +100,5 @@ KEYUTILS_1.9 { } KEYUTILS_1.8; KEYUTILS_1.10 { - /* Management functions */ - keyctl_watch_key; } KEYUTILS_1.9; diff --git a/watch_queue.h b/watch_queue.h deleted file mode 100644 index 16883d7..0000000 --- a/watch_queue.h +++ /dev/null @@ -1,128 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ -#ifndef _KEYUTILS_LINUX_WATCH_QUEUE_H -#define _KEYUTILS_LINUX_WATCH_QUEUE_H - -#include <linux/types.h> -#include <sys/ioctl.h> - -#define IOC_WATCH_QUEUE_SET_SIZE _IO('W', 0x60) /* Set the size in pages */ -#define IOC_WATCH_QUEUE_SET_FILTER _IO('W', 0x61) /* Set the filter */ - -enum watch_notification_type { - WATCH_TYPE_META = 0, /* Special record */ - WATCH_TYPE_KEY_NOTIFY = 1, /* Key change event notification */ - WATCH_TYPE___NR = 2 -}; - -enum watch_meta_notification_subtype { - WATCH_META_SKIP_NOTIFICATION = 0, /* Just skip this record */ - WATCH_META_REMOVAL_NOTIFICATION = 1, /* Watched object was removed */ -}; - -#define WATCH_LENGTH_GRANULARITY sizeof(__u64) - -/* - * Notification record header. This is aligned to 64-bits so that subclasses - * can contain __u64 fields. - */ -struct watch_notification { - __u32 type:24; /* enum watch_notification_type */ - __u32 subtype:8; /* Type-specific subtype (filterable) */ - __u32 info; -#define WATCH_INFO_LENGTH 0x0000003f /* Length of record / sizeof(watch_notification) */ -#define WATCH_INFO_LENGTH__SHIFT 0 -#define WATCH_INFO_ID 0x0000ff00 /* ID of watchpoint, if type-appropriate */ -#define WATCH_INFO_ID__SHIFT 8 -#define WATCH_INFO_TYPE_INFO 0xffff0000 /* Type-specific info */ -#define WATCH_INFO_TYPE_INFO__SHIFT 16 -#define WATCH_INFO_FLAG_0 0x00010000 /* Type-specific info, flag bit 0 */ -#define WATCH_INFO_FLAG_1 0x00020000 /* ... */ -#define WATCH_INFO_FLAG_2 0x00040000 -#define WATCH_INFO_FLAG_3 0x00080000 -#define WATCH_INFO_FLAG_4 0x00100000 -#define WATCH_INFO_FLAG_5 0x00200000 -#define WATCH_INFO_FLAG_6 0x00400000 -#define WATCH_INFO_FLAG_7 0x00800000 -} __attribute__((aligned(WATCH_LENGTH_GRANULARITY))); - -struct watch_queue_buffer { - union { - /* The first few entries are special, containing the - * ring management variables. - */ - struct { - struct watch_notification watch; /* WATCH_TYPE_META */ - __u32 head; /* Ring head index */ - __u32 tail; /* Ring tail index */ - __u32 mask; /* Ring index mask */ - __u32 __reserved; - } meta; - struct watch_notification slots[0]; - }; -}; - -/* - * The Metadata pseudo-notification message uses a flag bits in the information - * field to convey the fact that messages have been lost. We can only use a - * single bit in this manner per word as some arches that support SMP - * (eg. parisc) have no kernel<->user atomic bit ops. - */ -#define WATCH_INFO_NOTIFICATIONS_LOST WATCH_INFO_FLAG_0 - -/* - * Notification filtering rules (IOC_WATCH_QUEUE_SET_FILTER). - */ -struct watch_notification_type_filter { - __u32 type; /* Type to apply filter to */ - __u32 info_filter; /* Filter on watch_notification::info */ - __u32 info_mask; /* Mask of relevant bits in info_filter */ - __u32 subtype_filter[8]; /* Bitmask of subtypes to filter on */ -}; - -struct watch_notification_filter { - __u32 nr_filters; /* Number of filters */ - __u32 __reserved; /* Must be 0 */ - struct watch_notification_type_filter filters[]; -}; - - -/* - * Extended watch removal notification. This is used optionally if the type - * wants to indicate an identifier for the object being watched, if there is - * such. This can be distinguished by the length. - * - * type -> WATCH_TYPE_META - * subtype -> WATCH_META_REMOVAL_NOTIFICATION - * length -> 2 * gran - */ -struct watch_notification_removal { - struct watch_notification watch; - __u64 id; /* Type-dependent identifier */ -}; - -/* - * Type of key/keyring change notification. - */ -enum key_notification_subtype { - NOTIFY_KEY_INSTANTIATED = 0, /* Key was instantiated (aux is error code) */ - NOTIFY_KEY_UPDATED = 1, /* Key was updated */ - NOTIFY_KEY_LINKED = 2, /* Key (aux) was added to watched keyring */ - NOTIFY_KEY_UNLINKED = 3, /* Key (aux) was removed from watched keyring */ - NOTIFY_KEY_CLEARED = 4, /* Keyring was cleared */ - NOTIFY_KEY_REVOKED = 5, /* Key was revoked */ - NOTIFY_KEY_INVALIDATED = 6, /* Key was invalidated */ - NOTIFY_KEY_SETATTR = 7, /* Key's attributes got changed */ -}; - -/* - * Key/keyring notification record. - * - watch.type = WATCH_TYPE_KEY_NOTIFY - * - watch.subtype = enum key_notification_type - */ -struct key_notification { - struct watch_notification watch; - __u32 key_id; /* The key/keyring affected */ - __u32 aux; /* Per-type auxiliary data */ -}; - -#endif /* _KEYUTILS_LINUX_WATCH_QUEUE_H */ |