Skip to content

Commit bf2d3e7

Browse files
committed
Merged PR 698510: Interpose dup calls for fd_table correctness
`dup` returns a new file descriptor, so we should treat it as an `open` and reset the fd table. `dup2` and `dup3` silently close file descriptors, so we have to invalidate the entries for those fds.
1 parent 0679207 commit bf2d3e7

File tree

2 files changed

+29
-9
lines changed

2 files changed

+29
-9
lines changed

Public/Src/Sandbox/Linux/bxl_observer.hpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -496,10 +496,11 @@ class BxlObserver final
496496
GEN_FN_DEF(ssize_t, sendfile64, int out_fd, int in_fd, off_t *offset, size_t count);
497497
GEN_FN_DEF(ssize_t, copy_file_range, int fd_in, loff_t *off_in, int fd_out, loff_t *off_out, size_t len, unsigned int flags);
498498
GEN_FN_DEF(int, name_to_handle_at, int dirfd, const char *pathname, struct file_handle *handle, int *mount_id, int flags);
499-
500-
/* ============ don't need to be interposed ======================= */
501499
GEN_FN_DEF(int, dup, int oldfd);
502500
GEN_FN_DEF(int, dup2, int oldfd, int newfd);
501+
GEN_FN_DEF(int, dup3, int oldfd, int newfd, int flags);
502+
503+
/* ============ don't need to be interposed ======================= */
503504
GEN_FN_DEF(int, close, int fd);
504505
GEN_FN_DEF(int, fclose, FILE *stream);
505506
GEN_FN_DEF(int, statfs, const char *, struct statfs *buf);

Public/Src/Sandbox/Linux/detours.cpp

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -804,6 +804,32 @@ INTERPOSE(int, fclose, FILE *f) ({
804804
return bxl->fwd_fclose(f).restore();
805805
})
806806

807+
INTERPOSE(int, dup, int fd) ({
808+
return ret_fd(bxl->real_dup(fd), bxl);
809+
// Sometimes useful (for debugging) to interpose without access checking:
810+
// return bxl->fwd_dup(fd).restore();
811+
})
812+
813+
INTERPOSE(int, dup2, int oldfd, int newfd)({
814+
// If the file descriptor newfd was previously open, it is closed
815+
// before being reused; the close is performed silently, so we should reset the fd table.
816+
bxl->reset_fd_table_entry(newfd);
817+
818+
return bxl->real_dup2(oldfd, newfd);
819+
// Sometimes useful (for debugging) to interpose without access checking:
820+
// return bxl->fwd_dup2(oldfd, newfd).restore();
821+
})
822+
823+
INTERPOSE(int, dup3, int oldfd, int newfd, int flags)({
824+
// If the file descriptor newfd was previously open, it is closed
825+
// before being reused; the close is performed silently, so we should reset the fd table.
826+
bxl->reset_fd_table_entry(newfd);
827+
828+
return bxl->real_dup3(oldfd, newfd, flags);
829+
// Sometimes useful (for debugging) to interpose without access checking:
830+
//return bxl->fwd_dup3(oldfd, newfd).restore();
831+
})
832+
807833
static void report_exit(int exitCode, void *args)
808834
{
809835
BxlObserver::GetInstance()->report_access("on_exit", ES_EVENT_TYPE_NOTIFY_EXIT, std::string(""), std::string(""));
@@ -828,13 +854,6 @@ int main(int argc, char **argv)
828854
printf("Path: %s\n", inst->GetReportsPath());
829855
}
830856

831-
/* ============ Sometimes useful (for debugging) to interpose without access checking
832-
833-
INTERPOSE(int, dup, int fd) ({ return bxl->fwd_dup(fd).restore(); })
834-
INTERPOSE(int, dup2, int oldfd, int newfd)({ return bxl->fwd_dup2(oldfd, newfd).restore(); })
835-
836-
=================================================================== */
837-
838857
/* ============ don't need to be interposed =======================
839858
840859
INTERPOSE(int, statfs, const char *pathname, struct statfs *buf)({

0 commit comments

Comments
 (0)