def main(): "Main executable entry point." # initial sanity check for correct invocation method rootcheck() # drop unprivileged to parse args, etc. # uidManager saves current real uid/gid which are unprivileged (callers) # due to suid helper, our current effective uid is 0 # also supports being run by sudo # # setuid wrapper has real uid = unpriv, effective uid = 0 # sudo sets real/effective = 0, and sets env vars # setuid wrapper clears environment, so there wont be any conflict between these two mockgid = grp.getgrnam('mock').gr_gid uidManager = setup_uid_manager(mockgid) # go unpriv only when root to make --help etc work for non-mock users if os.geteuid() == 0: uidManager.dropPrivsTemp() (options, args) = command_parse() if options.printrootpath or options.list_snapshots: options.verbose = 0 # config path -- can be overridden on cmdline config_path = MOCKCONFDIR if options.configdir: config_path = options.configdir config_opts = util.load_config(config_path, options.chroot, uidManager, __VERSION__, PKGPYTHONDIR) config_opts['config_path'] = config_path # cmdline options override config options util.set_config_opts_per_cmdline(config_opts, options, args) # allow a different mock group to be specified if config_opts['chrootgid'] != mockgid: uidManager.restorePrivs() os.setgroups((mockgid, config_opts['chrootgid'])) uidManager.dropPrivsTemp() # verify that our unprivileged uid is in the mock group groupcheck(uidManager.unprivGid, config_opts['chrootgid']) # configure logging setup_logging(config_path, config_opts, options) # verify that we're not trying to build an arch that we can't check_arch_combination(config_opts['rpmbuild_arch'], config_opts) # security cleanup (don't need/want this in the chroot) if 'SSH_AUTH_SOCK' in os.environ: del os.environ['SSH_AUTH_SOCK'] # elevate privs uidManager.become_user_without_push(0, 0) # do whatever we're here to do py_version = '{0}.{1}.{2}'.format(*sys.version_info[:3]) log.info("mock.py version %s starting (python version = %s)...", __VERSION__, py_version) state = State() plugins = Plugins(config_opts, state) # outer buildroot to bootstrap the installation - based on main config with some differences bootstrap_buildroot = None if config_opts['use_bootstrap_container']: # first take a copy of the config so we can make some modifications bootstrap_buildroot_config = config_opts.copy() # copy plugins configuration so we get a separate deep copy bootstrap_buildroot_config['plugin_conf'] = config_opts[ 'plugin_conf'].copy() # pylint: disable=no-member # add '-bootstrap' to the end of the root name bootstrap_buildroot_config[ 'root'] = bootstrap_buildroot_config['root'] + '-bootstrap' # share a yum cache to save downloading everything twice bootstrap_buildroot_config['plugin_conf']['yum_cache_opts']['dir'] = \ "%(cache_topdir)s/" + config_opts['root'] + "/%(package_manager)s_cache/" # we don't want to affect the bootstrap.config['nspawn_args'] array, deep copy bootstrap_buildroot_config['nspawn_args'] = config_opts.get( 'nspawn_args', []).copy() # allow bootstrap buildroot to access the network for getting packages bootstrap_buildroot_config['rpmbuild_networking'] = True bootstrap_buildroot_config['use_host_resolv'] = True util.setup_host_resolv(bootstrap_buildroot_config) # use system_*_command for bootstrapping bootstrap_buildroot_config['yum_command'] = bootstrap_buildroot_config[ 'system_yum_command'] bootstrap_buildroot_config['dnf_command'] = bootstrap_buildroot_config[ 'system_dnf_command'] bootstrap_buildroot_state = State(bootstrap=True) bootstrap_plugins = Plugins(bootstrap_buildroot_config, bootstrap_buildroot_state) bootstrap_buildroot = Buildroot(bootstrap_buildroot_config, uidManager, bootstrap_buildroot_state, bootstrap_plugins, is_bootstrap=True) # this bit of config is needed after we have created the bootstrap buildroot since we need to # query pkg_manager to know which manager is in use bootstrap_buildroot.config[ 'chroot_setup_cmd'] = bootstrap_buildroot.pkg_manager.install_command # override configs for bootstrap_* for k in bootstrap_buildroot.config.copy(): if "bootstrap_" + k in bootstrap_buildroot.config: bootstrap_buildroot.config[k] = bootstrap_buildroot_config[ "bootstrap_" + k] del bootstrap_buildroot.config["bootstrap_" + k] # this changes config_opts['nspawn_args'], so do it after initializing # bootstrap chroot to not inherit the changes there util.setup_host_resolv(config_opts) buildroot = Buildroot(config_opts, uidManager, state, plugins, bootstrap_buildroot) commands = Commands(config_opts, uidManager, plugins, state, buildroot, bootstrap_buildroot) if config_opts['use_bootstrap_container']: bootstrap_buildroot.config[ 'chroot_setup_cmd'] = buildroot.pkg_manager.install_command state.start("run") if options.printrootpath: print(buildroot.make_chroot_path('')) sys.exit(0) if options.list_snapshots: plugins.call_hooks('list_snapshots', required=True) if bootstrap_buildroot is not None: bootstrap_buildroot.plugins.call_hooks('list_snapshots', required=True) sys.exit(0) # dump configuration to log log.debug("mock final configuration:") for k, v in list(config_opts.items()): log.debug(" %s: %s", k, v) os.umask(0o02) os.environ["HOME"] = buildroot.homedir # New namespace starting from here unshare_namespace(config_opts) if config_opts['hostname']: util.sethostname(config_opts['hostname']) # set personality (ie. setarch) util.condPersonality(config_opts['target_arch']) result = 0 try: result = run_command(options, args, config_opts, commands, buildroot, state) except mockbuild.exception.Error: result = 1 finally: buildroot.uid_manager.becomeUser(0, 0) buildroot.finalize() if bootstrap_buildroot is not None: bootstrap_buildroot.finalize() buildroot.uid_manager.restorePrivs() return result
def main(): "Main executable entry point." # initial sanity check for correct invocation method rootcheck() # drop unprivileged to parse args, etc. # uidManager saves current real uid/gid which are unprivileged (callers) # due to suid helper, our current effective uid is 0 # also supports being run by sudo # # setuid wrapper has real uid = unpriv, effective uid = 0 # sudo sets real/effective = 0, and sets env vars # setuid wrapper clears environment, so there wont be any conflict between these two mockgid = grp.getgrnam('mock').gr_gid uidManager = setup_uid_manager(mockgid) # go unpriv only when root to make --help etc work for non-mock users if os.geteuid() == 0: uidManager.dropPrivsTemp() (options, args) = command_parse() if options.printrootpath or options.list_snapshots: options.verbose = 0 # config path -- can be overridden on cmdline config_path = MOCKCONFDIR if options.configdir: config_path = options.configdir config_opts = util.load_config(config_path, options.chroot, uidManager, __VERSION__, PKGPYTHONDIR) # cmdline options override config options util.set_config_opts_per_cmdline(config_opts, options, args) util.subscription_redhat_init(config_opts) # allow a different mock group to be specified if config_opts['chrootgid'] != mockgid: uidManager.restorePrivs() os.setgroups((mockgid, config_opts['chrootgid'])) uidManager.dropPrivsTemp() # verify that our unprivileged uid is in the mock group groupcheck(uidManager.unprivGid, config_opts['chrootgid']) # configure logging setup_logging(config_path, config_opts, options) # verify that we're not trying to build an arch that we can't check_arch_combination(config_opts['rpmbuild_arch'], config_opts) # security cleanup (don't need/want this in the chroot) if 'SSH_AUTH_SOCK' in os.environ: del os.environ['SSH_AUTH_SOCK'] # elevate privs uidManager.become_user_without_push(0, 0) # do whatever we're here to do py_version = '{0}.{1}.{2}'.format(*sys.version_info[:3]) log.info("mock.py version %s starting (python version = %s)...", __VERSION__, py_version) state = State() plugins = Plugins(config_opts, state) # When scrubbing all, we also want to scrub a bootstrap chroot if options.scrub: config_opts['use_bootstrap'] = True # outer buildroot to bootstrap the installation - based on main config with some differences bootstrap_buildroot = None if config_opts['use_bootstrap']: # first take a copy of the config so we can make some modifications bootstrap_buildroot_config = config_opts.copy() # copy plugins configuration so we get a separate deep copy bootstrap_buildroot_config['plugin_conf'] = \ copy.deepcopy(config_opts['plugin_conf']) # pylint: disable=no-member # add '-bootstrap' to the end of the root name bootstrap_buildroot_config['root'] = bootstrap_buildroot_config['root'] + '-bootstrap' # don't share root cache tarball bootstrap_buildroot_config['plugin_conf']['root_cache_opts']['dir'] = \ "{{cache_topdir}}/" + bootstrap_buildroot_config['root'] + "/root_cache/" # we don't want to affect the bootstrap.config['nspawn_args'] array, deep copy bootstrap_buildroot_config['nspawn_args'] = config_opts.get('nspawn_args', []).copy() # allow bootstrap buildroot to access the network for getting packages bootstrap_buildroot_config['rpmbuild_networking'] = True bootstrap_buildroot_config['use_host_resolv'] = True util.setup_host_resolv(bootstrap_buildroot_config) # use system_*_command for bootstrapping bootstrap_buildroot_config['yum_command'] = bootstrap_buildroot_config['system_yum_command'] bootstrap_buildroot_config['dnf_command'] = bootstrap_buildroot_config['system_dnf_command'] # disable updating bootstrap chroot bootstrap_buildroot_config['update_before_build'] = False bootstrap_buildroot_state = State(bootstrap=True) bootstrap_plugins = Plugins(bootstrap_buildroot_config, bootstrap_buildroot_state) bootstrap_buildroot = Buildroot(bootstrap_buildroot_config, uidManager, bootstrap_buildroot_state, bootstrap_plugins, is_bootstrap=True) # this bit of config is needed after we have created the bootstrap buildroot since we need to # query pkg_manager to know which manager is in use bootstrap_buildroot.config['chroot_setup_cmd'] = bootstrap_buildroot.pkg_manager.install_command # override configs for bootstrap_* for k in bootstrap_buildroot.config.copy(): if "bootstrap_" + k in bootstrap_buildroot.config: bootstrap_buildroot.config[k] = bootstrap_buildroot_config["bootstrap_" + k] del bootstrap_buildroot.config["bootstrap_" + k] if config_opts['redhat_subscription_required']: key_dir = '/etc/pki/entitlement' chroot_dir = bootstrap_buildroot.make_chroot_path(key_dir) mount_point = BindMountPoint(srcpath=key_dir, bindpath=chroot_dir) bootstrap_buildroot.mounts.add(mount_point) # this changes config_opts['nspawn_args'], so do it after initializing # bootstrap chroot to not inherit the changes there util.setup_host_resolv(config_opts) buildroot = Buildroot(config_opts, uidManager, state, plugins, bootstrap_buildroot) if bootstrap_buildroot is not None: # add the extra bind mount to the outer chroot inner_mount = bootstrap_buildroot.make_chroot_path(buildroot.make_chroot_path()) # Hide re-mounted chroot from host by private tmpfs. buildroot.mounts.managed_mounts.append( FileSystemMountPoint(filetype='tmpfs', device='hide_root_in_bootstrap', path=inner_mount, options="private")) buildroot.mounts.managed_mounts.append( BindMountPoint(buildroot.make_chroot_path(), inner_mount, recursive=True, options="private")) signal.signal(signal.SIGTERM, partial(handle_signals, buildroot)) signal.signal(signal.SIGPIPE, partial(handle_signals, buildroot)) signal.signal(signal.SIGHUP, partial(handle_signals, buildroot)) # postprocess option arguments for bootstrap if options.mode in ['installdeps', 'install']: args = [buildroot.file_on_cmdline(arg) for arg in args] log.info("Signal handler active") commands = Commands(config_opts, uidManager, plugins, state, buildroot, bootstrap_buildroot) if config_opts['use_bootstrap']: bootstrap_buildroot.config['chroot_setup_cmd'] = buildroot.pkg_manager.install_command state.start("run") if options.printrootpath: print(buildroot.make_chroot_path('')) sys.exit(0) if options.list_snapshots: plugins.call_hooks('list_snapshots', required=True) if bootstrap_buildroot is not None: bootstrap_buildroot.plugins.call_hooks('list_snapshots', required=True) sys.exit(0) # dump configuration to log log.debug("mock final configuration:") for k, v in list(config_opts.items()): log.debug(" %s: %s", k, v) os.umask(0o02) os.environ["HOME"] = buildroot.homedir # New namespace starting from here unshare_namespace(config_opts) if config_opts['hostname']: util.sethostname(config_opts['hostname']) # set personality (ie. setarch) util.condPersonality(config_opts['target_arch']) result = 0 try: result = run_command(options, args, config_opts, commands, buildroot, state) finally: buildroot.finalize() if bootstrap_buildroot is not None: bootstrap_buildroot.finalize() return result