Bug 1470769 - unsafe localization of error() string after EIO in chroot
unsafe localization of error() string after EIO in chroot
Product: Fedora
Classification: Fedora
Component: coreutils (Show other bugs)
x86_64 Linux
unspecified Severity unspecified
: ---
: ---
Assigned To: Kamil Dudka
Fedora Extras Quality Assurance
Depends On:
  Show dependency treegraph
Reported: 2017-07-13 11:38 EDT by John Reiser
Modified: 2017-07-14 07:28 EDT (History)
9 users (show)

See Also:
Fixed In Version:
Doc Type: If docs needed, set a value
Doc Text:
Story Points: ---
Clone Of:
Last Closed: 2017-07-14 07:28:47 EDT
Type: Bug
Regression: ---
Mount Type: ---
Documentation: ---
Verified Versions:
Category: ---
oVirt Team: ---
RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: ---

Attachments (Terms of Use)

  None (edit)
Description John Reiser 2017-07-13 11:38:55 EDT
Description of problem: When chroot invokes execvp() and suffers a failure return because of EIO, then localizing the error string can cause confusion and trouble because it is likely that localization depends on setting up the locale machinery, which depends on I/O, which has just failed.

After EIO, then it is preferable to emit an immediate, non-localized indication 
of the EIO using as few system calls as possible; then [perhaps] resume the regular error processing.  Something in the spirit of:
   write(2, "\nchroot:(raw)EIO\n", 17);
just before the existing
   error (0, errno, _("failed to run command %s"), quote (argv[0]));

Version-Release number of selected component (if applicable):

How reproducible: every time, using deliberate error injection

Steps to Reproduce:
1. Inject a deliberate error.
--- coreutils-8.25/src/chroot.c.orig	2017-07-13 07:43:21.915621653 -0700
+++ coreutils-8.25/src/chroot.c	2017-07-13 07:44:41.806713319 -0700
@@ -420,8 +420,8 @@
   if (uid_set (uid) && setuid (uid))
     error (EXIT_CANCELED, errno, _("failed to set user-ID"));
-  /* Execute the given command.  */
-  execvp (argv[0], argv);
+  /* Inject deliberate error. */  /* Execute the given command.  */
+  errno = EIO;  /* execvp (argv[0], argv);*/
   int exit_status = errno == ENOENT ? EXIT_ENOENT : EXIT_CANNOT_INVOKE;
   error (0, errno, _("failed to run command %s"), quote (argv[0]));


Actual results: Localization of the third argument to error(), namely
   _("failed to run command %s")
uses I/O, namely to set up the locale machinery.

Expected results:  After EIO, then signal the error using as little I/O as possible.

Additional info:
Yes, this is rare.  But not _that_ rare, and anyway it is important because booting a machine into "Rescue mode" and then performing "chroot /mnt/sysimage" in order to fix an installation by running the package manager in its native environment, is prone to EIO if the boot was to a "Live" system stored on a physical DVD.  (Mechanical drive, infrequently used, intensive seeking for tens of seconds, cheap manufacture, etc.)  Of course booting a "Live" system from USB flash memory is preferable, but there are cheap USB flash drives, too.
Comment 1 Kamil Dudka 2017-07-14 07:28:47 EDT
Error messages in coreutils are localized consistently.  I am afraid that it would only cause confusion if we provided localized messages for EPERM but not for EIO.

If you find this feature unsafe, you can simply turn off localization globally:

% export LC_ALL=C

Note You need to log in before you can comment on or make changes to this bug.