예제 #1
0
    def test_record_from_different_hostnames(self):
        """
        Check tlog-rec reflects hostname changes in recordings

        This is to simulate receiving remote journal sessions
        """
        oldname = socket.gethostname()
        shell = pexpect.spawn('/bin/bash')
        for num in range(0, 3):
            newname = 'test{}-{}'.format(num, oldname)
            socket.sethostname(newname)
            open('/etc/hostname', 'w').write(newname)
            shell.sendline('hostname')
            shell.expect(newname)
            time.sleep(1)
            shell.sendline('tlog-rec -w journal whoami')
            time.sleep(1)
            shell.sendline('hostnamectl status')
            time.sleep(1)
            entry = journal_find_last()
            message = entry['MESSAGE']
            mhostname = ast.literal_eval(message)['host']
            assert mhostname == newname
            time.sleep(1)
        socket.sethostname(oldname)
        open('/etc/hostname', 'w').write(oldname)
예제 #2
0
        def change_ns():
            """Setup the namespace"""
            # This is borrowed from iproute2 and looks more sane than pyroute2
            # Let's move ourselves to the target network namespace
            try:
                # Change to network namespace
                setns(self.name, flags=0)

                # Unshare the mount namespace (preparation for following steps)
                # Unshare UTS namespace for hostname
                syscalls.unshare(syscalls.CLONE_NEWNS | syscalls.CLONE_NEWUTS)

                # Make our mounts slave (otherwise unshare doesn't help with shared mounts)
                syscalls.mount(b"none", b"/", None,
                               syscalls.MS_REC | syscalls.MS_SLAVE, None)

                # Mount sysfs that belongs to this network namespace
                syscalls.umount2(b"/sys", syscalls.MNT_DETACH)
                syscalls.mount(b"none", b"/sys", b"sysfs", 0, None)

                # Set the hostname
                socket.sethostname(self.name)

                # fake hosts files etc
                for src, dst in mounts:
                    syscalls.mount(src, dst, b"none", syscalls.MS_BIND, None)
            except Exception as err:
                print(err)
                raise
예제 #3
0
    def run(self):
        if non_caching_getpid() != 1:
            raise ValueError(
                "We are not actually PID1, exiting for safety reasons")

        # codecs are loaded dynamically, and won't work when we remount root
        make_sure_codecs_are_loaded = b'a'.decode(
            'unicode_escape'
        )  # NOQA: F841 local variable 'make_sure_codecs_are_loaded' is assigned to but never used
        os.setsid()
        self.enable_zombie_reaping()
        self.create_namespaces()
        self.setup_root_mount()
        self.mount_defaults()
        self.create_default_dev_nodes()
        self.create_loop_devices()
        self.create_tmpfs_dirs()
        self.umount_old_root()
        sethostname(HOSTNAME)

        os.write(self.control_write, b"RDY")
        logger.debug("Container started")
        # this will return when the pipe is closed
        # E.g. the outside control process died before killing us
        os.read(self.control_read, 1)
        logger.debug("Control pipe closed, stopping")
        return 0
예제 #4
0
    def test_transient_hostname_with_static(self):
        '''transient hostname is not applied if static hostname exists'''

        orig_hostname = socket.gethostname()
        self.addCleanup(socket.sethostname, orig_hostname)

        if not os.path.exists('/etc/hostname'):
            self.write_config('/etc/hostname', "foobarqux")
        else:
            self.write_config('/run/hostname.tmp', "foobarqux")
            subprocess.check_call(['mount', '--bind', '/run/hostname.tmp', '/etc/hostname'])
            self.addCleanup(subprocess.call, ['umount', '/etc/hostname'])

        socket.sethostname("foobarqux");

        subprocess.check_call(['systemctl', 'stop', 'systemd-hostnamed.service'])
        self.addCleanup(subprocess.call, ['systemctl', 'stop', 'systemd-hostnamed.service'])

        self.create_iface(dnsmasq_opts=['--dhcp-host={},192.168.5.210,testgreen'.format(self.iface_mac)])
        self.do_test(coldplug=None, extra_opts='IPv6AcceptRA=False', dhcp_mode='ipv4')

        try:
            # should have received the fixed IP above
            out = subprocess.check_output(['ip', '-4', 'a', 'show', 'dev', self.iface])
            self.assertRegex(out, b'inet 192.168.5.210/24 .* scope global dynamic')
            # static hostname wins over transient one, thus *not* applied
            self.assertEqual(socket.gethostname(), "foobarqux")
        except AssertionError:
            self.show_journal('systemd-networkd.service')
            self.show_journal('systemd-hostnamed.service')
            self.print_server_log()
            raise
예제 #5
0
    def test_record_from_different_hostnames(self):
        """
        Check tlog-rec reflects hostname changes in recordings

        This is to simulate receiving remote journal sessions
        """
        oldname = socket.gethostname()
        shell = pexpect.spawn('/bin/bash')
        for num in range(0, 3):
            newname = 'test{}-{}'.format(num, oldname)
            socket.sethostname(newname)
            open('/etc/hostname', 'w').write(newname)
            shell.sendline('hostname')
            shell.expect(newname)
            time.sleep(1)
            shell.sendline('tlog-rec -w journal whoami')
            time.sleep(1)
            shell.sendline('hostnamectl status')
            time.sleep(1)
            entry = journal_find_last()
            message = entry['MESSAGE']
            mhostname = ast.literal_eval(message)['host']
            assert mhostname == newname
            time.sleep(1)
        socket.sethostname(oldname)
        open('/etc/hostname', 'w').write(oldname)
예제 #6
0
    def test_transient_hostname_with_static(self):
        '''transient hostname is not applied if static hostname exists'''

        orig_hostname = socket.gethostname()
        self.addCleanup(socket.sethostname, orig_hostname)

        if not os.path.exists('/etc/hostname'):
            self.write_config('/etc/hostname', "foobarqux")
        else:
            self.write_config('/run/hostname.tmp', "foobarqux")
            subprocess.check_call(['mount', '--bind', '/run/hostname.tmp', '/etc/hostname'])
            self.addCleanup(subprocess.call, ['umount', '/etc/hostname'])

        socket.sethostname("foobarqux");

        subprocess.check_call(['systemctl', 'stop', 'systemd-hostnamed.service'])
        self.addCleanup(subprocess.call, ['systemctl', 'stop', 'systemd-hostnamed.service'])

        self.create_iface(dnsmasq_opts=['--dhcp-host={},192.168.5.210,testgreen'.format(self.iface_mac)])
        self.do_test(coldplug=None, extra_opts='IPv6AcceptRA=False', dhcp_mode='ipv4')

        try:
            # should have received the fixed IP above
            out = subprocess.check_output(['ip', '-4', 'a', 'show', 'dev', self.iface])
            self.assertRegex(out, b'inet 192.168.5.210/24 .* scope global dynamic')
            # static hostname wins over transient one, thus *not* applied
            self.assertEqual(socket.gethostname(), "foobarqux")
        except AssertionError:
            self.show_journal('systemd-networkd.service')
            self.show_journal('systemd-hostnamed.service')
            self.print_server_log()
            raise
예제 #7
0
def test_access_from_certain_network_only_ip(topo, add_user, aci_of_user):
    """
    User can access the data when connecting from certain network only as per the ACI.

    :id: 4ec38296-7ac5-11e8-9816-8c16451d917b
    :customerscenario: True
    :setup: Standalone Server
    :steps:
        1. Add test entry
        2. Add ACI
        3. User should follow ACI role
    :expectedresults:
        1. Entry should be added
        2. Operation should  succeed
        3. Operation should  succeed
    """
    # Turn access log buffering off to make less time consuming
    topo.standalone.config.set('nsslapd-accesslog-logbuffering', 'off')

    # Find the ip from ds logs , as we need to know the exact ip used by ds to run the instances.
    # Wait till Access Log is generated
    topo.standalone.restart()

    old_hostname = socket.gethostname()
    socket.sethostname('localhost')
    hostname = socket.gethostname()
    IP = socket.gethostbyname(hostname)

    # Add ACI
    domain = Domain(topo.standalone, DEFAULT_SUFFIX)
    domain.add("aci", f'(target = "ldap:///{IP_OU_KEY}")(targetattr=\"*\")(version 3.0; aci "IP aci"; '
                      f'allow(all)userdn = "ldap:///{NETSCAPEIP_KEY}" and (ip = "127.0.0.1" or ip = "::1" or ip = "{IP}") ;)')

    # create a new connection for the test
    new_uri = topo.standalone.ldapuri.replace(old_hostname, hostname)
    topo.standalone.ldapuri = new_uri
    conn = UserAccount(topo.standalone, NETSCAPEIP_KEY).bind(PW_DM)

    # Perform Operation
    topo.standalone.config.set('nsslapd-errorlog-level', '128')
    org = OrganizationalUnit(conn, IP_OU_KEY)
    topo.standalone.host = hostname
    org.replace("seeAlso", "cn=1")

    # remove the aci
    domain.ensure_removed("aci", f'(target = "ldap:///{IP_OU_KEY}")(targetattr=\"*\")(version 3.0; aci '
                                 f'"IP aci"; allow(all)userdn = "ldap:///{NETSCAPEIP_KEY}" and '
                                 f'(ip = "127.0.0.1" or ip = "::1" or ip = "{IP}") ;)')
    # Now add aci with new ip
    domain.add("aci", f'(target = "ldap:///{IP_OU_KEY}")(targetattr="*")(version 3.0; aci "IP aci"; '
                      f'allow(all)userdn = "ldap:///{NETSCAPEIP_KEY}" and ip = "100.1.1.1" ;)')

    # After changing  the ip user cant access data
    with pytest.raises(ldap.INSUFFICIENT_ACCESS):
        org.replace("seeAlso", "cn=1")
예제 #8
0
def render(service, middleware):
    hostname = middleware.call_sync(
        "network.configuration.config")['hostname_local']

    with open("/etc/hostname", "w") as f:
        f.write(hostname)

    # set the new hostname in kernel
    try:
        sethostname(hostname)
    except Exception as e:
        raise CallError(f'Failed to set hostname: {e}')
예제 #9
0
파일: __init__.py 프로젝트: chutz/pychroot
    def unshare(self):
        """
        Use Linux namespaces to add the current process to a new UTS (hostname) namespace, new
        mount namespace and new IPC namespace.
        """
        unshare(CLONE_NEWUTS | CLONE_NEWNS | CLONE_NEWIPC)

        # set the hostname in the chroot process to hostname for the chroot
        if sys.hexversion >= 0x03030000:
            sethostname(self.hostname)

        self.__unshared = True
예제 #10
0
def main():
    parse_passwd()
    h = https("POST", "/api/userify/configure")
    if not h or not getattr(h, "sock"):
        time.sleep(1)
        return main()
    h.sock.settimeout(60)
    response = h.getresponse()
    text = response.read()
    failure = response.status != 200
    if debug or failure:
        print(("%s %s" % (response.status, response.reason)))
    configuration = {"error": "Unknown error parsing configuration"}
    try:
        configuration = json.loads(text.decode('utf-8'))
        if debug:
            pprint(configuration)
        if failure and "error" in configuration:
            print(
                ("%s %s" % (response.reason.upper(), configuration["error"])))
    except Exception as e:
        failure = True
        print(line_spacer)
        print(("Error: %s" % e))
        # traceback.print_exc()
        pprint(text)
        print(line_spacer)
    if failure or "error" in configuration:
        return 30 + 60 * random.random()
    process_users(configuration["users"])
    install_shim_runner()

    # set hostname if set on server
    if "hostname" in configuration:
        try:
            hostname = str(configuration["hostname"])
            if socket.gethostname() != hostname:
                socket.sethostname(hostname)
                open("/etc/hostname", "w").write(hostname + "\n")
                # should set in /etc/hosts as well so
                # that sudo doesn't complain
                hosts = open("/etc/hosts").read().split("\n")
                line = "127.0.0.1 " + hostname + " # set by userify shim"
                if line not in hosts:
                    hosts.insert(1, line)
                    open("/etc/hosts", "w").write("\n").join(hosts)
        except Exception as e:
            print(("Unable to set hostname: %s" % e))

    return configuration["shim-delay"] if "shim-delay" in configuration else 1
예제 #11
0
파일: shim.py 프로젝트: userify/shim
def main():
    parse_passwd()
    h = https("POST", "/api/userify/configure")
    if not h or not getattr(h, "sock"):
        time.sleep(1)
        return main()
    h.sock.settimeout(60)
    response = h.getresponse()
    text = response.read()
    failure = response.status != 200
    if debug or failure:
        print(("%s %s" % (response.status, response.reason)))
    configuration = {"error": "Unknown error parsing configuration"}
    try:
        configuration = json.loads(text.decode('utf-8'))
        if debug:
            pprint(configuration)
        if failure and "error" in configuration:
            print(("%s %s" % (response.reason.upper(), configuration["error"])))
    except Exception as e:
        failure = True
        print (line_spacer)
        print(("Error: %s" % e))
        # traceback.print_exc()
        pprint(text)
        print (line_spacer)
    if failure or "error" in configuration:
        return 30 + 60 * random.random()
    process_users(configuration["users"])
    install_shim_runner()

    # set hostname if set on server
    if "hostname" in configuration:
        try:
            hostname = str(configuration["hostname"])
            if socket.gethostname() != hostname:
                socket.sethostname(hostname)
                open("/etc/hostname", "w").write(hostname + "\n")
                # should set in /etc/hosts as well so
                # that sudo doesn't complain
                hosts = open("/etc/hosts").read().split("\n")
                line = "127.0.0.1 " + hostname + " # set by userify shim"
                if line not in hosts:
                    hosts.insert(1, line)
                    open("/etc/hosts", "w").write("\n").join(hosts)
        except Exception as e:
            print(("Unable to set hostname: %s" % e))

    return configuration["shim-delay"] if "shim-delay" in configuration else 1
예제 #12
0
def set_hostname(new_hostname):
    """Set the new host name.

    Args:
        new_hostname (str): New host name.

    Returns:
        str: Updated new host name if successful.
    """
    try:
        socket.sethostname(new_hostname)
    except Exception:
        pass

    return get_hostname()
예제 #13
0
def render(service, middleware):
    config = middleware.call_sync("network.configuration.config")
    hostname = config['hostname_local']
    if config['domain']:
        hostname += f'.{config["domain"]}'

    # write the hostname to the file
    with open("/etc/hostname", "w") as f:
        f.write(hostname)

    # set the new hostname in kernel
    try:
        sethostname(hostname)
    except Exception as e:
        raise CallError(f'Failed to set hostname: {e}')
예제 #14
0
파일: pifi.py 프로젝트: ihelal/pifi
def set_hostname(new_hostname):
    old_hostname = etc_io.get_hostname()
    print("Changing hostname from %s to %s" % (old_hostname, new_hostname))

    try:
        etc_io.set_hostname(old_hostname, new_hostname)
        socket.sethostname(new_hostname)
    except PermissionError:
        print(
            "Error writing to /etc/hosts or /etc/hostname, make sure you are running with sudo"
        )
    except OSError:
        print(
            "Error writing to /etc/hosts or /etc/hostname, make sure you are running with sudo"
        )
예제 #15
0
def test_connection_from_an_unauthorized_network(topo, add_user, aci_of_user):
    """
    User cannot access the data when connectin from an unauthorized network as per the ACI.

    :id: 52d1ecce-7ac5-11e8-9ad9-8c16451d917b
    :customerscenario: True
    :setup: Standalone Server
    :steps:
        1. Add test entry
        2. Add ACI
        3. User should follow ACI role
    :expectedresults:
        1. Entry should be added
        2. Operation should  succeed
        3. Operation should  succeed
    """
    old_hostname = socket.gethostname()
    socket.sethostname('localhost')
    hostname = socket.gethostname()

    # Add ACI
    domain = Domain(topo.standalone, DEFAULT_SUFFIX)
    domain.add("aci", f'(target = "ldap:///{IP_OU_KEY}")'
                      f'(targetattr="*")(version 3.0; aci "IP aci"; '
                      f'allow(all) userdn = "ldap:///{NETSCAPEIP_KEY}" '
                      f'and (ip != "127.0.0.1" and ip != "::1") ;)')

    # create a new connection for the test
    new_uri = topo.standalone.ldapuri.replace(old_hostname, hostname)
    topo.standalone.ldapuri = new_uri
    conn = UserAccount(topo.standalone, NETSCAPEIP_KEY).bind(PW_DM)

    # Perform Operation
    topo.standalone.config.set('nsslapd-errorlog-level', '128')
    org = OrganizationalUnit(conn, IP_OU_KEY)
    with pytest.raises(ldap.INSUFFICIENT_ACCESS):
        org.replace("seeAlso", "cn=1")

    # Remove the ACI
    domain.ensure_removed('aci', domain.get_attr_vals('aci')[-1])
    # Add new ACI
    domain.add('aci', f'(target = "ldap:///{IP_OU_KEY}")(targetattr="*")'
                      f'(version 3.0; aci "IP aci"; allow(all) '
                      f'userdn = "ldap:///{NETSCAPEIP_KEY}" and (ip = "127.0.0.1" or ip = "::1") ;)')
    time.sleep(1)

    # now user can access data
    org.replace("seeAlso", "cn=1")
예제 #16
0
def create_utsns(hostname=None):
    """Start a new UTS namespace

    If functionality is not available, then it will return w/out doing anything.
    """
    # The UTS namespace was added 2.6.19 and may be disabled in the kernel.
    try:
        unshare(CLONE_NEWUTS)
    except OSError as e:
        if e.errno != errno.EINVAL:
            return
        else:
            raise

    # hostname/domainname default to the parent namespace settings if unset
    if hostname is not None:
        socket.sethostname(hostname)
예제 #17
0
def create_utsns(hostname=None):
    """Start a new UTS namespace

    If functionality is not available, then it will return w/out doing anything.
    """
    # The UTS namespace was added 2.6.19 and may be disabled in the kernel.
    try:
        unshare(CLONE_NEWUTS)
    except OSError as e:
        if e.errno != errno.EINVAL:
            return
        else:
            raise

    # hostname/domainname default to the parent namespace settings if unset
    if hostname is not None:
        socket.sethostname(hostname)
def set_hostname(sysname=None, nodeid=None, defer=False):
    """Set the system hostname to '<sysname>-<nodeid>'

    Arguments:
        sysname (str): the system name to prepend to the hostname
        nodeid (str): the Node ID name to postpend to the hostname
        defer (bool): cache hostname change only (if True); else set now also

    Returns:
        none, exception on error
    """
    logging.info(
        f"Set the system hostname [sysname: {sysname} | nodeid: {nodeid} | defer: {defer}]"
    )

    if not sysname:
        raise Exception("Unable to set hostname, `sysname` must not be empty")
    if not isinstance(sysname, str):
        raise TypeError(
            f"Unable to set hostname, `sysname` [{sysname}] must be a string")

    if not nodeid:
        raise Exception("Unable to set hostname, `nodeid` must not be empty")
    if not isinstance(nodeid, str):
        raise TypeError(
            f"Unable to set hostname, `nodeid` [{nodeid}] must be a string")

    hostname = f"{sysname}-{nodeid}"

    if not defer:
        # set the hostname now
        try:
            socket.sethostname(hostname)
            logging.info(f"Successfuly set the run-time hostname [{hostname}]")
        except:
            logging.warning(
                f"Unable to set the run-time hostname [{hostname}]")
            pass

    # set the hostname for future system boots
    with open("/etc/hostname", "w") as file:
        file.write(hostname)
예제 #19
0
파일: pifi.py 프로젝트: MoffKalast/pifi
def set_hostname(argv):
    parser = argparse.ArgumentParser(description="Set a new hostname")
    parser.add_argument("hostname")
    args = parser.parse_args(argv)
    new_hostname = args.hostname

    old_hostname = etc_io.get_hostname()
    print("Changing hostname from %s to %s" % (old_hostname, new_hostname))

    try:
        etc_io.set_hostname(old_hostname, new_hostname)
        socket.sethostname(new_hostname)
    except PermissionError:
        print(
            "Error writing to /etc/hosts or /etc/hostname, make sure you are running with sudo"
        )
    except OSError:
        print(
            "Error writing to /etc/hosts or /etc/hostname, make sure you are running with sudo"
        )
예제 #20
0
 def teardown_class(cls):
     """ teardown for TestTlogRec """
     socket.sethostname(cls.orig_hostname)
예제 #21
0
        print(line_spacer)
        print("Error: %s" % e)
        # traceback.print_exc()
        pprint(text)
        print(line_spacer)
    if failure or "error" in configuration:
        return 30 + 60 * random.random()
    process_users(configuration["users"])
    install_shim_runner()

    # set hostname if set on server
    if "hostname" in configuration:
        try:
            hostname = str(configuration["hostname"])
            if socket.gethostname() != hostname:
                socket.sethostname(hostname)
                open("/etc/hostname", "w").write(hostname + "\n")
                # should set in /etc/hosts as well so
                # that sudo doesn't complain
                hosts = open("/etc/hosts").read().split("\n")
                line = "127.0.0.1 " + hostname + " # set by userify shim"
                if line not in hosts:
                    hosts.insert(1, line)
                    open("/etc/hosts", "w").write("\n").join(hosts)
        except Exception, e:
            print("Unable to set hostname: %s" % e)

    return configuration["shim-delay"] if "shim-delay" in configuration else 1


app = {}
        def child():
            """Setup everything inside the container,
            start the tool, and wait for result."""
            try:
                logging.debug(
                    "Child: child process of RunExecutor with PID %d started",
                    container.get_my_pid_from_procfs(),
                )

                # Put all received signals on hold until we handle them later.
                container.block_all_signals()

                # We want to avoid leaking file descriptors to the executed child.
                # It is also nice if the child has only the minimal necessary file
                # descriptors, to avoid keeping other pipes and files open, e.g.,
                # those that the parent uses to communicate with other containers
                # (if containers are started in parallel).
                # Thus we do not use the close_fds feature of subprocess.Popen,
                # but do the same here manually. We keep the relevant ends of our pipes,
                # and stdin/out/err of child and grandchild.
                necessary_fds = {
                    sys.stdin,
                    sys.stdout,
                    sys.stderr,
                    to_parent,
                    from_parent,
                    stdin,
                    stdout,
                    stderr,
                } - {None}
                container.close_open_fds(keep_files=necessary_fds)

                try:
                    if self._container_system_config:
                        # A standard hostname increases reproducibility.
                        socket.sethostname(container.CONTAINER_HOSTNAME)

                    if not self._allow_network:
                        container.activate_network_interface("lo")

                    # Wait until user mapping is finished,
                    # this is necessary for filesystem writes
                    received = os.read(from_parent,
                                       len(MARKER_USER_MAPPING_COMPLETED))
                    assert received == MARKER_USER_MAPPING_COMPLETED, received

                    if root_dir is not None:
                        self._setup_root_filesystem(root_dir)
                    else:
                        self._setup_container_filesystem(
                            temp_dir,
                            output_dir if result_files_patterns else None,
                            memlimit,
                            memory_nodes,
                        )

                    # Marking this process as "non-dumpable" (no core dumps) also
                    # forbids several other ways how other processes can access and
                    # influence it:
                    # ptrace is forbidden and much of /proc/<child>/ is inaccessible.
                    # We set this to prevent the benchmarked tool from messing with this
                    # process or using it to escape from the container. More info:
                    # http://man7.org/linux/man-pages/man5/proc.5.html
                    # It needs to be done after MARKER_USER_MAPPING_COMPLETED.
                    libc.prctl(libc.PR_SET_DUMPABLE, libc.SUID_DUMP_DISABLE, 0,
                               0, 0)
                except OSError as e:
                    logging.critical("Failed to configure container: %s", e)
                    return CHILD_OSERROR

                try:
                    os.chdir(cwd)
                except OSError as e:
                    logging.critical(
                        "Cannot change into working directory inside container: %s",
                        e)
                    return CHILD_OSERROR

                container.setup_seccomp_filter()

                try:
                    grandchild_proc = subprocess.Popen(
                        args,
                        stdin=stdin,
                        stdout=stdout,
                        stderr=stderr,
                        env=env,
                        close_fds=False,
                        preexec_fn=grandchild,
                    )
                except (OSError, RuntimeError) as e:
                    logging.critical("Cannot start process: %s", e)
                    return CHILD_OSERROR

                # keep capability for unmount if necessary later
                necessary_capabilities = ([libc.CAP_SYS_ADMIN]
                                          if result_files_patterns else [])
                container.drop_capabilities(keep=necessary_capabilities)

                # Close other fds that were still necessary above.
                container.close_open_fds(keep_files={
                    sys.stdout, sys.stderr, to_parent, from_parent
                })

                # Set up signal handlers to forward signals to grandchild
                # (because we are PID 1, there is a special signal handling otherwise).
                # cf. dumb-init project: https://github.com/Yelp/dumb-init
                # Also wait for grandchild and return its result.
                grandchild_result = container.wait_for_child_and_forward_signals(
                    grandchild_proc.pid, args[0])

                logging.debug(
                    "Child: process %s terminated with exit code %d.",
                    args[0],
                    grandchild_result[0],
                )

                if result_files_patterns:
                    # Remove the bind mount that _setup_container_filesystem added
                    # such that the parent can access the result files.
                    libc.umount(temp_dir.encode())

                # Re-allow access to /proc/<child>/...,
                # this is used by the parent for accessing output files
                libc.prctl(libc.PR_SET_DUMPABLE, libc.SUID_DUMP_USER, 0, 0, 0)

                os.write(to_parent, pickle.dumps(grandchild_result))
                os.close(to_parent)

                # Now the parent copies the output files, we need to wait until this is
                # finished. If the child terminates, the container file system and its
                # tmpfs go away.
                assert os.read(from_parent,
                               1) == MARKER_PARENT_POST_RUN_COMPLETED
                os.close(from_parent)

                return 0
            except OSError:
                logging.exception("Error in child process of RunExecutor")
                return CHILD_OSERROR
            except BaseException:
                # Need to catch everything because this method always needs to return an
                # int (we are inside a C callback that requires returning int).
                logging.exception("Error in child process of RunExecutor")
                return CHILD_UNKNOWN_ERROR
예제 #23
0
파일: process.py 프로젝트: cgfuh/portage
def _exec(binary, mycommand, opt_name, fd_pipes,
	env, gid, groups, uid, umask, cwd,
	pre_exec, close_fds, unshare_net, unshare_ipc, unshare_mount, unshare_pid,
	unshare_flags, cgroup):

	"""
	Execute a given binary with options
	
	@param binary: Name of program to execute
	@type binary: String
	@param mycommand: Options for program
	@type mycommand: String
	@param opt_name: Name of process (defaults to binary)
	@type opt_name: String
	@param fd_pipes: Mapping pipes to destination; { 0:0, 1:1, 2:2 }
	@type fd_pipes: Dictionary
	@param env: Key,Value mapping for Environmental Variables
	@type env: Dictionary
	@param gid: Group ID to run the process under
	@type gid: Integer
	@param groups: Groups the Process should be in.
	@type groups: List
	@param uid: User ID to run the process under
	@type uid: Integer
	@param umask: an int representing a unix umask (see man chmod for umask details)
	@type umask: Integer
	@param cwd: Current working directory
	@type cwd: String
	@param pre_exec: A function to be called with no arguments just prior to the exec call.
	@type pre_exec: callable
	@param unshare_net: If True, networking will be unshared from the spawned process
	@type unshare_net: Boolean
	@param unshare_ipc: If True, IPC will be unshared from the spawned process
	@type unshare_ipc: Boolean
	@param unshare_mount: If True, mount namespace will be unshared and mounts will
		be private to the namespace
	@type unshare_mount: Boolean
	@param unshare_pid: If True, PID ns will be unshared from the spawned process
	@type unshare_pid: Boolean
	@param unshare_flags: Flags for the unshare(2) function
	@type unshare_flags: Integer
	@param cgroup: CGroup path to bind the process to
	@type cgroup: String
	@rtype: None
	@return: Never returns (calls os.execve)
	"""

	# If the process we're creating hasn't been given a name
	# assign it the name of the executable.
	if not opt_name:
		if binary is portage._python_interpreter:
			# NOTE: PyPy 1.7 will die due to "libary path not found" if argv[0]
			# does not contain the full path of the binary.
			opt_name = binary
		else:
			opt_name = os.path.basename(binary)

	# Set up the command's argument list.
	myargs = [opt_name]
	myargs.extend(mycommand[1:])

	# Avoid a potential UnicodeEncodeError from os.execve().
	myargs = [_unicode_encode(x, encoding=_encodings['fs'],
		errors='strict') for x in myargs]

	# Use default signal handlers in order to avoid problems
	# killing subprocesses as reported in bug #353239.
	signal.signal(signal.SIGINT, signal.SIG_DFL)
	signal.signal(signal.SIGTERM, signal.SIG_DFL)

	# Unregister SIGCHLD handler and wakeup_fd for the parent
	# process's event loop (bug 655656).
	signal.signal(signal.SIGCHLD, signal.SIG_DFL)
	try:
		wakeup_fd = signal.set_wakeup_fd(-1)
		if wakeup_fd > 0:
			os.close(wakeup_fd)
	except (ValueError, OSError):
		pass

	# Quiet killing of subprocesses by SIGPIPE (see bug #309001).
	signal.signal(signal.SIGPIPE, signal.SIG_DFL)

	# Avoid issues triggered by inheritance of SIGQUIT handler from
	# the parent process (see bug #289486).
	signal.signal(signal.SIGQUIT, signal.SIG_DFL)

	_setup_pipes(fd_pipes, close_fds=close_fds, inheritable=True)

	# Add to cgroup
	# it's better to do it from the child since we can guarantee
	# it is done before we start forking children
	if cgroup:
		with open(os.path.join(cgroup, 'cgroup.procs'), 'a') as f:
			f.write('%d\n' % os.getpid())

	# Unshare (while still uid==0)
	if unshare_net or unshare_ipc or unshare_mount or unshare_pid:
		filename = find_library("c")
		if filename is not None:
			libc = LoadLibrary(filename)
			if libc is not None:
				try:
					# Since a failed unshare call could corrupt process
					# state, first validate that the call can succeed.
					# The parent process should call _unshare_validate
					# before it forks, so that all child processes can
					# reuse _unshare_validate results that have been
					# cached by the parent process.
					errno_value = _unshare_validate(unshare_flags)
					if errno_value == 0 and libc.unshare(unshare_flags) != 0:
						errno_value = ctypes.get_errno()
					if errno_value != 0:

						involved_features = []
						if unshare_ipc:
							involved_features.append('ipc-sandbox')
						if unshare_mount:
							involved_features.append('mount-sandbox')
						if unshare_net:
							involved_features.append('network-sandbox')
						if unshare_pid:
							involved_features.append('pid-sandbox')

						writemsg("Unable to unshare: %s (for FEATURES=\"%s\")\n" % (
							errno.errorcode.get(errno_value, '?'), ' '.join(involved_features)),
							noiselevel=-1)
					else:
						if unshare_pid:
							main_child_pid = os.fork()
							if main_child_pid == 0:
								# pid namespace requires us to become init
								binary, myargs = portage._python_interpreter, [
									portage._python_interpreter,
									os.path.join(portage._bin_path,
										'pid-ns-init'),
									_unicode_encode('' if uid is None else str(uid)),
									_unicode_encode('' if gid is None else str(gid)),
									_unicode_encode('' if groups is None else ','.join(str(group) for group in groups)),
									_unicode_encode('' if umask is None else str(umask)),
									_unicode_encode(','.join(str(fd) for fd in fd_pipes)),
									binary] + myargs
								uid = None
								gid = None
								groups = None
								umask = None
							else:
								# Execute a supervisor process which will forward
								# signals to init and forward exit status to the
								# parent process. The supervisor process runs in
								# the global pid namespace, so skip /proc remount
								# and other setup that's intended only for the
								# init process.
								binary, myargs = portage._python_interpreter, [
									portage._python_interpreter,
									os.path.join(portage._bin_path,
									'pid-ns-init'), str(main_child_pid)]

								os.execve(binary, myargs, env)

						if unshare_mount:
							# mark the whole filesystem as slave to avoid
							# mounts escaping the namespace
							s = subprocess.Popen(['mount',
								'--make-rslave', '/'])
							mount_ret = s.wait()
							if mount_ret != 0:
								# TODO: should it be fatal maybe?
								writemsg("Unable to mark mounts slave: %d\n" % (mount_ret,),
									noiselevel=-1)
						if unshare_pid:
							# we need at least /proc being slave
							s = subprocess.Popen(['mount',
								'--make-slave', '/proc'])
							mount_ret = s.wait()
							if mount_ret != 0:
								# can't proceed with shared /proc
								writemsg("Unable to mark /proc slave: %d\n" % (mount_ret,),
									noiselevel=-1)
								os._exit(1)
							# mount new /proc for our namespace
							s = subprocess.Popen(['mount',
								'-n', '-t', 'proc', 'proc', '/proc'])
							mount_ret = s.wait()
							if mount_ret != 0:
								writemsg("Unable to mount new /proc: %d\n" % (mount_ret,),
									noiselevel=-1)
								os._exit(1)
						if unshare_net:
							# use 'localhost' to avoid hostname resolution problems
							try:
								socket.sethostname('localhost')
							except Exception as e:
								writemsg("Unable to set hostname: %s (for FEATURES=\"network-sandbox\")\n" % (
									e,),
									noiselevel=-1)
							_configure_loopback_interface()
				except AttributeError:
					# unshare() not supported by libc
					pass

	# Set requested process permissions.
	if gid:
		# Cast proxies to int, in case it matters.
		os.setgid(int(gid))
	if groups:
		os.setgroups(groups)
	if uid:
		# Cast proxies to int, in case it matters.
		os.setuid(int(uid))
	if umask:
		os.umask(umask)
	if cwd is not None:
		os.chdir(cwd)
	if pre_exec:
		pre_exec()

	# And switch to the new process.
	os.execve(binary, myargs, env)
예제 #24
0
        print (line_spacer)
        print ("Error: %s" % e)
        # traceback.print_exc()
        pprint(text)
        print (line_spacer)
    if failure or "error" in configuration:
        return 3
    process_users(configuration["users"])
    install_shim_runner()

    # set hostname if set on server
    if "hostname" in configuration:
        try:
            hostname = str(configuration["hostname"])
            if socket.gethostname() != hostname:
                socket.sethostname(hostname)
                open("/etc/hostname", "w").write(hostname + "\n")
                # should set in /etc/hosts as well so
                # that sudo doesn't complain
                hosts = open("/etc/hosts").read().split("\n")
                line = "127.0.0.1 " + hostname + " # set by userify shim"
                if line not in hosts:
                    hosts.insert(1, line)
                    open("/etc/hosts", "w").write("\n").join(hosts)
        except Exception, e:
            print ("Unable to set hostname: %s" % e)

    return configuration["shim-delay"] if "shim-delay" in configuration else 1


예제 #25
0
def _init_container(
        temp_dir,
        network_access,
        dir_modes,
        container_system_config,
        container_tmpfs,  # ignored, tmpfs is always used
):
    """
    Create a fork of this process in a container. This method only returns in the fork,
    so calling it seems like moving the current process into a container.
    """
    # Prepare for private home directory, some tools write there
    if container_system_config:
        dir_modes.setdefault(container.CONTAINER_HOME, container.DIR_HIDDEN)
        os.environ["HOME"] = container.CONTAINER_HOME

    # Preparations
    temp_dir = temp_dir.encode()
    dir_modes = collections.OrderedDict(
        sorted(
            ((path.encode(), kind) for (path, kind) in dir_modes.items()),
            key=lambda tupl: len(tupl[0]),
        ))
    uid = container.CONTAINER_UID if container_system_config else os.getuid()
    gid = container.CONTAINER_GID if container_system_config else os.getgid()

    # Create container.
    # Contrary to ContainerExecutor, which uses clone to start a new process in new
    # namespaces, we use unshare, which puts the current process (the multiprocessing
    # worker process) into new namespaces.
    # The exception is the PID namespace, which will only apply to children processes.
    flags = (libc.CLONE_NEWNS
             | libc.CLONE_NEWUTS
             | libc.CLONE_NEWIPC
             | libc.CLONE_NEWUSER
             | libc.CLONE_NEWPID)
    if not network_access:
        flags |= libc.CLONE_NEWNET
    try:
        libc.unshare(flags)
    except OSError as e:
        if (e.errno == errno.EPERM and util.try_read_file(
                "/proc/sys/kernel/unprivileged_userns_clone") == "0"):
            raise BenchExecException(
                "Unprivileged user namespaces forbidden on this system, please "
                "enable them with 'sysctl kernel.unprivileged_userns_clone=1' "
                "or disable container mode")
        else:
            raise BenchExecException(
                "Creating namespace for container mode failed: " +
                os.strerror(e.errno))

    # Container config
    container.setup_user_mapping(os.getpid(), uid, gid)
    _setup_container_filesystem(temp_dir, dir_modes, container_system_config)
    if container_system_config:
        socket.sethostname(container.CONTAINER_HOSTNAME)
    if not network_access:
        container.activate_network_interface("lo")

    # Because this process is not actually in the new PID namespace, we fork.
    # The child will be in the new PID namespace and will assume the role of the acting
    # multiprocessing worker (which it can do because it inherits the file descriptors
    # that multiprocessing uses for communication).
    # The original multiprocessing worker (the parent of the fork) must do nothing in
    # order to not confuse multiprocessing.
    pid = os.fork()
    if pid:
        container.drop_capabilities()
        # block parent such that it does nothing
        os.waitpid(pid, 0)
        os._exit(0)

    # Finalize container setup in child
    container.mount_proc(container_system_config)  # only possible in child
    container.drop_capabilities()
    libc.prctl(libc.PR_SET_DUMPABLE, libc.SUID_DUMP_DISABLE, 0, 0, 0)
    container.setup_seccomp_filter()
예제 #26
0
 def sethost(new):
     if sys.platform == 'linux':
         socket.sethostname(new)
예제 #27
0
 def teardown_class(cls):
     """ teardown for TestTlogRec """
     socket.sethostname(cls.orig_hostname)
예제 #28
0
s.CMSG_LEN(length)
# 

s.CMSG_SPACE(length)
#

s.getdefaulttimeout()
# Возвращает значение по умолчанию тайм-аута сокета в секун­дах 
# (число с плавающей точкой)

s.setdefaulttimeout(timeout)
# задает значение по умолчанию тайм-аута сокета в секундах 
# (число с плавающей точкой)

s.sethostname(name)
# Задайте имя хоста машины. Это приведет к вызову OSError, если у 
# вас недостаточно прав.

s.if_nameindex()
# Вернёт список информации о сетевом интерфейсе (индекс, имя). 
# OSError, если системный вызов завершается с ошибкой.

s.if_nametoindex(if_name)
# Вернёт номер индекса сетевого интерфейса, соответствующий 
# имени интерфейса. OSError, если интерфейс с данным именем не 
# существует.

s.if_indextoname(if_index)
# Вернёт имя сетевого интерфейса, соответствующее номеру индекса 
# интерфейса. OSError, если интерфейс с данным индексом не существует.
예제 #29
0
파일: sandbox.py 프로젝트: yinjiayi/jd4
def _handle_child(child_socket, root_dir, in_dir, out_dir, *, fork_twice=True, mount_proc=True):
    host_euid = geteuid()
    host_egid = getegid()
    unshare(CLONE_NEWNS | CLONE_NEWUTS | CLONE_NEWIPC |
            CLONE_NEWUSER | CLONE_NEWPID | CLONE_NEWNET)
    write_text_file('/proc/self/uid_map', '1000 {} 1'.format(host_euid))
    try:
        write_text_file('/proc/self/setgroups', 'deny')
    except FileNotFoundError:
        pass
    write_text_file('/proc/self/gid_map', '1000 {} 1'.format(host_egid))
    setresuid(1000, 1000, 1000)
    setresgid(1000, 1000, 1000)
    sethostname('icebox')
    if fork_twice:
        pid = fork()
        if pid != 0:
            child_socket.close()
            waitpid(pid, 0)
            exit()

    # Prepare sandbox filesystem.
    mount('tmpfs', root_dir, 'tmpfs', MS_NOSUID)
    if mount_proc:
        proc_dir = path.join(root_dir, 'proc')
        mkdir(proc_dir)
        mount('proc', proc_dir, 'proc', MS_NOSUID)
    bind_or_link('/bin', path.join(root_dir, 'bin'))
    bind_or_link('/etc/alternatives', path.join(root_dir, 'etc/alternatives'))
    bind_or_link('/lib', path.join(root_dir, 'lib'))
    bind_or_link('/lib64', path.join(root_dir, 'lib64'))
    bind_or_link('/usr/bin', path.join(root_dir, 'usr/bin'))
    bind_or_link('/usr/include', path.join(root_dir, 'usr/include'))
    bind_or_link('/usr/lib', path.join(root_dir, 'usr/lib'))
    bind_or_link('/usr/lib64', path.join(root_dir, 'usr/lib64'))
    bind_or_link('/usr/libexec', path.join(root_dir, 'usr/libexec'))
    bind_mount(in_dir, path.join(root_dir, 'in'))
    bind_mount(out_dir, path.join(root_dir, 'out'), rdonly=False)
    chdir(root_dir)
    mkdir('old_root')
    pivot_root('.', 'old_root')
    umount('old_root', MNT_DETACH)
    rmdir('old_root')
    write_text_file('/etc/passwd', 'icebox:x:1000:1000:icebox:/:/bin/bash\n')
    mount('/', '/', '', MS_BIND | MS_REMOUNT | MS_RDONLY | MS_NOSUID)

    # Execute pickles.
    socket_file = child_socket.makefile('rwb')
    while True:
        try:
            func = cloudpickle.load(socket_file)
        except EOFError:
            exit()
        try:
            ret, err = func(), None
        except Exception as e:
            ret, err = None, e
        data = cloudpickle.dumps((ret, err))
        socket_file.write(pack('I', len(data)))
        socket_file.write(data)
        socket_file.flush()
예제 #30
0
def main():
    parse_passwd()
    h = https("POST", "/api/userify/configure")
    if not h or not getattr(h, "sock"):
        time.sleep(1)
        return main()
    h.sock.settimeout(60)
    response = h.getresponse()
    text = response.read()
    failure = response.status != 200
    if debug or failure:
        print(("%s %s" % (response.status, response.reason)))
    configuration = {"error": "Unknown error parsing configuration"}
    try:
        configuration = json.loads(text.decode('utf-8'))
        if debug:
            pprint(configuration)
        if failure and "error" in configuration:
            print(
                ("%s %s" % (response.reason.upper(), configuration["error"])))
    except Exception as e:
        failure = True
        print(line_spacer)
        print(("Error: %s" % e))
        # traceback.print_exc()
        pprint(text)
        print(line_spacer)
    if failure or "error" in configuration:
        return 180 + 60 * random.random()
    process_users(configuration["users"])
    install_shim_runner()

    # set hostname if set on server
    if "hostname" in configuration:
        try:
            hostname = str(configuration["hostname"])
            if socket.gethostname() != hostname:
                socket.sethostname(hostname)
                open("/etc/hostname", "w").write(hostname + "\n")
                # should set in /etc/hosts as well so
                # that sudo doesn't complain
                hosts = open("/etc/hosts").read().split("\n")
                line = "127.0.0.1 " + hostname + " # set by userify shim"
                if line not in hosts:
                    hosts.insert(1, line)
                    open("/etc/hosts", "w").write("\n").join(hosts)
        except Exception as e:
            print(("Unable to set hostname: %s" % e))

    # take over users if enabled and any are found
    if "takeover_users" in configuration and configuration["takeover_users"]:
        for username in configuration["takeover_users"]:
            if username in system_usernames():
                qexec(["usermod", "-c", "userify-%s" % username, username])

    # disable root SSH login keys if enabled and one exists
    if "disable_root_ssh_key" in configuration and configuration[
            "disable_root_ssh_key"]:
        rootssh = "/root/.ssh/"
        for fname in "authorized_keys", "authorized_keys2":
            if os.path.isfile(rootssh + fname):
                qexec([
                    "/bin/mv", "-f", rootssh + fname,
                    rootssh + "deleted:" + fname
                ])

    return configuration["shim-delay"] if "shim-delay" in configuration else 1