Take the 2-minute tour ×
Ask Ubuntu is a question and answer site for Ubuntu users and developers. It's 100% free, no registration required.

Consider this python script, which invokes HandBrakeCLI, a program that attempts to read from the dvd drive:

invoke.py

#!/usr/bin/python

import sys
import os
import subprocess as subp
import pprint

#immediately switch users
os.setgid(1002) #gid of "media"
os.setuid(1005) #uid of "jack"

#verify the switch worked
print os.getuid(), os.geteuid()
print os.getgid(), os.getegid()

#clear up any possible env var diffs
os.environ['USER'] = 'jack'
os.environ['USERNAME'] = 'jack'
os.environ['LOGNAME'] = 'jack'

#output env variables to see if there's anything different:
ff = open('env_%s.log' % sys.argv[1], 'w')
ff.write(pprint.pformat(dict(os.environ)))
ff.write("\n")
ff.close()

#call the program
p = subp.Popen(["HandBrakeCLI", "-i", "/dev/sr0", "-t", "0"])
p.communicate()

sys.exit(p.returncode)

The following ("A") succeeds:

sudo -u jack -g media HandBrakeCLI -i /dev/sr0 -t 0

as does this ("B"):

sudo -u jack -g media ./invoke.py jack

but this ("C") fails:

sudo ./invoke.py root

and prints errors suggesting that HandBrakeCLI was unable to access the CD drive. The print statements confirm that the UID/GID were successfully changed to jack:media, however. If I remove the setuid/setgid and call HandBrakeCLI from invoke.py as root, it works once again.

A diff shows the environments are essentially the same:

$ diff env_root.log env_jack.log
8c8
<  'SUDO_COMMAND': './invoke.py root',
---
>  'SUDO_COMMAND': './invoke.py jack',

After invoking setuid and setgid, is there any "memory" of the original invoking user? If not, what could HandBrake possibly be seeing differently between "B" and "C"?

I am running 10.04 on a headless server which I access via ssh.

share|improve this question
add comment

1 Answer

up vote 2 down vote accepted

It does make a difference, as one can detect if the privileges were elevated (suid case) which is different from running via sudo. That's because the whole process is running as 'jack' in the sudo case (and never reverts the uid: the process just terminates), whereas the suid case "remembers" the original uid and only the effective uid is changed.

Your situation is slightly different but here is a test script which detects each combination of sudo/suid: test_privs.sh Similar code is now used in the X11 server to detect elevated privileges: xorg-devel discussion

I haven't looked at your specific device/handbrake needs, but this should put you on the right track.

share|improve this answer
    
Thanks, this is helpful. My own test script reports that the real/effective gid/uids are the same; and the "getresuid" test in your example fails-- I'm guessing Ubuntu doesn't support it. The only thing I can guess is different (based on your example) is the result of issetuid(). I can't find much documentation on this at all. What effects might it have on permissions/program behavior? How can I clear it to see if that's my problem? Is clearing it safe? If not, how do I properly relinquish root privileges? –  trbabb Jan 12 '12 at 0:29
    
As far as I know, you cannot reset issetuid(). If your binary is suid-root, I believe this flag will be set until it exits. –  totaam Jan 12 '12 at 6:47
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.