0

I am using the system c++ call to execute the shell script the caller program is running as root but the shell sctipt which is called form the c++ code is running as different user.

How can I make sure the shell script should also run as root user like the c++ binary. I don't want to rely on using sudo command as it can ask for password.

> [user@user ~]$ ll a.out temp.sh
> -rwsrwsr-x 1 root     root     8952 Jun 14 13:16 a.out
> -rwxrwxr-x 1 user     user   34 Jun 14 15:43 temp.sh
[user@user ~]$ cat temp.sh

#!/bin/bash read -n 1 -p "Hello"

[user@user ~]$ ps aux | grep temp 
root     13247  0.0  0.0  13252 1540 pts/0    S+   15:44   0:00 ./a.out ./temp.sh 
user 13248  0.0  0.0 113152  2544 pts/0    S+   15:44   0:00 /bin/bash ./temp.sh 

c++ code

#include <bits/stdc++.h>
using namespace std;
int main(int argc, char *argv[])
{
system(argv[1]);
return 0;
}
Aryaman Gupta
  • 616
  • 1
  • 8
  • 20

1 Answers1

1

A few bits of documentation to start:

From man 3 system's caveats section:

Do not use system() from a privileged program (a set-user-ID or set-group-ID program, or a program with capabilities) because strange values for some environment variables might be used to subvert system integrity. For example, PATH could be manipulated so that an arbitrary program is executed with privilege. Use the exec(3) family of functions instead, but not execlp(3) or execvp(3) (which also use the PATH environment variable to search for an executable).

system() will not, in fact, work properly from programs with set-user-ID or set-group-ID privileges on systems on which /bin/sh is bash version 2: as a security measure, bash 2 drops privileges on startup. Debian uses a different shell, dash(1), which does not do this when invoked as sh.)

And from the bash manual's description of the -p command line argument (Emphasis added):

Turn on privileged mode. In this mode, the $BASH_ENV and $ENV files are not processed, shell functions are not inherited from the environment, and the SHELLOPTS, BASHOPTS, CDPATH and GLOBIGNORE variables, if they appear in the environment, are ignored. If the shell is started with the effective user (group) id not equal to the real user (group) id, and the -p option is not supplied, these actions are taken and the effective user id is set to the real user id. If the -p option is supplied at startup, the effective user id is not reset. Turning this option off causes the effective user and group ids to be set to the real user and group ids.

So even if your /bin/sh doesn't drop privileges when run, bash will when it's run in turn without explicitly telling it not to.

So one option is to scrap using system(), and do a lower-level fork()/exec() of bash -p your-script-name.

Some other approaches to allowing scripts to run at elevated privileges are mentioned in Allow suid on shell scripts. In particular the answer using setuid() to change the real UID looks like it's worth investigating.

Or configure sudo to not require a password for a particular script for a given user.


Also see Why should I not #include <bits/stdc++.h>?

Shawn
  • 47,241
  • 3
  • 26
  • 60
  • using fork and setting the real uid with effetive uid of the parent(euid = 0 for parent as setuid field is set) and then calling the execl function for invokng the shell script does the work, not sure if this is right way to do so but it's working and the shell scipt is running as the root (euid = realui=0). This is as per the statement you mentioned I did make the euid equal to realuid for the child process. – Aryaman Gupta Jun 15 '21 at 13:43