* Tweaking the program name for <err.h> functions @ 2024-03-07 22:24 Alejandro Colomar 2024-03-08 0:30 ` Guillem Jover 0 siblings, 1 reply; 44+ messages in thread From: Alejandro Colomar @ 2024-03-07 22:24 UTC (permalink / raw) To: libc-alpha, libbsd Cc: Serge E. Hallyn, Skyler Ferrante (RIT Student), Iker Pedrosa, Christian Brauner, shadow [-- Attachment #1: Type: text/plain, Size: 1406 bytes --] Hi, I'm interested in knowing if the <err.h> functions have a supported way of tweaking the prefix they print. GNU's similar <error.h> functions support changing extern char *program_invocation_name; for that, as per the error(3) manual page: The program name printed by error() is the value of the global variable program_invocation_name(3). program_invocation_name initially has the same value as main()’s argv[0]. The value of this variable can be modified to change the output of error(). I have experimented with err(3), and it seems you can tweak it by modifying 'program_invocation_short_name', but I'd like to know if that's supported and/or portable. I guess that since the pointer is a GNU extension, while the functions come from the BSDs, that's not portable, and thus not supported. Maybe it would be interesting to get the BSDs to support these pointers? The rationale is that the user controls argv[0], which might be problematic in some cases --think of setuid programs-- where a user could write arbitrary text to fd 2, which might be opened as a privileged file. In such programs, you likely want to hardcode that prefix, with something like program_invocation_short_name = "su"; Have a lovely day! Alex -- <https://www.alejandro-colomar.es/> Looking for a remote C programming job at the moment. [-- Attachment #2: signature.asc --] [-- Type: application/pgp-signature, Size: 833 bytes --] ^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: Tweaking the program name for <err.h> functions 2024-03-07 22:24 Tweaking the program name for <err.h> functions Alejandro Colomar @ 2024-03-08 0:30 ` Guillem Jover 2024-03-08 0:47 ` enh 2024-03-08 0:52 ` Alejandro Colomar 0 siblings, 2 replies; 44+ messages in thread From: Guillem Jover @ 2024-03-08 0:30 UTC (permalink / raw) To: Alejandro Colomar Cc: libc-alpha, libbsd, Serge E. Hallyn, Skyler Ferrante (RIT Student), Iker Pedrosa, Christian Brauner, shadow Hi! On Thu, 2024-03-07 at 23:24:32 +0100, Alejandro Colomar wrote: > I'm interested in knowing if the <err.h> functions have a supported way > of tweaking the prefix they print. > > GNU's similar <error.h> functions support changing > > extern char *program_invocation_name; > > for that, as per the error(3) manual page: > > The program name printed by error() is the value of the global > variable program_invocation_name(3). program_invocation_name > initially has the same value as main()’s argv[0]. The value of > this variable can be modified to change the output of error(). > > > I have experimented with err(3), and it seems you can tweak it by > modifying 'program_invocation_short_name', but I'd like to know if > that's supported and/or portable. I guess that since the pointer is a > GNU extension, while the functions come from the BSDs, that's not > portable, and thus not supported. That is not portable because the BSDs do not support that variable. But all BSDs for which I've got a checkout (FreeBSD, NetBSD, OpenBSD, DragonflyBSD) support changing it via setprogname(), but that's not available in glibc (libbsd provides it though). libbsd and cosmopolitan libc support setting it via setprogname() or program_invocation_short_name. musl libc supports setting it via program_invocation_short_name. uclibc might support __progname and/or program_invocation_short_name depending on how it has been configured, but it does not support setting the err(3) program name via those. > Maybe it would be interesting to get the BSDs to support these pointers? They already have a way to control the program name though. (And it seems to me that using functions instead of global variables is superior. :) Thanks, Guillem ^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: Tweaking the program name for <err.h> functions 2024-03-08 0:30 ` Guillem Jover @ 2024-03-08 0:47 ` enh 2024-03-08 0:52 ` Alejandro Colomar 1 sibling, 0 replies; 44+ messages in thread From: enh @ 2024-03-08 0:47 UTC (permalink / raw) To: Guillem Jover, Alejandro Colomar, libc-alpha, libbsd, Serge E. Hallyn, Skyler Ferrante (RIT Student), Iker Pedrosa, Christian Brauner, shadow On Thu, Mar 7, 2024 at 4:31 PM Guillem Jover <guillem@hadrons.org> wrote: > > Hi! > > On Thu, 2024-03-07 at 23:24:32 +0100, Alejandro Colomar wrote: > > I'm interested in knowing if the <err.h> functions have a supported way > > of tweaking the prefix they print. > > > > GNU's similar <error.h> functions support changing > > > > extern char *program_invocation_name; > > > > for that, as per the error(3) manual page: > > > > The program name printed by error() is the value of the global > > variable program_invocation_name(3). program_invocation_name > > initially has the same value as main()’s argv[0]. The value of > > this variable can be modified to change the output of error(). > > > > > > I have experimented with err(3), and it seems you can tweak it by > > modifying 'program_invocation_short_name', but I'd like to know if > > that's supported and/or portable. I guess that since the pointer is a > > GNU extension, while the functions come from the BSDs, that's not > > portable, and thus not supported. > > That is not portable because the BSDs do not support that variable. > But all BSDs for which I've got a checkout (FreeBSD, NetBSD, OpenBSD, > DragonflyBSD) support changing it via setprogname(), but that's not > available in glibc (libbsd provides it though). (yeah, bionic -- having its <err.h> based on OpenBSD -- uses setprogname() for this.) > libbsd and cosmopolitan libc support setting it via setprogname() or > program_invocation_short_name. > > musl libc supports setting it via program_invocation_short_name. > > uclibc might support __progname and/or program_invocation_short_name > depending on how it has been configured, but it does not support > setting the err(3) program name via those. > > > Maybe it would be interesting to get the BSDs to support these pointers? > > They already have a way to control the program name though. (And > it seems to me that using functions instead of global variables is > superior. :) > > Thanks, > Guillem ^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: Tweaking the program name for <err.h> functions 2024-03-08 0:30 ` Guillem Jover 2024-03-08 0:47 ` enh @ 2024-03-08 0:52 ` Alejandro Colomar 2024-03-09 15:02 ` [musl] " Rich Felker 1 sibling, 1 reply; 44+ messages in thread From: Alejandro Colomar @ 2024-03-08 0:52 UTC (permalink / raw) To: Guillem Jover, libc-alpha, musl Cc: libbsd, Serge E. Hallyn, Skyler Ferrante (RIT Student), Iker Pedrosa, Christian Brauner, shadow [-- Attachment #1: Type: text/plain, Size: 1881 bytes --] [TO += musl] Hi! On Fri, Mar 08, 2024 at 01:30:51AM +0100, Guillem Jover wrote: > That is not portable because the BSDs do not support that variable. > But all BSDs for which I've got a checkout (FreeBSD, NetBSD, OpenBSD, > DragonflyBSD) support changing it via setprogname(), but that's not > available in glibc (libbsd provides it though). > > libbsd and cosmopolitan libc support setting it via setprogname() or > program_invocation_short_name. > > musl libc supports setting it via program_invocation_short_name. > > uclibc might support __progname and/or program_invocation_short_name > depending on how it has been configured, but it does not support > setting the err(3) program name via those. Hmmm. $ cat err.c #define _GNU_SOURCE #include <bsd/stdlib.h> #include <err.h> #include <errno.h> #include <error.h> int main(void) { program_invocation_name = "foo"; program_invocation_short_name = "bar"; setprogname("baz"); error(0, errno, "fmt string"); err(1, "fmt2"); } $ cc -Wall -Wextra err.c -lbsd $ ./a.out foo: fmt string baz: fmt2: Success This would already be portable enough for what I want, except that libbsd isn't very welcome in some OSes as a core library. I guess I'll need libc support. > > > Maybe it would be interesting to get the BSDs to support these pointers? > > They already have a way to control the program name though. (And > it seems to me that using functions instead of global variables is > superior. :) Indeed. I didn't know about such function. I'll reformulate my original suggestion to this other one: How about adding setprogname(3) (and getprogname(3)) to GNU and musl libc? > > Thanks, > Guillem Have a lovely night! Alex -- <https://www.alejandro-colomar.es/> Looking for a remote C programming job at the moment. [-- Attachment #2: signature.asc --] [-- Type: application/pgp-signature, Size: 833 bytes --] ^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [musl] Re: Tweaking the program name for <err.h> functions 2024-03-08 0:52 ` Alejandro Colomar @ 2024-03-09 15:02 ` Rich Felker 2024-03-09 15:49 ` Alejandro Colomar 0 siblings, 1 reply; 44+ messages in thread From: Rich Felker @ 2024-03-09 15:02 UTC (permalink / raw) To: Alejandro Colomar Cc: Guillem Jover, libc-alpha, musl, libbsd, Serge E. Hallyn, Skyler Ferrante (RIT Student), Iker Pedrosa, Christian Brauner On Fri, Mar 08, 2024 at 01:52:28AM +0100, Alejandro Colomar wrote: > [TO += musl] > > Hi! > > On Fri, Mar 08, 2024 at 01:30:51AM +0100, Guillem Jover wrote: > > That is not portable because the BSDs do not support that variable. > > But all BSDs for which I've got a checkout (FreeBSD, NetBSD, OpenBSD, > > DragonflyBSD) support changing it via setprogname(), but that's not > > available in glibc (libbsd provides it though). > > > > libbsd and cosmopolitan libc support setting it via setprogname() or > > program_invocation_short_name. > > > > musl libc supports setting it via program_invocation_short_name. > > > > uclibc might support __progname and/or program_invocation_short_name > > depending on how it has been configured, but it does not support > > setting the err(3) program name via those. > > Hmmm. > > $ cat err.c > #define _GNU_SOURCE > #include <bsd/stdlib.h> > #include <err.h> > #include <errno.h> > #include <error.h> > > > int > main(void) > { > program_invocation_name = "foo"; > program_invocation_short_name = "bar"; > setprogname("baz"); > > error(0, errno, "fmt string"); > err(1, "fmt2"); > } > $ cc -Wall -Wextra err.c -lbsd > $ ./a.out > foo: fmt string > baz: fmt2: Success > > This would already be portable enough for what I want, except that > libbsd isn't very welcome in some OSes as a core library. I guess I'll > need libc support. > > > > > > Maybe it would be interesting to get the BSDs to support these pointers? > > > > They already have a way to control the program name though. (And > > it seems to me that using functions instead of global variables is > > superior. :) > > Indeed. I didn't know about such function. I'll reformulate my > original suggestion to this other one: > > How about adding setprogname(3) (and getprogname(3)) to GNU and musl > libc? I really don't think they meet the criteria for inclusion. They don't have historical cross platform precedent, they're not something we've hit existing applications failing to build for lack of, they don't let you do anything you couldn't already do, and the semantics would be unclear (do they just configure the legacy err.h functions? set __progname/program_invocation_short_name? modify argv[0]?) The entire err.h function set in musl is 67 lines that compile down to less than 500 bytes of machine code. If there's not a portable way to configure them the way you want, and you refuse to run a configure script of some sort to determine if the setprogname function some systems need exists, the simpler solution, rather than trying to get new contracts into libc and wait for them to be widely available, is to copy-and-paste those 67 lines and customize them as needed in your program, no? Rich ^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [musl] Re: Tweaking the program name for <err.h> functions 2024-03-09 15:02 ` [musl] " Rich Felker @ 2024-03-09 15:49 ` Alejandro Colomar 2024-03-09 18:35 ` Andreas Schwab ` (2 more replies) 0 siblings, 3 replies; 44+ messages in thread From: Alejandro Colomar @ 2024-03-09 15:49 UTC (permalink / raw) To: Rich Felker Cc: Guillem Jover, libc-alpha, musl, libbsd, Serge E. Hallyn, Skyler Ferrante (RIT Student), Iker Pedrosa, Christian Brauner [-- Attachment #1: Type: text/plain, Size: 3625 bytes --] Hi Rich, On Sat, Mar 09, 2024 at 10:02:58AM -0500, Rich Felker wrote: > > How about adding setprogname(3) (and getprogname(3)) to GNU and musl > > libc? > > I really don't think they meet the criteria for inclusion. They don't > have historical cross platform precedent, they're not something we've > hit existing applications failing to build for lack of, they don't let > you do anything you couldn't already do, and the semantics would be > unclear I would ask the BSD authors of the API to learn all the implications of the pair of functions. I don't know them. Maybe Guillem knows. > (do they just configure the > legacy err.h functions? Why would you call err.h legacy? What do you offer to use instead? snprintf(3) + perror(3) + exit(3)? How about bugs in such NIH cases? You'd fix them in every project where you've written the same bug? That's why we have libraries. I don't mind if the entirety of err.h was moved to a liberr standalone library, but you have kidnapped those APIs in libc. Would you release them? > set > __progname/program_invocation_short_name? modify argv[0]?) Would you promise to keep __progname/program_invocation_short_name as a way to configure err.h in musl/glibc? If so, then maybe one can write a portable library that wraps the unportable set of libc's. But since you own err.h, _you_ must be the one making a contract. It's up to you to decide which contract you want to offer. I suggest making the same contract present in the BSDs. > > The entire err.h function set in musl is 67 lines that compile down to > less than 500 bytes of machine code. If there's not a portable way to > configure them the way you want, There's not a portable way to configure them, AFAIK. You could say it's glibc and musl's fault, for importing the err.h functions without importing setprogname(3). In the BSD world, where these APIs originated, they seem to be configurable portably (within BSDs). And with libbsd, you can get relative portability to other systems. You have a problem when you want to call these functions in a core package, like shadow, because some distributions refuse to include libbsd in their core packages. > and you refuse to run a configure > script of some sort to determine if the setprogname function some > systems need exists, the simpler solution, I don't refuse to do that, but it means I also need to write code to handle the case where it's not available, and do some non-portable stuff in that case. In fact, I'll need to do that anyway, at least for some years until all systems I care about have a version of libc that has the functions. But, I'd like to be able to remove that code in, say, 5 or 10 years from now. > rather than trying to get > new contracts into libc and wait for them to be widely available, is > to copy-and-paste those 67 lines and customize them as needed in your > program, no? I partially agree with you, in that I don't like adding new contracts into libc. But that contract was already added broken into glibc and musl. I suggest you remove err.h from libc, and let a standalone library to implement them separately, allowing to configure them. I don't agree with your suggestion of going the NIH way. Maybe I'll push a bit harder for inclusion of libbsd in distributions. Then it'll be the problem of distributors to either package libbsd, or do a lot of work to patch projects to not rely on libbsd. It's not a bad idea, actually. > > Rich Have a lovely day! Alex -- <https://www.alejandro-colomar.es/> [-- Attachment #2: signature.asc --] [-- Type: application/pgp-signature, Size: 833 bytes --] ^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: Tweaking the program name for <err.h> functions 2024-03-09 15:49 ` Alejandro Colomar @ 2024-03-09 18:35 ` Andreas Schwab 2024-03-09 18:46 ` Alejandro Colomar 2024-03-09 21:44 ` Thorsten Glaser 2024-03-10 6:01 ` NRK 2 siblings, 1 reply; 44+ messages in thread From: Andreas Schwab @ 2024-03-09 18:35 UTC (permalink / raw) To: Alejandro Colomar Cc: Rich Felker, musl, Guillem Jover, libc-alpha, libbsd, Serge E. Hallyn, Skyler Ferrante (RIT Student), Iker Pedrosa, Christian Brauner On Mär 09 2024, Alejandro Colomar wrote: > There's not a portable way to configure them, AFAIK. You could say it's > glibc and musl's fault, for importing the err.h functions without > importing setprogname(3). When glibc imported err, setprogname didn't exist yet. -- Andreas Schwab, schwab@linux-m68k.org GPG Key fingerprint = 7578 EB47 D4E5 4D69 2510 2552 DF73 E780 A9DA AEC1 "And now for something completely different." ^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: Tweaking the program name for <err.h> functions 2024-03-09 18:35 ` Andreas Schwab @ 2024-03-09 18:46 ` Alejandro Colomar 2024-03-09 19:18 ` [musl] " Markus Wichmann 2024-03-09 19:25 ` Rich Felker 0 siblings, 2 replies; 44+ messages in thread From: Alejandro Colomar @ 2024-03-09 18:46 UTC (permalink / raw) To: Andreas Schwab Cc: Rich Felker, musl, Guillem Jover, libc-alpha, libbsd, Serge E. Hallyn, Skyler Ferrante (RIT Student), Iker Pedrosa, Christian Brauner [-- Attachment #1: Type: text/plain, Size: 768 bytes --] Hi Andreas, On Sat, Mar 09, 2024 at 07:35:27PM +0100, Andreas Schwab wrote: > On Mär 09 2024, Alejandro Colomar wrote: > > > There's not a portable way to configure them, AFAIK. You could say it's > > glibc and musl's fault, for importing the err.h functions without > > importing setprogname(3). > > When glibc imported err, setprogname didn't exist yet. Thanks. Then BSD extended the contract. That's still a problem of musl and glibc. The API is deficient without setprogname(3), and should be fixed. I think libc should either drop err.h and let another library take ownership of the API, or add a way to configure it, hopefully being compatible with the BSDs. No? Have a lovely day! Alex -- <https://www.alejandro-colomar.es/> [-- Attachment #2: signature.asc --] [-- Type: application/pgp-signature, Size: 833 bytes --] ^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [musl] Re: Tweaking the program name for <err.h> functions 2024-03-09 18:46 ` Alejandro Colomar @ 2024-03-09 19:18 ` Markus Wichmann 2024-03-09 19:25 ` Rich Felker 1 sibling, 0 replies; 44+ messages in thread From: Markus Wichmann @ 2024-03-09 19:18 UTC (permalink / raw) To: musl Cc: Andreas Schwab, Rich Felker, Guillem Jover, libc-alpha, libbsd, Serge E. Hallyn, Skyler Ferrante (RIT Student), Iker Pedrosa, Christian Brauner Am Sat, Mar 09, 2024 at 07:46:38PM +0100 schrieb Alejandro Colomar: > Thanks. Then BSD extended the contract. That's still a problem of musl > and glibc. The API is deficient without setprogname(3), and should be > fixed. I think libc should either drop err.h and let another library > take ownership of the API, or add a way to configure it, hopefully being > compatible with the BSDs. No? > Well, that's the problem with library code. musl will never drop existing functionality for ABI stability alone. The most that was ever done was dropping the LFS64 symbols, and there the symbols are only hidden from the linker, but the dynamic linker can still find them. So no, musl will not be dropping the err.h functions. Of course, you can install a library that overrides these symbols. libc is always linked in last, and UNIX has a long and storied history of superseding symbols. In this particular case, though, if BSD extended the contract, should the onus of checking not be on the application? I think the application should check whether the extended or basic contract is in effect. Ciao, Markus ^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [musl] Re: Tweaking the program name for <err.h> functions 2024-03-09 18:46 ` Alejandro Colomar 2024-03-09 19:18 ` [musl] " Markus Wichmann @ 2024-03-09 19:25 ` Rich Felker 1 sibling, 0 replies; 44+ messages in thread From: Rich Felker @ 2024-03-09 19:25 UTC (permalink / raw) To: Alejandro Colomar Cc: Andreas Schwab, musl, Guillem Jover, libc-alpha, libbsd, Serge E. Hallyn, Skyler Ferrante (RIT Student), Iker Pedrosa, Christian Brauner On Sat, Mar 09, 2024 at 07:46:38PM +0100, Alejandro Colomar wrote: > Hi Andreas, > > On Sat, Mar 09, 2024 at 07:35:27PM +0100, Andreas Schwab wrote: > > On Mär 09 2024, Alejandro Colomar wrote: > > > > > There's not a portable way to configure them, AFAIK. You could say it's > > > glibc and musl's fault, for importing the err.h functions without > > > importing setprogname(3). > > > > When glibc imported err, setprogname didn't exist yet. > > Thanks. Then BSD extended the contract. That's still a problem of musl > and glibc. The API is deficient without setprogname(3), and should be > fixed. I think libc should either drop err.h and let another library > take ownership of the API, or add a way to configure it, hopefully being > compatible with the BSDs. No? libc can't drop anything at the binary level because that's breaking existing dynamic linked programs. It could remove the header, but that has its own problems. The err.h interfaces are called "legacy" in musl (appearing in src/legacy) because they are not part of any standard and are just something a bunch of ancient crufty code used and assumed was there. They were added to musl early on (back in 2011) because they were very-low-cost to add, no interaction with anything else (they didn't even support progname at the time), and made it easier for people who were getting musl-based systems up for the first time. They don't do anything significant you can't do yourself with fprintf/perror, the err forms exit without giving you any opportunity for clean exit (except installing atexit handlers, which are their own mess of global state), and as implmented aren't really multithread-friendly (they don't lock around the multiple stdio calls to make the error output atomic). Basically, they just go with a really, really antiquated programming model, and do not seem like the sort of thing anyone should be investing development time into improving *or* intentionally breaking. I agree there are sometimes hazards to copy-and-paste, but in the case of these, a copy-and-paste version (or just a rewrite) where you can wire up your own better behaviors more suited to your application is really *better* than using them as-is. If you have your own header and definition for these functions, the ones in libc will not even get used. There is no "ownership" conflict. Rich ^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [musl] Re: Tweaking the program name for <err.h> functions 2024-03-09 15:49 ` Alejandro Colomar 2024-03-09 18:35 ` Andreas Schwab @ 2024-03-09 21:44 ` Thorsten Glaser 2024-03-10 6:01 ` NRK 2 siblings, 0 replies; 44+ messages in thread From: Thorsten Glaser @ 2024-03-09 21:44 UTC (permalink / raw) To: Alejandro Colomar Cc: Guillem Jover, libc-alpha, musl, libbsd, Serge E. Hallyn, Skyler Ferrante (RIT Student), Iker Pedrosa, Christian Brauner Alejandro Colomar dixit: >You could say it's >glibc and musl's fault, for importing the err.h functions without >importing setprogname(3). In the BSD world, where these APIs >originated, they seem to be configurable portably (within BSDs). And Nope. They are rather new, there are BSDs without them (where “extern const char *__progname;” is still used). bye, //mirabilos -- FWIW, I'm quite impressed with mksh interactively. I thought it was much *much* more bare bones. But it turns out it beats the living hell out of ksh93 in that respect. I'd even consider it for my daily use if I hadn't wasted half my life on my zsh setup. :-) -- Frank Terbeck in #!/bin/mksh ^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [musl] Re: Tweaking the program name for <err.h> functions 2024-03-09 15:49 ` Alejandro Colomar 2024-03-09 18:35 ` Andreas Schwab 2024-03-09 21:44 ` Thorsten Glaser @ 2024-03-10 6:01 ` NRK 2024-03-10 13:17 ` Alejandro Colomar 2 siblings, 1 reply; 44+ messages in thread From: NRK @ 2024-03-10 6:01 UTC (permalink / raw) To: Alejandro Colomar Cc: Rich Felker, Guillem Jover, libc-alpha, musl, libbsd, Serge E. Hallyn, Skyler Ferrante (RIT Student), Iker Pedrosa, Christian Brauner > What do you offer to use instead? snprintf(3) + perror(3) + exit(3)? No need to have an intermediate buffer with snprintf when you can just use vfprintf directly. > I suggest you remove err.h from libc, and let a standalone library to > implement them separately, allowing to configure them. These are not mutually exclusive. You can have err.h in libc while also having them as separate library. And besides, these are not good interfaces anyways. Aside from what Rich already said, you'll realize this soon when you need to use various posix_* or pthread_* functions which don't set the errno and instead return an error code. Also, I don't think your fear of "NIH bug" is well grounded. This is not some highly complicated error-prone code, it's just simple logging facility. I am aware that there exists certain programming cultures [*] where having to write code instead of "import leftpad" is seen as taboo of the highest order. But in this case you don't even *have to* write anything when you can just copy err.c from musl and customize it. (* Counterculture to this also exists, such as Go's "A little copying is better than a little dependency" proverb for example.) - NRK ^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [musl] Re: Tweaking the program name for <err.h> functions 2024-03-10 6:01 ` NRK @ 2024-03-10 13:17 ` Alejandro Colomar 2024-03-10 14:01 ` NRK 0 siblings, 1 reply; 44+ messages in thread From: Alejandro Colomar @ 2024-03-10 13:17 UTC (permalink / raw) To: NRK Cc: Rich Felker, Guillem Jover, libc-alpha, musl, libbsd, Serge E. Hallyn, Skyler Ferrante (RIT Student), Iker Pedrosa, Christian Brauner [-- Attachment #1: Type: text/plain, Size: 4195 bytes --] Hi NRK, On Sun, Mar 10, 2024 at 06:01:14AM +0000, NRK wrote: > > What do you offer to use instead? snprintf(3) + perror(3) + exit(3)? > > No need to have an intermediate buffer with snprintf when you can just > use vfprintf directly. For an interface that prefixes the program name, I need to either call [v]fprintf(3) twice, or add locks; that is: lock() fprintf("%s: ", __progname); vfprintf(...); unlock(); or prepare the buffer and call it just once. Because I want to call it as foo("reason");, not having to use __progname all the time. > > > I suggest you remove err.h from libc, and let a standalone library to > > implement them separately, allowing to configure them. > > These are not mutually exclusive. You can have err.h in libc while also > having them as separate library. If I #include <err.h>, glibc considers those as reserved names. <https://www.gnu.org/software/libc/manual/html_node/Reserved-Names.html> | All other library names are reserved if your program explicitly | includes the header file that defines or declares them. I guess it would work, because of weak symbols, but the manual explicitly says don't do this. > And besides, these are not good interfaces anyways. Aside from what Rich > already said, you'll realize this soon when you need to use various > posix_* or pthread_* functions which don't set the errno and instead > return an error code. There's errc(3), and also warnc() (Guillem, libbsd is missing the link pages for warn*() variants!), to which you can pass an errno-like code. This isn't supported by glibc, but is available in libbsd (and of course, in the BSDs; at least I checked OpenBSD). And for the finctions that don't report an errno-like, like the gai_error(3) ones, you can use errx(3), and also warnx(3). These are supported in glibc. So these are actually quite well suited for different kinds of error- reporting functions. Regarding multi-threaded programs: If you're recommending writing a version because it's easy, but then you say it needs locking, well, I wouldn't say writing a locking version is easy. > > Also, I don't think your fear of "NIH bug" is well grounded. This is not > some highly complicated error-prone code, it's just simple logging > facility. locking code is error-prone, I'd say. > > I am aware that there exists certain programming cultures [*] where > having to write code instead of "import leftpad" is seen as taboo of the > highest order. But in this case you don't even *have to* write anything > when you can just copy err.c from musl and customize it. I think the BSD err.h functions are actually quite well designed for single-threaded programs (still the vast majority of software). And for multi-threaded versions, we just need to convince the BSD maintainers that they need to add locking. If glibc and musl don't consider these APIs as useless and legacy, and fix them, then maybe the BSDs follow. Again, is there anything better in glibc or musl? Something that prefixes "$progname: " and appends the errno message? Yeah, you could write fprintf("%s: ...", program_invocation_short_name, ...) all the time? or write a wrapper that calls fprintf("%s: ", program_invocation_short_name), but then you need to add locking? and then you need to set program_invocation_short_name = "su"? And then add *c() for functions that return an errno-like code? And then add *x() variants for functions that don't use errno-like codes? Oh well, you're basically writing the err.h interface. The interface is good. It's the implementation that has small problems, but I say let's fix them. This is certainly not what I want to be doing for every project. And as said above, having an overlay library that defines err.h is a violation of glibc's reserved names. Not too bad if done in a library, but certainly not that I'd do in every project. Have a lovely day! Alex > > (* Counterculture to this also exists, such as Go's "A little copying > is better than a little dependency" proverb for example.) > > - NRK -- <https://www.alejandro-colomar.es/> [-- Attachment #2: signature.asc --] [-- Type: application/pgp-signature, Size: 833 bytes --] ^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [musl] Re: Tweaking the program name for <err.h> functions 2024-03-10 13:17 ` Alejandro Colomar @ 2024-03-10 14:01 ` NRK 2024-03-10 19:39 ` Rich Felker 0 siblings, 1 reply; 44+ messages in thread From: NRK @ 2024-03-10 14:01 UTC (permalink / raw) To: Alejandro Colomar Cc: Rich Felker, Guillem Jover, libc-alpha, musl, libbsd, Serge E. Hallyn, Skyler Ferrante (RIT Student), Iker Pedrosa, Christian Brauner > or add locks; that is: > > lock() > fprintf("%s: ", __progname); > vfprintf(...); > unlock(); > > [...] > > locking code is error-prone, I'd say. These interfaces do not guarantee the output to be atomic. If you were expecting it to be atomic then that's just *another* reason to roll it yourself because a good ton of existing implementation doesn't lock. https://github.com/bminor/musl/blob/master/src/legacy/err.c https://github.com/freebsd/freebsd-src/blob/main/lib/libc/gen/err.c https://github.com/openbsd/src/blob/master/lib/libc/gen/verr.c https://cgit.freedesktop.org/libbsd/tree/src/err.c musl doesn't, freebsd doesn't, openbsd doesn't, libbsd doesn't. Out of the 5 implementations I checked, only glibc seems to lock. > There's errc(3) Which doesn't exist on musl, I don't think it exists on glibc either. So you're back to "DIY or depend on libbsd" land if you use this function. > Again, is there anything better in glibc or musl? > Something that prefixes "$progname: " and appends the errno message? > [...] > And then add *c() for functions that return an errno-like code? And > then add *x() variants for functions that don't use errno-like codes? glibc has error(3), and program_invocation_name(3) to customize $progname. Interface wise, I find it more pleasant than the err.h gang. Having an explicit `errnum` argument serves all 3 usecases (no errno, errno, errno-like return code) without having multiple functions with x/y/z/c suffix. (One issue I have with glibc's error() interface is that doing both warning and fatal error through same function weakens static analyzers. I'd split up the two and mark the fatal version with _Noreturn for better warnings/static-analysis.) But this function is even less portable (no musl or *BSD support last I checked). So you're back to square one. - NRK ^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [musl] Re: Tweaking the program name for <err.h> functions 2024-03-10 14:01 ` NRK @ 2024-03-10 19:39 ` Rich Felker 2024-03-10 22:25 ` Alejandro Colomar 2024-03-10 23:22 ` Thorsten Glaser 0 siblings, 2 replies; 44+ messages in thread From: Rich Felker @ 2024-03-10 19:39 UTC (permalink / raw) To: NRK Cc: Alejandro Colomar, Guillem Jover, libc-alpha, musl, libbsd, Serge E. Hallyn, Skyler Ferrante (RIT Student), Iker Pedrosa, Christian Brauner On Sun, Mar 10, 2024 at 02:01:18PM +0000, NRK wrote: > > or add locks; that is: > > > > lock() > > fprintf("%s: ", __progname); > > vfprintf(...); > > unlock(); > > > > [...] > > > > locking code is error-prone, I'd say. > > These interfaces do not guarantee the output to be atomic. If you were > expecting it to be atomic then that's just *another* reason to roll it > yourself because a good ton of existing implementation doesn't lock. Also, the whole reason this comes up is gratuitous impedance mismatch bringing in the need for a separate fprintf call to do the prefix (and possibly newline suffix, if you want that). They could have been designed to be one-line macros, ala... #define warn(f,...) fprintf(stderr, "%s: " f, __progname, __VA_ARGS__) or similar. I really see no justifiable reason for people writing new software to want to enhance the err.h functions rather than just rolling a one-line macro that can be better tailored to their specific needs. Rich ^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [musl] Re: Tweaking the program name for <err.h> functions 2024-03-10 19:39 ` Rich Felker @ 2024-03-10 22:25 ` Alejandro Colomar 2024-03-10 23:22 ` Thorsten Glaser 1 sibling, 0 replies; 44+ messages in thread From: Alejandro Colomar @ 2024-03-10 22:25 UTC (permalink / raw) To: Rich Felker Cc: NRK, Guillem Jover, libc-alpha, musl, libbsd, Serge E. Hallyn, Skyler Ferrante (RIT Student), Iker Pedrosa, Christian Brauner [-- Attachment #1: Type: text/plain, Size: 2479 bytes --] Hi Rich, On Sun, Mar 10, 2024 at 03:39:56PM -0400, Rich Felker wrote: > Also, the whole reason this comes up is gratuitous impedance mismatch > bringing in the need for a separate fprintf call to do the prefix (and > possibly newline suffix, if you want that). They could have been > designed to be one-line macros, ala... > > #define warn(f,...) fprintf(stderr, "%s: " f, __progname, __VA_ARGS__) > > or similar. Hmmm, it's an interesting definition. That's actually warnx(3), but you can write the others in terms of that: #define setprogname(n) do { program_invocation_short_name = n; } while (0) #define getprogname() (program_invocation_short_name) #define warnx(f, ...) fprintf(stderr, "%s: " f "\n", getprogname(), ##__VA_ARGS__) #define warnc(c, f, ...) warnx(f ": %s", ##__VA_ARGS__, strerror(c)) #define warn(f, ...) warnc(errno, f, ##__VA_ARGS__) #define errx(x, ...) do { warnx(__VA_ARGS__); exit(x); } while (0) #define errc(x, ...) do { warnc(__VA_ARGS__); exit(x); } while (0) #define err(x, ...) do { warn(__VA_ARGS__); exit(x); } while (0) The main problem is still portability. But I guess with some cpp(1) I can get it to work in the systems I care about. libc couldn't implement it this way, because complex things like "%2ms" wouldn't work. But it could be interesting in a multi-threaded program, where such complex conversion specifications don't occur. Still, that's not my case. I guess I'll do this: #if (!WITH_LIBBSD) inline void setprogname(const char *progname) { program_invocation_short_name = Basename(name); } inline const char * getprogname(void) { return program_invocation_short_name; } #endif > I really see no justifiable reason for people writing new > software to want to enhance the err.h functions rather than just I don't really need to enhance them. Just a statement that the current behavior will hold would be good enough. I would need to know that setting 'program_invocation_short_name' will set the prefix of these functions. That's already the current behavior, and I guess that you'll keep it, even if just for backwards compatibility; more so, considering your aversion to fix or break these APIs, or to change them at all. > rolling a one-line macro that can be better tailored to their specific > needs. > > Rich Have a lovely night! Alex -- <https://www.alejandro-colomar.es/> [-- Attachment #2: signature.asc --] [-- Type: application/pgp-signature, Size: 833 bytes --] ^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [musl] Re: Tweaking the program name for <err.h> functions 2024-03-10 19:39 ` Rich Felker 2024-03-10 22:25 ` Alejandro Colomar @ 2024-03-10 23:22 ` Thorsten Glaser 2024-03-10 23:44 ` Rich Felker 1 sibling, 1 reply; 44+ messages in thread From: Thorsten Glaser @ 2024-03-10 23:22 UTC (permalink / raw) To: musl Cc: NRK, Alejandro Colomar, Guillem Jover, libc-alpha, libbsd, Serge E. Hallyn, Skyler Ferrante (RIT Student), Iker Pedrosa, Christian Brauner Rich Felker dixit: >possibly newline suffix, if you want that). They could have been >designed to be one-line macros, ala... Nope. No __VA_ARGS__ and especially no ##__VA_ARGS__ in C89, back then. bye, //mirabilos -- 15:41⎜<Lo-lan-do:#fusionforge> Somebody write a testsuite for helloworld :-) ^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [musl] Re: Tweaking the program name for <err.h> functions 2024-03-10 23:22 ` Thorsten Glaser @ 2024-03-10 23:44 ` Rich Felker 2024-03-11 0:19 ` Thorsten Glaser 0 siblings, 1 reply; 44+ messages in thread From: Rich Felker @ 2024-03-10 23:44 UTC (permalink / raw) To: Thorsten Glaser Cc: musl, NRK, Alejandro Colomar, Guillem Jover, libc-alpha, libbsd, Serge E. Hallyn, Skyler Ferrante (RIT Student), Iker Pedrosa, Christian Brauner On Sun, Mar 10, 2024 at 11:22:51PM +0000, Thorsten Glaser wrote: > Rich Felker dixit: > > >possibly newline suffix, if you want that). They could have been > >designed to be one-line macros, ala... > > Nope. > > No __VA_ARGS__ and especially no ##__VA_ARGS__ in C89, back then. Well yeah, "could have been" was poor wording by me. At the time, the options didn't exist. But someone doing that kind of interface now can use these tools, or just design the interface differently. With that said, while I'll grant that there are exceptions, it's generally my impression that if you're pasting in the name of the program from argv[0] programmatically because it can't just be part of the string literal, because the string literal appears in modular library code that gets called from multiple utilities, then printing an error message (and even worse, exiting, if you do that too), rather than returning meaningful error information up to the caller for it to handle/display, is just really sloppy, low-quality programming. Rich ^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [musl] Re: Tweaking the program name for <err.h> functions 2024-03-10 23:44 ` Rich Felker @ 2024-03-11 0:19 ` Thorsten Glaser 2024-03-11 0:46 ` Alejandro Colomar 0 siblings, 1 reply; 44+ messages in thread From: Thorsten Glaser @ 2024-03-11 0:19 UTC (permalink / raw) To: Rich Felker Cc: musl, NRK, Alejandro Colomar, Guillem Jover, libc-alpha, libbsd, Serge E. Hallyn, Skyler Ferrante (RIT Student), Iker Pedrosa, Christian Brauner Rich Felker dixit: >the string literal, because the string literal appears in modular >library code that gets called from multiple utilities, then printing >an error message (and even worse, exiting, if you do that too), rather >than returning meaningful error information up to the caller for it to >handle/display, is just really sloppy, low-quality programming. Libraries totally should not call exit and thus not err/errx, and warn/warnx is… also questionable at best. But modularised code that builds a shared object and a few binaries using it? Why not. The thing I don’t get is why changing __progname is desired, but I guess everyone has use cases for something. bye, //mirabilos -- (gnutls can also be used, but if you are compiling lynx for your own use, there is no reason to consider using that package) -- Thomas E. Dickey on the Lynx mailing list, about OpenSSL ^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [musl] Re: Tweaking the program name for <err.h> functions 2024-03-11 0:19 ` Thorsten Glaser @ 2024-03-11 0:46 ` Alejandro Colomar 2024-03-11 14:46 ` Skyler Ferrante (RIT Student) 0 siblings, 1 reply; 44+ messages in thread From: Alejandro Colomar @ 2024-03-11 0:46 UTC (permalink / raw) To: Thorsten Glaser Cc: Rich Felker, musl, NRK, Guillem Jover, libc-alpha, libbsd, Serge E. Hallyn, Skyler Ferrante (RIT Student), Iker Pedrosa, Christian Brauner [-- Attachment #1: Type: text/plain, Size: 1419 bytes --] Hi Thorsten, On Mon, Mar 11, 2024 at 12:19:27AM +0000, Thorsten Glaser wrote: > Rich Felker dixit: > > >the string literal, because the string literal appears in modular > >library code that gets called from multiple utilities, then printing > >an error message (and even worse, exiting, if you do that too), rather > >than returning meaningful error information up to the caller for it to > >handle/display, is just really sloppy, low-quality programming. > > Libraries totally should not call exit and thus not err/errx, > and warn/warnx is… also questionable at best. > > But modularised code that builds a shared object and a few > binaries using it? Why not. > > The thing I don’t get is why changing __progname is desired, > but I guess everyone has use cases for something. setuid programs. Consider that a setuid program accidentally opens a privileged file in fd 2. Now what happens if a random user can trigger that accident, and write arbitrary text to a privileged file, just by calling that setuid program with execlp("su", "inject this stuff", ...)? Bad stuff. Have a lovely night! Alex > > bye, > //mirabilos > -- > (gnutls can also be used, but if you are compiling lynx for your own use, > there is no reason to consider using that package) > -- Thomas E. Dickey on the Lynx mailing list, about OpenSSL -- <https://www.alejandro-colomar.es/> [-- Attachment #2: signature.asc --] [-- Type: application/pgp-signature, Size: 833 bytes --] ^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [musl] Re: Tweaking the program name for <err.h> functions 2024-03-11 0:46 ` Alejandro Colomar @ 2024-03-11 14:46 ` Skyler Ferrante (RIT Student) 2024-03-11 15:09 ` Andreas Schwab 0 siblings, 1 reply; 44+ messages in thread From: Skyler Ferrante (RIT Student) @ 2024-03-11 14:46 UTC (permalink / raw) To: Alejandro Colomar Cc: Thorsten Glaser, Rich Felker, musl, NRK, Guillem Jover, libc-alpha, libbsd, Serge E. Hallyn, Iker Pedrosa, Christian Brauner Hi, "Consider that a setuid program accidentally opens a privileged file in fd 2." It seems like this is the main thing shadow-utils (and other projects) should be concerned about. Every setuid/setgid program should check for fd 0,1,2 being open at the start of execution, and either abort or open new fds to /dev/null to prevent file descriptor omission attacks. Any defenses used to prevent exploitation when a setuid/setgid program does not do this, seems unlikely to succeed. All an attacker would need would be an attacker defined string going to stdout/stderr. Argv[0] is useful for this, but it is not the only option. Usernames/group names/etc. are chosen by attackers. Preventing these from being printed might increase security a bit, but they would make error messages worse. That's just my two cents. Skyler On Sun, Mar 10, 2024 at 8:46 PM Alejandro Colomar <alx@kernel.org> wrote: > > Hi Thorsten, > > On Mon, Mar 11, 2024 at 12:19:27AM +0000, Thorsten Glaser wrote: > > Rich Felker dixit: > > > > >the string literal, because the string literal appears in modular > > >library code that gets called from multiple utilities, then printing > > >an error message (and even worse, exiting, if you do that too), rather > > >than returning meaningful error information up to the caller for it to > > >handle/display, is just really sloppy, low-quality programming. > > > > Libraries totally should not call exit and thus not err/errx, > > and warn/warnx is… also questionable at best. > > > > But modularised code that builds a shared object and a few > > binaries using it? Why not. > > > > The thing I don’t get is why changing __progname is desired, > > but I guess everyone has use cases for something. > > setuid programs. Consider that a setuid program accidentally opens a > privileged file in fd 2. Now what happens if a random user can trigger > that accident, and write arbitrary text to a privileged file, just by > calling that setuid program with execlp("su", "inject this stuff", ...)? > > Bad stuff. > > Have a lovely night! > Alex > > > > > bye, > > //mirabilos > > -- > > (gnutls can also be used, but if you are compiling lynx for your own use, > > there is no reason to consider using that package) > > -- Thomas E. Dickey on the Lynx mailing list, about OpenSSL > > -- > <https://www.alejandro-colomar.es/> ^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [musl] Re: Tweaking the program name for <err.h> functions 2024-03-11 14:46 ` Skyler Ferrante (RIT Student) @ 2024-03-11 15:09 ` Andreas Schwab 2024-03-11 15:30 ` Skyler Ferrante (RIT Student) 0 siblings, 1 reply; 44+ messages in thread From: Andreas Schwab @ 2024-03-11 15:09 UTC (permalink / raw) To: Skyler Ferrante (RIT Student) Cc: Alejandro Colomar, Thorsten Glaser, Rich Felker, musl, NRK, Guillem Jover, libc-alpha, libbsd, Serge E. Hallyn, Iker Pedrosa, Christian Brauner On Mär 11 2024, Skyler Ferrante (RIT Student) wrote: > It seems like this is the main thing shadow-utils (and other projects) > should be concerned about. Every setuid/setgid program should check > for fd 0,1,2 being open at the start of execution, and either abort or > open new fds to /dev/null to prevent file descriptor omission attacks. That's what glibc already does. -- Andreas Schwab, SUSE Labs, schwab@suse.de GPG Key fingerprint = 0196 BAD8 1CE9 1970 F4BE 1748 E4D4 88E3 0EEA B9D7 "And now for something completely different." ^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [musl] Re: Tweaking the program name for <err.h> functions 2024-03-11 15:09 ` Andreas Schwab @ 2024-03-11 15:30 ` Skyler Ferrante (RIT Student) 2024-03-11 18:23 ` Florian Weimer 2024-03-11 19:47 ` Rich Felker 0 siblings, 2 replies; 44+ messages in thread From: Skyler Ferrante (RIT Student) @ 2024-03-11 15:30 UTC (permalink / raw) To: Andreas Schwab Cc: Alejandro Colomar, Thorsten Glaser, Rich Felker, musl, NRK, Guillem Jover, libc-alpha, libbsd, Serge E. Hallyn, Iker Pedrosa, Christian Brauner Hmm, maybe I'm missing something, but it seems you can close(fd) for the standard fds and then call execve, and the new process image will have no fd 0,1,2. I've tried this on a default Ubuntu 22.04 system. This seems to affect shadow-utils and other setuid/setgid binaries. Here is a repo I built for testing, https://github.com/skyler-ferrante/fd_omission/. What is the correct glibc behavior? Am I misunderstanding something? Skyler On Mon, Mar 11, 2024 at 11:09 AM Andreas Schwab <schwab@suse.de> wrote: > > On Mär 11 2024, Skyler Ferrante (RIT Student) wrote: > > > It seems like this is the main thing shadow-utils (and other projects) > > should be concerned about. Every setuid/setgid program should check > > for fd 0,1,2 being open at the start of execution, and either abort or > > open new fds to /dev/null to prevent file descriptor omission attacks. > > That's what glibc already does. > > -- > Andreas Schwab, SUSE Labs, schwab@suse.de > GPG Key fingerprint = 0196 BAD8 1CE9 1970 F4BE 1748 E4D4 88E3 0EEA B9D7 > "And now for something completely different." ^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [musl] Re: Tweaking the program name for <err.h> functions 2024-03-11 15:30 ` Skyler Ferrante (RIT Student) @ 2024-03-11 18:23 ` Florian Weimer 2024-03-11 18:48 ` Skyler Ferrante (RIT Student) 2024-03-11 19:47 ` Rich Felker 1 sibling, 1 reply; 44+ messages in thread From: Florian Weimer @ 2024-03-11 18:23 UTC (permalink / raw) To: Skyler Ferrante (RIT Student) Cc: Andreas Schwab, Alejandro Colomar, Thorsten Glaser, Rich Felker, musl, NRK, Guillem Jover, libc-alpha, libbsd, Serge E. Hallyn, Iker Pedrosa, Christian Brauner * Skyler Ferrante: > Hmm, maybe I'm missing something, but it seems you can close(fd) for > the standard fds and then call execve, and the new process image will > have no fd 0,1,2. I've tried this on a default Ubuntu 22.04 system. > This seems to affect shadow-utils and other setuid/setgid binaries. > > Here is a repo I built for testing, > https://github.com/skyler-ferrante/fd_omission/. What is the correct > glibc behavior? Am I misunderstanding something? If you run it under strace, it's not running SUID (in AT_SECURE mode). I'm not saying we don't have bugs (although we do have some end-to-end AT_SECURE tests in the testsuite, but probably not for this legacy behavior), just that this approach to testing is questionable. Thanks, Florian ^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [musl] Re: Tweaking the program name for <err.h> functions 2024-03-11 18:23 ` Florian Weimer @ 2024-03-11 18:48 ` Skyler Ferrante (RIT Student) 2024-03-11 19:05 ` enh 0 siblings, 1 reply; 44+ messages in thread From: Skyler Ferrante (RIT Student) @ 2024-03-11 18:48 UTC (permalink / raw) To: Florian Weimer Cc: Andreas Schwab, Alejandro Colomar, Thorsten Glaser, Rich Felker, musl, NRK, Guillem Jover, libc-alpha, libbsd, Serge E. Hallyn, Iker Pedrosa, Christian Brauner Hi Florian, > it's not running SUID (in AT_SECURE mode) I see. I didn't realize that it had different behavior for setuid/not setuid. That makes sense though, sorry for the confusion. Skyler On Mon, Mar 11, 2024 at 2:23 PM Florian Weimer <fweimer@redhat.com> wrote: > > * Skyler Ferrante: > > > Hmm, maybe I'm missing something, but it seems you can close(fd) for > > the standard fds and then call execve, and the new process image will > > have no fd 0,1,2. I've tried this on a default Ubuntu 22.04 system. > > This seems to affect shadow-utils and other setuid/setgid binaries. > > > > Here is a repo I built for testing, > > https://github.com/skyler-ferrante/fd_omission/. What is the correct > > glibc behavior? Am I misunderstanding something? > > If you run it under strace, it's not running SUID (in AT_SECURE mode). > I'm not saying we don't have bugs (although we do have some end-to-end > AT_SECURE tests in the testsuite, but probably not for this legacy > behavior), just that this approach to testing is questionable. > > Thanks, > Florian > ^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [musl] Re: Tweaking the program name for <err.h> functions 2024-03-11 18:48 ` Skyler Ferrante (RIT Student) @ 2024-03-11 19:05 ` enh 2024-03-11 19:44 ` Rich Felker 0 siblings, 1 reply; 44+ messages in thread From: enh @ 2024-03-11 19:05 UTC (permalink / raw) To: sjf5462 Cc: Florian Weimer, Andreas Schwab, Alejandro Colomar, Thorsten Glaser, Rich Felker, musl, NRK, Guillem Jover, libc-alpha, libbsd, Serge E. Hallyn, Iker Pedrosa, Christian Brauner Android's libc actually does do this for everything except for first-stage `init`, the one process that doesn't have a /dev/null equivalent available yet: https://android.googlesource.com/platform/bionic/+/master/libc/bionic/libc_init_common.cpp#358 On Mon, Mar 11, 2024 at 11:49 AM Skyler Ferrante (RIT Student) <sjf5462@rit.edu> wrote: > > Hi Florian, > > > it's not running SUID (in AT_SECURE mode) > > I see. I didn't realize that it had different behavior for setuid/not > setuid. That makes sense though, sorry for the confusion. > > Skyler > > > On Mon, Mar 11, 2024 at 2:23 PM Florian Weimer <fweimer@redhat.com> wrote: > > > > * Skyler Ferrante: > > > > > Hmm, maybe I'm missing something, but it seems you can close(fd) for > > > the standard fds and then call execve, and the new process image will > > > have no fd 0,1,2. I've tried this on a default Ubuntu 22.04 system. > > > This seems to affect shadow-utils and other setuid/setgid binaries. > > > > > > Here is a repo I built for testing, > > > https://github.com/skyler-ferrante/fd_omission/. What is the correct > > > glibc behavior? Am I misunderstanding something? > > > > If you run it under strace, it's not running SUID (in AT_SECURE mode). > > I'm not saying we don't have bugs (although we do have some end-to-end > > AT_SECURE tests in the testsuite, but probably not for this legacy > > behavior), just that this approach to testing is questionable. > > > > Thanks, > > Florian > > ^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [musl] Re: Tweaking the program name for <err.h> functions 2024-03-11 19:05 ` enh @ 2024-03-11 19:44 ` Rich Felker 2024-03-11 20:35 ` enh 0 siblings, 1 reply; 44+ messages in thread From: Rich Felker @ 2024-03-11 19:44 UTC (permalink / raw) To: enh Cc: sjf5462, Florian Weimer, Andreas Schwab, Alejandro Colomar, Thorsten Glaser, musl, NRK, Guillem Jover, libc-alpha, libbsd, Serge E. Hallyn, Iker Pedrosa, Christian Brauner On Mon, Mar 11, 2024 at 12:05:11PM -0700, enh wrote: > Android's libc actually does do this for everything except for > first-stage `init`, the one process that doesn't have a /dev/null > equivalent available yet: > https://android.googlesource.com/platform/bionic/+/master/libc/bionic/libc_init_common.cpp#358 In the absence of /dev/null, you could probably call pipe() and close the unwanted end. This works with no fs available, and has the "bonus" that you'll get a nice SIGPIPE crash if you accidentally try to write anything to it. Rich ^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [musl] Re: Tweaking the program name for <err.h> functions 2024-03-11 19:44 ` Rich Felker @ 2024-03-11 20:35 ` enh 0 siblings, 0 replies; 44+ messages in thread From: enh @ 2024-03-11 20:35 UTC (permalink / raw) To: Rich Felker Cc: sjf5462, Florian Weimer, Andreas Schwab, Alejandro Colomar, Thorsten Glaser, musl, NRK, Guillem Jover, libc-alpha, libbsd, Serge E. Hallyn, Iker Pedrosa, Christian Brauner On Mon, Mar 11, 2024 at 12:44 PM Rich Felker <dalias@libc.org> wrote: > > On Mon, Mar 11, 2024 at 12:05:11PM -0700, enh wrote: > > Android's libc actually does do this for everything except for > > first-stage `init`, the one process that doesn't have a /dev/null > > equivalent available yet: > > https://android.googlesource.com/platform/bionic/+/master/libc/bionic/libc_init_common.cpp#358 > > In the absence of /dev/null, you could probably call pipe() and close > the unwanted end. This works with no fs available, and has the "bonus" > that you'll get a nice SIGPIPE crash if you accidentally try to write > anything to it. (that's an interesting idea. i'll have to think about that...) > Rich ^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [musl] Re: Tweaking the program name for <err.h> functions 2024-03-11 15:30 ` Skyler Ferrante (RIT Student) 2024-03-11 18:23 ` Florian Weimer @ 2024-03-11 19:47 ` Rich Felker 2024-03-11 20:08 ` Skyler Ferrante (RIT Student) ` (3 more replies) 1 sibling, 4 replies; 44+ messages in thread From: Rich Felker @ 2024-03-11 19:47 UTC (permalink / raw) To: Skyler Ferrante (RIT Student) Cc: Andreas Schwab, Alejandro Colomar, Thorsten Glaser, musl, NRK, Guillem Jover, libc-alpha, libbsd, Serge E. Hallyn, Iker Pedrosa, Christian Brauner On Mon, Mar 11, 2024 at 11:30:04AM -0400, Skyler Ferrante (RIT Student) wrote: > Hmm, maybe I'm missing something, but it seems you can close(fd) for > the standard fds and then call execve, and the new process image will > have no fd 0,1,2. I've tried this on a default Ubuntu 22.04 system. > This seems to affect shadow-utils and other setuid/setgid binaries. > > Here is a repo I built for testing, > https://github.com/skyler-ferrante/fd_omission/. What is the correct > glibc behavior? Am I misunderstanding something? As Florian noted, you're missing that strace cannot invoke it suid. POSIX explicitly permits the implementation to open these fds if they started closed in suid execs, and IIRC indicates as a future direction that it might be permitted for all execs. We do the same in musl in the suid case. So really the only way that "writing attacker controlled prefix strings to fd 2" becomes an issue is if the application erroneously closes fd 2 and lets something else get opened on it. (Aside: making _FORTIFY_SOURCE>1 trap close(n) with n<3 would be an interesting idea... :) Rich ^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [musl] Re: Tweaking the program name for <err.h> functions 2024-03-11 19:47 ` Rich Felker @ 2024-03-11 20:08 ` Skyler Ferrante (RIT Student) 2024-03-11 20:39 ` enh 2024-03-11 21:21 ` Laurent Bercot ` (2 subsequent siblings) 3 siblings, 1 reply; 44+ messages in thread From: Skyler Ferrante (RIT Student) @ 2024-03-11 20:08 UTC (permalink / raw) To: Rich Felker Cc: Andreas Schwab, Alejandro Colomar, Thorsten Glaser, musl, NRK, Guillem Jover, libc-alpha, libbsd, Serge E. Hallyn, Iker Pedrosa, Christian Brauner Yup, I agree. My confusion was from an incorrect assumption that non-suid / suid programs would be handled the same way. I knew that strace wouldn't keep it setuid by I didn't realize glibc only checked closed fds for suid programs (which makes sense, this doesn't matter for non-privileged programs). > application erroneously closes fd 2 And hopefully no program does that, and if it does, that's their fault :) Skyler ^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [musl] Re: Tweaking the program name for <err.h> functions 2024-03-11 20:08 ` Skyler Ferrante (RIT Student) @ 2024-03-11 20:39 ` enh 0 siblings, 0 replies; 44+ messages in thread From: enh @ 2024-03-11 20:39 UTC (permalink / raw) To: sjf5462 Cc: Rich Felker, Andreas Schwab, Alejandro Colomar, Thorsten Glaser, musl, NRK, Guillem Jover, libc-alpha, libbsd, Serge E. Hallyn, Iker Pedrosa, Christian Brauner On Mon, Mar 11, 2024 at 1:09 PM Skyler Ferrante (RIT Student) <sjf5462@rit.edu> wrote: > > Yup, I agree. My confusion was from an incorrect assumption that > non-suid / suid programs would be handled the same way. I knew that > strace wouldn't keep it setuid by I didn't realize glibc only checked > closed fds for suid programs (which makes sense, this doesn't matter > for non-privileged programs). > > > application erroneously closes fd 2 > > And hopefully no program does that, and if it does, that's their fault :) programs get confused about fds and close the wrong ones all the time. the fd equivalent of a malloc() double-free especially. bionic has a fairly general protection against this class of error: https://android.googlesource.com/platform/bionic/+/master/docs/fdsan.md (fork() children do it on purpose all the time too :-) ) > Skyler ^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [musl] Re: Tweaking the program name for <err.h> functions 2024-03-11 19:47 ` Rich Felker 2024-03-11 20:08 ` Skyler Ferrante (RIT Student) @ 2024-03-11 21:21 ` Laurent Bercot 2024-03-11 22:05 ` Thorsten Glaser 2024-03-12 0:18 ` Gabriel Ravier 3 siblings, 0 replies; 44+ messages in thread From: Laurent Bercot @ 2024-03-11 21:21 UTC (permalink / raw) To: musl, Skyler Ferrante (RIT Student) Cc: Andreas Schwab, Alejandro Colomar, Thorsten Glaser, musl, NRK, Guillem Jover, libc-alpha, libbsd, Serge E. Hallyn, Iker Pedrosa, Christian Brauner >(Aside: making _FORTIFY_SOURCE>1 trap close(n) with n<3 would be an >interesting idea... :) Please don't. close(0); if (open("something", O_RDONLY)) fail(); (only when single-threaded, obviously) is a valid pattern, and uses one fewer descriptor than fd=open("something", O_RDONLY); dup2(fd, 0); Also, running with stdin or stdout closed (or even stderr but what kind of monster would do that) is fine for a process that is internal to a project, that isn't user-facing; it's on the project to know the fd states of its various components. Private APIs should not have the same constraints as public ones. (And yes, for user-facing programs, i.e. 99% of them, it is a good idea to always sanitize around 0, 1 and 2.) -- Laurent ^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [musl] Re: Tweaking the program name for <err.h> functions 2024-03-11 19:47 ` Rich Felker 2024-03-11 20:08 ` Skyler Ferrante (RIT Student) 2024-03-11 21:21 ` Laurent Bercot @ 2024-03-11 22:05 ` Thorsten Glaser 2024-03-12 0:18 ` Gabriel Ravier 3 siblings, 0 replies; 44+ messages in thread From: Thorsten Glaser @ 2024-03-11 22:05 UTC (permalink / raw) To: musl Cc: Skyler Ferrante (RIT Student), Andreas Schwab, Alejandro Colomar, NRK, Guillem Jover, libc-alpha, libbsd, Serge E. Hallyn, Iker Pedrosa, Christian Brauner Rich Felker dixit: >POSIX explicitly permits the implementation to open these fds if they >started closed in suid execs, and IIRC indicates as a future direction AFAIR, POSIX recently clarified that when a utility isn’t invoked with fd#0, #1 and #2 open and suitable, the caller’s behaviour is nōn-conforming, and so the callee can probably do what it wants in that case as it’s left POSIX land. bye, //mirabilos -- “It is inappropriate to require that a time represented as seconds since the Epoch precisely represent the number of seconds between the referenced time and the Epoch.” -- IEEE Std 1003.1b-1993 (POSIX) Section B.2.2.2 ^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [musl] Re: Tweaking the program name for <err.h> functions 2024-03-11 19:47 ` Rich Felker ` (2 preceding siblings ...) 2024-03-11 22:05 ` Thorsten Glaser @ 2024-03-12 0:18 ` Gabriel Ravier 2024-03-12 0:43 ` Rich Felker 2024-03-12 13:54 ` Florian Weimer 3 siblings, 2 replies; 44+ messages in thread From: Gabriel Ravier @ 2024-03-12 0:18 UTC (permalink / raw) To: Rich Felker, Skyler Ferrante (RIT Student) Cc: Andreas Schwab, Alejandro Colomar, Thorsten Glaser, musl, NRK, Guillem Jover, libc-alpha, libbsd, Serge E. Hallyn, Iker Pedrosa, Christian Brauner On 3/11/24 19:47, Rich Felker wrote: > On Mon, Mar 11, 2024 at 11:30:04AM -0400, Skyler Ferrante (RIT Student) wrote: >> Hmm, maybe I'm missing something, but it seems you can close(fd) for >> the standard fds and then call execve, and the new process image will >> have no fd 0,1,2. I've tried this on a default Ubuntu 22.04 system. >> This seems to affect shadow-utils and other setuid/setgid binaries. >> >> Here is a repo I built for testing, >> https://github.com/skyler-ferrante/fd_omission/. What is the correct >> glibc behavior? Am I misunderstanding something? > As Florian noted, you're missing that strace cannot invoke it suid. > POSIX explicitly permits the implementation to open these fds if they > started closed in suid execs, and IIRC indicates as a future direction > that it might be permitted for all execs. We do the same in musl in > the suid case. So really the only way that "writing attacker > controlled prefix strings to fd 2" becomes an issue is if the > application erroneously closes fd 2 and lets something else get opened > on it. > > (Aside: making _FORTIFY_SOURCE>1 trap close(n) with n<3 would be an > interesting idea... :) > > Rich Doing this would break many programs, such as: - most of coreutils, e.g. programs like ls, cat or head, since they always `close` their input and output descriptors (when they've written or read something) to make sure to diagnose all errors - grep - xargs - find - strace, which (using the half-closed self-pipe trick mentioned earlier in this thread to avoid reusing them later btw) closes the standard descriptors, to avoid changing the behavior of programs calling it if e.g. its input is a pipe (where if it left the fds open that'd mean the writer would get SIGPIPE later than if the program was ran without strace) - tcsh, which deliberately does `close(n)` with `n < 3` to make it so all the standard FDs point to `/dev/null` - troff and groff (and thus man) - git - many more... I have found these by simply stracing random programs as found on my system with `ls /bin/ | shuf -n1` ^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [musl] Re: Tweaking the program name for <err.h> functions 2024-03-12 0:18 ` Gabriel Ravier @ 2024-03-12 0:43 ` Rich Felker 2024-03-12 3:23 ` Gabriel Ravier 2024-03-12 13:54 ` Florian Weimer 1 sibling, 1 reply; 44+ messages in thread From: Rich Felker @ 2024-03-12 0:43 UTC (permalink / raw) To: Gabriel Ravier Cc: Skyler Ferrante (RIT Student), Andreas Schwab, Alejandro Colomar, Thorsten Glaser, musl, NRK, Guillem Jover, libc-alpha, libbsd, Serge E. Hallyn, Iker Pedrosa, Christian Brauner On Tue, Mar 12, 2024 at 12:18:24AM +0000, Gabriel Ravier wrote: > On 3/11/24 19:47, Rich Felker wrote: > >On Mon, Mar 11, 2024 at 11:30:04AM -0400, Skyler Ferrante (RIT Student) wrote: > >>Hmm, maybe I'm missing something, but it seems you can close(fd) for > >>the standard fds and then call execve, and the new process image will > >>have no fd 0,1,2. I've tried this on a default Ubuntu 22.04 system. > >>This seems to affect shadow-utils and other setuid/setgid binaries. > >> > >>Here is a repo I built for testing, > >>https://github.com/skyler-ferrante/fd_omission/. What is the correct > >>glibc behavior? Am I misunderstanding something? > >As Florian noted, you're missing that strace cannot invoke it suid. > >POSIX explicitly permits the implementation to open these fds if they > >started closed in suid execs, and IIRC indicates as a future direction > >that it might be permitted for all execs. We do the same in musl in > >the suid case. So really the only way that "writing attacker > >controlled prefix strings to fd 2" becomes an issue is if the > >application erroneously closes fd 2 and lets something else get opened > >on it. > > > >(Aside: making _FORTIFY_SOURCE>1 trap close(n) with n<3 would be an > >interesting idea... :) > > Doing this would break many programs, such as: > - most of coreutils, e.g. programs like ls, cat or head, since they > always `close` their input and output descriptors (when they've > written or read something) to make sure to diagnose all errors > - grep > - xargs > - find This makes it so they can malfunction during exit when it flushes/closes the corresponding stdio FILEs. If nothing else has been opened in the mean time, under typical implementations it should be safe, but I think per 2.5.1 Interaction of File Descriptors and Standard I/O Streams: https://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html#tag_15_05_01 it's undefined. The safe way to do what they want is to dup the fd they want to close-and-check-for-errors, open /dev/null, dup2 that over the original fd, then close the first dup. Or, don't exit()/return-from-main, but instead _exit, so there's no subsequent access to the FILE. > - strace, which (using the half-closed self-pipe trick mentioned > earlier in this thread to avoid reusing them later btw) closes the > standard descriptors, to avoid changing the behavior of programs > calling it if e.g. its input is a pipe (where if it left the fds > open that'd mean the writer would get SIGPIPE later than if the > program was ran without strace) > - tcsh, which deliberately does `close(n)` with `n < 3` to make it > so all the standard FDs point to `/dev/null` > - troff and groff (and thus man) > - git > - many more... I have found these by simply stracing random programs > as found on my system with `ls /bin/ | shuf -n1` Yes, I'm quite aware it's commonplace, but it would be something nice to get cleaned up... Rich ^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [musl] Re: Tweaking the program name for <err.h> functions 2024-03-12 0:43 ` Rich Felker @ 2024-03-12 3:23 ` Gabriel Ravier 2024-03-12 14:44 ` Rich Felker 0 siblings, 1 reply; 44+ messages in thread From: Gabriel Ravier @ 2024-03-12 3:23 UTC (permalink / raw) To: Rich Felker Cc: Skyler Ferrante (RIT Student), Andreas Schwab, Alejandro Colomar, Thorsten Glaser, musl, NRK, Guillem Jover, libc-alpha, libbsd, Serge E. Hallyn, Iker Pedrosa, Christian Brauner [-- Attachment #1: Type: text/plain, Size: 6672 bytes --] On 3/12/24 00:43, Rich Felker wrote: > On Tue, Mar 12, 2024 at 12:18:24AM +0000, Gabriel Ravier wrote: >> On 3/11/24 19:47, Rich Felker wrote: >>> On Mon, Mar 11, 2024 at 11:30:04AM -0400, Skyler Ferrante (RIT Student) wrote: >>>> Hmm, maybe I'm missing something, but it seems you can close(fd) for >>>> the standard fds and then call execve, and the new process image will >>>> have no fd 0,1,2. I've tried this on a default Ubuntu 22.04 system. >>>> This seems to affect shadow-utils and other setuid/setgid binaries. >>>> >>>> Here is a repo I built for testing, >>>> https://github.com/skyler-ferrante/fd_omission/. What is the correct >>>> glibc behavior? Am I misunderstanding something? >>> As Florian noted, you're missing that strace cannot invoke it suid. >>> POSIX explicitly permits the implementation to open these fds if they >>> started closed in suid execs, and IIRC indicates as a future direction >>> that it might be permitted for all execs. We do the same in musl in >>> the suid case. So really the only way that "writing attacker >>> controlled prefix strings to fd 2" becomes an issue is if the >>> application erroneously closes fd 2 and lets something else get opened >>> on it. >>> >>> (Aside: making _FORTIFY_SOURCE>1 trap close(n) with n<3 would be an >>> interesting idea... :) >> Doing this would break many programs, such as: >> - most of coreutils, e.g. programs like ls, cat or head, since they >> always `close` their input and output descriptors (when they've >> written or read something) to make sure to diagnose all errors >> - grep >> - xargs >> - find > This makes it so they can malfunction during exit when it > flushes/closes the corresponding stdio FILEs. If nothing else has been > opened in the mean time, under typical implementations it should be > safe, but I think per 2.5.1 Interaction of File Descriptors and > Standard I/O Streams: > > https://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html#tag_15_05_01 > > it's undefined. > > The safe way to do what they want is to dup the fd they want to > close-and-check-for-errors, open /dev/null, dup2 that over the > original fd, then close the first dup. > > Or, don't exit()/return-from-main, but instead _exit, so there's no > subsequent access to the FILE. Those applications above (though some of those below appear to do raw /close/ calls) all circumvent your objection by calling /fclose/ on the standard streams rather than /close/-ing the file descriptors directly, which seems legal according to POSIX given otherwise the following quote would make no sense: > Since after the call to /fclose/( ) any use of stream results in undefined behavior, /fclose/( ) should not be used on /stdin/, /stdout/, or /stderr/ except immediately before process termination (see XBD Section 3.287, on page 73), so as to avoid triggering undefined behavior in other standard interfaces that rely on these streams. If there are any /atexit/( ) handlers registered by the application, such a call to /fclose/() should not occur until the last handler is finishing. - POSIX, /System Interfaces/, *fclose( )*, *APPLICATION USAGE* and all of those applications listed above do the /fclose/ at the end of their /atexit/ handlers - the wording implies the fact they return from that /atexit/ handler when the /fclose/ succeeds is fine too since it's done when "the last handler is finishing" (i.e. after all other usage of standard interfaces which may use the standard streams)), which seems to imply calling /exit/ after /fclose/-ing one of the standard streams should be legal. Furthermore, the description of /close/ also states: > Usage of /close/( ) on file descriptors STDIN_FILENO, STDOUT_FILENO, or STDERR_FILENO should immediately be followed by an operation to reopen these file descriptors. Unexpected behavior will result if any of these file descriptors is left in a closed state (for example, an [EBADF] error from /perror/( )) or if an unrelated /open/( ) or similar call later in the application accidentally allocates a file to one of these well-known file descriptors. Furthermore, a /close/( ) followed by a reopen operation (e.g., /open/( ), /dup/( ), etc.) is not atomic; /dup2/( ) should be used to change standard file descriptors. - POSIX, /System Interfaces/, *fclose( )*, *APPLICATION USAGE* which simply points out "unexpected" (which does not appear to mean "undefined") behavior along with examples of some of the potential consequences and points out replacing those descriptors after the /close/ is not atomic and that /dup2/ should be used instead - but "should" is not the same word as "must", so this seems to implicitly allow not using /dup2/ or even not reopening the file descriptors at all - which seems accurate to me, I can't see anything in the standard, including in that *Interaction of File Descriptors and Standard I/O Streams* section you mentioned earlier, that would result in undefined behavior upon /close/-ing the file descriptors before /fclose/, except that that section seems to indicate the application must not leave data buffered in the stream (which does not seem to be something any of the applications I've mentioned before or after this do - though it's not like I've engaged in exhaustive program analysis to ensure this is the case either, so that's more of an assumption than anything else, but the scenarios in which they close these streams (near the beginning or termination of the application) seem like they should make it quite likely this is not the case). It seems to me as though further use of a /FILE/ after its file descriptor was /close/-ed would simply result in [EBADF] errors (...which could obviously also easily lead to issues involving having multiple active handles on the same file if someone else was to call /open/ afterwards, but that's a separate issue). > >> - strace, which (using the half-closed self-pipe trick mentioned >> earlier in this thread to avoid reusing them later btw) closes the >> standard descriptors, to avoid changing the behavior of programs >> calling it if e.g. its input is a pipe (where if it left the fds >> open that'd mean the writer would get SIGPIPE later than if the >> program was ran without strace) >> - tcsh, which deliberately does `close(n)` with `n < 3` to make it >> so all the standard FDs point to `/dev/null` >> - troff and groff (and thus man) >> - git >> - many more... I have found these by simply stracing random programs >> as found on my system with `ls /bin/ | shuf -n1` > Yes, I'm quite aware it's commonplace, but it would be something nice > to get cleaned up... > > Rich ^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [musl] Re: Tweaking the program name for <err.h> functions 2024-03-12 3:23 ` Gabriel Ravier @ 2024-03-12 14:44 ` Rich Felker 0 siblings, 0 replies; 44+ messages in thread From: Rich Felker @ 2024-03-12 14:44 UTC (permalink / raw) To: Gabriel Ravier Cc: Skyler Ferrante (RIT Student), Andreas Schwab, Alejandro Colomar, Thorsten Glaser, musl, NRK, Guillem Jover, libc-alpha, libbsd, Serge E. Hallyn, Iker Pedrosa, Christian Brauner On Tue, Mar 12, 2024 at 03:23:32AM +0000, Gabriel Ravier wrote: > On 3/12/24 00:43, Rich Felker wrote: > >On Tue, Mar 12, 2024 at 12:18:24AM +0000, Gabriel Ravier wrote: > >>On 3/11/24 19:47, Rich Felker wrote: > >>>On Mon, Mar 11, 2024 at 11:30:04AM -0400, Skyler Ferrante (RIT Student) wrote: > >>>>Hmm, maybe I'm missing something, but it seems you can close(fd) for > >>>>the standard fds and then call execve, and the new process image will > >>>>have no fd 0,1,2. I've tried this on a default Ubuntu 22.04 system. > >>>>This seems to affect shadow-utils and other setuid/setgid binaries. > >>>> > >>>>Here is a repo I built for testing, > >>>>https://github.com/skyler-ferrante/fd_omission/. What is the correct > >>>>glibc behavior? Am I misunderstanding something? > >>>As Florian noted, you're missing that strace cannot invoke it suid. > >>>POSIX explicitly permits the implementation to open these fds if they > >>>started closed in suid execs, and IIRC indicates as a future direction > >>>that it might be permitted for all execs. We do the same in musl in > >>>the suid case. So really the only way that "writing attacker > >>>controlled prefix strings to fd 2" becomes an issue is if the > >>>application erroneously closes fd 2 and lets something else get opened > >>>on it. > >>> > >>>(Aside: making _FORTIFY_SOURCE>1 trap close(n) with n<3 would be an > >>>interesting idea... :) > >>Doing this would break many programs, such as: > >>- most of coreutils, e.g. programs like ls, cat or head, since they > >>always `close` their input and output descriptors (when they've > >>written or read something) to make sure to diagnose all errors > >>- grep > >>- xargs > >>- find > >This makes it so they can malfunction during exit when it > >flushes/closes the corresponding stdio FILEs. If nothing else has been > >opened in the mean time, under typical implementations it should be > >safe, but I think per 2.5.1 Interaction of File Descriptors and > >Standard I/O Streams: > > > >https://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html#tag_15_05_01 > > > >it's undefined. > > > >The safe way to do what they want is to dup the fd they want to > >close-and-check-for-errors, open /dev/null, dup2 that over the > >original fd, then close the first dup. > > > >Or, don't exit()/return-from-main, but instead _exit, so there's no > >subsequent access to the FILE. > > > Those applications above (though some of those below appear to do > raw /close/ calls) all circumvent your objection by calling /fclose/ > on the standard streams rather than /close/-ing the file descriptors > directly, which seems legal according to POSIX given otherwise the > following quote would make no sense: OK, in that case, _FORTIFY_SOURCE>1 trapping close(n) for n<3 would not affect them, since they're calling fclose not close... None of this is particularly intended as a serious proposal, but it could be interesting to experiment with and catch programs with dubious behavior that might be a bug. Rich ^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [musl] Re: Tweaking the program name for <err.h> functions 2024-03-12 0:18 ` Gabriel Ravier 2024-03-12 0:43 ` Rich Felker @ 2024-03-12 13:54 ` Florian Weimer 2024-03-12 14:21 ` Zack Weinberg 1 sibling, 1 reply; 44+ messages in thread From: Florian Weimer @ 2024-03-12 13:54 UTC (permalink / raw) To: Gabriel Ravier Cc: Rich Felker, Skyler Ferrante (RIT Student), musl, Andreas Schwab, Alejandro Colomar, Thorsten Glaser, NRK, Guillem Jover, libc-alpha, libbsd, Serge E. Hallyn, Iker Pedrosa, Christian Brauner * Gabriel Ravier: > Doing this would break many programs, such as: > - most of coreutils, e.g. programs like ls, cat or head, since they > always `close` their input and output descriptors (when they've > written or read something) to make sure to diagnose all errors A slightly better way to do this is to do fflush (stdout) followed by error checking on close (dup (fileno (stdout))). We can't do this implicitly as part of fflush because it potentially breaks legacy (non-OFD) POSIX file locking, at least not without parsing /proc and whatnot. The close system call is how the Linux NFS client reports ENOSPC errors without performing a costly fsync on the server. We don't have a better interface for this. Thanks, Florian ^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [musl] Re: Tweaking the program name for <err.h> functions 2024-03-12 13:54 ` Florian Weimer @ 2024-03-12 14:21 ` Zack Weinberg 2024-03-12 14:31 ` Florian Weimer 0 siblings, 1 reply; 44+ messages in thread From: Zack Weinberg @ 2024-03-12 14:21 UTC (permalink / raw) To: Florian Weimer, Gabriel Ravier Cc: Rich Felker, Skyler Ferrante (RIT Student), musl, Andreas Schwab, Alejandro Colomar, Thorsten Glaser, NRK, Guillem Jover, GNU libc development, libbsd, Serge E. Hallyn, Iker Pedrosa, Christian Brauner On Tue, Mar 12, 2024, at 9:54 AM, Florian Weimer wrote: >> Doing this would break many programs, such as: >> - most of coreutils, e.g. programs like ls, cat or head, since they >> always `close` their input and output descriptors (when they've >> written or read something) to make sure to diagnose all errors > > A slightly better way to do this is to do fflush (stdout) followed by > error checking on close (dup (fileno (stdout))). Does that actually report delayed write errors? As you have it, the close() just drops the fd created by the dup(), the OFD is still referenced by fd 1 and therefore remains open. I would expect scrupulously correct and thread-safe code for detecting write errors on stdout without fd 1 ever becoming invalid to look something like this: int stub_stdout = open("/dev/null", O_WRONLY|O_CLOEXEC); if (stub_stdout < 0) perror_exit("/dev/null"); flockfile(stdout); if (ferror(stdout) || fflush(stdout)) perror_exit("stdout: write error"); int original_stdout = fcntl(fileno(stdout), F_DUPFD_CLOEXEC, 3); if (original_stdout < 0) perror_exit("dup(stdout)"); // e.g. ENFILE dup2(stub_stdout, fileno(stdout)); // failure here should be impossible close(stub_stdout); // ditto funlockfile(stdout); if (close(original_stdout) < 0) perror_exit("stdout: write error"); ... Which is enough of a pain in the neck that I can't blame people for wanting to just do close(1), especially during process termination. (I thought Linux had a "swap these two fds" mode for dup3(), which would simplify the above a bunch and get rid of one of the two places where you can hit the file descriptor limit, but it's not mentioned in my copy of the manpage. Did I just dream it?) zw ^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [musl] Re: Tweaking the program name for <err.h> functions 2024-03-12 14:21 ` Zack Weinberg @ 2024-03-12 14:31 ` Florian Weimer 2024-03-12 14:42 ` Rich Felker 0 siblings, 1 reply; 44+ messages in thread From: Florian Weimer @ 2024-03-12 14:31 UTC (permalink / raw) To: Zack Weinberg Cc: Gabriel Ravier, Rich Felker, Skyler Ferrante (RIT Student), musl, Andreas Schwab, Alejandro Colomar, Thorsten Glaser, NRK, Guillem Jover, GNU libc development, libbsd, Serge E. Hallyn, Iker Pedrosa, Christian Brauner * Zack Weinberg: > On Tue, Mar 12, 2024, at 9:54 AM, Florian Weimer wrote: >>> Doing this would break many programs, such as: >>> - most of coreutils, e.g. programs like ls, cat or head, since they >>> always `close` their input and output descriptors (when they've >>> written or read something) to make sure to diagnose all errors >> >> A slightly better way to do this is to do fflush (stdout) followed by >> error checking on close (dup (fileno (stdout))). > > Does that actually report delayed write errors? As you have it, > the close() just drops the fd created by the dup(), the OFD is > still referenced by fd 1 and therefore remains open. I don't think the VFS close action is subject to reference counting. Otherwise the current coreutils error checking wouldn't work because in many cases, another process retains a reference to the OFD. Thanks, Florian ^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [musl] Re: Tweaking the program name for <err.h> functions 2024-03-12 14:31 ` Florian Weimer @ 2024-03-12 14:42 ` Rich Felker 2024-03-12 19:25 ` Zack Weinberg 0 siblings, 1 reply; 44+ messages in thread From: Rich Felker @ 2024-03-12 14:42 UTC (permalink / raw) To: Florian Weimer Cc: Zack Weinberg, Gabriel Ravier, Skyler Ferrante (RIT Student), musl, Andreas Schwab, Alejandro Colomar, Thorsten Glaser, NRK, Guillem Jover, GNU libc development, libbsd, Serge E. Hallyn, Iker Pedrosa, Christian Brauner On Tue, Mar 12, 2024 at 03:31:04PM +0100, Florian Weimer wrote: > * Zack Weinberg: > > > On Tue, Mar 12, 2024, at 9:54 AM, Florian Weimer wrote: > >>> Doing this would break many programs, such as: > >>> - most of coreutils, e.g. programs like ls, cat or head, since they > >>> always `close` their input and output descriptors (when they've > >>> written or read something) to make sure to diagnose all errors > >> > >> A slightly better way to do this is to do fflush (stdout) followed by > >> error checking on close (dup (fileno (stdout))). > > > > Does that actually report delayed write errors? As you have it, > > the close() just drops the fd created by the dup(), the OFD is > > still referenced by fd 1 and therefore remains open. > > I don't think the VFS close action is subject to reference counting. > Otherwise the current coreutils error checking wouldn't work because in > many cases, another process retains a reference to the OFD. It is. close only reports errors if it's the last fd referring to the ofd. It's an incredibly stupid design choice by NFS that mismatches expected fd behavior. This is why my alternate proposal for doing it used dup2 to remove the original reference on fd<3 without closing it, so that the close of the dup would have a chance to be the last close. But indeed none of these ways help if some other process still has a reference. The right thing to do here IMO has always been to ignore this and let people who configure their NFS setups not to synchronously report errors deal with the resulting data loss. (And on a deeper level, the right thing is not to use NFS, print out the NFS source code and burn it, etc. :) But if folks insist on trying to handle it more gracefully, I'm not stopping them. Rich ^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [musl] Re: Tweaking the program name for <err.h> functions 2024-03-12 14:42 ` Rich Felker @ 2024-03-12 19:25 ` Zack Weinberg 2024-03-12 21:19 ` Rich Felker 2024-03-13 8:28 ` Florian Weimer 0 siblings, 2 replies; 44+ messages in thread From: Zack Weinberg @ 2024-03-12 19:25 UTC (permalink / raw) To: Rich Felker, Florian Weimer Cc: Gabriel Ravier, Skyler Ferrante (RIT Student), musl, Andreas Schwab, Alejandro Colomar, Thorsten Glaser, NRK, Guillem Jover, GNU libc development, libbsd, Serge E. Hallyn, Iker Pedrosa, Christian Brauner On Tue, Mar 12, 2024, at 10:42 AM, Rich Felker wrote: > On Tue, Mar 12, 2024 at 03:31:04PM +0100, Florian Weimer wrote: >> * Zack Weinberg: >> >> > On Tue, Mar 12, 2024, at 9:54 AM, Florian Weimer wrote: >> >>> Doing this would break many programs, such as: >> >>> - most of coreutils, e.g. programs like ls, cat or head, since they >> >>> always `close` their input and output descriptors (when they've >> >>> written or read something) to make sure to diagnose all errors >> >> >> >> A slightly better way to do this is to do fflush (stdout) followed by >> >> error checking on close (dup (fileno (stdout))). >> > >> > Does that actually report delayed write errors? As you have it, >> > the close() just drops the fd created by the dup(), the OFD is >> > still referenced by fd 1 and therefore remains open. >> >> I don't think the VFS close action is subject to reference counting. >> Otherwise the current coreutils error checking wouldn't work because in >> many cases, another process retains a reference to the OFD. > > It is. close only reports errors if it's the last fd referring to the > ofd. It's an incredibly stupid design choice by NFS that mismatches > expected fd behavior. I do fully agree that this is a design error in NFS and in close(2) more generally [like all destructors, it should be _impossible_ for close to fail], but there is no realistic prospect of changing it, and I've been burned a few times by programs that didn't notice delayed write errors. The risk of missing an error because another process still has a ref to the OFD is real, but it comes up rarely enough that I don't think it should deter us from trying to get the "only one process has this file open" case right. (Think shell `>` redirection.) Also, I have written programs that expected fds 0 and/or 1 to be pipes, and closed them well before exiting as a cheap way to send one-shot events to the process on the other end of the pipe. I think that's a legitimate way to use inherited fds, and it would be significantly more difficult to do in some contexts if you had to use a fd > 2 to do it (e.g. the process on the other end used popen() to start things). If there's something we can do to make it easier for programmers to do the Right Thing with closing standard fds, IMHO we should. For stdio, we perfectly well _could_ special case fclose(), when the fileno is 0/1/2, to do the dup/close dance and leave both the FILE and the fd in a valid, stubbed state. (For stdin, open("/dev/null", O_RDONLY) is clearly an appropriate stub semantic; for stdout and stderr I am unsure whether "discard all writes silently" or "fail all writes" would be better.) I don't think it's safe to make close() special case 0/1/2, though—not least because it's supposed to be atomic and async signal safe. And we should maybe give some thought to runtimes for languages other than C, which probably have their own buffering wrappers for fds 0/1/2 and might care about cross-language interop. zw ^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [musl] Re: Tweaking the program name for <err.h> functions 2024-03-12 19:25 ` Zack Weinberg @ 2024-03-12 21:19 ` Rich Felker 2024-03-13 8:28 ` Florian Weimer 1 sibling, 0 replies; 44+ messages in thread From: Rich Felker @ 2024-03-12 21:19 UTC (permalink / raw) To: Zack Weinberg Cc: Florian Weimer, Gabriel Ravier, Skyler Ferrante (RIT Student), musl, Andreas Schwab, Alejandro Colomar, Thorsten Glaser, NRK, Guillem Jover, GNU libc development, libbsd, Serge E. Hallyn, Iker Pedrosa, Christian Brauner On Tue, Mar 12, 2024 at 03:25:31PM -0400, Zack Weinberg wrote: > > > On Tue, Mar 12, 2024, at 10:42 AM, Rich Felker wrote: > > On Tue, Mar 12, 2024 at 03:31:04PM +0100, Florian Weimer wrote: > >> * Zack Weinberg: > >> > >> > On Tue, Mar 12, 2024, at 9:54 AM, Florian Weimer wrote: > >> >>> Doing this would break many programs, such as: > >> >>> - most of coreutils, e.g. programs like ls, cat or head, since they > >> >>> always `close` their input and output descriptors (when they've > >> >>> written or read something) to make sure to diagnose all errors > >> >> > >> >> A slightly better way to do this is to do fflush (stdout) followed by > >> >> error checking on close (dup (fileno (stdout))). > >> > > >> > Does that actually report delayed write errors? As you have it, > >> > the close() just drops the fd created by the dup(), the OFD is > >> > still referenced by fd 1 and therefore remains open. > >> > >> I don't think the VFS close action is subject to reference counting. > >> Otherwise the current coreutils error checking wouldn't work because in > >> many cases, another process retains a reference to the OFD. > > > > It is. close only reports errors if it's the last fd referring to the > > ofd. It's an incredibly stupid design choice by NFS that mismatches > > expected fd behavior. > > I do fully agree that this is a design error in NFS and in close(2) > more generally [like all destructors, it should be _impossible_ for > close to fail], but there is no realistic prospect of changing it, > and I've been burned a few times by programs that didn't notice > delayed write errors. The risk of missing an error because another > process still has a ref to the OFD is real, but it comes up rarely > enough that I don't think it should deter us from trying to get the > "only one process has this file open" case right. (Think shell `>` > redirection.) > > Also, I have written programs that expected fds 0 and/or 1 to be > pipes, and closed them well before exiting as a cheap way to send > one-shot events to the process on the other end of the pipe. I think > that's a legitimate way to use inherited fds, and it would be > significantly more difficult to do in some contexts if you had to > use a fd > 2 to do it (e.g. the process on the other end used > popen() to start things). There's a perfectly safe way to do that: you dup2 something else over fd 0/1/2 as needed, rather than closing it. > If there's something we can do to make it easier for programmers to > do the Right Thing with closing standard fds, IMHO we should. For > stdio, we perfectly well _could_ special case fclose(), when the > fileno is 0/1/2, to do the dup/close dance and leave both the FILE > and the fd in a valid, stubbed state. (For stdin, open("/dev/null", > O_RDONLY) is clearly an appropriate stub semantic; for stdout and > stderr I am unsure whether "discard all writes silently" or "fail > all writes" would be better.) I don't think that's at all conforming. fclose is specified to close the fd too, and while that's generally bad behavior, it is the expected behavior that a program can be depending on. (A hardening level to trap if a voluntary constraint is violated is a lot different than making a standard function silently do the wrong thing because something else would be "better" to do.) FWIW, accessing any of the standard FILEs after fclose on them (e.g. calling printf after fclose(stdout) or getchar() after fclose(stdin)) is UB, and would potentially be worth trapping too. Zero-overhead trapping could probably be arranged just by fiddling with the buffer pointers. > I don't think it's safe to make > close() special case 0/1/2, though—not least because it's supposed > to be atomic and async signal safe. And we should maybe give some > thought to runtimes for languages other than C, which probably have > their own buffering wrappers for fds 0/1/2 and might care about > cross-language interop. Indeed, the hypothetical thing was not intended as a change of semantics, just as a hardening mode to catch programming errors. Rich ^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [musl] Re: Tweaking the program name for <err.h> functions 2024-03-12 19:25 ` Zack Weinberg 2024-03-12 21:19 ` Rich Felker @ 2024-03-13 8:28 ` Florian Weimer 1 sibling, 0 replies; 44+ messages in thread From: Florian Weimer @ 2024-03-13 8:28 UTC (permalink / raw) To: Zack Weinberg Cc: Rich Felker, Gabriel Ravier, Skyler Ferrante (RIT Student), musl, Andreas Schwab, Alejandro Colomar, Thorsten Glaser, NRK, Guillem Jover, GNU libc development, libbsd, Serge E. Hallyn, Iker Pedrosa, Christian Brauner * Zack Weinberg: > I do fully agree that this is a design error in NFS and in close(2) > more generally [like all destructors, it should be _impossible_ for > close to fail], but there is no realistic prospect of changing it, and > I've been burned a few times by programs that didn't notice delayed > write errors. There is fsync to avoid delayed write errors. Historically, it's been very bad for performance. What coreutils et al. aim to do is to deal with non-catastrophic failures (mainly out of space errors) without incurring the fsync overhead. Thanks, Florian ^ permalink raw reply [flat|nested] 44+ messages in thread
end of thread, other threads:[~2024-03-13 8:28 UTC | newest] Thread overview: 44+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2024-03-07 22:24 Tweaking the program name for <err.h> functions Alejandro Colomar 2024-03-08 0:30 ` Guillem Jover 2024-03-08 0:47 ` enh 2024-03-08 0:52 ` Alejandro Colomar 2024-03-09 15:02 ` [musl] " Rich Felker 2024-03-09 15:49 ` Alejandro Colomar 2024-03-09 18:35 ` Andreas Schwab 2024-03-09 18:46 ` Alejandro Colomar 2024-03-09 19:18 ` [musl] " Markus Wichmann 2024-03-09 19:25 ` Rich Felker 2024-03-09 21:44 ` Thorsten Glaser 2024-03-10 6:01 ` NRK 2024-03-10 13:17 ` Alejandro Colomar 2024-03-10 14:01 ` NRK 2024-03-10 19:39 ` Rich Felker 2024-03-10 22:25 ` Alejandro Colomar 2024-03-10 23:22 ` Thorsten Glaser 2024-03-10 23:44 ` Rich Felker 2024-03-11 0:19 ` Thorsten Glaser 2024-03-11 0:46 ` Alejandro Colomar 2024-03-11 14:46 ` Skyler Ferrante (RIT Student) 2024-03-11 15:09 ` Andreas Schwab 2024-03-11 15:30 ` Skyler Ferrante (RIT Student) 2024-03-11 18:23 ` Florian Weimer 2024-03-11 18:48 ` Skyler Ferrante (RIT Student) 2024-03-11 19:05 ` enh 2024-03-11 19:44 ` Rich Felker 2024-03-11 20:35 ` enh 2024-03-11 19:47 ` Rich Felker 2024-03-11 20:08 ` Skyler Ferrante (RIT Student) 2024-03-11 20:39 ` enh 2024-03-11 21:21 ` Laurent Bercot 2024-03-11 22:05 ` Thorsten Glaser 2024-03-12 0:18 ` Gabriel Ravier 2024-03-12 0:43 ` Rich Felker 2024-03-12 3:23 ` Gabriel Ravier 2024-03-12 14:44 ` Rich Felker 2024-03-12 13:54 ` Florian Weimer 2024-03-12 14:21 ` Zack Weinberg 2024-03-12 14:31 ` Florian Weimer 2024-03-12 14:42 ` Rich Felker 2024-03-12 19:25 ` Zack Weinberg 2024-03-12 21:19 ` Rich Felker 2024-03-13 8:28 ` Florian Weimer
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 read-only IMAP folder(s) and NNTP newsgroup(s).