[PATCH v4] Fix Linux fcntl OFD locks for non-LFS architectures (BZ#20251)

Stefan Liebler stli@linux.ibm.com
Fri Jul 6 13:02:00 GMT 2018


On 06/20/2018 11:43 PM, Adhemerval Zanella wrote:
> Changes from previous version:
> 
>    - Add a testcase for compat fcntl using OFD locks.
> 
> ---
> 
> This patch fixes the OFD ("file private") locks for architectures that
> support non-LFS flock definition (__USE_FILE_OFFSET64 not defined). The
> issue in this case is both F_OFD_{GETLK,SETLK,SETLKW} and
> F_{SET,GET}L{W}K64 expects a flock64 argument and when using old
> F_OFD_* flags with a non LFS flock argument the kernel might interpret
> the underlying data wrongly.  Kernel idea originally was to avoid using
> such flags in non-LFS syscall, but since GLIBC uses fcntl with LFS
> semantic as default it is possible to provide the functionality and
> avoid the bogus struct kernel passing by adjusting the struct manually
> for the required flags.
> 
> The idea follows other LFS interfaces that provide two symbols:
> 
>    1. A new LFS fcntl64 is added on default ABI with the usual macros to
>       select it for FILE_OFFSET_BITS=64.
> 
>    2. The Linux non-LFS fcntl use a stack allocated struct flock64 for
>       F_OFD_{GETLK,SETLK,SETLKW} copy the results on the user provided
>       struct.
> 
>    3. Keep a compat symbol with old broken semantic for architectures
>       that do not define __OFF_T_MATCHES_OFF64_T.
> 
> So for architectures which defines __USE_FILE_OFFSET64, fcntl64 will
> aliased to fcntl and no adjustment would be required.  So to actually
> use F_OFD_* with LFS support the source must be built with LFS support
> (_FILE_OFFSET_BITS=64).
> 
> Also F_OFD_SETLKW command is handled a cancellation point, as for
> F_SETLKW{64}.
> 
> Checked on x86_64-linux-gnu and i686-linux-gnu.
> 
...

Hi Adhemerval,

I'm running the new test misc/tst-ofdlocks-compat on s390-32.
If I run it on linux 4.17, the test succeeds and after the second fcntl 
call which returns zero, lck contains the region from the first fcntl call:
(gdb) p/x lck
$2 = {l_type = 0x1, l_whence = 0x0, l_start = 0x800003ff, l_len = 0x400, 
l_pid = 0xffffffff}

If I run it on linux 4.14, the test fails. There the second fcntl 
returns -1 and errno = EOVERFLOW
In this case, lck is not updated:
p/x lck
$4 = {l_type = 0x1, l_whence = 0x0, l_start = 0x7ffffbff, l_len = 
0x1000, l_pid = 0x0}

In both cases struct flock64 is just passed to syscall fcntl64 via 
__old_libc_fcntl64.

Are the different behaviours related to a change in kernel-code?

Bye
Stefan



More information about the Libc-alpha mailing list