Line data Source code
1 : #ifndef HEADER_fd_src_app_shared_fd_bootinfo_h 2 : #define HEADER_fd_src_app_shared_fd_bootinfo_h 3 : 4 : /* fd_bootinfo publishes a small ABI-frozen descriptor of a running 5 : validator at <mount_path>/<name>.bootinfo so control commands can 6 : discover and attach to it without the configuration file. 7 : 8 : The descriptor only locates the validator, it never authorizes: 9 : commands must still validate in-band magic and payload versions of 10 : whatever they attach to. Liveness is decided by matching the pid 11 : and pid start time against /proc, never by file existence. 12 : 13 : The struct layout is frozen. Grow only by appending fields and 14 : bumping FD_BOOTINFO_VERSION, never reorder or resize fields. */ 15 : 16 : #include "fd_config.h" 17 : 18 0 : #define FD_BOOTINFO_MAGIC (0xF17EDA2C3B007117UL) 19 0 : #define FD_BOOTINFO_VERSION (1UL) 20 : 21 : struct fd_bootinfo { 22 : ulong magic; /* ==FD_BOOTINFO_MAGIC */ 23 : ulong version; /* >=FD_BOOTINFO_VERSION for newer writers, this prefix stays valid */ 24 : ulong pid; /* run supervisor pid (host pidns) */ 25 : ulong pid_start_time; /* /proc/<pid>/stat field 22, defeats pid reuse */ 26 : long boot_wallclock_nanos; 27 : char commit_ref[ 48UL ]; /* git commit of the running build */ 28 : ulong fd_version[ 3UL ]; /* major, minor, patch */ 29 : char name[ 64UL ]; /* config->name */ 30 : uint uid; 31 : uint gid; 32 : ulong topo_layout_hash; /* fd_topo_t layout_hash of the running build */ 33 : char adminctl_wksp_file[ 64UL ]; /* "<name>_adminctl.wksp", empty if no adminctl */ 34 : ulong adminctl_page_sz; /* page size of the adminctl workspace */ 35 : ulong adminctl_offset; /* adminctl obj offset within the workspace */ 36 : char config_file[ 64UL ]; /* "<name>.config" resolved config blob, empty if none */ 37 : ulong config_sz; /* size of the config blob, ==sizeof(config_t) of the running build */ 38 : }; 39 : typedef struct fd_bootinfo fd_bootinfo_t; 40 : 41 0 : #define FD_BOOTINFO_INSTANCE_MAX (16UL) 42 : 43 : struct fd_bootinfo_instance { 44 : char mount_path[ PATH_MAX ]; 45 : fd_bootinfo_t info; 46 : int live; 47 : }; 48 : typedef struct fd_bootinfo_instance fd_bootinfo_instance_t; 49 : 50 : FD_PROTOTYPES_BEGIN 51 : 52 : /* fd_bootinfo_write publishes the resolved config blob and the 53 : descriptor for the given config to <mount_path>/<name>.{config, 54 : bootinfo} (atomic same-dir renames). The blob cannot go stale 55 : because readers only trust it via a descriptor whose process is 56 : verified live. A memfd recovered via /proc/<pid>/fd would be 57 : simpler but the supervisor drops privileges which makes /proc/<pid> 58 : root-only (non-dumpable), and these commands must work without 59 : root. Logs a warning and returns on failure, boot proceeds without 60 : discovery support. */ 61 : 62 : void 63 : fd_bootinfo_write( config_t const * config ); 64 : 65 : /* fd_bootinfo_unlink removes the descriptor for the given config, if 66 : present. */ 67 : 68 : void 69 : fd_bootinfo_unlink( config_t const * config ); 70 : 71 : /* fd_bootinfo_path_read reads and validates the descriptor at path. 72 : Returns 0 on success and fills out, -1 otherwise. Rejects files not 73 : owned by root or the caller, world-writable files, and bad magic or 74 : size. Descriptors from newer builds (version>FD_BOOTINFO_VERSION) 75 : are accepted, only the frozen prefix in out is meaningful. */ 76 : 77 : int 78 : fd_bootinfo_path_read( char const * path, 79 : fd_bootinfo_t * out ); 80 : 81 : /* fd_bootinfo_live returns 1 if the process described by info is still 82 : running (pid exists and start time matches), 0 otherwise. */ 83 : 84 : int 85 : fd_bootinfo_live( fd_bootinfo_t const * info ); 86 : 87 : /* fd_bootinfo_discover scans hugetlbfs mounts (and the default mount 88 : path) for bootinfo descriptors. Returns the number of instances 89 : found, at most max. Both live and stale instances are returned, 90 : distinguished by out[ i ].live. */ 91 : 92 : ulong 93 : fd_bootinfo_discover( fd_bootinfo_instance_t * out, 94 : ulong max ); 95 : 96 : /* fd_bootinfo_check_layout errs if a validator is running with the 97 : config's name and mount path whose topology layout differs from the 98 : one this binary computes. No-op if no live validator is found. */ 99 : 100 : void 101 : fd_bootinfo_check_layout( config_t const * config ); 102 : 103 : /* fd_bootinfo_print prints a table of discovered instances to stdout, 104 : colorized when stdout is a terminal. */ 105 : 106 : void 107 : fd_bootinfo_print( fd_bootinfo_instance_t const * instances, 108 : ulong cnt ); 109 : 110 : /* fd_bootinfo_notice logs a NOTICE describing the instance a command 111 : attached to. */ 112 : 113 : void 114 : fd_bootinfo_notice( fd_bootinfo_instance_t const * instance ); 115 : 116 : /* fd_bootinfo_adopt prepares config for a command that attaches to the 117 : full topology of a running validator. If --config was given, the 118 : topology from the file is used and only the layout is verified. 119 : Otherwise the running validator is discovered and config is replaced 120 : with the validator's own published resolved config, so all topology 121 : offsets are exactly the ones in use. Logs an error and exits if no 122 : or multiple validators are running, or on a version mismatch. */ 123 : 124 : void 125 : fd_bootinfo_adopt( config_t * config ); 126 : 127 : FD_PROTOTYPES_END 128 : 129 : #endif /* HEADER_fd_src_app_shared_fd_bootinfo_h */