cygwin 3.5.4-1: lockf() aborts on overlap and does not fail on overflow

Christian Franke Christian.Franke@t-online.de
Thu Oct 17 16:37:57 GMT 2024


Takashi Yano via Cygwin wrote:
> On Mon, 14 Oct 2024 15:36:02 +0200
> Christian Franke wrote:
>> Two possibly independent bugs found by 'stress-ng --lockf ...':
>>
>> 1) lockf() may abort the process with api_fatal() if the new range
>> partly overlaps with two ranges previously locked by the same process.
>>
>> 2) lockf() prints a warning on too many locks and returns success. It
>> should not print a warning and fail with ENOLCK instead.
>>
>> Testcase for both:
>>
>> $ uname -r
>> 3.5.4-1.x86_64
>>
>> $ cat locktest.c
>> #include <fcntl.h>
>> #include <stdio.h>
>> #include <unistd.h>
>>
>> static int lock_at(int fd, int off, int size)
>> {
>>     if (lseek(fd, off, SEEK_SET) < 0) {
>>       perror("lseek"); return -1;
>>     }
>>     printf("\rlock %d-%d\n", off, off + size - 1); fflush(stdout);
>>     if (lockf(fd, F_LOCK, size) < 0) {
>>       perror("lock"); return -1;
>>     }
>>     return 0;
>> }
>>
>> int main(int argc, char **argv)
>> {
>>     int fd = open("locktest.tmp", O_RDWR|O_CREAT, 0666);
>>     if (fd < 0) {
>>       perror("open"); return 1;
>>     }
>>
>>     if (argc == 1) {
>>       lock_at(fd, 0, 2);
>>       lock_at(fd, 2, 2);
>>       lock_at(fd, 1, 2);
>>     }
>>     else {
>>       for (int i = 0; i < 914; i++)
>>         if (lock_at(fd, i, 1))
>>           return 1;
>>     }
>>     printf("\rdone\n");
>>     return 0;
>> }
>>
>> $ gcc -o locktest locktest.c
>>
>> $ ./locktest
>> lock 0-1
>> lock 2-3
>> lock 1-2
>>        1 [main] locktest 44864 C:\cygwin64\tmp\locktest.exe: \
>>          *** fatal error - NtCreateEvent(lock): 0xC0000035\
>>          Hangup
>>
>> $ ./locktest loop
>> lock 0-0
>> lock 1-1
>> lock 2-2
>> lock 3-3
>> ...
>> lock 909-909
>> lock 910-910
>> lock 911-911
>>         0 [main] locktest 44865 inode_t::get_all_locks_list: \
>>           Warning, can't handle more than 910 locks per file.
>> lock 912-912
>>       727 [main] locktest 44865 inode_t::get_all_locks_list: \
>>           Warning, can't handle more than 910 locks per file.
>> lock 913-913
>>      1329 [main] locktest 44865 inode_t::get_all_locks_list: \
>>           Warning, can't handle more than 910 locks per file.
>> done
>>
>> There is possibly also an off-by-one error as the 912'th lockf() prints
>> the first warning.
> Thanks for the report.
> I looked into the problems, and considered how to fix them.
>
> Could you please try the experimental patch attached?


Works as expected with both 'locktest.exe' and 'stress-ng --lockf ...'.

-- 
Thanks,
Christian



More information about the Cygwin mailing list