From 356568be96729072800b32af65a610eddf70190c Mon Sep 17 00:00:00 2001 From: Carlos Torres Date: Tue, 4 Feb 2020 16:34:11 -0800 Subject: [PATCH] Avoid assuming IPv4, provided runAsRoot option --- base/HHVMDaemon.php | 7 ++++++ base/MemcachedDaemon.php | 7 +++--- base/NginxDaemon.php | 53 ++++++++++++++++++++++++++++++++++++---- base/PerfOptions.php | 3 +++ base/SystemChecks.php | 17 ++++++++++--- conf/nginx/nginx.conf.in | 2 ++ 6 files changed, 78 insertions(+), 11 deletions(-) diff --git a/base/HHVMDaemon.php b/base/HHVMDaemon.php index f96ca7b..8b303fb 100644 --- a/base/HHVMDaemon.php +++ b/base/HHVMDaemon.php @@ -17,6 +17,7 @@ public function __construct(private PerfOptions $options) { parent::__construct((string) $options->hhvm); $this->serverType = $options->proxygen ? 'proxygen' : 'fastcgi'; + $runAsRoot = $options->runAsRoot ? '1' : '0'; $output = []; $check_command = implode( @@ -25,6 +26,8 @@ public function __construct(private PerfOptions $options) { $options->hhvm, '-v', 'Eval.Jit=1', + '-v', + 'Server.AllowRunAsRoot='.$runAsRoot, __DIR__.'/hhvm_config_check.php', })->map($x ==> escapeshellarg($x)), ); @@ -103,6 +106,10 @@ protected function getArguments(): Vector { '-c', OSS_PERFORMANCE_ROOT.'/conf/php.ini', }; + + if ($this->options->runAsRoot) { + $args->addAll(Vector {'-v', 'Server.AllowRunAsRoot=1'}); + } if ($this->options->jit) { $args->addAll(Vector {'-v', 'Eval.Jit=1'}); } else { diff --git a/base/MemcachedDaemon.php b/base/MemcachedDaemon.php index c9d67f3..ec2a873 100644 --- a/base/MemcachedDaemon.php +++ b/base/MemcachedDaemon.php @@ -59,17 +59,18 @@ protected function getArguments(): Vector { if ($this->options->cpuBind) { $this->cpuRange = $this->options->helperProcessors; } + $processUser = posix_getpwuid(posix_geteuid()); return Vector { '-m', (string) $this->maxMemory, - '-l', - '127.0.0.1', '-t', (string) $this->getNumThreads(), '-p', (string) $this->options->memcachedPort, '-P', # pid file - $this->getPidFilePath() + $this->getPidFilePath(), + '-u', + $processUser['name'], }; } } diff --git a/base/NginxDaemon.php b/base/NginxDaemon.php index 6790f20..aa48307 100644 --- a/base/NginxDaemon.php +++ b/base/NginxDaemon.php @@ -128,20 +128,49 @@ protected function getArguments(): Vector { protected function getGeneratedConfigFile(): string { $path = $this->options->tempDir.'/nginx.conf'; + $nameservers = self::GetNameServers(); + $nginx_resolver_servers = []; + foreach ($nameservers as $nameserver) { + if (strpos($nameserver, ':')) { + // IPv6 + $nginx_resolver_servers[] = '['.$nameserver.']'; + } else if (strpos($nameserver, '.')) { + // IPv4 + $nginx_resolver_servers[] = $nameserver; + } + } + $nginx_resolver_line = $nginx_resolver_servers + ? 'resolver '.implode(" ", $nginx_resolver_servers).';' + : ''; + + + if ($nginx_resolver_line) { + $hostname = 'localhost'; + } else { + # Could not find resolver, assuming IPv4 (default behavior) + $hostname = '127.0.0.1'; + } + if ($this->options->proxygen) { $proxy_pass = sprintf( - 'proxy_pass http://127.0.0.1:%d$request_uri', + 'proxy_pass http://%s:%d$request_uri', + $hostname, PerfSettings::BackendPort(), ); $admin_proxy_pass = sprintf( - 'proxy_pass http://127.0.0.1:%d$request_uri', + 'proxy_pass http://%s:%d$request_uri', + $hostname, PerfSettings::BackendAdminPort(), ); } else { - $proxy_pass = - sprintf('fastcgi_pass 127.0.0.1:%d', PerfSettings::BackendPort()); + $proxy_pass = sprintf( + 'fastcgi_pass %s:%d', + $hostname, + PerfSettings::BackendPort() + ); $admin_proxy_pass = sprintf( - 'fastcgi_pass 127.0.0.1:%d', + 'fastcgi_pass %s:%d', + $hostname, PerfSettings::BackendAdminPort(), ); } @@ -161,6 +190,7 @@ protected function getGeneratedConfigFile(): string { '__FRAMEWORK_ROOT__' => $this->target->getSourceRoot(), '__NGINX_PID_FILE__' => $this->getPidFilePath(), '__DATE__' => date(DATE_W3C), + '__NGINX_RESOLVER__' => $nginx_resolver_line, }; $config = @@ -173,6 +203,19 @@ protected function getGeneratedConfigFile(): string { return $path; } + private static function GetNameServers(): Vector { + $config = file('/etc/resolv.conf'); + $matches = []; + $nameservers = Vector{}; + foreach ($config as $line) { + $match = preg_match("/nameserver\s+(\S+)/", $line, &$matches); + if ($match) { + $nameservers[] = $matches[1]; + } + } + return $nameservers; + } + private static function GetPercentiles( Vector $times, ): Map { diff --git a/base/PerfOptions.php b/base/PerfOptions.php index 1292d7b..f0ce292 100644 --- a/base/PerfOptions.php +++ b/base/PerfOptions.php @@ -55,6 +55,7 @@ final class PerfOptions { public bool $dumpIsCompressed = true; public bool $traceSubProcess = false; public bool $noTimeLimit = false; + public bool $runAsRoot = false; // Pause once benchmarking is complete to allow for manual inspection of the // HHVM or PHP process. @@ -174,6 +175,7 @@ public function __construct(Vector $argv) { 'php-extra-arguments:', 'php-fcgi-children:', 'no-time-limit', + 'run-as-root', 'fetch-resources', 'skip-sanity-check', 'skip-warmup', @@ -284,6 +286,7 @@ public function __construct(Vector $argv) { $this->skipVersionChecks = $this->getBool('skip-version-checks'); $this->skipDatabaseInstall = $this->getBool('skip-database-install'); $this->noTimeLimit = $this->getBool('no-time-limit'); + $this->runAsRoot = $this->getBool('run-as-root'); $this->waitAtEnd = $this->getBool('wait-at-end'); $this->proxygen = !$this->getBool('no-proxygen'); $this->statCache = $this->getBool('stat-cache'); diff --git a/base/SystemChecks.php b/base/SystemChecks.php index bcfc5a1..4784108 100644 --- a/base/SystemChecks.php +++ b/base/SystemChecks.php @@ -10,15 +10,26 @@ class SystemChecks { public static function CheckAll(PerfOptions $options): void { - self::CheckNotRoot(); + self::CheckNotRoot($options); self::CheckPortAvailability($options); self::CheckCPUFreq(); self::CheckTCPTimeWaitReuse(); self::CheckForAuditd($options); } - private static function CheckNotRoot(): void { - invariant(getmyuid() !== 0, 'Run this script as a regular user.'); + private static function CheckNotRoot(PerfOptions $options): void { + if ($options->runAsRoot) { + fprintf( + STDERR, + "WARNING: Running as root. This is dangerous.\n" + ); + } else { + invariant( + getmyuid() !== 0, + 'Run this script as a regular user. Alternatively, '. + 'pass the --run-as-root --i-am-not-benchmarking to continue anway.' + ); + } } private static function CheckForAuditd(PerfOptions $options): void { diff --git a/conf/nginx/nginx.conf.in b/conf/nginx/nginx.conf.in index 7d477e7..c2c6f16 100644 --- a/conf/nginx/nginx.conf.in +++ b/conf/nginx/nginx.conf.in @@ -33,6 +33,8 @@ http { #gzip on; + __NGINX_RESOLVER__ + server { listen [::]:__HTTP_PORT__ default_server; listen __HTTP_PORT__ default_server;