Skip to content

Commit 6eb838d

Browse files
committed
fix(locking): prevent lock fd inheritance and add read-only C open (#2)
## Summary - set close-on-exec for file open/create paths to prevent lock FD inheritance across exec - add `zvec_open_read_only(const char* path, zvec_collection_t* out)` C API and open collection with `read_only_=true` - add regression tests for CLOEXEC behavior and lock FD inheritance across fork+exec - fix the lock-inheritance regression test to move ownership from the create result and avoid shared ownership false negatives ## Testing - `./build-1349/bin/file_test --gtest_filter=File.CreateAndOpen_SetsCloseOnExecFlag` - `./build-1349/bin/collection_test --gtest_filter=CollectionTest.Feature_LockFdIsNotInheritedAcrossExec`
1 parent deedd32 commit 6eb838d

File tree

5 files changed

+307
-177
lines changed

5 files changed

+307
-177
lines changed

src/ailego/io/file.cc

Lines changed: 47 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,50 @@ static inline int OpenSafely(const char *path, int flags) {
3939
return fd;
4040
}
4141

42+
static inline bool SetCloseOnExec(int fd) {
43+
int current_flags = fcntl(fd, F_GETFD);
44+
while (current_flags == -1 && errno == EINTR) {
45+
current_flags = fcntl(fd, F_GETFD);
46+
}
47+
if (current_flags == -1) {
48+
return false;
49+
}
50+
if ((current_flags & FD_CLOEXEC) != 0) {
51+
return true;
52+
}
53+
54+
int ret = fcntl(fd, F_SETFD, current_flags | FD_CLOEXEC);
55+
while (ret == -1 && errno == EINTR) {
56+
ret = fcntl(fd, F_SETFD, current_flags | FD_CLOEXEC);
57+
}
58+
return ret == 0;
59+
}
60+
61+
static inline int OpenWithCloseOnExec(const char *path, int flags) {
62+
#ifdef O_CLOEXEC
63+
int cloexec_fd = OpenSafely(path, flags | O_CLOEXEC);
64+
if (cloexec_fd != -1) {
65+
return cloexec_fd;
66+
}
67+
if (errno != EINVAL) {
68+
return -1;
69+
}
70+
#endif
71+
72+
int fd = OpenSafely(path, flags);
73+
if (fd == -1) {
74+
return -1;
75+
}
76+
if (!SetCloseOnExec(fd)) {
77+
int ret = close(fd);
78+
while (ret == -1 && errno == EINTR) {
79+
ret = close(fd);
80+
}
81+
return -1;
82+
}
83+
return fd;
84+
}
85+
4286
static inline void CloseSafely(int fd) {
4387
int ret = close(fd);
4488
while (ret == -1 && errno == EINTR) {
@@ -144,7 +188,7 @@ bool File::create(const char *path, size_t len, bool direct) {
144188
(void)direct;
145189
#endif
146190

147-
int fd = OpenSafely(path, flags);
191+
int fd = OpenWithCloseOnExec(path, flags);
148192
ailego_false_if_lt_zero(fd);
149193

150194
#ifdef F_NOCACHE
@@ -178,7 +222,7 @@ bool File::open(const char *path, bool rdonly, bool direct) {
178222
(void)direct;
179223
#endif
180224

181-
int fd = OpenSafely(path, flags);
225+
int fd = OpenWithCloseOnExec(path, flags);
182226
ailego_false_if_lt_zero(fd);
183227

184228
#ifdef F_NOCACHE
@@ -724,4 +768,4 @@ void File::MemoryWarmup(void *addr, size_t len) {
724768
}
725769

726770
} // namespace ailego
727-
} // namespace zvec
771+
} // namespace zvec

0 commit comments

Comments
 (0)