Skip to content

Commit 0974c52

Browse files
committed
WIP: jail cleanup and updates
1 parent bb38acd commit 0974c52

File tree

1 file changed

+128
-13
lines changed

1 file changed

+128
-13
lines changed

server/lib/classes/system.inc.php

Lines changed: 128 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -944,17 +944,19 @@ function move($file1, $file2) {
944944
function rmdir($dir, $recursive=false) {
945945
$dir = rtrim($dir, '/');
946946
if (is_dir($dir)) {
947-
$objects = scandir($dir);
947+
$objects = array_diff(scandir($dir), array('.', '..'));
948948
foreach ($objects as $object) {
949-
if ($object != "." && $object != ".." && $recursive) {
950-
if (filetype($dir.'/'.$object) == 'dir')
951-
$this->rmdir($dir.'/'.$object, $recursive);
952-
else unlink ($dir.'/'.$object);
949+
if ($recursive) {
950+
if (is_dir("$dir/$object")) {
951+
$this->rmdir("$dir/$object", $recursive);
952+
} else {
953+
unlink ("$dir/$object");
954+
}
953955
}
954956
}
955-
reset($objects);
956-
rmdir($dir);
957+
return rmdir($dir);
957958
}
959+
return false;
958960
}
959961

960962
function touch($file, $allow_symlink = false){
@@ -2241,7 +2243,7 @@ public function create_jailkit_user($username, $home_dir, $user_home_dir, $shell
22412243

22422244
public function create_jailkit_chroot($home_dir, $app_sections = array(), $options = array()) {
22432245
if(!is_dir($home_dir)) {
2244-
$app->log("Jail directory does not exist: $homedir", LOGLEVEL_WARN);
2246+
$app->log("create_jailkit_chroot: jail directory does not exist: $homedir", LOGLEVEL_WARN);
22452247
return false;
22462248
}
22472249
if(empty($app_sections)) {
@@ -2291,7 +2293,7 @@ public function create_jailkit_chroot($home_dir, $app_sections = array(), $optio
22912293

22922294
public function create_jailkit_programs($home_dir, $programs = array(), $options = array()) {
22932295
if(!is_dir($home_dir)) {
2294-
$app->log("Jail directory does not exist: $homedir", LOGLEVEL_WARN);
2296+
$app->log("create_jailkit_programs: jail directory does not exist: $homedir", LOGLEVEL_WARN);
22952297
return false;
22962298
}
22972299
if(empty($programs)) {
@@ -2311,6 +2313,7 @@ public function create_jailkit_programs($home_dir, $programs = array(), $options
23112313
'|^/tmp/?$|',
23122314
'|^/run/?$|',
23132315
'|^/boot/?$|',
2316+
'|^/var(/?|/backups?/?)?$|',
23142317
);
23152318

23162319
$program_args = '';
@@ -2350,16 +2353,19 @@ public function create_jailkit_programs($home_dir, $programs = array(), $options
23502353

23512354
public function update_jailkit_chroot($home_dir, $sections = array(), $programs = array(), $options = array()) {
23522355
if(!is_dir($home_dir)) {
2353-
$app->log("Jail directory does not exist: $homedir", LOGLEVEL_WARN);
2356+
$app->log("update_jailkit_chroot: jail directory does not exist: $homedir", LOGLEVEL_WARN);
23542357
return false;
23552358
}
23562359

2357-
$opts = array('force');
2360+
$opts = array();
23582361
foreach ($options as $opt) {
23592362
switch ($opt) {
23602363
case '-k|hardlink':
23612364
$opts[] = 'hardlink';
23622365
break;
2366+
case '-f|force':
2367+
$opts[] = 'force';
2368+
break;
23632369
}
23642370
}
23652371

@@ -2380,17 +2386,21 @@ public function update_jailkit_chroot($home_dir, $sections = array(), $programs
23802386
'var',
23812387
);
23822388

2389+
$skips = '';
2390+
$multiple_links = array();
23832391
foreach ($jailkit_directories as $dir) {
23842392
$root_dir = '/'.$dir;
23852393
$jail_dir = rtrim($home_dir, '/') . '/'.$dir;
23862394

23872395
if (!is_dir($jail_dir)) {
2396+
$skips .= " --skip=/$dir";
23882397
continue;
23892398
}
23902399

23912400
// if directory exists in jail but not in root, remove it
23922401
if (is_dir($jail_dir) && !is_dir($root_dir)) {
23932402
$this->rmdir($jail_dir, true);
2403+
$skips .= " --skip=/$dir";
23942404
continue;
23952405
}
23962406

@@ -2401,6 +2411,51 @@ public function update_jailkit_chroot($home_dir, $sections = array(), $programs
24012411
if (!in_array($opts, 'hardlink') && !in_array($options, 'allow_hardlink')) {
24022412
$app->log("TODO: search for and remove hardlinked files", LOGLEVEL_DEBUG);
24032413
// search for and save list of files
2414+
2415+
$find_multiple_links = function ( $path ) use ( &$find_multiple_links ) {
2416+
$found = array();
2417+
if (is_dir($path)) {
2418+
$objects = array_diff(scandir($path), array('.', '..'));
2419+
foreach ($objects as $object) {
2420+
$ret = $find_multiple_links( "$path/$object" );
2421+
if (count($ret) > 0) {
2422+
$found = array_merge($found, $ret);
2423+
}
2424+
}
2425+
} else {
2426+
$stat = stat($path);
2427+
if ($stat['nlink'] > 1) {
2428+
$found[$path] = $path;
2429+
}
2430+
}
2431+
return $found;
2432+
};
2433+
2434+
$ret = $find_multiple_links( $jail_dir );
2435+
if (count($ret) > 0) {
2436+
$multiple_links = array_merge($multiple_links, $ret);
2437+
}
2438+
}
2439+
}
2440+
2441+
2442+
$cmd = 'jk_update --jail='.escapeshellarg($home_dir) . $skips;
2443+
exec($cmd, $out, $ret);
2444+
foreach ($out as $line) {
2445+
if (substr( $line, 0, 4 ) === "skip")) {
2446+
continue;
2447+
}
2448+
if (preg_match('|^(? [^ ]+){6}(.+)$'.preg_quote($home_dir, '|').'|', $line, $matches)) {
2449+
# remove deprecated files that jk_update failed to remove
2450+
if (is_file($matches[1])) {
2451+
$app->log("removing deprecated file which jk_update failed to remove: ".$matches[1], LOGLEVEL_DEBUG);
2452+
unlink($matches[1]);
2453+
} elseif (is_dir($matches[1])) {
2454+
$app->log("removing deprecated directory which jk_update failed to remove: ".$matches[1], LOGLEVEL_DEBUG);
2455+
$this->rmdir($matches[1], true);
2456+
}
2457+
# unhandled error
2458+
$app->log("jk_update error for jail $home_dir: ".$matches[1], LOGLEVEL_DEBUG);
24042459
}
24052460
}
24062461

@@ -2417,9 +2472,24 @@ public function update_jailkit_chroot($home_dir, $sections = array(), $programs
24172472
$this->chmod($home_dir . '/tmp', 0770, true);
24182473
}
24192474

2420-
// search for and remove hardlinked
2475+
// search for any hardlinked files which are now missing
24212476
if (!in_array($opts, 'hardlink') && !in_array($options, 'allow_hardlink')) {
2422-
$app->log("TODO: search for hardlinked files now missing and add back", LOGLEVEL_DEBUG);
2477+
foreach ($multiple_links as $file) {
2478+
if (!is_file($file)) {
2479+
// strip $home_dir from $file
2480+
if (substr($file, 0, strlen(rtrim($home_dir, '/'))) == strlen(rtrim($home_dir, '/'))) {
2481+
$file = substr($file, strlen(rtrim($home_dir, '/')));
2482+
}
2483+
if (is_file($file)) { // file exists in root
2484+
$app->log("file with multiple links still missing, running jk_cp to restore: $file", LOGLEVEL_DEBUG);
2485+
$cmd = 'jk_cp -j ? ' . escapeshellarg($file);
2486+
$this->exec_safe($cmd, $home_dir);
2487+
} else {
2488+
// not necessarily an error
2489+
$app->log("previously hardlinked file was not found to restore: $file", LOGLEVEL_DEBUG);
2490+
}
2491+
}
2492+
}
24232493
}
24242494

24252495
// Fix permissions of the root firectory
@@ -2428,6 +2498,51 @@ public function update_jailkit_chroot($home_dir, $sections = array(), $programs
24282498
return true;
24292499
}
24302500

2501+
public function delete_jailkit_chroot($home_dir, $options = array()) {
2502+
if(!is_dir($home_dir)) {
2503+
$app->log("delete_jailkit_chroot: jail directory does not exist: $homedir", LOGLEVEL_DEBUG);
2504+
return false;
2505+
}
2506+
2507+
$jailkit_directories = array(
2508+
'bin',
2509+
'dev',
2510+
'etc',
2511+
'lib',
2512+
'lib32',
2513+
'lib64',
2514+
'opt',
2515+
'sys',
2516+
'usr',
2517+
'var',
2518+
);
2519+
2520+
$removed = '';
2521+
foreach ($jailkit_directories as $dir) {
2522+
$jail_dir = rtrim($home_dir, '/') . '/'.$dir;
2523+
2524+
if (is_dir($jail_dir)) {
2525+
$this->rmdir($jail_dir, true);
2526+
$removed .= ' /'.$dir;
2527+
}
2528+
2529+
}
2530+
2531+
$app->log("delete_jailkit_chroot: removed from jail $homedir: $removed", LOGLEVEL_DEBUG);
2532+
2533+
// handle etc and home special
2534+
$home = rtrim($home_dir, '/') . '/home';
2535+
@rmdir($home); # ok to fail if non-empty
2536+
2537+
$private = rtrim($home_dir, '/') . '/private';
2538+
if (is_dir($home) && is_dir($private)) {
2539+
$archive = $private.'/home-'.date('c');
2540+
rename($home, $archive);
2541+
}
2542+
2543+
return true;
2544+
}
2545+
24312546

24322547
public function pipe_exec($cmd, $stdin, &$retval = null, &$stderr = null) {
24332548
$descriptors = array(

0 commit comments

Comments
 (0)