Search code examples
pythonrootpopen

how to open process with root privileges using subprocess.Popen


I am opening some subproceses in python script and i need one of them to be with root privileges.

Is there a way to do this without running the whole script with root privileges?

p1 = "../p1"
p2 = "../p2"
p_root = "../p_root"

proc_P1 = subprocess.Popen(p1, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE)
proc_P2 = subprocess.Popen(p2, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE)
proc_ROOT = subprocess.Popen(p_root, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE)

Solution

  • There are two (*) methods I can think of.

    /etc/sudoers.d

    Add that one script, ../p_root invocation to be a passwordless sudo configuration in the sudoers.d directory. This configuration will allow only ../p_root to be invoked with passwordless sudo. It is imperative you lock down the script write permissions. At least remove others' permission to write chmod o-w ../p_root. Otherwise, someone can exploit this and run arbitrary code as root by editing the file and adding their own content.

    Each file in /etc/sudoers.d contains rules for sudo. You can add your own files in that directory, to sanely manage your system. The files within /etc/sudoers.d are read in order (convention is to name them 10-something, 20-else, etc). They must be edited with visudo.

    visudo /etc/sudoers.d/20-special-proot
    

    Example content (full path to executable used is mandatory)

    youruser    ALL=(ALL)   NOPASSWD:   /usr/bin/bash /full/path/to/p_root
    

    More details about sudo

    SetUID

    The second is setting SetUID. This is a file permission that allows executing a script with its owner's permission. i.e., it means that you own the ../p_root script to root and whoever can execute it (group/others) will always run the script as root.

    chown root.yourgroup 
    chmod u+s ../p_root
    chmod o-w ../p_root
    

    Again, the same security implications apply here. Whoever can execute this file (group or others have execution permissions, especially) will run everything inside as root. If a low privileged user (e.g. others) have write permissions then they can simply edit the file, add themselves to root and change your PS1 to black on black.

    More details

    sudo (*)

    As advised by lior.i, I'm adding this option, too.
    You can prefix sudo and bash to your script's path as the executed command in order to achieve the same goal.

    Popen(['sudo', 'bash', '/path/to/script'])
    

    Popen is worth learning and the recommended way to execute subprocesses, especially in the long run. In other words, it can do anything the rest can. One of the reasoning for this, I found, is both flexibility and debugging. Flexibility to completely detach the subprocess from its parent or not. By default, if the parent is killed gracefully (SIGINT/Ctrl+C), the child will be signaled to die, too. Similarly, they're also attached at their stdin, stdout and stderr file descriptor. Perhaps you want to make use of a new file descriptor for some crafty magic.

    A consideration you should take if you use this is not using it in production. Leaving an applicative user with passwordless sudo is a security risk similar to just running everything as root.