bug-hurd
[Top][All Lists]
Advanced

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

Re: lost ssh access - where is a log?


From: Sergey Bugaev
Subject: Re: lost ssh access - where is a log?
Date: Tue, 29 Nov 2022 16:24:22 +0300

On Tue, Nov 29, 2022 at 11:47 AM Samuel Thibault
<samuel.thibault@gnu.org> wrote:
> Sergey Bugaev, le mar. 29 nov. 2022 09:22:20 +0300, a ecrit:
> > Hello everyone!
> >
> > I am indeed out of the army, alive and in one piece.
>
> !! \o/ !!
>
> I have to say I was very worried, I'm glad that you are back in one
> piece.

Thank you so much for caring! I am in fact _so_ glad that my online
friends & peers not only remembered me, but actually cared & worried
about me throughout all this.

Fortunately — while this has been a year of my personal hell, of being
mistreated, disrespected, and humiliated — they never sent me to
you-know-where. I spent all the time on a military airdrom near
Moscow. So there's not that much physical injury that could happen to
me, mental health notwithstanding.

> > As for the SSH/arc4random issue: I believe a better workaround would
> > be for glibc to cache the /dev/urandom port between calls to getrandom
> > (), the same way that it caches socket server ports (see
> > hurd/hurdsock.c).
>
> Indeed, that would solve the problem while at the same time optimize
> things.

Well, here's a preliminary patch. Please don't expect it to be any
good, I must have forgotten all the subtleties of glibc development —
those that I managed to learn in the first place — over the year. That
being said, it builds; I haven't tested whether it works.

The existing code supports GRND_RANDOM and GRND_NONBLOCK; the latter
we should still support in some way, the former I'm not sure about,
given that urandom and random are the same thing. Or is that a Debian
thing that glibc should not rely on?

--------------------------- >8 ------------------------------
diff --git a/sysdeps/mach/hurd/getrandom.c b/sysdeps/mach/hurd/getrandom.c
index ad2d3ba3..9c0ea5db 100644
--- a/sysdeps/mach/hurd/getrandom.c
+++ b/sysdeps/mach/hurd/getrandom.c
@@ -16,22 +16,61 @@
    License along with the GNU C Library; if not, see
    <https://www.gnu.org/licenses/>.  */

+#include <hurd.h>
 #include <sys/random.h>
 #include <fcntl.h>
-#include <unistd.h>
-#include <not-cancel.h>
+
+__libc_rwlock_define_initialized (static, lock);
+static file_t random_server;

 extern char *__trivfs_server_name __attribute__((weak));

+static file_t
+get_random_server (int dead)
+{
+  file_t server;
+  int flags;
+
+  if (!dead)
+    {
+      /* Attempt to use the cached port, if any.  */
+      __libc_rwlock_rdlock (lock);
+      server = random_server;
+      if (MACH_PORT_VALID (server))
+        goto out;
+
+      __libc_rwlock_unlock (lock);
+    }
+
+  __libc_rwlock_wrlock (lock);
+  /* Re-check whether the port is still invalid, since someone
+   * could have reset it while we were waiting.  */
+  server = random_server;
+  if (MACH_PORT_VALID (server))
+    goto out;
+
+  flags = O_RDONLY | O_NOCTTY;
+  /* TODO: O_NONBLOCK? */
+  server = random_server = __file_name_lookup ("/dev/urandom", flags, 0);
+
+out:
+  __libc_rwlock_unlock (lock);
+
+  if (server == MACH_PORT_DEAD)
+    server = MACH_PORT_NULL;
+  return server;
+}
+
 /* Write up to LENGTH bytes of randomness starting at BUFFER.
    Return the number of bytes written, or -1 on error.  */
 ssize_t
 __getrandom (void *buffer, size_t length, unsigned int flags)
 {
-  const char *random_source = "/dev/urandom";
-  int open_flags = O_RDONLY | O_CLOEXEC;
-  size_t amount_read;
-  int fd;
+  file_t server;
+  error_t err;
+  int dead = 0;
+  char *data = buffer;
+  mach_msg_type_number_t nread = length;

   if (&__trivfs_server_name && __trivfs_server_name
       && __trivfs_server_name[0] == 'r'
@@ -44,19 +83,33 @@ __getrandom (void *buffer, size_t length, unsigned
int flags)
     /* We are random, don't try to read ourselves!  */
     return length;

-  if (flags & GRND_RANDOM)
-    random_source = "/dev/random";
+again:
+  server = get_random_server (dead);
+  if (!MACH_PORT_VALID (server))
+    return -1;

-  if (flags & GRND_NONBLOCK)
-    open_flags |= O_NONBLOCK;
+  err = __io_read (server, &data, &nread, -1, length);
+  if (!dead && (err == MACH_SEND_INVALID_DEST || err == MIG_SERVER_DIED))
+    {
+      dead = 1;
+      goto again;
+    }

-  fd = __open_nocancel(random_source, open_flags);
-  if (fd == -1)
-    return -1;
+  if (err)
+    return __hurd_fail (err);
+
+  if (data != buffer)
+    {
+      if (nread > length)
+        {
+          __vm_deallocate (__mach_task_self (), (vm_address_t) data, nread);
+          return __hurd_fail (EGRATUITOUS);
+        }
+      memcpy (buffer, data, nread);
+      __vm_deallocate (__mach_task_self (), (vm_address_t) data, nread);
+    }

-  amount_read = __read_nocancel(fd, buffer, length);
-  __close_nocancel_nostatus(fd);
-  return amount_read;
+  return nread;
 }

 libc_hidden_def (__getrandom)

--------------------------- 8< ------------------------------


> I'm wondering, though: does ssh fork-off other processes inside
> the chroot, that might get the same issue?

I don't think it does. In any case, there's nothing for it to exec
inside the chroot, and just forking w/o exec'ing should work, as fork
preserves ports.

Sergey



reply via email to

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