bug-hurd
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

bug in puts(3) affecting /hurd/init


From: Justus Winter
Subject: bug in puts(3) affecting /hurd/init
Date: Wed, 15 Oct 2014 16:46:50 +0200
User-agent: alot/0.3.5

Hello,

there is a strange bug in puts(3) affecting /hurd/init (or
/hurd/startup if you live on the edge).  It is also sometimes
affecting printf(3), as it is replaced by gcc with a call to puts
under certain conditions (e.g. with a format string ending in '\n'
without any conversion specifiers).

Here is a screenshot of /hurd/startup patched with the patch below:

[... gnumach stuff...]
task loaded: exec /hurd/exec

start ext2fs: Hurd server bootstrap: ext2fs[device:hd0s1] exec startup proc 
auth.

INIT: version 2.88 booting
Using makefile-style concurrent boot in runlevel S.
[...]

Note the '.' after "auth", followed by a newline.  The extra newline
is printed by our runsystem script, as a workaround for this bug.

This is what the shutdown is supposed to look like:

[...]
Deactivating swap...swapoff: /dev/hd0s5: 177152k swap space
done.
Unmounting local filesystems...done.
mount: cannot remount /: Device or resource busy
Will now halt.
startup: notifying pfinet of halt...done
startup: notifying tmpfs none of halt...done
startup: notifying tmpfs none of halt...done
startup: notifying tmpfs none of halt...done
startup: notifying ext2fs device:hd0s1 of halt...done
startup: halting Mach (flags 0x8)...

In contrast, here is a shutdown with the unpatched /hurd/init:

root@debian:~# halt-hurd
init: notifying pfinet of shutdown...init: notifying tmpfs none of 
shutdown...init: notifying tmpfs none of shutdown...init: notifying tmpfs none 
of shutdown...init: notifying ext2fs device:hd0s1 of shutdown...init: halting 
Mach (flags 0x8)...

Note that contrary to my comment in the patch below it isn't only
swallowing the newline, but the whole string (i.e. ".\n" and
"done\n").

I've no idea whats wrong, or why it is only affecting /hurd/startup.

Maybe it's the way /hurd/startup setups stdout.  Here's the code:

  /* Fetch a port to the bootstrap filesystem, the host priv and
     master device ports, and the console.  */
  if (task_get_bootstrap_port (mach_task_self (), &bootport)
      || fsys_getpriv (bootport, &host_priv, &device_master, &fstask)
      || device_open (device_master, D_WRITE, "console", &consdev))
    crash_mach ();
[...]
  stderr = stdout = mach_open_devstream (consdev, "w");
  stdin = mach_open_devstream (consdev, "r");
  if (stdout == NULL || stdin == NULL)
    crash_mach ();
  setbuf (stdout, NULL);

In contrast, here is what libdiskfs does:

      err = get_privileged_ports (NULL, &dev);
      assert_perror (err);
      err = device_open (dev, D_READ|D_WRITE, "console", &cons);
      mach_port_deallocate (mach_task_self (), dev);
      assert_perror (err);
      stdin = mach_open_devstream (cons, "r");
      stdout = stderr = mach_open_devstream (cons, "w");

So, startup calls setbuf while libdiskfs does not.  I once removed
that call, it didn't affect the bug.

Also, startup only passes D_WRITE to device_open, while libdiskfs uses
D_READ|D_WRITE.  This is probably a bug, but I would expect it do
affect reading from stdin (if anything), not writing to stdout.

Thoughts?
Justus

diff --git a/startup/startup.c b/startup/startup.c
index ff58270..e1f07a2 100644
--- a/startup/startup.c
+++ b/startup/startup.c
@@ -1663,3 +1663,10 @@ S_fsys_forward (mach_port_t server, mach_port_t 
requestor,
 {
   return EOPNOTSUPP;
 }
+
+/* XXX: puts is broken, it doesn't print the newline.  */
+int
+puts (const char *s)
+{
+  return printf ("%s%c", s, '\n') == 0? EOF: 1;
+}



reply via email to

[Prev in Thread] Current Thread [Next in Thread]