1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
|
#!/usr/bin/env python
import os
import sys
import pwd
import grp
from stat import S_ISREG, ST_MODE
from os.path import join, isdir
from optparse import OptionParser
from pprint import pformat
from rainbow.inject import inject
from rainbow.permissions import PermissionSet
from rainbow.util import make_reporter, trace, unshare, CLONE_NEWNS, read_envdir
sys.excepthook = trace
def main():
parser = OptionParser(version='0.1')
parser.add_option('-v', '--verbose', default=0, action='count',
help='Verbosity. Repeat for more verbose output.')
parser.add_option('-q', '--quiet', default=False, action='store_true',
help='Quiet. Disable all output.')
parser.add_option('-s', '--spool', default=None,
help='Location of the rainbow spool.')
parser.add_option('-e', '--envdir', default=None,
help="Location of an envdir describing the desired environment.")
parser.add_option('-E', '--env', default=[], action='append',
help="Environment bindings to override.")
parser.add_option('-c', '--cwd', default=None,
help="Working directory.")
parser.add_option('-f', '--fd', default=[], action='append',
help="File descriptor number to leave open.")
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.")
parser.add_option('-p', '--permissions', default=None,
help="Location of a permissions.info file.")
parser.add_option('-u', '--user', default=None,
help="Owning user.")
parser.add_option('-r', '--resume-user', default=None,
help="Resume <user>.")
parser.add_option('-a', '--assistant', default=None,
help="Task-specific assistant.")
parser.add_option('-G', '--group', default=[], action='append',
help="Extra groups.")
opts, args = parser.parse_args()
if len(args) == 0:
parser.print_help()
exit(1)
report = make_reporter(opts.verbose, opts.quiet, sys.stdout)
def check_spool(opts):
return opts.spool
def check_env(opts):
return read_envdir(opts.envdir, opts.env)
def check_argv(args):
return args
def check_cwd(opts):
return opts.cwd
def check_fds(opts):
return [int(s) for s in opts.fd]
def check_owner(opts):
p = pwd.getpwnam(opts.user)
return p.pw_uid, p.pw_gid
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_constant_uid(opts):
return 'constant-uid' in opts.option
def check_audio(opts):
return 'audio' in opts.option
def check_video(opts):
return 'video' in opts.option
def check_serial(opts):
return 'serial' in opts.option
def check_network(opts):
return 'network' in opts.option
def check_resume_user(opts):
uid = None
if opts.resume_user:
uid = pwd.getpwnam(opts.resume_user).pw_uid
assert 10000 <= uid and uid < 60000
return uid
def check_data_ids(opts):
return opts.id
def check_assistant(opts):
return opts.assistant
uid, gid = check_owner(opts)
spool = check_spool(opts)
# Use empty env? Use partial env? Fail unless perfect?
env = check_env(opts)
argv = check_argv(args)
cwd = check_cwd(opts)
safe_fds = check_fds(opts)
groups = check_groups(opts)
pset = PermissionSet(opts.permissions or [])
# Dirty hack -- pass 'constant-uid' and 'strace' in as permissions. <MS>
for perm in ('constant-uid', 'audio', 'video', 'serial', 'network'):
pset._permissions.setdefault(perm, locals()['check_'+perm.replace('-','_')](opts))
data_ids = check_data_ids(opts)
assistant = check_assistant(opts)
xephyr = check_xephyr(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)
report(1, 'rainbow:\n%s', pformat(args))
unshare(CLONE_NEWNS)
return inject(*args)
if __name__ == '__main__':
main()
# vim : et sw=4 ts=4 sts=4 :
|