-
Notifications
You must be signed in to change notification settings - Fork 251
Add cheap defense mechanisms #1171
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
It would be interesting to patch the fork(2) manual page to do the same thing in the EXAMPLES section. Would you mind sending a patch to linux-man@ too? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM. Thanks!
Reviewed-by: Alejandro Colomar <alx@kernel.org>
Calling exit might trigger cleanup functions registered through atexit. Since some programs use this mechanism, be extra cautious to never release passwd/group locks too early. Reviewed-by: Alejandro Colomar <alx@kernel.org> Signed-off-by: Tobias Stoeckmann <tobias@stoeckmann.org>
With glibc we can use "e" in mode argument to set O_CLOEXEC on opened files. The /etc/shadow and /etc/gshadow file handles should be protected to make sure that they are never passed to child processes by accident. Reviewed-by: Alejandro Colomar <alx@kernel.org> Signed-off-by: Tobias Stoeckmann <tobias@stoeckmann.org>
Since nobody commented, I'll merge now. Thanks! |
I've looked at the EXAMPLES section now, but I'm not sure if it really helps there. No exec call is performed and the whole main-function is printed without any atexit calls. Leaving the forked process with exit in this case is no problem and introducing _exit might make the code less readable or more confusing imho. |
I guess _exit(2) is never wrong there? Or is it sometimes wrong? If _exit(2) is always better (or at least equivalent), maybe it would be good to show it in the example, to promote it. And in the commit message we could add a detailed explanation. What do you think? |
I'll prepare a patch. Promoting that _exit exists might help people out there to at least read its manual page. We can discuss this further on man-pages mailing list if needed. |
Thanks! Indeed, I knew it existed, but had only seen it sporadically, and never knew what it was really good for, until you sent this PR. Using it in the manual page will hopefully help people know about it, and give it more visibility. |
Doesn't use of glibc extensions break functioning with non-glibc, like musl? Isn't it safer to use constructs like shadow = fopen (SGROUP_FILE, "re");
if (NULL == shadow )
shadow = fopen (SGROUP_FILE, "r"); ? Or, alternatively, detect extension in |
Hi,
On Sun, Feb 16, 2025 at 06:15:18PM -0800, Karlson2k wrote:
Karlson2k left a comment (shadow-maint/shadow#1171)
Doesn't use of glibc extensions break functioning with non-glibc, like musl?
Hmmm, I didn't know musl doesn't support this. It would be interesting
to get them to support it. I've CCd several interested parties in this
email.
Isn't it safe to use constructs like
``` C
shadow = fopen (SGROUP_FILE, "re");
if (NULL == shadow )
shadow = fopen (SGROUP_FILE, "r");
```
?
Is 'e' only available in glibc? Do other libraries consciously not
support O_CLOEXEC in fopen(3)?
I see that POSIX.1-2024 added the 'e' mode string character, so we're
using standard features (yeah, very modern ones, but still standard).
Is there any reason to not implement them, or is it just a matter of
time and contributors?
<https://pubs.opengroup.org/onlinepubs/9799919799/functions/fopen.html>
Or, alternatively, detect extension in `configure`?
If we have to...
Have a lovely day!
Alex
…
|
Hi, On Mon, Feb 17, 2025 at 10:42:11AM +0100, Alejandro Colomar wrote:
After reading musl's source code, it does support 'e'. And it does so
Cheers, |
On GNU/Linux I'm using glibc mainly, but my comment is not related to my specific use. The generic approach to writing reliable portable software:
Talking about this flag. It is supported by glibc, musl and uclibc-ng. Not supported by dietlibc. |
We make compromises between portability and security/safety. For portability reasons, one could argue using the ISO C89 dialect (we even had some fallback code for K&R C compilers until a few weeks ago), but that would result in code that is more unsafe. Fallback code also results in many untested paths, so we avoid it unless its really important. Since this extension is old (available in glibc since 2007, and in musl since 2012), and it provides important security features, and it has been standardized, I think it's okay to use it. Even back in 2012, it had already been accepted into the next POSIX standard (which would eventually become POSIX.1-2024), as the commit message from musl documents:
Good; it has wide support. dietlibc should implement it. |
Sure, it is up to maintainers whether to improve code portability or wait for others to adapt. 😉 |
As a sanity check, the major BSDs (Free,Net,Open) also support Thorsten, is it an undocumented feature? Or does MirBSD not implement O_CLOEXEC in fopen(3)? Anyone feel free to contact the dietlibc maintainer(s) to ask them to support this POSIX feature. |
(Not that there’s any need for the shadow package on MirBSD, but…)
On Mon, 17 Feb 2025, Alejandro Colomar wrote:
Thorsten, is it an undocumented feature? Or does MirBSD not implement
O_CLOEXEC in fopen(3)?
MirBSD didn’t even have O_CLOEXEC in open until recently (2016),
and I don’t expect it to provide latest POSIX features any time
soon other than on a need basis for now. I’m stuck fixing some
locale-related issues at the moment…
fopen(3) and friends currently support /^[rwa]b?\+?/ with [rwa]
and [+] actually doing something (src/lib/libc/stdio/flags.c).
In general, MirBSD doesn’t really target POSIX, that’s pretty
much insurmountable (especially the threads part) and in parts
(leap seconds) even against a law in my country, but I try to
bring mksh as close to POSIX as possible/sensible (all current
shells ignore the part where you’re supposed to assign a path
for builtins). Expect porting to MirBSD to be similar to porting
to a classic BSD or other Unix, not to a modern one. And, given
its slow progress at the moment it’s sensible to not consider it
much when porting software (not calling it abandoned, but I’ve
yet to get quite some working on it done before I can even use
it as daily box myself again).
Still thanks for thinking about it,
//mirabilos
|
The _exit(2) function is a better choice for exiting a child in many cases. Most prominently it avoids calls of functions registered with atexit(3) by the parent. There are valid reasons to call exit(3) and the example is actually one of them: flush FILE-based output. Since atexit(3) is never called, we could just stay with exit(3). Signed-off-by: Tobias Stoeckmann <tobias@stoeckmann.org> Message-ID: <tngwcffbrzbfkj6vrxgxpekrp3bzuftdy2mzow56xyfkrcna2w@nbgr2ourerxo> Link: <shadow-maint/shadow#1171> Signed-off-by: Alejandro Colomar <alx@kernel.org>
Before you read any further: No reachable issues exist in current code base (as far as I can tell)
But these defense mechanisms would have made reviewing easier because I could have skipped a few searches:
_exit
instead ofexit
after execution errorsAfter a fork and a failing exec, calling
exit
is not the best choice. Use_exit
instead because tools likegroupmod
etc. useadd_cleanup
to clean up whenexit
is called. If the child, which inherits these instructions, callsexit
by itself, these cleanup routines could release passwd/group locks too early. Again: Does not happen, because the code launches sub processes only after these cleanup routines have been already released again. Yet, better be safe than sorry.Even though
fopen
is used in lib/gshadow.c and lib/shadow.c, we can add the "e" mode to trigger O_CLOEXEC for systems which support this glibc extension. The file descriptor which keeps /etc/gshadow or /etc/shadow open is then guaranteed to not be passed down to a sub process. Again: Does not happen. The code carefully closes these file descriptors through dedicated function calls before sub processes are launched. Yet, better be safe than sorry again.