Re: execve() x system()

From: Glynn Clements (glynn.clementsat_private)
Date: Sun Jun 24 2001 - 18:51:04 PDT

  • Next message: Steve Vinsik: "RE: CDSA-biometrics"

    [NB: apart from the final paragraphs regarding the environment, this
    belongs on a generic Unix programming list, not SecProg. Please
    address follow-ups accordingly.]
    
    Luciano Miguel Ferreira Rocha wrote:
    
    > > I've made some tests with execve() and system()
    > > and now some questions stay open here. I think
    > > you can help me.
    > > I wrote a more friendly interface to useradd.
    > > The problem is, I call 'useradd user' with execve()
    > > and then getpwname(user). At this point getpwname
    > > returns me NULL. Trying with system() it works.
    > > Any idea?
    > 
    > How are you calling execve? You should call it like this:
    >     const char *user = "zbr";
    >     const char *arg[] = { "/usr/sbin/useradd", user, NULL };
    
    NB: this is pseudo-code, not actual C (using a variable inside an
    initialiser is illegal).
    
    >     const char *env[] = { "PATH=/bin:/sbin:/usr/bin:/usr/sbin", NULL };
    > 
    >     if (execve(arg[0], arg, env)) {
    >         perror(argv[0]);
    >     }
    
    Or even just:
    
    	execve(arg[0], arg, env);
    	perror(argv[0]);
    
    Testing the return value from execve() is redundant; if it returns,
    it failed:
    
    > RETURN VALUE
    >        On success, execve() does  not  return,  on  error  -1  is
    >        returned, and errno is set appropriately.
    
    A system() work-alike should look roughly like:
    
    	int status;
    	pid_t pid;
    
    	pid = fork();
    
    	if (pid < 0)
    		return -1;
    	if (pid == 0) { /* child */
    		execv(path, argv);
    		_exit(127);	/* don't use exit(); it flushes I/O buffers */
    	}
    	/* parent */
    	while (waitpid(pid, &status, 0) < 0)
    		if (errno != EINTR)
    			return -1;
    	return status;
    
    Except that in the actual POSIX system(), the parent blocks SIGCHLD
    and ignores SIGINT and SIGQUIT until the child completes. If you're
    writing your own system() replacement, you get to choose the signal
    handling policy.
    
    Also, use of a hard-coded environment is somewhat dubious. It may
    actually make security worse, e.g. by discarding TMPDIR. Whilst setuid
    programs may need to exercise control over the environment, most
    programs should leave untouched any environment variables which they
    don't understand.
    
    Unless the program needs to add, remove or change specific environment
    variables, it probably shouldn't be using execle() or execve().
    
    -- 
    Glynn Clements <glynn.clementsat_private>
    



    This archive was generated by hypermail 2b30 : Mon Jun 25 2001 - 18:43:56 PDT