242 lines
9.8 KiB
Diff
242 lines
9.8 KiB
Diff
|
From ee9b9b1241a427732781173caf9db611757c5152 Mon Sep 17 00:00:00 2001
|
||
|
From: Daniel Molkentin <dmolkentin@suse.com>
|
||
|
Date: Thu, 1 Oct 2020 17:12:26 +0200
|
||
|
Subject: [PATCH] dracut-install: fix edge-case regression with weak modules
|
||
|
|
||
|
This was introduced with 6dafdda4a6bdb8721133e4267553c5d86564f9e8, but
|
||
|
is actually caused by the fact that modules that have already been
|
||
|
installed cause dracut_install() to return without adding the module
|
||
|
to the hashmap. This can happen if an earlier-run dracut module chose
|
||
|
to install the same module. Now modprobe statements like:
|
||
|
|
||
|
softdep usb_storage post: uas
|
||
|
softdep uas pre: usb_storage
|
||
|
|
||
|
(which look weird, but are perfectly valid), cause
|
||
|
dracut_install() to enter an infinite recursion if and only if
|
||
|
at least one of the files has previously been installed by another
|
||
|
module.
|
||
|
|
||
|
Fix this by also adding already installed modules to the hashmap.
|
||
|
---
|
||
|
install/dracut-install.c | 176 +++++++++++++++++++++++------------------------
|
||
|
1 file changed, 88 insertions(+), 88 deletions(-)
|
||
|
|
||
|
diff --git a/install/dracut-install.c b/install/dracut-install.c
|
||
|
index ea0668b8..97c75dbd 100644
|
||
|
--- a/install/dracut-install.c
|
||
|
+++ b/install/dracut-install.c
|
||
|
@@ -810,123 +810,123 @@ static int dracut_install(const char *orig_src, const char *orig_dst, bool isdir
|
||
|
log_debug("'%s' already exists", fulldstpath);
|
||
|
|
||
|
/* dst does already exist */
|
||
|
- return ret;
|
||
|
- }
|
||
|
+ } else {
|
||
|
|
||
|
- /* check destination directory */
|
||
|
- fulldstdir = strdup(fulldstpath);
|
||
|
- if (!fulldstdir) {
|
||
|
- log_error("Out of memory!");
|
||
|
- return 1;
|
||
|
- }
|
||
|
- fulldstdir[dir_len(fulldstdir)] = '\0';
|
||
|
+ /* check destination directory */
|
||
|
+ fulldstdir = strdup(fulldstpath);
|
||
|
+ if (!fulldstdir) {
|
||
|
+ log_error("Out of memory!");
|
||
|
+ return 1;
|
||
|
+ }
|
||
|
+ fulldstdir[dir_len(fulldstdir)] = '\0';
|
||
|
|
||
|
- ret = stat(fulldstdir, &db);
|
||
|
+ ret = stat(fulldstdir, &db);
|
||
|
|
||
|
- if (ret < 0) {
|
||
|
- _cleanup_free_ char *dname = NULL;
|
||
|
+ if (ret < 0) {
|
||
|
+ _cleanup_free_ char *dname = NULL;
|
||
|
|
||
|
- if (errno != ENOENT) {
|
||
|
- log_error("ERROR: stat '%s': %m", fulldstdir);
|
||
|
- return 1;
|
||
|
- }
|
||
|
- /* create destination directory */
|
||
|
- log_debug("dest dir '%s' does not exist", fulldstdir);
|
||
|
- dname = strdup(dst);
|
||
|
- if (!dname)
|
||
|
- return 1;
|
||
|
+ if (errno != ENOENT) {
|
||
|
+ log_error("ERROR: stat '%s': %m", fulldstdir);
|
||
|
+ return 1;
|
||
|
+ }
|
||
|
+ /* create destination directory */
|
||
|
+ log_debug("dest dir '%s' does not exist", fulldstdir);
|
||
|
+ dname = strdup(dst);
|
||
|
+ if (!dname)
|
||
|
+ return 1;
|
||
|
|
||
|
- dname[dir_len(dname)] = '\0';
|
||
|
- ret = dracut_install(dname, dname, true, false, true);
|
||
|
+ dname[dir_len(dname)] = '\0';
|
||
|
+ ret = dracut_install(dname, dname, true, false, true);
|
||
|
|
||
|
- if (ret != 0) {
|
||
|
- log_error("ERROR: failed to create directory '%s'", fulldstdir);
|
||
|
- return 1;
|
||
|
+ if (ret != 0) {
|
||
|
+ log_error("ERROR: failed to create directory '%s'", fulldstdir);
|
||
|
+ return 1;
|
||
|
+ }
|
||
|
}
|
||
|
- }
|
||
|
|
||
|
- if (src_isdir) {
|
||
|
- if (dst_exists) {
|
||
|
- if (S_ISDIR(sb.st_mode)) {
|
||
|
- log_debug("dest dir '%s' already exists", fulldstpath);
|
||
|
- return 0;
|
||
|
+ if (src_isdir) {
|
||
|
+ if (dst_exists) {
|
||
|
+ if (S_ISDIR(sb.st_mode)) {
|
||
|
+ log_debug("dest dir '%s' already exists", fulldstpath);
|
||
|
+ return 0;
|
||
|
+ }
|
||
|
+ log_error("dest dir '%s' already exists but is not a directory", fulldstpath);
|
||
|
+ return 1;
|
||
|
}
|
||
|
- log_error("dest dir '%s' already exists but is not a directory", fulldstpath);
|
||
|
- return 1;
|
||
|
- }
|
||
|
|
||
|
- log_info("mkdir '%s'", fulldstpath);
|
||
|
- ret = dracut_mkdir(fulldstpath);
|
||
|
- if (ret == 0) {
|
||
|
- i = strdup(dst);
|
||
|
- if (!i)
|
||
|
- return -ENOMEM;
|
||
|
+ log_info("mkdir '%s'", fulldstpath);
|
||
|
+ ret = dracut_mkdir(fulldstpath);
|
||
|
+ if (ret == 0) {
|
||
|
+ i = strdup(dst);
|
||
|
+ if (!i)
|
||
|
+ return -ENOMEM;
|
||
|
|
||
|
- hashmap_put(items, i, i);
|
||
|
+ hashmap_put(items, i, i);
|
||
|
+ }
|
||
|
+ return ret;
|
||
|
}
|
||
|
- return ret;
|
||
|
- }
|
||
|
|
||
|
- /* ready to install src */
|
||
|
+ /* ready to install src */
|
||
|
|
||
|
- if (src_islink) {
|
||
|
- _cleanup_free_ char *abspath = NULL;
|
||
|
+ if (src_islink) {
|
||
|
+ _cleanup_free_ char *abspath = NULL;
|
||
|
|
||
|
- abspath = get_real_file(src, false);
|
||
|
+ abspath = get_real_file(src, false);
|
||
|
|
||
|
- if (abspath == NULL)
|
||
|
- return 1;
|
||
|
+ if (abspath == NULL)
|
||
|
+ return 1;
|
||
|
|
||
|
- if (dracut_install(abspath, abspath, false, resolvedeps, hashdst)) {
|
||
|
- log_debug("'%s' install error", abspath);
|
||
|
- return 1;
|
||
|
- }
|
||
|
+ if (dracut_install(abspath, abspath, false, resolvedeps, hashdst)) {
|
||
|
+ log_debug("'%s' install error", abspath);
|
||
|
+ return 1;
|
||
|
+ }
|
||
|
|
||
|
- if (lstat(abspath, &sb) != 0) {
|
||
|
- log_debug("lstat '%s': %m", abspath);
|
||
|
- return 1;
|
||
|
- }
|
||
|
+ if (lstat(abspath, &sb) != 0) {
|
||
|
+ log_debug("lstat '%s': %m", abspath);
|
||
|
+ return 1;
|
||
|
+ }
|
||
|
|
||
|
- if (lstat(fulldstpath, &sb) != 0) {
|
||
|
- _cleanup_free_ char *absdestpath = NULL;
|
||
|
+ if (lstat(fulldstpath, &sb) != 0) {
|
||
|
+ _cleanup_free_ char *absdestpath = NULL;
|
||
|
|
||
|
- ret = asprintf(&absdestpath, "%s/%s", destrootdir, (abspath[0]=='/' ? (abspath+1) : abspath) + sysrootdirlen);
|
||
|
- if (ret < 0) {
|
||
|
- log_error("Out of memory!");
|
||
|
- exit(EXIT_FAILURE);
|
||
|
+ ret = asprintf(&absdestpath, "%s/%s", destrootdir, (abspath[0]=='/' ? (abspath+1) : abspath) + sysrootdirlen);
|
||
|
+ if (ret < 0) {
|
||
|
+ log_error("Out of memory!");
|
||
|
+ exit(EXIT_FAILURE);
|
||
|
+ }
|
||
|
+
|
||
|
+ ln_r(absdestpath, fulldstpath);
|
||
|
}
|
||
|
|
||
|
- ln_r(absdestpath, fulldstpath);
|
||
|
- }
|
||
|
+ if (arg_hmac) {
|
||
|
+ /* copy .hmac files also */
|
||
|
+ hmac_install(src, dst, NULL);
|
||
|
+ }
|
||
|
|
||
|
- if (arg_hmac) {
|
||
|
- /* copy .hmac files also */
|
||
|
- hmac_install(src, dst, NULL);
|
||
|
+ return 0;
|
||
|
}
|
||
|
|
||
|
- return 0;
|
||
|
- }
|
||
|
-
|
||
|
- if (src_mode & (S_IXUSR | S_IXGRP | S_IXOTH)) {
|
||
|
- if (resolvedeps)
|
||
|
- ret += resolve_deps(fullsrcpath + sysrootdirlen);
|
||
|
- if (arg_hmac) {
|
||
|
- /* copy .hmac files also */
|
||
|
- hmac_install(src, dst, NULL);
|
||
|
+ if (src_mode & (S_IXUSR | S_IXGRP | S_IXOTH)) {
|
||
|
+ if (resolvedeps)
|
||
|
+ ret += resolve_deps(fullsrcpath + sysrootdirlen);
|
||
|
+ if (arg_hmac) {
|
||
|
+ /* copy .hmac files also */
|
||
|
+ hmac_install(src, dst, NULL);
|
||
|
+ }
|
||
|
}
|
||
|
- }
|
||
|
|
||
|
- log_debug("dracut_install ret = %d", ret);
|
||
|
+ log_debug("dracut_install ret = %d", ret);
|
||
|
|
||
|
- if (arg_hostonly && !arg_module)
|
||
|
- mark_hostonly(dst);
|
||
|
+ if (arg_hostonly && !arg_module)
|
||
|
+ mark_hostonly(dst);
|
||
|
|
||
|
- if (isdir) {
|
||
|
- log_info("mkdir '%s'", fulldstpath);
|
||
|
- ret += dracut_mkdir(fulldstpath);
|
||
|
- } else {
|
||
|
- log_info("cp '%s' '%s'", fullsrcpath, fulldstpath);
|
||
|
- ret += cp(fullsrcpath, fulldstpath);
|
||
|
+ if (isdir) {
|
||
|
+ log_info("mkdir '%s'", fulldstpath);
|
||
|
+ ret += dracut_mkdir(fulldstpath);
|
||
|
+ } else {
|
||
|
+ log_info("cp '%s' '%s'", fullsrcpath, fulldstpath);
|
||
|
+ ret += cp(fullsrcpath, fulldstpath);
|
||
|
+ }
|
||
|
}
|
||
|
|
||
|
if (ret == 0) {
|
||
|
|