MediaWiki REL1_39
CommandFactory.php
Go to the documentation of this file.
1<?php
21namespace MediaWiki\Shell;
22
24use Psr\Log\LoggerAwareTrait;
25use Psr\Log\NullLogger;
26use Shellbox\Command\BoxedCommand;
27use Shellbox\Command\RemoteBoxedExecutor;
28use Shellbox\Shellbox;
29
36 use LoggerAwareTrait;
37
39 private $limits;
40
42 private $cgroup;
43
45 private $doLogStderr = false;
46
50 private $restrictionMethod;
51
55 private $firejail;
56
58 private $useAllUsers;
59
61 private $shellboxClientFactory;
62
69 public function __construct( ShellboxClientFactory $shellboxClientFactory,
70 array $limits, $cgroup, $restrictionMethod
71 ) {
72 $this->shellboxClientFactory = $shellboxClientFactory;
73 $this->limits = $limits;
74 $this->cgroup = $cgroup;
75 if ( $restrictionMethod === 'autodetect' ) {
76 // On Linux systems check for firejail
77 if ( PHP_OS === 'Linux' && $this->findFirejail() ) {
78 $this->restrictionMethod = 'firejail';
79 } else {
80 $this->restrictionMethod = false;
81 }
82 } else {
83 $this->restrictionMethod = $restrictionMethod;
84 }
85 $this->setLogger( new NullLogger() );
86 }
87
91 protected function findFirejail() {
92 if ( $this->firejail === null ) {
93 $this->firejail = ExecutableFinder::findInDefaultPaths( 'firejail' );
94 }
95
96 return $this->firejail;
97 }
98
105 public function logStderr( bool $yesno = true ): void {
106 $this->doLogStderr = $yesno;
107 }
108
116 private function getLocalShellboxOptions() {
117 $options = [
118 'tempDir' => wfTempDir(),
119 'useBashWrapper' => file_exists( '/bin/bash' ),
120 'cgroup' => $this->cgroup
121 ];
122 if ( $this->restrictionMethod === 'firejail' ) {
123 $firejailPath = $this->findFirejail();
124 if ( !$firejailPath ) {
125 throw new \RuntimeException( 'firejail is enabled, but cannot be found' );
126 }
127 $options['useFirejail'] = true;
128 $options['firejailPath'] = $firejailPath;
129 $options['firejailProfile'] = __DIR__ . '/firejail.profile';
130 }
131 return $options;
132 }
133
139 public function create(): Command {
140 $allUsers = false;
141 if ( $this->restrictionMethod === 'firejail' ) {
142 if ( $this->useAllUsers === null ) {
143 global $IP;
144 // In case people are doing funny things with symlinks
145 // or relative paths, resolve them all.
146 $realIP = realpath( $IP );
147 $currentUser = posix_getpwuid( posix_geteuid() );
148 $this->useAllUsers = ( strpos( $realIP, '/home/' ) === 0 )
149 && ( strpos( $realIP, $currentUser['dir'] ) !== 0 );
150 if ( $this->useAllUsers ) {
151 $this->logger->warning( 'firejail: MediaWiki is located ' .
152 'in a home directory that does not belong to the ' .
153 'current user, so allowing access to all home ' .
154 'directories (--allusers)' );
155 }
156 }
157 $allUsers = $this->useAllUsers;
158 }
159 $executor = Shellbox::createUnboxedExecutor(
160 $this->getLocalShellboxOptions(), $this->logger );
161
162 $command = new Command( $executor );
163 $command->setLogger( $this->logger );
164 if ( $allUsers ) {
165 $command->allowPath( '/home' );
166 }
167 return $command
168 ->limits( $this->limits )
169 ->logStderr( $this->doLogStderr );
170 }
171
179 public function createBoxed( ?string $service = null ): BoxedCommand {
180 if ( $this->shellboxClientFactory->isEnabled( $service ) ) {
181 $client = $this->shellboxClientFactory->getClient( [
182 'timeout' => $this->limits['walltime'] + 1,
183 'service' => $service,
184 ] );
185 $executor = new RemoteBoxedExecutor( $client );
186 $executor->setLogger( $this->logger );
187 } else {
188 $executor = Shellbox::createBoxedExecutor(
189 $this->getLocalShellboxOptions(),
190 $this->logger );
191 }
192 return $executor->createCommand()
193 ->cpuTimeLimit( $this->limits['time'] )
194 ->wallTimeLimit( $this->limits['walltime'] )
195 ->memoryLimit( $this->limits['memory'] * 1024 )
196 ->fileSizeLimit( $this->limits['filesize'] * 1024 )
197 ->logStderr( $this->doLogStderr );
198 }
199}
wfTempDir()
Tries to get the system directory for temporary files.
if(!defined( 'MEDIAWIKI')) if(ini_get('mbstring.func_overload')) if(!defined( 'MW_ENTRY_POINT')) global $IP
Environment checks.
Definition Setup.php:91
if(!defined('MW_SETUP_CALLBACK'))
The persistent session ID (if any) loaded at startup.
Definition WebStart.php:82
Utility class to find executables in likely places.
static findInDefaultPaths( $names, $versionInfo=false)
Same as locateExecutable(), but checks in getPossibleBinPaths() by default.
Factory facilitating dependency injection for Command.
logStderr(bool $yesno=true)
When enabled, text sent to stderr will be logged with a level of 'error'.
__construct(ShellboxClientFactory $shellboxClientFactory, array $limits, $cgroup, $restrictionMethod)
createBoxed(?string $service=null)
Instantiates a new BoxedCommand.
create()
Instantiates a new Command.
Class used for executing shell commands.
Definition Command.php:39
This is a service which provides a configured client to access a remote Shellbox installation.
$command
Definition mcc.php:125