Elektrine lite

← Feed

@madcoder@infosec.exchange

Post #3970695

2026-07-20 21:53 UTC

@jann@infosec.exchange is that allowed? That feels unintuitive to me. I’d implicitly expect that the fd allocation for dup() must be atomic with respect to close() happening and that as a result either dup(5) EBADFs or returns != 5 XNU goes to lengths (that scale poorly) to guarantee it. And I think FreeBSD does too.

Replies (1)

  • @jann@infosec.exchange 2026-07-20 22:12

    @madcoder@infosec.exchange Linux implements dup() as "first look up the file object from the file descriptor, then install the file object into a new file descriptor" as two separate steps with no locks held in between: SYSCALL_DEFINE1(dup, unsigned int, fildes) { int ret = -EBADF; struct file *file = fget_raw(fildes); if (file) { ret = get_unused_fd_flags(0); if (ret >= 0) fd_install(ret, file); else fput(file); } return ret; } And unlike what IIRC XNU does, Linux generally does not prevent you from closing a file descriptor while another syscall is operating on a file object that was looked up from that descriptor. So you could, for example, start a blocking read() on a pipe on one thread, and then let another thread close() the pipe's FD while the read() is still pending. I think Linux takes the position that if userspace decides to close() a file descriptor while another thread is operating on that file descriptor, userspace is being silly and shouldn't expect anything good to happen.

    Open ##3971121