pythonmultiprocessingpython-2.xpython-multiprocessing

How do you temporarily run your code as 'root'?


I want to use Python's multiprocessing.Pool

import multiprocessing as mp
pool =  mp.Pool(3)
for i in range(num_to_run):
    pool.apply_async(popen_wrapper, args=(i,), callback=log_result)

But I get an OSError:

  File "/usr/local/lib/python2.6/multiprocessing/__init__.py", line 178, in RLock
    return RLock()
  File "/usr/local/lib/python2.6/multiprocessing/synchronize.py", line 142, in __init__
    SemLock.__init__(self, RECURSIVE_MUTEX, 1, 1)
  File "/usr/local/lib/python2.6/multiprocessing/synchronize.py", line 49, in __init__
    sl = self._semlock = _multiprocessing.SemLock(kind, value, maxvalue)
OSError: [Errno 13] Permission denied

I understand that this is because the code doesn't have read-write access to /dev/shm. I would like for the code to temporarily run as root so that it can acquire the lock, and run with user-level privileges otherwise. How can I accomplish this?


Solution

  • In order from the least dangerous to the most dangerous.

    1. You can try dropping permissions as John Zwinck suggested. Basically you would start the program with root level permissions, immediately do what you need to do, and then switch to a non-root user.

      From this StackOverflow.

      import os, pwd, grp
      
      def drop_privileges(uid_name='nobody', gid_name='nogroup'):
      if os.getuid() != 0:
      # We're not root so, like, whatever dude
      return
      
      # Get the uid/gid from the name
      running_uid = pwd.getpwnam(uid_name).pw_uid
      running_gid = grp.getgrnam(gid_name).gr_gid
      
      # Remove group privileges
      os.setgroups([])
      
      # Try setting the new uid/gid
      os.setgid(running_gid)
      os.setuid(running_uid)
      
      # Ensure a very conservative umask
      old_umask = os.umask(077)
      
    2. You could also require the credentials for the root user to be inputed into the script, and then only use them when they are required.

      subprocess.call("sudo python RunStuffWithElevatedPrivelages.py")
      #From here, the main script will continue to run without root permissions
      

      Or if you don't want the script to prompt the user for the password you can do

      subprocess.call("echo getRootCredentials() | sudo -S python RunStuffWithElevatedPrivelages.py")
      
    3. Or you could just run the entire program as a root user -- sudo python myScript.py.

    As far as temporarily giving users root permission to /dev/shm only when they run your script, the only thing I could think of was having some script that runs in the background under the root user that can temporarily grant anyone who uses your script root privileges to /dev/shm. This could be done through using setuid to grant such permissions and then after a certain amount of time or if the script ends the privilege is taken away. My only concern would be if there is a way a user who has temporarily been given such permissions might be able to secure more permanent privileges.