[PATCH stable] osx: patch .pax.gz files in pkg bundles so they extract as root (issue4081)

Mads Kiilerich mads at kiilerich.com
Fri Jan 23 05:28:58 UTC 2015


# HG changeset patch
# User Mads Kiilerich <madski at unity3d.com>
# Date 1421990908 -3600
#      Fri Jan 23 06:28:28 2015 +0100
# Branch stable
# Node ID e5ec4b39ffe4a53eb9267d6ec30d6e9e34ca50eb
# Parent  de519517f597abd733961a8c549074eecb6c0ab3
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.

diff --git a/Makefile b/Makefile
--- a/Makefile
+++ b/Makefile
@@ -140,6 +140,7 @@ osx:
 	   (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
diff --git a/contrib/fixpax.py b/contrib/fixpax.py
new file mode 100644
--- /dev/null
+++ b/contrib/fixpax.py
@@ -0,0 +1,53 @@
+"""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)


More information about the Mercurial-devel mailing list