mirror of
https://github.com/systemd/systemd.git
synced 2026-08-03 22:50:29 +00:00
Merge pull request #26707 from DaanDeMeyer/firstboot-modernize
firstboot: modernize path handling
This commit is contained in:
@@ -80,7 +80,8 @@ int take_etc_passwd_lock(const char *root);
|
||||
#define UID_MAPPED_ROOT ((uid_t) (INT32_MAX-1))
|
||||
#define GID_MAPPED_ROOT ((gid_t) (INT32_MAX-1))
|
||||
|
||||
#define ETC_PASSWD_LOCK_PATH "/etc/.pwd.lock"
|
||||
#define ETC_PASSWD_LOCK_NAME ".pwd.lock"
|
||||
#define ETC_PASSWD_LOCK_PATH "/etc/" ETC_PASSWD_LOCK_NAME
|
||||
|
||||
/* The following macros add 1 when converting things, since UID 0 is a valid UID, while the pointer
|
||||
* NULL is special */
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include "kbd-util.h"
|
||||
#include "libcrypt-util.h"
|
||||
#include "locale-util.h"
|
||||
#include "lock-util.h"
|
||||
#include "main-func.h"
|
||||
#include "memory-util.h"
|
||||
#include "mkdir.h"
|
||||
@@ -228,6 +229,19 @@ static int prompt_loop(const char *text, char **l, unsigned percentage, bool (*i
|
||||
}
|
||||
}
|
||||
|
||||
static int should_configure(int dir_fd, const char *filename) {
|
||||
int r;
|
||||
|
||||
assert(dir_fd >= 0);
|
||||
assert(filename);
|
||||
|
||||
r = faccessat(dir_fd, filename, F_OK, AT_SYMLINK_NOFOLLOW);
|
||||
if (r < 0 && errno != ENOENT)
|
||||
return log_error_errno(errno, "Failed to access %s: %m", filename);
|
||||
|
||||
return r < 0 || arg_force;
|
||||
}
|
||||
|
||||
static bool locale_is_ok(const char *name) {
|
||||
|
||||
if (arg_root)
|
||||
@@ -309,28 +323,34 @@ static int prompt_locale(void) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int process_locale(void) {
|
||||
const char *etc_localeconf;
|
||||
static int process_locale(int rfd) {
|
||||
_cleanup_close_ int pfd = -EBADF;
|
||||
_cleanup_free_ char *f = NULL;
|
||||
char* locales[3];
|
||||
unsigned i = 0;
|
||||
int r;
|
||||
|
||||
etc_localeconf = prefix_roota(arg_root, "/etc/locale.conf");
|
||||
if (laccess(etc_localeconf, F_OK) >= 0 && !arg_force) {
|
||||
log_debug("Found %s, assuming locale information has been configured.",
|
||||
etc_localeconf);
|
||||
return 0;
|
||||
}
|
||||
assert(rfd >= 0);
|
||||
|
||||
if (arg_copy_locale && arg_root) {
|
||||
pfd = chase_and_open_parent_at(rfd, "/etc/locale.conf",
|
||||
CHASE_AT_RESOLVE_IN_ROOT|CHASE_MKDIR_0755|CHASE_WARN,
|
||||
&f);
|
||||
if (pfd < 0)
|
||||
return log_error_errno(pfd, "Failed to chase /etc/locale.conf: %m");
|
||||
|
||||
(void) mkdir_parents(etc_localeconf, 0755);
|
||||
r = copy_file("/etc/locale.conf", etc_localeconf, 0, 0644, COPY_REFLINK);
|
||||
r = should_configure(pfd, f);
|
||||
if (r == 0)
|
||||
log_debug("Found /etc/locale.conf, assuming locale information has been configured.");
|
||||
if (r <= 0)
|
||||
return r;
|
||||
|
||||
if (arg_copy_locale && !dir_fd_is_root(rfd)) {
|
||||
r = copy_file_atomic_at(AT_FDCWD, "/etc/locale.conf", pfd, f, 0644, COPY_REFLINK);
|
||||
if (r != -ENOENT) {
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to copy %s: %m", etc_localeconf);
|
||||
return log_error_errno(r, "Failed to copy host's /etc/locale.conf: %m");
|
||||
|
||||
log_info("%s copied.", etc_localeconf);
|
||||
log_info("Copied host's /etc/locale.conf.");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -349,12 +369,11 @@ static int process_locale(void) {
|
||||
|
||||
locales[i] = NULL;
|
||||
|
||||
(void) mkdir_parents(etc_localeconf, 0755);
|
||||
r = write_env_file(etc_localeconf, locales);
|
||||
r = write_env_file_at(pfd, f, locales);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to write %s: %m", etc_localeconf);
|
||||
return log_error_errno(r, "Failed to write /etc/locale.conf: %m");
|
||||
|
||||
log_info("%s written.", etc_localeconf);
|
||||
log_info("/etc/locale.conf written.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -390,27 +409,33 @@ static int prompt_keymap(void) {
|
||||
kmaps, 60, keymap_is_valid, &arg_keymap);
|
||||
}
|
||||
|
||||
static int process_keymap(void) {
|
||||
const char *etc_vconsoleconf;
|
||||
static int process_keymap(int rfd) {
|
||||
_cleanup_close_ int pfd = -EBADF;
|
||||
_cleanup_free_ char *f = NULL;
|
||||
char **keymap;
|
||||
int r;
|
||||
|
||||
etc_vconsoleconf = prefix_roota(arg_root, "/etc/vconsole.conf");
|
||||
if (laccess(etc_vconsoleconf, F_OK) >= 0 && !arg_force) {
|
||||
log_debug("Found %s, assuming console has been configured.",
|
||||
etc_vconsoleconf);
|
||||
return 0;
|
||||
}
|
||||
assert(rfd >= 0);
|
||||
|
||||
if (arg_copy_keymap && arg_root) {
|
||||
pfd = chase_and_open_parent_at(rfd, "/etc/vconsole.conf",
|
||||
CHASE_AT_RESOLVE_IN_ROOT|CHASE_MKDIR_0755|CHASE_WARN,
|
||||
&f);
|
||||
if (pfd < 0)
|
||||
return log_error_errno(pfd, "Failed to chase /etc/vconsole.conf: %m");
|
||||
|
||||
(void) mkdir_parents(etc_vconsoleconf, 0755);
|
||||
r = copy_file("/etc/vconsole.conf", etc_vconsoleconf, 0, 0644, COPY_REFLINK);
|
||||
r = should_configure(pfd, f);
|
||||
if (r == 0)
|
||||
log_debug("Found /etc/vconsole.conf, assuming console has been configured.");
|
||||
if (r <= 0)
|
||||
return r;
|
||||
|
||||
if (arg_copy_keymap && !dir_fd_is_root(rfd)) {
|
||||
r = copy_file_atomic_at(AT_FDCWD, "/etc/vconsole.conf", pfd, f, 0644, COPY_REFLINK);
|
||||
if (r != -ENOENT) {
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to copy %s: %m", etc_vconsoleconf);
|
||||
return log_error_errno(r, "Failed to copy host's /etc/vconsole.conf: %m");
|
||||
|
||||
log_info("%s copied.", etc_vconsoleconf);
|
||||
log_info("Copied host's /etc/vconsole.conf.");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -426,15 +451,11 @@ static int process_keymap(void) {
|
||||
|
||||
keymap = STRV_MAKE(strjoina("KEYMAP=", arg_keymap));
|
||||
|
||||
r = mkdir_parents(etc_vconsoleconf, 0755);
|
||||
r = write_env_file_at(pfd, f, keymap);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to create the parent directory of %s: %m", etc_vconsoleconf);
|
||||
return log_error_errno(r, "Failed to write /etc/vconsole.conf: %m");
|
||||
|
||||
r = write_env_file(etc_vconsoleconf, keymap);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to write %s: %m", etc_vconsoleconf);
|
||||
|
||||
log_info("%s written.", etc_vconsoleconf);
|
||||
log_info("/etc/vconsole.conf written.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -476,31 +497,39 @@ static int prompt_timezone(void) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int process_timezone(void) {
|
||||
const char *etc_localtime, *e;
|
||||
static int process_timezone(int rfd) {
|
||||
_cleanup_close_ int pfd = -EBADF;
|
||||
_cleanup_free_ char *f = NULL;
|
||||
const char *e;
|
||||
int r;
|
||||
|
||||
etc_localtime = prefix_roota(arg_root, "/etc/localtime");
|
||||
if (laccess(etc_localtime, F_OK) >= 0 && !arg_force) {
|
||||
log_debug("Found %s, assuming timezone has been configured.",
|
||||
etc_localtime);
|
||||
return 0;
|
||||
}
|
||||
assert(rfd >= 0);
|
||||
|
||||
if (arg_copy_timezone && arg_root) {
|
||||
_cleanup_free_ char *p = NULL;
|
||||
pfd = chase_and_open_parent_at(rfd, "/etc/localtime",
|
||||
CHASE_AT_RESOLVE_IN_ROOT|CHASE_MKDIR_0755|CHASE_WARN|CHASE_NOFOLLOW,
|
||||
&f);
|
||||
if (pfd < 0)
|
||||
return log_error_errno(pfd, "Failed to chase /etc/localtime: %m");
|
||||
|
||||
r = readlink_malloc("/etc/localtime", &p);
|
||||
r = should_configure(pfd, f);
|
||||
if (r == 0)
|
||||
log_debug("Found /etc/localtime, assuming timezone has been configured.");
|
||||
if (r <= 0)
|
||||
return r;
|
||||
|
||||
if (arg_copy_timezone && !dir_fd_is_root(rfd)) {
|
||||
_cleanup_free_ char *s = NULL;
|
||||
|
||||
r = readlink_malloc("/etc/localtime", &s);
|
||||
if (r != -ENOENT) {
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to read host timezone: %m");
|
||||
return log_error_errno(r, "Failed to read host's /etc/localtime: %m");
|
||||
|
||||
(void) mkdir_parents(etc_localtime, 0755);
|
||||
r = symlink_atomic(p, etc_localtime);
|
||||
r = symlinkat_atomic_full(s, pfd, f, /* make_relative= */ false);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to create %s symlink: %m", etc_localtime);
|
||||
return log_error_errno(r, "Failed to create /etc/localtime symlink: %m");
|
||||
|
||||
log_info("%s copied.", etc_localtime);
|
||||
log_info("Copied host's /etc/localtime.");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -514,12 +543,11 @@ static int process_timezone(void) {
|
||||
|
||||
e = strjoina("../usr/share/zoneinfo/", arg_timezone);
|
||||
|
||||
(void) mkdir_parents(etc_localtime, 0755);
|
||||
r = symlink_atomic(e, etc_localtime);
|
||||
r = symlinkat_atomic_full(e, pfd, f, /* make_relative= */ false);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to create %s symlink: %m", etc_localtime);
|
||||
return log_error_errno(r, "Failed to create /etc/localtime symlink: %m");
|
||||
|
||||
log_info("%s written", etc_localtime);
|
||||
log_info("/etc/localtime written");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -563,16 +591,24 @@ static int prompt_hostname(void) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int process_hostname(void) {
|
||||
const char *etc_hostname;
|
||||
static int process_hostname(int rfd) {
|
||||
_cleanup_close_ int pfd = -EBADF;
|
||||
_cleanup_free_ char *f = NULL;
|
||||
int r;
|
||||
|
||||
etc_hostname = prefix_roota(arg_root, "/etc/hostname");
|
||||
if (laccess(etc_hostname, F_OK) >= 0 && !arg_force) {
|
||||
log_debug("Found %s, assuming hostname has been configured.",
|
||||
etc_hostname);
|
||||
return 0;
|
||||
}
|
||||
assert(rfd >= 0);
|
||||
|
||||
pfd = chase_and_open_parent_at(rfd, "/etc/hostname",
|
||||
CHASE_AT_RESOLVE_IN_ROOT|CHASE_MKDIR_0755|CHASE_WARN,
|
||||
&f);
|
||||
if (pfd < 0)
|
||||
return log_error_errno(pfd, "Failed to chase /etc/hostname: %m");
|
||||
|
||||
r = should_configure(pfd, f);
|
||||
if (r == 0)
|
||||
log_debug("Found /etc/hostname, assuming hostname has been configured.");
|
||||
if (r <= 0)
|
||||
return r;
|
||||
|
||||
r = prompt_hostname();
|
||||
if (r < 0)
|
||||
@@ -581,39 +617,45 @@ static int process_hostname(void) {
|
||||
if (isempty(arg_hostname))
|
||||
return 0;
|
||||
|
||||
r = write_string_file(etc_hostname, arg_hostname,
|
||||
WRITE_STRING_FILE_CREATE | WRITE_STRING_FILE_SYNC | WRITE_STRING_FILE_MKDIR_0755 |
|
||||
(arg_force ? WRITE_STRING_FILE_ATOMIC : 0));
|
||||
r = write_string_file_at(pfd, f, arg_hostname,
|
||||
WRITE_STRING_FILE_CREATE|WRITE_STRING_FILE_SYNC|WRITE_STRING_FILE_ATOMIC);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to write %s: %m", etc_hostname);
|
||||
return log_error_errno(r, "Failed to write /etc/hostname: %m");
|
||||
|
||||
log_info("%s written.", etc_hostname);
|
||||
log_info("/etc/hostname written.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int process_machine_id(void) {
|
||||
const char *etc_machine_id;
|
||||
static int process_machine_id(int rfd) {
|
||||
_cleanup_close_ int pfd = -EBADF;
|
||||
_cleanup_free_ char *f = NULL;
|
||||
int r;
|
||||
|
||||
etc_machine_id = prefix_roota(arg_root, "/etc/machine-id");
|
||||
if (laccess(etc_machine_id, F_OK) >= 0 && !arg_force) {
|
||||
log_debug("Found %s, assuming machine-id has been configured.",
|
||||
etc_machine_id);
|
||||
return 0;
|
||||
}
|
||||
assert(rfd >= 0);
|
||||
|
||||
pfd = chase_and_open_parent_at(rfd, "/etc/machine-id",
|
||||
CHASE_AT_RESOLVE_IN_ROOT|CHASE_MKDIR_0755|CHASE_WARN,
|
||||
&f);
|
||||
if (pfd < 0)
|
||||
return log_error_errno(pfd, "Failed to chase /etc/machine-id: %m");
|
||||
|
||||
r = should_configure(pfd, f);
|
||||
if (r == 0)
|
||||
log_debug("Found /etc/machine-id, assuming machine-id has been configured.");
|
||||
if (r <= 0)
|
||||
return r;
|
||||
|
||||
if (sd_id128_is_null(arg_machine_id)) {
|
||||
log_debug("Initialization of machine-id was not requested, skipping.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = write_string_file(etc_machine_id, SD_ID128_TO_STRING(arg_machine_id),
|
||||
WRITE_STRING_FILE_CREATE | WRITE_STRING_FILE_SYNC | WRITE_STRING_FILE_MKDIR_0755 |
|
||||
(arg_force ? WRITE_STRING_FILE_ATOMIC : 0));
|
||||
r = write_string_file_at(pfd, "machine-id", SD_ID128_TO_STRING(arg_machine_id),
|
||||
WRITE_STRING_FILE_CREATE|WRITE_STRING_FILE_SYNC|WRITE_STRING_FILE_ATOMIC);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to write machine id: %m");
|
||||
return log_error_errno(r, "Failed to write /etc/machine id: %m");
|
||||
|
||||
log_info("%s written.", etc_machine_id);
|
||||
log_info("/etc/machine-id written.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -681,7 +723,7 @@ static int prompt_root_password(void) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int find_shell(const char *path, const char *root) {
|
||||
static int find_shell(int rfd, const char *path) {
|
||||
int r;
|
||||
|
||||
assert(path);
|
||||
@@ -689,17 +731,14 @@ static int find_shell(const char *path, const char *root) {
|
||||
if (!valid_shell(path))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "%s is not a valid shell", path);
|
||||
|
||||
r = chase(path, root, CHASE_PREFIX_ROOT, NULL, NULL);
|
||||
if (r < 0) {
|
||||
const char *p;
|
||||
p = prefix_roota(root, path);
|
||||
return log_error_errno(r, "Failed to resolve shell %s: %m", p);
|
||||
}
|
||||
r = chaseat(rfd, path, CHASE_AT_RESOLVE_IN_ROOT, NULL, NULL);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to resolve shell %s: %m", path);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int prompt_root_shell(void) {
|
||||
static int prompt_root_shell(int rfd) {
|
||||
int r;
|
||||
|
||||
if (arg_root_shell)
|
||||
@@ -733,7 +772,7 @@ static int prompt_root_shell(void) {
|
||||
break;
|
||||
}
|
||||
|
||||
r = find_shell(s, arg_root);
|
||||
r = find_shell(rfd, s);
|
||||
if (r < 0)
|
||||
continue;
|
||||
|
||||
@@ -744,18 +783,21 @@ static int prompt_root_shell(void) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int write_root_passwd(const char *passwd_path, const char *password, const char *shell) {
|
||||
static int write_root_passwd(int etc_fd, const char *password, const char *shell) {
|
||||
_cleanup_fclose_ FILE *original = NULL, *passwd = NULL;
|
||||
_cleanup_(unlink_and_freep) char *passwd_tmp = NULL;
|
||||
int r;
|
||||
|
||||
assert(password);
|
||||
|
||||
r = fopen_temporary_label("/etc/passwd", passwd_path, &passwd, &passwd_tmp);
|
||||
r = fopen_temporary_at_label(etc_fd, "passwd", "passwd", &passwd, &passwd_tmp);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
original = fopen(passwd_path, "re");
|
||||
r = xfopenat(etc_fd, "passwd", "re", O_NOFOLLOW, &original);
|
||||
if (r < 0 && r != -ENOENT)
|
||||
return r;
|
||||
|
||||
if (original) {
|
||||
struct passwd *i;
|
||||
|
||||
@@ -805,25 +847,28 @@ static int write_root_passwd(const char *passwd_path, const char *password, cons
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = rename_and_apply_smack_floor_label(passwd_tmp, passwd_path);
|
||||
r = renameat_and_apply_smack_floor_label(etc_fd, passwd_tmp, etc_fd, "passwd");
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int write_root_shadow(const char *shadow_path, const char *hashed_password) {
|
||||
static int write_root_shadow(int etc_fd, const char *hashed_password) {
|
||||
_cleanup_fclose_ FILE *original = NULL, *shadow = NULL;
|
||||
_cleanup_(unlink_and_freep) char *shadow_tmp = NULL;
|
||||
int r;
|
||||
|
||||
assert(hashed_password);
|
||||
|
||||
r = fopen_temporary_label("/etc/shadow", shadow_path, &shadow, &shadow_tmp);
|
||||
r = fopen_temporary_at_label(etc_fd, "shadow", "shadow", &shadow, &shadow_tmp);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
original = fopen(shadow_path, "re");
|
||||
r = xfopenat(etc_fd, "shadow", "re", O_NOFOLLOW, &original);
|
||||
if (r < 0 && r != -ENOENT)
|
||||
return r;
|
||||
|
||||
if (original) {
|
||||
struct spwd *i;
|
||||
|
||||
@@ -874,26 +919,46 @@ static int write_root_shadow(const char *shadow_path, const char *hashed_passwor
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = rename_and_apply_smack_floor_label(shadow_tmp, shadow_path);
|
||||
r = renameat_and_apply_smack_floor_label(etc_fd, shadow_tmp, etc_fd, "shadow");
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int process_root_account(void) {
|
||||
_cleanup_close_ int lock = -EBADF;
|
||||
static int process_root_account(int rfd) {
|
||||
_cleanup_close_ int pfd = -EBADF;
|
||||
_cleanup_(release_lock_file) LockFile lock = LOCK_FILE_INIT;
|
||||
_cleanup_(erase_and_freep) char *_hashed_password = NULL;
|
||||
const char *password, *hashed_password;
|
||||
const char *etc_passwd, *etc_shadow;
|
||||
int r;
|
||||
int k = 0, r;
|
||||
|
||||
etc_passwd = prefix_roota(arg_root, "/etc/passwd");
|
||||
etc_shadow = prefix_roota(arg_root, "/etc/shadow");
|
||||
assert(rfd >= 0);
|
||||
|
||||
if (laccess(etc_passwd, F_OK) >= 0 && laccess(etc_shadow, F_OK) >= 0 && !arg_force) {
|
||||
log_debug("Found %s and %s, assuming root account has been initialized.",
|
||||
etc_passwd, etc_shadow);
|
||||
pfd = chase_and_open_parent_at(rfd, "/etc/passwd",
|
||||
CHASE_AT_RESOLVE_IN_ROOT|CHASE_MKDIR_0755|CHASE_WARN|CHASE_NOFOLLOW,
|
||||
NULL);
|
||||
if (pfd < 0)
|
||||
return log_error_errno(pfd, "Failed to chase /etc/passwd: %m");
|
||||
|
||||
/* Ensure that passwd and shadow are in the same directory and are not symlinks. */
|
||||
|
||||
FOREACH_STRING(s, "passwd", "shadow") {
|
||||
r = verify_regular_at(pfd, s, /* follow = */ false);
|
||||
if (IN_SET(r, -EISDIR, -ELOOP, -EBADFD))
|
||||
return log_error_errno(r, "/etc/%s is not a regular file", s);
|
||||
if (r < 0 && r != -ENOENT)
|
||||
return log_error_errno(r, "Failed to check whether /etc/%s is a regular file: %m", s);
|
||||
|
||||
r = should_configure(pfd, s);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
k += r;
|
||||
}
|
||||
|
||||
if (k == 0) {
|
||||
log_debug("Found /etc/passwd and /etc/shadow, assuming root account has been initialized.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -904,11 +969,11 @@ static int process_root_account(void) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
lock = take_etc_passwd_lock(arg_root);
|
||||
if (lock < 0)
|
||||
return log_error_errno(lock, "Failed to take a lock on %s: %m", etc_passwd);
|
||||
r = make_lock_file_at(pfd, ETC_PASSWD_LOCK_NAME, LOCK_EX, &lock);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to take a lock on /etc/passwd: %m");
|
||||
|
||||
if (arg_copy_root_shell && arg_root) {
|
||||
if (arg_copy_root_shell && !dir_fd_is_root(rfd)) {
|
||||
struct passwd *p;
|
||||
|
||||
errno = 0;
|
||||
@@ -921,11 +986,11 @@ static int process_root_account(void) {
|
||||
return log_oom();
|
||||
}
|
||||
|
||||
r = prompt_root_shell();
|
||||
r = prompt_root_shell(rfd);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (arg_copy_root_password && arg_root) {
|
||||
if (arg_copy_root_password && !dir_fd_is_root(rfd)) {
|
||||
struct spwd *p;
|
||||
|
||||
errno = 0;
|
||||
@@ -960,43 +1025,50 @@ static int process_root_account(void) {
|
||||
else
|
||||
password = hashed_password = PASSWORD_LOCKED_AND_INVALID;
|
||||
|
||||
r = write_root_passwd(etc_passwd, password, arg_root_shell);
|
||||
r = write_root_passwd(pfd, password, arg_root_shell);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to write %s: %m", etc_passwd);
|
||||
return log_error_errno(r, "Failed to write /etc/passwd: %m");
|
||||
|
||||
log_info("%s written", etc_passwd);
|
||||
log_info("/etc/passwd written.");
|
||||
|
||||
r = write_root_shadow(etc_shadow, hashed_password);
|
||||
r = write_root_shadow(pfd, hashed_password);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to write %s: %m", etc_shadow);
|
||||
return log_error_errno(r, "Failed to write /etc/shadow: %m");
|
||||
|
||||
log_info("%s written.", etc_shadow);
|
||||
log_info("/etc/shadow written.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int process_kernel_cmdline(void) {
|
||||
const char *etc_kernel_cmdline;
|
||||
static int process_kernel_cmdline(int rfd) {
|
||||
_cleanup_close_ int pfd = -EBADF;
|
||||
_cleanup_free_ char *f = NULL;
|
||||
int r;
|
||||
|
||||
etc_kernel_cmdline = prefix_roota(arg_root, "/etc/kernel/cmdline");
|
||||
if (laccess(etc_kernel_cmdline, F_OK) >= 0 && !arg_force) {
|
||||
log_debug("Found %s, assuming kernel has been configured.",
|
||||
etc_kernel_cmdline);
|
||||
return 0;
|
||||
}
|
||||
assert(rfd >= 0);
|
||||
|
||||
pfd = chase_and_open_parent_at(rfd, "/etc/kernel/cmdline",
|
||||
CHASE_AT_RESOLVE_IN_ROOT|CHASE_MKDIR_0755|CHASE_WARN,
|
||||
&f);
|
||||
if (pfd < 0)
|
||||
return log_error_errno(pfd, "Failed to chase /etc/kernel/cmdline: %m");
|
||||
|
||||
r = should_configure(pfd, f);
|
||||
if (r == 0)
|
||||
log_debug("Found /etc/kernel/cmdline, assuming kernel command line has been configured.");
|
||||
if (r <= 0)
|
||||
return r;
|
||||
|
||||
if (!arg_kernel_cmdline) {
|
||||
log_debug("Creation of /etc/kernel/cmdline was not requested, skipping.");
|
||||
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));
|
||||
r = write_string_file_at(pfd, "cmdline", arg_kernel_cmdline,
|
||||
WRITE_STRING_FILE_CREATE|WRITE_STRING_FILE_SYNC|WRITE_STRING_FILE_ATOMIC);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to write %s: %m", etc_kernel_cmdline);
|
||||
return log_error_errno(r, "Failed to write /etc/kernel/cmdline: %m");
|
||||
|
||||
log_info("%s written.", etc_kernel_cmdline);
|
||||
log_info("/etc/kernel/cmdline written.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1210,10 +1282,6 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
break;
|
||||
|
||||
case ARG_ROOT_SHELL:
|
||||
r = find_shell(optarg, arg_root);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = free_and_strdup(&arg_root_shell, optarg);
|
||||
if (r < 0)
|
||||
return log_oom();
|
||||
@@ -1351,6 +1419,7 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
static int run(int argc, char *argv[]) {
|
||||
_cleanup_(loop_device_unrefp) LoopDevice *loop_device = NULL;
|
||||
_cleanup_(umount_and_rmdir_and_freep) char *unlink_dir = NULL;
|
||||
_cleanup_close_ int rfd = -EBADF;
|
||||
int r;
|
||||
|
||||
r = parse_argv(argc, argv);
|
||||
@@ -1389,7 +1458,7 @@ static int run(int argc, char *argv[]) {
|
||||
DISSECT_IMAGE_FSCK |
|
||||
DISSECT_IMAGE_GROWFS,
|
||||
&unlink_dir,
|
||||
/* ret_dir_fd= */ NULL,
|
||||
&rfd,
|
||||
&loop_device);
|
||||
if (r < 0)
|
||||
return r;
|
||||
@@ -1397,33 +1466,45 @@ static int run(int argc, char *argv[]) {
|
||||
arg_root = strdup(unlink_dir);
|
||||
if (!arg_root)
|
||||
return log_oom();
|
||||
} else {
|
||||
rfd = open(empty_to_root(arg_root), O_DIRECTORY|O_CLOEXEC);
|
||||
if (rfd < 0)
|
||||
return log_error_errno(errno, "Failed to open %s: %m", empty_to_root(arg_root));
|
||||
}
|
||||
|
||||
r = process_locale();
|
||||
LOG_SET_PREFIX(arg_image ?: arg_root);
|
||||
|
||||
if (arg_root_shell) {
|
||||
r = find_shell(rfd, arg_root_shell);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
r = process_locale(rfd);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = process_keymap();
|
||||
r = process_keymap(rfd);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = process_timezone();
|
||||
r = process_timezone(rfd);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = process_hostname();
|
||||
r = process_hostname(rfd);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = process_machine_id();
|
||||
r = process_machine_id(rfd);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = process_root_account();
|
||||
r = process_root_account(rfd);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = process_kernel_cmdline();
|
||||
r = process_kernel_cmdline(rfd);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user