Bug 1470769 - unsafe localization of error() string after EIO in chroot
Summary: unsafe localization of error() string after EIO in chroot
Keywords:
Status: CLOSED NOTABUG
Alias: None
Product: Fedora
Classification: Fedora
Component: coreutils
Version: 25
Hardware: x86_64
OS: Linux
unspecified
unspecified
Target Milestone: ---
Assignee: Kamil Dudka
QA Contact: Fedora Extras Quality Assurance
URL:
Whiteboard:
Depends On:
Blocks:
TreeView+ depends on / blocked
 
Reported: 2017-07-13 15:38 UTC by John Reiser
Modified: 2017-07-14 11:28 UTC (History)
9 users (show)

Fixed In Version:
Clone Of:
Environment:
Last Closed: 2017-07-14 11:28:47 UTC
Type: Bug
Embargoed:


Attachments (Terms of Use)

Description John Reiser 2017-07-13 15:38:55 UTC
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):
coreutils-8.25-17.fc25.x86_64


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]));

2.
3.

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 11:28:47 UTC
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.