Skip to content

Commit 6186194

Browse files
committed
crypto: rng - Fix spurious EFAULT when the destination PTE is zapped
While GUP pinning makes it possible to pin the page _backing_ a user address, it *doesn't* pin the page table entry (PTE) for that mapping. This means the pinned physical page can be separated from the user address it was backing, and even back a _different_ user address within the same process. PTE zapping naturally happens during memory reclaim when memory pressure is elevated, and can even be done directly by userspace via madvise(MADV_DONTNEED). Since the optimized per-CPU DRBG loop assumes copy_to_user_nofault() will always succeed on a GUP-pinned page, it immediately bails out when the nofault copy actually *does* fail for the reasons described above. This results in either fewer than requested random bytes copied or, more seriously, a spurious EFAULT returned to userspace when no random bytes were copied. As it turns out, there's no way to pin a PTE. That means it's not possible to guarantee a 100% success rate for the copy_to_user_nofault() attempt. Fix this by handling copy_to_user_nofault() errors correctly with a fall back to a faultable copy attempt outside of the RNG lock. In order to guarantee forward progress for the caller, an on-stack bounce buffer is used to copy up to 256 bytes of the generated random bytes whenever this happens rather than discarding the whole thing. There's no need to use GUP pinning anymore since there's no use for having a page pinned without pinning a PTE to go along with that page, hence the page pinning is eliminated which saves a software page table walk that was performed for _at least_ every destination page. Reported-by: Kun Yi <kunyi@google.com> Signed-off-by: Sultan Alsawaf <sultan@ciq.com>
1 parent 6d6b2c3 commit 6186194

1 file changed

Lines changed: 95 additions & 51 deletions

File tree

crypto/rng.c

Lines changed: 95 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -418,16 +418,30 @@ clear_rng_page(struct cpu_rng_inst *cri, size_t count)
418418
count < PAGE_SIZE ? memset(cri->page, 0, count) : clear_page(cri->page);
419419
}
420420

421+
static __always_inline void
422+
no_reseed_clear_unlock(struct cpu_rng_inst *cri, size_t *page_dirty_len)
423+
{
424+
/*
425+
* Clear the buffer of our latest random bytes before unlocking and
426+
* potentially migrating CPUs, in which case we wouldn't have the same
427+
* `cri` anymore.
428+
*/
429+
clear_rng_page(cri, *page_dirty_len);
430+
unlock_local_rng(cri, false);
431+
*page_dirty_len = 0;
432+
}
433+
421434
static ssize_t crypto_devrandom_read_iter(struct iov_iter *iter, bool reseed)
422435
{
423436
/* lock_local_rng() puts us in atomic context for !reseed on non-RT */
424437
const bool atomic = !reseed && !IS_ENABLED(CONFIG_PREEMPT_RT);
425438
const bool user_no_reseed = !reseed && user_backed_iter(iter);
439+
/* Align the bounce buffer to a word to prevent alignment traps */
440+
u8 bounce[SZ_256] __aligned(sizeof(long));
426441
size_t ulen, page_dirty_len = 0;
427442
struct cpu_rng_inst *cri;
428443
struct crypto_rng *rng;
429-
void __user *uaddr;
430-
struct page *upage;
444+
u8 __user *uaddr;
431445
ssize_t ret = 0;
432446

433447
if (unlikely(!iov_iter_count(iter)))
@@ -462,21 +476,39 @@ static ssize_t crypto_devrandom_read_iter(struct iov_iter *iter, bool reseed)
462476

463477
restart:
464478
/*
465-
* Pin the user page backing the current user destination address,
466-
* potentially prefaulting to allocate a page for the destination. By
467-
* prefaulting without the RNG lock held, the DRBG won't be blocked by
468-
* time spent on page faults for this task, and thus the DRBG can still
469-
* be used by other tasks.
479+
* Prefault the current user destination address in case the page for
480+
* that virtual address is not resident. This is done by simply writing
481+
* a single zero byte to the destination, which forces a COW if the page
482+
* isn't resident, leaving us with a writable mapping. By prefaulting
483+
* without the RNG lock held, the DRBG won't be blocked by time spent on
484+
* page faults for this task, and thus the DRBG can still be used by
485+
* other tasks.
486+
*
487+
* Notably, this doesn't keep the page from getting evicted later on;
488+
* it's just an optimistic prefault under the assumption that the page
489+
* won't be evicted before we copy random bytes into it, which is often
490+
* but _not always_ the case.
491+
*
492+
* While GUP pinning makes it possible to pin the page _backing_ a user
493+
* address, it *doesn't* pin the page table entry (PTE) for that
494+
* mapping. This means the pinned physical page can be separated from
495+
* the user address it was backing, and even back a _different_ user
496+
* address within the same process. PTE zapping naturally happens during
497+
* memory reclaim when memory pressure is elevated, and can even be done
498+
* directly by userspace via madvise(MADV_DONTNEED). Since there's no
499+
* way to pin a PTE, that means it's not possible to guarantee a page
500+
* will be resident when copy_to_user_nofault() runs under the RNG lock
501+
* below; in other words, there's no way to guarantee a 100% success
502+
* rate for the copy_to_user_nofault() attempt.
470503
*/
471-
if (user_no_reseed && pin_user_pages_fast((unsigned long)uaddr, 1,
472-
FOLL_WRITE, &upage) != 1)
504+
if (user_no_reseed && put_user((u8)0, uaddr))
473505
goto exit;
474506

475507
cri = lock_local_rng(&rng, reseed);
476508
if (IS_ERR(cri)) {
477509
if (!ret)
478510
ret = PTR_ERR(cri);
479-
goto unpin_upage;
511+
goto exit;
480512
}
481513

482514
while (1) {
@@ -486,7 +518,7 @@ static ssize_t crypto_devrandom_read_iter(struct iov_iter *iter, bool reseed)
486518

487519
/*
488520
* Generate up to one page at a time, and align to a page
489-
* boundary so we only need to pin one user page at a time.
521+
* boundary to track page residence one page at a time.
490522
*/
491523
if (user_no_reseed)
492524
i = min3(i, PAGE_SIZE - offset_in_page(uaddr), ulen);
@@ -523,33 +555,56 @@ static ssize_t crypto_devrandom_read_iter(struct iov_iter *iter, bool reseed)
523555
* the entire call; this is why a mutex is used instead of a
524556
* local lock for the reseed RNG, to permit sleeping without
525557
* yielding the DRBG instance.
558+
*
559+
* From this point on, err != 0 means the nofault copy failed.
526560
*/
527561
page_dirty_len = max(i, page_dirty_len);
528-
if (user_no_reseed) {
529-
err = copy_to_user_nofault(uaddr, cri->page, i);
530-
if (err >= 0) {
531-
iov_iter_advance(iter, i - err);
532-
ret += i - err;
533-
}
534-
if (err)
535-
break;
562+
if (user_no_reseed &&
563+
!(err = copy_to_user_nofault(uaddr, cri->page, i))) {
564+
iov_iter_advance(iter, i);
565+
copied = i;
536566
} else {
567+
const void *src = cri->page;
568+
537569
/*
538-
* We know that copying from cri->page is safe, so use
539-
* _copy_to_iter() directly to skip check_copy_size().
570+
* Fall back to a faultable copy attempt when the
571+
* non-faulting attempt failed, likely because the PTE
572+
* was zapped. To ensure forward progress, some of the
573+
* generated bytes are retained in an on-stack bounce
574+
* buffer and copied out rather than just discarding all
575+
* of it and going back to `restart`.
540576
*/
541-
copied = _copy_to_iter(cri->page, i, iter);
542-
ret += copied;
543-
if (copied != i)
544-
break;
577+
if (unlikely(err)) {
578+
i = min(i, sizeof(bounce));
579+
memcpy(bounce, cri->page, i);
580+
no_reseed_clear_unlock(cri, &page_dirty_len);
581+
src = bounce;
582+
}
583+
584+
/*
585+
* We know that copying from cri->page (or the bounce
586+
* buffer) is safe, so use _copy_to_iter() directly to
587+
* skip check_copy_size().
588+
*/
589+
copied = _copy_to_iter(src, i, iter);
590+
591+
/* Sanitize the on-stack bounce buffer if it was used */
592+
if (err)
593+
memzero_explicit(bounce, i);
545594
}
595+
ret += copied;
546596

547597
/*
548-
* Quit when either the requested number of bytes have been
549-
* generated or there is a pending signal.
598+
* Quit when the copy fell short, the requested number of bytes
599+
* have been generated, or there is a pending signal.
550600
*/
551-
if (!iov_iter_count(iter) || signal_pending(current))
601+
if (copied != i || !iov_iter_count(iter) ||
602+
signal_pending(current)) {
603+
/* Skip the unlock when already unlocked */
604+
if (unlikely(err))
605+
goto exit;
552606
break;
607+
}
553608

554609
/* Compute the next user destination address and length */
555610
if (user_no_reseed) {
@@ -570,8 +625,6 @@ static ssize_t crypto_devrandom_read_iter(struct iov_iter *iter, bool reseed)
570625
uaddr = iter_iov(iter)->iov_base;
571626
ulen = iter_iov(iter)->iov_len;
572627
}
573-
574-
unpin_user_page(upage);
575628
}
576629

577630
/*
@@ -586,33 +639,27 @@ static ssize_t crypto_devrandom_read_iter(struct iov_iter *iter, bool reseed)
586639
}
587640

588641
/*
589-
* Optimistically try to pin the next user page without
590-
* faulting, so we don't need to clear cri->page and drop the
591-
* lock on every iteration. If this fails, we fall back to
592-
* pinning with the option to prefault.
642+
* Optimistically check if the next user page is resident and
643+
* writable with a dummy copy_to_user_nofault() attempt to write
644+
* a single zero byte. If this fails, fall back to prefaulting
645+
* outside of the lock.
593646
*/
594-
if (user_no_reseed && !resched_without_lock &&
595-
pin_user_pages_fast_only((unsigned long)uaddr, 1,
596-
FOLL_WRITE, &upage) == 1)
647+
if (!err && user_no_reseed && !resched_without_lock &&
648+
!copy_to_user_nofault(uaddr, &(u8){ 0 }, 1))
597649
continue;
598650

599651
/*
600652
* Restart if either rescheduling is needed (and requires
601-
* dropping the lock since we're atomic) or the optimistic page
602-
* pinning attempt failed.
653+
* dropping the lock since we're atomic) or the destination page
654+
* wasn't resident when copy_to_user_nofault() was attempted.
603655
*
604656
* This always implies `reseed == false`, so unlock_local_rng()
605-
* can just be passed `false` for reseed to eliminate a branch.
657+
* can just be passed `false` for reseed to eliminate a branch,
658+
* hence using no_reseed_clear_unlock().
606659
*/
607660
if (resched_without_lock || user_no_reseed) {
608-
/*
609-
* Clear the buffer of our latest random bytes before
610-
* unlocking and potentially migrating CPUs, in which
611-
* case we wouldn't have the same `cri` anymore.
612-
*/
613-
clear_rng_page(cri, page_dirty_len);
614-
unlock_local_rng(cri, false);
615-
page_dirty_len = 0;
661+
if (!err)
662+
no_reseed_clear_unlock(cri, &page_dirty_len);
616663
if (resched_without_lock)
617664
cond_resched();
618665
goto restart;
@@ -622,9 +669,6 @@ static ssize_t crypto_devrandom_read_iter(struct iov_iter *iter, bool reseed)
622669
if (page_dirty_len)
623670
clear_rng_page(cri, page_dirty_len);
624671
unlock_local_rng(cri, reseed);
625-
unpin_upage:
626-
if (user_no_reseed)
627-
unpin_user_page(upage);
628672
exit:
629673
return ret ? ret : -EFAULT;
630674
}

0 commit comments

Comments
 (0)