LCOV - code coverage report
Current view: top level - app/shared/boot - fd_boot.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 0 174 0.0 %
Date: 2025-07-01 05:00:49 Functions: 0 7 0.0 %

          Line data    Source code
       1             : #define _GNU_SOURCE
       2             : #include "fd_boot.h"
       3             : 
       4             : #include "../fd_config.h"
       5             : #include "../fd_action.h"
       6             : #include "../../platform/fd_file_util.h"
       7             : #include "../../../disco/topo/fd_topo.h"
       8             : 
       9             : #include <errno.h>
      10             : #include <unistd.h>
      11             : #include <fcntl.h>
      12             : #include <sys/mman.h>
      13             : 
      14             : extern action_t * ACTIONS[];
      15             : extern fd_topo_run_tile_t * TILES[];
      16             : 
      17             : extern int * fd_log_private_shared_lock;
      18             : 
      19             : fd_topo_run_tile_t
      20           0 : fdctl_tile_run( fd_topo_tile_t const * tile ) {
      21           0 :   for( ulong i=0UL; TILES[ i ]; i++ ) {
      22           0 :     if( !strcmp( tile->name, TILES[ i ]->name ) ) return *TILES[ i ];
      23           0 :   }
      24           0 :   FD_LOG_ERR(( "tile `%s` not found", tile->name ));
      25           0 :   return (fd_topo_run_tile_t){0};
      26           0 : }
      27             : 
      28             : static void
      29             : copy_config_from_fd( int        config_fd,
      30           0 :                      config_t * config ) {
      31           0 :   uchar * bytes = mmap( NULL, sizeof( config_t ), PROT_READ, MAP_PRIVATE, config_fd, 0 );
      32           0 :   if( FD_UNLIKELY( bytes == MAP_FAILED ) ) FD_LOG_ERR(( "mmap() failed (%i-%s)", errno, fd_io_strerror( errno ) ));
      33           0 :   fd_memcpy( config, bytes, sizeof( config_t ) );
      34           0 :   if( FD_UNLIKELY( munmap( bytes, sizeof( config_t ) ) ) ) FD_LOG_ERR(( "munmap() failed (%i-%s)", errno, fd_io_strerror( errno ) ));
      35           0 :   if( FD_UNLIKELY( close( config_fd ) ) ) FD_LOG_ERR(( "close() failed (%i-%s)", errno, fd_io_strerror( errno ) ));
      36           0 : }
      37             : 
      38             : static int *
      39           0 : map_log_memfd( int log_memfd ) {
      40           0 :   void * shmem = mmap( NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, log_memfd, (off_t)0 );
      41           0 :   if( FD_UNLIKELY( shmem==MAP_FAILED ) ) {
      42           0 :     FD_LOG_ERR(( "mmap(NULL,sizeof(int),PROT_READ|PROT_WRITE,MAP_SHARED,memfd,(off_t)0) (%i-%s); ", errno, fd_io_strerror( errno ) ));
      43           0 :   } else {
      44           0 :     if( FD_UNLIKELY( mlock( shmem, 4096 ) ) ) {
      45           0 :       FD_LOG_ERR(( "mlock(%p,4096) (%i-%s); unable to lock log file shared lock in memory\n", shmem, errno, fd_io_strerror( errno ) ));
      46           0 :     }
      47           0 :   }
      48           0 :   return shmem;
      49           0 : }
      50             : 
      51             : /* Try to allocate an anonymous page of memory in a file descriptor
      52             :    (memfd) for fd_log_private_shared_lock such that the log can strictly
      53             :    sequence messages written by clones of the caller made after the
      54             :    caller has finished booting the log.  Must be a file descriptor so
      55             :    we can pass it through `execve` calls. */
      56             : static int
      57           0 : init_log_memfd( void ) {
      58           0 :   int memfd = memfd_create( "fd_log_lock_page", 0U );
      59           0 :   if( FD_UNLIKELY( -1==memfd) ) FD_LOG_ERR(( "memfd_create(\"fd_log_lock_page\",0) failed (%i-%s)", errno, fd_io_strerror( errno ) ));
      60           0 :   if( FD_UNLIKELY( -1==ftruncate( memfd, 4096 ) ) ) FD_LOG_ERR(( "ftruncate(memfd,4096) failed (%i-%s)", errno, fd_io_strerror( errno ) ));
      61           0 :   return memfd;
      62           0 : }
      63             : 
      64             : static int
      65           0 : should_colorize( void ) {
      66           0 :   char const * cstr = fd_env_strip_cmdline_cstr( NULL, NULL, NULL, "COLORTERM", NULL );
      67           0 :   if( cstr && !strcmp( cstr, "truecolor" ) ) return 1;
      68             : 
      69           0 :   cstr = fd_env_strip_cmdline_cstr( NULL, NULL, NULL, "TERM", NULL );
      70           0 :   if( cstr && !strcmp( cstr, "xterm-256color" ) ) return 1;
      71           0 :   return 0;
      72           0 : }
      73             : 
      74             : void
      75             : fd_main_init( int *        pargc,
      76             :               char ***     pargv,
      77             :               config_t   * config,
      78             :               const char * opt_user_config_path,
      79             :               int          is_firedancer,
      80             :               int          is_local_cluster,
      81             :               char const * log_path,
      82             :               char const * default_config,
      83             :               ulong        default_config_sz,
      84           0 :               void (* topo_init )( config_t * config ) ) {
      85           0 :   fd_log_enable_unclean_exit(); /* Don't call atexit handlers on FD_LOG_ERR */
      86           0 :   fd_log_level_core_set( 5 ); /* Don't dump core for FD_LOG_ERR during boot */
      87           0 :   fd_log_colorize_set( should_colorize() ); /* Colorize during boot until we can determine from config */
      88           0 :   fd_log_level_stderr_set( 2 ); /* Only NOTICE and above will be logged during boot until fd_log is initialized */
      89             : 
      90           0 :   int config_fd = fd_env_strip_cmdline_int( pargc, pargv, "--config-fd", NULL, -1 );
      91             : 
      92           0 :   fd_memset( config, 0, sizeof( config_t ) );
      93           0 :   char * thread = "";
      94           0 :   if( FD_UNLIKELY( config_fd >= 0 ) ) {
      95           0 :     copy_config_from_fd( config_fd, config );
      96             :     /* tick_per_ns needs to be synchronized across processes so that
      97             :        they can coordinate on metrics measurement. */
      98           0 :     fd_tempo_set_tick_per_ns( config->tick_per_ns_mu, config->tick_per_ns_sigma );
      99           0 :   } else {
     100           0 :     char * user_config = NULL;
     101           0 :     ulong user_config_sz = 0UL;
     102           0 :     if( FD_LIKELY( opt_user_config_path ) ) {
     103           0 :       user_config = fd_file_util_read_all( opt_user_config_path, &user_config_sz );
     104           0 :       if( FD_UNLIKELY( user_config==MAP_FAILED ) ) FD_LOG_ERR(( "failed to read user config file `%s` (%d-%s)", opt_user_config_path, errno, fd_io_strerror( errno ) ));
     105           0 :     }
     106             : 
     107           0 :     int netns = fd_env_strip_cmdline_contains( pargc, pargv, "--netns" );
     108           0 :     fd_config_load( is_firedancer, netns, is_local_cluster, default_config, default_config_sz, user_config, user_config_sz, opt_user_config_path, config );
     109           0 :     topo_init( config );
     110             : 
     111           0 :     if( FD_UNLIKELY( user_config && -1==munmap( user_config, user_config_sz ) ) ) FD_LOG_ERR(( "munmap() failed (%i-%s)", errno, fd_io_strerror( errno ) ));
     112             : 
     113           0 :     config->log.lock_fd = init_log_memfd();
     114           0 :     config->log.log_fd  = -1;
     115           0 :     thread = "main";
     116           0 :     if( FD_UNLIKELY( log_path ) )
     117           0 :       strncpy( config->log.path, log_path, sizeof( config->log.path ) - 1 );
     118           0 :   }
     119             : 
     120           0 :   char * shmem_args[ 3 ];
     121             :   /* pass in --shmem-path value from the config */
     122           0 :   shmem_args[ 0 ] = "--shmem-path";
     123           0 :   shmem_args[ 1 ] = config->hugetlbfs.mount_path;
     124           0 :   shmem_args[ 2 ] = NULL;
     125           0 :   char ** argv = shmem_args;
     126           0 :   int     argc = 2;
     127             : 
     128           0 :   int * log_lock = map_log_memfd( config->log.lock_fd );
     129           0 :   ulong pid = fd_sandbox_getpid(); /* Need to read /proc since we might be in a PID namespace now */;
     130             : 
     131           0 :   log_path = config->log.path;
     132           0 :   if( FD_LIKELY( config->log.path[ 0 ]=='\0' ) ) log_path = NULL;
     133             : 
     134             :   /* Switch to the sandbox uid/gid for log file creation, so it's always
     135             :      owned by that user. */
     136             : 
     137           0 :   gid_t gid = getgid();
     138           0 :   uid_t uid = getuid();
     139           0 :   if( FD_LIKELY( !gid && setegid( config->gid ) ) ) FD_LOG_ERR(( "setegid() failed (%i-%s)", errno, fd_io_strerror( errno ) ));
     140           0 :   if( FD_LIKELY( !uid && seteuid( config->uid ) ) ) FD_LOG_ERR(( "seteuid() failed (%i-%s)", errno, fd_io_strerror( errno ) ));
     141             : 
     142           0 :   int boot_silent = config_fd>=0;
     143           0 :   fd_log_private_boot_custom( log_lock,
     144           0 :                               0UL,
     145           0 :                               config->name,
     146           0 :                               0UL,    /* Thread ID will be initialized later */
     147           0 :                               thread, /* Thread will be initialized later */
     148           0 :                               0UL,
     149           0 :                               config->hostname,
     150           0 :                               fd_log_private_cpu_id_default(),
     151           0 :                               NULL,
     152           0 :                               pid,
     153           0 :                               NULL,
     154           0 :                               pid,
     155           0 :                               config->uid,
     156           0 :                               config->user,
     157           0 :                               1,
     158           0 :                               config->log.colorize1,
     159           0 :                               boot_silent ? 2 : config->log.level_logfile1,
     160           0 :                               boot_silent ? 2 : config->log.level_stderr1,
     161           0 :                               boot_silent ? 3 : config->log.level_flush1,
     162           0 :                               5,
     163           0 :                               config->log.log_fd,
     164           0 :                               log_path );
     165             : 
     166           0 :   if( FD_UNLIKELY( seteuid( uid ) ) ) FD_LOG_ERR(( "seteuid() failed (%i-%s)", errno, fd_io_strerror( errno ) ));
     167           0 :   if( FD_UNLIKELY( setegid( gid ) ) ) FD_LOG_ERR(( "setegid() failed (%i-%s)", errno, fd_io_strerror( errno ) ));
     168             : 
     169           0 :   config->log.log_fd = fd_log_private_logfile_fd();
     170           0 :   fd_shmem_private_boot( &argc, &argv );
     171           0 :   fd_tile_private_boot( 0, NULL );
     172             : 
     173           0 :   fd_log_level_logfile_set( config->log.level_logfile1 );
     174           0 :   fd_log_level_stderr_set( config->log.level_stderr1 );
     175           0 :   fd_log_level_flush_set( config->log.level_flush1 );
     176           0 : }
     177             : 
     178             : static config_t config;
     179             : 
     180             : int
     181             : fd_main( int          argc,
     182             :          char **      _argv,
     183             :          int          is_firedancer,
     184             :          char const * default_config,
     185             :          ulong        default_config_sz,
     186           0 :          void (* topo_init )( config_t * config ) ) {
     187           0 :   char ** argv = _argv;
     188           0 :   argc--; argv++;
     189             : 
     190             :   /* Short circuit evaluating help and version commands so that we don't
     191             :      need to load and evaluate the entire config file to run them.
     192             :      This is useful for some operators in CI environments where, for
     193             :      example, they want to show the version or validate the produced
     194             :      binary without yet setting up the full TOML. */
     195             : 
     196           0 :   if( FD_UNLIKELY( !argc ) ) {
     197           0 :     for( ulong i=0UL; ACTIONS[ i ]; i++ ) {
     198           0 :       action_t * action = ACTIONS[ i ];
     199           0 :       if( FD_UNLIKELY( action->is_help ) ) {
     200           0 :         action->fn( NULL, NULL );
     201           0 :         FD_LOG_WARNING(( "no subcommand specified, exiting" ));
     202           0 :         return 1;
     203           0 :       }
     204           0 :     }
     205           0 :   }
     206             : 
     207             :   /* We need to strip away (potentially leading) cmdline flags first,
     208             :      since the parser assumes the action is the leading argument */
     209           0 :   const char * opt_user_config_path = fd_env_strip_cmdline_cstr(
     210           0 :     &argc,
     211           0 :     &argv,
     212           0 :     "--config",
     213           0 :     "FIREDANCER_CONFIG_TOML",
     214           0 :     NULL );
     215             : 
     216           0 :   action_t * action = NULL;
     217           0 :   for( ulong i=0UL; ACTIONS[ i ]; i++ ) {
     218           0 :     if( FD_UNLIKELY( !strcmp( argv[ 0 ], ACTIONS[ i ]->name ) ||
     219           0 :                      (!strcmp( argv[ 0 ], "--version" ) && !strcmp( "version", ACTIONS[ i ]->name )) ||
     220           0 :                      (!strcmp( argv[ 0 ], "--help" ) && !strcmp( "help", ACTIONS[ i ]->name ))
     221           0 :     ) ) {
     222           0 :       action = ACTIONS[ i ];
     223           0 :       if( FD_UNLIKELY( action->is_immediate ) ) {
     224           0 :         action->fn( NULL, NULL );
     225           0 :         return 0;
     226           0 :       }
     227           0 :       break;
     228           0 :     }
     229           0 :   }
     230             : 
     231           0 :   int is_local_cluster = action ? action->is_local_cluster : 0;
     232           0 :   fd_main_init( &argc, &argv, &config, opt_user_config_path, is_firedancer, is_local_cluster, NULL, default_config, default_config_sz, topo_init );
     233             : 
     234           0 :   if( FD_UNLIKELY( !action ) ) {
     235           0 :     for( ulong i=0UL; ACTIONS[ i ]; i++ ) {
     236           0 :       action_t * action = ACTIONS[ i ];
     237           0 :       if( FD_UNLIKELY( action->is_help ) ) {
     238           0 :         action->fn( NULL, NULL );
     239           0 :         break;
     240           0 :       }
     241           0 :     }
     242           0 :     FD_LOG_ERR(( "unknown subcommand `%s`", argv[ 0 ] ));
     243           0 :   }
     244             : 
     245           0 :   argc--; argv++;
     246             : 
     247           0 :   args_t args = {0};
     248           0 :   if( FD_LIKELY( action->args ) ) action->args( &argc, &argv, &args );
     249           0 :   if( FD_UNLIKELY( argc ) ) FD_LOG_ERR(( "unknown argument `%s`", argv[ 0 ] ));
     250             : 
     251           0 :   if( FD_LIKELY( action->perm ) ) {
     252           0 :     fd_cap_chk_t * chk = fd_cap_chk_join( fd_cap_chk_new( __builtin_alloca_with_align( fd_cap_chk_footprint(), FD_CAP_CHK_ALIGN ) ) );
     253             : 
     254           0 :     action->perm( &args, chk, &config );
     255             : 
     256           0 :     ulong err_cnt = fd_cap_chk_err_cnt( chk );
     257           0 :     if( FD_UNLIKELY( err_cnt ) ) {
     258           0 :       for( ulong i=0UL; i<err_cnt; i++ ) FD_LOG_WARNING(( "%s", fd_cap_chk_err( chk, i ) ));
     259             : 
     260           0 :       if( FD_LIKELY( action->permission_err ) ) FD_LOG_ERR(( action->permission_err, action->name ));
     261           0 :       else                                      FD_LOG_ERR(( "insufficient permissions to execute command `%s`", action->name ));
     262           0 :     }
     263           0 :   }
     264             : 
     265           0 :   action->fn( &args, &config );
     266             : 
     267           0 :   return 0;
     268           0 : }

Generated by: LCOV version 1.14