summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/ppc/kernel/misc.S3
-rw-r--r--arch/ppc64/Kconfig5
-rw-r--r--arch/ppc64/kernel/misc.S6
-rw-r--r--arch/ppc64/kernel/sys_ppc32.c18
-rw-r--r--include/asm-ppc/unistd.h5
-rw-r--r--include/asm-ppc64/unistd.h5
-rw-r--r--include/linux/compat.h2
-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
11 files changed, 166 insertions, 31 deletions
diff --git a/arch/ppc/kernel/misc.S b/arch/ppc/kernel/misc.S
index 7141d7ecdafd..2e3a07675a10 100644
--- a/arch/ppc/kernel/misc.S
+++ b/arch/ppc/kernel/misc.S
@@ -1447,3 +1447,6 @@ _GLOBAL(sys_call_table)
.long sys_mq_notify
.long sys_mq_getsetattr
.long sys_ni_syscall /* 268 reserved for sys_kexec_load */
+ .long sys_add_key
+ .long sys_request_key /* 270 */
+ .long sys_keyctl
diff --git a/arch/ppc64/Kconfig b/arch/ppc64/Kconfig
index aeab781b58bd..6aef1b6ec4c5 100644
--- a/arch/ppc64/Kconfig
+++ b/arch/ppc64/Kconfig
@@ -376,6 +376,11 @@ source "arch/ppc64/Kconfig.debug"
source "security/Kconfig"
+config KEYS_COMPAT
+ bool
+ depends on COMPAT && KEYS
+ default y
+
source "crypto/Kconfig"
source "lib/Kconfig"
diff --git a/arch/ppc64/kernel/misc.S b/arch/ppc64/kernel/misc.S
index e43d02098fdc..a422c7146644 100644
--- a/arch/ppc64/kernel/misc.S
+++ b/arch/ppc64/kernel/misc.S
@@ -963,6 +963,9 @@ _GLOBAL(sys_call_table32)
.llong .compat_sys_mq_notify
.llong .compat_sys_mq_getsetattr
.llong .sys_ni_syscall /* 268 reserved for sys_kexec_load */
+ .llong .sys32_add_key
+ .llong .sys32_request_key
+ .llong .compat_keyctl
.balign 8
_GLOBAL(sys_call_table)
@@ -1235,3 +1238,6 @@ _GLOBAL(sys_call_table)
.llong .sys_mq_notify
.llong .sys_mq_getsetattr
.llong .sys_ni_syscall /* 268 reserved for sys_kexec_load */
+ .llong .sys_add_key
+ .llong .sys_request_key /* 270 */
+ .llong .sys_keyctl
diff --git a/arch/ppc64/kernel/sys_ppc32.c b/arch/ppc64/kernel/sys_ppc32.c
index 6a514b3d977c..2ff7af2c9d80 100644
--- a/arch/ppc64/kernel/sys_ppc32.c
+++ b/arch/ppc64/kernel/sys_ppc32.c
@@ -1328,3 +1328,21 @@ long ppc32_timer_create(clockid_t clock,
return err;
}
+
+asmlinkage long sys32_add_key(const char __user *_type,
+ const char __user *_description,
+ const void __user *_payload,
+ u32 plen,
+ u32 ringid)
+{
+ return sys_add_key(_type, _description, _payload, plen, ringid);
+}
+
+asmlinkage long sys32_request_key(const char __user *_type,
+ const char __user *_description,
+ const char __user *_callout_info,
+ u32 destringid)
+{
+ return sys_request_key(_type, _description, _callout_info, destringid);
+}
+
diff --git a/include/asm-ppc/unistd.h b/include/asm-ppc/unistd.h
index 57fb02c6c9d3..63a16a4a8cbc 100644
--- a/include/asm-ppc/unistd.h
+++ b/include/asm-ppc/unistd.h
@@ -273,8 +273,11 @@
#define __NR_mq_notify 266
#define __NR_mq_getsetattr 267
#define __NR_kexec_load 268
+#define __NR_add_key 269
+#define __NR_request_key 270
+#define __NR_keyctl 271
-#define __NR_syscalls 269
+#define __NR_syscalls 272
#define __NR(n) #n
diff --git a/include/asm-ppc64/unistd.h b/include/asm-ppc64/unistd.h
index b2ac359c7658..7851d0c5868c 100644
--- a/include/asm-ppc64/unistd.h
+++ b/include/asm-ppc64/unistd.h
@@ -279,8 +279,11 @@
#define __NR_mq_notify 266
#define __NR_mq_getsetattr 267
#define __NR_kexec_load 268
+#define __NR_add_key 269
+#define __NR_request_key 270
+#define __NR_keyctl 271
-#define __NR_syscalls 269
+#define __NR_syscalls 272
#ifdef __KERNEL__
#define NR_syscalls __NR_syscalls
#endif
diff --git a/include/linux/compat.h b/include/linux/compat.h
index e1e78bb971aa..98eda6dfe594 100644
--- a/include/linux/compat.h
+++ b/include/linux/compat.h
@@ -119,6 +119,8 @@ long compat_sys_shmat(int first, int second, compat_uptr_t third, int version,
long compat_sys_shmctl(int first, int second, void __user *uptr);
long compat_sys_semtimedop(int semid, struct sembuf __user *tsems,
unsigned nsems, const struct compat_timespec __user *timeout);
+asmlinkage long compat_keyctl(u32 option,
+ u32 arg2, u32 arg3, u32 arg4, u32 arg5);
asmlinkage ssize_t compat_sys_readv(unsigned long fd,
const struct compat_iovec __user *vec, unsigned long vlen);
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)