]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - arch/arm64/kernel/ptrace.c
treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 234
[linux.git] / arch / arm64 / kernel / ptrace.c
index ddaea0fd2fa4bba34bd79988f6fcd72470e6e537..da2441d7b0660cfbcae43a302e974dfcc54f2ba3 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0-only
 /*
  * Based on arch/arm/kernel/ptrace.c
  *
@@ -5,18 +6,6 @@
  * edited by Linus Torvalds
  * ARM modifications Copyright (C) 2000 Russell King
  * Copyright (C) 2012 ARM Ltd.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
 #include <linux/audit.h>
@@ -979,6 +968,131 @@ static int pac_mask_get(struct task_struct *target,
 
        return user_regset_copyout(&pos, &count, &kbuf, &ubuf, &uregs, 0, -1);
 }
+
+#ifdef CONFIG_CHECKPOINT_RESTORE
+static __uint128_t pac_key_to_user(const struct ptrauth_key *key)
+{
+       return (__uint128_t)key->hi << 64 | key->lo;
+}
+
+static struct ptrauth_key pac_key_from_user(__uint128_t ukey)
+{
+       struct ptrauth_key key = {
+               .lo = (unsigned long)ukey,
+               .hi = (unsigned long)(ukey >> 64),
+       };
+
+       return key;
+}
+
+static void pac_address_keys_to_user(struct user_pac_address_keys *ukeys,
+                                    const struct ptrauth_keys *keys)
+{
+       ukeys->apiakey = pac_key_to_user(&keys->apia);
+       ukeys->apibkey = pac_key_to_user(&keys->apib);
+       ukeys->apdakey = pac_key_to_user(&keys->apda);
+       ukeys->apdbkey = pac_key_to_user(&keys->apdb);
+}
+
+static void pac_address_keys_from_user(struct ptrauth_keys *keys,
+                                      const struct user_pac_address_keys *ukeys)
+{
+       keys->apia = pac_key_from_user(ukeys->apiakey);
+       keys->apib = pac_key_from_user(ukeys->apibkey);
+       keys->apda = pac_key_from_user(ukeys->apdakey);
+       keys->apdb = pac_key_from_user(ukeys->apdbkey);
+}
+
+static int pac_address_keys_get(struct task_struct *target,
+                               const struct user_regset *regset,
+                               unsigned int pos, unsigned int count,
+                               void *kbuf, void __user *ubuf)
+{
+       struct ptrauth_keys *keys = &target->thread.keys_user;
+       struct user_pac_address_keys user_keys;
+
+       if (!system_supports_address_auth())
+               return -EINVAL;
+
+       pac_address_keys_to_user(&user_keys, keys);
+
+       return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+                                  &user_keys, 0, -1);
+}
+
+static int pac_address_keys_set(struct task_struct *target,
+                               const struct user_regset *regset,
+                               unsigned int pos, unsigned int count,
+                               const void *kbuf, const void __user *ubuf)
+{
+       struct ptrauth_keys *keys = &target->thread.keys_user;
+       struct user_pac_address_keys user_keys;
+       int ret;
+
+       if (!system_supports_address_auth())
+               return -EINVAL;
+
+       pac_address_keys_to_user(&user_keys, keys);
+       ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+                                &user_keys, 0, -1);
+       if (ret)
+               return ret;
+       pac_address_keys_from_user(keys, &user_keys);
+
+       return 0;
+}
+
+static void pac_generic_keys_to_user(struct user_pac_generic_keys *ukeys,
+                                    const struct ptrauth_keys *keys)
+{
+       ukeys->apgakey = pac_key_to_user(&keys->apga);
+}
+
+static void pac_generic_keys_from_user(struct ptrauth_keys *keys,
+                                      const struct user_pac_generic_keys *ukeys)
+{
+       keys->apga = pac_key_from_user(ukeys->apgakey);
+}
+
+static int pac_generic_keys_get(struct task_struct *target,
+                               const struct user_regset *regset,
+                               unsigned int pos, unsigned int count,
+                               void *kbuf, void __user *ubuf)
+{
+       struct ptrauth_keys *keys = &target->thread.keys_user;
+       struct user_pac_generic_keys user_keys;
+
+       if (!system_supports_generic_auth())
+               return -EINVAL;
+
+       pac_generic_keys_to_user(&user_keys, keys);
+
+       return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+                                  &user_keys, 0, -1);
+}
+
+static int pac_generic_keys_set(struct task_struct *target,
+                               const struct user_regset *regset,
+                               unsigned int pos, unsigned int count,
+                               const void *kbuf, const void __user *ubuf)
+{
+       struct ptrauth_keys *keys = &target->thread.keys_user;
+       struct user_pac_generic_keys user_keys;
+       int ret;
+
+       if (!system_supports_generic_auth())
+               return -EINVAL;
+
+       pac_generic_keys_to_user(&user_keys, keys);
+       ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+                                &user_keys, 0, -1);
+       if (ret)
+               return ret;
+       pac_generic_keys_from_user(keys, &user_keys);
+
+       return 0;
+}
+#endif /* CONFIG_CHECKPOINT_RESTORE */
 #endif /* CONFIG_ARM64_PTR_AUTH */
 
 enum aarch64_regset {
@@ -995,6 +1109,10 @@ enum aarch64_regset {
 #endif
 #ifdef CONFIG_ARM64_PTR_AUTH
        REGSET_PAC_MASK,
+#ifdef CONFIG_CHECKPOINT_RESTORE
+       REGSET_PACA_KEYS,
+       REGSET_PACG_KEYS,
+#endif
 #endif
 };
 
@@ -1074,6 +1192,24 @@ static const struct user_regset aarch64_regsets[] = {
                .get = pac_mask_get,
                /* this cannot be set dynamically */
        },
+#ifdef CONFIG_CHECKPOINT_RESTORE
+       [REGSET_PACA_KEYS] = {
+               .core_note_type = NT_ARM_PACA_KEYS,
+               .n = sizeof(struct user_pac_address_keys) / sizeof(__uint128_t),
+               .size = sizeof(__uint128_t),
+               .align = sizeof(__uint128_t),
+               .get = pac_address_keys_get,
+               .set = pac_address_keys_set,
+       },
+       [REGSET_PACG_KEYS] = {
+               .core_note_type = NT_ARM_PACG_KEYS,
+               .n = sizeof(struct user_pac_generic_keys) / sizeof(__uint128_t),
+               .size = sizeof(__uint128_t),
+               .align = sizeof(__uint128_t),
+               .get = pac_generic_keys_get,
+               .set = pac_generic_keys_set,
+       },
+#endif
 #endif
 };