ioctl argument type [Was Re: svn commit: r359968 - head/sys/kern]
Hans Petter Selasky
hps at selasky.org
Mon Sep 14 08:01:35 UTC 2020
On 2020-09-14 09:44, Xin LI wrote:
> Hi,
>
> I have seen Chromium trigger the warning (I run -CURRENT with INVARIANTS)
> and looked into the code history a little bit.
>
> It seems that the command was changed to u_long in r36846
> <https://svnweb.freebsd.org/base?view=revision&revision=36846> with a
> follow up commit of r38517
> <https://svnweb.freebsd.org/base?view=revision&revision=38517> , possibly
> because ioctl was defined to take an unsigned long command before FreeBSD.
>
> Internally, we have truncated it to 32-bit since 2005 (r140406
> <https://svnweb.freebsd.org/base?view=revision&revision=140406>), and this
> recent change made it a silent behavior. POSIX, on the other hand, defined
> <https://pubs.opengroup.org/onlinepubs/9699919799/functions/ioctl.html>
> ioctl as taking an int as its second parameter, but neither Linux (glibc in
> particular, despite its documentation says
> <https://www.gnu.org/software/libc/manual/html_node/IOCTLs.html>
> differently) nor macOS appear to define it that way, but Solaris seems
> <https://docs.oracle.com/cd/E23824_01/html/821-1463/ioctl-2.html> to be
> defining it as an int.
>
> What was the motivation to keep the prototype definition as
>
> int
> ioctl(int fd, unsigned long request, ...);
>
> instead of:
>
> int
> ioctl(int fd, int request, ...);
>
> Other than to make existing code happy? Alternatively, will it be a good
> idea to give compiler some hints (e.g. by using __attribute__(enable_if))
> to emit errors, if we insist keeping the existing signature?
>
>
> On Wed, Apr 15, 2020 at 6:21 AM Hans Petter Selasky <hselasky at freebsd.org>
> wrote:
>
>> Author: hselasky
>> Date: Wed Apr 15 13:20:51 2020
>> New Revision: 359968
>> URL: https://svnweb.freebsd.org/changeset/base/359968
>>
>> Log:
>> Cast all ioctl command arguments through uint32_t internally.
>>
>> Hide debug print showing use of sign extended ioctl command argument
>> under INVARIANTS. The print is available to all and can easily fill
>> up the logs.
>>
>> No functional change intended.
>>
>> MFC after: 1 week
>> Sponsored by: Mellanox Technologies
>>
>> Modified:
>> head/sys/kern/sys_generic.c
>>
>> Modified: head/sys/kern/sys_generic.c
>>
>> ==============================================================================
>> --- head/sys/kern/sys_generic.c Wed Apr 15 13:13:46 2020 (r359967)
>> +++ head/sys/kern/sys_generic.c Wed Apr 15 13:20:51 2020 (r359968)
>> @@ -652,18 +652,19 @@ int
>> sys_ioctl(struct thread *td, struct ioctl_args *uap)
>> {
>> u_char smalldata[SYS_IOCTL_SMALL_SIZE]
>> __aligned(SYS_IOCTL_SMALL_ALIGN);
>> - u_long com;
>> + uint32_t com;
>> int arg, error;
>> u_int size;
>> caddr_t data;
>>
>> +#ifdef INVARIANTS
>> if (uap->com > 0xffffffff) {
>> printf(
>> "WARNING pid %d (%s): ioctl sign-extension ioctl
>> %lx\n",
>> td->td_proc->p_pid, td->td_name, uap->com);
>> - uap->com &= 0xffffffff;
>> }
>> - com = uap->com;
>> +#endif
>> + com = (uint32_t)uap->com;
>>
>> /*
>> * Interpret high order word to find amount of data to be
>>
Hi,
Using unsigned long is not cross platform compatible, especially when
you have 32-bit compat shim layers.
On 64-bit platforms long is usually 64-bit and on 32-bit platforms long
is usually 32-bit.
You've brought up a good question with a good history line.
Maybe we should just "#if 0" the INVARIANTS check and remove that code?
--HPS
More information about the freebsd-current
mailing list