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

login
register
mail settings
Submitter Mads Kiilerich
Date Jan. 23, 2015, 5:28 a.m.
Message ID <e5ec4b39ffe4a53eb926.1421990938@localhost.localdomain>
Download mbox | patch
Permalink /patch/7536/
State Accepted
Commit d0ef40776999b47cccb79c187f9cbb0e9a6d58f3
Headers show

Comments

Mads Kiilerich - Jan. 23, 2015, 5:28 a.m.
# HG changeset patch
# User Mads Kiilerich <madski@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.
Matt Mackall - Jan. 23, 2015, 9:57 p.m.
On Fri, 2015-01-23 at 06:28 +0100, Mads Kiilerich wrote:
> # HG changeset patch
> # User Mads Kiilerich <madski@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)

Thanks, I've queued this for stable.

Amusingly, this is almost exactly the code I first wrote, then I decided
to get fancy and wrap zip handling around it... which was apparently
overkill. I've slapped an MIT copyright notice on it so bdist_mpkg can
make use of it.

Patch

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)