1*105f6285SAndroid Build Coastguard Worker# Copyright 2020 Google LLC 2*105f6285SAndroid Build Coastguard Worker# 3*105f6285SAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License"); 4*105f6285SAndroid Build Coastguard Worker# you may not use this file except in compliance with the License. 5*105f6285SAndroid Build Coastguard Worker# You may obtain a copy of the License at 6*105f6285SAndroid Build Coastguard Worker# 7*105f6285SAndroid Build Coastguard Worker# https://www.apache.org/licenses/LICENSE-2.0 8*105f6285SAndroid Build Coastguard Worker# 9*105f6285SAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software 10*105f6285SAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS, 11*105f6285SAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12*105f6285SAndroid Build Coastguard Worker# See the License for the specific language governing permissions and 13*105f6285SAndroid Build Coastguard Worker# limitations under the License. 14*105f6285SAndroid Build Coastguard Worker 15*105f6285SAndroid Build Coastguard Worker"""Runs a command inside an NsJail sandbox for building Android. 16*105f6285SAndroid Build Coastguard Worker 17*105f6285SAndroid Build Coastguard WorkerNsJail creates a user namespace sandbox where 18*105f6285SAndroid Build Coastguard WorkerAndroid can be built in an isolated process. 19*105f6285SAndroid Build Coastguard WorkerIf no command is provided then it will open 20*105f6285SAndroid Build Coastguard Workeran interactive bash shell. 21*105f6285SAndroid Build Coastguard Worker""" 22*105f6285SAndroid Build Coastguard Worker 23*105f6285SAndroid Build Coastguard Workerimport argparse 24*105f6285SAndroid Build Coastguard Workerimport collections 25*105f6285SAndroid Build Coastguard Workerimport os 26*105f6285SAndroid Build Coastguard Workerimport re 27*105f6285SAndroid Build Coastguard Workerimport subprocess 28*105f6285SAndroid Build Coastguard Workerfrom . import config 29*105f6285SAndroid Build Coastguard Workerfrom .overlay import BindMount 30*105f6285SAndroid Build Coastguard Workerfrom .overlay import BindOverlay 31*105f6285SAndroid Build Coastguard Worker 32*105f6285SAndroid Build Coastguard Worker_DEFAULT_META_ANDROID_DIR = 'LINUX/android' 33*105f6285SAndroid Build Coastguard Worker_DEFAULT_COMMAND = '/bin/bash' 34*105f6285SAndroid Build Coastguard Worker 35*105f6285SAndroid Build Coastguard Worker_SOURCE_MOUNT_POINT = '/src' 36*105f6285SAndroid Build Coastguard Worker_OUT_MOUNT_POINT = '/src/out' 37*105f6285SAndroid Build Coastguard Worker_DIST_MOUNT_POINT = '/dist' 38*105f6285SAndroid Build Coastguard Worker_META_MOUNT_POINT = '/meta' 39*105f6285SAndroid Build Coastguard Worker 40*105f6285SAndroid Build Coastguard Worker_CHROOT_MOUNT_POINTS = [ 41*105f6285SAndroid Build Coastguard Worker 'bin', 'sbin', 42*105f6285SAndroid Build Coastguard Worker 'etc/alternatives', 'etc/default', 'etc/perl', 43*105f6285SAndroid Build Coastguard Worker 'etc/ssl', 'etc/xml', 44*105f6285SAndroid Build Coastguard Worker 'lib', 'lib32', 'lib64', 'libx32', 45*105f6285SAndroid Build Coastguard Worker 'usr', 46*105f6285SAndroid Build Coastguard Worker] 47*105f6285SAndroid Build Coastguard Worker 48*105f6285SAndroid Build Coastguard Worker 49*105f6285SAndroid Build Coastguard Workerdef run(command, 50*105f6285SAndroid Build Coastguard Worker build_target, 51*105f6285SAndroid Build Coastguard Worker nsjail_bin, 52*105f6285SAndroid Build Coastguard Worker chroot, 53*105f6285SAndroid Build Coastguard Worker overlay_config=None, 54*105f6285SAndroid Build Coastguard Worker source_dir=os.getcwd(), 55*105f6285SAndroid Build Coastguard Worker dist_dir=None, 56*105f6285SAndroid Build Coastguard Worker build_id=None, 57*105f6285SAndroid Build Coastguard Worker out_dir = None, 58*105f6285SAndroid Build Coastguard Worker meta_root_dir = None, 59*105f6285SAndroid Build Coastguard Worker meta_android_dir = _DEFAULT_META_ANDROID_DIR, 60*105f6285SAndroid Build Coastguard Worker mount_local_device = False, 61*105f6285SAndroid Build Coastguard Worker max_cpus=None, 62*105f6285SAndroid Build Coastguard Worker extra_bind_mounts=[], 63*105f6285SAndroid Build Coastguard Worker readonly_bind_mounts=[], 64*105f6285SAndroid Build Coastguard Worker extra_nsjail_args=[], 65*105f6285SAndroid Build Coastguard Worker dry_run=False, 66*105f6285SAndroid Build Coastguard Worker quiet=False, 67*105f6285SAndroid Build Coastguard Worker env=[], 68*105f6285SAndroid Build Coastguard Worker nsjail_wrapper=[], 69*105f6285SAndroid Build Coastguard Worker stdout=None, 70*105f6285SAndroid Build Coastguard Worker stderr=None, 71*105f6285SAndroid Build Coastguard Worker allow_network=False): 72*105f6285SAndroid Build Coastguard Worker """Run inside an NsJail sandbox. 73*105f6285SAndroid Build Coastguard Worker 74*105f6285SAndroid Build Coastguard Worker Args: 75*105f6285SAndroid Build Coastguard Worker command: A list of strings with the command to run. 76*105f6285SAndroid Build Coastguard Worker build_target: A string with the name of the build target to be prepared 77*105f6285SAndroid Build Coastguard Worker inside the container. 78*105f6285SAndroid Build Coastguard Worker nsjail_bin: A string with the path to the nsjail binary. 79*105f6285SAndroid Build Coastguard Worker chroot: A string with the path to the chroot. 80*105f6285SAndroid Build Coastguard Worker overlay_config: A string path to an overlay configuration file. 81*105f6285SAndroid Build Coastguard Worker source_dir: A string with the path to the Android platform source. 82*105f6285SAndroid Build Coastguard Worker dist_dir: A string with the path to the dist directory. 83*105f6285SAndroid Build Coastguard Worker build_id: A string with the build identifier. 84*105f6285SAndroid Build Coastguard Worker out_dir: An optional path to the Android build out folder. 85*105f6285SAndroid Build Coastguard Worker meta_root_dir: An optional path to a folder containing the META build. 86*105f6285SAndroid Build Coastguard Worker meta_android_dir: An optional path to the location where the META build expects 87*105f6285SAndroid Build Coastguard Worker the Android build. This path must be relative to meta_root_dir. 88*105f6285SAndroid Build Coastguard Worker mount_local_device: Whether to mount /dev/usb (and related) trees enabling 89*105f6285SAndroid Build Coastguard Worker adb to run inside the jail 90*105f6285SAndroid Build Coastguard Worker max_cpus: An integer with maximum number of CPUs. 91*105f6285SAndroid Build Coastguard Worker extra_bind_mounts: An array of extra mounts in the 'source' or 'source:dest' syntax. 92*105f6285SAndroid Build Coastguard Worker readonly_bind_mounts: An array of read only mounts in the 'source' or 'source:dest' syntax. 93*105f6285SAndroid Build Coastguard Worker extra_nsjail_args: A list of strings that contain extra arguments to nsjail. 94*105f6285SAndroid Build Coastguard Worker dry_run: If true, the command will be returned but not executed 95*105f6285SAndroid Build Coastguard Worker quiet: If true, the function will not display the command and 96*105f6285SAndroid Build Coastguard Worker will pass -quiet argument to nsjail 97*105f6285SAndroid Build Coastguard Worker env: An array of environment variables to define in the jail in the `var=val` syntax. 98*105f6285SAndroid Build Coastguard Worker nsjail_wrapper: A list of strings used to wrap the nsjail command. 99*105f6285SAndroid Build Coastguard Worker stdout: the standard output for all printed messages. Valid values are None, a file 100*105f6285SAndroid Build Coastguard Worker descriptor or file object. A None value means sys.stdout is used. 101*105f6285SAndroid Build Coastguard Worker stderr: the standard error for all printed messages. Valid values are None, a file 102*105f6285SAndroid Build Coastguard Worker descriptor or file object, and subprocess.STDOUT (which indicates that all stderr 103*105f6285SAndroid Build Coastguard Worker should be redirected to stdout). A None value means sys.stderr is used. 104*105f6285SAndroid Build Coastguard Worker allow_network: allow access to host network 105*105f6285SAndroid Build Coastguard Worker 106*105f6285SAndroid Build Coastguard Worker Returns: 107*105f6285SAndroid Build Coastguard Worker A list of strings with the command executed. 108*105f6285SAndroid Build Coastguard Worker """ 109*105f6285SAndroid Build Coastguard Worker 110*105f6285SAndroid Build Coastguard Worker 111*105f6285SAndroid Build Coastguard Worker nsjail_command = get_command( 112*105f6285SAndroid Build Coastguard Worker command=command, 113*105f6285SAndroid Build Coastguard Worker build_target=build_target, 114*105f6285SAndroid Build Coastguard Worker nsjail_bin=nsjail_bin, 115*105f6285SAndroid Build Coastguard Worker chroot=chroot, 116*105f6285SAndroid Build Coastguard Worker cfg=config.factory(overlay_config), 117*105f6285SAndroid Build Coastguard Worker source_dir=source_dir, 118*105f6285SAndroid Build Coastguard Worker dist_dir=dist_dir, 119*105f6285SAndroid Build Coastguard Worker build_id=build_id, 120*105f6285SAndroid Build Coastguard Worker out_dir=out_dir, 121*105f6285SAndroid Build Coastguard Worker meta_root_dir=meta_root_dir, 122*105f6285SAndroid Build Coastguard Worker meta_android_dir=meta_android_dir, 123*105f6285SAndroid Build Coastguard Worker mount_local_device=mount_local_device, 124*105f6285SAndroid Build Coastguard Worker max_cpus=max_cpus, 125*105f6285SAndroid Build Coastguard Worker extra_bind_mounts=extra_bind_mounts, 126*105f6285SAndroid Build Coastguard Worker readonly_bind_mounts=readonly_bind_mounts, 127*105f6285SAndroid Build Coastguard Worker extra_nsjail_args=extra_nsjail_args, 128*105f6285SAndroid Build Coastguard Worker quiet=quiet, 129*105f6285SAndroid Build Coastguard Worker env=env, 130*105f6285SAndroid Build Coastguard Worker nsjail_wrapper=nsjail_wrapper, 131*105f6285SAndroid Build Coastguard Worker allow_network=allow_network) 132*105f6285SAndroid Build Coastguard Worker 133*105f6285SAndroid Build Coastguard Worker run_command( 134*105f6285SAndroid Build Coastguard Worker nsjail_command=nsjail_command, 135*105f6285SAndroid Build Coastguard Worker mount_local_device=mount_local_device, 136*105f6285SAndroid Build Coastguard Worker dry_run=dry_run, 137*105f6285SAndroid Build Coastguard Worker quiet=quiet, 138*105f6285SAndroid Build Coastguard Worker stdout=stdout, 139*105f6285SAndroid Build Coastguard Worker stderr=stderr) 140*105f6285SAndroid Build Coastguard Worker 141*105f6285SAndroid Build Coastguard Worker return nsjail_command 142*105f6285SAndroid Build Coastguard Worker 143*105f6285SAndroid Build Coastguard Workerdef get_command(command, 144*105f6285SAndroid Build Coastguard Worker build_target, 145*105f6285SAndroid Build Coastguard Worker nsjail_bin, 146*105f6285SAndroid Build Coastguard Worker chroot, 147*105f6285SAndroid Build Coastguard Worker cfg=None, 148*105f6285SAndroid Build Coastguard Worker source_dir=os.getcwd(), 149*105f6285SAndroid Build Coastguard Worker dist_dir=None, 150*105f6285SAndroid Build Coastguard Worker build_id=None, 151*105f6285SAndroid Build Coastguard Worker out_dir = None, 152*105f6285SAndroid Build Coastguard Worker meta_root_dir = None, 153*105f6285SAndroid Build Coastguard Worker meta_android_dir = _DEFAULT_META_ANDROID_DIR, 154*105f6285SAndroid Build Coastguard Worker mount_local_device = False, 155*105f6285SAndroid Build Coastguard Worker max_cpus=None, 156*105f6285SAndroid Build Coastguard Worker extra_bind_mounts=[], 157*105f6285SAndroid Build Coastguard Worker readonly_bind_mounts=[], 158*105f6285SAndroid Build Coastguard Worker extra_nsjail_args=[], 159*105f6285SAndroid Build Coastguard Worker quiet=False, 160*105f6285SAndroid Build Coastguard Worker env=[], 161*105f6285SAndroid Build Coastguard Worker nsjail_wrapper=[], 162*105f6285SAndroid Build Coastguard Worker allow_network=False): 163*105f6285SAndroid Build Coastguard Worker """Get command to run nsjail sandbox. 164*105f6285SAndroid Build Coastguard Worker 165*105f6285SAndroid Build Coastguard Worker Args: 166*105f6285SAndroid Build Coastguard Worker command: A list of strings with the command to run. 167*105f6285SAndroid Build Coastguard Worker build_target: A string with the name of the build target to be prepared 168*105f6285SAndroid Build Coastguard Worker inside the container. 169*105f6285SAndroid Build Coastguard Worker nsjail_bin: A string with the path to the nsjail binary. 170*105f6285SAndroid Build Coastguard Worker chroot: A string with the path to the chroot. 171*105f6285SAndroid Build Coastguard Worker cfg: A config.Config instance or None. 172*105f6285SAndroid Build Coastguard Worker source_dir: A string with the path to the Android platform source. 173*105f6285SAndroid Build Coastguard Worker dist_dir: A string with the path to the dist directory. 174*105f6285SAndroid Build Coastguard Worker build_id: A string with the build identifier. 175*105f6285SAndroid Build Coastguard Worker out_dir: An optional path to the Android build out folder. 176*105f6285SAndroid Build Coastguard Worker meta_root_dir: An optional path to a folder containing the META build. 177*105f6285SAndroid Build Coastguard Worker meta_android_dir: An optional path to the location where the META build expects 178*105f6285SAndroid Build Coastguard Worker the Android build. This path must be relative to meta_root_dir. 179*105f6285SAndroid Build Coastguard Worker max_cpus: An integer with maximum number of CPUs. 180*105f6285SAndroid Build Coastguard Worker extra_bind_mounts: An array of extra mounts in the 'source' or 'source:dest' syntax. 181*105f6285SAndroid Build Coastguard Worker readonly_bind_mounts: An array of read only mounts in the 'source' or 'source:dest' syntax. 182*105f6285SAndroid Build Coastguard Worker extra_nsjail_args: A list of strings that contain extra arguments to nsjail. 183*105f6285SAndroid Build Coastguard Worker quiet: If true, the function will not display the command and 184*105f6285SAndroid Build Coastguard Worker will pass -quiet argument to nsjail 185*105f6285SAndroid Build Coastguard Worker env: An array of environment variables to define in the jail in the `var=val` syntax. 186*105f6285SAndroid Build Coastguard Worker allow_network: allow access to host network 187*105f6285SAndroid Build Coastguard Worker 188*105f6285SAndroid Build Coastguard Worker Returns: 189*105f6285SAndroid Build Coastguard Worker A list of strings with the command to execute. 190*105f6285SAndroid Build Coastguard Worker """ 191*105f6285SAndroid Build Coastguard Worker script_dir = os.path.dirname(os.path.abspath(__file__)) 192*105f6285SAndroid Build Coastguard Worker config_file = os.path.join(script_dir, 'nsjail.cfg') 193*105f6285SAndroid Build Coastguard Worker 194*105f6285SAndroid Build Coastguard Worker # Run expects absolute paths 195*105f6285SAndroid Build Coastguard Worker if out_dir: 196*105f6285SAndroid Build Coastguard Worker out_dir = os.path.abspath(out_dir) 197*105f6285SAndroid Build Coastguard Worker if dist_dir: 198*105f6285SAndroid Build Coastguard Worker dist_dir = os.path.abspath(dist_dir) 199*105f6285SAndroid Build Coastguard Worker if meta_root_dir: 200*105f6285SAndroid Build Coastguard Worker meta_root_dir = os.path.abspath(meta_root_dir) 201*105f6285SAndroid Build Coastguard Worker if source_dir: 202*105f6285SAndroid Build Coastguard Worker source_dir = os.path.abspath(source_dir) 203*105f6285SAndroid Build Coastguard Worker 204*105f6285SAndroid Build Coastguard Worker if nsjail_bin: 205*105f6285SAndroid Build Coastguard Worker nsjail_bin = os.path.join(source_dir, nsjail_bin) 206*105f6285SAndroid Build Coastguard Worker 207*105f6285SAndroid Build Coastguard Worker if chroot: 208*105f6285SAndroid Build Coastguard Worker chroot = os.path.join(source_dir, chroot) 209*105f6285SAndroid Build Coastguard Worker 210*105f6285SAndroid Build Coastguard Worker if meta_root_dir: 211*105f6285SAndroid Build Coastguard Worker if not meta_android_dir or os.path.isabs(meta_android_dir): 212*105f6285SAndroid Build Coastguard Worker raise ValueError('error: the provided meta_android_dir is not a path' 213*105f6285SAndroid Build Coastguard Worker 'relative to meta_root_dir.') 214*105f6285SAndroid Build Coastguard Worker 215*105f6285SAndroid Build Coastguard Worker nsjail_command = nsjail_wrapper + [nsjail_bin, 216*105f6285SAndroid Build Coastguard Worker '--env', 'USER=nobody', 217*105f6285SAndroid Build Coastguard Worker '--config', config_file] 218*105f6285SAndroid Build Coastguard Worker 219*105f6285SAndroid Build Coastguard Worker # By mounting the points individually that we need we reduce exposure and 220*105f6285SAndroid Build Coastguard Worker # keep the chroot clean from artifacts 221*105f6285SAndroid Build Coastguard Worker if chroot: 222*105f6285SAndroid Build Coastguard Worker for mpoints in _CHROOT_MOUNT_POINTS: 223*105f6285SAndroid Build Coastguard Worker source = os.path.join(chroot, mpoints) 224*105f6285SAndroid Build Coastguard Worker dest = os.path.join('/', mpoints) 225*105f6285SAndroid Build Coastguard Worker if os.path.exists(source): 226*105f6285SAndroid Build Coastguard Worker nsjail_command.extend([ 227*105f6285SAndroid Build Coastguard Worker '--bindmount_ro', '%s:%s' % (source, dest) 228*105f6285SAndroid Build Coastguard Worker ]) 229*105f6285SAndroid Build Coastguard Worker 230*105f6285SAndroid Build Coastguard Worker if build_id: 231*105f6285SAndroid Build Coastguard Worker nsjail_command.extend(['--env', 'BUILD_NUMBER=%s' % build_id]) 232*105f6285SAndroid Build Coastguard Worker if max_cpus: 233*105f6285SAndroid Build Coastguard Worker nsjail_command.append('--max_cpus=%i' % max_cpus) 234*105f6285SAndroid Build Coastguard Worker if quiet: 235*105f6285SAndroid Build Coastguard Worker nsjail_command.append('--quiet') 236*105f6285SAndroid Build Coastguard Worker 237*105f6285SAndroid Build Coastguard Worker whiteout_list = set() 238*105f6285SAndroid Build Coastguard Worker if out_dir and ( 239*105f6285SAndroid Build Coastguard Worker os.path.dirname(out_dir) == source_dir) and ( 240*105f6285SAndroid Build Coastguard Worker os.path.basename(out_dir) != 'out'): 241*105f6285SAndroid Build Coastguard Worker whiteout_list.add(os.path.abspath(out_dir)) 242*105f6285SAndroid Build Coastguard Worker if not os.path.exists(out_dir): 243*105f6285SAndroid Build Coastguard Worker os.makedirs(out_dir) 244*105f6285SAndroid Build Coastguard Worker 245*105f6285SAndroid Build Coastguard Worker # Apply the overlay for the selected Android target to the source directory 246*105f6285SAndroid Build Coastguard Worker # from the supplied config.Config instance (which may be None). 247*105f6285SAndroid Build Coastguard Worker if cfg is not None: 248*105f6285SAndroid Build Coastguard Worker overlay = BindOverlay(build_target, 249*105f6285SAndroid Build Coastguard Worker source_dir, 250*105f6285SAndroid Build Coastguard Worker cfg, 251*105f6285SAndroid Build Coastguard Worker whiteout_list, 252*105f6285SAndroid Build Coastguard Worker _SOURCE_MOUNT_POINT, 253*105f6285SAndroid Build Coastguard Worker quiet=quiet) 254*105f6285SAndroid Build Coastguard Worker bind_mounts = overlay.GetBindMounts() 255*105f6285SAndroid Build Coastguard Worker else: 256*105f6285SAndroid Build Coastguard Worker bind_mounts = collections.OrderedDict() 257*105f6285SAndroid Build Coastguard Worker bind_mounts[_SOURCE_MOUNT_POINT] = BindMount(source_dir, False, False) 258*105f6285SAndroid Build Coastguard Worker 259*105f6285SAndroid Build Coastguard Worker if out_dir: 260*105f6285SAndroid Build Coastguard Worker bind_mounts[_OUT_MOUNT_POINT] = BindMount(out_dir, False, False) 261*105f6285SAndroid Build Coastguard Worker 262*105f6285SAndroid Build Coastguard Worker if dist_dir: 263*105f6285SAndroid Build Coastguard Worker bind_mounts[_DIST_MOUNT_POINT] = BindMount(dist_dir, False, False) 264*105f6285SAndroid Build Coastguard Worker nsjail_command.extend([ 265*105f6285SAndroid Build Coastguard Worker '--env', 'DIST_DIR=%s'%_DIST_MOUNT_POINT 266*105f6285SAndroid Build Coastguard Worker ]) 267*105f6285SAndroid Build Coastguard Worker 268*105f6285SAndroid Build Coastguard Worker if meta_root_dir: 269*105f6285SAndroid Build Coastguard Worker bind_mounts[_META_MOUNT_POINT] = BindMount(meta_root_dir, False, False) 270*105f6285SAndroid Build Coastguard Worker bind_mounts[os.path.join(_META_MOUNT_POINT, meta_android_dir)] = BindMount(source_dir, False, False) 271*105f6285SAndroid Build Coastguard Worker if out_dir: 272*105f6285SAndroid Build Coastguard Worker bind_mounts[os.path.join(_META_MOUNT_POINT, meta_android_dir, 'out')] = BindMount(out_dir, False, False) 273*105f6285SAndroid Build Coastguard Worker 274*105f6285SAndroid Build Coastguard Worker for bind_destination, bind_mount in bind_mounts.items(): 275*105f6285SAndroid Build Coastguard Worker if bind_mount.readonly: 276*105f6285SAndroid Build Coastguard Worker nsjail_command.extend([ 277*105f6285SAndroid Build Coastguard Worker '--bindmount_ro', bind_mount.source_dir + ':' + bind_destination 278*105f6285SAndroid Build Coastguard Worker ]) 279*105f6285SAndroid Build Coastguard Worker else: 280*105f6285SAndroid Build Coastguard Worker nsjail_command.extend([ 281*105f6285SAndroid Build Coastguard Worker '--bindmount', bind_mount.source_dir + ':' + bind_destination 282*105f6285SAndroid Build Coastguard Worker ]) 283*105f6285SAndroid Build Coastguard Worker 284*105f6285SAndroid Build Coastguard Worker if mount_local_device: 285*105f6285SAndroid Build Coastguard Worker # Mount /dev/bus/usb and several /sys/... paths, which adb will examine 286*105f6285SAndroid Build Coastguard Worker # while attempting to find the attached android device. These paths expose 287*105f6285SAndroid Build Coastguard Worker # a lot of host operating system device space, so it's recommended to use 288*105f6285SAndroid Build Coastguard Worker # the mount_local_device option only when you need to use adb (e.g., for 289*105f6285SAndroid Build Coastguard Worker # atest or some other purpose). 290*105f6285SAndroid Build Coastguard Worker nsjail_command.extend(['--bindmount', '/dev/bus/usb']) 291*105f6285SAndroid Build Coastguard Worker nsjail_command.extend(['--bindmount', '/sys/bus/usb/devices']) 292*105f6285SAndroid Build Coastguard Worker nsjail_command.extend(['--bindmount', '/sys/dev']) 293*105f6285SAndroid Build Coastguard Worker nsjail_command.extend(['--bindmount', '/sys/devices']) 294*105f6285SAndroid Build Coastguard Worker 295*105f6285SAndroid Build Coastguard Worker for mount in extra_bind_mounts: 296*105f6285SAndroid Build Coastguard Worker nsjail_command.extend(['--bindmount', mount]) 297*105f6285SAndroid Build Coastguard Worker for mount in readonly_bind_mounts: 298*105f6285SAndroid Build Coastguard Worker nsjail_command.extend(['--bindmount_ro', mount]) 299*105f6285SAndroid Build Coastguard Worker 300*105f6285SAndroid Build Coastguard Worker for var in env: 301*105f6285SAndroid Build Coastguard Worker nsjail_command.extend(['--env', var]) 302*105f6285SAndroid Build Coastguard Worker 303*105f6285SAndroid Build Coastguard Worker if allow_network: 304*105f6285SAndroid Build Coastguard Worker nsjail_command.extend(['--disable_clone_newnet', 305*105f6285SAndroid Build Coastguard Worker '--bindmount_ro', 306*105f6285SAndroid Build Coastguard Worker '/etc/resolv.conf']) 307*105f6285SAndroid Build Coastguard Worker 308*105f6285SAndroid Build Coastguard Worker nsjail_command.extend(extra_nsjail_args) 309*105f6285SAndroid Build Coastguard Worker 310*105f6285SAndroid Build Coastguard Worker nsjail_command.append('--') 311*105f6285SAndroid Build Coastguard Worker nsjail_command.extend(command) 312*105f6285SAndroid Build Coastguard Worker 313*105f6285SAndroid Build Coastguard Worker return nsjail_command 314*105f6285SAndroid Build Coastguard Worker 315*105f6285SAndroid Build Coastguard Workerdef run_command(nsjail_command, 316*105f6285SAndroid Build Coastguard Worker mount_local_device=False, 317*105f6285SAndroid Build Coastguard Worker dry_run=False, 318*105f6285SAndroid Build Coastguard Worker quiet=False, 319*105f6285SAndroid Build Coastguard Worker stdout=None, 320*105f6285SAndroid Build Coastguard Worker stderr=None): 321*105f6285SAndroid Build Coastguard Worker """Run the provided nsjail command. 322*105f6285SAndroid Build Coastguard Worker 323*105f6285SAndroid Build Coastguard Worker Args: 324*105f6285SAndroid Build Coastguard Worker nsjail_command: A list of strings with the command to run. 325*105f6285SAndroid Build Coastguard Worker mount_local_device: Whether to mount /dev/usb (and related) trees enabling 326*105f6285SAndroid Build Coastguard Worker adb to run inside the jail 327*105f6285SAndroid Build Coastguard Worker dry_run: If true, the command will be returned but not executed 328*105f6285SAndroid Build Coastguard Worker quiet: If true, the function will not display the command and 329*105f6285SAndroid Build Coastguard Worker will pass -quiet argument to nsjail 330*105f6285SAndroid Build Coastguard Worker stdout: the standard output for all printed messages. Valid values are None, a file 331*105f6285SAndroid Build Coastguard Worker descriptor or file object. A None value means sys.stdout is used. 332*105f6285SAndroid Build Coastguard Worker stderr: the standard error for all printed messages. Valid values are None, a file 333*105f6285SAndroid Build Coastguard Worker descriptor or file object, and subprocess.STDOUT (which indicates that all stderr 334*105f6285SAndroid Build Coastguard Worker should be redirected to stdout). A None value means sys.stderr is used. 335*105f6285SAndroid Build Coastguard Worker """ 336*105f6285SAndroid Build Coastguard Worker 337*105f6285SAndroid Build Coastguard Worker if mount_local_device: 338*105f6285SAndroid Build Coastguard Worker # A device can only communicate with one adb server at a time, so the adb server is 339*105f6285SAndroid Build Coastguard Worker # killed on the host machine. 340*105f6285SAndroid Build Coastguard Worker for line in subprocess.check_output(['ps','-eo','cmd']).decode().split('\n'): 341*105f6285SAndroid Build Coastguard Worker if re.match(r'adb.*fork-server.*', line): 342*105f6285SAndroid Build Coastguard Worker print('An adb server is running on your host machine. This server must be ' 343*105f6285SAndroid Build Coastguard Worker 'killed to use the --mount_local_device flag.') 344*105f6285SAndroid Build Coastguard Worker print('Continue? [y/N]: ', end='') 345*105f6285SAndroid Build Coastguard Worker if input().lower() != 'y': 346*105f6285SAndroid Build Coastguard Worker exit() 347*105f6285SAndroid Build Coastguard Worker subprocess.check_call(['adb', 'kill-server']) 348*105f6285SAndroid Build Coastguard Worker 349*105f6285SAndroid Build Coastguard Worker if not quiet: 350*105f6285SAndroid Build Coastguard Worker print('NsJail command:', file=stdout) 351*105f6285SAndroid Build Coastguard Worker print(' '.join(nsjail_command), file=stdout) 352*105f6285SAndroid Build Coastguard Worker 353*105f6285SAndroid Build Coastguard Worker if not dry_run: 354*105f6285SAndroid Build Coastguard Worker try: 355*105f6285SAndroid Build Coastguard Worker subprocess.check_call(nsjail_command, stdout=stdout, stderr=stderr) 356*105f6285SAndroid Build Coastguard Worker except subprocess.CalledProcessError as error: 357*105f6285SAndroid Build Coastguard Worker if len(error.cmd) > 13: 358*105f6285SAndroid Build Coastguard Worker cmd = error.cmd[:6] + ['...elided...'] + error.cmd[-6:] 359*105f6285SAndroid Build Coastguard Worker else: 360*105f6285SAndroid Build Coastguard Worker cmd = error.cmd 361*105f6285SAndroid Build Coastguard Worker msg = 'nsjail command %s failed with return code %d' % (cmd, error.returncode) 362*105f6285SAndroid Build Coastguard Worker # Raise from None to avoid exception chaining. 363*105f6285SAndroid Build Coastguard Worker raise RuntimeError(msg) from None 364*105f6285SAndroid Build Coastguard Worker 365*105f6285SAndroid Build Coastguard Worker 366*105f6285SAndroid Build Coastguard Workerdef parse_args(): 367*105f6285SAndroid Build Coastguard Worker """Parse command line arguments. 368*105f6285SAndroid Build Coastguard Worker 369*105f6285SAndroid Build Coastguard Worker Returns: 370*105f6285SAndroid Build Coastguard Worker An argparse.Namespace object. 371*105f6285SAndroid Build Coastguard Worker """ 372*105f6285SAndroid Build Coastguard Worker 373*105f6285SAndroid Build Coastguard Worker # Use the top level module docstring for the help description 374*105f6285SAndroid Build Coastguard Worker parser = argparse.ArgumentParser( 375*105f6285SAndroid Build Coastguard Worker description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter) 376*105f6285SAndroid Build Coastguard Worker parser.add_argument( 377*105f6285SAndroid Build Coastguard Worker '--nsjail_bin', 378*105f6285SAndroid Build Coastguard Worker required=True, 379*105f6285SAndroid Build Coastguard Worker help='Path to NsJail binary.') 380*105f6285SAndroid Build Coastguard Worker parser.add_argument( 381*105f6285SAndroid Build Coastguard Worker '--chroot', 382*105f6285SAndroid Build Coastguard Worker help='Path to the chroot to be used for building the Android' 383*105f6285SAndroid Build Coastguard Worker 'platform. This will be mounted as the root filesystem in the' 384*105f6285SAndroid Build Coastguard Worker 'NsJail sandbox.') 385*105f6285SAndroid Build Coastguard Worker parser.add_argument( 386*105f6285SAndroid Build Coastguard Worker '--overlay_config', 387*105f6285SAndroid Build Coastguard Worker help='Path to the overlay configuration file.') 388*105f6285SAndroid Build Coastguard Worker parser.add_argument( 389*105f6285SAndroid Build Coastguard Worker '--source_dir', 390*105f6285SAndroid Build Coastguard Worker default=os.getcwd(), 391*105f6285SAndroid Build Coastguard Worker help='Path to Android platform source to be mounted as /src.') 392*105f6285SAndroid Build Coastguard Worker parser.add_argument( 393*105f6285SAndroid Build Coastguard Worker '--out_dir', 394*105f6285SAndroid Build Coastguard Worker help='Full path to the Android build out folder. If not provided, uses ' 395*105f6285SAndroid Build Coastguard Worker 'the standard \'out\' folder in the current path.') 396*105f6285SAndroid Build Coastguard Worker parser.add_argument( 397*105f6285SAndroid Build Coastguard Worker '--meta_root_dir', 398*105f6285SAndroid Build Coastguard Worker default='', 399*105f6285SAndroid Build Coastguard Worker help='Full path to META folder. Default to \'\'') 400*105f6285SAndroid Build Coastguard Worker parser.add_argument( 401*105f6285SAndroid Build Coastguard Worker '--meta_android_dir', 402*105f6285SAndroid Build Coastguard Worker default=_DEFAULT_META_ANDROID_DIR, 403*105f6285SAndroid Build Coastguard Worker help='Relative path to the location where the META build expects ' 404*105f6285SAndroid Build Coastguard Worker 'the Android build. This path must be relative to meta_root_dir. ' 405*105f6285SAndroid Build Coastguard Worker 'Defaults to \'%s\'' % _DEFAULT_META_ANDROID_DIR) 406*105f6285SAndroid Build Coastguard Worker parser.add_argument( 407*105f6285SAndroid Build Coastguard Worker '--command', 408*105f6285SAndroid Build Coastguard Worker default=_DEFAULT_COMMAND, 409*105f6285SAndroid Build Coastguard Worker help='Command to run after entering the NsJail.' 410*105f6285SAndroid Build Coastguard Worker 'If not set then an interactive Bash shell will be launched') 411*105f6285SAndroid Build Coastguard Worker parser.add_argument( 412*105f6285SAndroid Build Coastguard Worker '--build_target', 413*105f6285SAndroid Build Coastguard Worker required=True, 414*105f6285SAndroid Build Coastguard Worker help='Android target selected for building') 415*105f6285SAndroid Build Coastguard Worker parser.add_argument( 416*105f6285SAndroid Build Coastguard Worker '--dist_dir', 417*105f6285SAndroid Build Coastguard Worker help='Path to the Android dist directory. This is where' 418*105f6285SAndroid Build Coastguard Worker 'Android platform release artifacts will be written.' 419*105f6285SAndroid Build Coastguard Worker 'If unset then the Android platform default will be used.') 420*105f6285SAndroid Build Coastguard Worker parser.add_argument( 421*105f6285SAndroid Build Coastguard Worker '--build_id', 422*105f6285SAndroid Build Coastguard Worker help='Build identifier what will label the Android platform' 423*105f6285SAndroid Build Coastguard Worker 'release artifacts.') 424*105f6285SAndroid Build Coastguard Worker parser.add_argument( 425*105f6285SAndroid Build Coastguard Worker '--max_cpus', 426*105f6285SAndroid Build Coastguard Worker type=int, 427*105f6285SAndroid Build Coastguard Worker help='Limit of concurrent CPU cores that the NsJail sandbox' 428*105f6285SAndroid Build Coastguard Worker 'can use. Defaults to unlimited.') 429*105f6285SAndroid Build Coastguard Worker parser.add_argument( 430*105f6285SAndroid Build Coastguard Worker '--bindmount', 431*105f6285SAndroid Build Coastguard Worker type=str, 432*105f6285SAndroid Build Coastguard Worker default=[], 433*105f6285SAndroid Build Coastguard Worker action='append', 434*105f6285SAndroid Build Coastguard Worker help='List of mountpoints to be mounted. Can be specified multiple times. ' 435*105f6285SAndroid Build Coastguard Worker 'Syntax: \'source\' or \'source:dest\'') 436*105f6285SAndroid Build Coastguard Worker parser.add_argument( 437*105f6285SAndroid Build Coastguard Worker '--bindmount_ro', 438*105f6285SAndroid Build Coastguard Worker type=str, 439*105f6285SAndroid Build Coastguard Worker default=[], 440*105f6285SAndroid Build Coastguard Worker action='append', 441*105f6285SAndroid Build Coastguard Worker help='List of mountpoints to be mounted read-only. Can be specified multiple times. ' 442*105f6285SAndroid Build Coastguard Worker 'Syntax: \'source\' or \'source:dest\'') 443*105f6285SAndroid Build Coastguard Worker parser.add_argument( 444*105f6285SAndroid Build Coastguard Worker '--dry_run', 445*105f6285SAndroid Build Coastguard Worker action='store_true', 446*105f6285SAndroid Build Coastguard Worker help='Prints the command without executing') 447*105f6285SAndroid Build Coastguard Worker parser.add_argument( 448*105f6285SAndroid Build Coastguard Worker '--quiet', '-q', 449*105f6285SAndroid Build Coastguard Worker action='store_true', 450*105f6285SAndroid Build Coastguard Worker help='Suppress debugging output') 451*105f6285SAndroid Build Coastguard Worker parser.add_argument( 452*105f6285SAndroid Build Coastguard Worker '--mount_local_device', 453*105f6285SAndroid Build Coastguard Worker action='store_true', 454*105f6285SAndroid Build Coastguard Worker help='If provided, mount locally connected Android USB devices inside ' 455*105f6285SAndroid Build Coastguard Worker 'the container. WARNING: Using this flag will cause the adb server to be ' 456*105f6285SAndroid Build Coastguard Worker 'killed on the host machine. WARNING: Using this flag exposes parts of ' 457*105f6285SAndroid Build Coastguard Worker 'the host /sys/... file system. Use only when you need adb.') 458*105f6285SAndroid Build Coastguard Worker parser.add_argument( 459*105f6285SAndroid Build Coastguard Worker '--env', '-e', 460*105f6285SAndroid Build Coastguard Worker type=str, 461*105f6285SAndroid Build Coastguard Worker default=[], 462*105f6285SAndroid Build Coastguard Worker action='append', 463*105f6285SAndroid Build Coastguard Worker help='Specify an environment variable to the NSJail sandbox. Can be specified ' 464*105f6285SAndroid Build Coastguard Worker 'muliple times. Syntax: var_name=value') 465*105f6285SAndroid Build Coastguard Worker parser.add_argument( 466*105f6285SAndroid Build Coastguard Worker '--allow_network', action='store_true', 467*105f6285SAndroid Build Coastguard Worker help='If provided, allow access to the host network. WARNING: Using this ' 468*105f6285SAndroid Build Coastguard Worker 'flag exposes the network inside jail. Use only when needed.') 469*105f6285SAndroid Build Coastguard Worker return parser.parse_args() 470*105f6285SAndroid Build Coastguard Worker 471*105f6285SAndroid Build Coastguard Workerdef run_with_args(args): 472*105f6285SAndroid Build Coastguard Worker """Run inside an NsJail sandbox. 473*105f6285SAndroid Build Coastguard Worker 474*105f6285SAndroid Build Coastguard Worker Use the arguments from an argspace namespace. 475*105f6285SAndroid Build Coastguard Worker 476*105f6285SAndroid Build Coastguard Worker Args: 477*105f6285SAndroid Build Coastguard Worker An argparse.Namespace object. 478*105f6285SAndroid Build Coastguard Worker 479*105f6285SAndroid Build Coastguard Worker Returns: 480*105f6285SAndroid Build Coastguard Worker A list of strings with the commands executed. 481*105f6285SAndroid Build Coastguard Worker """ 482*105f6285SAndroid Build Coastguard Worker run(chroot=args.chroot, 483*105f6285SAndroid Build Coastguard Worker nsjail_bin=args.nsjail_bin, 484*105f6285SAndroid Build Coastguard Worker overlay_config=args.overlay_config, 485*105f6285SAndroid Build Coastguard Worker source_dir=args.source_dir, 486*105f6285SAndroid Build Coastguard Worker command=args.command.split(), 487*105f6285SAndroid Build Coastguard Worker build_target=args.build_target, 488*105f6285SAndroid Build Coastguard Worker dist_dir=args.dist_dir, 489*105f6285SAndroid Build Coastguard Worker build_id=args.build_id, 490*105f6285SAndroid Build Coastguard Worker out_dir=args.out_dir, 491*105f6285SAndroid Build Coastguard Worker meta_root_dir=args.meta_root_dir, 492*105f6285SAndroid Build Coastguard Worker meta_android_dir=args.meta_android_dir, 493*105f6285SAndroid Build Coastguard Worker mount_local_device=args.mount_local_device, 494*105f6285SAndroid Build Coastguard Worker max_cpus=args.max_cpus, 495*105f6285SAndroid Build Coastguard Worker extra_bind_mounts=args.bindmount, 496*105f6285SAndroid Build Coastguard Worker readonly_bind_mounts=args.bindmount_ro, 497*105f6285SAndroid Build Coastguard Worker dry_run=args.dry_run, 498*105f6285SAndroid Build Coastguard Worker quiet=args.quiet, 499*105f6285SAndroid Build Coastguard Worker env=args.env, 500*105f6285SAndroid Build Coastguard Worker allow_network=args.allow_network) 501*105f6285SAndroid Build Coastguard Worker 502*105f6285SAndroid Build Coastguard Workerdef main(): 503*105f6285SAndroid Build Coastguard Worker run_with_args(parse_args()) 504*105f6285SAndroid Build Coastguard Worker 505*105f6285SAndroid Build Coastguard Workerif __name__ == '__main__': 506*105f6285SAndroid Build Coastguard Worker main() 507