Bug 1380858
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: | |||||
Embargoed: | |||||||
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: