osx: patch .pax.gz files in pkg bundles so they extract as root (issue4081) stable
authorMads Kiilerich <madski@unity3d.com>
Fri, 23 Jan 2015 06:28:28 +0100
branchstable
changeset 23940 d0ef40776999
parent 23939 33d1b81c6ef0
child 23941 164bd5218ddb
osx: patch .pax.gz files in pkg bundles so they extract as root (issue4081) The packages has to be installed by root but they would be installed insecurely, owned by the uid of the unprivileged user that made the package. The local user with that uid could thus write to /usr/local/bin/hg . bdist_mpkg calls out to pax to create the package, but pax do apparently not have the power to control what it is writing. Instead, patch the pax files and set their uid fields to 0 before they are wrapped in a dmg.
Makefile
contrib/fixpax.py
--- a/Makefile	Wed Jan 21 15:54:52 2015 -0800
+++ b/Makefile	Fri Jan 23 06:28:28 2015 +0100
@@ -140,6 +140,7 @@
 	   (echo "Missing bdist_mpkg (easy_install bdist_mpkg)"; false)
 	rm -rf dist/mercurial-*.mpkg
 	python -m bdist_mpkg.script_bdist_mpkg setup.py --
+	python contrib/fixpax.py dist/mercurial-*.mpkg/Contents/Packages/*.pkg/Contents/Archive.pax.gz
 	mkdir -p packages/osx
 	N=`cd dist && echo mercurial-*.mpkg | sed 's,\.mpkg$$,,'` && hdiutil create -srcfolder dist/$$N.mpkg/ -scrub -volname "$$N" -ov packages/osx/$$N.dmg
 	rm -rf dist/mercurial-*.mpkg
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/fixpax.py	Fri Jan 23 06:28:28 2015 +0100
@@ -0,0 +1,60 @@
+# fixpax - fix ownership in bdist_mpkg output
+#
+# Copyright 2015 Matt Mackall <mpm@selenic.com>
+#
+# This software may be used and distributed according to the terms of the
+# MIT license (http://opensource.org/licenses/MIT)
+
+"""Set file ownership to 0 in an Archive.pax.gz.
+Suitable for fixing files bdist_mpkg output:
+*.mpkg/Contents/Packages/*.pkg/Contents/Archive.pax.gz
+"""
+
+import sys, os, gzip
+
+def fixpax(iname, oname):
+    i = gzip.GzipFile(iname)
+    o = gzip.GzipFile(oname, "w")
+
+    while True:
+        magic = i.read(6)
+        dev = i.read(6)
+        ino = i.read(6)
+        mode = i.read(6)
+        i.read(6) # uid
+        i.read(6) # gid
+        nlink = i.read(6)
+        rdev = i.read(6)
+        mtime = i.read(11)
+        namesize = i.read(6)
+        filesize = i.read(11)
+        name = i.read(int(namesize, 8))
+        data = i.read(int(filesize, 8))
+
+        o.write(magic)
+        o.write(dev)
+        o.write(ino)
+        o.write(mode)
+        o.write("000000")
+        o.write("000000")
+        o.write(nlink)
+        o.write(rdev)
+        o.write(mtime)
+        o.write(namesize)
+        o.write(filesize)
+        o.write(name)
+        o.write(data)
+
+        if name.startswith("TRAILER!!!"):
+            o.write(i.read())
+            break
+
+    o.close()
+    i.close()
+
+if __name__ == '__main__':
+    for iname in sys.argv[1:]:
+        print 'fixing file ownership in %s' % iname
+        oname = sys.argv[1] + '.tmp'
+        fixpax(iname, oname)
+        os.rename(oname, iname)