diff --git a/utils/apparmor/sandbox.py b/utils/apparmor/sandbox.py index 7fcb07f6f..0dccd0c90 100644 --- a/utils/apparmor/sandbox.py +++ b/utils/apparmor/sandbox.py @@ -14,6 +14,7 @@ import optparse import os import pwd import re +import signal import sys import tempfile import time @@ -50,15 +51,19 @@ def parse_args(args=None, parser=None): dest='xserver', default='xpra', help='Nested X server to use: xpra (default), xpra3d, xephyr') + parser.add_option('--with-xauthority', + dest='xauthority', + default=None, + help='Specify Xauthority file to use') parser.add_option('-d', '--debug', dest='debug', default=False, help='Show debug messages', action='store_true') - parser.add_option('-r', '--with-geometry', - dest='geometry', + parser.add_option('--with-xephyr-geometry', + dest='xephyr_geometry', default='640x480', - help='Resolution for X application') + help='Geometry for Xephyr window') parser.add_option('--profile', dest='profile', default=None, @@ -127,7 +132,7 @@ def aa_exec(command, opt, environ={}): raise AppArmorException("Could not load policy") set_environ(environ) - args = ['aa-exec', '-p', policy_name] + command + args = ['aa-exec', '-p', policy_name, '--'] + command rc, report = cmd(args) return rc, report @@ -138,7 +143,7 @@ def run_sandbox(command, opt): return rc, report class SandboxXserver(): - def __init__(self, geometry, title, driver=None): + def __init__(self, title, geometry=None, driver=None, xauth=None): self.geometry = geometry self.title = title self.pids = [] @@ -154,6 +159,11 @@ class SandboxXserver(): # prepare the new environment self.display, self.xauth = self.find_free_x_display() + if xauth: + abs_xauth = os.path.expanduser(xauth) + if os.path.expanduser("~/.Xauthority") == abs_xauth: + raise AppArmorException("Trusted Xauthority file specified. Aborting") + self.xauth = abs_xauth self.new_environ = dict() self.new_environ['DISPLAY'] = self.display self.new_environ['XAUTHORITY'] = self.xauth @@ -162,10 +172,17 @@ class SandboxXserver(): def cleanup(self): '''Cleanup our forked pids, reset the environment, etc''' + self.pids.reverse() + debug(self.pids) for pid in self.pids: - # kill server now. It should've terminated, but be sure - debug("Killing '%d'" % pid) - cmd(['kill', "%d" % pid]) + # Kill server with TERM + debug("kill %d" % pid) + os.kill(pid, signal.SIGTERM) + + for pid in self.pids: + # Shoot the server dead + debug("kill -9 %d" % pid) + os.kill(pid, signal.SIGKILL) for t in self.tempfiles: if os.path.exists(t): @@ -275,7 +292,7 @@ class SandboxXephyr(SandboxXserver): args = ['/usr/bin/Xephyr'] + x_args + [self.display] debug(" ".join(args)) - cmd(args) + os.execv(args[0], args) sys.exit(0) self.pids.append(listener_x) @@ -288,8 +305,6 @@ class SandboxXephyr(SandboxXserver): if listener_wm == 0: # update environment set_environ(self.new_environ) - #os.environ["DISPLAY"] = self.display - #debug("DISPLAY is now '%s'" % os.environ["DISPLAY"]) args = ['/usr/bin/matchbox-window-manager', '-use_titlebar', 'no'] debug(" ".join(args)) @@ -302,13 +317,22 @@ class SandboxXephyr(SandboxXserver): class SandboxXpra(SandboxXserver): def cleanup(self): - # This can block + sys.stderr.flush() listener = os.fork() if listener == 0: - cmd(['xpra', 'stop', self.display]) + args = ['/usr/bin/xpra', 'stop', self.display] + debug(" ".join(args)) + os.execv(args[0], args) sys.exit(0) - self.pids.append(listener_x) time.sleep(2) + + # Annoyingly, xpra doesn't clean up itself well if the application + # failed for some reason. Try to account for that. + rc, report = cmd(['ps', 'auxww']) + for line in report.splitlines(): + if '-for-Xpra-%s' % self.display in line: + self.pids.append(int(line.split()[1])) + SandboxXserver.cleanup(self) def _get_xvfb_args(self): @@ -333,7 +357,8 @@ class SandboxXpra(SandboxXserver): elif self.driver == 'xdummy': # The dummy driver allows us to use GLX, etc. See: # http://xpra.org/Xdummy.html - conf = '''# Based on /usr/share/doc/xpra/examples/dummy.xorg.conf.gz + conf = '''# /usr/share/doc/xpra/examples/dummy.xorg.conf.gz +# http://xpra.org/Xdummy.html ##Xdummy:## Section "ServerFlags" Option "DontVTSwitch" "true" @@ -343,6 +368,7 @@ Section "ServerFlags" Option "AutoAddDevices" "false" EndSection + ##Xdummy:## Section "InputDevice" Identifier "NoMouse" @@ -360,10 +386,107 @@ EndSection Section "Device" Identifier "Videocard0" Driver "dummy" + # In kByte #VideoRam 4096000 - #VideoRam 256000 + VideoRam 256000 EndSection +##Xdummy:## +Section "Monitor" + Identifier "Monitor0" + HorizSync 10.0 - 300.0 + VertRefresh 10.0 - 200.0 + DisplaySize 4335 1084 + #The following modeline is invalid (calculator overflowed): + #Modeline "32000x32000@0" -38917.43 32000 32032 -115848 -115816 32000 32775 32826 33601 + Modeline "16384x8192@10" 2101.93 16384 16416 24400 24432 8192 8390 8403 8602 + Modeline "8192x4096@10" 424.46 8192 8224 9832 9864 4096 4195 4202 4301 + Modeline "5120x3200@10" 199.75 5120 5152 5904 5936 3200 3277 3283 3361 + Modeline "3840x2880@10" 133.43 3840 3872 4376 4408 2880 2950 2955 3025 + Modeline "3840x2560@10" 116.93 3840 3872 4312 4344 2560 2622 2627 2689 + Modeline "3840x2048@10" 91.45 3840 3872 4216 4248 2048 2097 2101 2151 + Modeline "2048x2048@10" 49.47 2048 2080 2264 2296 2048 2097 2101 2151 + Modeline "2560x1600@10" 47.12 2560 2592 2768 2800 1600 1639 1642 1681 + Modeline "1920x1200@10" 26.28 1920 1952 2048 2080 1200 1229 1231 1261 + Modeline "1920x1080@10" 23.53 1920 1952 2040 2072 1080 1106 1108 1135 + Modeline "1680x1050@10" 20.08 1680 1712 1784 1816 1050 1075 1077 1103 + Modeline "1600x900@20" 33.92 1600 1632 1760 1792 900 921 924 946 + Modeline "1440x900@20" 30.66 1440 1472 1584 1616 900 921 924 946 + Modeline "1360x768@20" 24.49 1360 1392 1480 1512 768 786 789 807 + #common resolutions for android devices (both orientations): + Modeline "800x1280@20" 25.89 800 832 928 960 1280 1310 1315 1345 + Modeline "1280x800@20" 24.15 1280 1312 1400 1432 800 819 822 841 + Modeline "720x1280@25" 30.22 720 752 864 896 1280 1309 1315 1345 + Modeline "1280x720@25" 27.41 1280 1312 1416 1448 720 737 740 757 + Modeline "768x1024@25" 24.93 768 800 888 920 1024 1047 1052 1076 + Modeline "1024x768@25" 23.77 1024 1056 1144 1176 768 785 789 807 + Modeline "600x1024@25" 19.90 600 632 704 736 1024 1047 1052 1076 + Modeline "1024x600@25" 18.26 1024 1056 1120 1152 600 614 617 631 + Modeline "536x960@25" 16.74 536 568 624 656 960 982 986 1009 + Modeline "960x536@25" 15.23 960 992 1048 1080 536 548 551 563 + Modeline "600x800@25" 15.17 600 632 688 720 800 818 822 841 + Modeline "800x600@25" 14.50 800 832 880 912 600 614 617 631 + Modeline "480x854@25" 13.34 480 512 560 592 854 873 877 897 + Modeline "848x480@25" 12.09 848 880 920 952 480 491 493 505 + Modeline "480x800@25" 12.43 480 512 552 584 800 818 822 841 + Modeline "800x480@25" 11.46 800 832 872 904 480 491 493 505 + Modeline "320x480@50" 10.73 320 352 392 424 480 490 494 505 + Modeline "480x320@50" 9.79 480 512 544 576 320 327 330 337 + Modeline "240x400@50" 6.96 240 272 296 328 400 408 412 421 + Modeline "400x240@50" 6.17 400 432 448 480 240 245 247 253 + Modeline "240x320@50" 5.47 240 272 288 320 320 327 330 337 + Modeline "320x240@50" 5.10 320 352 368 400 240 245 247 253 + #resolutions for android devices (both orientations) + #minus the status bar + #38px status bar (and width rounded up) + Modeline "800x1242@20" 25.03 800 832 920 952 1242 1271 1275 1305 + Modeline "1280x762@20" 22.93 1280 1312 1392 1424 762 780 783 801 + Modeline "720x1242@25" 29.20 720 752 856 888 1242 1271 1276 1305 + Modeline "1280x682@25" 25.85 1280 1312 1408 1440 682 698 701 717 + Modeline "768x986@25" 23.90 768 800 888 920 986 1009 1013 1036 + Modeline "1024x730@25" 22.50 1024 1056 1136 1168 730 747 750 767 + Modeline "600x986@25" 19.07 600 632 704 736 986 1009 1013 1036 + Modeline "1024x562@25" 17.03 1024 1056 1120 1152 562 575 578 591 + Modeline "536x922@25" 16.01 536 568 624 656 922 943 947 969 + Modeline "960x498@25" 14.09 960 992 1040 1072 498 509 511 523 + Modeline "600x762@25" 14.39 600 632 680 712 762 779 783 801 + Modeline "800x562@25" 13.52 800 832 880 912 562 575 578 591 + Modeline "480x810@25" 12.59 480 512 552 584 810 828 832 851 + Modeline "848x442@25" 11.09 848 880 920 952 442 452 454 465 + Modeline "480x762@25" 11.79 480 512 552 584 762 779 783 801 + Modeline "800x442@25" 10.51 800 832 864 896 442 452 454 465 + #32px status bar (no need for rounding): + Modeline "320x448@50" 9.93 320 352 384 416 448 457 461 471 + Modeline "480x288@50" 8.75 480 512 544 576 288 294 297 303 + #24px status bar: + Modeline "240x376@50" 6.49 240 272 296 328 376 384 387 395 + Modeline "400x216@50" 5.50 400 432 448 480 216 220 222 227 + Modeline "240x296@50" 5.02 240 272 288 320 296 302 305 311 + Modeline "320x216@50" 4.55 320 352 368 400 216 220 222 227 +EndSection + +##Xdummy:## +Section "Screen" + Identifier "Screen0" + Device "Videocard0" + Monitor "Monitor0" + DefaultDepth 24 + SubSection "Display" + Viewport 0 0 + Depth 24 + Modes "32000x32000" "16384x8192" "8192x4096" "5120x3200" "3840x2880" "3840x2560" "3840x2048" "2048x2048" "2560x1600" "1920x1440" "1920x1200" "1920x1080" "1600x1200" "1680x1050" "1600x900" "1400x1050" "1440x900" "1280x1024" "1366x768" "1280x800" "1024x768" "1024x600" "800x600" "320x200" + #Virtual 32000 32000 + #Virtual 16384 8192 + Virtual 8192 4096 + EndSubSection +EndSection + +Section "ServerLayout" + Identifier "dummy_layout" + Screen "screen0" + InputDevice "NoMouse" + InputDevice "NoKeyboard" +EndSection ''' tmp, xorg_conf = tempfile.mkstemp(prefix='aa-sandbox-xorg.conf-') @@ -424,11 +547,8 @@ EndSection args = ['/usr/bin/xpra', 'start', self.display] + x_args debug(" ".join(args)) - if apparmor.common.DEBUGGING == True: - sys.stderr.flush() - os.execv(args[0], args) - else: - cmd(args) + sys.stderr.flush() + os.execv(args[0], args) sys.exit(0) self.pids.append(listener_x) @@ -458,21 +578,14 @@ EndSection '--no-clipboard', '--no-pulseaudio'] debug(" ".join(args)) - if apparmor.common.DEBUGGING == True: - sys.stderr.flush() - os.execv(args[0], args) - else: - cmd(args) + sys.stderr.flush() + os.execv(args[0], args) sys.exit(0) self.pids.append(listener_attach) - msg("TODO: --with-geometry not honored in xpra") msg("TODO: filter '~/.xpra/run-xpra'") - def cleanup(self): - cmd(['xpra', 'stop', self.display]) - SandboxXserver.cleanup(self) def run_xsandbox(command, opt): '''Run X application in a sandbox''' @@ -480,11 +593,11 @@ def run_xsandbox(command, opt): # first, start X if opt.xserver.lower() == "xephyr": - x = SandboxXephyr(opt.geometry, command[0]) + x = SandboxXephyr(command[0], opt.geometry, xauth=opt.xauthority) elif opt.xserver.lower() == "xpra3d": - x = SandboxXpra(opt.geometry, command[0], driver="xdummy") + x = SandboxXpra(command[0], geometry=None, driver="xdummy", xauth=opt.xauthority) else: - x = SandboxXpra(opt.geometry, command[0]) + x = SandboxXpra(command[0], geometry=None, xauth=opt.xauthority) x.verify_host_setup() @@ -502,7 +615,6 @@ def run_xsandbox(command, opt): # aa-exec try: rc, report = aa_exec(command, opt, x.new_environ) - #x.start2() except Exception as e: x.cleanup() raise