[libc-commits] [libc] [libc] implement secure random buffer filling with vDSO (PR #109870)

Schrodinger ZHU Yifan via libc-commits libc-commits at lists.llvm.org
Wed Oct 2 15:23:19 PDT 2024


================
@@ -0,0 +1,363 @@
+//===- Linux implementation of secure random buffer generation --*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+#include "src/__support/OSUtil/linux/cprng.h"
+#include "src/__support/CPP/atomic.h"
+#include "src/__support/CPP/mutex.h"
+#include "src/__support/CPP/new.h"
+#include "src/__support/OSUtil/linux/syscall.h"
+#include "src/__support/OSUtil/linux/vdso.h"
+#include "src/__support/block.h"
+#include "src/__support/libc_assert.h"
+#include "src/__support/threads/callonce.h"
+#include "src/__support/threads/linux/raw_mutex.h"
+#include "src/sched/sched_getaffinity.h"
+#include "src/sched/sched_getcpucount.h"
+#include "src/sys/mman/mmap.h"
+#include "src/sys/mman/munmap.h"
+#include "src/unistd/sysconf.h"
+
+extern "C" int __cxa_thread_atexit_impl(void (*)(void *), void *, void *);
+extern "C" int __cxa_atexit(void (*)(void *), void *, void *);
+extern "C" [[gnu::weak, gnu::visibility("hidden")]] void *__dso_handle =
+    nullptr;
+
+namespace LIBC_NAMESPACE_DECL {
+namespace cprng {
+namespace {
+
+using namespace vdso;
+// A block of random state together with enough space to hold all its freelist.
+// ┌───────────┬────────────┐
+// │           │            │
+// │           │   Pages    ├──────────────┐
+// │           │            │              ▼
+// │ Prev      ├────────────┤    ┌──────────────────┐
+// │           │            │    │                  │
+// │           │   State0   ├───►│   Opaque Area    │
+// │           │            │    │                  │
+// │           ├────────────┤    ├──────────────────┤
+// ├───────────┤            │    │                  │
+// │           │   State1   ├───►│   Opaque Area    │
+// │           │            │    │                  │
+// │           ├────────────┤    ├──────────────────┤
+// │ Next      │            │    │                  │
+// │           │   State2   ├───►│   Opaque Area    │
+// │           │            │    │                  │
+// │           ├────────────┤    ├──────────────────┤
+// │           │   ......   │    │  ..............  │
+// └───────────┴────────────┘    └──────────────────┘
+// State blocks are doubly linked so that we can iterate bidrectionally as a
+// freelist. We'will use a sentinel to simplify the implementation.
+struct StateBlock {
+  StateBlock *prev;
+  StateBlock *next;
+  void *appendix[0];
+  void *&pages() { return appendix[0]; }
+  void *&freelist(size_t index) { return appendix[index + 1]; }
+};
----------------
SchrodingerZhu wrote:

We need a separate freelist here. We need the freelist size always to be capable of holding all blocks inside an allocation, which is a dynamically sized here.

https://github.com/llvm/llvm-project/pull/109870


More information about the libc-commits mailing list