0

I am writing a python script that will use subprocess Popen (with communicate() I am thinking) to run various shell commands, etc. Often, the shell commands that I am executing would typically be run (manually) with sudo.

I am running the script that uses subprocess with sudo. I am wondering if I can safely leave sudo off all of my subprocess calls or if I need to include it and use stdin to provide a password.

This seems like a pretty simple question, but I have been unable to find the answer yet. From my experimentation, it seems like I might not need to sudo, but I am not sure if that is really true or if it is simply 'working this way' because I have recently provided my password.

EDIT: I figured out how to drop and recover root. Its pretty simple with the multiprocessing package

...
from multiprocessing import Process, Pipe
...
parent_conn, child_conn = Pipe()
p = P(input_list, child_conn)
p.start()
p.join()
return RunSyncReturn(**parent_conn.recv())
...

class P(Process):
    def __init__(self, input_list, conn):
        super(P, self).__init__()
        self._input_list = input_list
        self._conn = conn

    def run(self):
        drop_privileges()
        process = Popen(self._input_list, stdout=PIPE)
        stdout, stderr = process.communicate()
        pmap = {}
        pmap['stdout'] = stdout
        pmap['stderr'] = stderr
        pmap['exit_code'] = process.returncode
        self._conn.send(pmap)
        self._conn.close()

RunSyncReturn is just a data holder class. When the Process launched with the multiprocessing Process class dies, the lowered privileges go away with it.

chrismead
  • 2,163
  • 3
  • 24
  • 36
  • 1
    UIDs are inherited by `fork()`ed processes. It might be worth considering whether you really *need* to be `root` for everything or whether you can drop privileges to (say) `nobody` where possible (with `os.setuid()` and `os.setgid()`). As a general rule-of-thumb, you should only be `root` when you absolutely need to be, and it's pretty easy to do. – Emmet Mar 06 '14 at 19:38
  • Emmet, that is a good point. I will look into using os.setuid() and os.setgid() unless sudo is truly needed. Thanks for the comment. – chrismead Mar 06 '14 at 20:10
  • 1
    Chris, I [found this](http://antonym.org/2005/12/dropping-privileges-in-python.html) and thought it might be useful to you. – Emmet Mar 06 '14 at 20:14
  • Thanks again, Emmet. That is a helpful link. Do you happen to know if there is a way to 'drop privileges' only for a particular code block. In other words, a way to get back to root after dropping to nobody. I modified to the code you pointed me to for this purpose, but os.setgid() and os.setuid() fail (not permitted) once I drop to nobody. – chrismead Mar 06 '14 at 21:21
  • you should have probably asked a separate question about `Could not set effective group id` error – jfs Mar 06 '14 at 21:57
  • Chris, there's [an answer here on Stack Overflow](http://stackoverflow.com/questions/1770209/run-child-processes-as-different-user-from-a-long-running-process) that you might find useful. – Emmet Mar 06 '14 at 22:24

2 Answers2

4

User IDs and access rights will get inherited by subprocesses. As long as none of the commands you're running is owned by a different user and has the s-bit set, they will run as root as well.

Guntram Blohm
  • 9,667
  • 2
  • 24
  • 31
0

I was hoping to do this: change_privileges(); do_something(); change_privileges('root', 'root')

Instead of trying temporarily to change privileges in the same process, use prexec_fn function to drop privileges only for the child process started by Popen() e.g., look at demote() function.

Community
  • 1
  • 1
jfs
  • 399,953
  • 195
  • 994
  • 1,670