fighting mount duplications
authorThomas Walker Lynch <eknp9n@reasoningtechnology.com>
Thu, 25 Sep 2025 13:02:20 +0000 (13:02 +0000)
committerThomas Walker Lynch <eknp9n@reasoningtechnology.com>
Thu, 25 Sep 2025 13:02:20 +0000 (13:02 +0000)
13 files changed:
developer/source/mount/device_mapname__open_mount.sh
developer/source/mount/device_umount.sh
developer/source/mount/disable_linger.sh
developer/source/mount/logout_subu.sh
developer/source/mount/mapname__mounted_masu_list.sh
developer/source/mount/mapname_masu__to_home.sh
developer/source/mount/masu__map_own_all.sh
developer/source/mount/masu__subu_data_dir_list.sh
developer/source/mount/masu__subu_dir_list.sh
developer/source/mount/masu_subu__map_own.sh
developer/source/mount/masu_subu__map_own_orig.sh
developer/source/mount/masu_subu__uid.sh
developer/source/mount/mount_pt_list.sh

index 130c925..b14ebe3 100755 (executable)
@@ -1,4 +1,4 @@
-#!/bin/env bash
+#!/usr/bin/env bash
 
 if [[ $EUID -ne 0 ]]; then
   echo "❌ This script must be run as root." >&2
index fd2e819..3eadc37 100755 (executable)
@@ -1,4 +1,4 @@
-#!/bin/env bash
+#!/usr/bin/env bash
 
 if [[ $EUID -ne 0 ]]; then
   echo "❌ This script must be run as root." >&2
index 8a95198..a9fffdd 100755 (executable)
@@ -1,4 +1,4 @@
-#!/bin/env bash
+#!/usr/bin/env bash
 # disable_linger_subu — turn off systemd --user lingering for all <masu>-* users
 # Usage: sudo disable_linger_subu --masu Thomas
 
index e9e7280..9e95cb2 100755 (executable)
@@ -1,4 +1,4 @@
-#!#!/bin/env bash
+#!/usr/bin/env bash
 # logout_subu — cleanly stop subu users, tear down bindfs, unbind /home, unmount device, close LUKS
 # Usage:
 #   sudo logout_subu --masu Thomas --device Eagle [--aggressive] [--dry-run]
index bd83a46..b955b07 100755 (executable)
@@ -1,4 +1,4 @@
-#!/bin/env bash
+#!/usr/bin/env bash
 
 # Function to list users in the /mnt/<device>/user_data directory
 device_user_list() {
index 89a8acc..b776626 100755 (executable)
@@ -1,4 +1,4 @@
-#!/bin/env bash
+#!/usr/bin/env bash
 
 # Function to bind mount a user's data to /home/<user>
 device_user_bind() {
index 0bcfb92..59cd368 100755 (executable)
@@ -1,28 +1,28 @@
-#!/bin/env bash
-# masu__map_own_all.sh
-
+#!/usr/bin/env bash
+# usage: sudo ./masu__map_own_all.sh <masu> [--suid=subu1,subu2]
 set -euo pipefail
+
 masu="${1:?Usage: $0 <masu> [--suid=subu1,subu2] }"
-suid_list="${2-}"  # optional: --suid=a,b,c
+suid_list="${2-}"  # optional --suid=a,b,c
 
-# Build a set for quick membership checks
 want_suid() {
-  [[ -n "$suid_list" ]] || return 1
-  [[ "$suid_list" =~ ^--suid= ]] || return 1
+  [[ -n "$suid_list" && "$suid_list" =~ ^--suid= ]] || return 1
   IFS=',' read -r -a arr <<< "${suid_list#--suid=}"
   for n in "${arr[@]}"; do [[ "$n" == "$1" ]] && return 0; done
   return 1
 }
 
-subus=$(./masu__subu_dir_list.sh "$masu")
-[[ -n "$subus" ]] || { echo "No sub-users found for $masu"; exit 1; }
+# List subu names from authoritative source
+subu_root="/home/$masu/subu_data"
+[[ -d "$subu_root" ]] || { echo "No subu_data dir for $masu: $subu_root" >&2; exit 1; }
+mapfile -t subus < <(find "$subu_root" -mindepth 1 -maxdepth 1 -type d -printf '%f\n' | sort -u)
+[[ ${#subus[@]} -gt 0 ]] || { echo "No sub-users found for $masu"; exit 1; }
 
-while IFS= read -r s; do
-  [[ -n "$s" ]] || continue
+for s in "${subus[@]}"; do
   echo "Opening sub-user: $s"
   if want_suid "$s"; then
     sudo ./masu_subu__map_own.sh "$masu" "$s" --suid
   else
     sudo ./masu_subu__map_own.sh "$masu" "$s"
   fi
-done <<< "$subus"
+done
index ccfc890..de4f9a0 100755 (executable)
@@ -1,4 +1,4 @@
-#!/bin/env bash
+#!/usr/bin/env bash
 
 # Function to list sub-users in /home/<user>/subu_data
 subu_home_dir_list() {
index be20e59..383ea57 100755 (executable)
@@ -1,4 +1,4 @@
-#!/bin/env bash
+#!/usr/bin/env bash
 # masu__subu_dir_list.sh
 
 set -euo pipefail
index 5244658..aa2c3a5 100755 (executable)
@@ -1,11 +1,11 @@
-#!/bin/env bash
-# masu_subu__map_own.sh
-
+#!/usr/bin/env bash
 # usage: sudo ./masu_subu__map_own.sh <masu> <subu> [--suid]
 set -euo pipefail
 
 need(){ command -v "$1" >/dev/null 2>&1 || { echo "missing: $1" >&2; exit 1; }; }
 
+masu="${1:?usage: $0 <masu> <subu> [--suid] }"
+subu="${2:?usage: $0 <masu> <subu> [--suid] }"
 want_suid=0
 case "${3-}" in
   --suid) want_suid=1 ;;
@@ -13,14 +13,11 @@ case "${3-}" in
   * ) echo "unknown option: $3" >&2; exit 2 ;;
 esac
 
-masu="${1:?usage: $0 <masu> <subu> [--suid] }"
-subu="${2:?usage: $0 <masu> <subu> [--suid] }"
-
-need bindfs; need findmnt; need mountpoint; id "$masu" >/dev/null
-id "${masu}-${subu}" >/dev/null
+need bindfs; need findmnt; need mountpoint; id "$masu" >/dev/null; id "${masu}-${subu}" >/dev/null
 
 src="/home/$masu/subu_data/$subu"
 tgt="/home/$masu/subu/$subu"
+
 [[ -d "$src" ]] || { echo "Error: source dir '$src' does not exist" >&2; exit 1; }
 mkdir -p "$tgt"
 
@@ -28,36 +25,24 @@ base_opts="allow_other,default_permissions,exec"
 desired_opts="$base_opts,$([[ $want_suid -eq 1 ]] && echo suid || echo nosuid)"
 map_opt="--map=${masu}-${subu}/${masu}:@${masu}-${subu}/@${masu}"
 
-opts_have() { grep -qw "$1"; }
-
-# Peel off incorrect layers until either:
-#  - nothing is mounted on $tgt, or
-#  - the top-most layer is a bindfs of $src with desired opts
+# Peel any existing stack at $tgt (no matter what it is)
 while mountpoint -q "$tgt"; do
-  read -r FSTYPE SOURCE OPTIONS < <(findmnt -T "$tgt" -no FSTYPE,SOURCE,OPTIONS)
-  if [[ "$FSTYPE" != fuse*bindfs* && "$FSTYPE" != fuse.bindfs && "$FSTYPE" != fuse3.bindfs ]]; then
-    echo "⚠︎ '$tgt' is a mountpoint but not bindfs (fstype=$FSTYPE); unmounting this layer…"
-    umount "$tgt" || umount -l "$tgt" || true
-    continue
-  fi
-
-  # Normalize desired
-  want_suid_kw=$([[ $want_suid -eq 1 ]] && echo suid || echo nosuid)
-  # Check source and essential flags without brittle full-string compare
-  if [[ "$SOURCE" == "$src" ]] \
-     && opts_have <<<"$OPTIONS" allow_other \
-     && opts_have <<<"$OPTIONS" exec \
-     && opts_have <<<"$OPTIONS" "$want_suid_kw" \
-     && ! opts_have <<<"$OPTIONS" "$([[ $want_suid -eq 1 ]] && echo nosuid || echo suid)"; then
-    echo "already mounted OK: $tgt ← $src ($OPTIONS)"
-    exit 0
-  fi
-
-  echo "unmounting incorrect layer on $tgt (src=$SOURCE opts=$OPTIONS)…"
-  umount "$tgt" || umount -l "$tgt" || true
+  umount "$tgt" 2>/dev/null || umount -l "$tgt" || break
 done
 
 echo "mounting $src -> $tgt  (opts: $desired_opts)"
 bindfs -o "$desired_opts" $map_opt "$src" "$tgt"
-findmnt "$tgt" -o TARGET,SOURCE,FSTYPE,OPTIONS
+
+# If, for any reason, multiple identical layers ended up stacked, peel until one remains.
+while [ "$(findmnt -nr -T "$tgt" | wc -l)" -gt 1 ]; do
+  umount "$tgt" || umount -l "$tgt" || break
+done
+
+# Show only the bindfs line (or the only remaining one)
+findmnt -nr -T "$tgt" -o TARGET,SOURCE,FSTYPE,OPTIONS | head -n1
 echo "OK"
+if (( want_suid )); then
+  echo "note: suid enabled; setuid binaries can take effect on this mount."
+else
+  echo "note: nosuid (default) — setuid will NOT take effect on this mount."
+fi
index 09b23cb..2a1b1f5 100644 (file)
@@ -1,4 +1,4 @@
-#!/bin/env bash
+#!/usr/bin/env bash
 
 # Function to bind mount with UID/GID mapping
 subu_bind() {
index 4c58373..d3a976e 100755 (executable)
@@ -1,4 +1,4 @@
-#!/bin/env bash
+#!/usr/bin/env bash
 
 # Function to lookup the UID of the user and sub-user combination                                                                          
 get_subu_uid() {
index 45695f5..588958d 100755 (executable)
@@ -1,4 +1,4 @@
-#!/bin/env bash
+#!/usr/bin/env bash
 
 # Function to list available devices under /mnt, excluding /mnt itself
 mount_pt_list() {