diff --git a/TODO b/TODO index 37323e3a19..624ae2aafd 100644 --- a/TODO +++ b/TODO @@ -256,8 +256,6 @@ Features: * systemd-firstboot: teach it dissector magic, so that you can point it to some disk image and it will just set everything in it all behind the scenes. -* systemd-firstboot: add --force mode that replaces existing configuration. - * We should probably replace /var/log/README, /etc/rc.d/README with symlinks that are linked to these places instead of copied. After all they are constant vendor data. diff --git a/man/systemd-firstboot.xml b/man/systemd-firstboot.xml index 0eb212341f..81e62484fd 100644 --- a/man/systemd-firstboot.xml +++ b/man/systemd-firstboot.xml @@ -150,18 +150,27 @@ + - Sets the password of the system's root user. - This creates a + Sets the password of the system's root user. This creates a shadow5 - file. This setting exists in two forms: - accepts the password to set - directly on the command line, and - reads it from a file. - Note that it is not recommended to specify passwords on the - command line, as other users might be able to see them simply - by invoking - ps1. + file. This setting exists in three forms: accepts the password to + set directly on the command line, reads it from a file and + accepts an already hashed password on the command line. See + shadow5 + for more information on the format of the hashed password. Note that it is not recommended to specify + plaintext passwords on the command line, as other users might be able to see them simply by invoking + ps1. + + + + + + + Sets the system's kernel command line. This controls the + /etc/kernel/cmdline file which is used by + kernel-install8. + @@ -221,6 +230,23 @@ . + + + + systemd-firstboot doesn't modify existing files unless + is specified. For modifications to /etc/passwd and + /etc/shadow, systemd-firstboot only modifies the entry of the + root user instead of overwriting the entire file. + + + + + + Removes the password of the system's root user, enabling login as root without a + password unless the root account is locked. Note that this is extremely insecure and hence this + option should not be used lightly. + + diff --git a/src/basic/fileio.c b/src/basic/fileio.c index 00dce02064..f2f1e1139f 100644 --- a/src/basic/fileio.c +++ b/src/basic/fileio.c @@ -1187,3 +1187,25 @@ int warn_file_is_world_accessible(const char *filename, struct stat *st, const c filename, st->st_mode & 07777); return 0; } + +int sync_rights(int from, int to) { + struct stat st; + + if (fstat(from, &st) < 0) + return -errno; + + return fchmod_and_chown(to, st.st_mode & 07777, st.st_uid, st.st_gid); +} + +int rename_and_apply_smack_floor_label(const char *from, const char *to) { + int r = 0; + if (rename(from, to) < 0) + return -errno; + +#ifdef SMACK_RUN_LABEL + r = mac_smack_apply(to, SMACK_ATTR_ACCESS, SMACK_FLOOR_LABEL); + if (r < 0) + return r; +#endif + return r; +} diff --git a/src/basic/fileio.h b/src/basic/fileio.h index e6062121a3..e2830b7963 100644 --- a/src/basic/fileio.h +++ b/src/basic/fileio.h @@ -106,3 +106,7 @@ static inline int read_nul_string(FILE *f, size_t limit, char **ret) { int safe_fgetc(FILE *f, char *ret); int warn_file_is_world_accessible(const char *filename, struct stat *st, const char *unit, unsigned line); + +int sync_rights(int from, int to); + +int rename_and_apply_smack_floor_label(const char *temp_path, const char *dest_path); diff --git a/src/firstboot/firstboot.c b/src/firstboot/firstboot.c index f9fdf7b1d7..0c3ef3e2a7 100644 --- a/src/firstboot/firstboot.c +++ b/src/firstboot/firstboot.c @@ -30,6 +30,7 @@ #include "strv.h" #include "terminal-util.h" #include "time-util.h" +#include "tmpfile-util-label.h" #include "umask-util.h" #include "user-util.h" @@ -41,6 +42,7 @@ static char *arg_timezone = NULL; static char *arg_hostname = NULL; static sd_id128_t arg_machine_id = {}; static char *arg_root_password = NULL; +static char *arg_kernel_cmdline = NULL; static bool arg_prompt_locale = false; static bool arg_prompt_keymap = false; static bool arg_prompt_timezone = false; @@ -50,6 +52,9 @@ static bool arg_copy_locale = false; static bool arg_copy_keymap = false; static bool arg_copy_timezone = false; static bool arg_copy_root_password = false; +static bool arg_force = false; +static bool arg_delete_root_password = false; +static bool arg_root_password_is_hashed = false; STATIC_DESTRUCTOR_REGISTER(arg_root, freep); STATIC_DESTRUCTOR_REGISTER(arg_locale, freep); @@ -273,7 +278,7 @@ static int process_locale(void) { int r; etc_localeconf = prefix_roota(arg_root, "/etc/locale.conf"); - if (laccess(etc_localeconf, F_OK) >= 0) + if (laccess(etc_localeconf, F_OK) >= 0 && !arg_force) return 0; if (arg_copy_locale && arg_root) { @@ -340,7 +345,7 @@ static int process_keymap(void) { int r; etc_vconsoleconf = prefix_roota(arg_root, "/etc/vconsole.conf"); - if (laccess(etc_vconsoleconf, F_OK) >= 0) + if (laccess(etc_vconsoleconf, F_OK) >= 0 && !arg_force) return 0; if (arg_copy_keymap && arg_root) { @@ -412,7 +417,7 @@ static int process_timezone(void) { int r; etc_localtime = prefix_roota(arg_root, "/etc/localtime"); - if (laccess(etc_localtime, F_OK) >= 0) + if (laccess(etc_localtime, F_OK) >= 0 && !arg_force) return 0; if (arg_copy_timezone && arg_root) { @@ -492,7 +497,7 @@ static int process_hostname(void) { int r; etc_hostname = prefix_roota(arg_root, "/etc/hostname"); - if (laccess(etc_hostname, F_OK) >= 0) + if (laccess(etc_hostname, F_OK) >= 0 && !arg_force) return 0; r = prompt_hostname(); @@ -503,7 +508,8 @@ static int process_hostname(void) { return 0; r = write_string_file(etc_hostname, arg_hostname, - WRITE_STRING_FILE_CREATE | WRITE_STRING_FILE_SYNC | WRITE_STRING_FILE_MKDIR_0755); + WRITE_STRING_FILE_CREATE | WRITE_STRING_FILE_SYNC | WRITE_STRING_FILE_MKDIR_0755 | + (arg_force ? WRITE_STRING_FILE_ATOMIC : 0)); if (r < 0) return log_error_errno(r, "Failed to write %s: %m", etc_hostname); @@ -517,14 +523,15 @@ static int process_machine_id(void) { int r; etc_machine_id = prefix_roota(arg_root, "/etc/machine-id"); - if (laccess(etc_machine_id, F_OK) >= 0) + if (laccess(etc_machine_id, F_OK) >= 0 && !arg_force) return 0; if (sd_id128_is_null(arg_machine_id)) return 0; r = write_string_file(etc_machine_id, sd_id128_to_string(arg_machine_id, id), - WRITE_STRING_FILE_CREATE | WRITE_STRING_FILE_SYNC | WRITE_STRING_FILE_MKDIR_0755); + WRITE_STRING_FILE_CREATE | WRITE_STRING_FILE_SYNC | WRITE_STRING_FILE_MKDIR_0755 | + (arg_force ? WRITE_STRING_FILE_ATOMIC : 0)); if (r < 0) return log_error_errno(r, "Failed to write machine id: %m"); @@ -533,7 +540,7 @@ static int process_machine_id(void) { } static int prompt_root_password(void) { - const char *msg1, *msg2, *etc_shadow; + const char *msg1, *msg2; int r; if (arg_root_password) @@ -542,10 +549,6 @@ static int prompt_root_password(void) { if (!arg_prompt_root_password) return 0; - etc_shadow = prefix_roota(arg_root, "/etc/shadow"); - if (laccess(etc_shadow, F_OK) >= 0) - return 0; - print_welcome(); putchar('\n'); @@ -586,45 +589,145 @@ static int prompt_root_password(void) { return 0; } -static int write_root_shadow(const char *path, const struct spwd *p) { - _cleanup_fclose_ FILE *f = NULL; +static int write_root_passwd(const char *passwd_path, const char *password) { + _cleanup_fclose_ FILE *original = NULL, *passwd = NULL; + _cleanup_(unlink_and_freep) char *passwd_tmp = NULL; int r; - assert(path); - assert(p); - - RUN_WITH_UMASK(0777) - f = fopen(path, "wex"); - if (!f) - return -errno; - - r = putspent_sane(p, f); + r = fopen_temporary_label("/etc/passwd", passwd_path, &passwd, &passwd_tmp); if (r < 0) return r; - return fflush_sync_and_check(f); + original = fopen(passwd_path, "re"); + if (original) { + struct passwd *i; + + r = sync_rights(fileno(original), fileno(passwd)); + if (r < 0) + return r; + + while ((r = fgetpwent_sane(original, &i)) > 0) { + + if (streq(i->pw_name, "root")) + i->pw_passwd = (char *) password; + + r = putpwent_sane(i, passwd); + if (r < 0) + return r; + } + if (r < 0) + return r; + + } else { + struct passwd root = { + .pw_name = (char *) "root", + .pw_passwd = (char *) password, + .pw_uid = 0, + .pw_gid = 0, + .pw_gecos = (char *) "Super User", + .pw_dir = (char *) "/root", + .pw_shell = (char *) "/bin/sh", + }; + + if (errno != ENOENT) + return -errno; + + r = fchmod(fileno(passwd), 0000); + if (r < 0) + return -errno; + + r = putpwent_sane(&root, passwd); + if (r < 0) + return r; + } + + r = fflush_sync_and_check(passwd); + if (r < 0) + return r; + + r = rename_and_apply_smack_floor_label(passwd_tmp, passwd_path); + if (r < 0) + return r; + + return 0; +} + +static int write_root_shadow(const char *shadow_path, const char *hashed_password) { + _cleanup_fclose_ FILE *original = NULL, *shadow = NULL; + _cleanup_(unlink_and_freep) char *shadow_tmp = NULL; + int r; + + r = fopen_temporary_label("/etc/shadow", shadow_path, &shadow, &shadow_tmp); + if (r < 0) + return r; + + original = fopen(shadow_path, "re"); + if (original) { + struct spwd *i; + + r = sync_rights(fileno(original), fileno(shadow)); + if (r < 0) + return r; + + while ((r = fgetspent_sane(original, &i)) > 0) { + + if (streq(i->sp_namp, "root")) { + i->sp_pwdp = (char *) hashed_password; + i->sp_lstchg = (long) (now(CLOCK_REALTIME) / USEC_PER_DAY); + } + + r = putspent_sane(i, shadow); + if (r < 0) + return r; + } + if (r < 0) + return r; + + } else { + struct spwd root = { + .sp_namp = (char*) "root", + .sp_pwdp = (char *) hashed_password, + .sp_lstchg = (long) (now(CLOCK_REALTIME) / USEC_PER_DAY), + .sp_min = -1, + .sp_max = -1, + .sp_warn = -1, + .sp_inact = -1, + .sp_expire = -1, + .sp_flag = (unsigned long) -1, /* this appears to be what everybody does ... */ + }; + + if (errno != ENOENT) + return -errno; + + r = fchmod(fileno(shadow), 0000); + if (r < 0) + return -errno; + + r = putspent_sane(&root, shadow); + if (r < 0) + return r; + } + + r = fflush_sync_and_check(shadow); + if (r < 0) + return r; + + r = rename_and_apply_smack_floor_label(shadow_tmp, shadow_path); + if (r < 0) + return r; + + return 0; } static int process_root_password(void) { - - struct spwd item = { - .sp_namp = (char*) "root", - .sp_min = -1, - .sp_max = -1, - .sp_warn = -1, - .sp_inact = -1, - .sp_expire = -1, - .sp_flag = (unsigned long) -1, /* this appears to be what everybody does ... */ - }; - _cleanup_free_ char *salt = NULL; _cleanup_close_ int lock = -1; struct crypt_data cd = {}; - + const char *hashed_password; const char *etc_shadow; int r; etc_shadow = prefix_roota(arg_root, "/etc/shadow"); - if (laccess(etc_shadow, F_OK) >= 0) + if (laccess(etc_shadow, F_OK) >= 0 && !arg_force) return 0; (void) mkdir_parents(etc_shadow, 0755); @@ -633,6 +736,21 @@ static int process_root_password(void) { if (lock < 0) return log_error_errno(lock, "Failed to take a lock: %m"); + if (arg_delete_root_password) { + const char *etc_passwd; + + /* Mixing alloca() and other stuff that touches the stack in one expression is not portable. */ + etc_passwd = prefix_roota(arg_root, "/etc/passwd"); + + r = write_root_passwd(etc_passwd, ""); + if (r < 0) + return log_error_errno(r, "Failed to write %s: %m", etc_passwd); + + log_info("%s written", etc_passwd); + + return 0; + } + if (arg_copy_root_password && arg_root) { struct spwd *p; @@ -646,7 +764,7 @@ static int process_root_password(void) { return log_error_errno(errno, "Failed to find shadow entry for root: %m"); } - r = write_root_shadow(etc_shadow, p); + r = write_root_shadow(etc_shadow, p->sp_pwdp); if (r < 0) return log_error_errno(r, "Failed to write %s: %m", etc_shadow); @@ -662,19 +780,24 @@ static int process_root_password(void) { if (!arg_root_password) return 0; - r = make_salt(&salt); - if (r < 0) - return log_error_errno(r, "Failed to get salt: %m"); + if (arg_root_password_is_hashed) + hashed_password = arg_root_password; + else { + _cleanup_free_ char *salt = NULL; + /* hashed_password points inside cd after crypt_r returns so cd has function scope. */ - errno = 0; - item.sp_pwdp = crypt_r(arg_root_password, salt, &cd); - if (!item.sp_pwdp) - return log_error_errno(errno == 0 ? SYNTHETIC_ERRNO(EINVAL) : errno, - "Failed to encrypt password: %m"); + r = make_salt(&salt); + if (r < 0) + return log_error_errno(r, "Failed to get salt: %m"); - item.sp_lstchg = (long) (now(CLOCK_REALTIME) / USEC_PER_DAY); + errno = 0; + hashed_password = crypt_r(arg_root_password, salt, &cd); + if (!hashed_password) + return log_error_errno(errno == 0 ? SYNTHETIC_ERRNO(EINVAL) : errno, + "Failed to encrypt password: %m"); + } - r = write_root_shadow(etc_shadow, &item); + r = write_root_shadow(etc_shadow, hashed_password); if (r < 0) return log_error_errno(r, "Failed to write %s: %m", etc_shadow); @@ -682,6 +805,27 @@ static int process_root_password(void) { return 0; } +static int process_kernel_cmdline(void) { + const char *etc_kernel_cmdline; + int r; + + etc_kernel_cmdline = prefix_roota(arg_root, "/etc/kernel/cmdline"); + if (laccess(etc_kernel_cmdline, F_OK) >= 0 && !arg_force) + return 0; + + if (!arg_kernel_cmdline) + return 0; + + r = write_string_file(etc_kernel_cmdline, arg_kernel_cmdline, + WRITE_STRING_FILE_CREATE | WRITE_STRING_FILE_SYNC | WRITE_STRING_FILE_MKDIR_0755 | + (arg_force ? WRITE_STRING_FILE_ATOMIC : 0)); + if (r < 0) + return log_error_errno(r, "Failed to write %s: %m", etc_kernel_cmdline); + + log_info("%s written.", etc_kernel_cmdline); + return 0; +} + static int help(void) { _cleanup_free_ char *link = NULL; int r; @@ -692,29 +836,32 @@ static int help(void) { printf("%s [OPTIONS...]\n\n" "Configures basic settings of the system.\n\n" - " -h --help Show this help\n" - " --version Show package version\n" - " --root=PATH Operate on an alternate filesystem root\n" - " --locale=LOCALE Set primary locale (LANG=)\n" - " --locale-messages=LOCALE Set message locale (LC_MESSAGES=)\n" - " --keymap=KEYMAP Set keymap\n" - " --timezone=TIMEZONE Set timezone\n" - " --hostname=NAME Set hostname\n" - " --machine-ID=ID Set machine ID\n" - " --root-password=PASSWORD Set root password\n" - " --root-password-file=FILE Set root password from file\n" - " --prompt-locale Prompt the user for locale settings\n" - " --prompt-keymap Prompt the user for keymap settings\n" - " --prompt-timezone Prompt the user for timezone\n" - " --prompt-hostname Prompt the user for hostname\n" - " --prompt-root-password Prompt the user for root password\n" - " --prompt Prompt for all of the above\n" - " --copy-locale Copy locale from host\n" - " --copy-keymap Copy keymap from host\n" - " --copy-timezone Copy timezone from host\n" - " --copy-root-password Copy root password from host\n" - " --copy Copy locale, keymap, timezone, root password\n" - " --setup-machine-id Generate a new random machine ID\n" + " -h --help Show this help\n" + " --version Show package version\n" + " --root=PATH Operate on an alternate filesystem root\n" + " --locale=LOCALE Set primary locale (LANG=)\n" + " --locale-messages=LOCALE Set message locale (LC_MESSAGES=)\n" + " --keymap=KEYMAP Set keymap\n" + " --timezone=TIMEZONE Set timezone\n" + " --hostname=NAME Set hostname\n" + " --machine-ID=ID Set machine ID\n" + " --root-password=PASSWORD Set root password from plaintext password\n" + " --root-password-file=FILE Set root password from file\n" + " --root-password-hashed=HASHED_PASSWORD Set root password from hashed password\n" + " --prompt-locale Prompt the user for locale settings\n" + " --prompt-keymap Prompt the user for keymap settings\n" + " --prompt-timezone Prompt the user for timezone\n" + " --prompt-hostname Prompt the user for hostname\n" + " --prompt-root-password Prompt the user for root password\n" + " --prompt Prompt for all of the above\n" + " --copy-locale Copy locale from host\n" + " --copy-keymap Copy keymap from host\n" + " --copy-timezone Copy timezone from host\n" + " --copy-root-password Copy root password from host\n" + " --copy Copy locale, keymap, timezone, root password\n" + " --setup-machine-id Generate a new random machine ID\n" + " --force Overwrite existing files\n" + " --delete-root-password Delete root password\n" "\nSee the %s for details.\n" , program_invocation_short_name , link @@ -736,6 +883,8 @@ static int parse_argv(int argc, char *argv[]) { ARG_MACHINE_ID, ARG_ROOT_PASSWORD, ARG_ROOT_PASSWORD_FILE, + ARG_ROOT_PASSWORD_HASHED, + ARG_KERNEL_COMMAND_LINE, ARG_PROMPT, ARG_PROMPT_LOCALE, ARG_PROMPT_KEYMAP, @@ -748,32 +897,38 @@ static int parse_argv(int argc, char *argv[]) { ARG_COPY_TIMEZONE, ARG_COPY_ROOT_PASSWORD, ARG_SETUP_MACHINE_ID, + ARG_FORCE, + ARG_DELETE_ROOT_PASSWORD, }; static const struct option options[] = { - { "help", no_argument, NULL, 'h' }, - { "version", no_argument, NULL, ARG_VERSION }, - { "root", required_argument, NULL, ARG_ROOT }, - { "locale", required_argument, NULL, ARG_LOCALE }, - { "locale-messages", required_argument, NULL, ARG_LOCALE_MESSAGES }, - { "keymap", required_argument, NULL, ARG_KEYMAP }, - { "timezone", required_argument, NULL, ARG_TIMEZONE }, - { "hostname", required_argument, NULL, ARG_HOSTNAME }, - { "machine-id", required_argument, NULL, ARG_MACHINE_ID }, - { "root-password", required_argument, NULL, ARG_ROOT_PASSWORD }, - { "root-password-file", required_argument, NULL, ARG_ROOT_PASSWORD_FILE }, - { "prompt", no_argument, NULL, ARG_PROMPT }, - { "prompt-locale", no_argument, NULL, ARG_PROMPT_LOCALE }, - { "prompt-keymap", no_argument, NULL, ARG_PROMPT_KEYMAP }, - { "prompt-timezone", no_argument, NULL, ARG_PROMPT_TIMEZONE }, - { "prompt-hostname", no_argument, NULL, ARG_PROMPT_HOSTNAME }, - { "prompt-root-password", no_argument, NULL, ARG_PROMPT_ROOT_PASSWORD }, - { "copy", no_argument, NULL, ARG_COPY }, - { "copy-locale", no_argument, NULL, ARG_COPY_LOCALE }, - { "copy-keymap", no_argument, NULL, ARG_COPY_KEYMAP }, - { "copy-timezone", no_argument, NULL, ARG_COPY_TIMEZONE }, - { "copy-root-password", no_argument, NULL, ARG_COPY_ROOT_PASSWORD }, - { "setup-machine-id", no_argument, NULL, ARG_SETUP_MACHINE_ID }, + { "help", no_argument, NULL, 'h' }, + { "version", no_argument, NULL, ARG_VERSION }, + { "root", required_argument, NULL, ARG_ROOT }, + { "locale", required_argument, NULL, ARG_LOCALE }, + { "locale-messages", required_argument, NULL, ARG_LOCALE_MESSAGES }, + { "keymap", required_argument, NULL, ARG_KEYMAP }, + { "timezone", required_argument, NULL, ARG_TIMEZONE }, + { "hostname", required_argument, NULL, ARG_HOSTNAME }, + { "machine-id", required_argument, NULL, ARG_MACHINE_ID }, + { "root-password", required_argument, NULL, ARG_ROOT_PASSWORD }, + { "root-password-file", required_argument, NULL, ARG_ROOT_PASSWORD_FILE }, + { "root-password-hashed", required_argument, NULL, ARG_ROOT_PASSWORD_HASHED }, + { "kernel-command-line", required_argument, NULL, ARG_KERNEL_COMMAND_LINE }, + { "prompt", no_argument, NULL, ARG_PROMPT }, + { "prompt-locale", no_argument, NULL, ARG_PROMPT_LOCALE }, + { "prompt-keymap", no_argument, NULL, ARG_PROMPT_KEYMAP }, + { "prompt-timezone", no_argument, NULL, ARG_PROMPT_TIMEZONE }, + { "prompt-hostname", no_argument, NULL, ARG_PROMPT_HOSTNAME }, + { "prompt-root-password", no_argument, NULL, ARG_PROMPT_ROOT_PASSWORD }, + { "copy", no_argument, NULL, ARG_COPY }, + { "copy-locale", no_argument, NULL, ARG_COPY_LOCALE }, + { "copy-keymap", no_argument, NULL, ARG_COPY_KEYMAP }, + { "copy-timezone", no_argument, NULL, ARG_COPY_TIMEZONE }, + { "copy-root-password", no_argument, NULL, ARG_COPY_ROOT_PASSWORD }, + { "setup-machine-id", no_argument, NULL, ARG_SETUP_MACHINE_ID }, + { "force", no_argument, NULL, ARG_FORCE }, + { "delete-root-password", no_argument, NULL, ARG_DELETE_ROOT_PASSWORD }, {} }; @@ -838,6 +993,8 @@ static int parse_argv(int argc, char *argv[]) { r = free_and_strdup(&arg_root_password, optarg); if (r < 0) return log_oom(); + + arg_root_password_is_hashed = false; break; case ARG_ROOT_PASSWORD_FILE: @@ -847,6 +1004,15 @@ static int parse_argv(int argc, char *argv[]) { if (r < 0) return log_error_errno(r, "Failed to read %s: %m", optarg); + arg_root_password_is_hashed = false; + break; + + case ARG_ROOT_PASSWORD_HASHED: + r = free_and_strdup(&arg_root_password, optarg); + if (r < 0) + return log_oom(); + + arg_root_password_is_hashed = true; break; case ARG_HOSTNAME: @@ -868,6 +1034,13 @@ static int parse_argv(int argc, char *argv[]) { break; + case ARG_KERNEL_COMMAND_LINE: + r = free_and_strdup(&arg_kernel_cmdline, optarg); + if (r < 0) + return log_oom(); + + break; + case ARG_PROMPT: arg_prompt_locale = arg_prompt_keymap = arg_prompt_timezone = arg_prompt_hostname = arg_prompt_root_password = true; break; @@ -920,6 +1093,14 @@ static int parse_argv(int argc, char *argv[]) { break; + case ARG_FORCE: + arg_force = true; + break; + + case ARG_DELETE_ROOT_PASSWORD: + arg_delete_root_password = true; + break; + case '?': return -EINVAL; @@ -935,6 +1116,10 @@ static int parse_argv(int argc, char *argv[]) { if (arg_locale_messages && !locale_is_ok(arg_locale_messages)) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Locale %s is not installed.", arg_locale_messages); + if (arg_delete_root_password && (arg_copy_root_password || arg_root_password || arg_prompt_root_password)) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "--delete-root-password cannot be combined with other root password options"); + return 1; } @@ -980,6 +1165,10 @@ static int run(int argc, char *argv[]) { if (r < 0) return r; + r = process_kernel_cmdline(); + if (r < 0) + return r; + return 0; } diff --git a/src/sysusers/sysusers.c b/src/sysusers/sysusers.c index 847aebc516..6fbd5985d3 100644 --- a/src/sysusers/sysusers.c +++ b/src/sysusers/sysusers.c @@ -345,28 +345,6 @@ static int putsgent_with_members(const struct sgrp *sg, FILE *gshadow) { } #endif -static int sync_rights(FILE *from, const char *to) { - struct stat st; - - if (fstat(fileno(from), &st) < 0) - return -errno; - - return chmod_and_chown_unsafe(to, st.st_mode & 07777, st.st_uid, st.st_gid); -} - -static int rename_and_apply_smack(const char *temp_path, const char *dest_path) { - int r = 0; - if (rename(temp_path, dest_path) < 0) - return -errno; - -#ifdef SMACK_RUN_LABEL - r = mac_smack_apply(dest_path, SMACK_ATTR_ACCESS, SMACK_FLOOR_LABEL); - if (r < 0) - return r; -#endif - return r; -} - static const char* default_shell(uid_t uid) { return uid == 0 ? "/bin/sh" : NOLOGIN; } @@ -389,7 +367,7 @@ static int write_temporary_passwd(const char *passwd_path, FILE **tmpfile, char original = fopen(passwd_path, "re"); if (original) { - r = sync_rights(original, passwd_tmp); + r = sync_rights(fileno(original), fileno(passwd)); if (r < 0) return r; @@ -491,7 +469,7 @@ static int write_temporary_shadow(const char *shadow_path, FILE **tmpfile, char original = fopen(shadow_path, "re"); if (original) { - r = sync_rights(original, shadow_tmp); + r = sync_rights(fileno(original), fileno(shadow)); if (r < 0) return r; @@ -588,7 +566,7 @@ static int write_temporary_group(const char *group_path, FILE **tmpfile, char ** original = fopen(group_path, "re"); if (original) { - r = sync_rights(original, group_tmp); + r = sync_rights(fileno(original), fileno(group)); if (r < 0) return r; @@ -687,7 +665,7 @@ static int write_temporary_gshadow(const char * gshadow_path, FILE **tmpfile, ch if (original) { struct sgrp *sg; - r = sync_rights(original, gshadow_tmp); + r = sync_rights(fileno(original), fileno(gshadow)); if (r < 0) return r; @@ -794,14 +772,14 @@ static int write_files(void) { /* And make the new files count */ if (group) { - r = rename_and_apply_smack(group_tmp, group_path); + r = rename_and_apply_smack_floor_label(group_tmp, group_path); if (r < 0) return r; group_tmp = mfree(group_tmp); } if (gshadow) { - r = rename_and_apply_smack(gshadow_tmp, gshadow_path); + r = rename_and_apply_smack_floor_label(gshadow_tmp, gshadow_path); if (r < 0) return r; @@ -809,14 +787,14 @@ static int write_files(void) { } if (passwd) { - r = rename_and_apply_smack(passwd_tmp, passwd_path); + r = rename_and_apply_smack_floor_label(passwd_tmp, passwd_path); if (r < 0) return r; passwd_tmp = mfree(passwd_tmp); } if (shadow) { - r = rename_and_apply_smack(shadow_tmp, shadow_path); + r = rename_and_apply_smack_floor_label(shadow_tmp, shadow_path); if (r < 0) return r;