From: David Howells <dhowells@redhat.com>
To: torvalds@osdl.org, akpm@linux-foundation.org
Cc: linux-kernel@vger.kernel.org, linux-afs@lists.infradead.org,
linux-fsdevel@vger.kernel.org,
David Howells <dhowells@redhat.com>
Subject: [PATCH 16/17] KEYS: Add a function by which the contents of a keyring can be enumerated
Date: Tue, 16 Jun 2009 21:40:08 +0100 [thread overview]
Message-ID: <20090616204008.4526.31983.stgit@warthog.procyon.org.uk> (raw)
In-Reply-To: <20090616203845.4526.60013.stgit@warthog.procyon.org.uk>
Add a function by which the contents of a keyring can be enumerated.
This allows AFS's VIOCGETTOK/PGetTokens pioctl to list the AFS RxRPC keys on
behalf of userspace.
The following text is added to Documentation/keys.txt:
(*) The contents of a keyring may be enumerated by the following function:
typedef bool (*keyring_enum_filter_t)(const struct key *key,
void *filter_data);
key_ref_t keyring_enum(key_ref_t keyring_ref,
unsigned skip,
keyring_enum_filter_t filter,
void *filter_data,
key_perm_t perm)
This scans the keyring in question for keys for which the caller has the
specified permissions and that match the filter provided. It returns a
reference to the first of those keys, after the specified quantity of them
have been skipped. If no key is found error ENOKEY will be returned.
If the keyring is invalid or unsearchable, error ENOTDIR or EACCES will be
returned.
The filter function should return true if the key it is passed is a match,
and false if it is not. The filter_data passed to keyring_enum() will be
passed on to the filter function.
Signed-off-by: David Howells <dhowells@redhat.com>
---
Documentation/keys.txt | 23 +++++++++++++++++
include/linux/key.h | 5 ++++
security/keys/keyring.c | 65 +++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 93 insertions(+), 0 deletions(-)
diff --git a/Documentation/keys.txt b/Documentation/keys.txt
index 35618d1..77bbe07 100644
--- a/Documentation/keys.txt
+++ b/Documentation/keys.txt
@@ -947,6 +947,29 @@ payload contents" for more information.
reference pointer if successful.
+(*) The contents of a keyring may be enumerated by the following function:
+
+ typedef bool (*keyring_enum_filter_t)(const struct key *key,
+ void *filter_data);
+ key_ref_t keyring_enum(key_ref_t keyring_ref,
+ unsigned skip,
+ keyring_enum_filter_t filter,
+ void *filter_data,
+ key_perm_t perm)
+
+ This scans the keyring in question for keys for which the caller has the
+ specified permissions and that match the filter provided. It returns a
+ reference to the first of those keys, after the specified quantity of them
+ have been skipped. If no key is found error ENOKEY will be returned.
+
+ If the keyring is invalid or unsearchable, error ENOTDIR or EACCES will be
+ returned.
+
+ The filter function should return true if the key it is passed is a match,
+ and false if it is not. The filter_data passed to keyring_enum() will be
+ passed on to the filter function.
+
+
(*) To check the validity of a key, this function can be called:
int validate_key(struct key *key);
diff --git a/include/linux/key.h b/include/linux/key.h
index 4d8cc1e..6d41a4e 100644
--- a/include/linux/key.h
+++ b/include/linux/key.h
@@ -273,6 +273,11 @@ extern key_ref_t keyring_search(key_ref_t keyring,
extern int keyring_add_key(struct key *keyring,
struct key *key);
+typedef bool (*keyring_enum_filter_t)(const struct key *key, void *data);
+extern key_ref_t keyring_enum(key_ref_t keyring_r, unsigned skip,
+ keyring_enum_filter_t filter, void *filter_data,
+ key_perm_t perm);
+
extern struct key *key_lookup(key_serial_t id);
static inline key_serial_t key_serial(struct key *key)
diff --git a/security/keys/keyring.c b/security/keys/keyring.c
index 97529ab..c83ab26 100644
--- a/security/keys/keyring.c
+++ b/security/keys/keyring.c
@@ -1000,3 +1000,68 @@ static void keyring_revoke(struct key *keyring)
}
} /* end keyring_revoke() */
+
+/**
+ * keyring_enum - Allow enumeration of a keyring
+ * @keyring_ref: The keyring to search
+ * @skip: Number of matching keys to skip
+ * @filter: A function to filter out unwanted matches
+ * @filter_data: Data to be passed to filter()
+ * @perm: The permissions desired on the key
+ *
+ * Allow the caller to enumerate a keyring by getting the (skip+1)'th
+ * permissible key that matched a particular filter.
+ *
+ * The caller must lock the keyring if they don't want the contents to change
+ * between calls.
+ */
+key_ref_t keyring_enum(key_ref_t keyring_ref, unsigned skip,
+ keyring_enum_filter_t filter, void *filter_data,
+ key_perm_t perm)
+{
+ struct keyring_list *klist;
+ unsigned long possessed;
+ struct key *keyring, *key;
+ long ret;
+ int loop;
+
+ key_check(keyring);
+
+ /* top keyring must have search permission to begin the search */
+ ret = key_permission(keyring_ref, WANT_KEY_SEARCH);
+ if (ret < 0)
+ return ERR_PTR(ret);
+
+ keyring = key_ref_to_ptr(keyring_ref);
+ if (keyring->type != &key_type_keyring)
+ return ERR_PTR(-ENOTDIR);
+
+ possessed = is_key_possessed(keyring_ref);
+
+ rcu_read_lock();
+
+ klist = rcu_dereference(keyring->payload.subscriptions);
+ if (klist) {
+ for (loop = 0; loop < klist->nkeys; loop++) {
+ key = klist->keys[loop];
+
+ if (!filter(key, filter_data) ||
+ key_permission(make_key_ref(key, possessed),
+ perm) != 0 ||
+ test_bit(KEY_FLAG_REVOKED, &key->flags))
+ continue;
+ if (skip == 0)
+ goto found;
+ skip--;
+ }
+ }
+
+ rcu_read_unlock();
+ return ERR_PTR(-ENOKEY);
+
+ found:
+ atomic_inc(&key->usage);
+ rcu_read_unlock();
+ return make_key_ref(key, possessed);
+}
+EXPORT_SYMBOL(keyring_enum);
next prev parent reply other threads:[~2009-06-16 20:40 UTC|newest]
Thread overview: 45+ messages / expand[flat|nested] mbox.gz Atom feed top
2009-06-16 20:38 [PATCH 00/17] [RFC] AFS: Implement OpenAFS pioctls(version)s David Howells
2009-06-16 20:38 ` [PATCH 01/17] VFS: Implement the pioctl() system call David Howells
2009-06-16 20:54 ` Christoph Hellwig
2009-06-17 0:19 ` David Howells
2009-06-17 9:02 ` Alan Cox
2009-06-16 20:38 ` [PATCH 02/17] VFS: Implement the AFS " David Howells
2009-06-16 20:39 ` [PATCH 03/17] VFS: Implement handling for pathless pioctls David Howells
2009-06-17 7:47 ` Andreas Dilger
2009-06-17 18:26 ` David Howells
2009-06-16 20:39 ` [PATCH 04/17] AFS: Add key request for pioctl David Howells
2009-06-16 20:39 ` [PATCH 05/17] AFS: Handle pathless pioctls aimed at AFS David Howells
2009-06-16 20:39 ` [PATCH 06/17] VFS: Define pioctl command wrappers David Howells
2009-06-16 20:39 ` [PATCH 07/17] AFS: Implement the PGetFid pioctl David Howells
2009-06-16 20:39 ` [PATCH 08/17] AFS: Implement the PGetFileCell pioctl David Howells
2009-06-16 20:39 ` [PATCH 09/17] AFS: Implement the PGetVolStat pioctl David Howells
2009-06-16 20:39 ` [PATCH 10/17] AFS: Implement the PWhereIs pioctl David Howells
2009-06-17 7:51 ` Andreas Dilger
2009-06-17 18:05 ` David Howells
2009-06-16 20:39 ` [PATCH 11/17] AFS: Implement the PFlushCB pioctl David Howells
2009-06-16 20:39 ` [PATCH 12/17] KEYS: Export lookup_user_key() and the key permission request flags David Howells
2009-06-16 20:39 ` [PATCH 13/17] RxRPC: Record extra data in key David Howells
2009-06-16 20:39 ` [PATCH 14/17] RxRPC: Declare the security index constants symbolically David Howells
2009-06-16 20:40 ` [PATCH 15/17] AFS: Implement the PSetTokens pioctl David Howells
2009-06-16 20:40 ` David Howells [this message]
2009-06-16 20:40 ` [PATCH 17/17] AFS: Implement the PGetTokens pioctl David Howells
2009-06-16 22:59 ` [PATCH 00/17] [RFC] AFS: Implement OpenAFS pioctls(version)s David Howells
2009-06-16 23:11 ` Alan Cox
2009-06-17 0:25 ` David Howells
2009-06-17 7:55 ` Andreas Dilger
2009-06-17 16:09 ` Linus Torvalds
2009-06-17 18:37 ` Al Viro
2009-06-17 18:44 ` Linus Torvalds
2009-06-17 18:52 ` Al Viro
2009-06-17 19:28 ` David Howells
2009-06-18 12:50 ` Olivier Galibert
2009-06-17 17:24 ` David Howells
2009-06-17 17:33 ` Linus Torvalds
2009-06-17 18:03 ` David Howells
2009-06-17 18:24 ` Linus Torvalds
2009-06-17 18:30 ` Theodore Tso
2009-06-17 19:14 ` david
2009-06-17 19:30 ` David Howells
2009-06-17 19:51 ` David Howells
2009-06-17 20:09 ` Linus Torvalds
2009-06-17 9:00 ` Alan Cox
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20090616204008.4526.31983.stgit@warthog.procyon.org.uk \
--to=dhowells@redhat.com \
--cc=akpm@linux-foundation.org \
--cc=linux-afs@lists.infradead.org \
--cc=linux-fsdevel@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=torvalds@osdl.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).