From 787fe3864ef6a9ac5145af3c1ee998a7492fc062 Mon Sep 17 00:00:00 2001 From: CyberMind-FR Date: Sun, 25 Jan 2026 09:59:07 +0100 Subject: [PATCH] fix(tor-shield): Fix json_init bug and permission issues RPCD backend: - Fix critical json_init bug: variables must be extracted BEFORE json_init() which wipes the loaded JSON. Affected functions: save_settings, do_enable, set_bridges, add/remove_hidden_service - Fix process detection: use pgrep instead of pid file - Fix uptime calculation: get PID from pgrep, not pid file - Fix RPC expect unwrapping in getDashboardData for presets Init script: - Remove PidFile directive (procd manages the process) - Clean up stale files before starting to avoid permission issues - Set proper ownership on torrc after generation - Fix iptables chain creation to handle "already exists" gracefully - Remove from OUTPUT chain before attempting chain deletion Co-Authored-By: Claude Opus 4.5 --- .../luci-static/resources/tor-shield/api.js | 6 +- .../root/usr/libexec/rpcd/luci.tor-shield | 56 +++++++++++-------- .../files/etc/init.d/tor-shield | 19 +++++-- 3 files changed, 53 insertions(+), 28 deletions(-) diff --git a/package/secubox/luci-app-tor-shield/htdocs/luci-static/resources/tor-shield/api.js b/package/secubox/luci-app-tor-shield/htdocs/luci-static/resources/tor-shield/api.js index db0c26e5..2f4b6a1d 100644 --- a/package/secubox/luci-app-tor-shield/htdocs/luci-static/resources/tor-shield/api.js +++ b/package/secubox/luci-app-tor-shield/htdocs/luci-static/resources/tor-shield/api.js @@ -188,9 +188,13 @@ return baseclass.extend({ callPresets(), callBandwidth() ]).then(function(results) { + // Handle RPC expect unwrapping - results may be array or object + var presetsData = results[1] || []; + var presets = Array.isArray(presetsData) ? presetsData : (presetsData.presets || []); + return { status: results[0] || {}, - presets: (results[1] || {}).presets || [], + presets: presets, bandwidth: results[2] || {} }; }); diff --git a/package/secubox/luci-app-tor-shield/root/usr/libexec/rpcd/luci.tor-shield b/package/secubox/luci-app-tor-shield/root/usr/libexec/rpcd/luci.tor-shield index 3a14c369..2c49bbd3 100644 --- a/package/secubox/luci-app-tor-shield/root/usr/libexec/rpcd/luci.tor-shield +++ b/package/secubox/luci-app-tor-shield/root/usr/libexec/rpcd/luci.tor-shield @@ -32,15 +32,10 @@ tor_control() { } | socat - UNIX-CONNECT:"$TOR_CONTROL" 2>/dev/null } -# Check if Tor is running (via tor-shield, not just any tor process) +# Check if Tor is running is_running() { - # Check for tor-shield's pid file first - if [ -f "$TOR_RUN/tor.pid" ]; then - local pid=$(cat "$TOR_RUN/tor.pid" 2>/dev/null) - [ -n "$pid" ] && [ -d "/proc/$pid" ] && return 0 - fi - # Fallback to checking any tor process - pgrep tor >/dev/null 2>&1 + # Check for tor process (procd manages the process, no pid file) + pgrep -f "/usr/sbin/tor" >/dev/null 2>&1 } # Check if tor-shield control socket is available @@ -113,15 +108,12 @@ get_status() { fi fi - # Uptime from pid file - local pidfile="$TOR_RUN/tor.pid" - if [ -f "$pidfile" ]; then - local pid=$(cat "$pidfile") - if [ -d "/proc/$pid" ]; then - local start_time=$(stat -c %Y "/proc/$pid" 2>/dev/null) - local now=$(date +%s) - json_add_int "uptime" "$((now - start_time))" - fi + # Uptime from process start time + local pid=$(pgrep -f "/usr/sbin/tor" | head -1) + if [ -n "$pid" ] && [ -d "/proc/$pid" ]; then + local start_time=$(stat -c %Y "/proc/$pid" 2>/dev/null) + local now=$(date +%s) + json_add_int "uptime" "$((now - start_time))" fi else json_add_boolean "running" 0 @@ -149,12 +141,15 @@ get_status() { do_enable() { read input json_load "$input" + + # Get values from input BEFORE json_init + local preset json_get_var preset preset - - json_init - [ -z "$preset" ] && preset="anonymous" + # Now initialize output JSON + json_init + # Load preset configuration config_load "$CONFIG" @@ -383,10 +378,14 @@ add_hidden_service_json() { add_hidden_service() { read input json_load "$input" + + # Get values from input BEFORE json_init + local name local_port virtual_port json_get_var name name json_get_var local_port local_port json_get_var virtual_port virtual_port + # Now initialize output JSON json_init if [ -z "$name" ]; then @@ -420,8 +419,12 @@ add_hidden_service() { remove_hidden_service() { read input json_load "$input" + + # Get values from input BEFORE json_init + local name json_get_var name name + # Now initialize output JSON json_init if [ -z "$name" ]; then @@ -587,9 +590,13 @@ add_bridge_json() { set_bridges() { read input json_load "$input" + + # Get values from input BEFORE json_init + local enabled type json_get_var enabled enabled json_get_var type type + # Now initialize output JSON json_init [ -n "$enabled" ] && uci set tor-shield.bridges.enabled="$enabled" @@ -664,9 +671,9 @@ save_settings() { read input json_load "$input" - json_init - - # Get values from input + # Get values from input BEFORE json_init (which wipes loaded JSON) + local mode dns_over_tor kill_switch socks_port trans_port dns_port + local exit_nodes exclude_exit strict_nodes json_get_var mode mode json_get_var dns_over_tor dns_over_tor json_get_var kill_switch kill_switch @@ -677,6 +684,9 @@ save_settings() { json_get_var exclude_exit exclude_exit_nodes json_get_var strict_nodes strict_nodes + # Now initialize output JSON + json_init + # Apply settings [ -n "$mode" ] && uci set tor-shield.main.mode="$mode" [ -n "$dns_over_tor" ] && uci set tor-shield.main.dns_over_tor="$dns_over_tor" diff --git a/package/secubox/secubox-app-tor/files/etc/init.d/tor-shield b/package/secubox/secubox-app-tor/files/etc/init.d/tor-shield index 7fc04611..a7e112b0 100644 --- a/package/secubox/secubox-app-tor/files/etc/init.d/tor-shield +++ b/package/secubox/secubox-app-tor/files/etc/init.d/tor-shield @@ -37,6 +37,11 @@ generate_torrc() { config_get strict_nodes security strict_nodes '0' mkdir -p "$TOR_RUN" "$TOR_DATA" + + # Clean up stale files that may have wrong ownership + rm -f "$TOR_RUN/tor.pid" "$TOR_RUN/control" "$TOR_RUN/control_auth_cookie" 2>/dev/null + rm -f "$TOR_DATA/lock" 2>/dev/null + chown tor:tor "$TOR_RUN" "$TOR_DATA" chmod 700 "$TOR_RUN" "$TOR_DATA" @@ -46,7 +51,6 @@ generate_torrc() { User tor DataDirectory $TOR_DATA -PidFile $TOR_RUN/tor.pid Log notice syslog ControlSocket $TOR_RUN/control ControlSocketsGroupWritable 1 @@ -123,6 +127,9 @@ EOF if [ -f /usr/share/tor/geoip6 ]; then echo "GeoIPv6File /usr/share/tor/geoip6" >> "$TORRC" fi + + # Ensure torrc is readable by tor user + chown tor:tor "$TORRC" } add_bridge_line() { @@ -166,6 +173,10 @@ setup_iptables() { # Get Tor user ID local tor_uid=$(id -u tor 2>/dev/null || echo "tor") + # Remove from OUTPUT chain first (to allow chain deletion) + iptables -t nat -D OUTPUT -j TOR_SHIELD 2>/dev/null + iptables -t filter -D OUTPUT -j TOR_SHIELD 2>/dev/null + # Clear existing Tor rules iptables -t nat -F TOR_SHIELD 2>/dev/null iptables -t nat -X TOR_SHIELD 2>/dev/null @@ -174,9 +185,9 @@ setup_iptables() { [ "$mode" = "transparent" ] || return 0 - # Create chains - iptables -t nat -N TOR_SHIELD - iptables -t filter -N TOR_SHIELD + # Create chains (ignore "already exists" errors) + iptables -t nat -N TOR_SHIELD 2>/dev/null || true + iptables -t filter -N TOR_SHIELD 2>/dev/null || true # Exclude Tor traffic iptables -t nat -A TOR_SHIELD -m owner --uid-owner $tor_uid -j RETURN