Follow @Openwall on Twitter for new release announcements and other news
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <ZxztEfJLtCyZ_x26@voyager>
Date: Sat, 26 Oct 2024 15:22:25 +0200
From: Markus Wichmann <nullplan@....net>
To: musl@...ts.openwall.com
Subject: Re: Prototypes without implementations

Am Sat, Oct 26, 2024 at 10:28:38AM +0000 schrieb Laurent Bercot:
>  Who's "we"?

Me and my sockpuppet. I was under the impression that this is the
general consensus among regulars on this list, as it shone through on
past discussions, but maybe I'm mistaken.

> >  Just because a
> > function exists in the lib does not mean it will succeed at run-time.
> > This is already the case with functions like getrandom() or pselect().
>
>  getrandom() is part of the problem, yes - a function that you cannot
> test for at link time and that you have to make depend on a kernel
> version in order to use. But because the problem already exists doesn't
> mean it's a good idea to add to it.
>

You call the function, and if it fails, you fall back to another method
(which includes attempting to seed a PRNG with getauxval(AT_RANDOM) or
trying to open /dev/urandom or the like). Does it matter if it fails
because the kernel is too old or just having a bad day?

I would never check the kernel version before just calling the kernel
interface.

>  pselect() is posix, it has a specification. If your pselect() isn't
> doing what it's supposed to, then your implementation is nonconformant.

Failing with ENOSYS and no side effects and no wait time is conformant
as well. In the case of pselect(), it is probably the better behavior of
libc as well if the kernel doesn't provide the necessary syscall,
because the workaround if pselect() doesn't exist is so invasive.
Indeed, if you have an application that can deal with pselect() not
being available, you likely have an application that doesn't need
pselect() at all. (The workaround could be the self-pipe trick, which
obviates the need for pselect() completely).

> > Even if you could run run-time tests, just because it succeeds at
> > configure time does not mean it succeeds at any later date. And
> > conversely, just because it fails at configure time does not mean it
> > cannot succeed.
>
>  The point isn't to test for "success" or "failure" (unless you've
> found a solution to the halting problem, in which case I'm definitely
> interested).

The halting problem is precisely the reason why run-time tests are a bad
idea even not cross-compiling. If the function under test fails with
ENOSYS, you still have no idea if that is because of a stubbed out
implementation.

> The point is to have a decent heuristic for whether a
> given function, identified by its name and signature, exists in your
> system and has a reasonable chance of doing what you think it will do.

See above. Failing with ENOSYS and no side effects is a perfectly
conforming implementation of most POSIX functions.

> Is it perfect? No. Do we have a better way of writing portable software
> that does not involve starting every single executable with a battery
> of tests? Also no.
>

If your binary links against musl, it does do precisely those tests. Not
necessarily at the start of the runtime, but inside many functions, and
in many of those never saves the state about what is or is not possible
in the run-time kernel, so the tests are re-run everytime the function
is called. I am talking about things such as all of the socket functions
on socketcall architectures attempting to do the newer syscall directly
and falling back to the socketcall mechanism if that fails. Or
clock_gettime(), if it cannot be implemented in VDSO, trying first the
64-bit syscall, then the 32-bit one.

To me, not much difference exists between a function failing with ENOSYS
and it failing for any other reason. In the end, you still simply have a
function failure at run-time and need to cope with it. And it could
start working at any point in the future. Maybe not in the same process
lifetime, but maybe in another one.

> >  Writing your software in the above manner is therefore
> > not sensible.
>
>  Every single project using a configure script such as one created by
> GNU autoconf, or a build system generator such as cmake or meson, is
> therefore not sensible. That's fair, but maybe we should still try to
> avoid breaking them?
>

It is possible, though not effortless, to write sensible software using
any of the aforementioned build systems. I have done so with cmake at
least. It does require a shift in perspective, though, to not assuming a
function will be successful just because it exists.

Ciao,
Markus

Powered by blists - more mailing lists

Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.