about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorLaurent Bercot <ska-skaware@skarnet.org>2024-05-03 20:43:37 +0000
committerLaurent Bercot <ska@appnovation.com>2024-05-03 20:43:37 +0000
commit6d0c114f57bcd554383a41c9ca791e25e95b81b5 (patch)
tree7ed5e04fa40a18c9e7d1858ae073b9ef602faa3b /src
parent35709f34aaafad99c89d9848b68e3d211b7e0f02 (diff)
downloads6-6d0c114f57bcd554383a41c9ca791e25e95b81b5.tar.gz
s6-6d0c114f57bcd554383a41c9ca791e25e95b81b5.tar.xz
s6-6d0c114f57bcd554383a41c9ca791e25e95b81b5.zip
Restore cleanups in s6-ftrigrd; fix an old bug and a new bug
ftrigw_clean() didn't clean properly.
ftrig1_make() didn't give enough perms to the fifo, notification
could fail in certain cases.

Signed-off-by: Laurent Bercot <ska@appnovation.com>
Diffstat (limited to 'src')
-rw-r--r--src/libs6/ftrig1_make.c2
-rw-r--r--src/libs6/ftrigw_clean.c8
-rw-r--r--src/libs6/s6-ftrigrd.c49
3 files changed, 46 insertions, 13 deletions
diff --git a/src/libs6/ftrig1_make.c b/src/libs6/ftrig1_make.c
index 04c8c73..5c38e4b 100644
--- a/src/libs6/ftrig1_make.c
+++ b/src/libs6/ftrig1_make.c
@@ -23,7 +23,7 @@ int ftrig1_make (ftrig1_t *f, char const *path)
   tmp[pathlen + 2 + FTRIG1_PREFIXLEN] = ':' ;
   if (!timestamp(tmp + pathlen + 3 + FTRIG1_PREFIXLEN)) return 0 ;
   memcpy(tmp + pathlen + FTRIG1_PREFIXLEN + 28, ":XXXXXX", 8) ;
-  ff.fd = mkptemp2(tmp, O_NONBLOCK|O_CLOEXEC) ;
+  ff.fd = mkptemp3(tmp, 0622, O_NONBLOCK|O_CLOEXEC) ;
   if (ff.fd == -1) return 0 ;
   ff.fdw = open_write(tmp) ;
   if (ff.fdw == -1) goto err1 ;
diff --git a/src/libs6/ftrigw_clean.c b/src/libs6/ftrigw_clean.c
index 3ad9e3a..e540aba 100644
--- a/src/libs6/ftrigw_clean.c
+++ b/src/libs6/ftrigw_clean.c
@@ -15,9 +15,9 @@ int ftrigw_clean (char const *path)
   DIR *dir = opendir(path) ;
   if (!dir) return 0 ;
   {
-    char tmp[pathlen + FTRIG1_PREFIXLEN + 45] ;
+    char tmp[pathlen + FTRIG1_PREFIXLEN + 35] ;
     memcpy(tmp, path, pathlen) ;
-    tmp[pathlen] = '/' ; tmp[pathlen + FTRIG1_PREFIXLEN + 44] = 0 ;
+    tmp[pathlen] = '/' ; tmp[pathlen + FTRIG1_PREFIXLEN + 34] = 0 ;
     for (;;)
     {
       direntry *d ;
@@ -26,8 +26,8 @@ int ftrigw_clean (char const *path)
       d = readdir(dir) ;
       if (!d) break ;
       if (strncmp(d->d_name, FTRIG1_PREFIX, FTRIG1_PREFIXLEN)) continue ;
-      if (strlen(d->d_name) != FTRIG1_PREFIXLEN + 43) continue ;
-      memcpy(tmp + pathlen + 1, d->d_name, FTRIG1_PREFIXLEN + 43) ;
+      if (strlen(d->d_name) != FTRIG1_PREFIXLEN + 33) continue ;
+      memcpy(tmp + pathlen + 1, d->d_name, FTRIG1_PREFIXLEN + 33) ;
       fd = open_write(tmp) ;
       if (fd >= 0) fd_close(fd) ;
       else if ((errno == ENXIO) && (unlink(tmp) < 0)) e = errno ;
diff --git a/src/libs6/s6-ftrigrd.c b/src/libs6/s6-ftrigrd.c
index 202ea31..b6ca40b 100644
--- a/src/libs6/s6-ftrigrd.c
+++ b/src/libs6/s6-ftrigrd.c
@@ -48,26 +48,40 @@ struct ftrigio_s
 
 static genalloc g = GENALLOC_ZERO ; /* ftrigio */
 
+static void ftrigio_deepfree (ftrigio *p)
+{
+  ftrig1_free(&p->trig) ;
+  stralloc_free(&p->sa) ;
+  regfree(&p->re) ;
+}
+
+static void cleanup (void)
+{
+  size_t n = genalloc_len(ftrigio, &g) ;
+  ftrigio *a = genalloc_s(ftrigio, &g) ;
+  for (size_t i = 0 ; i < n ; i++) ftrigio_deepfree(a + i) ;
+  genalloc_setlen(ftrigio, &g, 0) ;
+}
+
 static void trig (uint16_t id, char what, char info)
 {
   char pack[4] ;
   uint16_pack_big(pack, id) ;
   pack[2] = what ; pack[3] = info ;
   if (!textmessage_put(textmessage_sender_x, pack, 4))
+  {
+    cleanup() ;
     strerr_diefu1sys(111, "build answer") ;
+  }
 }
 
 static void answer (unsigned char c)
 {
   if (!textmessage_put(textmessage_sender_1, (char *)&c, 1))
+  {
+    cleanup() ;
     strerr_diefu1sys(111, "textmessage_put") ;
-}
-
-static void ftrigio_deepfree (ftrigio *p)
-{
-  ftrig1_free(&p->trig) ;
-  stralloc_free(&p->sa) ;
-  regfree(&p->re) ;
+  }
 }
 
 static void remove (size_t i)
@@ -91,7 +105,11 @@ static inline int ftrigio_read (ftrigio *p)
     if (!r) break ;
     if (r < 0) return (trig(p->id, 'd', errno), 0) ;
     blen = buffer_len(&p->b) ;
-    if (!stralloc_readyplus(&p->sa, blen+1)) dienomem() ;
+    if (!stralloc_readyplus(&p->sa, blen+1))
+    {
+      cleanup() ;
+      dienomem() ;
+    }
     buffer_getnofill(&p->b, p->sa.s + p->sa.len, blen) ;
     p->sa.len += blen ;
     p->sa.s[p->sa.len] = 0 ;
@@ -111,7 +129,10 @@ static int parse_protocol (struct iovec const *v, void *context)
   char const *s = v->iov_base ;
   uint16_t id ;
   if (v->iov_len < 3)
+  {
+    cleanup() ;
     strerr_dief1x(100, "invalid client request") ;
+  }
   uint16_unpack_big(s, &id) ;
   switch (s[2])
   {
@@ -174,6 +195,7 @@ static int parse_protocol (struct iovec const *v, void *context)
       break ;
     }
     default :
+      cleanup() ;
       strerr_dief1x(100, "invalid client request") ;
   }
   (void)context ;
@@ -216,7 +238,10 @@ int main (void)
     }
 
     if (iopause(x, 3 + n, 0, 0) < 0)
+    {
+      cleanup() ;
       strerr_diefu1sys(111, "iopause") ;
+    }
 
    /* client closed */
     if ((x[0].revents | x[1].revents) & IOPAUSE_EXCEPT) break ;
@@ -224,10 +249,16 @@ int main (void)
    /* client is reading */
     if (x[1].revents & IOPAUSE_WRITE)
       if (!textmessage_sender_flush(textmessage_sender_1) && !error_isagain(errno))
+      {
+        cleanup() ;
         strerr_diefu1sys(111, "flush stdout") ;
+      }
     if (x[2].revents & IOPAUSE_WRITE)
       if (!textmessage_sender_flush(textmessage_sender_x) && !error_isagain(errno))
+      {
+        cleanup() ;
         return 1 ;
+      }
 
    /* scan listening ftrigs */
     for (i = 0 ; i < genalloc_len(ftrigio, &g) ; i++)
@@ -243,9 +274,11 @@ int main (void)
       if (textmessage_handle(textmessage_receiver_0, &parse_protocol, 0) < 0)
       {
         if (errno == EPIPE) break ; /* normal exit */
+        cleanup() ;
         strerr_diefu1sys(111, "handle messages from client") ;
       }
     }
   }
+  cleanup() ;
   return 0 ;
 }