From: Rich Felker <dalias@libc.org>
To: Markus Wichmann <nullplan@gmx.net>
Cc: musl@lists.openwall.com
Subject: Re: [musl] fcntl: Purpose of second DUPFD_CLOEXEC?
Date: Thu, 22 Aug 2024 10:48:53 -0400 [thread overview]
Message-ID: <20240822144852.GA10433@brightrain.aerifal.cx> (raw)
In-Reply-To: <ZsdCumxt_DuZl9Rp@voyager>
On Thu, Aug 22, 2024 at 03:52:58PM +0200, Markus Wichmann wrote:
> Hi all,
>
> I just stumbled upon the code to emulate F_DUPFD_CLOEXEC on old kernels.
> At the moment, it looks like this:
>
> |int ret = __syscall(SYS_fcntl, fd, F_DUPFD_CLOEXEC, arg);
> |if (ret != -EINVAL) {
> | if (ret >= 0)
> | __syscall(SYS_fcntl, ret, F_SETFD, FD_CLOEXEC);
> | return __syscall_ret(ret);
> |}
> |ret = __syscall(SYS_fcntl, fd, F_DUPFD_CLOEXEC, 0);
> |if (ret != -EINVAL) {
> | if (ret >= 0) __syscall(SYS_close, ret);
> | return __syscall_ret(-EINVAL);
> |}
> |ret = __syscall(SYS_fcntl, fd, F_DUPFD, arg);
> |if (ret >= 0) __syscall(SYS_fcntl, ret, F_SETFD, FD_CLOEXEC);
> |return __syscall_ret(ret);
>
> And I'm wondering what the point of the second call to F_DUPFD_CLOEXEC
> is. If it is just to test that the argument is valid, then why not just
> get rid of the block?
It's to test if F_DUPFD_CLOEXEC failed with EINVAL because it's an
unknown fcntl command or because arg exceeds the fd limit.
Unfortunately, the error is ambiguous.
> F_DUPFD has the same constraints on the argument.
That's a good point -- F_DUPFD can be expected to fail (thus not
introduce any fd leak race condition) as long as the limit does not
change concurrently with the fcntl call. But if the limit does change
concurrently, the test result may be outdated by the time it's used.
So I think it may make sense to try the fallback directly.
> Getting rid of that block also has the advantage of being able to factor
> out the F_SETFD call. Then it would simply be
>
> int ret = __syscall(SYS_fcntl, fd, F_DUPFD_CLOEXEC, arg);
> if (ret == -EINVAL) ret = __syscall(SYS_fcntl, fd, F_DUPFD, arg);
> if (ret >= 0) __syscall(SYS_fcntl, fd, F_SETFL, FD_CLOEXEC);
> return __syscall_ret(ret);
>
> Much nicer, isn't it? And it doesn't even allocate a file descriptor
> uselessly.
Seems like it. I'll wait for further feedback but this might be the
right thing to do.
Note that this factoring-out by inverting the conditions can be done
even without dropping the arg=0 second check.
Rich
next prev parent reply other threads:[~2024-08-22 14:49 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-08-22 13:52 Markus Wichmann
2024-08-22 14:48 ` Rich Felker [this message]
2024-08-24 9:17 ` Markus Wichmann
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20240822144852.GA10433@brightrain.aerifal.cx \
--to=dalias@libc.org \
--cc=musl@lists.openwall.com \
--cc=nullplan@gmx.net \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this public inbox
https://git.vuxu.org/mirror/musl/
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).