This is the mail archive of the glibc-bugs@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Bug libc/20251] New: 32bit programs pass garbage in struct flock for OFD locks


https://sourceware.org/bugzilla/show_bug.cgi?id=20251

            Bug ID: 20251
           Summary: 32bit programs pass garbage in struct flock for OFD
                    locks
           Product: glibc
           Version: 2.22
            Status: NEW
          Severity: normal
          Priority: P2
         Component: libc
          Assignee: unassigned at sourceware dot org
          Reporter: jiri.jabu at redhat dot com
                CC: drepper.fsp at gmail dot com
  Target Milestone: ---

For OFD ("file private") locks, the Linux kernel explicitly disables 32bit
offset support, in do_flock():

#if BITS_PER_LONG != 32
        /* 32-bit arches must use fcntl64() */
        case F_OFD_GETLK:
#endif
...
#if BITS_PER_LONG != 32
        /* 32-bit arches must use fcntl64() */
        case F_OFD_SETLK:
        case F_OFD_SETLKW:
#endif

and the fcntl64 syscall passes the argument as struct flock64 to fcntl_getlk64
/ fcntl_setlk64.

When a program is compiled as 32bit without using the _FILE_OFFSET_BITS=64 or
_LARGEFILE64_SOURCE interfaces, struct flock members are treated as 32bit, but
the flock64 syscall is used, causing garbage to be passed in the upper 32bits
to fcntl_getlk64 / fcntl_setlk64.

SYSCALL_DEFINE3(fcntl64, unsigned int, fd, unsigned int, cmd,
                unsigned long, arg)
{
        ...
        case F_OFD_GETLK:
                err = fcntl_getlk64(f.file, cmd, (struct flock64 __user *)
arg);
                break;
        ...
        case F_OFD_SETLK:
        case F_OFD_SETLKW:
                err = fcntl_setlk64(fd, f.file, cmd,
                                (struct flock64 __user *) arg);
                break;

The glibc OFD example also suffers from this, if you compile
manual/examples/ofdlocks.c as -m32, it hangs.
Using _FILE_OFFSET_BITS=64 or struct flock64 directly "fixes" the problem.

I'm not sure how to best solve this without breaking compatibility, maybe an
error should be returned by fcntl(), as OFD locks are not supported with 32bit
struct flock members? The kernel already seems to return EINVAL for "my"
garbage, but probing using systemtap confirms that the garbage is being passed
all the way to the kernel - maybe glibc could return EINVAL right away?

Alternatively, is there any way to make such 32bit programs use 64bit offsets
(struct flock64) by default, silently?

The BITS_PER_LONG #if was added with the original "file private locks" commit,
5d50ffd7c31dab47c6b828841ca1ec70a1b40169, mentioning:

    Also, note that with this implementation the new cmd values are only
    available via fcntl64() on 32-bit arches. There's little need to
    add support for legacy apps on a new interface like this.

See also Linux Test Project thread:
http://lists.linux.it/pipermail/ltp/2016-June/001986.html

Tested on (updated) Fedora 23,
glibc-2.22-17.fc23
gcc-5.3.1-6.fc23

Thanks.

-- 
You are receiving this mail because:
You are on the CC list for the bug.

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]