summaryrefslogtreecommitdiff
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
parent35709f34aaafad99c89d9848b68e3d211b7e0f02 (diff)
downloads6-6d0c114f57bcd554383a41c9ca791e25e95b81b5.tar.xz
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>
-rw-r--r--doc/fifodir.html2
-rw-r--r--src/libs6/ftrig1_make.c2
-rw-r--r--src/libs6/ftrigw_clean.c8
-rw-r--r--src/libs6/s6-ftrigrd.c49
4 files changed, 47 insertions, 14 deletions
diff --git a/doc/fifodir.html b/doc/fifodir.html
index 0a1f344..b37a268 100644
--- a/doc/fifodir.html
+++ b/doc/fifodir.html
@@ -115,7 +115,7 @@ subscribe).
</p>
<p>
- A publicly accessible fifodir must have rights 1733:
+ A publicly accessible fifodir must have rights 1733:
</p>
<ul>
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 ;
}