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 <noreply@anthropic.com>
This commit is contained in:
CyberMind-FR 2026-01-25 09:59:07 +01:00
parent 5400e34e1f
commit 787fe3864e
3 changed files with 53 additions and 28 deletions

View File

@ -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] || {}
};
});

View File

@ -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"

View File

@ -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