mirror of
https://github.com/troglobit/finit.git
synced 2026-10-30 12:50:34 +00:00
conf: adopt the systemd semantics for per-service directories
Aaron Andersen points out in the #492 discussion that the *Directory settings carry more contract than create-and-chown: per-directory modes, specific ownership rules, and cleanup toggles. Without them config-dir was chowned to the service user, which systemd never does, an existing directory with drifted ownership was left wrong, and the runtime directory could not survive a restart. Now matching systemd.exec(5), and where the man page is vague, the code in setup_exec_directory(): - each directory takes a matching -mode key, octal with the leading zero, default 0755. The mode of the named directory is locked down again on every start, also when it already exists - config-dir is created but never chowned - the contents of an existing directory are left alone as long as the owner is right; on drift everything under it is chowned back - runtime-dir-preserve = no | restart | yes maps RuntimeDirectoryPreserve=. A service still qualified to run when the runtime directory would be removed is restarting, not stopping, which is what svc_enabled() answers The dir mechanics move to mksubsysd(), taking resolved ids, with mksubsys() reduced to a name-resolving wrapper for the dbus plugin. The child resolves uid/gid once for both directory setup and privilege drop. The symlink form, RuntimeDirectory=foo:bar, is not adopted. Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
This commit is contained in:
8 files changed
+191
-44
No files matched your search
+52
-16
@@ -325,6 +325,33 @@ static int rmrf_cb(const char *fpath, const struct stat *sb, int tflag, struct F
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* nftw() cannot pass user data, see also tmpfiles.c do_clean() */
|
||||
static uid_t chownr_uid;
|
||||
static gid_t chownr_gid;
|
||||
|
||||
static int chownr_cb(const char *fpath, const struct stat *sb, int tflag, struct FTW *ftw)
|
||||
{
|
||||
(void)tflag;
|
||||
(void)ftw;
|
||||
|
||||
if (sb->st_uid == chownr_uid && sb->st_gid == chownr_gid)
|
||||
return 0;
|
||||
|
||||
if (lchown(fpath, chownr_uid, chownr_gid))
|
||||
warn("Failed chown(%s, %d, %d)", fpath, (int)chownr_uid, (int)chownr_gid);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* chown -R */
|
||||
int chownr(const char *path, uid_t uid, gid_t gid)
|
||||
{
|
||||
chownr_uid = uid;
|
||||
chownr_gid = gid;
|
||||
|
||||
return nftw(path, chownr_cb, 20, FTW_PHYS);
|
||||
}
|
||||
|
||||
/* empty a directory but keep it, silently ignores a missing path */
|
||||
int rmcontents(const char *path)
|
||||
{
|
||||
@@ -347,34 +374,43 @@ int rmrf(const char *path)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mksubsys(const char *dir, mode_t mode, char *user, char *group)
|
||||
/*
|
||||
* Like mksubsys() but with the ids already resolved, uid -1 skips the
|
||||
* chown. Parents are created 0755, only the leaf gets @mode.
|
||||
*/
|
||||
int mksubsysd(const char *dir, mode_t mode, uid_t uid, gid_t gid)
|
||||
{
|
||||
mode_t omask;
|
||||
int uid, gid;
|
||||
int rc = 0;
|
||||
int rc;
|
||||
|
||||
omask = umask(0);
|
||||
|
||||
rc = makedir(dir, mode);
|
||||
if (rc && errno == EEXIST)
|
||||
rc = mkpath(dir, 0755);
|
||||
if (!rc) {
|
||||
rc = chmod(dir, mode);
|
||||
|
||||
uid = getuser(user, NULL);
|
||||
if (uid >= 0) {
|
||||
gid = getgroup(group);
|
||||
if (gid < 0)
|
||||
gid = 0;
|
||||
|
||||
if (chown(dir, uid, gid))
|
||||
err(1, "Failed chown(%s, %d, %d)", dir, uid, gid);
|
||||
} else
|
||||
warnx("Cannot find user %s, %s is owned by root", user, dir);
|
||||
if (!rc && uid != (uid_t)-1 && chown(dir, uid, gid))
|
||||
err(1, "Failed chown(%s, %d, %d)", dir, (int)uid, (int)gid);
|
||||
}
|
||||
|
||||
umask(omask);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int mksubsys(const char *dir, mode_t mode, char *user, char *group)
|
||||
{
|
||||
int uid, gid;
|
||||
|
||||
uid = getuser(user, NULL);
|
||||
gid = getgroup(group);
|
||||
if (gid < 0)
|
||||
gid = 0;
|
||||
if (uid < 0)
|
||||
warnx("Cannot find user %s, %s is owned by root", user, dir);
|
||||
|
||||
return mksubsysd(dir, mode, uid < 0 ? (uid_t)-1 : (uid_t)uid, (gid_t)gid);
|
||||
}
|
||||
|
||||
/*
|
||||
* Read an open stream to EOF into a malloc()'ed, NUL terminated buffer.
|
||||
*
|
||||
|
||||
Reference in new issue
Block a user