From 8832a2aad6d104f95008fafbb0dcf7d33d108a36 Mon Sep 17 00:00:00 2001 From: Peter Cai Date: Sun, 6 Nov 2022 17:48:42 -0500 Subject: [PATCH] Use a file-based lock to prevent closing while being accessed --- gocrypt.bash | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/gocrypt.bash b/gocrypt.bash index ae7dcac..a68e3e0 100755 --- a/gocrypt.bash +++ b/gocrypt.bash @@ -36,6 +36,17 @@ gocrypt_unique_task_identifier() { echo "pass-gocrypt-$(sha256sum <<< "$PREFIX" | cut -d ' ' -f 1)" } +# This file is used as a lock for all access to the encrypted password store +# so that it prevents the auto-close task from unmounting before all operations +# are completed +gocrypt_lock_file_path() { + local path="$XDG_RUNTIME_DIR" + if [ -z "$path" ] || [ ! -d "$path" ]; then + path="/tmp" + fi + echo "$path/$(gocrypt_unique_task_identifier).lck" +} + gocrypt_spawn_close_task() { which systemd-run > /dev/null || return which sha256sum > /dev/null || return @@ -45,7 +56,8 @@ gocrypt_spawn_close_task() { systemctl --user stop "$task_name.timer" > /dev/null 2>1 # Create a new task - systemd-run --user --on-active=$gocrypt_close_timeout --unit="$task_name" /usr/bin/env bash -c \ + systemd-run --user --on-active=$gocrypt_close_timeout --unit="$task_name" \ + /usr/bin/env flock -x "$(gocrypt_lock_file_path)" /usr/bin/env bash -c \ "fusermount -u '$PREFIX'/'$gocrypt_dec_dir' || fusermount -u -z '$PREFIX'/'$gocrypt_dec_dir'" echo "Will close the gocryptfs mount after $gocrypt_close_timeout seconds" @@ -151,6 +163,7 @@ gocrypt_close() { } gocrypt_delegate() { + # Note: the caller MUST hold the lock for accessing the encrypted password store before calling gocrypt_open_check # Delegate command to another `pass` instance that manages what is inside of the mountpoint PASSWORD_STORE_DIR="$PWD/$gocrypt_dec_dir" "$PROGRAM" "$@" @@ -236,6 +249,13 @@ fi # cd into the password store prefix cd "$PREFIX" +# Open the lock file +touch "$(gocrypt_lock_file_path)" || exit 1 +exec {lock_fd}< "$(gocrypt_lock_file_path)" || exit 1 + +# Always take the exclusive lock while any command is running -- to prevent the close task from running at the same time +flock -x $lock_fd + case "$1" in help) gocrypt_help @@ -264,3 +284,6 @@ case "$1" in *) gocrypt_die "Unknown command $1 for gocrypt" esac + +# Manual unlock; not strictly necessary since exit will also release the lock +flock -u $lock_fd