diff options
| author | Michael E Brown <mebrown@michaels-house.net> | 2007-10-18 21:39:52 -0500 |
|---|---|---|
| committer | Michael E Brown <mebrown@michaels-house.net> | 2007-10-18 21:39:52 -0500 |
| commit | 9e820575ac528d562fc9bd207c8674bfed03589d (patch) | |
| tree | b8167af16e4527861c411f10bed5c2837c98940c /src | |
| parent | a9172fdfdf9811cb84626f0a414668cc2ab03dc4 (diff) | |
| download | mock-9e820575ac528d562fc9bd207c8674bfed03589d.tar.gz mock-9e820575ac528d562fc9bd207c8674bfed03589d.tar.xz mock-9e820575ac528d562fc9bd207c8674bfed03589d.zip | |
completely drop privs (real and effective) when running RPM commands. add a bit of infrastructure to mock.util.do() to handle this. Change mock.util.do to not return output by default. No users use the output, and it can be switched on via karg.
Diffstat (limited to 'src')
| -rw-r--r-- | src/py-libs/backend.py | 48 | ||||
| -rw-r--r-- | src/py-libs/util.py | 33 |
2 files changed, 44 insertions, 37 deletions
diff --git a/src/py-libs/backend.py b/src/py-libs/backend.py index 6a190fa..809383d 100644 --- a/src/py-libs/backend.py +++ b/src/py-libs/backend.py @@ -210,6 +210,7 @@ class Root(object): # files in /dev mock.util.rmtree(os.path.join(self.rootdir, "dev")) mock.util.mkdirIfAbsent(os.path.join(self.rootdir, "dev", "pts")) + prevMask = os.umask(0000) os.mknod(os.path.join(self.rootdir, "dev/zero"), stat.S_IFCHR | 0666, os.makedev(1, 5)) os.mknod(os.path.join(self.rootdir, "dev/tty"), stat.S_IFCHR | 0666, os.makedev(5, 0)) os.mknod(os.path.join(self.rootdir, "dev/null"), stat.S_IFCHR | 0666, os.makedev(1, 3)) @@ -219,6 +220,7 @@ class Root(object): os.symlink("/proc/self/fd/0", os.path.join(self.rootdir, "dev/stdin")) os.symlink("/proc/self/fd/1", os.path.join(self.rootdir, "dev/stdout")) os.symlink("/proc/self/fd/2", os.path.join(self.rootdir, "dev/stderr")) + os.umask(prevMask) # set up cache dirs: self._initCache() @@ -292,8 +294,13 @@ class Root(object): srpmBasename = os.path.basename(srpmChrootFilename) # install srpm - env = "HOME=%s" % self.homedir - self.doChroot("rpm -Uvh --nodeps %s" % srpmChrootFilename, env=env) + os.environ["HOME"] = self.homedir + # Completely/Permanently drop privs while running the following: + mock.util.do( + "rpm -Uvh --nodeps %s" % srpmChrootFilename, + chrootPath=self.rootdir, + uidManager=self.uidManager, + ) # rebuild srpm/rpm from SPEC file specs = glob.glob("%s/%s/SPECS/*.spec" % (self.rootdir, self.builddir)) @@ -302,9 +309,13 @@ class Root(object): spec = specs[0] # if there's more than one then someone is an idiot chrootspec = spec.replace(self.rootdir, '') # get rid of rootdir prefix - self.doChroot( + self.root_log.info("about to drop to unpriv mode.") + # Completely/Permanently drop privs while running the following: + mock.util.do( "rpmbuild -bs --target %s --nodeps %s" % (self.target_arch, chrootspec), - env=env, logger=self.build_log, timeout=timeout, output=0 + chrootPath=self.rootdir, + uidManager=self.uidManager, + logger=self.build_log, timeout=timeout, ) rebuiltSrpmFile = glob.glob("%s/%s/SRPMS/*.src.rpm" % (self.rootdir, self.builddir)) @@ -315,28 +326,13 @@ class Root(object): self.installSrpmDeps(rebuiltSrpmFile) #have to permanently drop privs or rpmbuild regains them - # can only do this by forking... self.state("build") - pid = os.fork() - if pid: - # parent - try: - os.waitpid(pid,0) - except: - os.kill(-pid, signal.SIGTERM) - time.sleep(1) - os.kill(-pid, signal.SIGKILL) - - else: - # child - try: - uidManager.dropPrivsForever() - self.doChroot( - "rpmbuild -bb --target %s --nodeps %s" % (self.target_arch, chrootspec), - env=env, logger=self.build_log, timeout=timeout, output=0 - ) - finally: - os._exit(0) + mock.util.do( + "rpmbuild -bb --target %s --nodeps %s" % (self.target_arch, chrootspec), + chrootPath=self.rootdir, + uidManager=self.uidManager, + logger=self.build_log, timeout=timeout, + ) bd_out = self.rootdir + self.builddir rpms = glob.glob(bd_out + '/RPMS/*.rpm') @@ -495,7 +491,7 @@ class Root(object): self.root_log.info(cmd) try: self._callHooks("preyum") - mock.util.do(cmd, output=0) + mock.util.do(cmd) self._callHooks("postyum") except mock.exception.Error, e: self.root_log.exception("Error performing yum command: %s" % cmd) diff --git a/src/py-libs/util.py b/src/py-libs/util.py index 0bca233..868fb41 100644 --- a/src/py-libs/util.py +++ b/src/py-libs/util.py @@ -142,24 +142,19 @@ def uniqReqs(*args): master.extend(l) return rpmUtils.miscutils.unique(master) -@traceLog(log) -def do_interactive(command, *args, **kargs): - # we always assume that we dont care about return code for interactive stuff - os.system(command) - # logger = # output = [1|0] +# chrootPath +# +# Warning: this is the function from hell. :( +# @traceLog(log) -def do(command, timeout=0, raiseExc=True, interactive=0, *args, **kargs): +def do(command, chrootPath=None, timeout=0, raiseExc=True, returnOutput=0, *args, **kargs): """execute given command outside of chroot""" logger = kargs.get("logger", log) logger.debug("Run cmd: %s" % command) - # need to not fork, etc or interactive command wont properly display, so catch it here. - if interactive: - return do_interactive(command, timeout=timeout, raiseExc=raiseExc, *args, **kargs) - class alarmExc(Exception): pass def alarmhandler(signum,stackframe): raise alarmExc("timeout expired") @@ -187,7 +182,7 @@ def do(command, timeout=0, raiseExc=True, interactive=0, *args, **kargs): else: logger.debug(line) - if kargs.get("output",1): + if returnOutput: output += line # close read handle, get child return status, etc @@ -225,6 +220,22 @@ def do(command, timeout=0, raiseExc=True, interactive=0, *args, **kargs): # can kill our children os.setpgrp() + uidManager = kargs.get("uidManager") + + if chrootPath is not None: + if uidManager: + logger.debug("elevate privs to run chroot") + uidManager.becomeUser(0) + os.chdir(chrootPath) + os.chroot(chrootPath) + if uidManager: + logger.debug("back to other privs") + uidManager.restorePrivs() + + if uidManager: + logger.debug("about to drop privs") + uidManager.dropPrivsForever() + child = popen2.Popen4(command) child.tochild.close() |
