summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRich Felker <dalias@aerifal.cx>2023-02-28 12:21:23 -0500
committerRich Felker <dalias@aerifal.cx>2023-02-28 12:21:23 -0500
commitc99b7daafdbf1e2415bf408e67ca7813e7ddeedf (patch)
tree054b6fe6e7e42c2b087e40574bcf080b956eac0f
parentfb7fb5e4bd7ccb8efa691364404efc7804fad90c (diff)
downloadmusl-c99b7daafdbf1e2415bf408e67ca7813e7ddeedf.tar.gz
fix dup3 ignoring all flags but O_CLOEXEC on archs with SYS_dup2 syscall
our dup3 code wrongly skipped directly to making the SYS_dup2 syscall whenever the O_CLOEXEC bit of flags was not set. this is incorrect if any new flags are ever added, as it would silently ignore them rather than failing with an error. archs which lack SYS_dup2 were unaffected. adjust the logic so that SYS_dup3 is attempted whenever flags is nonzero, and explicitly fail with EINVAL if SYS_dup3 is unavailable and there are any unknown flags.
-rw-r--r--src/unistd/dup3.c3
1 files changed, 2 insertions, 1 deletions
diff --git a/src/unistd/dup3.c b/src/unistd/dup3.c
index f919f791..1e7dc3e7 100644
--- a/src/unistd/dup3.c
+++ b/src/unistd/dup3.c
@@ -9,9 +9,10 @@ int __dup3(int old, int new, int flags)
int r;
#ifdef SYS_dup2
if (old==new) return __syscall_ret(-EINVAL);
- if (flags & O_CLOEXEC) {
+ if (flags) {
while ((r=__syscall(SYS_dup3, old, new, flags))==-EBUSY);
if (r!=-ENOSYS) return __syscall_ret(r);
+ if (flags & ~O_CLOEXEC) return __syscall_ret(-EINVAL);
}
while ((r=__syscall(SYS_dup2, old, new))==-EBUSY);
if (flags & O_CLOEXEC) __syscall(SYS_fcntl, new, F_SETFD, FD_CLOEXEC);