Update OTA to understand SELinux filesystem labels
Make fs_config aware of SELinux contexts, and output the context
whenever we output the UID / GID / file perms.
Pass the selinux context to the set_perm2() and set_perm2_recursive()
calls. When the OTA script fixes up filesystem permissions, it will
also fix up the SELinux context on the files.
Bug: 8985290
Change-Id: I6419b64c06309a93ac6b2f2cf9fc7f8815adeaf3
diff --git a/tools/releasetools/edify_generator.py b/tools/releasetools/edify_generator.py
index 9ef1926..cafdeb3 100644
--- a/tools/releasetools/edify_generator.py
+++ b/tools/releasetools/edify_generator.py
@@ -217,14 +217,14 @@
else:
raise ValueError("don't know how to write \"%s\" partitions" % (p.fs_type,))
- def SetPermissions(self, fn, uid, gid, mode):
+ def SetPermissions(self, fn, uid, gid, mode, secontext):
"""Set file ownership and permissions."""
- self.script.append('set_perm(%d, %d, 0%o, "%s");' % (uid, gid, mode, fn))
+ self.script.append('set_perm2(%d, %d, 0%o, "%s", "%s");' % (uid, gid, mode, secontext, fn))
- def SetPermissionsRecursive(self, fn, uid, gid, dmode, fmode):
+ def SetPermissionsRecursive(self, fn, uid, gid, dmode, fmode, secontext):
"""Recursively set path ownership and permissions."""
- self.script.append('set_perm_recursive(%d, %d, 0%o, 0%o, "%s");'
- % (uid, gid, dmode, fmode, fn))
+ self.script.append('set_perm2_recursive(%d, %d, 0%o, 0%o, "%s", "%s");'
+ % (uid, gid, dmode, fmode, secontext, fn))
def MakeSymlinks(self, symlink_list):
"""Create symlinks, given a list of (dest, link) pairs."""
diff --git a/tools/releasetools/ota_from_target_files b/tools/releasetools/ota_from_target_files
index 1e1d04e..e79c13f 100755
--- a/tools/releasetools/ota_from_target_files
+++ b/tools/releasetools/ota_from_target_files
@@ -117,6 +117,7 @@
self.uid = None
self.gid = None
self.mode = None
+ self.secontext = None
self.dir = dir
if name:
@@ -166,63 +167,66 @@
for line in output.split("\n"):
if not line: continue
- name, uid, gid, mode = line.split()
+ name, uid, gid, mode, secontext = line.split()
i = cls.ITEMS.get(name, None)
if i is not None:
i.uid = int(uid)
i.gid = int(gid)
i.mode = int(mode, 8)
+ i.secontext = secontext
if i.dir:
i.children.sort(key=lambda i: i.name)
# set metadata for the files generated by this script.
i = cls.ITEMS.get("system/recovery-from-boot.p", None)
- if i: i.uid, i.gid, i.mode = 0, 0, 0644
+ if i: i.uid, i.gid, i.mode, i.secontext = 0, 0, 0644, "u:object_r:system_file:s0"
i = cls.ITEMS.get("system/etc/install-recovery.sh", None)
- if i: i.uid, i.gid, i.mode = 0, 0, 0544
+ if i: i.uid, i.gid, i.mode, i.secontext = 0, 0, 0544, "u:object_r:system_file:s0"
def CountChildMetadata(self):
- """Count up the (uid, gid, mode) tuples for all children and
+ """Count up the (uid, gid, mode, secontext) tuples for all children and
determine the best strategy for using set_perm_recursive and
set_perm to correctly chown/chmod all the files to their desired
values. Recursively calls itself for all descendants.
- Returns a dict of {(uid, gid, dmode, fmode): count} counting up
+ Returns a dict of {(uid, gid, dmode, fmode, secontext): count} counting up
all descendants of this node. (dmode or fmode may be None.) Also
sets the best_subtree of each directory Item to the (uid, gid,
- dmode, fmode) tuple that will match the most descendants of that
+ dmode, fmode, secontext) tuple that will match the most descendants of that
Item.
"""
assert self.dir
- d = self.descendants = {(self.uid, self.gid, self.mode, None): 1}
+ d = self.descendants = {(self.uid, self.gid, self.mode, None, self.secontext): 1}
for i in self.children:
if i.dir:
for k, v in i.CountChildMetadata().iteritems():
d[k] = d.get(k, 0) + v
else:
- k = (i.uid, i.gid, None, i.mode)
+ k = (i.uid, i.gid, None, i.mode, i.secontext)
d[k] = d.get(k, 0) + 1
- # Find the (uid, gid, dmode, fmode) tuple that matches the most
+ # Find the (uid, gid, dmode, fmode, secontext) tuple that matches the most
# descendants.
# First, find the (uid, gid) pair that matches the most
# descendants.
ug = {}
- for (uid, gid, _, _), count in d.iteritems():
+ for (uid, gid, _, _, _), count in d.iteritems():
ug[(uid, gid)] = ug.get((uid, gid), 0) + count
ug = MostPopularKey(ug, (0, 0))
- # Now find the dmode and fmode that match the most descendants
+ # Now find the dmode, fmode and secontext that match the most descendants
# with that (uid, gid), and choose those.
best_dmode = (0, 0755)
best_fmode = (0, 0644)
+ best_secontext = (0, "u:object_r:system_file:s0")
for k, count in d.iteritems():
if k[:2] != ug: continue
if k[2] is not None and count >= best_dmode[0]: best_dmode = (count, k[2])
if k[3] is not None and count >= best_fmode[0]: best_fmode = (count, k[3])
- self.best_subtree = ug + (best_dmode[1], best_fmode[1])
+ if k[4] is not None and count >= best_secontext[0]: best_secontext = (count, k[4])
+ self.best_subtree = ug + (best_dmode[1], best_fmode[1], best_secontext[1])
return d
@@ -234,7 +238,7 @@
self.CountChildMetadata()
def recurse(item, current):
- # current is the (uid, gid, dmode, fmode) tuple that the current
+ # current is the (uid, gid, dmode, fmode, secontext) tuple that the current
# item (and all its children) have already been set to. We only
# need to issue set_perm/set_perm_recursive commands if we're
# supposed to be something different.
@@ -244,17 +248,17 @@
current = item.best_subtree
if item.uid != current[0] or item.gid != current[1] or \
- item.mode != current[2]:
- script.SetPermissions("/"+item.name, item.uid, item.gid, item.mode)
+ item.mode != current[2] or item.secontext != current[4]:
+ script.SetPermissions("/"+item.name, item.uid, item.gid, item.mode, item.secontext)
for i in item.children:
recurse(i, current)
else:
if item.uid != current[0] or item.gid != current[1] or \
- item.mode != current[3]:
- script.SetPermissions("/"+item.name, item.uid, item.gid, item.mode)
+ item.mode != current[3] or item.secontext != current[4]:
+ script.SetPermissions("/"+item.name, item.uid, item.gid, item.mode, item.secontext)
- recurse(self, (-1, -1, -1, -1))
+ recurse(self, (-1, -1, -1, -1, "u:object_r:unlabeled:s0"))
def CopySystemFiles(input_zip, output_zip=None,
@@ -733,7 +737,7 @@
for item in deferred_patch_list:
fn, tf, sf, size, _ = item
script.ApplyPatch("/"+fn, "-", tf.size, tf.sha1, sf.sha1, "patch/"+fn+".p")
- script.SetPermissions("/system/build.prop", 0, 0, 0644)
+ script.SetPermissions("/system/build.prop", 0, 0, 0644, "u:object_r:system_file:s0")
script.AddToZip(target_zip, output_zip)
WriteMetadata(metadata, output_zip)