lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20210312032712.GB27924@1wt.eu>
Date:   Fri, 12 Mar 2021 04:27:12 +0100
From:   Willy Tarreau <w@....eu>
To:     Masahiro Yamada <masahiroy@...nel.org>
Cc:     Linux Kernel Mailing List <linux-kernel@...r.kernel.org>,
        linux-api@...r.kernel.org
Subject: Re: Why is the bit size different between a syscall and its wrapper?

On Fri, Mar 12, 2021 at 11:48:11AM +0900, Masahiro Yamada wrote:
> Hi.
> 
> I think I am missing something, but
> is there any particular reason to
> use a different bit size between
> a syscall and its userspace wrapper?
> 
> 
> 
> For example, for the unshare syscall,
> 
> unshare(2) says the parameter is int.
> 
> 
> SYNOPSIS
>        #define _GNU_SOURCE
>        #include <sched.h>
> 
>        int unshare(int flags);
> 
> 
> 
> 
> In the kernel, it is unsigned long.
> 
> 
> SYSCALL_DEFINE1(unshare, unsigned long, unshare_flags)
> {
>         return ksys_unshare(unshare_flags);
> }

The syscalls must have a well defined interface for a given architecture.
Thus in practice the ABI will define that arg1 goes into this register,
arg2 into this one etc, regardless of their type (plenty of them are
pointers for example). The long is the size of a register so it can carry
any of the types we care about. So by defining each syscall as a function
taking 1 to 6 fixed-size arguments you can implement about all syscalls.

Regarding the libc, it has to offer an interface which is compatible with
the standard definition of the syscalls as defined by POSIX or as commonly
found on other OSes, and this regardless of the platform.

For example look at recv(), it takes an int, a pointer, a size_t and an
int. It requires to be defined like this for portability, but at the OS
level all these will typically be passed as a register each.

Hoping this helps,
Willy

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ