Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Stone <michael@laptop.org>2010-06-29 04:30:45 (GMT)
committer Michael Stone <michael@laptop.org>2010-09-24 02:12:24 (GMT)
commit5b8ad4f19fe16b65df3607be57882bc187899cd6 (patch)
treee100face543b37e4d391c5d6035e2bdb6d214e09
parent633b1f0944eff610d8323a6e1d0591a170323ff1 (diff)
Start work on a port to VNC.ms/vnc
-rwxr-xr-xbin/rainbow-gc2
-rwxr-xr-xbin/rainbow-run10
-rw-r--r--rainbow/inject.py101
3 files changed, 62 insertions, 51 deletions
diff --git a/bin/rainbow-gc b/bin/rainbow-gc
index 60a4ebe..6f1d99a 100755
--- a/bin/rainbow-gc
+++ b/bin/rainbow-gc
@@ -42,7 +42,7 @@ def gc_uid(log, spool, uid):
log(1, "skipped uid %s", uid)
return
- for table in ('uid_to_instance_dir', 'uid_to_home_dir', 'uid_to_gid', 'uid_to_xephyr_auth', 'uid_to_xephyr_cookie', 'uid_to_xephyr_display'):
+ for table in ('uid_to_instance_dir', 'uid_to_home_dir', 'uid_to_gid', 'uid_to_x11_auth', 'uid_to_x11_cookie', 'uid_to_x11_display'):
row = join(spool, table, uid)
# NB: it is important that rm -rf doesn't follow links. <MS>
cmd = ['/bin/rm', '-r', '-f', row]
diff --git a/bin/rainbow-run b/bin/rainbow-run
index 7f5241c..70ba823 100755
--- a/bin/rainbow-run
+++ b/bin/rainbow-run
@@ -35,7 +35,7 @@ def main():
parser.add_option('-i', '--id', default=[], action='append',
help="ID of shared-data group.")
parser.add_option('-o', '--option', default=[], action='append',
- help="Options: video, audio, serial, constant-uid, xephyr, network.")
+ help="Options: video, audio, serial, constant-uid, x11, network.")
parser.add_option('-p', '--permissions', default=None,
help="Location of a permissions.info file.")
parser.add_option('-u', '--user', default=None,
@@ -75,8 +75,8 @@ def main():
def check_groups(opts):
return [grp.getgrnam(g)[2] for g in opts.group]
- def check_xephyr(opts):
- return 'xephyr' in opts.option
+ def check_x11(opts):
+ return 'x11' in opts.option
def check_constant_uid(opts):
return 'constant-uid' in opts.option
@@ -125,12 +125,12 @@ def main():
data_ids = check_data_ids(opts)
assistant = check_assistant(opts)
- xephyr = check_xephyr(opts)
+ x11 = check_x11(opts)
resume_uid = check_resume_user(opts)
if resume_uid: report(1, "resuming uid (%d)", resume_uid)
- args = (report, spool, env, argv, cwd, pset, safe_fds, uid, gid, resume_uid, groups, data_ids, assistant, xephyr)
+ args = (report, spool, env, argv, cwd, pset, safe_fds, uid, gid, resume_uid, groups, data_ids, assistant, x11)
report(1, 'rainbow:\n%s', pformat(args))
unshare(CLONE_NEWNS)
diff --git a/rainbow/inject.py b/rainbow/inject.py
index 1dfd4d6..f628f6d 100644
--- a/rainbow/inject.py
+++ b/rainbow/inject.py
@@ -10,6 +10,7 @@ from tempfile import mkdtemp, mkstemp
from grp import getgrnam, getgrgid
from pwd import getpwuid
from glob import glob
+from time import sleep
import resource
from rainbow.util import Checker, mount, make_dirs, get_fds, read_envdir
@@ -93,40 +94,39 @@ def mount_fsen(log, _):
#mount('tmpfs', '/tmp', 'tmpfs', 0, '')
mount('tmpfs', '/var/tmp', 'tmpfs', 0, '')
+def run_cmd_as_owner(log, cmd, env, owner_uid, owner_gid, groups, safe_fds):
+ pid = fork()
+ if not pid:
+ log(1, 'Dropping privilege to run cmd as owner.')
+ setgroups(groups)
+ setgid(owner_gid)
+ setuid(owner_uid)
+ log(1, 'Closing fds.')
+ for fd in get_fds():
+ if fd not in safe_fds:
+ try: os.close(fd) # propagate failure from EIO or EBADF.
+ except: pass
+ log(1, 'Running cmd.')
+ log(1, '%r %r', cmd, env)
+ execvpe(cmd[0], cmd, env)
+ _exit(59)
+ else:
+ return pid
+
def run_assistant(log, assistant, env, owner_uid, owner_gid, uid, groups, safe_fds):
envdir = None
try:
envdir = mkdtemp()
chown(envdir, owner_uid, owner_gid)
- pid = fork()
- except:
+ assistant_argv = [assistant, '-v', '-v', '-v', '-u', str(uid), '-e', envdir]
+ pid = run_cmd_as_owner(log, assistant_argv, env, owner_uid, owner_gid, groups, safe_fds)
+ pid, status = waitpid(pid, 0)
+ log(1, 'Assistant returned %d.', status)
+ log(1, 'pid %d uid %d', getpid(), getuid())
+ assert not WEXITSTATUS(status)
+ return read_envdir(envdir)
+ finally:
if envdir: check_call(['/bin/rm', '-rf', envdir])
- raise
- else:
- if not pid:
- log(1, 'Dropping privilege to run assistant.')
- setgroups(groups)
- setgid(owner_gid)
- setuid(owner_uid)
- log(1, 'Closing fds.')
- for fd in get_fds():
- if fd not in safe_fds:
- try: os.close(fd) # propagate failure from EIO or EBADF.
- except: pass
- log(1, 'Running assistant.')
- assistant_argv = [assistant, '-v', '-v', '-v', '-u', str(uid), '-e', envdir]
- log(1, '%r %r', assistant_argv, env)
- execvpe(assistant_argv[0], assistant_argv, env)
- _exit(55)
- else:
- try:
- pid, status = waitpid(pid, 0)
- log(1, 'Assistant returned %d.', status)
- assert not WEXITSTATUS(status)
- return read_envdir(envdir)
- finally:
- log(1, 'pid %d uid %d', getpid(), getuid())
- if envdir: check_call(['/bin/rm', '-rf', envdir])
def launch(log, _, uid, gid, groups, argv, env, cwd, pset, safe_fds):
# Set appropriate group membership(s), depending on requested permissions
@@ -187,9 +187,9 @@ def check_cwd(uid, gid, cwd):
def check_spool(spool, owner_uid, owner_gid):
make_dirs(spool, 0, 0, 0755)
spool_dirs = ('uid_pool', 'gid_pool', 'uid_to_gid', 'bundle_id_to_gid',
- 'gid_to_data_dir', 'uid_to_home_dir', 'xephyr_display_pool',
- 'uid_to_xephyr_cookie', 'uid_to_xephyr_display',
- 'uid_to_xephyr_auth', 'gid_to_members', 'gid_to_owner')
+ 'gid_to_data_dir', 'uid_to_home_dir', 'x11_display_pool',
+ 'uid_to_x11_cookie', 'uid_to_x11_display',
+ 'uid_to_x11_auth', 'gid_to_members', 'gid_to_owner')
for frag in spool_dirs:
make_dirs(join(spool, frag), 0, 0, 0755)
ck = Checker(join(spool, frag), owner_uid, owner_gid)
@@ -231,37 +231,48 @@ def configure_groups(log, owner_uid, groups, gid, data_group_to_gid, recorded_gr
except Exception, e: log(1, "Skipping permission (%s) because of (%s).", cap, e)
return list(set(groups))
-def configure_xephyr(_, spool, owner_gid, uid, env, safe_fds):
+def configure_x11(log, spool, owner_uid, owner_gid, uid, env, safe_fds):
# XXX: MUST CHECK RETURN VALUES on subprocesses!!!!!
# XXX: I shouldn't be running these subprocesses as uid 0.
# XXX: Must get env, fds right!!!!
- cookie_path = join(spool, 'uid_to_xephyr_cookie', str(uid))
+ cookie_path = join(spool, 'uid_to_x11_cookie', str(uid))
if lexists(cookie_path):
cookie = readlink(cookie_path)
else:
cookie = Popen(["mcookie"], stdout=PIPE).communicate()[0]
- symlink(cookie, join(spool, 'uid_to_xephyr_cookie', str(uid)))
+ symlink(cookie, join(spool, 'uid_to_x11_cookie', str(uid)))
- display_path = join(spool, 'uid_to_xephyr_display', str(uid))
+ display_path = join(spool, 'uid_to_x11_display', str(uid))
if lexists(display_path):
display = int(readlink(display_path))
else:
- display = reserve_elt(join(spool, 'xephyr_display_pool'), 100, 10000, 2, 'displays')
+ display = reserve_elt(join(spool, 'x11_display_pool'), 100, 10000, 2, 'displays')
symlink(str(display), display_path)
- auth_path = join(spool, 'uid_to_xephyr_auth', str(uid))
+ auth_path = join(spool, 'uid_to_x11_auth', str(uid))
if not exists(auth_path):
- fd, name = mkstemp(prefix='tmp', dir=join(spool, 'uid_to_xephyr_auth'))
+ fd, name = mkstemp(prefix='tmp', dir=join(spool, 'uid_to_x11_auth'))
os.close(fd)
Popen(["xauth", "-f", name], stdin=PIPE).communicate("add :%d . %s\n" % (display, cookie))
rename(name, auth_path)
chmod(auth_path, 0640)
chown(auth_path, 0, owner_gid)
- # NB: Current versions of Xephyr will exit if the display we specified is
- # already in use. This permits us to run Xephyr unconditionally even when
- # we're resuming an old uid. <MS>
- Popen(["Xephyr", "-screen", "800x600x24", "-auth", auth_path, "-reset", "-terminate", ":%d" % display])
+ x11_server_argv = (['Xvnc', '-DisconnectClients', '-NeverShared',
+ '-localhost', '-SecurityTypes', 'None', '-auth',
+ auth_path, '-geometry', '1024x768', '-depth', '24',
+ ':%d' % display])
+ # -extension XFIXES, on ubuntu?
+
+ run_cmd_as_owner(log, x11_server_argv, {}, owner_uid, owner_gid, [owner_gid], safe_fds)
+ sleep(1.0) # XXX: Argh; race condition.
+
+ owner_pw = getpwuid(owner_uid)
+ client_env = { 'HOME' : owner_pw.pw_dir, 'DISPLAY' : env['DISPLAY'] }
+
+ x11_client_argv = (['vncviewer', 'localhost:%d' % (5900 + display)])
+ run_cmd_as_owner(log, x11_client_argv, client_env, owner_uid, owner_gid, [owner_gid], safe_fds)
+ # XXX: need to check that the client successfully connected to the server.
newenv = {'DISPLAY' : ':%d' % display, 'XAUTHORITY' : auth_path}
return newenv
@@ -283,7 +294,7 @@ def check_uid(_, spool, owner_uid, uid):
assert getpwuid(owner_uid).pw_name in getgrgid(uid).gr_mem
def inject(log, spool, env, argv, cwd, pset, safe_fds, owner_uid, owner_gid,
- uid, groups, data_groups, assistant, xephyr):
+ uid, groups, data_groups, assistant, x11):
# Note: exceptions are intended to bubble up to the caller and should
# terminate execution.
check_data_groups(data_groups)
@@ -314,8 +325,8 @@ def inject(log, spool, env, argv, cwd, pset, safe_fds, owner_uid, owner_gid,
check_home(uid, gid, home)
groups = configure_groups(log, owner_uid, groups, gid, data_group_to_gid, recorded_groups, pset)
- if xephyr:
- env.update(configure_xephyr(log, spool, owner_gid, uid, env, safe_fds))
+ if x11:
+ env.update(configure_x11(log, spool, owner_uid, owner_gid, uid, env, safe_fds))
if assistant:
env.update(run_assistant(log, assistant, env, owner_uid, owner_gid, uid, groups, safe_fds))