summaryrefslogtreecommitdiff
path: root/security
diff options
context:
space:
mode:
Diffstat (limited to 'security')
-rw-r--r--security/keys/Makefile1
-rw-r--r--security/keys/compat.c78
-rw-r--r--security/keys/internal.h20
-rw-r--r--security/keys/keyctl.c54
4 files changed, 124 insertions, 29 deletions
diff --git a/security/keys/Makefile b/security/keys/Makefile
index bd6500dbab0e..ddb495d65062 100644
--- a/security/keys/Makefile
+++ b/security/keys/Makefile
@@ -10,4 +10,5 @@ obj-y := \
user_defined.o \
request_key.o
+obj-$(CONFIG_KEYS_COMPAT) += compat.o
obj-$(CONFIG_PROC_FS) += proc.o
diff --git a/security/keys/compat.c b/security/keys/compat.c
new file mode 100644
index 000000000000..5f8c31a1c1c0
--- /dev/null
+++ b/security/keys/compat.c
@@ -0,0 +1,78 @@
+/* compat.c: 32-bit compatibility syscall for 64-bit systems
+ *
+ * Copyright (C) 2004 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.
+ */
+
+#include <linux/sched.h>
+#include <linux/syscalls.h>
+#include <linux/keyctl.h>
+#include <linux/compat.h>
+#include "internal.h"
+
+/*****************************************************************************/
+/*
+ * the key control system call, 32-bit compatibility version for 64-bit archs
+ * - this should only be called if the 64-bit arch uses weird pointers in
+ * 32-bit mode or doesn't guarantee that the top 32-bits of the argument
+ * registers on taking a 32-bit syscall are zero
+ * - if you can, you should call sys_keyctl directly
+ */
+asmlinkage long compat_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(arg3));
+
+ 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);
+
+ default:
+ return -EOPNOTSUPP;
+ }
+
+} /* end compat_keyctl() */
diff --git a/security/keys/internal.h b/security/keys/internal.h
index e68e0c7ee29e..75c2d154d568 100644
--- a/security/keys/internal.h
+++ b/security/keys/internal.h
@@ -81,6 +81,26 @@ extern struct key *find_keyring_by_name(const char *name, key_serial_t bound);
extern int install_thread_keyring(struct task_struct *tsk);
+/*
+ * keyctl functions
+ */
+extern long keyctl_get_keyring_ID(key_serial_t, int);
+extern long keyctl_join_session_keyring(const char __user *);
+extern long keyctl_update_key(key_serial_t, const void __user *, size_t);
+extern long keyctl_revoke_key(key_serial_t);
+extern long keyctl_keyring_clear(key_serial_t);
+extern long keyctl_keyring_link(key_serial_t, key_serial_t);
+extern long keyctl_keyring_unlink(key_serial_t, key_serial_t);
+extern long keyctl_describe_key(key_serial_t, char __user *, size_t);
+extern long keyctl_keyring_search(key_serial_t, const char __user *,
+ const char __user *, key_serial_t);
+extern long keyctl_read_key(key_serial_t, char __user *, size_t);
+extern long keyctl_chown_key(key_serial_t, uid_t, gid_t);
+extern long keyctl_setperm_key(key_serial_t, key_perm_t);
+extern long keyctl_instantiate_key(key_serial_t, const void __user *,
+ size_t, key_serial_t);
+extern long keyctl_negate_key(key_serial_t, unsigned, key_serial_t);
+
/*
* debugging key validation
diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c
index 2045b24615fd..4d95fdb75bce 100644
--- a/security/keys/keyctl.c
+++ b/security/keys/keyctl.c
@@ -13,6 +13,7 @@
#include <linux/init.h>
#include <linux/sched.h>
#include <linux/slab.h>
+#include <linux/syscalls.h>
#include <linux/keyctl.h>
#include <linux/fs.h>
#include <linux/err.h>
@@ -231,7 +232,7 @@ asmlinkage long sys_request_key(const char __user *_type,
* - the keyring must have search permission to be found
* - implements keyctl(KEYCTL_GET_KEYRING_ID)
*/
-static long keyctl_get_keyring_ID(key_serial_t id, int create)
+long keyctl_get_keyring_ID(key_serial_t id, int create)
{
struct key *key;
long ret;
@@ -254,7 +255,7 @@ static long keyctl_get_keyring_ID(key_serial_t id, int create)
* join the session keyring
* - implements keyctl(KEYCTL_JOIN_SESSION_KEYRING)
*/
-static long keyctl_join_session_keyring(const char __user *_name)
+long keyctl_join_session_keyring(const char __user *_name)
{
char *name;
long nlen, ret;
@@ -297,9 +298,9 @@ static long keyctl_join_session_keyring(const char __user *_name)
* - the key must be writable
* - implements keyctl(KEYCTL_UPDATE)
*/
-static long keyctl_update_key(key_serial_t id,
- const void __user *_payload,
- size_t plen)
+long keyctl_update_key(key_serial_t id,
+ const void __user *_payload,
+ size_t plen)
{
struct key *key;
void *payload;
@@ -346,7 +347,7 @@ static long keyctl_update_key(key_serial_t id,
* - the key must be writable
* - implements keyctl(KEYCTL_REVOKE)
*/
-static long keyctl_revoke_key(key_serial_t id)
+long keyctl_revoke_key(key_serial_t id)
{
struct key *key;
long ret;
@@ -372,7 +373,7 @@ static long keyctl_revoke_key(key_serial_t id)
* - the keyring must be writable
* - implements keyctl(KEYCTL_CLEAR)
*/
-static long keyctl_keyring_clear(key_serial_t ringid)
+long keyctl_keyring_clear(key_serial_t ringid)
{
struct key *keyring;
long ret;
@@ -398,7 +399,7 @@ static long keyctl_keyring_clear(key_serial_t ringid)
* - the key must be linkable
* - implements keyctl(KEYCTL_LINK)
*/
-static long keyctl_keyring_link(key_serial_t id, key_serial_t ringid)
+long keyctl_keyring_link(key_serial_t id, key_serial_t ringid)
{
struct key *keyring, *key;
long ret;
@@ -432,7 +433,7 @@ static long keyctl_keyring_link(key_serial_t id, key_serial_t ringid)
* - we don't need any permissions on the key
* - implements keyctl(KEYCTL_UNLINK)
*/
-static long keyctl_keyring_unlink(key_serial_t id, key_serial_t ringid)
+long keyctl_keyring_unlink(key_serial_t id, key_serial_t ringid)
{
struct key *keyring, *key;
long ret;
@@ -470,9 +471,9 @@ static long keyctl_keyring_unlink(key_serial_t id, key_serial_t ringid)
* type;uid;gid;perm;description<NUL>
* - implements keyctl(KEYCTL_DESCRIBE)
*/
-static long keyctl_describe_key(key_serial_t keyid,
- char __user *buffer,
- size_t buflen)
+long keyctl_describe_key(key_serial_t keyid,
+ char __user *buffer,
+ size_t buflen)
{
struct key *key;
char *tmpbuf;
@@ -532,10 +533,10 @@ static long keyctl_describe_key(key_serial_t keyid,
* there's one specified
* - implements keyctl(KEYCTL_SEARCH)
*/
-static long keyctl_keyring_search(key_serial_t ringid,
- const char __user *_type,
- const char __user *_description,
- key_serial_t destringid)
+long keyctl_keyring_search(key_serial_t ringid,
+ const char __user *_type,
+ const char __user *_description,
+ key_serial_t destringid)
{
struct key_type *ktype;
struct key *keyring, *key, *dest;
@@ -649,9 +650,7 @@ static int keyctl_read_key_same(const struct key *key, const void *target)
* irrespective of how much we may have copied
* - implements keyctl(KEYCTL_READ)
*/
-static long keyctl_read_key(key_serial_t keyid,
- char __user *buffer,
- size_t buflen)
+long keyctl_read_key(key_serial_t keyid, char __user *buffer, size_t buflen)
{
struct key *key, *skey;
long ret;
@@ -711,7 +710,7 @@ static long keyctl_read_key(key_serial_t keyid,
* - if the uid or gid is -1, then that parameter is not changed
* - implements keyctl(KEYCTL_CHOWN)
*/
-static long keyctl_chown_key(key_serial_t id, uid_t uid, gid_t gid)
+long keyctl_chown_key(key_serial_t id, uid_t uid, gid_t gid)
{
struct key *key;
long ret;
@@ -770,7 +769,7 @@ static long keyctl_chown_key(key_serial_t id, uid_t uid, gid_t gid)
* - the keyring owned by the changer
* - implements keyctl(KEYCTL_SETPERM)
*/
-static long keyctl_setperm_key(key_serial_t id, key_perm_t perm)
+long keyctl_setperm_key(key_serial_t id, key_perm_t perm)
{
struct key *key;
long ret;
@@ -814,10 +813,10 @@ static long keyctl_setperm_key(key_serial_t id, key_perm_t perm)
* instantiate the key with the specified payload, and, if one is given, link
* the key into the keyring
*/
-static long keyctl_instantiate_key(key_serial_t id,
- const void __user *_payload,
- size_t plen,
- key_serial_t ringid)
+long keyctl_instantiate_key(key_serial_t id,
+ const void __user *_payload,
+ size_t plen,
+ key_serial_t ringid)
{
struct key *key, *keyring;
void *payload;
@@ -877,9 +876,7 @@ static long keyctl_instantiate_key(key_serial_t id,
* negatively instantiate the key with the given timeout (in seconds), and, if
* one is given, link the key into the keyring
*/
-static long keyctl_negate_key(key_serial_t id,
- unsigned timeout,
- key_serial_t ringid)
+long keyctl_negate_key(key_serial_t id, unsigned timeout, key_serial_t ringid)
{
struct key *key, *keyring;
long ret;
@@ -916,7 +913,6 @@ static long keyctl_negate_key(key_serial_t id,
/*****************************************************************************/
/*
* the key control system call
- * - currently invoked through prctl()
*/
asmlinkage long sys_keyctl(int option, unsigned long arg2, unsigned long arg3,
unsigned long arg4, unsigned long arg5)