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