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: Samuel Thibault
Subject: Re: lost ssh access - where is a log?
Date: Wed, 30 Nov 2022 01:31:50 +0100
User-agent: NeoMutt/20170609 (1.8.3)

Sergey Bugaev, le mar. 29 nov. 2022 16:36:58 +0300, a ecrit:
> On Tue, Nov 29, 2022 at 4:24 PM Sergey Bugaev <bugaevc@gmail.com> wrote:
> > 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.
> 
> ...and I already see some of the brokenness. Here's a slightly better version:
> 
> --------------------------- >8 ------------------------------
> diff --git a/sysdeps/mach/hurd/getrandom.c b/sysdeps/mach/hurd/getrandom.c
> index ad2d3ba3..44bf1e8f 100644
> --- a/sysdeps/mach/hurd/getrandom.c
> +++ b/sysdeps/mach/hurd/getrandom.c
> @@ -16,22 +16,65 @@
>     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);
> +
> +  server = random_server;
> +  if (MACH_PORT_VALID (server))
> +    if (!dead)
> +      /* Someone else has obtained a new port while we were
> +         waiting for the lock.  */
> +      goto out;
> +    else
> +      __mach_port_deallocate (__mach_task_self (), server);
> +
> +  flags = O_RDONLY | O_NOCTTY;
> +  /* TODO: O_NONBLOCK? */
> +  server = random_server = __file_name_lookup ("/dev/urandom", flags, 0);

Yes, pass a nonblock parameter and cache both a blocking port and a
non-blocking port.

> +
> +out:
> +  __libc_rwlock_unlock (lock);

Mmm, but here, another thread might be quickly trying that port, getting
an error, and reopen another port, and this port will be undefined.

Either you extend the rwlock section, or (probably simpler), you add a
ref to the port while having the lock, and the caller will release the
ref.

> +  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 +87,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)
> 



reply via email to

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