DPDK patches and discussions
 help / color / mirror / Atom feed
From: "Mattias Rönnblom" <mattias.ronnblom@ericsson.com>
To: Dan Gora <dg@adax.com>
Cc: "dev@dpdk.org" <dev@dpdk.org>,
	David Marchand <david.marchand@redhat.com>,
	 Jerin Jacob <jerinjacobk@gmail.com>
Subject: Re: [dpdk-dev] [PATCH 2/2] eal: resolve getentropy at run time for random seed
Date: Wed, 22 Apr 2020 20:14:30 +0000	[thread overview]
Message-ID: <80e5cf97-feae-c753-5c65-4f3b121729f3@ericsson.com> (raw)
In-Reply-To: <CAGyogRb1N3X6A2yhX0-9611AOdMaHQf91HBi+zGb144DT-LLkg@mail.gmail.com>

On 2020-04-22 19:44, Dan Gora wrote:
> On Wed, Apr 22, 2020 at 5:28 AM Mattias Rönnblom
> <mattias.ronnblom@ericsson.com> wrote:
>> On 2020-04-21 21:54, Dan Gora wrote:
>>> The getentropy() function was introduced into glibc v2.25 and so is
>>> not available on all supported platforms.  Previously, if DPDK was
>>> compiled (using meson) on a system which has getentropy(), it would
>>> introduce a dependency on glibc v2.25 which would prevent that binary
>>> from running on a system with an older glibc.  Similarly if DPDK was
>>> compiled on a system which did not have getentropy(), getentropy()
>>> could not be used even if the execution system supported it.
>>>
>>> Introduce a new static function, __rte_getentropy() which will try to
>>> resolve the getentropy() function dynamically using dlopen()/dlsym(),
>>> returning failure if the getentropy() function cannot be resolved or
>>> if it fails.
>>
>> Two other options: providing a DPDK-native syscall wrapper for
>> getrandom(), or falling back to reading /dev/urandom. Have you
>> considered any of those two options? If so, why do you prefer
>> dlopen()/dlsym()?
> I didn't give any thought at all to using /dev/urandom.  The goal was
> not really to change how the thing worked, just to remove the
> dependency on glibc 2.25.


/dev/urandom is basically only a different interface to the same 
underlying mechanism.

Such an alternative would look something like:

static int
getentropy(void *buffer, size_t length)
{
         int rc = -1;
         int old_errno = errno;
         int fd;

         fd = open("/dev/urandom", O_RDONLY);

         if (fd < 0)
                 goto out;

         if (read(fd, buffer, length) != length)
                 goto out_close;

         rc = 0;

out_close:
         close(fd);
out:
         errno = old_errno;

         return rc;
}


> Using a syscall wrapper is not really going to be any easier, and in
> fact probably more complicated.  Here is the code in glibc for
> getentropy():
>
> int
> getentropy (void *buffer, size_t length)
> {
>    /* The interface is documented to return EIO for buffer lengths
>       longer than 256 bytes.  */
>    if (length > 256)
>      {
>        __set_errno (EIO);
>        return -1;
>      }
>
>    /* Try to fill the buffer completely.  Even with the 256 byte limit
>       above, we might still receive an EINTR error (when blocking
>       during boot).  */
>    void *end = buffer + length;
>    while (buffer < end)
>      {
>        /* NB: No cancellation point.  */
>        ssize_t bytes = INLINE_SYSCALL_CALL (getrandom, buffer, end - buffer, 0);
>        if (bytes < 0)
>          {
>            if (errno == EINTR)
>              /* Try again if interrupted by a signal.  */
>              continue;
>            else
>              return -1;
>          }
>        if (bytes == 0)
>          {
>            /* No more bytes available.  This should not happen under
>               normal circumstances.  */
>            __set_errno (EIO);
>            return -1;
>          }
>        /* Try again in case of a short read.  */
>        buffer += bytes;
>      }
>    return 0;
> }
>
> __rte_getentropy() is easier than this.  Plus the syscall interface
> does not solve the problem of being able to compile on a system with
> the syscall and run it on a system without it or vice versa, which is
> what I was trying to solve.
>
>> Failure to run on old libc seems like a non-issue to me.
> Well, again, it's a new dependency that didn't exist before.. We sell
> to telco customers, so we have to support 10s of different target
> platforms of various ages.  If they update their system, we'd have to
> recompile our code to be able to use getentropy().  Similarly, if we
> compiled on a system which has getentropy(), but the target system
> doesn't, then they cannot run our binary because of the glibc 2.25
> dependency.  That means that we have to have separate versions with
> and without getentropy().  It's a maintenance headache for no real
> benefit.


I'm not sure I follow. Why would you need to recompile DPDK in case they 
upgrade their system? It sounds like you care about initial seeding, 
since you want getentropy() if it exists, but then in the next paragraph 
you want to throw it out, so I'm a little confused.


Why doesn't the standard practice of compiling against the oldest 
supported libc work for you?


> To my mind, since getentropy() can block it seems like it would
> probably be better to just remove it entirely, but I suppose that's up
> to the person(s) who put it in in the first place.


Maybe I'm wrong, but I found it unlikely that a DPDK application would 
start before the entropy pool was initialized. After this point, 
getentropy() will not block. Do you consider this a real problem?


>>> This also allows getentropy() to be used as the random seed source
>>> when the traditional Makefile build for DPDK is used.
>>>
>>> Signed-off-by: Dan Gora <dg@adax.com>
>>> ---
>>>    lib/librte_eal/common/rte_random.c | 33 ++++++++++++++++++++++++------
>>>    lib/librte_eal/meson.build         |  3 ---
>>>    2 files changed, 27 insertions(+), 9 deletions(-)
>>>
>>> diff --git a/lib/librte_eal/common/rte_random.c b/lib/librte_eal/common/rte_random.c
>>> index df02f1307..f8203f4c7 100644
>>> --- a/lib/librte_eal/common/rte_random.c
>>> +++ b/lib/librte_eal/common/rte_random.c
>>> @@ -7,6 +7,7 @@
>>>    #endif
>>>    #include <stdlib.h>
>>>    #include <unistd.h>
>>> +#include <dlfcn.h>
>>>
>>>    #include <rte_branch_prediction.h>
>>>    #include <rte_cycles.h>
>>> @@ -176,18 +177,38 @@ rte_rand_max(uint64_t upper_bound)
>>>        return res;
>>>    }
>>>
>>> +/* Try to use the getentropy() function from glibc >= 2.25 */
>>> +static int
>>> +__rte_getentropy(uint64_t *ge_seed)
>>> +{
>>> +     void *handle = NULL;
>>> +     void **sym;
>>> +     int (*getentropy_p)(void *__buffer, size_t __length);
>>> +     int gc_rc;
>>> +
>>> +     handle = dlopen("libc.so.6", RTLD_LAZY);
>>> +     if (!handle)
>> != NULL
>>> +             return -1;
>>> +
>>> +     sym = dlsym(handle, "getentropy");
>>> +     if (!sym || !*sym)
>> != NULL again
>>
>>
>> dlsym() returns a "void *". The man page says nothing about
>> de-referencing it. Is that allowed?
> This was blindly stolen from mlx5_common.c, so blame them :P
>
>>> +             /* Cannot resolve getentropy */
>>> +             return -1;
>> Missing a dlclose()
> This was fixed in version 2 of my patch...



  reply	other threads:[~2020-04-22 20:14 UTC|newest]

Thread overview: 48+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-04-21 19:54 [dpdk-dev] [PATCH 0/2] eal: choose initial PRNG seed source at runtime Dan Gora
2020-04-21 19:54 ` [dpdk-dev] [PATCH 1/2] eal: check for rdseed at run time for random seed Dan Gora
2020-04-22  8:22   ` Mattias Rönnblom
2020-04-21 19:54 ` [dpdk-dev] [PATCH 2/2] eal: resolve getentropy " Dan Gora
2020-04-21 21:03   ` Stephen Hemminger
2020-04-21 21:08     ` Dan Gora
2020-04-22  8:28   ` Mattias Rönnblom
2020-04-22 17:44     ` Dan Gora
2020-04-22 20:14       ` Mattias Rönnblom [this message]
2020-04-22 20:35         ` Dan Gora
2020-04-23 10:04           ` Luca Boccassi
2020-04-23 17:38             ` Dan Gora
2020-04-27 12:44               ` Luca Boccassi
2020-04-27 16:57                 ` Dan Gora
2020-04-30  8:41                   ` Luca Boccassi
2020-04-30 20:43                     ` Dan Gora
2020-05-01 10:33                       ` Luca Boccassi
2020-05-01 21:05                         ` Dan Gora
2020-05-04  8:04                           ` Mattias Rönnblom
2020-05-04 14:13                             ` Dan Gora
2020-05-04 14:19                               ` Dan Gora
2020-06-02  5:10                                 ` Dan Gora
2020-06-09 15:37                                   ` Dan Gora
2020-06-10  8:15                                     ` Thomas Monjalon
2020-06-10  8:33                                       ` Luca Boccassi
2023-06-12 15:55                                         ` Stephen Hemminger
2020-06-10  8:07                               ` Thomas Monjalon
2020-04-23 12:36           ` Mattias Rönnblom
2020-04-23 17:27             ` Dan Gora
2020-04-21 20:41 ` [dpdk-dev] [PATCH v2 0/2] eal: choose initial PRNG seed source at runtime Dan Gora
2020-04-21 20:41   ` [dpdk-dev] [PATCH v2 1/2] eal: check for rdseed at run time for random seed Dan Gora
2020-04-21 20:41   ` [dpdk-dev] [PATCH v2 2/2] eal: resolve getentropy " Dan Gora
2020-04-22 18:15 ` [dpdk-dev] [PATCH v3 0/2] eal: choose initial PRNG seed source at runtime Dan Gora
2020-04-22 18:15   ` [dpdk-dev] [PATCH v3 1/2] eal: check for rdseed at run time for random seed Dan Gora
2020-04-22 18:15   ` [dpdk-dev] [PATCH v3 2/2] eal: resolve getentropy " Dan Gora
2020-04-22 23:42 ` [dpdk-dev] [PATCH v4 0/2] eal: choose initial PRNG seed source at runtime Dan Gora
2020-04-22 23:42   ` [dpdk-dev] [PATCH v4 1/2] eal: check for rdseed at run time for random seed Dan Gora
2020-04-22 23:42   ` [dpdk-dev] [PATCH v4 2/2] eal: emulate glibc getentropy for initial " Dan Gora
2020-04-23  2:39     ` Stephen Hemminger
2020-04-23 17:42       ` Dan Gora
2020-06-29  9:30     ` Mattias Rönnblom
2020-06-29 17:57       ` Dan Gora
2020-06-29 20:57         ` Mattias Rönnblom
2020-06-29  9:32   ` [dpdk-dev] [PATCH v4 0/2] eal: choose initial PRNG seed source at runtime Mattias Rönnblom
2020-06-29 18:01     ` Dan Gora
2020-06-29 18:04       ` Dan Gora
2020-06-29 21:05       ` Mattias Rönnblom
2020-06-29 21:14         ` Dan Gora

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=80e5cf97-feae-c753-5c65-4f3b121729f3@ericsson.com \
    --to=mattias.ronnblom@ericsson.com \
    --cc=david.marchand@redhat.com \
    --cc=dev@dpdk.org \
    --cc=dg@adax.com \
    --cc=jerinjacobk@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).