1 | /* Check non representable OFD locks regions in non-LFS mode for compat |
2 | mode (BZ #20251) |
3 | Copyright (C) 2018-2024 Free Software Foundation, Inc. |
4 | |
5 | This program is free software; you can redistribute it and/or |
6 | modify it under the terms of the GNU General Public License |
7 | as published by the Free Software Foundation; either version 2 |
8 | of the License, or (at your option) any later version. |
9 | |
10 | This program is distributed in the hope that it will be useful, |
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
13 | GNU General Public License for more details. |
14 | |
15 | You should have received a copy of the GNU General Public License |
16 | along with this program; if not, see <https://www.gnu.org/licenses/>. |
17 | */ |
18 | |
19 | #include <unistd.h> |
20 | #include <fcntl.h> |
21 | #include <stdint.h> |
22 | #include <errno.h> |
23 | |
24 | #include <support/temp_file.h> |
25 | #include <support/check.h> |
26 | |
27 | #include <shlib-compat.h> |
28 | compat_symbol_reference (libc, fcntl, fcntl, GLIBC_2_0); |
29 | |
30 | static char *temp_filename; |
31 | static int temp_fd; |
32 | |
33 | static void |
34 | do_prepare (int argc, char **argv) |
35 | { |
36 | temp_fd = create_temp_file (base: "tst-ofdlocks-compat." , filename: &temp_filename); |
37 | TEST_VERIFY_EXIT (temp_fd != -1); |
38 | } |
39 | |
40 | #define PREPARE do_prepare |
41 | |
42 | /* Linux between 4.13 and 4.15 return EOVERFLOW for LFS OFD locks usage |
43 | in compat mode (non-LFS ABI running on a LFS default kernel, such as |
44 | i386 on a x86_64 kernel or s390-32 on a s390-64 kernel) [1]. This is |
45 | a kernel issue because __NR_fcntl64 is the expected way to use OFD locks |
46 | (used on GLIBC for both fcntl and fcntl64). |
47 | |
48 | [1] https://sourceware.org/ml/libc-alpha/2018-07/msg00243.html */ |
49 | |
50 | static int |
51 | do_test (void) |
52 | { |
53 | /* The compat fcntl version for architectures which support non-LFS |
54 | operations does not wrap the flock OFD argument, so the struct is passed |
55 | unmodified to kernel. It means no EOVERFLOW is returned, so operations |
56 | with LFS should not incur in failure. */ |
57 | |
58 | struct flock64 lck64 = { |
59 | .l_type = F_WRLCK, |
60 | .l_whence = SEEK_SET, |
61 | .l_start = (off64_t)INT32_MAX + 1024, |
62 | .l_len = 1024, |
63 | }; |
64 | int ret = fcntl (fd: temp_fd, F_OFD_SETLKW, &lck64); |
65 | if (ret == -1 && errno == EINVAL) |
66 | /* OFD locks are only available on Linux 3.15. */ |
67 | FAIL_UNSUPPORTED ("fcntl (F_OFD_SETLKW) not supported" ); |
68 | |
69 | TEST_VERIFY_EXIT (ret == 0); |
70 | |
71 | /* Open file description locks placed through the same open file description |
72 | (either by same file descriptor or a duplicated one created by fork, |
73 | dup, fcntl F_DUPFD, etc.) overwrites then old lock. To force a |
74 | conflicting lock combination, it creates a new file descriptor. */ |
75 | int fd = open64 (file: temp_filename, O_RDWR, 0666); |
76 | TEST_VERIFY_EXIT (fd != -1); |
77 | |
78 | struct flock64 lck = { |
79 | .l_type = F_WRLCK, |
80 | .l_whence = SEEK_SET, |
81 | .l_start = INT32_MAX - 1024, |
82 | .l_len = 4 * 1024, |
83 | }; |
84 | TEST_VERIFY (fcntl (fd, F_OFD_GETLK, &lck) == 0); |
85 | |
86 | return 0; |
87 | } |
88 | |
89 | #include <support/test-driver.c> |
90 | |