Skip to content

Commit be9d59e

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 bc68467 commit be9d59e

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
@@ -421,16 +421,30 @@ clear_rng_page(struct cpu_rng_inst *cri, size_t count)
421421
count < PAGE_SIZE ? memset(cri->page, 0, count) : clear_page(cri->page);
422422
}
423423

424+
static __always_inline void
425+
no_reseed_clear_unlock(struct cpu_rng_inst *cri, size_t *page_dirty_len)
426+
{
427+
/*
428+
* Clear the buffer of our latest random bytes before unlocking and
429+
* potentially migrating CPUs, in which case we wouldn't have the same
430+
* `cri` anymore.
431+
*/
432+
clear_rng_page(cri, *page_dirty_len);
433+
unlock_local_rng(cri, false);
434+
*page_dirty_len = 0;
435+
}
436+
424437
static ssize_t crypto_devrandom_read_iter(struct iov_iter *iter, bool reseed)
425438
{
426439
/* lock_local_rng() puts us in atomic context for !reseed on non-RT */
427440
const bool atomic = !reseed && !IS_ENABLED(CONFIG_PREEMPT_RT);
428441
const bool user_no_reseed = !reseed && user_backed_iter(iter);
442+
/* Align the bounce buffer to a word to prevent alignment traps */
443+
u8 bounce[SZ_256] __aligned(sizeof(long));
429444
size_t ulen, page_dirty_len = 0;
430445
struct cpu_rng_inst *cri;
431446
struct crypto_rng *rng;
432-
void __user *uaddr;
433-
struct page *upage;
447+
u8 __user *uaddr;
434448
ssize_t ret = 0;
435449

436450
if (unlikely(!iov_iter_count(iter)))
@@ -465,21 +479,39 @@ static ssize_t crypto_devrandom_read_iter(struct iov_iter *iter, bool reseed)
465479

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

478510
cri = lock_local_rng(&rng, reseed);
479511
if (IS_ERR(cri)) {
480512
if (!ret)
481513
ret = PTR_ERR(cri);
482-
goto unpin_upage;
514+
goto exit;
483515
}
484516

485517
while (1) {
@@ -489,7 +521,7 @@ static ssize_t crypto_devrandom_read_iter(struct iov_iter *iter, bool reseed)
489521

490522
/*
491523
* Generate up to one page at a time, and align to a page
492-
* boundary so we only need to pin one user page at a time.
524+
* boundary to track page residence one page at a time.
493525
*/
494526
if (user_no_reseed)
495527
i = min3(i, PAGE_SIZE - offset_in_page(uaddr), ulen);
@@ -526,33 +558,56 @@ static ssize_t crypto_devrandom_read_iter(struct iov_iter *iter, bool reseed)
526558
* the entire call; this is why a mutex is used instead of a
527559
* local lock for the reseed RNG, to permit sleeping without
528560
* yielding the DRBG instance.
561+
*
562+
* From this point on, err != 0 means the nofault copy failed.
529563
*/
530564
page_dirty_len = max(i, page_dirty_len);
531-
if (user_no_reseed) {
532-
err = copy_to_user_nofault(uaddr, cri->page, i);
533-
if (err >= 0) {
534-
iov_iter_advance(iter, i - err);
535-
ret += i - err;
536-
}
537-
if (err)
538-
break;
565+
if (user_no_reseed &&
566+
!(err = copy_to_user_nofault(uaddr, cri->page, i))) {
567+
iov_iter_advance(iter, i);
568+
copied = i;
539569
} else {
570+
const void *src = cri->page;
571+
540572
/*
541-
* We know that copying from cri->page is safe, so use
542-
* _copy_to_iter() directly to skip check_copy_size().
573+
* Fall back to a faultable copy attempt when the
574+
* non-faulting attempt failed, likely because the PTE
575+
* was zapped. To ensure forward progress, some of the
576+
* generated bytes are retained in an on-stack bounce
577+
* buffer and copied out rather than just discarding all
578+
* of it and going back to `restart`.
543579
*/
544-
copied = _copy_to_iter(cri->page, i, iter);
545-
ret += copied;
546-
if (copied != i)
547-
break;
580+
if (unlikely(err)) {
581+
i = min(i, sizeof(bounce));
582+
memcpy(bounce, cri->page, i);
583+
no_reseed_clear_unlock(cri, &page_dirty_len);
584+
src = bounce;
585+
}
586+
587+
/*
588+
* We know that copying from cri->page (or the bounce
589+
* buffer) is safe, so use _copy_to_iter() directly to
590+
* skip check_copy_size().
591+
*/
592+
copied = _copy_to_iter(src, i, iter);
593+
594+
/* Sanitize the on-stack bounce buffer if it was used */
595+
if (err)
596+
memzero_explicit(bounce, i);
548597
}
598+
ret += copied;
549599

550600
/*
551-
* Quit when either the requested number of bytes have been
552-
* generated or there is a pending signal.
601+
* Quit when the copy fell short, the requested number of bytes
602+
* have been generated, or there is a pending signal.
553603
*/
554-
if (!iov_iter_count(iter) || signal_pending(current))
604+
if (copied != i || !iov_iter_count(iter) ||
605+
signal_pending(current)) {
606+
/* Skip the unlock when already unlocked */
607+
if (unlikely(err))
608+
goto exit;
555609
break;
610+
}
556611

557612
/* Compute the next user destination address and length */
558613
if (user_no_reseed) {
@@ -573,8 +628,6 @@ static ssize_t crypto_devrandom_read_iter(struct iov_iter *iter, bool reseed)
573628
uaddr = iter_iov(iter)->iov_base;
574629
ulen = iter_iov(iter)->iov_len;
575630
}
576-
577-
unpin_user_page(upage);
578631
}
579632

580633
/*
@@ -589,33 +642,27 @@ static ssize_t crypto_devrandom_read_iter(struct iov_iter *iter, bool reseed)
589642
}
590643

591644
/*
592-
* Optimistically try to pin the next user page without
593-
* faulting, so we don't need to clear cri->page and drop the
594-
* lock on every iteration. If this fails, we fall back to
595-
* pinning with the option to prefault.
645+
* Optimistically check if the next user page is resident and
646+
* writable with a dummy copy_to_user_nofault() attempt to write
647+
* a single zero byte. If this fails, fall back to prefaulting
648+
* outside of the lock.
596649
*/
597-
if (user_no_reseed && !resched_without_lock &&
598-
pin_user_pages_fast_only((unsigned long)uaddr, 1,
599-
FOLL_WRITE, &upage) == 1)
650+
if (!err && user_no_reseed && !resched_without_lock &&
651+
!copy_to_user_nofault(uaddr, &(u8){ 0 }, 1))
600652
continue;
601653

602654
/*
603655
* Restart if either rescheduling is needed (and requires
604-
* dropping the lock since we're atomic) or the optimistic page
605-
* pinning attempt failed.
656+
* dropping the lock since we're atomic) or the destination page
657+
* wasn't resident when copy_to_user_nofault() was attempted.
606658
*
607659
* This always implies `reseed == false`, so unlock_local_rng()
608-
* can just be passed `false` for reseed to eliminate a branch.
660+
* can just be passed `false` for reseed to eliminate a branch,
661+
* hence using no_reseed_clear_unlock().
609662
*/
610663
if (resched_without_lock || user_no_reseed) {
611-
/*
612-
* Clear the buffer of our latest random bytes before
613-
* unlocking and potentially migrating CPUs, in which
614-
* case we wouldn't have the same `cri` anymore.
615-
*/
616-
clear_rng_page(cri, page_dirty_len);
617-
unlock_local_rng(cri, false);
618-
page_dirty_len = 0;
664+
if (!err)
665+
no_reseed_clear_unlock(cri, &page_dirty_len);
619666
if (resched_without_lock)
620667
cond_resched();
621668
goto restart;
@@ -625,9 +672,6 @@ static ssize_t crypto_devrandom_read_iter(struct iov_iter *iter, bool reseed)
625672
if (page_dirty_len)
626673
clear_rng_page(cri, page_dirty_len);
627674
unlock_local_rng(cri, reseed);
628-
unpin_upage:
629-
if (user_no_reseed)
630-
unpin_user_page(upage);
631675
exit:
632676
return ret ? ret : -EFAULT;
633677
}

0 commit comments

Comments
 (0)