def main(): """ The entry point of daemon_factory process """ parser = argparse.ArgumentParser( description='Factory process to manage storlet daemons') parser.add_argument('sbus_path', help='the path to unix domain socket') parser.add_argument('log_level', help='log level') parser.add_argument('container_id', help='container id') opts = parser.parse_args() # Initialize logger logger = get_logger("daemon-factory", opts.log_level, opts.container_id) logger.debug("Daemon factory started") try: SBus.start_logger("DEBUG", container_id=opts.container_id) # Impersonate the swift user pw = pwd.getpwnam('swift') os.setresgid(pw.pw_gid, pw.pw_gid, pw.pw_gid) os.setresuid(pw.pw_uid, pw.pw_uid, pw.pw_uid) # create an instance of daemon_factory factory = StorletDaemonFactory(opts.sbus_path, logger, opts.container_id) # Start the main loop sys.exit(factory.main_loop()) except Exception: logger.eception('Unhandled exception') sys.exit(EXIT_FAILURE)
def __init__(self, user, visitor, token): self.user = user self.visitor = visitor self.token = token if os.geteuid() is 0: os.setresgid(61015, 61015, 61015) os.setresuid(61020, 61020, 61020)
def prepare(suid, slave): if suid is not None: try: if not type(suid) in (int, long): userinfo = pwd.getpwnam(suid) suid = userinfo.pw_uid sgid = userinfo.pw_gid else: userinfo = pwd.getpwuid(suid) sgid = userinfo.pw_gid except: pass try: if slave: path = os.getttyname(slave) os.chown(path, suid) except: pass try: os.initgroups(userinfo.pw_name, sgid) os.chdir(userinfo.pw_dir) except: pass try: os.setresgid(suid, suid, sgid) os.setresuid(suid, suid, sgid) except: pass os.setsid() fcntl.ioctl(sys.stdin, termios.TIOCSCTTY, 0)
def _drop_privs(self): # First get the list of groups to assign. # This *should* generate a list *exactly* like as if that user ran os.getgroups(), # with the addition of self.cfg['build_user']['gid'] (if it isn't included already). newgroups = list( sorted([ g.gr_gid for g in grp.getgrall() if pwd.getpwuid(self.cfg['build_user']['uid']) in g.gr_mem ])) if self.cfg['build_user']['gid'] not in newgroups: newgroups.append(self.cfg['build_user']['gid']) newgroups.sort() # This is the user's "primary group" user_gid = pwd.getpwuid(self.cfg['build_user']['uid']).pw_gid if user_gid not in newgroups: newgroups.append(user_gid) os.setgroups(newgroups) # If we used os.setgid and os.setuid, we would PERMANENTLY/IRREVOCABLY drop privs. # Being that that doesn't suit the meta of the rest of the script (chmodding, etc.) - probably not a good idea. os.setresgid(self.cfg['build_user']['gid'], self.cfg['build_user']['gid'], -1) os.setresuid(self.cfg['build_user']['uid'], self.cfg['build_user']['uid'], -1) # Default on most linux systems. reasonable enough for building? (equal to chmod 755/644) os.umask(0o0022) # TODO: we need a full env construction here, I think, as well. PATH, HOME, GNUPGHOME at the very least? return ()
def EnterSandbox(user: str, group: str) -> None: """Enters the sandbox. Drops root privileges, by changing the user and group. Args: user: New UNIX user name to run as. If empty then the user is not changed. group: New UNIX group name to run as. If empty then the group is not changed. """ if group: gid = grp.getgrnam(group).gr_gid os.setgroups([gid]) if getattr(os, "setresgid", False): # We prefer setresgid if available, which is the case on Linux. # The reason is that it's the most explicit of the various set*id # variants. os.setresgid(gid, gid, gid) else: # This is the same as the above if called by the superuser. os.setgid(gid) if user: uid = pwd.getpwnam(user).pw_uid if getattr(os, "setresuid", False): # We prefer setresuid if available, which is the case on Linux. # The reason is that it's the most explicit of the various set*id # variants. os.setresuid(uid, uid, uid) else: # This is the same as the above if called by the superuser. os.setuid(uid)
def main(argv): """ The entry point of daemon_factory process :param argv: parameters given from command line """ if (len(argv) != 5): usage() return EXIT_FAILURE storlet_name = argv[0] sbus_path = argv[1] log_level = argv[2] pool_size = argv[3] container_id = argv[4] # Initialize logger logger = start_logger("storlets-daemon", log_level, container_id) logger.debug("Storlet Daemon started") SBus.start_logger("DEBUG", container_id=container_id) # Impersonate the swift user pw = pwd.getpwnam('swift') os.setresgid(pw.pw_gid, pw.pw_gid, pw.pw_gid) os.setresuid(pw.pw_uid, pw.pw_uid, pw.pw_uid) # create an instance of storlet daemon try: daemon = Daemon(storlet_name, sbus_path, logger, pool_size) except Exception as e: logger.error(e.message) return EXIT_FAILURE # Start the main loop return daemon.main_loop()
def start(self): serversockets = [] for port in self.ports: s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) try: s.bind(("", port)) except socket.error as e: self.print_error("Could not bind port %s: %s." % (port, e)) sys.exit(1) s.listen(5) serversockets.append(s) del s self.print_info("Listening on port %d." % port) if self.chroot: os.chdir(self.chroot) os.chroot(self.chroot) self.print_info("Changed root directory to %s" % self.chroot) if self.setuid: os.setresgid(self.setuid[1], self.setuid[1], self.setuid[1]) os.setresuid(self.setuid[0], self.setuid[0], self.setuid[0]) self.print_info("Setting uid:gid to %s:%s" % (self.setuid[0], self.setuid[1])) last_aliveness_check = time.time() while True: (iwtd, owtd, ewtd) = select.select( serversockets + [x.socket for x in self.clients.values()], [x.socket for x in self.clients.values() if x.write_queue_size() > 0], [], 10) for x in iwtd: if x in self.clients: self.clients[x].socket_readable_notification() else: (conn, addr) = x.accept() if self.ssl_pem_file: import ssl try: conn = ssl.wrap_socket( conn, server_side=True, certfile=self.ssl_pem_file, keyfile=self.ssl_pem_file) except ssl.SSLError as e: self.print_error( "SSL error for connection from %s:%s: %s" % ( addr[0], addr[1], e)) continue self.clients[conn] = self.client_factory(conn) self.print_info("Accepted connection from %s:%s." % ( addr[0], addr[1])) for x in owtd: if x in self.clients: # client may have been disconnected self.clients[x].socket_writable_notification() now = time.time() if last_aliveness_check + 10 < now: for client in self.clients.values(): client.check_aliveness() last_aliveness_check = now
def inner(*args, **kwargs): # Get sudoer's UID try: sudo_uid = int(os.environ['SUDO_UID']) except (KeyError, ValueError): print("Could not get UID for sudoer", file=sys.stderr) return # Get sudoer's GID try: sudo_gid = int(os.environ['SUDO_GID']) except (KeyError, ValueError): print("Could not get GID for sudoer", file=sys.stderr) return # Make sure groups are reset try: os.setgroups([]) except PermissionError: pass # Drop root os.setresgid(sudo_gid, sudo_gid, -1) os.setresuid(sudo_uid, sudo_uid, -1) # Execute function ret = function(*args, **kwargs) # Get root back os.setresgid(0, 0, -1) os.setresuid(0, 0, -1) return ret
def _unmount_as_user_fstab_fail(self, pipe, uid, gid, device): """ Try to unmount @device as user with given @uid and @gid. @device shouldn't be listed in /etc/fstab when running this, so this is expected to fail. """ os.setresgid(gid, gid, gid) os.setresuid(uid, uid, uid) # try to mount the device -- it should fail try: safe_dbus.call_sync(self.iface_prefix, self.path_prefix + '/block_devices/' + os.path.basename(device), self.iface_prefix + '.Filesystem', 'Unmount', GLib.Variant('(a{sv})', ({},))) except Exception as e: msg = 'GDBus.Error:org.freedesktop.UDisks2.Error.NotAuthorizedCanObtain: Not authorized to perform operation' if msg in str(e): pipe.send([True, '']) pipe.close() return else: pipe.send([False, 'Unmount DBus call failed with unexpected exception: %s' % str(e)]) pipe.close() return ret, _out = self.run_command('grep \"%s\" /proc/mounts' % device) if ret == 0: pipe.send([False, 'Unmount DBus call didn\'t fail but %s seems to be still mounted.' % device]) pipe.close() return else: pipe.send([False, '%s was unmounted for UID %d without proper record in fstab' % (device, uid)]) pipe.close() return
def demote_subprocess(): """ Lower the privileges of the spawned subprocess by setting limits on its resource use and by switching it to be run as another user. NOTE: The resource limits were set by using ulimit and shell=True before. This was changed in order to address security questions raised by using the shell and to make passing arguments easier. """ #info("Demoting subprocess.") # Set resource limits resource.setrlimit(resource.RLIMIT_NPROC, (10, 10)) # Prevent fork bombs resource.setrlimit(resource.RLIMIT_NOFILE, (50, 50)) # Limit number of files resource.setrlimit(resource.RLIMIT_FSIZE, (500*1024, 500*1024)) # Limit space used by a file resource.setrlimit(resource.RLIMIT_CPU, (2, 2)) # Limit CPU time # Change the group and user IDs to lower privileged ones user_gid = Privileges.get_low_gid() user_uid = Privileges.get_low_uid() try: os.setresgid(user_gid, user_gid, user_gid) os.setresuid(user_uid, user_uid, user_uid) except OSError: #error("Unable to demote the subprocess to uid: %d, gid: %d!" % (user_uid, user_gid)) pass else: #info("Successfully demoted the subprocess to uid: %d, gid: %d." % (user_uid, user_gid)) pass
def main(argv): """ The entry point of daemon_factory process :param argv: parameters given from command line """ if (len(argv) != 3): usage() # TODO(takashi): returning non-zero value is better? return pipe_path = argv[0] log_level = argv[1] container_id = argv[2] # Initialize logger logger = start_logger("daemon_factory", log_level, container_id) logger.debug("Daemon factory started") SBus.start_logger("DEBUG", container_id=container_id) # Impersonate the swift user pw = pwd.getpwnam('swift') os.setresgid(pw.pw_gid, pw.pw_gid, pw.pw_gid) os.setresuid(pw.pw_uid, pw.pw_uid, pw.pw_uid) # create an instance of daemon_factory factory = daemon_factory(pipe_path, logger) # Start the main loop factory.main_loop(container_id)
def root_privileges_drop(): if (os.geteuid() == 0 and 'SUDO_GID' in os.environ and 'SUDO_UID' in os.environ): sudo_gid = int(os.environ['SUDO_GID']) sudo_uid = int(os.environ['SUDO_UID']) os.setresgid(sudo_gid, sudo_gid, -1) os.setresuid(sudo_uid, sudo_uid, -1)
def runfastcgi(argset=[], **kwargs): options = FASTCGI_OPTIONS.copy() options.update(kwargs) for x in argset: if '=' in x: k, v = x.split('=', 1) else: k, v = x, True options[k.lower()] = v if 'help' in options: return fastcgi_help() if 'run_as' in options: from pwd import getpwnam try: pw = getpwnam(options['run_as']) except KeyError: pw = None if pw: os.setresgid(pw.pw_gid, pw.pw_gid, pw.pw_gid) os.setresuid(pw.pw_uid, pw.pw_uid, pw.pw_uid) try: import flup except ImportError, e: print >> sys.stderr, 'ERROR: %s' % e print >> sys.stderr, ' Unable to load the flup package. In order to run pyzzle' print >> sys.stderr, ' as a FastCGI application, you will need to get flup from' print >> sys.stderr, " http://www.saddi.com/software/flup/ If you've already" print >> sys.stderr, ' installed flup, then make sure you have it in your PYTHONPATH.' return False
def drop_privileges(user, group): if user is None: uid = os.getuid() elif user.lstrip("-").isdigit(): uid = int(user) else: uid = pwd.getpwnam(user).pw_uid if group is None: gid = os.getgid() elif group.lstrip("-").isdigit(): gid = int(group) else: gid = grp.getgrnam(group).gr_gid username = pwd.getpwuid(uid).pw_name # groupname = grp.getgrgid(gid).gr_name groups = [g for g in grp.getgrall() if username in g.gr_mem] os.setgroups(groups) if hasattr(os, 'setresgid'): os.setresgid(gid, gid, gid) else: os.setregid(gid, gid) if hasattr(os, 'setresuid'): os.setresuid(uid, uid, uid) else: os.setreuid(uid, uid)
def _mount_as_user_fstab(self, pipe, uid, gid, device): """ Try to mount and then unmount @device as user with given @uid and @gid. @device should be listed in /etc/fstab with proper options so user is able to run these operations and this shouldn't fail. """ os.setresgid(gid, gid, gid) os.setresuid(uid, uid, uid) # try to mount the device try: safe_dbus.call_sync(self.iface_prefix, self.path_prefix + '/block_devices/' + os.path.basename(device), self.iface_prefix + '.Filesystem', 'Mount', GLib.Variant('(a{sv})', ({},))) except Exception as e: pipe.send([False, 'Mount DBus call failed: %s' % str(e)]) pipe.close() return ret, out = self.run_command('grep \"%s\" /proc/mounts' % device) if ret != 0: pipe.send([False, '%s not mounted' % device]) pipe.close() return if 'uid=%s,gid=%s' % (uid, gid) not in out: pipe.send([False, '%s not mounted with given uid/gid.\nMount info: %s' % (device, out)]) pipe.close() return pipe.send([True, '']) pipe.close() return
def debug_server(self, shared_queue): self.read_configuration() uid = int(self.server_uid) if os.getuid() != uid: os.setresuid(uid, uid, uid) gid = int(self.server_gid) if os.getgid() != gid: os.setresgid(gid, gid, gid) for key in self.env: debug("Setting environment variable %s=%s" % (key, self.env[key])) os.putenv(key, self.env[key]) if self.pre_command is not None: os.system(self.pre_command) crash = None for i in range(0,3): try: crash = self.launch_debugger(self.timeout, self.command, "") break except: log("Exception: %s" % sys.exc_info()[1]) continue if self.post_command is not None: os.system(self.post_command) if crash is not None: self.crash_info = crash shared_queue.put(crash) return True return False
def main(): os.open('/bin/bash', os.O_RDONLY) fd = os.open('./flag', os.O_RDONLY) os.dup2(fd, 9) path = os.path.join('/tmp', secrets.token_hex(16)) data = os.read(0, 0x10) os.close(0) check_input(data) fd = os.open(path, os.O_CREAT | os.O_RDWR, 0o777) os.write(fd, b'#!/d' + data) os.close(fd) pid = os.fork() if pid == 0: os.setresgid(NOGROUP, NOGROUP, NOGROUP) os.setresuid(NOBODY, NOBODY, NOBODY) try: os.execv(path, [path]) except: os._exit(-1) else: os.waitpid(pid, 0) os.unlink(path)
def _unmount_as_user_fstab(self, pipe, uid, gid, device): """ Try to unmount @device as user with given @uid and @gid. @device should be listed in /etc/fstab with "users" option when running this, so this is expected to succeed. """ os.setresgid(gid, gid, gid) os.setresuid(uid, uid, uid) # try to unmount the device try: safe_dbus.call_sync(self.iface_prefix, self.path_prefix + '/block_devices/' + os.path.basename(device), self.iface_prefix + '.Filesystem', 'Unmount', GLib.Variant('(a{sv})', ({},))) except Exception as e: pipe.send([False, 'Unmount DBus call failed: %s' % str(e)]) pipe.close() return ret, _out = self.run_command('grep \"%s\" /proc/mounts' % device) if ret == 0: pipe.send([False, 'Unmount DBus call didn\'t fail but %s seems to be still mounted.' % device]) pipe.close() return else: pipe.send([True, '']) pipe.close() return
def main(argv): ''' @summary: main The entry point. - Initialize logger, - impersonate to swift user, - create an instance of daemon_factory, - start the main loop. ''' if (len(argv) != 2): usage() return pipe_path = argv[0] log_level = argv[1] logger = start_logger("daemon_factory", log_level) logger.debug("Daemon factory started") SBus.start_logger("DEBUG") # Impersonate the swift user pw = pwd.getpwnam('swift') os.setresgid(pw.pw_gid,pw.pw_gid,pw.pw_gid) os.setresuid(pw.pw_uid,pw.pw_uid,pw.pw_uid) factory = daemon_factory(pipe_path, logger) factory.main_loop()
def runfastcgi(app, argset=[], **kwargs): options = FASTCGI_OPTIONS.copy() options.update(kwargs) for x in argset: if '=' in x: k, v = x.split('=', 1) else: k, v = x, True options[k.lower()] = v if 'help' in options: return fastcgi_help() if 'run_as' in options: from pwd import getpwnam try: pw = getpwnam(options['run_as']) except KeyError: pw = None if pw: os.setresgid(pw.pw_gid, pw.pw_gid, pw.pw_gid) os.setresuid(pw.pw_uid, pw.pw_uid, pw.pw_uid) try: import flup except ImportError, e: print >> sys.stderr, 'ERROR: %s' % e print >> sys.stderr, ' Unable to load the flup package. In order to run rsted' print >> sys.stderr, ' as a FastCGI application, you will need to get flup from' print >> sys.stderr, " http://www.saddi.com/software/flup/ If you've already" print >> sys.stderr, ' installed flup, then make sure you have it in your PYTHONPATH.' return False
def _demoted_child_call(uid, gid, ret_data_q, func): """Call a function/method with different uid/gid""" # Set UID and GID if gid and gid > 0: try: os.setresgid(gid, gid, gid) except OSError as err: ret_data_q.put(GbpServiceError("Setting GID (%s) failed: %s" % (gid, err))) sys.exit(_RET_FORK_ERR) if uid and uid > 0: try: os.setresuid(uid, uid, uid) except OSError as err: ret_data_q.put(GbpServiceError("Setting UID (%s) failed: %s" % (uid, err))) sys.exit(_RET_FORK_ERR) try: # Set environment os.environ['HOME'] = pwd.getpwuid(uid).pw_dir except KeyError: pass # Call the function try: # Func must be a callable without arguments ret = func() # pylint: disable=broad-except except Exception as err: ret_data_q.put(GbpChildBTError()) sys.exit(_RET_FORK_ERR) # pylint: enable=broad-except else: ret_data_q.put(ret) sys.exit(_RET_FORK_OK)
def set_user_context(user_details: dict) -> None: os.setgroups(user_details['grouplist']) os.setresgid(user_details['pw_gid'], user_details['pw_gid'], user_details['pw_gid']) os.setresuid(user_details['pw_uid'], user_details['pw_uid'], user_details['pw_uid']) if any(c() != v for c, v in ( (os.getuid, user_details['pw_uid']), (os.geteuid, user_details['pw_uid']), (os.getgid, user_details['pw_gid']), (os.getegid, user_details['pw_gid']), )): raise Exception( f'Unable to set user context to {user_details["pw_name"]!r} user') try: os.chdir(user_details['pw_dir']) except Exception: os.chdir('/var/empty') os.environ.update({ 'HOME': user_details['pw_dir'], 'PATH': '/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:/root/bin', })
def debug_server(self, shared_queue): self.read_configuration() uid = int(self.server_uid) if os.getuid() != uid: os.setresuid(uid, uid, uid) gid = int(self.server_gid) if os.getgid() != gid: os.setresgid(gid, gid, gid) for key in self.env: debug("Setting environment variable %s=%s" % (key, self.env[key])) os.putenv(key, self.env[key]) if self.pre_command is not None: os.system(self.pre_command) crash = None for i in range(0, 3): try: crash = self.launch_debugger(self.timeout, self.command, "") break except: log("Exception: %s" % sys.exc_info()[1]) continue if self.post_command is not None: os.system(self.post_command) if crash is not None: self.crash_info = crash shared_queue.put(crash) return True return False
def _drop_priv(username): pw = pwd.getpwnam(username) groups = list(set([ g.gr_gid for g in grp.getgrall() if pw.pw_name in g.gr_mem ] + [ pw.pw_gid])) os.setgroups(groups) os.setresgid(pw.pw_gid, pw.pw_gid, pw.pw_gid) os.setresuid(pw.pw_uid, pw.pw_uid, pw.pw_uid)
def drop_privileges(): try: uid = os.getuid() gid = os.getgid() os.setresgid(gid, gid, gid) os.setresuid(uid, uid, uid) except: die('Unable to drop privileges')
def preexec(): try: os.setresgid(1000, 1000, 1000) os.setresuid(1000, 1000, 1000) os.makedirs(home, 0o755, exist_ok=True) os.chdir(home) except e: print(e)
def __exit__(self, exc_type: Optional[Type[BaseException]], exc_value: Optional[BaseException], traceback: Optional[TracebackType]) -> None: os.umask(self.current_mask) unprivileged_uid = os.getresuid()[2] # retrieve saved-set-UID unprivileged_gid = os.getresgid()[2] # retrieve saved-set-GID os.setresuid(unprivileged_uid, unprivileged_uid, 0) os.setresgid(unprivileged_gid, unprivileged_gid, 0)
def __init__(self, user, visitor): uid = 61060 gid = 60000 # To access person and transfer db self.user = user self.visitor = visitor self.token = get_token(user) os.setresgid(gid, gid, gid) os.setresuid(uid, uid, uid)
def drop_privileges(uid_spec=None, uid=None, gid=None): if uid_spec: assert not (uid or gid), [uid_spec, uid, gid] uid, gid = parse_uid_spec(uid_spec) assert uid is not None and gid is not None, [uid_spec, uid, gid] os.setresgid(gid, gid, gid) os.setresuid(uid, uid, uid) log.debug('Switched uid/gid to %s:%s', uid, gid)
def __init__(self, user, visitor): self.user = user self.visitor = visitor credDb = zoodb.cred_setup() cred = credDb.query(zoodb.Cred).get(self.user) self.token = cred.token os.setresgid(61013, 61013, 61013) os.setresuid(61014, 61014, 61014)
def __set_unprivileged_user(): """ Set the real and effective user and group to an unprivileged user. """ _, _, uid, gid, _, _, _ = pwd.getpwnam('enarksh') os.setresgid(gid, gid, 0) os.setresuid(uid, uid, 0)
def setresgid(space, rgid, egid, sgid): """ setresgid(rgid, egid, sgid) Set the current process's real, effective, and saved group ids. """ try: os.setresgid(rgid, egid, sgid) except OSError as e: raise wrap_oserror(space, e)
def _change_privileges(root): gid = 0 if root else int(os.getenv('SUDO_GID')) uid = 0 if root else int(os.getenv('SUDO_UID')) if not root and uid == 0: raise Exception('Rights weren\'t changed!') os.setresgid(gid, gid, -1) os.setresuid(uid, uid, -1)
def __enter__(self) -> Tuple[int, int]: current_uid = os.geteuid() current_gid = os.getegid() if current_uid == 0 or current_gid == 0: raise CosmkError("nested privileges elevations do not work") os.setresgid(0, 0, current_gid) # GID before UID otherwise this fails os.setresuid(0, 0, current_uid) self.current_mask = os.umask(0o022) return (current_uid, current_gid)
def restore_user_group(self): try: (ruid, euid, suid) = os.getresuid() (rgid, egid, sgid) = os.getresgid() os.setresuid(suid, suid, suid) os.setresgid(sgid, sgid, sgid) except Exception, e: log.error("Error: %s" % e) exit(1)
def down_permissions(self): """ Drop our current permissions """ try: os.setresgid(self.down_gid, self.down_gid, 0) os.setresuid(self.down_uid, self.down_uid, 0) os.environ['HOME'] = self.home_dir except Exception as e: print("Failed to drop permissions: {}".format(e)) return False return True
def up_permissions(self): """ Elevate our current permissions """ try: os.setresuid(0, 0, 0) os.setresgid(0, 0, 0) os.environ['HOME'] = '/root' except Exception as e: print("Failed to raise permissions: {}".format(e)) return False return True
def drop_privileges(uid_spec=None, uid=None, gid=None, log=None): if log is False: log = lambda *a,**k: None elif log is None: log = logging.getLogger('fgc.sh.drop_privileges') if uid_spec: assert not (uid or gid), [uid_spec, uid, gid] uid, gid = parse_uid_spec(uid_spec) assert uid is not None and gid is not None, [uid_spec, uid, gid] os.setresgid(gid, gid, gid) os.setresuid(uid, uid, uid) log.debug('Switched uid/gid to %s:%s', uid, gid)
def _injectBackup(self): try: destination = self._get_volume_path() except RuntimeError as e: return (1, str(e)) # NFS mounts using root_squash will fail if accessed with root user. # Dropping root privileges and moving to vdsm user. prev_xdg_runtime_dir = os.getenv('XDG_RUNTIME_DIR', None) try: os.setresgid(self._parent.environment[ohostedcons.VDSMEnv.KVM_GID], self._parent.environment[ohostedcons.VDSMEnv.KVM_GID], -1) os.setresuid( self._parent.environment[ohostedcons.VDSMEnv.VDSM_UID], self._parent.environment[ohostedcons.VDSMEnv.VDSM_UID], -1) # $XDG_RUNTIME_DIR is not set if the current user is not the # original user of the session os.unsetenv('XDG_RUNTIME_DIR') except OSError as os_err: self._parent.logger.error('Unable to drop root privileges') self._parent.logger.debug('exception', exc_info=True) raise os_err try: g = guestfs.GuestFS(python_return_dict=True) g.set_backend('direct') g.add_drive_opts(filename=destination, format='raw', readonly=0) self.logger.debug( 'disk added from {path}'.format(path=destination)) try: g.launch() self._parent.logger.debug('guestfs launched') g.mount('/dev/sda1', '/') self._parent.logger.debug('disk mounted') g.upload( self._backup_src, self._parent.environment[ ohostedcons.Upgrade.DST_BACKUP_FILE]) self._parent.logger.debug('backup file uploaded') g.umount('/') self._parent.logger.debug('disk unmounted') finally: g.shutdown() finally: g.close() try: # regain root privileges os.setresgid(0, 0, -1) os.setresuid(0, 0, -1) if prev_xdg_runtime_dir: os.environ['XDG_RUNTIME_DIR'] = prev_xdg_runtime_dir except OSError as os_err: self._parent.logger.error('Unable to regain root privileges') self._parent.logger.debug('exception', exc_info=True) raise os_err return (0, 'OK')
def _restore_privs(self): os.setresuid(self.cfg['orig_user']['uid'], self.cfg['orig_user']['uid'], self.cfg['orig_user']['uid']) os.setresgid(self.cfg['orig_user']['gid'], self.cfg['orig_user']['gid'], self.cfg['orig_user']['gid']) os.setgroups(self.cfg['orig_user']['groups']) os.umask(self.cfg['orig_user']['umask']) # TODO: if we change the env, we need to change it back here. I capture it in self.cfg['orig_user']['env']. return ()
def _setuid(): """ Drop root: switch to UID 1000. Why call this? Because Linux gives special capabilities to root (even after we drop privileges). ref: man setresuid(2) """ os.setresuid(1000, 1000, 1000) os.setresgid(1000, 1000, 1000)
def start_job(self): self.__log_job_start() # Create pipes for stdout and stderr. pipe_stdout = os.pipe() pipe_stderr = os.pipe() self.__child_pid = os.fork() if self.__child_pid == 0: # Child process. try: # Close the read ends from the pipes. os.close(pipe_stdout[0]) os.close(pipe_stderr[0]) # Duplicate stdout and stderr on the pipes. sys.stdout.flush() sys.stderr.flush() os.dup2(pipe_stdout[1], sys.stdout.fileno()) os.dup2(pipe_stderr[1], sys.stderr.fileno()) # Set the effective user and group. if self.__user_name in self.__allowed_users: _, _, uid, gid, _, _, _ = pwd.getpwnam(self.__user_name) os.setuid(0) os.setresgid(gid, gid, gid) os.setresuid(uid, uid, uid) else: raise RuntimeError("Spanner is not allowed to start processes under user '%s'." % self.__user_name) # Set variable for subprocess. os.putenv('ENK_RND_ID', str(self.__rnd_id)) os.putenv('ENK_SCH_ID', str(self.__sch_id)) # Replace this child process with the actual job. os.execv(self.__args[0], self.__args) except Exception as e: self.__log.error('Unable to start job') self.__log.error('Reason: {}'.format(str(e))) self.__log.exception('Error') # Exit immediately without running the exit handlers (e.g. from daemon) from the parent process. os._exit(-1) else: # Parent process. # Close the write ends from the pipes. os.close(pipe_stdout[1]) os.close(pipe_stderr[1]) # Remember the fds for reading the stdout and stderr from the child process. self.__stdout = pipe_stdout[0] self.__stderr = pipe_stderr[0]
def _mount_as_user_fstab(self, pipe, uid, gid, device): """ Try to mount and then unmount @device as user with given @uid and @gid. @device should be listed in /etc/fstab with proper options so user is able to run these operations and this shouldn't fail. """ os.setresgid(gid, gid, gid) os.setresuid(uid, uid, uid) # try to mount the device try: safe_dbus.call_sync(self.iface_prefix, self.path_prefix + '/block_devices/' + os.path.basename(device), self.iface_prefix + '.Filesystem', 'Mount', GLib.Variant('(a{sv})', ({},))) except Exception as e: pipe.send([False, 'Mount DBus call failed: %s' % str(e)]) pipe.close() return ret, out = self.run_command('grep \"%s\" /proc/mounts' % device) if ret != 0: pipe.send([False, '%s not mounted' % device]) pipe.close() return if 'uid=%s,gid=%s' % (uid, gid) not in out: pipe.send([False, '%s not mounted with given uid/gid.\nMount info: %s' % (device, out)]) pipe.close() return # and now try to unmount it try: safe_dbus.call_sync(self.iface_prefix, self.path_prefix + '/block_devices/' + os.path.basename(device), self.iface_prefix + '.Filesystem', 'Unmount', GLib.Variant('(a{sv})', ({},))) except Exception as e: pipe.send([False, 'Unmount DBus call failed: %s' % str(e)]) pipe.close() return ret, _out = self.run_command('grep \"%s\" /proc/mounts' % device) if ret == 0: pipe.send([False, '%s mounted after unmount called' % device]) pipe.close() return pipe.send([True, '']) pipe.close() return
def drop_privileges_save(): """Drop the real UID/GID as well, and hide them in saved IDs.""" # At the moment, we only know how to handle this when effective # privileges were already dropped. assert _dropped_privileges is not None and _dropped_privileges > 0 uid = os.environ.get('SUDO_UID') gid = os.environ.get('SUDO_GID') if uid is not None: uid = int(uid) set_groups_for_uid(uid) if gid is not None: gid = int(gid) os.setresgid(gid, gid, 0) if uid is not None: os.setresuid(uid, uid, 0)
def launch_sequence(): print "Creating resource directories." for resource in resources.values(): if not os.path.exists(resource.path): print "Creating: %s" % resource.path os.mkdir(resource.path) print "Setting permissions on resources." for resource in resources.values(): uid, gid = resource.uid, resource.gid for leaf in os.listdir(resource.path) + ["."]: path = resource.path + "/" + leaf # Set the owner bits. os.chown(path, uid, gid) # Set the permission bits. if os.path.isdir(path): # Justification: os.chmod(path, 0750) # rwxr-x--- else: os.chmod(path, 0640) # rw-r----- wait_list = [] for process in processes.values(): print "Spawning", process.name # Delete the RPC resource socket, if there happens to be an old one sitting around. # XXX: This code knows about the convention of rpc/Service/sock! if process.rpc_resource != None: if os.path.exists(process.rpc_resource.path + "/sock"): os.unlink(process.rpc_resource.path + "/sock") pid = os.fork() if pid == 0: # Change into the dryer21 directory. os.chdir("/dryer21") # Drop permissions. os.setresgid(NO_PRIVS, NO_PRIVS, NO_PRIVS) os.setgroups(process.groups) os.setresuid(process.uid, process.uid, process.uid) # Now launch python on the given script. os.execve("/usr/bin/python", ["python", process.binary_path] + process.arguments, {"HOME": "/nonexistant", "PYTHONPATH": "/dryer21/code"}) else: # Wait for the child to finish setting up, if it has an rpc_resource. # This is necessary to prevent race conditions where future processes try to connect before this one is done setting up. if process.rpc_resource != None: # Currently I just use a little spin loop, which is good enough -- I'm not going to use inotify. while not os.path.exists(process.rpc_resource.path + "/sock"): time.sleep(0.1) wait_list.append(pid) for pid in wait_list: os.waitpid(pid, 0) print "Exiting."
def act(act_as): srv_uid = Privileges.get_high_uid() srv_gid = Privileges.get_high_gid() sp_uid = Privileges.get_low_uid() sp_gid = Privileges.get_low_gid() try: if act_as == "server": os.setresgid(srv_gid, sp_gid, srv_gid) os.setresuid(srv_uid, sp_uid, srv_uid) elif act_as == "subprocess": os.setresgid(srv_gid, sp_gid, sp_gid) os.setresuid(srv_uid, sp_uid, sp_uid) except OSError: error("Unable to set effective user rights as %s!" % (act_as)) else: info("Effective user: %s." % (act_as))
def demote_server(): srv_uid = Privileges.get_high_uid() srv_gid = Privileges.get_high_gid() srv_name = Privileges.get_high_name() sp_uid = Privileges.get_low_uid() sp_gid = Privileges.get_low_gid() # Demote the server to server_uid, but allow further demotion to sp_uid try: # http://stackoverflow.com/a/6037494 os.setresgid(srv_gid, sp_gid, sp_gid) os.setresuid(srv_uid, sp_uid, sp_uid) except OSError: error("Losing privileges not permitted.") else: info("Demoted the server process to user %s (%d) and group %d." % (srv_name, srv_uid, srv_gid))
def _ReExecuteIfNeeded(argv, network): """Re-execute as root so we can unshare resources.""" if os.geteuid() != 0: cmd = ['sudo', '-E', 'HOME=%s' % os.environ['HOME'], 'PATH=%s' % os.environ['PATH'], '--'] + argv os.execvp(cmd[0], cmd) else: cgroups.Cgroup.InitSystem() namespaces.SimpleUnshare(net=not network, pid=True) # We got our namespaces, so switch back to the user to run the tests. gid = int(os.environ.pop('SUDO_GID')) uid = int(os.environ.pop('SUDO_UID')) user = os.environ.pop('SUDO_USER') os.initgroups(user, gid) os.setresgid(gid, gid, gid) os.setresuid(uid, uid, uid) os.environ['USER'] = user
def drop_privileges(): """ Drop all the privileges that can be reasonably dropped. This is to prevent the forked process from harming its creator and from accessing any data belonging to the evaluation server process exclusively. For more information, review: - http://man7.org/linux/man-pages/man2/setresuid.2.html - https://docs.python.org/3/library/os.html#os.setresuid """ # Drop the real, effective and saved group and user ids try: os.setresgid(student_gid, student_gid, student_gid) os.setresuid(student_uid, student_uid, student_uid) except OSError: print("Unable to drop privileges to GID: (r:{s_gid}, e:{s_gid}, s:{s_gid}), UID: (r:{s_uid}, e:{s_uid}, s:{s_uid})". format(s_gid=student_gid, s_uid=student_uid))
def drop_privileges(user, group): """Drop privileges to specified user and group""" if group is not None: import grp gid = grp.getgrnam(group).gr_gid logger.debug("Dropping privileges to group {0}/{1}".format(group, gid)) try: os.setresgid(gid, gid, gid) except AttributeError: os.setregid(gid, gid) if user is not None: import pwd uid = pwd.getpwnam(user).pw_uid logger.debug("Dropping privileges to user {0}/{1}".format(user, uid)) try: os.setresuid(uid, uid, uid) except AttributeError: os.setreuid(uid, uid)
def _do_callable( runnable ): "changes the user and group id of the process" ret = None exc = None exc_traceback = None stdout = '' try: # catch streams: with capture.StreamCapture() as output: os.setresuid( runnable.uid,runnable.uid,runnable.uid ) os.setresgid( runnable.gid,runnable.gid,runnable.gid ) ret = runnable.callable( *(runnable.args), **(runnable.kwargs) ) stdout = '\n'.join( output.getvalue() ) except: exc_type, exc, exc_traceback = sys.exc_info() ret = None return RunResult( ret, exc, stdout ) # must be pickle-able, as it will travel between processes