aboutsummaryrefslogtreecommitdiff
path: root/security/keys/compat.c
diff options
context:
space:
mode:
Diffstat (limited to 'security/keys/compat.c')
-rw-r--r--security/keys/compat.c60
1 files changed, 58 insertions, 2 deletions
diff --git a/security/keys/compat.c b/security/keys/compat.c
index 07a5f35e397..347896548ad 100644
--- a/security/keys/compat.c
+++ b/security/keys/compat.c
@@ -12,9 +12,52 @@
#include <linux/syscalls.h>
#include <linux/keyctl.h>
#include <linux/compat.h>
+#include <linux/slab.h>
#include "internal.h"
/*
+ * Instantiate a key with the specified compatibility multipart payload and
+ * link the key into the destination keyring if one is given.
+ *
+ * The caller must have the appropriate instantiation permit set for this to
+ * work (see keyctl_assume_authority). No other permissions are required.
+ *
+ * If successful, 0 will be returned.
+ */
+static long compat_keyctl_instantiate_key_iov(
+ key_serial_t id,
+ const struct compat_iovec __user *_payload_iov,
+ unsigned ioc,
+ key_serial_t ringid)
+{
+ struct iovec iovstack[UIO_FASTIOV], *iov = iovstack;
+ long ret;
+
+ if (!_payload_iov || !ioc)
+ goto no_payload;
+
+ ret = compat_rw_copy_check_uvector(WRITE, _payload_iov, ioc,
+ ARRAY_SIZE(iovstack),
+ iovstack, &iov);
+ if (ret < 0)
+ goto err;
+ if (ret == 0)
+ goto no_payload_free;
+
+ ret = keyctl_instantiate_key_common(id, iov, ioc, ret, ringid);
+err:
+ if (iov != iovstack)
+ kfree(iov);
+ return ret;
+
+no_payload_free:
+ if (iov != iovstack)
+ kfree(iov);
+no_payload:
+ return keyctl_instantiate_key_common(id, NULL, 0, 0, ringid);
+}
+
+/*
* 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
@@ -22,8 +65,8 @@
* taking a 32-bit syscall are zero. If you can, you should call sys_keyctl()
* directly.
*/
-asmlinkage long compat_sys_keyctl(u32 option,
- u32 arg2, u32 arg3, u32 arg4, u32 arg5)
+COMPAT_SYSCALL_DEFINE5(keyctl, u32, option,
+ u32, arg2, u32, arg3, u32, arg4, u32, arg5)
{
switch (option) {
case KEYCTL_GET_KEYRING_ID:
@@ -85,6 +128,19 @@ asmlinkage long compat_sys_keyctl(u32 option,
case KEYCTL_SESSION_TO_PARENT:
return keyctl_session_to_parent();
+ case KEYCTL_REJECT:
+ return keyctl_reject_key(arg2, arg3, arg4, arg5);
+
+ case KEYCTL_INSTANTIATE_IOV:
+ return compat_keyctl_instantiate_key_iov(
+ arg2, compat_ptr(arg3), arg4, arg5);
+
+ case KEYCTL_INVALIDATE:
+ return keyctl_invalidate_key(arg2);
+
+ case KEYCTL_GET_PERSISTENT:
+ return keyctl_get_persistent(arg2, arg3);
+
default:
return -EOPNOTSUPP;
}