mirror of
https://github.com/troglobit/finit.git
synced 2026-11-13 17:00:16 +00:00
tmpfiles: set mode and owner of d/D directories through an fd
makedir() swallows EEXIST, so the chmod branch for directories that
already existed never ran, while chown() ran every time. On finix
/var/empty is immutable, which gave a warning on every boot even
though the owner was already correct.
mksubsys() is the original of this code and has the same shape, the
dbus plugin uses it for /tmp/dbus. Both now go through dirperm(),
which opens the directory and uses fstat/fchmod/fchown on the fd,
changing only what differs. A failed chown in mksubsys() is a warning
now rather than err(1), PID 1 should not exit over a directory it
cannot adjust.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
(cherry picked from commit 3a72d1263c)
This commit is contained in:
1 parent
417abf9000
commit
9bfbdc6bac
3 files changed
+35
-10
No files matched your search
+5
-5
@@ -557,11 +557,11 @@ static void tmpfiles(char *line)
|
|||||||
if (gid < 0)
|
if (gid < 0)
|
||||||
gid = 0;
|
gid = 0;
|
||||||
|
|
||||||
rc = makedir(path, mode ?: 0755);
|
if (!mode)
|
||||||
if (rc && errno == EEXIST)
|
mode = 0755;
|
||||||
rc = chmod(path, mode ?: 0755);
|
rc = makedir(path, mode);
|
||||||
if (chown(path, uid, gid))
|
if (!rc && dirperm(path, mode, uid, gid))
|
||||||
warn("Failed chown(%s, %d, %d)", path, uid, gid);
|
warn("Failed setting mode/owner on %s", path);
|
||||||
}
|
}
|
||||||
umask(omask);
|
umask(omask);
|
||||||
break;
|
break;
|
||||||
|
|||||||
+29
-5
@@ -25,6 +25,7 @@
|
|||||||
|
|
||||||
#include <ctype.h> /* isprint() */
|
#include <ctype.h> /* isprint() */
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
#include <grp.h>
|
#include <grp.h>
|
||||||
#include <pwd.h>
|
#include <pwd.h>
|
||||||
#ifdef HAVE_MNTENT_H
|
#ifdef HAVE_MNTENT_H
|
||||||
@@ -374,6 +375,32 @@ int rmrf(const char *path)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set mode and owner on a directory that may already exist. Works on
|
||||||
|
* an fd opened with O_NOFOLLOW | O_DIRECTORY, so the change lands on
|
||||||
|
* the directory itself and not on whatever a link at @path points to.
|
||||||
|
* Only what differs is touched, the directory may be immutable. uid
|
||||||
|
* -1 skips the chown.
|
||||||
|
*/
|
||||||
|
int dirperm(const char *path, mode_t mode, uid_t uid, gid_t gid)
|
||||||
|
{
|
||||||
|
struct stat st;
|
||||||
|
int fd, rc;
|
||||||
|
|
||||||
|
fd = open(path, O_RDONLY | O_DIRECTORY | O_NOFOLLOW | O_CLOEXEC);
|
||||||
|
if (fd < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
rc = fstat(fd, &st);
|
||||||
|
if (!rc && (st.st_mode & 07777) != mode)
|
||||||
|
rc = fchmod(fd, mode);
|
||||||
|
if (!rc && uid != (uid_t)-1 && (st.st_uid != uid || st.st_gid != gid))
|
||||||
|
rc = fchown(fd, uid, gid);
|
||||||
|
close(fd);
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Like mksubsys() but with the ids already resolved, uid -1 skips the
|
* Like mksubsys() but with the ids already resolved, uid -1 skips the
|
||||||
* chown. Parents are created 0755, only the leaf gets @mode.
|
* chown. Parents are created 0755, only the leaf gets @mode.
|
||||||
@@ -386,11 +413,8 @@ int mksubsysd(const char *dir, mode_t mode, uid_t uid, gid_t gid)
|
|||||||
omask = umask(0);
|
omask = umask(0);
|
||||||
|
|
||||||
rc = mkpath(dir, 0755);
|
rc = mkpath(dir, 0755);
|
||||||
if (!rc) {
|
if (!rc && dirperm(dir, mode, uid, gid))
|
||||||
rc = chmod(dir, mode);
|
warn("Failed setting mode/owner on %s", 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);
|
umask(omask);
|
||||||
|
|
||||||
|
|||||||
@@ -71,6 +71,7 @@ int getgroup (const char *group);
|
|||||||
int getcuser (char *buf, size_t len);
|
int getcuser (char *buf, size_t len);
|
||||||
int getcgroup (char *buf, size_t len);
|
int getcgroup (char *buf, size_t len);
|
||||||
|
|
||||||
|
int dirperm (const char *path, mode_t mode, uid_t uid, gid_t gid);
|
||||||
int mksubsys (const char *dir, mode_t mode, char *user, char *group);
|
int mksubsys (const char *dir, mode_t mode, char *user, char *group);
|
||||||
int mksubsysd (const char *dir, mode_t mode, uid_t uid, gid_t gid);
|
int mksubsysd (const char *dir, mode_t mode, uid_t uid, gid_t gid);
|
||||||
int chownr (const char *path, uid_t uid, gid_t gid);
|
int chownr (const char *path, uid_t uid, gid_t gid);
|
||||||
|
|||||||
Reference in new issue
Block a user