2017-12-22 01:20:45 +00:00
|
|
|
<?php
|
|
|
|
|
|
|
|
|
|
use MediaWiki\Shell\FirejailCommand;
|
|
|
|
|
use MediaWiki\Shell\Shell;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Integration tests to ensure that firejail actually prevents execution.
|
|
|
|
|
* Meant to run on vagrant, although will probably work on other setups
|
|
|
|
|
* as long as firejail and sudo has similar config.
|
2018-03-20 16:14:34 +00:00
|
|
|
*
|
2018-03-29 19:53:10 +00:00
|
|
|
* @group large
|
2017-12-22 01:20:45 +00:00
|
|
|
* @group Shell
|
2018-03-20 16:14:34 +00:00
|
|
|
* @covers FirejailCommand
|
2017-12-22 01:20:45 +00:00
|
|
|
*/
|
2018-02-17 12:29:13 +00:00
|
|
|
class FirejailCommandIntegrationTest extends PHPUnit\Framework\TestCase {
|
2017-12-22 01:20:45 +00:00
|
|
|
|
|
|
|
|
public function setUp() {
|
|
|
|
|
parent::setUp();
|
2018-06-24 21:09:32 +00:00
|
|
|
if ( Shell::isDisabled() ) {
|
|
|
|
|
$this->markTestSkipped( 'shelling out is disabled' );
|
|
|
|
|
} elseif ( Shell::command( 'which', 'firejail' )->execute()->getExitCode() ) {
|
2017-12-22 01:20:45 +00:00
|
|
|
$this->markTestSkipped( 'firejail not installed' );
|
|
|
|
|
} elseif ( wfIsWindows() ) {
|
|
|
|
|
$this->markTestSkipped( 'test supports POSIX environments only' );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function testSanity() {
|
|
|
|
|
// Make sure that firejail works at all.
|
|
|
|
|
$command = new FirejailCommand( 'firejail' );
|
|
|
|
|
$command
|
|
|
|
|
->unsafeParams( 'ls .' )
|
|
|
|
|
->restrict( Shell::RESTRICT_DEFAULT );
|
|
|
|
|
$result = $command->execute();
|
|
|
|
|
$this->assertSame( 0, $result->getExitCode() );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @coversNothing
|
|
|
|
|
* @dataProvider provideExecute
|
|
|
|
|
*/
|
|
|
|
|
public function testExecute( $testCommand, $flag ) {
|
|
|
|
|
if ( preg_match( '/^sudo /', $testCommand ) ) {
|
|
|
|
|
if ( Shell::command( 'sudo', '-n', 'ls', '/' )->execute()->getExitCode() ) {
|
|
|
|
|
$this->markTestSkipped( 'need passwordless sudo' );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$command = new FirejailCommand( 'firejail' );
|
|
|
|
|
$command
|
|
|
|
|
->unsafeParams( $testCommand )
|
|
|
|
|
// If we don't restrict at all, firejail won't be invoked,
|
|
|
|
|
// so the test will give a false positive if firejail breaks
|
|
|
|
|
// the command for some non-flag-related reason. Instead,
|
|
|
|
|
// set some flag that won't get in the way.
|
|
|
|
|
->restrict( $flag === Shell::NO_NETWORK ? Shell::PRIVATE_DEV : Shell::NO_NETWORK );
|
|
|
|
|
$result = $command->execute();
|
|
|
|
|
$this->assertSame( 0, $result->getExitCode(), 'sanity check' );
|
|
|
|
|
|
|
|
|
|
$command = new FirejailCommand( 'firejail' );
|
|
|
|
|
$command
|
|
|
|
|
->unsafeParams( $testCommand )
|
|
|
|
|
->restrict( $flag );
|
|
|
|
|
$result = $command->execute();
|
|
|
|
|
$this->assertNotSame( 0, $result->getExitCode(), 'real check' );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function provideExecute() {
|
|
|
|
|
global $IP;
|
|
|
|
|
return [
|
|
|
|
|
[ 'sudo -n ls /', Shell::NO_ROOT ],
|
|
|
|
|
[ 'sudo -n ls /', Shell::SECCOMP ], // not a great test but seems to work
|
|
|
|
|
[ 'ls /dev/cpu', Shell::PRIVATE_DEV ],
|
|
|
|
|
[ 'curl -fsSo /dev/null https://wikipedia.org/', Shell::NO_NETWORK ],
|
|
|
|
|
[ 'exec ls /', Shell::NO_EXECVE ],
|
|
|
|
|
[ "cat $IP/LocalSettings.php", Shell::NO_LOCALSETTINGS ],
|
|
|
|
|
];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|