[PATCH] Make key management syscalls work on PPC/PPC64

David Howells dhowells at redhat.com
Thu Oct 28 05:08:41 EST 2004


The attached patch permits my key management stuff to be used on PPC, PPC64
and PPC on PPC64. Syscall numbers were allocated by Paul Mackerras.

I've updated my keyctl utility to work on PPC/PPC64 too:

	http://people.redhat.com/~dhowells/keys/keyctl.c

Signed-Off-By: David Howells <dhowells at redhat.com>
---

warthog>diffstat keys-269bk5.diff 
 arch/ppc/kernel/misc.S        |    3 +
 arch/ppc64/Kconfig            |    5 ++
 arch/ppc64/kernel/misc.S      |    6 +++
 arch/ppc64/kernel/sys_ppc32.c |   18 +++++++++
 include/asm-ppc/unistd.h      |    5 ++
 include/asm-ppc64/unistd.h    |    5 ++
 include/linux/compat.h        |    2 +
 security/keys/Makefile        |    1 
 security/keys/compat.c        |   78 ++++++++++++++++++++++++++++++++++++++++++
 security/keys/internal.h      |   20 ++++++++++
 security/keys/keyctl.c        |   54 +++++++++++++----------------
 11 files changed, 166 insertions(+), 31 deletions(-)

diff -uNrp linux-2.6.9-bk5/arch/ppc/kernel/misc.S linux-2.6.9-bk5-keys/arch/ppc/kernel/misc.S
--- linux-2.6.9-bk5/arch/ppc/kernel/misc.S	2004-10-19 10:41:46.000000000 +0100
+++ linux-2.6.9-bk5-keys/arch/ppc/kernel/misc.S	2004-10-22 10:27:40.000000000 +0100
@@ -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 -uNrp linux-2.6.9-bk5/arch/ppc64/Kconfig linux-2.6.9-bk5-keys/arch/ppc64/Kconfig
--- linux-2.6.9-bk5/arch/ppc64/Kconfig	2004-10-21 11:21:45.000000000 +0100
+++ linux-2.6.9-bk5-keys/arch/ppc64/Kconfig	2004-10-22 14:01:30.000000000 +0100
@@ -356,6 +356,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 -uNrp linux-2.6.9-bk5/arch/ppc64/kernel/misc.S linux-2.6.9-bk5-keys/arch/ppc64/kernel/misc.S
--- linux-2.6.9-bk5/arch/ppc64/kernel/misc.S	2004-10-21 11:21:45.000000000 +0100
+++ linux-2.6.9-bk5-keys/arch/ppc64/kernel/misc.S	2004-10-22 11:08:44.000000000 +0100
@@ -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 -uNrp linux-2.6.9-bk5/arch/ppc64/kernel/sys_ppc32.c linux-2.6.9-bk5-keys/arch/ppc64/kernel/sys_ppc32.c
--- linux-2.6.9-bk5/arch/ppc64/kernel/sys_ppc32.c	2004-10-21 11:21:45.000000000 +0100
+++ linux-2.6.9-bk5-keys/arch/ppc64/kernel/sys_ppc32.c	2004-10-22 13:55:56.000000000 +0100
@@ -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 -uNrp linux-2.6.9-bk5/include/asm-ppc/unistd.h linux-2.6.9-bk5-keys/include/asm-ppc/unistd.h
--- linux-2.6.9-bk5/include/asm-ppc/unistd.h	2004-06-18 13:44:05.000000000 +0100
+++ linux-2.6.9-bk5-keys/include/asm-ppc/unistd.h	2004-10-22 10:27:40.000000000 +0100
@@ -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 -uNrp linux-2.6.9-bk5/include/asm-ppc64/unistd.h linux-2.6.9-bk5-keys/include/asm-ppc64/unistd.h
--- linux-2.6.9-bk5/include/asm-ppc64/unistd.h	2004-10-19 10:42:14.000000000 +0100
+++ linux-2.6.9-bk5-keys/include/asm-ppc64/unistd.h	2004-10-22 10:27:40.000000000 +0100
@@ -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 -uNrp linux-2.6.9-bk5/include/linux/compat.h linux-2.6.9-bk5-keys/include/linux/compat.h
--- linux-2.6.9-bk5/include/linux/compat.h	2004-10-19 10:42:16.000000000 +0100
+++ linux-2.6.9-bk5-keys/include/linux/compat.h	2004-10-22 11:02:14.000000000 +0100
@@ -119,6 +119,8 @@ long compat_sys_shmat(int first, int sec
 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 -uNrp linux-2.6.9-bk5/security/keys/compat.c linux-2.6.9-bk5-keys/security/keys/compat.c
--- linux-2.6.9-bk5/security/keys/compat.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.9-bk5-keys/security/keys/compat.c	2004-10-22 14:02:07.000000000 +0100
@@ -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 at 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 -uNrp linux-2.6.9-bk5/security/keys/internal.h linux-2.6.9-bk5-keys/security/keys/internal.h
--- linux-2.6.9-bk5/security/keys/internal.h	2004-10-21 11:22:11.000000000 +0100
+++ linux-2.6.9-bk5-keys/security/keys/internal.h	2004-10-21 11:39:25.000000000 +0100
@@ -81,6 +81,26 @@ extern struct key *find_keyring_by_name(
 
 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 -uNrp linux-2.6.9-bk5/security/keys/keyctl.c linux-2.6.9-bk5-keys/security/keys/keyctl.c
--- linux-2.6.9-bk5/security/keys/keyctl.c	2004-10-21 11:22:11.000000000 +0100
+++ linux-2.6.9-bk5-keys/security/keys/keyctl.c	2004-10-21 11:54:48.000000000 +0100
@@ -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 ch
  * - 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_se
  * 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(
  * - 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
  * - 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
  * - 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_ser
  * - 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_seri
  * - 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_se
  *	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_seri
  *   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 st
  *   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
  * - 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_
  * - 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_seria
  * 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_s
  * 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
 /*****************************************************************************/
 /*
  * 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)
diff -uNrp linux-2.6.9-bk5/security/keys/Makefile linux-2.6.9-bk5-keys/security/keys/Makefile
--- linux-2.6.9-bk5/security/keys/Makefile	2004-10-21 11:22:11.000000000 +0100
+++ linux-2.6.9-bk5-keys/security/keys/Makefile	2004-10-22 10:49:39.000000000 +0100
@@ -10,4 +10,5 @@ obj-y := \
 	user_defined.o \
 	request_key.o
 
+obj-$(CONFIG_KEYS_COMPAT) += compat.o
 obj-$(CONFIG_PROC_FS) += proc.o



More information about the Linuxppc64-dev mailing list