Merge pull request #291 from dyne/slam-refactor

Slam refactor
This commit is contained in:
Jaromil 2017-12-14 17:48:47 +01:00 committed by GitHub
commit e083ce7a23
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 125 additions and 53 deletions

View File

@ -74,6 +74,7 @@ For the instructions on how to get started using Tomb, see [INSTALL](INSTALL.md)
index update the search indexes of tombs index update the search indexes of tombs
search looks for filenames matching text patterns search looks for filenames matching text patterns
list list of open TOMBs and information on them list list of open TOMBs and information on them
ps list of running processes inside open TOMBs
close close a specific TOMB (or 'all') close close a specific TOMB (or 'all')
slam slam a TOMB killing all programs using it slam slam a TOMB killing all programs using it
resize resize a TOMB to a new size -s (can only grow) resize resize a TOMB to a new size -s (can only grow)
@ -95,10 +96,10 @@ For the instructions on how to get started using Tomb, see [INSTALL](INSTALL.md)
-k path to the key to be used ('-k -' to read from stdin) -k path to the key to be used ('-k -' to read from stdin)
-n don't process the hooks found in tomb -n don't process the hooks found in tomb
-o options passed to commands: open, lock, forge (see man) -o options passed to commands: open, lock, forge (see man)
-f force operation (i.e. even if swap is active) -f force operation (i.e. open even if swap is active)
-g use a GnuPG key to encrypt a tomb key -g use a GnuPG key to encrypt a tomb key
-r provide GnuPG recipients (separated by coma) -r provide GnuPG recipients (separated by comma)
-R provide GnuPG hidden recipients (separated by coma) -R provide GnuPG hidden recipients (separated by comma)
--kdf forge keys armored against dictionary attacks --kdf forge keys armored against dictionary attacks
-h print this help -h print this help

View File

@ -88,6 +88,14 @@ returns an error if it's not found. If the option
\fI--get-mountpoint\fR is used then print a simple list of currently \fI--get-mountpoint\fR is used then print a simple list of currently
open tomb mountpoint paths. open tomb mountpoint paths.
.B
.IP "ps"
List all the processes found running inside the tombs that are open,
printing out their PIDs and owners. This is useful to have an overview
of programs that are keeping the tombs busy and would eventually be
killed by the \fIslam\fR command. The lsof(8) utility is used
internally to enumerate processes running in one or all tombs.
.B .B
.IP "index" .IP "index"
Creates or updates the search indexes of all tombs currently open: Creates or updates the search indexes of all tombs currently open:

153
tomb
View File

@ -624,6 +624,7 @@ usage() {
_print " index update the search indexes of tombs" _print " index update the search indexes of tombs"
_print " search looks for filenames matching text patterns" _print " search looks for filenames matching text patterns"
_print " list list of open TOMBs and information on them" _print " list list of open TOMBs and information on them"
_print " ps list of running processes inside open TOMBs"
_print " close close a specific TOMB (or 'all')" _print " close close a specific TOMB (or 'all')"
_print " slam slam a TOMB killing all programs using it" _print " slam slam a TOMB killing all programs using it"
[[ $RESIZER == 1 ]] && { [[ $RESIZER == 1 ]] && {
@ -2272,10 +2273,13 @@ BEGIN { main="" }
main=$1 main=$1
} }
' '
} || { } || { # list a specific tomb
# list a specific tomb # add square parens if not present
local tname
if [[ "${1[1]}" = "[" ]]; then tname=$1
else tname="[$1]"; fi
mount -l \ mount -l \
| awk -vtomb="[$1]" ' | awk -vtomb="$tname" '
BEGIN { main="" } BEGIN { main="" }
/^\/dev\/mapper\/tomb/ { /^\/dev\/mapper\/tomb/ {
if($7!=tomb) next; if($7!=tomb) next;
@ -2609,7 +2613,6 @@ umount_tomb() {
for t in ${mounted_tombs}; do for t in ${mounted_tombs}; do
mapper=`basename ${t[(ws:;:)1]}` mapper=`basename ${t[(ws:;:)1]}`
# strip square parens from tombname
tombname=${t[(ws:;:)5]} tombname=${t[(ws:;:)5]}
tombmount=${t[(ws:;:)2]} tombmount=${t[(ws:;:)2]}
tombfs=${t[(ws:;:)3]} tombfs=${t[(ws:;:)3]}
@ -2636,31 +2639,17 @@ umount_tomb() {
} }
} }
[[ -n $SLAM ]] && {
_success "Slamming tomb ::1 tomb name:: mounted on ::2 mount point::" \
$tombname $tombmount
_message "Kill all processes busy inside the tomb."
{ slam_tomb "$tombmount" } || {
_failure "Cannot slam the tomb ::1 tomb name::" $tombname }
} || {
_message "Closing tomb ::1 tomb name:: mounted on ::2 mount point::" \ _message "Closing tomb ::1 tomb name:: mounted on ::2 mount point::" \
$tombname $tombmount } $tombname $tombmount
# check if there are binded dirs and close them # check if there are binded dirs and close them
bind_tombs=(`list_tomb_binds $tombname $tombmount`) bind_tombs=(`list_tomb_binds $tombname $tombmount`)
for b in ${bind_tombs}; do for b in ${(f)"$(list_tomb_binds $tombname $tombmount)"}; do
bind_mapper="${b[(ws:;:)1]}" bind_mapper="${b[(ws:;:)1]}"
bind_mount="${b[(ws:;:)2]}" bind_mount="${b[(ws:;:)2]}"
_message "Closing tomb bind hook: ::1 hook::" $bind_mount _message "Closing tomb bind hook: ::1 hook::" $bind_mount
_sudo umount "`print - ${bind_mount}`" || { _sudo umount $bind_mount ||
[[ -n $SLAM ]] && {
_success "Slamming tomb: killing all processes using this hook."
slam_tomb "`print - ${bind_mount}`" || _failure "Cannot slam the bind hook ::1 hook::" $bind_mount
umount "`print - ${bind_mount}`" || _failure "Cannot slam the bind hook ::1 hook::" $bind_mount
} || {
_failure "Tomb bind hook ::1 hook:: is busy, cannot close tomb." $bind_mount _failure "Tomb bind hook ::1 hook:: is busy, cannot close tomb." $bind_mount
}
}
done done
# check if the tomb is actually still mounted. Background: # check if the tomb is actually still mounted. Background:
@ -2694,14 +2683,13 @@ umount_tomb() {
[[ "$tombmount" -regex-match "[/run]?/media[/$_USER]?/$tombname_regex" ]] && { [[ "$tombmount" -regex-match "[/run]?/media[/$_USER]?/$tombname_regex" ]] && {
_sudo rmdir $tombmount } _sudo rmdir $tombmount }
_sudo cryptsetup luksClose $mapper _sudo cryptsetup luksClose $mapper ||
[[ $? == 0 ]] || { _failure "Error occurred in cryptsetup luksClose ::1 mapper::" $mapper
_failure "Error occurred in cryptsetup luksClose ::1 mapper::" $mapper }
# Normally the loopback device is detached when unused # Normally the loopback device is detached when unused
[[ -e "/dev/$tombloop" ]] && { [[ -e "/dev/$tombloop" ]] && {
_sudo losetup -d "/dev/$tombloop" _sudo losetup -d "/dev/$tombloop" ||
[[ $? = 0 ]] || _verbose "/dev/$tombloop was already closed." _verbose "/dev/$tombloop was already closed."
} }
_success "Tomb ::1 tomb name:: closed: your bones will rest in peace." $tombname _success "Tomb ::1 tomb name:: closed: your bones will rest in peace." $tombname
@ -2711,30 +2699,94 @@ umount_tomb() {
return 0 return 0
} }
list_processes() {
# $1 = (optional) name of tomb
# returns a list of process UIDs, one per line
local mounted_tombs i
local pnum puid pcmd powner found
found=0
mounted_tombs=(`list_tomb_mounts $1`)
if [[ "${#mounted_tombs}" -gt 0 ]]; then
if [[ "$1" = "" ]]; then
_success "Listing processes running inside all open tombs..."
else
_success "Listing processes running inside tomb '::1 tombname::'..." "$1"
fi
for i in ${mounted_tombs}; do
_verbose "scanning tomb: ::1 tombmount::" $i
tombmount=${i[(ws:;:)2]}
tombname=${i[(ws:;:)5]}
for pnum in ${(f)"$(_sudo lsof -t +D $tombmount)"}; do
found=$(($found + 1))
_verbose "process found: $pnum"
puid=$(_cat /proc/${pnum}/loginuid)
pcmd=$(_cat /proc/${pnum}/cmdline)
powner=$(getent passwd $puid)
powner=${powner[(ws@:@)1]}
_verbose "process found: $pnum $pcmd ($powner)"
_message "::1 tombname:: ::2 cmd:: (::3 owner::)" \
$tombname $pcmd $powner
done
done
fi
_message "::1 foundproc:: running processes found inside ::2 numtombs:: open tombs" \
$found ${#mounted_tombs}
}
# Kill all processes using the tomb # Kill all processes using the tomb
slam_tomb() { slam_tomb() {
# $1 = tomb mount point # $1 = (optional) name of tomb to slam, or "all" if more mounted
if [[ -z `lsof -t +D "$1" 2>/dev/null` ]]; then
return 0 if [ "$1" = "all" ]; then
mounted_tombs=(`list_tomb_mounts`)
else
mounted_tombs=(`list_tomb_mounts $1`)
fi fi
#Note: shells are NOT killed by INT or TERM, but they are killed by HUP
[[ ${#mounted_tombs} == 0 ]] && {
_failure "There is no open tomb to be closed." }
[[ ${#mounted_tombs} -gt 1 && -z "$1" ]] && {
_warning "Too many tombs mounted, please specify one (see tomb list)"
_warning "or issue the command 'tomb close all' to close them all."
_failure "Operation aborted." }
local pnum puid pcmd powner result
result=0
# iterate through all mounted tomb affected
for i in ${mounted_tombs}; do
tombname=${i[(ws:;:)5]}
tombmount=${i[(ws:;:)2]}
_success "Slamming tomb ::1 tombname:: mounted on ::2 tombmount::" \
${tombname} ${tombmount}
# iterate through all processes running in mounted tombs
for pnum in ${(f)"$(_sudo lsof -t +D $tombmount)"}; do
puid=$(_cat /proc/${pnum}/loginuid)
pcmd=$(_cat /proc/${pnum}/cmdline)
powner=$(getent passwd $puid)
powner=${powner[(ws@:@)1]}
_verbose "process found: $pnum $pcmd ($powner)"
# iterate through 3 different signals to send, break on success
for s in TERM HUP KILL; do for s in TERM HUP KILL; do
_verbose "Sending ::1:: to processes inside the tomb:" $s _message "::1 tombname:: sending ::2 sig:: to ::3 cmd:: (::4 uid::)" \
if option_is_set -D; then ${tombname} ${s} ${pcmd} ${powner}
ps -fp `lsof -t +D "$1" 2>/dev/null`| _sudo kill -$s $pnum
while read line; do # give some time to the process for a clean quit
_verbose $line sleep .5
# stop sending other signals if kill was succesfull
[[ -r /proc/$pnum ]] || break
done done
fi # if process still running then signal failure
kill -$s `lsof -t +D "$1"` [[ -r /proc/$pnum ]] && {
if [[ -z `lsof -t +D "$1" 2>/dev/null` ]]; then _warning "Can't kill ::1 process:: ::2 pcmd:: (::3 powner::)" \
return 0 $pnum $pcmd $powner
fi result=1 }
if ! option_is_set -f; then
sleep 3
fi
done done
return 1 # if it failed killing a process, report it
[[ $result = 0 ]] && umount_tomb $tombname
done
return $result
} }
# }}} - Tomb close # }}} - Tomb close
@ -2787,6 +2839,7 @@ main() {
subcommands_opts[close]="" subcommands_opts[close]=""
subcommands_opts[help]="" subcommands_opts[help]=""
subcommands_opts[slam]="" subcommands_opts[slam]=""
subcommands_opts[ps]=""
subcommands_opts[list]="-get-mountpoint " subcommands_opts[list]="-get-mountpoint "
subcommands_opts[index]="" subcommands_opts[index]=""
@ -2935,9 +2988,19 @@ main() {
mount_tomb $PARAM mount_tomb $PARAM
;; ;;
# List all processes using a tomb
ps)
list_processes $PARAM
;;
# Slam a tomb killing all processes running inside
slam)
slam_tomb $PARAM
;;
# Close the tomb # Close the tomb
# `slam` is used to force closing. # `slam` is used to force closing.
umount|close|slam) umount|close)
[[ "$subcommand" == "slam" ]] && { [[ "$subcommand" == "slam" ]] && {
SLAM=1 SLAM=1
[[ $LSOF == 0 ]] && { [[ $LSOF == 0 ]] && {