1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
|
<?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.
*
* @group large
* @group Shell
* @covers FirejailCommand
*/
class FirejailCommandIntegrationTest extends PHPUnit\Framework\TestCase {
public function setUp() {
parent::setUp();
if ( Shell::command( 'which', 'firejail' )->execute()->getExitCode() ) {
$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 ],
];
}
}
|