[BusyBox 0002884]: ioctl() wrappers broken on 64-bit systems

bugs at busybox.net bugs at busybox.net
Thu Apr 24 04:48:25 UTC 2008


The following issue has been CLOSED 
====================================================================== 
http://busybox.net/bugs/view.php?id=2884 
====================================================================== 
Reported By:                ncase
Assigned To:                BusyBox
====================================================================== 
Project:                    BusyBox
Issue ID:                   2884
Category:                   Other
Reproducibility:            always
Severity:                   major
Priority:                   normal
Status:                     closed
Resolution:                 open
Fixed in Version:           
====================================================================== 
Date Submitted:             04-10-2008 16:06 PDT
Last Modified:              04-23-2008 21:48 PDT
====================================================================== 
Summary:                    ioctl() wrappers broken on 64-bit systems
Description: 
The ioctl_*() and bb_xioctl*() functions declare the second argument as
"int request" rather than "unsigned long int request" which break the
ioctl() calls on 64-bit systems.

This bug presented itself in the form of login failing during the termios
TCSETS call:

    getty: /dev/ttyS0: TCSETS: Invalid argument

I verified that changing the "request" argument to "unsigned long int"
fixes the problem.  It should leave 32-bit systems unaffected.  See
attached patch.
====================================================================== 

---------------------------------------------------------------------- 
 ncase - 04-10-08 16:08  
---------------------------------------------------------------------- 
The patches are for the unstable tree and also the busybox_1_9_stable tree. 

---------------------------------------------------------------------- 
 vda - 04-10-08 16:25  
---------------------------------------------------------------------- 
This is strange, since both Linux and POSIX man pages say that that
parameter is int, not long:

#include <sys/ioctl.h>
int ioctl(int d, int request, ...);


I assume you are talking about this call in getty.c:

ioctl_or_perror_and_die(0, TCSETS, tp, "%s: TCSETS", op->tty);

TCSETS is defined as follows (in glibc, probaly the same in all other
lics):

#define TCSETS          0x5402

I don't understand how this code doesn't work:

int ioctl_or_perror_and_die(int fd, int request, void *argp, const char
*fmt,...)
{
        int ret;
        va_list p;

        ret = ioctl(fd, request, argp);
        if (ret < 0) {
                va_start(p, fmt);
                bb_verror_msg(fmt, p, strerror(errno));
                /* xfunc_die can actually longjmp, so be nice */
                va_end(p);
                xfunc_die();
        }
        return ret;
}

but replacing "int request" with "unsigned long request" makes it work?
It should work the same since 0x5402 comfortably fits into both 32-bit
int
and 64-bit long.

Can you describe failure scenario in more details? Why exactly it is
failing? 

---------------------------------------------------------------------- 
 ncase - 04-10-08 16:41  
---------------------------------------------------------------------- 
The man pages do say int, but if I actually look in sys/ioctl.h on all of
my systems here I see the following:

extern int ioctl (int __fd, unsigned long int __request, ...) __THROW;

You are correct that it's the ioctl_or_perror_and_die() call in getty.c
which is failing.  I suspected that something was getting mangled in the
argument passing after seeing this strange strace of getty (I've included
only the ioctl calls):

    ioctl(0, TCGETS, {B115200 opost isig -icanon -echo ...}) = 0
    ioctl(0, TIOCSPGRP, [-1905424])         = -1 ENOTTY (Inappropriate
ioctl for    device)
    ioctl(0, TCFLSH, 0x2)                   = 0
    ioctl(0, TCSETS, {B115200 opost -isig -icanon -echo ...}) = 0
    ioctl(0, TCFLSH, 0)                     = 0
    ioctl(1, TCGETS, {B115200 opost -isig -icanon -echo ...}) = 0
    ioctl(0, TCSETS, 0xfffffe2eb90)         = -1 EINVAL (Invalid
argument)

The final ioctl() which fails happens right after I enter the login name,
and it prints out the error message I mentioned before.  The ioctls()
before it which succeed are calling ioctl() directly rather than using the
wrapper.

So what appears to be happening is that the incorrect size of 'request' is
actually mangling the value of the argp that gets passed, since you can see
that strace sees it as TCSETS properly. 

---------------------------------------------------------------------- 
 vda - 04-10-08 16:47  
---------------------------------------------------------------------- 
Can you printf("%p", argp) before the call to ioctl_or_perror_and_die() and
inside the call? 

---------------------------------------------------------------------- 
 vda - 04-23-08 21:48  
---------------------------------------------------------------------- 
fixed in svn and will be in 1.10.2. 

Issue History 
Date Modified   Username       Field                    Change               
====================================================================== 
04-10-08 16:06  ncase          New Issue                                    
04-10-08 16:06  ncase          Status                   new => assigned     
04-10-08 16:06  ncase          Assigned To               => BusyBox         
04-10-08 16:06  ncase          File Added:
busybox-unstable-ioctl-64bit-fix.patch                    
04-10-08 16:08  ncase          File Added: busybox-stable-ioctl-64bit-fix.patch 
                  
04-10-08 16:08  ncase          Note Added: 0006514                          
04-10-08 16:25  vda            Note Added: 0006524                          
04-10-08 16:41  ncase          Note Added: 0006534                          
04-10-08 16:47  vda            Note Added: 0006544                          
04-23-08 21:48  vda            Status                   assigned => closed  
04-23-08 21:48  vda            Note Added: 0007044                          
======================================================================




More information about the busybox-cvs mailing list