@@ -403,6 +403,103 @@ copy_struct_from_user(void *dst, size_t ksize, const void __user *src,
403
403
return 0 ;
404
404
}
405
405
406
+ /**
407
+ * copy_struct_to_user: copy a struct to userspace
408
+ * @dst: Destination address, in userspace. This buffer must be @ksize
409
+ * bytes long.
410
+ * @usize: (Alleged) size of @dst struct.
411
+ * @src: Source address, in kernel space.
412
+ * @ksize: Size of @src struct.
413
+ * @ignored_trailing: Set to %true if there was a non-zero byte in @src that
414
+ * userspace cannot see because they are using an smaller struct.
415
+ *
416
+ * Copies a struct from kernel space to userspace, in a way that guarantees
417
+ * backwards-compatibility for struct syscall arguments (as long as future
418
+ * struct extensions are made such that all new fields are *appended* to the
419
+ * old struct, and zeroed-out new fields have the same meaning as the old
420
+ * struct).
421
+ *
422
+ * Some syscalls may wish to make sure that userspace knows about everything in
423
+ * the struct, and if there is a non-zero value that userspce doesn't know
424
+ * about, they want to return an error (such as -EMSGSIZE) or have some other
425
+ * fallback (such as adding a "you're missing some information" flag). If
426
+ * @ignored_trailing is non-%NULL, it will be set to %true if there was a
427
+ * non-zero byte that could not be copied to userspace (ie. was past @usize).
428
+ *
429
+ * While unconditionally returning an error in this case is the simplest
430
+ * solution, for maximum backward compatibility you should try to only return
431
+ * -EMSGSIZE if the user explicitly requested the data that couldn't be copied.
432
+ * Note that structure sizes can change due to header changes and simple
433
+ * recompilations without code changes(!), so if you care about
434
+ * @ignored_trailing you probably want to make sure that any new field data is
435
+ * associated with a flag. Otherwise you might assume that a program knows
436
+ * about data it does not.
437
+ *
438
+ * @ksize is just sizeof(*src), and @usize should've been passed by userspace.
439
+ * The recommended usage is something like the following:
440
+ *
441
+ * SYSCALL_DEFINE2(foobar, struct foo __user *, uarg, size_t, usize)
442
+ * {
443
+ * int err;
444
+ * bool ignored_trailing;
445
+ * struct foo karg = {};
446
+ *
447
+ * if (usize > PAGE_SIZE)
448
+ * return -E2BIG;
449
+ * if (usize < FOO_SIZE_VER0)
450
+ * return -EINVAL;
451
+ *
452
+ * // ... modify karg somehow ...
453
+ *
454
+ * err = copy_struct_to_user(uarg, usize, &karg, sizeof(karg),
455
+ * &ignored_trailing);
456
+ * if (err)
457
+ * return err;
458
+ * if (ignored_trailing)
459
+ * return -EMSGSIZE:
460
+ *
461
+ * // ...
462
+ * }
463
+ *
464
+ * There are three cases to consider:
465
+ * * If @usize == @ksize, then it's copied verbatim.
466
+ * * If @usize < @ksize, then the kernel is trying to pass userspace a newer
467
+ * struct than it supports. Thus we only copy the interoperable portions
468
+ * (@usize) and ignore the rest (but @ignored_trailing is set to %true if
469
+ * any of the trailing (@ksize - @usize) bytes are non-zero).
470
+ * * If @usize > @ksize, then the kernel is trying to pass userspace an older
471
+ * struct than userspace supports. In order to make sure the
472
+ * unknown-to-the-kernel fields don't contain garbage values, we zero the
473
+ * trailing (@usize - @ksize) bytes.
474
+ *
475
+ * Returns (in all cases, some data may have been copied):
476
+ * * -EFAULT: access to userspace failed.
477
+ */
478
+ static __always_inline __must_check int
479
+ copy_struct_to_user (void __user * dst , size_t usize , const void * src ,
480
+ size_t ksize , bool * ignored_trailing )
481
+ {
482
+ size_t size = min (ksize , usize );
483
+ size_t rest = max (ksize , usize ) - size ;
484
+
485
+ /* Double check if ksize is larger than a known object size. */
486
+ if (WARN_ON_ONCE (ksize > __builtin_object_size (src , 1 )))
487
+ return - E2BIG ;
488
+
489
+ /* Deal with trailing bytes. */
490
+ if (usize > ksize ) {
491
+ if (clear_user (dst + size , rest ))
492
+ return - EFAULT ;
493
+ }
494
+ if (ignored_trailing )
495
+ * ignored_trailing = ksize < usize &&
496
+ memchr_inv (src + size , 0 , rest ) != NULL ;
497
+ /* Copy the interoperable parts of the struct. */
498
+ if (copy_to_user (dst , src , size ))
499
+ return - EFAULT ;
500
+ return 0 ;
501
+ }
502
+
406
503
bool copy_from_kernel_nofault_allowed (const void * unsafe_src , size_t size );
407
504
408
505
long copy_from_kernel_nofault (void * dst , const void * src , size_t size );
0 commit comments