public inbox for libc-alpha@sourceware.org
 help / color / mirror / Atom feed
From: Askar Safin <safinaskar@zohomail.com>
To: "dalias" <dalias@libc.org>
Cc: "Adhemerval Zanella Netto" <adhemerval.zanella@linaro.org>,
	"libc-alpha" <libc-alpha@sourceware.org>,
	"carlos" <carlos@redhat.com>
Subject: Re: [PATCH, RFC] Add public function syscall_no_errno
Date: Thu, 08 Feb 2024 21:08:43 +0400	[thread overview]
Message-ID: <18d89b16d90.c00028f96755.7590497864655577678@zohomail.com> (raw)
In-Reply-To: <20240207205908.GJ22081@brightrain.aerifal.cx>

 ---- On Thu, 08 Feb 2024 00:59:02 +0400  dalias  wrote --- 
 > You're missing the point. Of course glibc maintains that invariant
 > because it's providing a consistent platform to applications. If you
 > have application code that uses clone() itself, it may not be meeting
 > those invariants necessary to be able to call into libc.

Let me try to explain in other way. I tried to understand what guarantees
of "syscall" and "syscall_no_errno" functions will be easy for glibc
maintainers to provide, and what will be hard. Let's begin with
guarantee "it is okay to call 'syscall_no_errno', when TLS is possibly not initialized
properly, for example in child created by clone(CLONE_VM)".
Such guarantee will be hard to provide, because it seems that it is not
provided currently. I. e. additional work will be needed to provide it.
It seems to be not provided, because glibc nearly never uses it.
glibc seems to never use it, because in glibc TLS is nearly always initialized.

Now let's consider another possible guarantee "it is okay to call
'syscall' and 'syscall_no_errno' in child created by clone(CLONE_VM | CLONE_VFORK)".
It will be easy to provide, because (as of current master) it is already provided,
but not documented. I see that it is provided, because I see that glibc internally
uses this guarantee. glibc uses it in spawn implementation. glibc creates
child in posix_spawn using CLONE_VM | CLONE_VFORK.
And then issues syscalls using something very close to "syscall".
So it is very easy to provide such guarantee. We just need to
document it. If it is broken, glibc developers will notice this,
because they depend on this guarantee in spawn implementation.

So I don't propose to add that guarantee about TLS. But I do propose to
add (i. e. to document) guarantee about CLONE_VM | CLONE_VFORK.

 > Can you clarify *why* you want to do that?

As I already told I want to write that Rust library.
I don't want to publish it. Just for personal use.
I need it to expirement with Linux. I. e. no any serious use.
Just a playground.

I want to have full control over what syscalls I issue.

And I want to send syscall_no_errno to upstream glibc (and
ideally to upstream musl, too), because other developers
may have similar needs. I. e. because they sometimes
want to have full control over syscalls they issue.

Currently, if someone wants to issue syscall, such as SYS_getuid32
on i386, they must either use assembly (which is hard to do right),
either use some third-party library.

But I don't trust third-party libraries, as I already told in this thread.
So I suggest other people not to use them. For example, there exists
https://chromium.googlesource.com/linux-syscall-support/ , which
is intended to be way to make raw syscalls. But as I said previously,
it doesn't provide way to call getuid, and also it had a bug, which was
not fixed until *I* noticed it.

So I propose to export battle-tested trusted glibc implementation
as a public symbol. And everyone will be able to use it.

 > Making raw syscalls like
 > this is ill-advised and *will* run into mismatched ABI for certain
 > types (where the kernel and user types differ)

It will not, because I will use Rust crate "linux-raw-sys", which is
based on Linux uapi headers, i. e. headers from dir "include/uapi"
from Linux source tree.

 > poor compatibility
 > with kernel versions that aren't the same you expected

What you mean? Newer kernel versions are ABI compatible
with older ones. And yes, if you write program for newer
kernel and try to run it on older, you may get some issues.
But the same applies to usual programs written with glibc
and musl. Yes, glibc and musl know how to fail back to
older syscalls. So, what? I can manually write such fail back
code if needed. Again: I'm aware of all these issues. Of course,
I know that issuing syscalls directly is harder than using libc
wrappers.

 > time64 issues
 > on 32-bit archs, etc.

As I said, I will use prototypes parsed from /sys/... with types
got from Linux uapi headers. This will remove all time64 and
similar problems. Yes, this will mean that I will have to manually
write fail back code, i. e. "try time64, if it fails, then do time32".
But I'm aware about this.

 > It most certainly cannot be handled
 > in an automated way by parsing the data you have in mind

As I said, it *can* be done it automated way. Just use prototypes
from /sys/... and type definitions from uapi headers.

Feel free to steal this idea and use it in musl. :)

Also you may consider this project https://syscalls.mebeim.net/ instead
of parsing /sys/... . They get prototypes from kernel ELF binary.

And, yes, I know that when I see, say, "pid_t" in /sys/... , this
really means __kernel_pid_t from uapi headers.

(Also I plan to parse files from strace project, such as this:
https://github.com/strace/strace/blob/eb6014c510d663938db331fef5ac4ef78fdcf583/src/linux/i386/syscallent.h .
Because they mark functions, which cannot fail, as "NF". So I will know
when I should check errors, and when not.)

Of course, this process will produce not-so-usable functions.
So I then will manually write for them wrappers. For example,
this process may automatically produce this Rust prototype for "write":

fn write(fd: c_int, buf: *const c_void, len: usize) -> Result<isize, Errno>

And then I will futher manually wrap it and will make something like this:

fn write(fd: c_int, buf: &[u8]) -> Result<usize, Errno>

And of course, all these functions will be marked as "unsafe". I have no plans
for creating safe (in Rust sense) interface for Linux syscalls.

I do not plan to publish code, but if you want, I can show it to you,
when it is ready.

 > doing it
 > right requires knowing semantic relationships between syscalls.

Knowing semantic relationship may be required if I want to
add extra type data not present in /sys/... . For example if I want
to have separated type for "int", which means file descriptor, and
for other "int"s. Yes, I know that this cannot be done in automated
way. Yes, I know that generated code will simply have "int"s everywhere
and I will have to write manual wrapper if I want something more type-safe.

Also semantic relationship may be needed if I want to present
safe interface (in Rust sense). I have no such plans.

--
Askar Safin
https://types.pl/@safinaskar

  reply	other threads:[~2024-02-08 17:08 UTC|newest]

Thread overview: 23+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-01-28 16:39 Askar Safin
2024-02-01 17:53 ` Adhemerval Zanella Netto
2024-02-01 18:18   ` Rich Felker
2024-02-01 19:32   ` Askar Safin
2024-02-01 20:16     ` dalias
2024-02-01 20:57       ` Adhemerval Zanella Netto
2024-02-08 15:02         ` [PATCH v2] " Askar Safin
2024-02-08 17:48           ` Szabolcs Nagy
2024-02-12 14:24           ` Florian Weimer
2024-02-12 14:44             ` Rich Felker
2024-02-12 16:16               ` Askar Safin
2024-02-12 17:25                 ` Zack Weinberg
2024-02-12 17:43                   ` Andreas Schwab
2024-02-12 18:22                     ` Zack Weinberg
2024-02-13  9:10                       ` Andreas Schwab
2024-02-13 11:57                         ` Adhemerval Zanella Netto
2024-02-12 17:55                   ` Adhemerval Zanella Netto
2024-02-12 18:34                   ` Askar Safin
2024-02-07  0:59       ` [PATCH, RFC] " Askar Safin
2024-02-07 20:59         ` dalias
2024-02-08 17:08           ` Askar Safin [this message]
2024-02-07  1:57 ` Mike Frysinger
2024-02-07 12:55   ` Askar Safin

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=18d89b16d90.c00028f96755.7590497864655577678@zohomail.com \
    --to=safinaskar@zohomail.com \
    --cc=adhemerval.zanella@linaro.org \
    --cc=carlos@redhat.com \
    --cc=dalias@libc.org \
    --cc=libc-alpha@sourceware.org \
    /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 read-only IMAP folder(s) and NNTP newsgroup(s).