LCOV - code coverage report
Current view: top level - util/sandbox - fd_pkeys.h (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 0 30 0.0 %
Date: 2026-05-18 08:34:01 Functions: 0 9 0.0 %

          Line data    Source code
       1             : #ifndef HEADER_fd_src_util_sandbox_fd_pkeys_h
       2             : #define HEADER_fd_src_util_sandbox_fd_pkeys_h
       3             : 
       4             : /* fd_pkeys.h provides APIs for userland memory protection keys.
       5             : 
       6             :    ### Protection Keys
       7             : 
       8             :    https://man7.org/linux/man-pages/man7/pkeys.7.html
       9             :    https://man7.org/linux/man-pages/man2/pkey_alloc.2.html
      10             :    https://man7.org/linux/man-pages/man2/pkey_mprotect.2.html
      11             : 
      12             :    Modern x86 and Arm CPUs allow labelling pages with a protection key
      13             :    (usually a 4 bit number).  Using a special userland instruction,
      14             :    permission bits for such a key can then be modified very cheaply
      15             :    without kernel involvement.
      16             : 
      17             :    Example operation:
      18             :    - exec tile creates a pkey: pkey 3
      19             :      (using pkey_alloc(2))
      20             :    - exec tile installs pkey 3 on the 'database' workspace
      21             :      (using fd_wksp_pkey_install, wrapping pkey_mprotect(2))
      22             :    - whenever exec tile runs untrusted code (a user transaction), the
      23             :      exec tile sets pkey 3 to read-only, preventing stray writes to the
      24             :      database */
      25             : 
      26             : #include "../wksp/fd_wksp.h"
      27             : 
      28             : #if defined(__linux__)
      29             : 
      30             : FD_PROTOTYPES_BEGIN
      31             : 
      32             : /* Syscall wrappers.  Behavior matches glibc wrappers. */
      33             : 
      34             : int
      35             : fd_syscall_pkey_alloc( uint flags,
      36             :                        uint access_rights );
      37             : int
      38             : fd_syscall_pkey_free( int pkey );
      39             : 
      40             : int
      41             : fd_syscall_pkey_mprotect( void * addr,
      42             :                           ulong  size,
      43             :                           int    prot,
      44             :                           int    pkey );
      45             : 
      46             : /* Setup APIs.  These are typically only used at startup. */
      47             : 
      48             : /* fd_wksp_pkey_install protects a workspace with a memory protection
      49             :    key.  Wraps fd_shmem_pkey_install.  Uses syscall pkey_mprotect.
      50             :    Returns 0 on success, errno otherwise. */
      51             : 
      52             : int
      53             : fd_wksp_pkey_install( fd_wksp_t * wksp,
      54             :                       int         pkey );
      55             : 
      56             : /* fd_shmem_pkey_install protects an fd_shmem segment with a memory
      57             :    protection key.  Uses syscall pkey_mprotect.  Returns 0 on success,
      58             :    errno otherwise. */
      59             : 
      60             : int
      61             : fd_shmem_pkey_install( fd_shmem_join_info_t const * join_info,
      62             :                        int                          pkey );
      63             : 
      64             : FD_PROTOTYPES_END
      65             : 
      66             : #endif /* defined(__linux__) */
      67             : 
      68             : /* APIs to update the PKRU register */
      69             : 
      70             : #if defined(__x86_64__)
      71             : 
      72             : static inline ulong
      73           0 : fd_x86_pkru_read( void ) {
      74           0 :   ulong pkru;
      75           0 :   __asm__ volatile (
      76           0 :     "xor %%ecx, %%ecx\n"
      77           0 :     ".byte 0x0f,0x01,0xee\n" /* rdpkru */
      78           0 :     : "=a" (pkru)
      79           0 :     : /* no inputs */
      80           0 :     : "rcx", "rdx" /* rcx and rdx are clobbered */
      81           0 :   );
      82           0 :   return pkru;
      83           0 : }
      84             : 
      85             : static inline void
      86           0 : fd_x86_pkru_write( ulong pkru ) {
      87           0 :   __asm__ volatile (
      88           0 :     "xor %%ecx, %%ecx\n"
      89           0 :     "xor %%edx, %%edx\n"
      90           0 :     ".byte 0x0f,0x01,0xef\n" /* wrpkru */
      91           0 :     : /* no outputs */
      92           0 :     : "a" (pkru)
      93           0 :     : "rcx", "rdx" /* rcx and rdx are clobbered */
      94           0 :   );
      95           0 : }
      96             : 
      97             : static inline void
      98             : fd_x86_pkey_update( int pkey,
      99             :                     int access_disable,
     100           0 :                     int write_disable ) {
     101           0 :   FD_TEST( pkey>=0 && pkey<16 ); /* x86 supports 16 pkeys (4 bits) */
     102           0 :   int   perm = (!!access_disable) | ((!!write_disable)<<1);
     103           0 :   int   idx  = pkey<<1;
     104           0 :   ulong pkru = fd_x86_pkru_read();
     105           0 :   pkru &= ~(3UL<<idx);
     106           0 :   pkru |= ((ulong)perm)<<idx;
     107           0 :   fd_x86_pkru_write( pkru );
     108           0 : }
     109             : 
     110             : #endif /* defined(__x86_64__) */
     111             : 
     112             : #endif /* HEADER_fd_src_util_sandbox_fd_pkeys_h */

Generated by: LCOV version 1.14