x86/sev: Fix SEV-ES INS/OUTS instructions for word, dword, and qword

Properly type the operands being passed to __put_user()/__get_user().
Otherwise, these routines truncate data for dependent instructions
(e.g., INSW) and only read/write one byte.

This has been tested by sending a string with REP OUTSW to a port and
then reading it back in with REP INSW on the same port.

Previous behavior was to only send and receive the first char of the
size. For example, word operations for "abcd" would only read/write
"ac". With change, the full string is now written and read back.

Fixes: f980f9c31a923 (x86/sev-es: Compile early handler code into kernel image)
Signed-off-by: Michael Sterritt <sterritt@google.com>
Signed-off-by: Borislav Petkov <bp@suse.de>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Reviewed-by: Marc Orr <marcorr@google.com>
Reviewed-by: Peter Gonda <pgonda@google.com>
Reviewed-by: Joerg Roedel <jroedel@suse.de>
Link: https://lkml.kernel.org/r/20211119232757.176201-1-sterritt@google.com

authored by Michael Sterritt and committed by Borislav Petkov 1d5379d0 51523ed1

+39 -18
+39 -18
arch/x86/kernel/sev.c
··· 294 294 char *dst, char *buf, size_t size) 295 295 { 296 296 unsigned long error_code = X86_PF_PROT | X86_PF_WRITE; 297 - char __user *target = (char __user *)dst; 298 - u64 d8; 299 - u32 d4; 300 - u16 d2; 301 - u8 d1; 302 297 303 298 /* 304 299 * This function uses __put_user() independent of whether kernel or user ··· 315 320 * instructions here would cause infinite nesting. 316 321 */ 317 322 switch (size) { 318 - case 1: 323 + case 1: { 324 + u8 d1; 325 + u8 __user *target = (u8 __user *)dst; 326 + 319 327 memcpy(&d1, buf, 1); 320 328 if (__put_user(d1, target)) 321 329 goto fault; 322 330 break; 323 - case 2: 331 + } 332 + case 2: { 333 + u16 d2; 334 + u16 __user *target = (u16 __user *)dst; 335 + 324 336 memcpy(&d2, buf, 2); 325 337 if (__put_user(d2, target)) 326 338 goto fault; 327 339 break; 328 - case 4: 340 + } 341 + case 4: { 342 + u32 d4; 343 + u32 __user *target = (u32 __user *)dst; 344 + 329 345 memcpy(&d4, buf, 4); 330 346 if (__put_user(d4, target)) 331 347 goto fault; 332 348 break; 333 - case 8: 349 + } 350 + case 8: { 351 + u64 d8; 352 + u64 __user *target = (u64 __user *)dst; 353 + 334 354 memcpy(&d8, buf, 8); 335 355 if (__put_user(d8, target)) 336 356 goto fault; 337 357 break; 358 + } 338 359 default: 339 360 WARN_ONCE(1, "%s: Invalid size: %zu\n", __func__, size); 340 361 return ES_UNSUPPORTED; ··· 373 362 char *src, char *buf, size_t size) 374 363 { 375 364 unsigned long error_code = X86_PF_PROT; 376 - char __user *s = (char __user *)src; 377 - u64 d8; 378 - u32 d4; 379 - u16 d2; 380 - u8 d1; 381 365 382 366 /* 383 367 * This function uses __get_user() independent of whether kernel or user ··· 394 388 * instructions here would cause infinite nesting. 395 389 */ 396 390 switch (size) { 397 - case 1: 391 + case 1: { 392 + u8 d1; 393 + u8 __user *s = (u8 __user *)src; 394 + 398 395 if (__get_user(d1, s)) 399 396 goto fault; 400 397 memcpy(buf, &d1, 1); 401 398 break; 402 - case 2: 399 + } 400 + case 2: { 401 + u16 d2; 402 + u16 __user *s = (u16 __user *)src; 403 + 403 404 if (__get_user(d2, s)) 404 405 goto fault; 405 406 memcpy(buf, &d2, 2); 406 407 break; 407 - case 4: 408 + } 409 + case 4: { 410 + u32 d4; 411 + u32 __user *s = (u32 __user *)src; 412 + 408 413 if (__get_user(d4, s)) 409 414 goto fault; 410 415 memcpy(buf, &d4, 4); 411 416 break; 412 - case 8: 417 + } 418 + case 8: { 419 + u64 d8; 420 + u64 __user *s = (u64 __user *)src; 413 421 if (__get_user(d8, s)) 414 422 goto fault; 415 423 memcpy(buf, &d8, 8); 416 424 break; 425 + } 417 426 default: 418 427 WARN_ONCE(1, "%s: Invalid size: %zu\n", __func__, size); 419 428 return ES_UNSUPPORTED;