MediaWiki  master
CommandFactory.php
Go to the documentation of this file.
1 <?php
21 namespace MediaWiki\Shell;
22 
24 use Psr\Log\LoggerAwareTrait;
25 use Psr\Log\NullLogger;
26 use Shellbox\Command\BoxedCommand;
27 use Shellbox\Command\RemoteBoxedExecutor;
28 use Shellbox\Shellbox;
29 
36  use LoggerAwareTrait;
37 
39  private $limits;
40 
42  private $cgroup;
43 
45  private $doLogStderr = false;
46 
51 
55  private $firejail;
56 
58  private $useAllUsers;
59 
62 
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 }
MediaWiki\Shell\CommandFactory\$limits
array $limits
Definition: CommandFactory.php:39
MediaWiki\Shell\Command
Class used for executing shell commands.
Definition: Command.php:39
MediaWiki\Shell\CommandFactory\$firejail
string bool null $firejail
Definition: CommandFactory.php:55
MediaWiki\Shell\CommandFactory\__construct
__construct(ShellboxClientFactory $shellboxClientFactory, array $limits, $cgroup, $restrictionMethod)
Definition: CommandFactory.php:69
MediaWiki\Shell\CommandFactory\createBoxed
createBoxed(?string $service=null)
Instantiates a new BoxedCommand.
Definition: CommandFactory.php:179
MediaWiki\Shell\CommandFactory\$doLogStderr
bool $doLogStderr
Definition: CommandFactory.php:45
MediaWiki\Shell\CommandFactory\$useAllUsers
bool $useAllUsers
Definition: CommandFactory.php:58
ExecutableFinder
Utility class to find executables in likely places.
Definition: ExecutableFinder.php:28
MediaWiki\Shell\CommandFactory\logStderr
logStderr(bool $yesno=true)
When enabled, text sent to stderr will be logged with a level of 'error'.
Definition: CommandFactory.php:105
MediaWiki\Shell\CommandFactory\$restrictionMethod
string bool $restrictionMethod
Definition: CommandFactory.php:50
MediaWiki\Shell\CommandFactory
Factory facilitating dependency injection for Command.
Definition: CommandFactory.php:35
MediaWiki\Shell\ShellboxClientFactory
This is a service which provides a configured client to access a remote Shellbox installation.
Definition: ShellboxClientFactory.php:20
MediaWiki\Shell\CommandFactory\$cgroup
string bool $cgroup
Definition: CommandFactory.php:42
$command
$command
Definition: mcc.php:125
wfTempDir
wfTempDir()
Tries to get the system directory for temporary files.
Definition: GlobalFunctions.php:1728
MediaWiki\Shell
Definition: Command.php:21
MediaWiki\Shell\CommandFactory\getLocalShellboxOptions
getLocalShellboxOptions()
Get the options which will be used for local unboxed execution.
Definition: CommandFactory.php:116
ExecutableFinder\findInDefaultPaths
static findInDefaultPaths( $names, $versionInfo=false)
Same as locateExecutable(), but checks in getPossibleBinPaths() by default.
Definition: ExecutableFinder.php:96
MediaWiki\Shell\CommandFactory\findFirejail
findFirejail()
Definition: CommandFactory.php:91
$IP
$IP
Definition: WebStart.php:49
MediaWiki\Shell\CommandFactory\$shellboxClientFactory
ShellboxClientFactory $shellboxClientFactory
Definition: CommandFactory.php:61
MediaWiki\Shell\CommandFactory\create
create()
Instantiates a new Command.
Definition: CommandFactory.php:139