| Summary: | Race within conf_reload_path() results in a kernel panic | ||||||
|---|---|---|---|---|---|---|---|
| Product: | Red Hat Enterprise Linux 6 | Reporter: | Kyle Walker <kwalker> | ||||
| Component: | upstart | Assignee: | Lukáš Nykrýn <lnykryn> | ||||
| Status: | CLOSED ERRATA | QA Contact: | Frantisek Sumsal <fsumsal> | ||||
| Severity: | urgent | Docs Contact: | |||||
| Priority: | unspecified | ||||||
| Version: | 6.9 | CC: | cww, fsorenso, fsumsal, gkeegan, jkurik, tbowling | ||||
| Target Milestone: | rc | Keywords: | Reproducer | ||||
| Target Release: | --- | ||||||
| Hardware: | Unspecified | ||||||
| OS: | Unspecified | ||||||
| Whiteboard: | |||||||
| Fixed In Version: | upstart-0.6.5-17.el6 | Doc Type: | If docs needed, set a value | ||||
| Doc Text: | Story Points: | --- | |||||
| Clone Of: | Environment: | ||||||
| Last Closed: | 2018-06-19 05:20:15 UTC | Type: | Bug | ||||
| Regression: | --- | Mount Type: | --- | ||||
| Documentation: | --- | CRM: | |||||
| Verified Versions: | Category: | --- | |||||
| oVirt Team: | --- | RHEL 7.3 requirements from Atomic Host: | |||||
| Cloudforms Team: | --- | Target Upstream Version: | |||||
| Bug Depends On: | |||||||
| Bug Blocks: | 1374441, 1461138, 1494481 | ||||||
| Attachments: |
|
||||||
diff --git a/init/conf.c b/init/conf.c
index 215effa..88f13b8 100644
--- a/init/conf.c
+++ b/init/conf.c
@@ -771,6 +771,8 @@ error:
_("Error while loading configuration file"),
err->message);
nih_free (err);
+
+ file = (ConfFile *)nih_hash_lookup (source->files, new_path);
if (file)
nih_unref (file, source);
}
Since the problem described in this bug report should be resolved in a recent advisory, it has been closed with a resolution of ERRATA. For information on the advisory, and where to find the updated files, follow the link below. If the solution does not work for you, open a new bug report. https://access.redhat.com/errata/RHBA-2018:1903 |
Created attachment 1206354 [details] Reproducer utility created by Frank Sorenson Description of problem: Within conf_reload_path(), if an override is loaded immediately preceding the underlying configuration file, a race condition can result in a kernel panic. Using the following files as examples: /etc/init/control-alt-delete.conf /etc/init/control-alt-delete.override 1) A override write completes, exercising conf_reload_path() for the underlying configuration file following: conf_create_modify_handler <snip> nih_debug ("Loading configuration and override files for %s", path); /* load conf file */ nih_debug ("Loading configuration file %s", path); ret = conf_reload_path (source, path, NULL); if (ret < 0) { error_path = path; goto error; } /* ensure we ignore directory changes (which won't have overrides. */ if (is_conf_file_std (path)) { struct stat st; if (stat (new_path, &st) == 0) { /* overlay override settings */ nih_debug ("Loading override file %s for %s", new_path, path); ret = conf_reload_path (source, path, new_path); if (ret < 0) { error_path = new_path; goto error; } } } <snip> 2) The .conf file is the first path given to conf_reload_path() which subsequently issues a nih_unref() in: conf_reload_path <snip> path_to_load = ( override_path ? override_path : path); /* If there is no corresponding override file, look up the old * conf file in memory, and then free it. In cases of failure, * we discard it anyway, so there's no particular reason * to keep it around anymore. */ file = (ConfFile *)nih_hash_lookup (source->files, path); if (! override_path && file) nih_unref (file, source); /* Read the file into memory for parsing, if this fails we don't * bother creating a new ConfFile structure for it and bail out * now. */ buf = nih_file_read (NULL, path_to_load, &len); if (! buf) return -1; <snip> 3) In the last nih_file_read() the .conf file is overwritten between the two operations: nih_file_read() <snip> if (fstat (fileno (fp), &statbuf) < 0) goto error; <snip> if (fread (file, 1, statbuf.st_size, fp) != (size_t)statbuf.st_size) { errno = EILSEQ; goto error; } <snip> 4) Following the above EILSEQ being returned, the already nih_unref()'d file structure is again issued a nih_unref() when returning to conf_create_modify_handler() in: conf_create_modify_handler <snip> /* load conf file */ nih_debug ("Loading configuration file %s", path); ret = conf_reload_path (source, path, NULL); if (ret < 0) { error_path = path; goto error; } <snip> error: { NihError *err; err = nih_error_get (); nih_error ("%s: %s: %s", error_path, _("Error while loading configuration file"), err->message); nih_free (err); if (file) nih_unref (file, source); } } <snip> Version-Release number of selected component (if applicable): upstart-0.6.5-16.el6 How reproducible: Intermittently Steps to Reproduce: 1. Copy an override file to /etc/init/control-alt-delete.override 2. Before upstart loads the override, replace the undelrying /etc/init/control-alt-delete.conf with an empty file 3. Actual results: Periodically, a kernel panic is encountered Expected results: The system continues operation Additional info: