0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023 #include <linux/module.h>
0024 #include <linux/kernel.h>
0025 #include <linux/miscdevice.h>
0026 #include <linux/types.h>
0027 #include <linux/stddef.h>
0028 #include <linux/vmalloc.h>
0029 #include <linux/slab.h>
0030 #include <linux/cpufeature.h>
0031
0032 #include <asm/uvdevice.h>
0033 #include <asm/uv.h>
0034
0035 static int uvio_build_uvcb_attest(struct uv_cb_attest *uvcb_attest, u8 *arcb,
0036 u8 *meas, u8 *add_data, struct uvio_attest *uvio_attest)
0037 {
0038 void __user *user_buf_arcb = (void __user *)uvio_attest->arcb_addr;
0039
0040 if (copy_from_user(arcb, user_buf_arcb, uvio_attest->arcb_len))
0041 return -EFAULT;
0042
0043 uvcb_attest->header.len = sizeof(*uvcb_attest);
0044 uvcb_attest->header.cmd = UVC_CMD_RETR_ATTEST;
0045 uvcb_attest->arcb_addr = (u64)arcb;
0046 uvcb_attest->cont_token = 0;
0047 uvcb_attest->user_data_len = uvio_attest->user_data_len;
0048 memcpy(uvcb_attest->user_data, uvio_attest->user_data, sizeof(uvcb_attest->user_data));
0049 uvcb_attest->meas_len = uvio_attest->meas_len;
0050 uvcb_attest->meas_addr = (u64)meas;
0051 uvcb_attest->add_data_len = uvio_attest->add_data_len;
0052 uvcb_attest->add_data_addr = (u64)add_data;
0053
0054 return 0;
0055 }
0056
0057 static int uvio_copy_attest_result_to_user(struct uv_cb_attest *uvcb_attest,
0058 struct uvio_ioctl_cb *uv_ioctl,
0059 u8 *measurement, u8 *add_data,
0060 struct uvio_attest *uvio_attest)
0061 {
0062 struct uvio_attest __user *user_uvio_attest = (void __user *)uv_ioctl->argument_addr;
0063 void __user *user_buf_add = (void __user *)uvio_attest->add_data_addr;
0064 void __user *user_buf_meas = (void __user *)uvio_attest->meas_addr;
0065 void __user *user_buf_uid = &user_uvio_attest->config_uid;
0066
0067 if (copy_to_user(user_buf_meas, measurement, uvio_attest->meas_len))
0068 return -EFAULT;
0069 if (add_data && copy_to_user(user_buf_add, add_data, uvio_attest->add_data_len))
0070 return -EFAULT;
0071 if (copy_to_user(user_buf_uid, uvcb_attest->config_uid, sizeof(uvcb_attest->config_uid)))
0072 return -EFAULT;
0073 return 0;
0074 }
0075
0076 static int get_uvio_attest(struct uvio_ioctl_cb *uv_ioctl, struct uvio_attest *uvio_attest)
0077 {
0078 u8 __user *user_arg_buf = (u8 __user *)uv_ioctl->argument_addr;
0079
0080 if (copy_from_user(uvio_attest, user_arg_buf, sizeof(*uvio_attest)))
0081 return -EFAULT;
0082
0083 if (uvio_attest->arcb_len > UVIO_ATT_ARCB_MAX_LEN)
0084 return -EINVAL;
0085 if (uvio_attest->arcb_len == 0)
0086 return -EINVAL;
0087 if (uvio_attest->meas_len > UVIO_ATT_MEASUREMENT_MAX_LEN)
0088 return -EINVAL;
0089 if (uvio_attest->meas_len == 0)
0090 return -EINVAL;
0091 if (uvio_attest->add_data_len > UVIO_ATT_ADDITIONAL_MAX_LEN)
0092 return -EINVAL;
0093 if (uvio_attest->reserved136)
0094 return -EINVAL;
0095 return 0;
0096 }
0097
0098
0099
0100
0101
0102
0103
0104
0105
0106
0107
0108
0109
0110
0111
0112
0113
0114
0115
0116
0117
0118
0119
0120
0121
0122
0123
0124
0125
0126
0127
0128
0129
0130 static int uvio_attestation(struct uvio_ioctl_cb *uv_ioctl)
0131 {
0132 struct uv_cb_attest *uvcb_attest = NULL;
0133 struct uvio_attest *uvio_attest = NULL;
0134 u8 *measurement = NULL;
0135 u8 *add_data = NULL;
0136 u8 *arcb = NULL;
0137 int ret;
0138
0139 ret = -EINVAL;
0140 if (uv_ioctl->argument_len != sizeof(*uvio_attest))
0141 goto out;
0142
0143 ret = -ENOMEM;
0144 uvio_attest = kzalloc(sizeof(*uvio_attest), GFP_KERNEL);
0145 if (!uvio_attest)
0146 goto out;
0147
0148 ret = get_uvio_attest(uv_ioctl, uvio_attest);
0149 if (ret)
0150 goto out;
0151
0152 ret = -ENOMEM;
0153 arcb = kvzalloc(uvio_attest->arcb_len, GFP_KERNEL);
0154 measurement = kvzalloc(uvio_attest->meas_len, GFP_KERNEL);
0155 if (!arcb || !measurement)
0156 goto out;
0157
0158 if (uvio_attest->add_data_len) {
0159 add_data = kvzalloc(uvio_attest->add_data_len, GFP_KERNEL);
0160 if (!add_data)
0161 goto out;
0162 }
0163
0164 uvcb_attest = kzalloc(sizeof(*uvcb_attest), GFP_KERNEL);
0165 if (!uvcb_attest)
0166 goto out;
0167
0168 ret = uvio_build_uvcb_attest(uvcb_attest, arcb, measurement, add_data, uvio_attest);
0169 if (ret)
0170 goto out;
0171
0172 uv_call_sched(0, (u64)uvcb_attest);
0173
0174 uv_ioctl->uv_rc = uvcb_attest->header.rc;
0175 uv_ioctl->uv_rrc = uvcb_attest->header.rrc;
0176
0177 ret = uvio_copy_attest_result_to_user(uvcb_attest, uv_ioctl, measurement, add_data,
0178 uvio_attest);
0179 out:
0180 kvfree(arcb);
0181 kvfree(measurement);
0182 kvfree(add_data);
0183 kfree(uvio_attest);
0184 kfree(uvcb_attest);
0185 return ret;
0186 }
0187
0188 static int uvio_copy_and_check_ioctl(struct uvio_ioctl_cb *ioctl, void __user *argp)
0189 {
0190 if (copy_from_user(ioctl, argp, sizeof(*ioctl)))
0191 return -EFAULT;
0192 if (ioctl->flags != 0)
0193 return -EINVAL;
0194 if (memchr_inv(ioctl->reserved14, 0, sizeof(ioctl->reserved14)))
0195 return -EINVAL;
0196
0197 return 0;
0198 }
0199
0200
0201
0202
0203 static long uvio_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
0204 {
0205 void __user *argp = (void __user *)arg;
0206 struct uvio_ioctl_cb uv_ioctl = { };
0207 long ret;
0208
0209 switch (cmd) {
0210 case UVIO_IOCTL_ATT:
0211 ret = uvio_copy_and_check_ioctl(&uv_ioctl, argp);
0212 if (ret)
0213 return ret;
0214 ret = uvio_attestation(&uv_ioctl);
0215 break;
0216 default:
0217 ret = -ENOIOCTLCMD;
0218 break;
0219 }
0220 if (ret)
0221 return ret;
0222
0223 if (copy_to_user(argp, &uv_ioctl, sizeof(uv_ioctl)))
0224 ret = -EFAULT;
0225
0226 return ret;
0227 }
0228
0229 static const struct file_operations uvio_dev_fops = {
0230 .owner = THIS_MODULE,
0231 .unlocked_ioctl = uvio_ioctl,
0232 .llseek = no_llseek,
0233 };
0234
0235 static struct miscdevice uvio_dev_miscdev = {
0236 .minor = MISC_DYNAMIC_MINOR,
0237 .name = UVIO_DEVICE_NAME,
0238 .fops = &uvio_dev_fops,
0239 };
0240
0241 static void __exit uvio_dev_exit(void)
0242 {
0243 misc_deregister(&uvio_dev_miscdev);
0244 }
0245
0246 static int __init uvio_dev_init(void)
0247 {
0248 return misc_register(&uvio_dev_miscdev);
0249 }
0250
0251 module_cpu_feature_match(S390_CPU_FEATURE_UV, uvio_dev_init);
0252 module_exit(uvio_dev_exit);
0253
0254 MODULE_AUTHOR("IBM Corporation");
0255 MODULE_LICENSE("GPL");
0256 MODULE_DESCRIPTION("Ultravisor UAPI driver");