mailing list of musl libc
 help / color / mirror / code / Atom feed
* [musl] Namespace violation in system()?
@ 2023-05-04 16:33 Markus Wichmann
  2023-05-04 17:52 ` Rich Felker
  0 siblings, 1 reply; 5+ messages in thread
From: Markus Wichmann @ 2023-05-04 16:33 UTC (permalink / raw)
  To: musl

Hi all,

I stumbled upon the source code of system() today. It is this at the
moment:

|int system(const char *cmd)
|{
|	pid_t pid;
|	sigset_t old, reset;
|	struct sigaction sa = { .sa_handler = SIG_IGN }, oldint, oldquit;
|	int status = -1, ret;
|	posix_spawnattr_t attr;
|
|	pthread_testcancel();
|
|	if (!cmd) return 1;
|
|	sigaction(SIGINT, &sa, &oldint);
|	sigaction(SIGQUIT, &sa, &oldquit);
|	sigaddset(&sa.sa_mask, SIGCHLD);
|	sigprocmask(SIG_BLOCK, &sa.sa_mask, &old);
|
|	sigemptyset(&reset);
|	if (oldint.sa_handler != SIG_IGN) sigaddset(&reset, SIGINT);
|	if (oldquit.sa_handler != SIG_IGN) sigaddset(&reset, SIGQUIT);
|	posix_spawnattr_init(&attr);
|	posix_spawnattr_setsigmask(&attr, &old);
|	posix_spawnattr_setsigdefault(&attr, &reset);
|	posix_spawnattr_setflags(&attr, POSIX_SPAWN_SETSIGDEF|POSIX_SPAWN_SETSIGMASK);
|	ret = posix_spawn(&pid, "/bin/sh", 0, &attr,
|		(char *[]){"sh", "-c", (char *)cmd, 0}, __environ);
|	posix_spawnattr_destroy(&attr);
|
|	if (!ret) while (waitpid(pid, &status, 0)<0 && errno == EINTR);
|	sigaction(SIGINT, &oldint, NULL);
|	sigaction(SIGQUIT, &oldquit, NULL);
|	sigprocmask(SIG_SETMASK, &old, NULL);
|
|	if (ret) errno = ret;
|	return status;
|}

Aren't all of those calls namespace violations? system() is an ISO-C
function, so the only symbols it is allowed to pull into the link are
other ISO-C functions or hidden double-underscore symbols, right? But
all the functions called here POSIX functions. And while POSIX contains
the rule that posix_* functions are reserved, that is in POSIX, not
ISO-C. And even with that rule, there are all the other calls.

Does someone need to pour out a bucket of underscores over this
function?

Ciao,
Markus

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [musl] Namespace violation in system()?
  2023-05-04 16:33 [musl] Namespace violation in system()? Markus Wichmann
@ 2023-05-04 17:52 ` Rich Felker
  2023-05-04 18:53   ` Petr Skocik
  2023-05-04 19:12   ` Rich Felker
  0 siblings, 2 replies; 5+ messages in thread
From: Rich Felker @ 2023-05-04 17:52 UTC (permalink / raw)
  To: Markus Wichmann; +Cc: musl

On Thu, May 04, 2023 at 06:33:27PM +0200, Markus Wichmann wrote:
> Hi all,
> 
> I stumbled upon the source code of system() today. It is this at the
> moment:
> 
> |int system(const char *cmd)
> |{
> |	pid_t pid;
> |	sigset_t old, reset;
> |	struct sigaction sa = { .sa_handler = SIG_IGN }, oldint, oldquit;
> |	int status = -1, ret;
> |	posix_spawnattr_t attr;
> |
> |	pthread_testcancel();
> |
> |	if (!cmd) return 1;
> |
> |	sigaction(SIGINT, &sa, &oldint);
> |	sigaction(SIGQUIT, &sa, &oldquit);
> |	sigaddset(&sa.sa_mask, SIGCHLD);
> |	sigprocmask(SIG_BLOCK, &sa.sa_mask, &old);
> |
> |	sigemptyset(&reset);
> |	if (oldint.sa_handler != SIG_IGN) sigaddset(&reset, SIGINT);
> |	if (oldquit.sa_handler != SIG_IGN) sigaddset(&reset, SIGQUIT);
> |	posix_spawnattr_init(&attr);
> |	posix_spawnattr_setsigmask(&attr, &old);
> |	posix_spawnattr_setsigdefault(&attr, &reset);
> |	posix_spawnattr_setflags(&attr, POSIX_SPAWN_SETSIGDEF|POSIX_SPAWN_SETSIGMASK);
> |	ret = posix_spawn(&pid, "/bin/sh", 0, &attr,
> |		(char *[]){"sh", "-c", (char *)cmd, 0}, __environ);
> |	posix_spawnattr_destroy(&attr);
> |
> |	if (!ret) while (waitpid(pid, &status, 0)<0 && errno == EINTR);
> |	sigaction(SIGINT, &oldint, NULL);
> |	sigaction(SIGQUIT, &oldquit, NULL);
> |	sigprocmask(SIG_SETMASK, &old, NULL);
> |
> |	if (ret) errno = ret;
> |	return status;
> |}
> 
> Aren't all of those calls namespace violations? system() is an ISO-C
> function, so the only symbols it is allowed to pull into the link are
> other ISO-C functions or hidden double-underscore symbols, right? But
> all the functions called here POSIX functions. And while POSIX contains
> the rule that posix_* functions are reserved, that is in POSIX, not
> ISO-C. And even with that rule, there are all the other calls.
> 
> Does someone need to pour out a bucket of underscores over this
> function?

The behavior of system() is implementation-defined, so we define it as
calling those functions. :-)

Rich

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [musl] Namespace violation in system()?
  2023-05-04 17:52 ` Rich Felker
@ 2023-05-04 18:53   ` Petr Skocik
  2023-05-04 19:16     ` Rich Felker
  2023-05-04 19:12   ` Rich Felker
  1 sibling, 1 reply; 5+ messages in thread
From: Petr Skocik @ 2023-05-04 18:53 UTC (permalink / raw)
  To: Rich Felker; +Cc: musl

On 5/4/23 19:52, Rich Felker wrote:
> On Thu, May 04, 2023 at 06:33:27PM +0200, Markus Wichmann wrote:
>> Hi all,
>>
>> I stumbled upon the source code of system() today. It is this at the
>> moment:
>>
>> |int system(const char *cmd)
>> |{
>> |	pid_t pid;
>> |	sigset_t old, reset;
>> |	struct sigaction sa = { .sa_handler = SIG_IGN }, oldint, oldquit;
>> |	int status = -1, ret;
>> |	posix_spawnattr_t attr;
>> |
>> |	pthread_testcancel();
>> |
>> |	if (!cmd) return 1;
>> |
>> |	sigaction(SIGINT, &sa, &oldint);
>> |	sigaction(SIGQUIT, &sa, &oldquit);
>> |	sigaddset(&sa.sa_mask, SIGCHLD);
>> |	sigprocmask(SIG_BLOCK, &sa.sa_mask, &old);
>> |
>> |	sigemptyset(&reset);
>> |	if (oldint.sa_handler != SIG_IGN) sigaddset(&reset, SIGINT);
>> |	if (oldquit.sa_handler != SIG_IGN) sigaddset(&reset, SIGQUIT);
>> |	posix_spawnattr_init(&attr);
>> |	posix_spawnattr_setsigmask(&attr, &old);
>> |	posix_spawnattr_setsigdefault(&attr, &reset);
>> |	posix_spawnattr_setflags(&attr, POSIX_SPAWN_SETSIGDEF|POSIX_SPAWN_SETSIGMASK);
>> |	ret = posix_spawn(&pid, "/bin/sh", 0, &attr,
>> |		(char *[]){"sh", "-c", (char *)cmd, 0}, __environ);
>> |	posix_spawnattr_destroy(&attr);
>> |
>> |	if (!ret) while (waitpid(pid, &status, 0)<0 && errno == EINTR);
>> |	sigaction(SIGINT, &oldint, NULL);
>> |	sigaction(SIGQUIT, &oldquit, NULL);
>> |	sigprocmask(SIG_SETMASK, &old, NULL);
>> |
>> |	if (ret) errno = ret;
>> |	return status;
>> |}
>>
>> Aren't all of those calls namespace violations? system() is an ISO-C
>> function, so the only symbols it is allowed to pull into the link are
>> other ISO-C functions or hidden double-underscore symbols, right? But
>> all the functions called here POSIX functions. And while POSIX contains
>> the rule that posix_* functions are reserved, that is in POSIX, not
>> ISO-C. And even with that rule, there are all the other calls.
>>
>> Does someone need to pour out a bucket of underscores over this
>> function?
> The behavior of system() is implementation-defined, so we define it as
> calling those functions. :-)
>
> Rich

Hi. I think Markus Wichmann makes a valid point.

Unless it's valid behavior for

#include <stdio.h>
#include <stdlib.h>
void sigprocmask(void){
     puts("Hi, I'm a user-defined sigprocmask");
     system("echo hello world");
}
int main(void){ sigprocmask(); }

to keep outputting "Hi, I'm a user-defined sigprocmask" until it crashes 
from stack overflow (musl-gcc -static).

Cheers, Petr Skocik

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [musl] Namespace violation in system()?
  2023-05-04 17:52 ` Rich Felker
  2023-05-04 18:53   ` Petr Skocik
@ 2023-05-04 19:12   ` Rich Felker
  1 sibling, 0 replies; 5+ messages in thread
From: Rich Felker @ 2023-05-04 19:12 UTC (permalink / raw)
  To: Markus Wichmann; +Cc: musl

On Thu, May 04, 2023 at 01:52:08PM -0400, Rich Felker wrote:
> On Thu, May 04, 2023 at 06:33:27PM +0200, Markus Wichmann wrote:
> > Hi all,
> > 
> > I stumbled upon the source code of system() today. It is this at the
> > moment:
> > 
> > |int system(const char *cmd)
> > |{
> > |	pid_t pid;
> > |	sigset_t old, reset;
> > |	struct sigaction sa = { .sa_handler = SIG_IGN }, oldint, oldquit;
> > |	int status = -1, ret;
> > |	posix_spawnattr_t attr;
> > |
> > |	pthread_testcancel();
> > |
> > |	if (!cmd) return 1;
> > |
> > |	sigaction(SIGINT, &sa, &oldint);
> > |	sigaction(SIGQUIT, &sa, &oldquit);
> > |	sigaddset(&sa.sa_mask, SIGCHLD);
> > |	sigprocmask(SIG_BLOCK, &sa.sa_mask, &old);
> > |
> > |	sigemptyset(&reset);
> > |	if (oldint.sa_handler != SIG_IGN) sigaddset(&reset, SIGINT);
> > |	if (oldquit.sa_handler != SIG_IGN) sigaddset(&reset, SIGQUIT);
> > |	posix_spawnattr_init(&attr);
> > |	posix_spawnattr_setsigmask(&attr, &old);
> > |	posix_spawnattr_setsigdefault(&attr, &reset);
> > |	posix_spawnattr_setflags(&attr, POSIX_SPAWN_SETSIGDEF|POSIX_SPAWN_SETSIGMASK);
> > |	ret = posix_spawn(&pid, "/bin/sh", 0, &attr,
> > |		(char *[]){"sh", "-c", (char *)cmd, 0}, __environ);
> > |	posix_spawnattr_destroy(&attr);
> > |
> > |	if (!ret) while (waitpid(pid, &status, 0)<0 && errno == EINTR);
> > |	sigaction(SIGINT, &oldint, NULL);
> > |	sigaction(SIGQUIT, &oldquit, NULL);
> > |	sigprocmask(SIG_SETMASK, &old, NULL);
> > |
> > |	if (ret) errno = ret;
> > |	return status;
> > |}
> > 
> > Aren't all of those calls namespace violations? system() is an ISO-C
> > function, so the only symbols it is allowed to pull into the link are
> > other ISO-C functions or hidden double-underscore symbols, right? But
> > all the functions called here POSIX functions. And while POSIX contains
> > the rule that posix_* functions are reserved, that is in POSIX, not
> > ISO-C. And even with that rule, there are all the other calls.
> > 
> > Does someone need to pour out a bucket of underscores over this
> > function?
> 
> The behavior of system() is implementation-defined, so we define it as
> calling those functions. :-)

To elaborate:

    "If string is a null pointer, the system function determines
    whether the host environment has a command processor. If string is
    not a null pointer, the system function passes the string pointed
    to by string to that command processor to be executed in a manner
    which the implementation shall document; this might then cause the
    program calling system to behave in a non-conforming manner or to
    terminate."

The manner in which we pass the string to a command processor to be
executed is via calls to external identifiers defined by POSIX.

Even if this sounds like a silly way to be "technically conforming",
it's really not. The semantics of calling system() are completely
unspecified without assuming POSIX or some other specification beyond
just plain C, so there's no reasonable way a C program running on top
of the implementation can call system() without further assumptions
about the implementation (e.g. that it's implementing POSIX).

Rich

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [musl] Namespace violation in system()?
  2023-05-04 18:53   ` Petr Skocik
@ 2023-05-04 19:16     ` Rich Felker
  0 siblings, 0 replies; 5+ messages in thread
From: Rich Felker @ 2023-05-04 19:16 UTC (permalink / raw)
  To: Petr Skocik; +Cc: musl

On Thu, May 04, 2023 at 08:53:03PM +0200, Petr Skocik wrote:
> On 5/4/23 19:52, Rich Felker wrote:
> >On Thu, May 04, 2023 at 06:33:27PM +0200, Markus Wichmann wrote:
> >>Hi all,
> >>
> >>I stumbled upon the source code of system() today. It is this at the
> >>moment:
> >>
> >>|int system(const char *cmd)
> >>|{
> >>|	pid_t pid;
> >>|	sigset_t old, reset;
> >>|	struct sigaction sa = { .sa_handler = SIG_IGN }, oldint, oldquit;
> >>|	int status = -1, ret;
> >>|	posix_spawnattr_t attr;
> >>|
> >>|	pthread_testcancel();
> >>|
> >>|	if (!cmd) return 1;
> >>|
> >>|	sigaction(SIGINT, &sa, &oldint);
> >>|	sigaction(SIGQUIT, &sa, &oldquit);
> >>|	sigaddset(&sa.sa_mask, SIGCHLD);
> >>|	sigprocmask(SIG_BLOCK, &sa.sa_mask, &old);
> >>|
> >>|	sigemptyset(&reset);
> >>|	if (oldint.sa_handler != SIG_IGN) sigaddset(&reset, SIGINT);
> >>|	if (oldquit.sa_handler != SIG_IGN) sigaddset(&reset, SIGQUIT);
> >>|	posix_spawnattr_init(&attr);
> >>|	posix_spawnattr_setsigmask(&attr, &old);
> >>|	posix_spawnattr_setsigdefault(&attr, &reset);
> >>|	posix_spawnattr_setflags(&attr, POSIX_SPAWN_SETSIGDEF|POSIX_SPAWN_SETSIGMASK);
> >>|	ret = posix_spawn(&pid, "/bin/sh", 0, &attr,
> >>|		(char *[]){"sh", "-c", (char *)cmd, 0}, __environ);
> >>|	posix_spawnattr_destroy(&attr);
> >>|
> >>|	if (!ret) while (waitpid(pid, &status, 0)<0 && errno == EINTR);
> >>|	sigaction(SIGINT, &oldint, NULL);
> >>|	sigaction(SIGQUIT, &oldquit, NULL);
> >>|	sigprocmask(SIG_SETMASK, &old, NULL);
> >>|
> >>|	if (ret) errno = ret;
> >>|	return status;
> >>|}
> >>
> >>Aren't all of those calls namespace violations? system() is an ISO-C
> >>function, so the only symbols it is allowed to pull into the link are
> >>other ISO-C functions or hidden double-underscore symbols, right? But
> >>all the functions called here POSIX functions. And while POSIX contains
> >>the rule that posix_* functions are reserved, that is in POSIX, not
> >>ISO-C. And even with that rule, there are all the other calls.
> >>
> >>Does someone need to pour out a bucket of underscores over this
> >>function?
> >The behavior of system() is implementation-defined, so we define it as
> >calling those functions. :-)
> >
> >Rich
> 
> Hi. I think Markus Wichmann makes a valid point.
> 
> Unless it's valid behavior for
> 
> #include <stdio.h>
> #include <stdlib.h>
> void sigprocmask(void){
>     puts("Hi, I'm a user-defined sigprocmask");
>     system("echo hello world");
> }
> int main(void){ sigprocmask(); }
> 
> to keep outputting "Hi, I'm a user-defined sigprocmask" until it
> crashes from stack overflow (musl-gcc -static).

Yes, it is valid behavior. C doesn't define anything about what the
command in the string means, and in fact there are commands which
would do specifically that regardless of how we implement system. For
example, system("gdb ..."); with an appropriately nasty set of gdb
commands pointed at $PPID or something.

If you want to be assuming there's an echo command with POSIX
semantics, you're writing a POSIX program not a plain C program, and
then redefining sigprocmask has undefined behavior.

Rich

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2023-05-04 19:17 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-05-04 16:33 [musl] Namespace violation in system()? Markus Wichmann
2023-05-04 17:52 ` Rich Felker
2023-05-04 18:53   ` Petr Skocik
2023-05-04 19:16     ` Rich Felker
2023-05-04 19:12   ` Rich Felker

Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/musl/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).