From: Colin Guthrie Date: Wed, 29 Oct 2014 14:03:41 +0000 (+0000) Subject: sysusers: Preserve ownership and mode on /etc/passwd and friends X-Git-Tag: v218~662 X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=commitdiff_plain;h=e3c72c21d62aadabf4df436c3e2c7219eeeccc1c;ds=sidebyside sysusers: Preserve ownership and mode on /etc/passwd and friends When running sysusers we would clobber file ownership and permissions on the files /etc/passwd, /etc/group and /etc/[g]shadow. This simply preserves the ownership and mode if existing files are found. --- diff --git a/src/sysusers/sysusers.c b/src/sysusers/sysusers.c index 9b9be96a0..c133dc5f1 100644 --- a/src/sysusers/sysusers.c +++ b/src/sysusers/sysusers.c @@ -358,6 +358,7 @@ static int write_files(void) { _cleanup_fclose_ FILE *passwd = NULL, *group = NULL, *shadow = NULL, *gshadow = NULL; _cleanup_free_ char *passwd_tmp = NULL, *group_tmp = NULL, *shadow_tmp = NULL, *gshadow_tmp = NULL; const char *passwd_path = NULL, *group_path = NULL, *shadow_path = NULL, *gshadow_path = NULL; + struct stat st; bool group_changed = false; Iterator iterator; Item *i; @@ -372,15 +373,17 @@ static int write_files(void) { if (r < 0) goto finish; - if (fchmod(fileno(group), 0644) < 0) { - r = -errno; - goto finish; - } - original = fopen(group_path, "re"); if (original) { struct group *gr; + if (fstat(fileno(original), &st) < 0 || + fchmod(fileno(group), st.st_mode & 07777) < 0 || + fchown(fileno(group), st.st_uid, st.st_gid) < 0) { + r = -errno; + goto finish; + } + errno = 0; while ((gr = fgetgrent(original))) { /* Safety checks against name and GID @@ -418,6 +421,9 @@ static int write_files(void) { } else if (errno != ENOENT) { r = -errno; goto finish; + } else if (fchmod(fileno(group), 0644) < 0) { + r = -errno; + goto finish; } HASHMAP_FOREACH(i, todo_gids, iterator) { @@ -449,15 +455,17 @@ static int write_files(void) { if (r < 0) goto finish; - if (fchmod(fileno(gshadow), 0000) < 0) { - r = -errno; - goto finish; - } - original = fopen(gshadow_path, "re"); if (original) { struct sgrp *sg; + if (fstat(fileno(original), &st) < 0 || + fchmod(fileno(gshadow), st.st_mode & 07777) < 0 || + fchown(fileno(gshadow), st.st_uid, st.st_gid) < 0) { + r = -errno; + goto finish; + } + errno = 0; while ((sg = fgetsgent(original))) { @@ -483,6 +491,9 @@ static int write_files(void) { } else if (errno != ENOENT) { r = -errno; goto finish; + } else if (fchmod(fileno(gshadow), 0000) < 0) { + r = -errno; + goto finish; } HASHMAP_FOREACH(i, todo_gids, iterator) { @@ -513,15 +524,17 @@ static int write_files(void) { if (r < 0) goto finish; - if (fchmod(fileno(passwd), 0644) < 0) { - r = -errno; - goto finish; - } - original = fopen(passwd_path, "re"); if (original) { struct passwd *pw; + if (fstat(fileno(original), &st) < 0 || + fchmod(fileno(passwd), st.st_mode & 07777) < 0 || + fchown(fileno(passwd), st.st_uid, st.st_gid) < 0) { + r = -errno; + goto finish; + } + errno = 0; while ((pw = fgetpwent(original))) { @@ -552,6 +565,9 @@ static int write_files(void) { } else if (errno != ENOENT) { r = -errno; goto finish; + } else if (fchmod(fileno(passwd), 0644) < 0) { + r = -errno; + goto finish; } HASHMAP_FOREACH(i, todo_uids, iterator) { @@ -596,15 +612,17 @@ static int write_files(void) { if (r < 0) goto finish; - if (fchmod(fileno(shadow), 0000) < 0) { - r = -errno; - goto finish; - } - original = fopen(shadow_path, "re"); if (original) { struct spwd *sp; + if (fstat(fileno(original), &st) < 0 || + fchmod(fileno(shadow), st.st_mode & 07777) < 0 || + fchown(fileno(shadow), st.st_uid, st.st_gid) < 0) { + r = -errno; + goto finish; + } + errno = 0; while ((sp = fgetspent(original))) { @@ -629,6 +647,9 @@ static int write_files(void) { } else if (errno != ENOENT) { r = -errno; goto finish; + } else if (fchmod(fileno(shadow), 0000) < 0) { + r = -errno; + goto finish; } lstchg = (long) (now(CLOCK_REALTIME) / USEC_PER_DAY);