| @@ -979,6 +979,131 @@ static int pac_mask_get(struct task_struct *target, · 978 unmodified lines |
| 979 | 979 | |
| 980 | 980 | return user_regset_copyout(&pos, &count, &kbuf, &ubuf, &uregs, 0, -1); |
| 981 | 981 | } |
| 982 | + |
| 983 | +#ifdef CONFIG_CHECKPOINT_RESTORE |
| 984 | +static __uint128_t pac_key_to_user(const struct ptrauth_key *key) |
| 985 | +{ |
| 986 | + return (__uint128_t)key->hi << 64 | key->lo; |
| 987 | +} |
| 988 | + |
| 989 | +static struct ptrauth_key pac_key_from_user(__uint128_t ukey) |
| 990 | +{ |
| 991 | + struct ptrauth_key key = { |
| 992 | + .lo = (unsigned long)ukey, |
| 993 | + .hi = (unsigned long)(ukey >> 64), |
| 994 | + }; |
| 995 | + |
| 996 | + return key; |
| 997 | +} |
| 998 | + |
| 999 | +static void pac_address_keys_to_user(struct user_pac_address_keys *ukeys, |
| 1000 | + const struct ptrauth_keys *keys) |
| 1001 | +{ |
| 1002 | + ukeys->apiakey = pac_key_to_user(&keys->apia); |
| 1003 | + ukeys->apibkey = pac_key_to_user(&keys->apib); |
| 1004 | + ukeys->apdakey = pac_key_to_user(&keys->apda); |
| 1005 | + ukeys->apdbkey = pac_key_to_user(&keys->apdb); |
| 1006 | +} |
| 1007 | + |
| 1008 | +static void pac_address_keys_from_user(struct ptrauth_keys *keys, |
| 1009 | + const struct user_pac_address_keys *ukeys) |
| 1010 | +{ |
| 1011 | + keys->apia = pac_key_from_user(ukeys->apiakey); |
| 1012 | + keys->apib = pac_key_from_user(ukeys->apibkey); |
| 1013 | + keys->apda = pac_key_from_user(ukeys->apdakey); |
| 1014 | + keys->apdb = pac_key_from_user(ukeys->apdbkey); |
| 1015 | +} |
| 1016 | + |
| 1017 | +static int pac_address_keys_get(struct task_struct *target, |
| 1018 | + const struct user_regset *regset, |
| 1019 | + unsigned int pos, unsigned int count, |
| 1020 | + void *kbuf, void __user *ubuf) |
| 1021 | +{ |
| 1022 | + struct ptrauth_keys *keys = &target->thread.keys_user; |
| 1023 | + struct user_pac_address_keys user_keys; |
| 1024 | + |
| 1025 | + if (!system_supports_address_auth()) |
| 1026 | + return -EINVAL; |
| 1027 | + |
| 1028 | + pac_address_keys_to_user(&user_keys, keys); |
| 1029 | + |
| 1030 | + return user_regset_copyout(&pos, &count, &kbuf, &ubuf, |
| 1031 | + &user_keys, 0, -1); |
| 1032 | +} |
| 1033 | + |
| 1034 | +static int pac_address_keys_set(struct task_struct *target, |
| 1035 | + const struct user_regset *regset, |
| 1036 | + unsigned int pos, unsigned int count, |
| 1037 | + const void *kbuf, const void __user *ubuf) |
| 1038 | +{ |
| 1039 | + struct ptrauth_keys *keys = &target->thread.keys_user; |
| 1040 | + struct user_pac_address_keys user_keys; |
| 1041 | + int ret; |
| 1042 | + |
| 1043 | + if (!system_supports_address_auth()) |
| 1044 | + return -EINVAL; |
| 1045 | + |
| 1046 | + pac_address_keys_to_user(&user_keys, keys); |
| 1047 | + ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, |
| 1048 | + &user_keys, 0, -1); |
| 1049 | + if (ret) |
| 1050 | + return ret; |
| 1051 | + pac_address_keys_from_user(keys, &user_keys); |
| 1052 | + |
| 1053 | + return 0; |
| 1054 | +} |
| 1055 | + |
| 1056 | +static void pac_generic_keys_to_user(struct user_pac_generic_keys *ukeys, |
| 1057 | + const struct ptrauth_keys *keys) |
| 1058 | +{ |
| 1059 | + ukeys->apgakey = pac_key_to_user(&keys->apga); |
| 1060 | +} |
| 1061 | + |
| 1062 | +static void pac_generic_keys_from_user(struct ptrauth_keys *keys, |
| 1063 | + const struct user_pac_generic_keys *ukeys) |
| 1064 | +{ |
| 1065 | + keys->apga = pac_key_from_user(ukeys->apgakey); |
| 1066 | +} |
| 1067 | + |
| 1068 | +static int pac_generic_keys_get(struct task_struct *target, |
| 1069 | + const struct user_regset *regset, |
| 1070 | + unsigned int pos, unsigned int count, |
| 1071 | + void *kbuf, void __user *ubuf) |
| 1072 | +{ |
| 1073 | + struct ptrauth_keys *keys = &target->thread.keys_user; |
| 1074 | + struct user_pac_generic_keys user_keys; |
| 1075 | + |
| 1076 | + if (!system_supports_generic_auth()) |
| 1077 | + return -EINVAL; |
| 1078 | + |
| 1079 | + pac_generic_keys_to_user(&user_keys, keys); |
| 1080 | + |
| 1081 | + return user_regset_copyout(&pos, &count, &kbuf, &ubuf, |
| 1082 | + &user_keys, 0, -1); |
| 1083 | +} |
| 1084 | + |
| 1085 | +static int pac_generic_keys_set(struct task_struct *target, |
| 1086 | + const struct user_regset *regset, |
| 1087 | + unsigned int pos, unsigned int count, |
| 1088 | + const void *kbuf, const void __user *ubuf) |
| 1089 | +{ |
| 1090 | + struct ptrauth_keys *keys = &target->thread.keys_user; |
| 1091 | + struct user_pac_generic_keys user_keys; |
| 1092 | + int ret; |
| 1093 | + |
| 1094 | + if (!system_supports_generic_auth()) |
| 1095 | + return -EINVAL; |
| 1096 | + |
| 1097 | + pac_generic_keys_to_user(&user_keys, keys); |
| 1098 | + ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, |
| 1099 | + &user_keys, 0, -1); |
| 1100 | + if (ret) |
| 1101 | + return ret; |
| 1102 | + pac_generic_keys_from_user(keys, &user_keys); |
| 1103 | + |
| 1104 | + return 0; |
| 1105 | +} |
| 1106 | +#endif /* CONFIG_CHECKPOINT_RESTORE */ |
| 982 | 1107 | #endif /* CONFIG_ARM64_PTR_AUTH */ |
| 983 | 1108 | |
| 984 | 1109 | enum aarch64_regset { |
| @@ -995,6 +1120,10 @@ enum aarch64_regset { · 10 unmodified lines |
| 995 | 1120 | #endif |
| 996 | 1121 | #ifdef CONFIG_ARM64_PTR_AUTH |
| 997 | 1122 | REGSET_PAC_MASK, |
| 1123 | +#ifdef CONFIG_CHECKPOINT_RESTORE |
| 1124 | + REGSET_PACA_KEYS, |
| 1125 | + REGSET_PACG_KEYS, |
| 1126 | +#endif |
| 998 | 1127 | #endif |
| 999 | 1128 | }; |
| 1000 | 1129 | |
| @@ -1074,6 +1203,24 @@ static const struct user_regset aarch64_regsets[] = { · 73 unmodified lines |
| 1074 | 1203 | .get = pac_mask_get, |
| 1075 | 1204 | /* this cannot be set dynamically */ |
| 1076 | 1205 | }, |
| 1206 | +#ifdef CONFIG_CHECKPOINT_RESTORE |
| 1207 | + [REGSET_PACA_KEYS] = { |
| 1208 | + .core_note_type = NT_ARM_PACA_KEYS, |
| 1209 | + .n = sizeof(struct user_pac_address_keys) / sizeof(__uint128_t), |
| 1210 | + .size = sizeof(__uint128_t), |
| 1211 | + .align = sizeof(__uint128_t), |
| 1212 | + .get = pac_address_keys_get, |
| 1213 | + .set = pac_address_keys_set, |
| 1214 | + }, |
| 1215 | + [REGSET_PACG_KEYS] = { |
| 1216 | + .core_note_type = NT_ARM_PACG_KEYS, |
| 1217 | + .n = sizeof(struct user_pac_generic_keys) / sizeof(__uint128_t), |
| 1218 | + .size = sizeof(__uint128_t), |
| 1219 | + .align = sizeof(__uint128_t), |
| 1220 | + .get = pac_generic_keys_get, |
| 1221 | + .set = pac_generic_keys_set, |
| 1222 | + }, |
| 1223 | +#endif |
| 1077 | 1224 | #endif |
| 1078 | 1225 | }; |
| 1079 | 1226 | |