Shared Clipboard fixed

Hi, I wrote a script that solves the problem (no changes to the code, no need to compile binaries, etc.). My script start custom service in the system root, and your clipboard will work (user mode also):

I’m posting this because I want others who have encountered the same problem to get a quick, effective solution without having to run third-party code on the host machine.

I ask everyone, including @arraybolt3 @Patrick to take note of my solution (from an OS security perspective)

!!!

  1. Update your VirtualBox

  2. login to system like sysmaint

  3. run script

  4. set bidirectional

  5. reboot system

(I understand how this looks from the outside, so I suggest and ask everyone to familiarize themselves with this script (don’t trust people on the internet, especially on a forum about an anonymous OS; there’s nothing criminal here, just automation so you don’t have to type things manually)

After you run it, don’t forget to set it to Bidirectional, and the buffer will work the same way as a root/user

Let me know if you run into any issues :upside_down_face:

download file:
https[:]//filebin[.]net/562pahe0lulimhj7/setup.sh

or copy it:

#!/bin/bash
set -o nounset
set -o pipefail

UNIT_NAME='vbox-wayland-clipboard.service'
UNIT_PATH='/usr/lib/systemd/user/vbox-wayland-clipboard.service'
LAUNCH_PATH='/usr/libexec/vm-config-dist/vbox-wayland-clipboard-autostart'
DESK_PATH='/etc/xdg/autostart/vbox-wayland-clipboard.desktop'

red() { printf '\033[31m%s\033[0m\n' "$*"; }
grn() { printf '\033[32m%s\033[0m\n' "$*"; }
ylw() { printf '\033[33m%s\033[0m\n' "$*"; }

if [ "$(id -u)" -ne 0 ]; then
   red "ERROR: run as root in the 'sysmaint' boot mode:  sudo bash $0"
   exit 1
fi

search_dirs=(/etc/systemd/user /run/systemd/user /usr/lib/systemd/user \
             /usr/local/lib/systemd/user /root/.config/systemd/user)
for h in /home/*; do
   [ -d "$h/.config/systemd/user" ] && search_dirs+=("$h/.config/systemd/user")
done

echo "=== INSTALL ==="

echo "[1/6] clearing masks (/dev/null symlinks) and empty unit files ..."
for d in "${search_dirs[@]}"; do
   f="$d/$UNIT_NAME"
   if [ -L "$f" ] || { [ -e "$f" ] && [ ! -s "$f" ]; }; then
      echo "  removing $f"
      rm -f "$f"
   fi
done
systemctl --global unmask "$UNIT_NAME" 2>/dev/null || true

echo "[2/6] writing $UNIT_PATH ..."
install -d /usr/lib/systemd/user
cat > "$UNIT_PATH" <<'UNIT'
[Unit]
Description=VirtualBox shared clipboard for Wayland (opt-in, default-off)
ConditionVirtualization=oracle
ConditionEnvironment=WAYLAND_DISPLAY
StartLimitIntervalSec=10
StartLimitBurst=3

[Service]
Type=simple
ExecStart=/usr/bin/VBoxClient --foreground --wayland
Restart=on-failure
RestartSec=2s

[Install]
WantedBy=default.target
UNIT

echo "[3/6] writing $LAUNCH_PATH ..."
install -d /usr/libexec/vm-config-dist
cat > "$LAUNCH_PATH" <<'LAUNCH'
#!/bin/bash
set -o nounset
set -o pipefail
PATH=/usr/bin:/bin
unit='vbox-wayland-clipboard.service'
state="$(systemctl --user is-enabled "$unit" 2>/dev/null || true)"
case "$state" in
   enabled|enabled-runtime) ;;
   *) exit 0 ;;
esac
counter=0
while [ "$counter" -lt 50 ]; do
   systemctl --user show-environment 2>/dev/null | grep -q '^WAYLAND_DISPLAY=' && break
   counter="$(( counter + 1 ))"
   sleep 0.2
done
systemctl --user reset-failed "$unit" 2>/dev/null || true
exec systemctl --user start "$unit"
LAUNCH
chmod 755 "$LAUNCH_PATH"

echo "[4/6] writing $DESK_PATH ..."
cat > "$DESK_PATH" <<'DESK'
[Desktop Entry]
Type=Application
Name=VirtualBox shared clipboard for Wayland (opt-in)
Exec=/usr/libexec/vm-config-dist/vbox-wayland-clipboard-autostart
StartupNotify=false
NoDisplay=true
NotShowIn=QUBES;
DESK

echo "[5/6] Guest Additions device (/dev/vboxuser) on every boot ..."
systemctl enable --now virtualbox-guest-utils.service 2>/dev/null \
   || ylw "  virtualbox-guest-utils.service not found; loading module only."
echo vboxguest > /etc/modules-load.d/vboxguest.conf
modprobe vboxguest 2>/dev/null || true

echo "[6/6] enabling for ALL users ..."
systemctl daemon-reload
systemctl --global enable "$UNIT_NAME"

echo
echo "=== CHECKUP ==="
fail=0; warn=0

chk_file() {
   local p="$1" min="$2" sz
   if [ -L "$p" ]; then red "  FAIL  $p is a symlink (masked?)"; fail=$((fail+1)); return; fi
   if [ ! -f "$p" ]; then red "  FAIL  $p missing"; fail=$((fail+1)); return; fi
   sz="$(wc -c < "$p")"
   if [ "$sz" -lt "$min" ]; then red "  FAIL  $p is $sz bytes (empty/too small)"; fail=$((fail+1)); return; fi
   grn "  OK    $p ($sz bytes)"
}
chk_file "$UNIT_PATH"   100
chk_file "$LAUNCH_PATH" 100
chk_file "$DESK_PATH"    50

leftover=0
for d in "${search_dirs[@]}"; do
   f="$d/$UNIT_NAME"
   [ "$f" = "$UNIT_PATH" ] && continue
   if [ -L "$f" ] || { [ -e "$f" ] && [ ! -s "$f" ]; }; then
      red "  FAIL  leftover mask/empty: $f"; leftover=$((leftover+1)); fail=$((fail+1))
   fi
done
[ "$leftover" -eq 0 ] && grn "  OK    no leftover masks / empty unit files"

if [ -x "$LAUNCH_PATH" ]; then grn "  OK    launcher is executable"; else red "  FAIL  launcher not executable"; fail=$((fail+1)); fi

if [ -L "/etc/systemd/user/default.target.wants/$UNIT_NAME" ]; then
   grn "  OK    enabled for all users (default.target.wants symlink present)"
else
   ylw "  WARN  global enable symlink missing"; warn=$((warn+1))
fi

if command -v VBoxClient >/dev/null 2>&1; then
   grn "  OK    VBoxClient present ($(VBoxClient --version 2>/dev/null | head -n1))"
else
   red "  FAIL  /usr/bin/VBoxClient not found (Guest Additions missing)"; fail=$((fail+1))
fi

if lsmod 2>/dev/null | grep -q '^vboxguest'; then grn "  OK    vboxguest module loaded"; else ylw "  WARN  vboxguest module not loaded"; warn=$((warn+1)); fi
if [ -e /dev/vboxuser ]; then grn "  OK    /dev/vboxuser present"; else red "  FAIL  /dev/vboxuser missing (VBoxClient will fail VbglR3InitUser)"; fail=$((fail+1)); fi

echo
if [ "$fail" -eq 0 ]; then grn "RESULT: install OK ($warn warning(s))."; else red "RESULT: $fail problem(s), $warn warning(s) — fix the FAIL lines above."; fi
echo
echo "NEXT:"
echo "  1) On the HOST (normal user, VM powered off):"
echo "       VBoxManage modifyvm \"<vm-name-or-uuid>\" --clipboard-mode bidirectional"
echo "     and launch the VM as your NORMAL user, not root."
echo "  2) Reboot Whonix into the normal 'user' mode."
echo "  3) As 'user' (no sudo) verify:"
echo "       systemctl --user is-enabled $UNIT_NAME    # => enabled  (NOT masked)"
echo "       systemctl --user status    $UNIT_NAME     # => active (running)"

[ "$fail" -eq 0 ] && exit 0 || exit 1