summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLaurent Bercot <ska-skaware@skarnet.org>2015-07-20 05:33:26 +0000
committerLaurent Bercot <ska-skaware@skarnet.org>2015-07-20 05:33:26 +0000
commitfd38bd8ad5ddaf5f81887b878dddd212a77113b0 (patch)
treee946c63605e478333aa031b2346f50a3111f319d
parent76861bf832577df0883dee12a502a8e3d5ae6a11 (diff)
downloads6-rc-fd38bd8ad5ddaf5f81887b878dddd212a77113b0.tar.xz
Always use names linked in scandir
-rw-r--r--src/s6-rc/s6-rc-init.c2
-rw-r--r--src/s6-rc/s6-rc-update.c95
-rw-r--r--src/s6-rc/s6-rc.c16
3 files changed, 104 insertions, 9 deletions
diff --git a/src/s6-rc/s6-rc-init.c b/src/s6-rc/s6-rc-init.c
index b22d399..e34ed18 100644
--- a/src/s6-rc/s6-rc-init.c
+++ b/src/s6-rc/s6-rc-init.c
@@ -220,7 +220,7 @@ int main (int argc, char const *const *argv)
unsigned int i = 0 ;
int r ;
uint16 ids[ndirs] ;
- char srcfn[llen + 23 + maxlen] ;
+ char srcfn[llen + 23 + maxlen] ; /* XXX: unsafe is dir is writable by non-root */
char dstfn[llen + 9 + sizeof(S6_SVSCAN_CTLDIR "/control") + maxlen] ;
rewinddir(dir) ;
byte_copy(srcfn, llen + 12, lfn) ;
diff --git a/src/s6-rc/s6-rc-update.c b/src/s6-rc/s6-rc-update.c
index 89db68e..a146c99 100644
--- a/src/s6-rc/s6-rc-update.c
+++ b/src/s6-rc/s6-rc-update.c
@@ -1,11 +1,106 @@
/* ISC license. */
+#include <unistd.h>
+#include <errno.h>
+#include <stdio.h>
+#include <skalibs/bytestr.h>
#include <skalibs/sgetopt.h>
#include <skalibs/strerr2.h>
+#include <skalibs/djbunix.h>
+#include <s6/s6-supervise.h>
+#include <s6-rc/s6rc-constants.h>
#define USAGE "s6-rc-update [ -l live ]"
#define dieusage() strerr_dieusage(100, USAGE)
+static char const *live = S6RC_LIVE_BASE ;
+
+static int safe_servicedir_update (char const *dst, char const *src, int h)
+{
+ unsigned int dstlen = str_len(dst) ;
+ unsigned int srclen = str_len(src) ;
+ int fd ;
+ int hasdata = 1, hasenv = 1, ok = 1 ;
+ char dstfn[dstlen + 15 + sizeof(S6_SUPERVISE_CTLDIR)] ;
+ char srcfn[srclen + 17] ;
+ char tmpfn[dstlen + 21] ;
+ byte_copy(dstfn, dstlen, dst) ;
+ byte_copy(srcfn, srclen, src) ;
+
+ byte_copy(dstfn + dstlen, 6, "/down") ;
+ fd = open_trunc(dstfn) ;
+ if (fd < 0) strerr_warnwu2sys("touch ", dstfn) ;
+ else close(fd) ;
+ byte_copy(dstfn + dstlen + 1, 5, "data") ;
+ byte_copy(tmpfn, dstlen + 5, dstfn) ;
+ byte_copy(tmpfn + dstlen + 5, 5, ".old") ;
+ if (rename(dstfn, tmpfn) < 0)
+ {
+ if (errno == ENOENT) hasdata = 0 ;
+ else goto err ;
+ }
+ byte_copy(dstfn + dstlen + 1, 4, "env") ;
+ byte_copy(tmpfn + dstlen + 1, 8, "env.old") ;
+ if (rename(dstfn, tmpfn) < 0)
+ {
+ if (errno == ENOENT) hasenv = 0 ;
+ else goto err ;
+ }
+ byte_copy(dstfn + dstlen + 1, 9, "nosetsid") ;
+ if (unlink(dstfn) < 0 && errno != ENOENT) goto err ;
+ byte_copy(dstfn + dstlen + 3, 14, "tification-fd") ;
+ if (unlink(dstfn) < 0 && errno != ENOENT) goto err ;
+
+ byte_copy(srcfn + srclen, 17, "/notification-fd") ;
+ hiercopy(srcfn, dstfn) ;
+ byte_copy(srcfn + srclen + 3, 7, "setsid") ;
+ byte_copy(dstfn + dstlen + 3, 7, "setsid") ;
+ hiercopy(srcfn, dstfn) ;
+ byte_copy(srcfn + srclen + 1, 5, "data") ;
+ byte_copy(dstfn + dstlen + 1, 5, "data") ;
+ hiercopy(srcfn, dstfn) ;
+ byte_copy(srcfn + srclen + 1, 4, "env") ;
+ byte_copy(dstfn + dstlen + 1, 4, "env") ;
+ hiercopy(srcfn, dstfn) ;
+ byte_copy(srcfn + srclen + 1, 4, "run") ;
+ byte_copy(dstfn + dstlen + 1, 4, "run") ;
+ if (!hiercopy(srcfn, dstfn)) goto err ;
+ byte_copy(srcfn + srclen + 1, 4, "run") ;
+ byte_copy(dstfn + dstlen + 1, 4, "finish") ;
+ hiercopy(srcfn, dstfn) ;
+ if (h)
+ {
+ byte_copy(dstfn + dstlen + 1, 5, "down") ;
+ if (unlink(dstfn) < 0)
+ {
+ strerr_warnwu2sys("unlink ", dstfn) ;
+ ok = 0 ;
+ }
+ byte_copy(dstfn + dstlen + 1, 8 + sizeof(S6_SUPERVISE_CTLDIR), S6_SUPERVISE_CTLDIR "/control") ;
+ s6_svc_write(dstfn, "u", 1) ;
+ }
+ byte_copy(dstfn + dstlen + 1, 9, "data.old") ;
+ rm_rf(dstfn) ;
+ byte_copy(dstfn + dstlen + 1, 8, "env.old") ;
+ rm_rf(dstfn) ;
+ return 1 ;
+
+ err:
+ if (h)
+ {
+ int e = errno ;
+ byte_copy(dstfn + dstlen + 1, 5, "down") ;
+ unlink(dstfn) ;
+ errno = e ;
+ }
+ return 0 ;
+}
+
+static int servicedir_name_change (char const *live, char const *oldname, char const *newname)
+{
+ return 1 ;
+}
+
int main (int argc, char const *const *argv)
{
PROG = "s6-rc-update" ;
diff --git a/src/s6-rc/s6-rc.c b/src/s6-rc/s6-rc.c
index 2190404..bd5011c 100644
--- a/src/s6-rc/s6-rc.c
+++ b/src/s6-rc/s6-rc.c
@@ -112,14 +112,14 @@ static pid_t start_longrun (unsigned int i, int h)
unsigned int m = 0 ;
char fmt[UINT32_FMT] ;
char vfmt[UINT_FMT] ;
- char servicefn[livelen + svdlen + 30] ;
+ char servicefn[livelen + svdlen + 26] ;
char const *newargv[7 + !!dryrun[0] * 6] ;
byte_copy(servicefn, livelen, live) ;
- byte_copy(servicefn + livelen, 13, "/servicedirs/") ;
- byte_copy(servicefn + livelen + 13, svdlen, db->string + db->services[i].x.longrun.servicedir) ;
+ byte_copy(servicefn + livelen, 9, "/scandir/") ;
+ byte_copy(servicefn + livelen + 9, svdlen, db->string + db->services[i].x.longrun.servicedir) ;
if (h)
{
- byte_copy(servicefn + livelen + 13 + svdlen, 17, "/notification-fd") ;
+ byte_copy(servicefn + livelen + 9 + svdlen, 17, "/notification-fd") ;
if (access(servicefn, F_OK) < 0)
{
h = 2 ;
@@ -154,11 +154,11 @@ static void success_longrun (unsigned int i, int h)
if (!dryrun[0])
{
unsigned int svdlen = str_len(db->string + db->services[i].x.longrun.servicedir) ;
- char fn[livelen + svdlen + 19] ;
+ char fn[livelen + svdlen + 15] ;
byte_copy(fn, livelen, live) ;
- byte_copy(fn + livelen, 13, "/servicedirs/") ;
- byte_copy(fn + livelen + 13, svdlen, db->string + db->services[i].x.longrun.servicedir) ;
- byte_copy(fn + livelen + 13 + svdlen, 6, "/down") ;
+ byte_copy(fn + livelen, 9, "/scandir/") ;
+ byte_copy(fn + livelen + 9, svdlen, db->string + db->services[i].x.longrun.servicedir) ;
+ byte_copy(fn + livelen + 9 + svdlen, 6, "/down") ;
if (h)
{
if (unlink(fn) < 0 && verbosity)