Package: squidguard
Version: 1.5-4
Severity: normal
Tags: upstream

Dear Maintainer,

squidGuard seems to support the SIGHUP signal to reload its
configuration, as is common for daemons. Though this doesn't seem to be
documented as far as I can tell, from the code it's obvious that it
should be supported - main.c at several points checks for sig_hup and calls
sgReloadConfig, for example:

  if(sig_hup) {
    sgReloadConfig();
  }

sgReloadConfig is defined like this:

  void sgReloadConfig()
  {
    struct LogFileStat *sg;
    struct Source *src;
    struct Destination *dest;
    sig_hup = 0;
    sgLogWarn("WARN: Received sigHUP, reloaded configuration");
    for(sg = LogFileStat; sg != NULL; sg = sg->next){ /* closing logfiles */
      if(sg->fd == stderr || sg->fd == stdout) {
        continue;
      }
      fclose(sg->fd);
    }
    for(src = Source; src != NULL; src = src->next){
      if(src->domainDb != NULL && src->domainDb->dbp != NULL) {
        (void)src->domainDb->dbp->close(src->domainDb->dbp,0);
      }
      if(src->userDb != NULL && src->userDb->dbp != NULL) {
        (void)src->userDb->dbp->close(src->userDb->dbp,0);
      }
    }
    for(dest = Dest; dest != NULL; dest = dest->next){
      if(dest->domainlistDb != NULL && dest->domainlistDb->dbp != NULL) {
        (void)dest->domainlistDb->dbp->close(dest->domainlistDb->dbp,0);
      }
      if(dest->urllistDb != NULL && dest->urllistDb->dbp != NULL) {
        (void)dest->urllistDb->dbp->close(dest->urllistDb->dbp,0);
      }
    }
    sgFreeAllLists();
    execve(*globalArgv,globalArgv, globalEnvp);
    fprintf(stderr,"error execve: %d\n",errno);
    exit(1);
  }

Unfortunately, this doesn't work as expected when squidGuard is used as
url_rewrite_program in squid - sending SIGHUP to squidGuard will crash
it instead of reloading it. To reproduce:

1. strace squidGuard (works best when only a single instance is
   running):

    strace -p $(pidof '(squidGuard)')

2. Send SIGHUP:

    pkill -SIGHUP squidGuard

3. Observe in strace that squidGuard has received the SIGHUP, but
   nothing bad has happened yet:

    host ~ # strace -p $(pidof '(squidGuard)')
    Process 5598 attached
    read(0, 0xf7779000, 4096)               = ? ERESTARTSYS (To be restarted if 
SA_RESTART is set)
    --- SIGHUP {si_signo=SIGHUP, si_code=SI_USER, si_pid=8385, si_uid=0} ---
    sigreturn() (mask [])                   = 3
    read(0,

4. Send a request to squid:

    http_proxy=http://localhost:3128 GET google.de > /dev/null

5. Observe in strace that squidGuard crashes:

    host ~ # strace -p $(pidof '(squidGuard)')
    Process 8452 attached
    read(0, 0xf7737000, 4096)               = ? ERESTARTSYS (To be restarted if 
SA_RESTART is set)
    --- SIGHUP {si_signo=SIGHUP, si_code=SI_USER, si_pid=8503, si_uid=0} ---
    sigreturn() (mask [])                   = 3
    read(0, "http://google.de/ 127.0.0.1/loca"..., 4096) = 71
    time(NULL)                              = 1527782365
    stat64("/etc/localtime", {st_mode=S_IFREG|0644, st_size=2309, ...}) = 0
    write(5, "2018-05-31 17:59:25 [8452] WARN:"..., 73) = 73
    close(4)                                = 0
    munmap(0xf7745000, 4096)                = 0
    close(6)                                = 0
    munmap(0xf7743000, 4096)                = 0
    close(11)                               = 0
    munmap(0xf7742000, 4096)                = 0
    close(14)                               = 0
    munmap(0xf7741000, 4096)                = 0
    close(17)                               = 0
    munmap(0xf7740000, 4096)                = 0
    close(20)                               = 0
    munmap(0xf773f000, 4096)                = 0
    close(23)                               = 0
    munmap(0xf773e000, 4096)                = 0
    close(26)                               = 0
    munmap(0xf773d000, 4096)                = 0
    close(29)                               = 0
    munmap(0xf773c000, 4096)                = 0
    close(32)                               = 0
    munmap(0xf773b000, 4096)                = 0
    close(35)                               = 0
    munmap(0xf773a000, 4096)                = 0
    close(38)                               = 0
    munmap(0xf7739000, 4096)                = 0
    close(41)                               = 0
    munmap(0xf7738000, 4096)                = 0
    close(5)                                = 0
    munmap(0xf7744000, 4096)                = 0
    close(7)                                = 0
    close(8)                                = 0
    close(9)                                = 0
    close(10)                               = 0
    close(12)                               = 0
    close(13)                               = 0
    close(15)                               = 0
    close(16)                               = 0
    close(18)                               = 0
    close(19)                               = 0
    close(21)                               = 0
    close(22)                               = 0
    close(24)                               = 0
    close(25)                               = 0
    close(27)                               = 0
    close(28)                               = 0
    close(30)                               = 0
    close(31)                               = 0
    close(33)                               = 0
    close(34)                               = 0
    close(36)                               = 0
    close(37)                               = 0
    close(39)                               = 0
    close(40)                               = 0
    close(42)                               = 0
    close(43)                               = 0
    execve("(squidGuard)", ["(squidGuard)"], [/* 7 vars */]) = -1 ENOENT (No 
such file or directory)
    write(2, "error execve: 2\n", 16)       = 16
    close(3)                                = 0
    exit_group(1)                           = ?
    +++ exited with 1 +++

I believe the cause for this issue is squidGuard tries to restart itself
with its original argv:

  execve(*globalArgv,globalArgv, globalEnvp);

But this doesn't work because squid likes to rename its child processes,
as you can easily see in htop:

5495 root       21   1 15460  4748  3368 S  0.0  0.1  0:00.00 ├─ 
/usr/sbin/squid3 -YC -f /etc/squid3/squid.conf
5497 proxy      21   1 49388 21872  7800 S  0.0  0.6  0:00.22 │  └─ (squid-1) 
-YC -f /etc/squid3/squid.conf
5598 proxy      21   1  8148  5004  4208 S  0.0  0.1  0:00.01 │     ├─ 
(squidGuard)
5502 proxy      21   1  4028  2544  2316 S  0.0  0.1  0:00.05 │     ├─ (pinger)
5501 proxy      21   1  3756  1236  1048 S  0.0  0.0  0:00.01 │     └─ (unlinkd)

So now squidGuard tries to execve '(squidGuard)', and that obviously
doesn't work. I'm not sure though whether this is a bug in squidGuard
(should it rely on its argv?) or in squid (should it put arbitrary
strings in argv of its helpers?).

The unfortunate result is that it is currently very easy to crash squid
by sending too many SIGHUPs to squidGuard:

for i in $(seq 1 10); do pkill -SIGHUP squidGuard; done

Will print the following errors to /var/log/squid3/cache.log:

2018/05/31 17:37:18 kid1| WARNING: redirector #Hlpr0 exited
2018/05/31 17:37:18 kid1| Too few redirector processes are running (need 1/10)
2018/05/31 17:37:18 kid1| Starting new helpers
2018/05/31 17:37:18 kid1| helperOpenServers: Starting 1/10 'squidGuard' 
processes
2018/05/31 17:37:18 kid1| ERROR: URL rewrite helper returned invalid result 
code. Wrong helper? {result=Unknown}
2018/05/31 17:40:12| Current Directory is /
2018/05/31 17:50:12| Current Directory is /
error execve: 2
2018/05/31 17:58:46 kid1| WARNING: redirector #Hlpr0 exited
2018/05/31 17:58:46 kid1| Too few redirector processes are running (need 1/10)
2018/05/31 17:58:46 kid1| Starting new helpers
2018/05/31 17:58:46 kid1| helperOpenServers: Starting 1/10 'squidGuard' 
processes
2018/05/31 17:58:46 kid1| ERROR: URL rewrite helper returned invalid result 
code. Wrong helper? {result=Unknown}
error execve: 2
2018/05/31 17:59:25 kid1| WARNING: redirector #Hlpr0 exited
2018/05/31 17:59:25 kid1| Too few redirector processes are running (need 1/10)
2018/05/31 17:59:25 kid1| Starting new helpers
2018/05/31 17:59:25 kid1| helperOpenServers: Starting 1/10 'squidGuard' 
processes
2018/05/31 17:59:25 kid1| ERROR: URL rewrite helper returned invalid result 
code. Wrong helper? {result=Unknown}
2018/05/31 18:00:12| Current Directory is /
2018/05/31 18:08:01 kid1| WARNING: redirector #Hlpr0 exited
2018/05/31 18:08:01 kid1| Too few redirector processes are running (need 1/10)
2018/05/31 18:08:01 kid1| Starting new helpers
2018/05/31 18:08:01 kid1| helperOpenServers: Starting 1/10 'squidGuard' 
processes
2018/05/31 18:08:01 kid1| WARNING: redirector #Hlpr0 exited
2018/05/31 18:08:01 kid1| Too few redirector processes are running (need 1/10)
2018/05/31 18:08:01 kid1| Closing HTTP port 10.2.0.1:3129
2018/05/31 18:08:01 kid1| Closing HTTP port 192.168.178.1:3129
2018/05/31 18:08:01 kid1| Closing HTTP port 192.168.5.7:3129
2018/05/31 18:08:01 kid1| Closing HTTP port 192.168.9.8:3129
2018/05/31 18:08:01 kid1| Closing HTTP port 10.2.0.1:3128
2018/05/31 18:08:01 kid1| Closing HTTP port 192.168.178.1:3128
2018/05/31 18:08:01 kid1| Closing HTTP port 192.168.5.7:3128
2018/05/31 18:08:01 kid1| Closing HTTP port 192.168.9.8:3128
2018/05/31 18:08:01 kid1| Closing HTTP port 127.0.0.1:3128
2018/05/31 18:08:01 kid1| storeDirWriteCleanLogs: Starting...
2018/05/31 18:08:01 kid1|   Finished.  Wrote 13725 entries.
2018/05/31 18:08:01 kid1|   Took 0.00 seconds (8078281.34 entries/sec).
FATAL: The redirector helpers are crashing too rapidly, need help!

Squid Cache (Version 3.4.8): Terminated abnormally.
CPU Usage: 0.460 seconds = 0.176 user + 0.284 sys
Maximum Resident Size: 87664 KB
Page faults with physical i/o: 2
Memory usage for squid via mallinfo():
        total space in arena:    6940 KB
        Ordinary blocks:         6679 KB     26 blks
        Small blocks:               0 KB      0 blks
        Holding blocks:         27800 KB      9 blks
        Free Small blocks:          0 KB
        Free Ordinary blocks:     260 KB
        Total in use:           34479 KB 497%
        Total free:               260 KB 4%
2018/05/31 18:08:01 kid1| Closing Pinger socket on FD 28

I was able to reproduce this issue both on Debian jessie and on Debian
stretch.

-- System Information:
Debian Release: 8.10
  APT prefers oldstable-updates
  APT policy: (500, 'oldstable-updates'), (500, 'oldstable')
Architecture: i386 (x86_64)
Foreign Architectures: amd64

Kernel: Linux 3.16.0-5-amd64 (SMP w/4 CPU cores)
Locale: LANG=de_DE.UTF-8, LC_CTYPE=de_DE.UTF-8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/dash
Init: systemd (via /run/systemd/system)

Versions of packages squidguard depends on:
ii  debconf [debconf-2.0]  1.5.56+deb8u1
ii  libc6                  2.19-18+deb8u10
ii  libdb5.3               5.3.28-9+deb8u1
ii  libldap-2.4-2          2.4.40+dfsg-1+deb8u3

Versions of packages squidguard recommends:
ii  liburi-perl  1.64-1
ii  libwww-perl  6.08-1
ii  squid3       3.4.8-6+deb8u5

Versions of packages squidguard suggests:
ii  ldap-utils      2.4.40+dfsg-1+deb8u3
pn  squidguard-doc  <none>

-- Configuration Files:
/etc/logrotate.d/squidguard changed [not included]

-- debconf information:
* squidguard/db:
* squidguard/dbreload: true

Reply via email to