-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Hello all,

I was poking around in the mock source last week and did some minor
refactoring, a couple of name-changes and tried out the rpmlint
request. Attached below is a CVS diff of my mock.py with the head of
CVS. Please review and comment. A quick summary of the changes:

1. Changed version to 0.7.
2. Added code to avoid exec'ing mount for proc, sys, and dev/pts if
we've already done it
3. Oh yeah, added /sys to chroot mount
4. Refactoring: renamed _mount to _mountall, created _mount routine
that is called by _mountall
5. Renamed _umount_by_file to _umountall
6. Added code to run rpmlint
7. Added elevate/drop around raw chroot command

I'd especially like some thought on #7, since any time you elevate and
drop you can introduce a security hole and I freely admit that I'm not
always thinking security first.

If I don't get any push-back (or if I do and then get things
resolved), I'll commit these later this week.

Clark

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.4 (GNU/Linux)
Comment: Using GnuPG with Fedora - http://enigmail.mozdev.org

iD8DBQFEu6y9Hyuj/+TTEp0RAgumAJ9STO3Qc/7Ca4xYNdIAifcKs4oPvACgqpDD
zOm5eNJ1Gwsgc4KqhS8WW0s=
=0mBy
-----END PGP SIGNATURE-----

Index: mock.py
===================================================================
RCS file: /cvs/fedora/mock/mock.py,v
retrieving revision 1.55
diff -u -r1.55 mock.py
--- mock.py	17 Jul 2006 15:04:00 -0000	1.55
+++ mock.py	17 Jul 2006 15:15:16 -0000
@@ -31,7 +31,7 @@
 
 from optparse import OptionParser
 
-__VERSION__ = '0.6'
+__VERSION__ = '0.7'
 
 def error(msg):
     print >> sys.stderr, msg
@@ -162,12 +162,18 @@
         cfgout.write('statedir = %s\n' % self.statedir)
         cfgout.flush()
         cfgout.close()
-    
+
+        # note that we haven't mounted anything (yet)
+        self._mounted = 0
+        self.run_rpmlint = config['run_rpmlint']
+
     def elevate(self):
+        "elevate privileges by changing to privileged uid"
         self.debug("elevate: setting uid to %d" % self.highuid)
         os.setreuid(self.highuid, self.lowuid)
 
     def drop(self):
+        "drop privileges by changing to unprivileged uid"
         self.debug("drop: setting uid to %d" % self.lowuid)
         os.setreuid(self.lowuid, self.highuid)
         
@@ -293,7 +299,7 @@
         # mock-helper yum --installroot=rootdir cmd
         basecmd = '%s --installroot %s' % (self.config['yum'], self.rootdir)
         
-        self._mount() # check it again        
+        self._mountall() # check it again        
         command = '%s %s' % (basecmd, cmd)
         self.debug("yum: command %s" % command)
 
@@ -308,7 +314,7 @@
         """take an srpm, install it, rebuild it to srpm, 
            return chroot-local path to the resulting srpm"""
         
-        self._mount() # check it again
+        self._mountall() # check it again
         bd_out = '%s%s' % (self.rootdir, self.builddir)
         # init build_dir
         self._build_dir_setup()
@@ -366,6 +372,10 @@
             
             arg_string = arg_string + " " + "'%s'" % item
 
+        # if running rpmlint add it to the transaction set
+        if self.run_rpmlint:
+            arg_string = arg_string + " 'rpmlint'"
+
         # everything exists, okay, install them all.
         # pass build reqs (as strings) to installer
         if arg_string != "":
@@ -412,13 +422,24 @@
         for item in packages:
             shutil.copy2(item, self.resultdir)
         
+        if self.run_rpmlint:
+            self.rpmlint(packages)
 
-
+    def rpmlint(self, packages):
+        """Run the rpmlint utility on the list of input packages and append the output
+        to an rpmlint log file"""
+        cmd = "rpmlint -iv %s" % " ".join(packages)
+        (retval, output) = self.do_elevated(cmd)
+        lintlog = open(os.path.join(self.resultdir, "rpmlint.log"), "w+")
+        lintlog.write(output)
+        lintlog.close()
+        return (retval, output)
+    
     def close(self):
         """unmount things and clean up a bit"""
         self.root_log("Cleaning up...")
         self.state("ending")
-        self._umount_by_file()
+        self._umountall()
         self._build_log.close()
         self.state("done")
         self.root_log("Done.")
@@ -438,45 +459,43 @@
             except OSError, e:
                 raise Error, "Could not create dir %s. Error: %s" % (path, e)
 
-    def _mount(self):
-        """mount proc and devpts into chroot"""
+    def _mount(self, type, device, path):
+        "mount a device, given a filesystem type and a path"
+        mntpath = os.path.join(self.rootdir, path)
+        self._ensure_dir(mntpath)
+        self.debug("mounting %s as %s" % (device, mntpath))
+        command = '%s -n -t %s %s %s' % (self.config['mount'], type, device, mntpath)
         mf = os.path.join(self.statedir, 'mounted-locations')
-        track = open(mf, 'w+')
-
-        # make the procdir if we don't have it
-        # mount up proc
-        procdir = os.path.join(self.rootdir, 'proc')
-        self._ensure_dir(procdir)
-
-        self.debug("mounting proc in %s" % procdir)
-        command = '%s -n -t proc proc %s/proc' % (self.config['mount'], 
-                                               self.rootdir)
-        track.write('proc\n')
         (retval, output) = self.do_elevated(command)
-        track.flush()
-        
         if retval != 0:
             if output.find('already mounted') == -1: # probably won't work in other LOCALES
-                error("could not mount proc error was: %s" % output)
-        
-        # devpts
-        # 
-        devptsdir = os.path.join(self.rootdir, 'dev/pts')
-        self._ensure_dir(devptsdir)
-        self.debug("mounting devpts in %s" % devptsdir)
-        command = '%s -n -t devpts devpts %s' % (self.config['mount'], devptsdir)
-        track.write('dev/pts\n')
-        (retval, output) = self.do_elevated(command)
-        track.flush()
+                estr = "could not mount %s. Error was: %s" % (path, output)
+                error(estr)
+                raise RootError, estr
+        track = open(mf, 'w+')
+        track.write('%s\n' % path)
         track.close()
-
-        if retval != 0:
-            if output.find('already mounted') == -1: # probably won't work in other LOCALES
-                raise RootError, "could not mount /dev/pts error was: %s" % output
         
+    def _mountall(self):
+        """mount proc, sys and devpts into chroot"""
+
+        # if we've already mounted these guys, then just return
+        if self._mounted:
+            return
+
+        # mount /proc
+        self._mount('proc', 'proc', 'proc')
+
+        # mount /dev/pts
+        self._mount('devpts', 'dev/pts', 'dev/pts')
+
+        # mount /sys (if we're on a 2.6 kernel)
+        if os.uname()[2].find('2.6') == 0:
+            self._mount('sysfs', 'sys', 'sys')
+
+        self._mounted = 1
 
     def _umount(self, path):
-    
         item = '%s/%s' % (self.rootdir, path)
         command = '%s -n %s' % (self.config['umount'], item)
         (retval, output) = self.do_elevated(command)
@@ -486,8 +505,9 @@
                 raise RootError, "could not umount %s error was: %s" % (path, output)
 
     
-    def _umount_by_file(self):
-                
+    def _umountall(self):
+        "undo the results of _mountall (umount proc,sys, and dev/pts)"
+
         mf = os.path.join(self.statedir, 'mounted-locations')
         if not os.path.exists(mf):
             return
@@ -497,13 +517,10 @@
         track.close()
         
         for item in lines:
-            item = item.replace('\n','')
-            if len(item.strip()) < 1:
+            item = item.strip()
+            if len(item) < 1:
                 continue
-            
-            self.elevate()
             self._umount(item)
-            self.drop()
             
         # poof, no more file
         if os.path.exists(mf):
@@ -651,7 +668,7 @@
                      os.path.join(self.rootdir, 'etc/yum.repos.d')]:
             self._ensure_dir(item)
         
-        self._mount()
+        self._mountall()
 
         # we need stuff
         devices = [('null', 'c', '1', '3', '666'),
@@ -783,7 +800,7 @@
         """prep the chroot for building packages"""
         self._make_our_user()
         self._build_dir_setup()
-        self._mount() # check it again
+        self._mountall() # check it again
         
 def command_parse():
     """return options and args from parsing the command line"""
@@ -818,7 +835,9 @@
             default=False, help="Turn on build-root caching")
     parser.add_option("--rebuildcache", action ="store_true", dest="rebuild_cache",
             default=False, help="Force rebuild of build-root cache")
-
+    parser.add_option("--rpmlint", action = "store_true", dest="run_rpmlint",
+                      default=False, help="Run rpmlint on rpms after a build")
+    
     return parser.parse_args()
 
 def setup_default_config_opts(config_opts):
@@ -871,6 +890,8 @@
     config_opts['quiet'] = options.quiet
     config_opts['use_cache'] = options.use_cache
     config_opts['rebuild_cache'] = options.rebuild_cache
+    config_opts['run_rpmlint'] = options.run_rpmlint
+    
     if config_opts['rebuild_cache']: 
         config_opts['use_cache'] = True
     
@@ -903,14 +924,16 @@
 def do_run_cmd(config_opts, cmd, env='', raw_chroot=0):
         my = Root(config_opts)
         my.debug("executing: %s" % cmd)
-        my._mount()
+        my._mountall()
         if raw_chroot: 
             cmd = '%s %s %s %s' % (env, config_opts['chroot'], my.rootdir, cmd)
+            my.elevate()
             os.system(cmd)
+            my.drop()
         else:
             my.do_chroot(cmd, True)
         my.close()
-        my.debug('finished chroot command')
+        my.debug('finished: %s' % cmd)
                
 def ensure_filetype_srpm(srpms):
     for srpm in srpms:
--
Fedora-buildsys-list mailing list
Fedora-buildsys-list@redhat.com
https://www.redhat.com/mailman/listinfo/fedora-buildsys-list

Reply via email to