sudo: add kill-child.sh
ultimately, a non-previlieged child cannot kill previlieged parent. all the notes and research in shell.js are not useful.
This commit is contained in:
@@ -71,4 +71,7 @@ yellowtent ALL=(root) NOPASSWD: /home/yellowtent/box/src/scripts/hdparm.sh
|
||||
Defaults!/home/yellowtent/box/src/scripts/hdparm.sh env_keep="HOME BOX_ENV"
|
||||
yellowtent ALL=(root) NOPASSWD: /home/yellowtent/box/src/scripts/logtail.sh
|
||||
|
||||
Defaults!/home/yellowtent/box/src/scripts/kill-child.sh env_keep="HOME BOX_ENV"
|
||||
yellowtent ALL=(root) NOPASSWD: /home/yellowtent/box/src/scripts/kill-child.sh
|
||||
|
||||
cloudron-support ALL=(ALL) NOPASSWD: ALL
|
||||
|
||||
+6
-6
@@ -9,6 +9,7 @@ const assert = require('assert'),
|
||||
TransformStream = stream.Transform;
|
||||
|
||||
const LOGTAIL_CMD = path.join(__dirname, 'scripts/logtail.sh');
|
||||
const KILL_CHILD_CMD = path.join(__dirname, 'scripts/kill-child.sh');
|
||||
|
||||
class LogStream extends TransformStream {
|
||||
constructor(options) {
|
||||
@@ -68,13 +69,12 @@ function tail(filePaths, options) {
|
||||
if (options.follow) args.push('--follow');
|
||||
|
||||
if (options.sudo) {
|
||||
const cp = child_process.spawn('/usr/bin/sudo', [ '-S', LOGTAIL_CMD, ...args, ...filePaths ]);
|
||||
cp.terminate = () => { // see note in shell.js
|
||||
child_process.spawn('kill', ['-SIGKILL', -cp.pid], { detached: true }, (error) => {
|
||||
if (error) debug(`tail could not terminate`, error);
|
||||
const cp = child_process.spawn('/usr/bin/sudo', [ LOGTAIL_CMD, ...args, ...filePaths ]);
|
||||
cp.terminate = () => {
|
||||
child_process.execFile('/usr/bin/sudo', [ KILL_CHILD_CMD, cp.pid, process.pid ], { encoding: 'utf8' }, (error, stdout, stderr) => {
|
||||
if (error) debug(`tail: failed to kill children`, stdout, stderr);
|
||||
});
|
||||
};
|
||||
cp.stdin.end();
|
||||
return cp;
|
||||
} else {
|
||||
const cp = child_process.spawn('/usr/bin/tail', args.concat(filePaths));
|
||||
@@ -96,7 +96,7 @@ function journalctl(unit, options) {
|
||||
|
||||
if (options.follow) args.push('--follow');
|
||||
|
||||
const cp = spawn('journalctl', args);
|
||||
const cp = child_process.spawn('journalctl', args);
|
||||
cp.terminate = () => cp.kill('SIGKILL');
|
||||
return cp;
|
||||
}
|
||||
|
||||
Executable
+46
@@ -0,0 +1,46 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -eu -o pipefail
|
||||
|
||||
if [[ ${EUID} -ne 0 ]]; then
|
||||
echo "This script should be run as root." > /dev/stderr
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ $# -eq 0 ]]; then
|
||||
echo "No arguments supplied"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ "$1" == "--check" ]]; then
|
||||
echo "OK"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
function killtree() {
|
||||
local pid=$1
|
||||
for cpid in $(pgrep -P "$pid"); do
|
||||
killtree "${cpid}" || true
|
||||
done
|
||||
echo "kill-child: killing $pid"
|
||||
kill -SIGKILL "${pid}" 2>/dev/null || true
|
||||
}
|
||||
|
||||
readonly target_pid="$1"
|
||||
readonly expected_parent_pid="$2"
|
||||
|
||||
readonly target_actual_parent_pid=$(ps -o ppid= -p "${target_pid}" 2>/dev/null | tr -d ' ')
|
||||
|
||||
if [[ -z "${target_actual_parent_pid}" ]]; then
|
||||
echo "kill-child: target PID ${target_pid} does not exist."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ "${target_actual_parent_pid}" -ne "${expected_parent_pid}" ]]; then
|
||||
echo "kill-child: refusing to kill — PID ${target_pid} is not a child of ${expected_parent_pid}."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
readonly child_cmd=$(ps -o cmd= -p "${target_pid}")
|
||||
echo "kill-child: kill PID ${target_pid} (command: ${child_cmd})"
|
||||
killtree ${target_pid}
|
||||
Reference in New Issue
Block a user