Skip to content

Commit 4b9d7e1

Browse files
authored
Reapply "[libc] Return errno from OFD failure paths in fcntl." (#166658) (#166846)
The previous implementation in #166252 (rolled back in #166658) caused buildbot failures due to a bug in an added test. The modified `UseAfterClose` did not pass a `struct flock` value to `fcntl`: https://github.com/llvm/llvm-project/blob/2d5170594147b42a37698760d6e0194eec4f1390/libc/test/src/fcntl/fcntl_test.cpp#L175 Which ASAN caught and errored in the `fcntl` implementation when the unspecified argument was accessed: https://github.com/llvm/llvm-project/blob/c12cb2892c808af459eaa270b8738a2b375ecc9b/libc/src/__support/OSUtil/linux/fcntl.cpp#L59
1 parent fb2fa21 commit 4b9d7e1

File tree

2 files changed

+100
-63
lines changed

2 files changed

+100
-63
lines changed

libc/src/__support/OSUtil/linux/fcntl.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ ErrorOr<int> fcntl(int fd, int cmd, void *arg) {
6666
LIBC_NAMESPACE::syscall_impl<int>(FCNTL_SYSCALL_ID, fd, cmd, &flk64);
6767
// On failure, return
6868
if (ret < 0)
69-
return Error(-1);
69+
return Error(-ret);
7070
// Check for overflow, i.e. the offsets are not the same when cast
7171
// to off_t from off64_t.
7272
if (static_cast<off_t>(flk64.l_len) != flk64.l_len ||

libc/test/src/fcntl/fcntl_test.cpp

Lines changed: 99 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -94,68 +94,105 @@ TEST_F(LlvmLibcFcntlTest, FcntlSetFl) {
9494
ASSERT_THAT(LIBC_NAMESPACE::close(fd), Succeeds(0));
9595
}
9696

97-
TEST_F(LlvmLibcFcntlTest, FcntlGetLkRead) {
98-
using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Succeeds;
99-
constexpr const char *TEST_FILE_NAME = "testdata/fcntl_getlkread.test";
100-
auto TEST_FILE = libc_make_test_file_path(TEST_FILE_NAME);
101-
102-
struct flock flk, svflk;
103-
int retVal;
104-
int fd =
105-
LIBC_NAMESPACE::open(TEST_FILE, O_CREAT | O_TRUNC | O_RDONLY, S_IRWXU);
106-
ASSERT_ERRNO_SUCCESS();
107-
ASSERT_GT(fd, 0);
108-
109-
flk.l_type = F_RDLCK;
110-
flk.l_start = 0;
111-
flk.l_whence = SEEK_SET;
112-
flk.l_len = 50;
113-
114-
// copy flk into svflk
115-
svflk = flk;
116-
117-
retVal = LIBC_NAMESPACE::fcntl(fd, F_GETLK, &svflk);
118-
ASSERT_ERRNO_SUCCESS();
119-
ASSERT_GT(retVal, -1);
120-
ASSERT_NE((int)flk.l_type, F_WRLCK); // File should not be write locked.
121-
122-
retVal = LIBC_NAMESPACE::fcntl(fd, F_SETLK, &svflk);
123-
ASSERT_ERRNO_SUCCESS();
124-
ASSERT_GT(retVal, -1);
125-
126-
ASSERT_THAT(LIBC_NAMESPACE::close(fd), Succeeds(0));
127-
}
128-
129-
TEST_F(LlvmLibcFcntlTest, FcntlGetLkWrite) {
130-
using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Succeeds;
131-
constexpr const char *TEST_FILE_NAME = "testdata/fcntl_getlkwrite.test";
132-
auto TEST_FILE = libc_make_test_file_path(TEST_FILE_NAME);
133-
134-
struct flock flk, svflk;
135-
int retVal;
136-
int fd = LIBC_NAMESPACE::open(TEST_FILE, O_CREAT | O_TRUNC | O_RDWR, S_IRWXU);
137-
ASSERT_ERRNO_SUCCESS();
138-
ASSERT_GT(fd, 0);
139-
140-
flk.l_type = F_WRLCK;
141-
flk.l_start = 0;
142-
flk.l_whence = SEEK_SET;
143-
flk.l_len = 0;
144-
145-
// copy flk into svflk
146-
svflk = flk;
147-
148-
retVal = LIBC_NAMESPACE::fcntl(fd, F_GETLK, &svflk);
149-
ASSERT_ERRNO_SUCCESS();
150-
ASSERT_GT(retVal, -1);
151-
ASSERT_NE((int)flk.l_type, F_RDLCK); // File should not be read locked.
152-
153-
retVal = LIBC_NAMESPACE::fcntl(fd, F_SETLK, &svflk);
154-
ASSERT_ERRNO_SUCCESS();
155-
ASSERT_GT(retVal, -1);
156-
157-
ASSERT_THAT(LIBC_NAMESPACE::close(fd), Succeeds(0));
158-
}
97+
/* Tests that are common between OFD and traditional variants of fcntl locks. */
98+
template <int GETLK_CMD, int SETLK_CMD>
99+
class LibcFcntlCommonLockTests : public LlvmLibcFcntlTest {
100+
public:
101+
void GetLkRead() {
102+
using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Succeeds;
103+
constexpr const char *TEST_FILE_NAME = "testdata/fcntl_getlkread.test";
104+
const auto TEST_FILE = libc_make_test_file_path(TEST_FILE_NAME);
105+
106+
struct flock flk = {};
107+
struct flock svflk = {};
108+
int retVal;
109+
int fd =
110+
LIBC_NAMESPACE::open(TEST_FILE, O_CREAT | O_TRUNC | O_RDONLY, S_IRWXU);
111+
ASSERT_ERRNO_SUCCESS();
112+
ASSERT_GT(fd, 0);
113+
114+
flk.l_type = F_RDLCK;
115+
flk.l_start = 0;
116+
flk.l_whence = SEEK_SET;
117+
flk.l_len = 50;
118+
119+
// copy flk into svflk
120+
svflk = flk;
121+
122+
retVal = LIBC_NAMESPACE::fcntl(fd, GETLK_CMD, &svflk);
123+
ASSERT_ERRNO_SUCCESS();
124+
ASSERT_GT(retVal, -1);
125+
ASSERT_NE((int)svflk.l_type, F_WRLCK); // File should not be write locked.
126+
127+
retVal = LIBC_NAMESPACE::fcntl(fd, SETLK_CMD, &svflk);
128+
ASSERT_ERRNO_SUCCESS();
129+
ASSERT_GT(retVal, -1);
130+
131+
ASSERT_THAT(LIBC_NAMESPACE::close(fd), Succeeds(0));
132+
}
133+
134+
void GetLkWrite() {
135+
using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Succeeds;
136+
constexpr const char *TEST_FILE_NAME = "testdata/fcntl_getlkwrite.test";
137+
const auto TEST_FILE = libc_make_test_file_path(TEST_FILE_NAME);
138+
139+
struct flock flk = {};
140+
struct flock svflk = {};
141+
int retVal;
142+
int fd =
143+
LIBC_NAMESPACE::open(TEST_FILE, O_CREAT | O_TRUNC | O_RDWR, S_IRWXU);
144+
ASSERT_ERRNO_SUCCESS();
145+
ASSERT_GT(fd, 0);
146+
147+
flk.l_type = F_WRLCK;
148+
flk.l_start = 0;
149+
flk.l_whence = SEEK_SET;
150+
flk.l_len = 0;
151+
152+
// copy flk into svflk
153+
svflk = flk;
154+
155+
retVal = LIBC_NAMESPACE::fcntl(fd, GETLK_CMD, &svflk);
156+
ASSERT_ERRNO_SUCCESS();
157+
ASSERT_GT(retVal, -1);
158+
ASSERT_NE((int)svflk.l_type, F_RDLCK); // File should not be read locked.
159+
160+
retVal = LIBC_NAMESPACE::fcntl(fd, SETLK_CMD, &svflk);
161+
ASSERT_ERRNO_SUCCESS();
162+
ASSERT_GT(retVal, -1);
163+
164+
ASSERT_THAT(LIBC_NAMESPACE::close(fd), Succeeds(0));
165+
}
166+
167+
void UseAfterClose() {
168+
using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Succeeds;
169+
constexpr const char *TEST_FILE_NAME =
170+
"testdata/fcntl_use_after_close.test";
171+
const auto TEST_FILE = libc_make_test_file_path(TEST_FILE_NAME);
172+
int fd =
173+
LIBC_NAMESPACE::open(TEST_FILE, O_CREAT | O_TRUNC | O_RDWR, S_IRWXU);
174+
ASSERT_THAT(LIBC_NAMESPACE::close(fd), Succeeds(0));
175+
176+
flock flk = {};
177+
flk.l_type = F_RDLCK;
178+
flk.l_start = 0;
179+
flk.l_whence = SEEK_SET;
180+
flk.l_len = 50;
181+
ASSERT_EQ(-1, LIBC_NAMESPACE::fcntl(fd, GETLK_CMD, &flk));
182+
ASSERT_ERRNO_EQ(EBADF);
183+
}
184+
};
185+
186+
#define COMMON_LOCK_TESTS(NAME, GETLK_CMD, SETLK_CMD) \
187+
using NAME = LibcFcntlCommonLockTests<GETLK_CMD, SETLK_CMD>; \
188+
TEST_F(NAME, GetLkRead) { GetLkRead(); } \
189+
TEST_F(NAME, GetLkWrite) { GetLkWrite(); } \
190+
TEST_F(NAME, UseAfterClose) { UseAfterClose(); } \
191+
static_assert(true, "Require semicolon.")
192+
193+
COMMON_LOCK_TESTS(LlvmLibcFcntlProcessAssociatedLockTest, F_GETLK, F_SETLK);
194+
COMMON_LOCK_TESTS(LlvmLibcFcntlOpenFileDescriptionLockTest, F_OFD_GETLK,
195+
F_OFD_SETLK);
159196

160197
TEST_F(LlvmLibcFcntlTest, UseAfterClose) {
161198
using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Succeeds;

0 commit comments

Comments
 (0)