cros deploy: restorecon after deploy
SELinux label is not applied at emerge build process, but build_image
process. The tarball for the gentoo package doesn't have SELinux labels
stored.
This change will apply restorecon for every touched file and directory
in a package to make sure it has the right label of current runnng
system being reflected after cros deploy.
BUG=chromium:932156
TEST=cros deploy shill && ssh betty ls -Z /usr/bin/shill
Change-Id: Ifd78cae12f3c30fe05921de099a6955a7fd480ca
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/chromite/+/1583482
Tested-by: Qijiang Fan <fqj@google.com>
Reviewed-by: Mike Frysinger <vapier@chromium.org>
Commit-Queue: Qijiang Fan <fqj@google.com>
diff --git a/cli/deploy.py b/cli/deploy.py
index 9a30905..d09f34d 100644
--- a/cli/deploy.py
+++ b/cli/deploy.py
@@ -796,27 +796,52 @@
logging.notice('%s has been installed.', pkg_name)
-def _SetSELinuxPermissive(device):
- """Set SELinux to permissive on target device.
+def _HasSELinux(device):
+ """Check whether the device has SELinux-enabled.
Args:
device: A ChromiumOSDevice object.
"""
try:
- enforce = device.CatFile('/sys/fs/selinux/enforce', max_size=None)
- # See if SELinux is already disabled.
- if enforce.strip() == '0':
- return
+ device.CatFile('/sys/fs/selinux/enforce', max_size=None)
+ return True
except remote_access.CatFileError:
- # Assume SELinux is not enabled.
- return
- device.RunCommand(['setenforce', '0'], remote_sudo=True)
- device.RunCommand(['sed', '-i', 's/SELINUX=.*/SELINUX=permissive/',
- '/etc/selinux/config'], remote_sudo=True)
- logging.notice('SELinux is set to permissive(crbug.com/932156). '
- 'Use build_image to test whether the change works '
- 'with current SELinux policy, or to test SELinux-'
- 'related changes.')
+ return False
+
+
+def _IsSELinuxEnforced(device):
+ """Check whether the device has SELinux-enforced.
+
+ Args:
+ device: A ChromiumOSDevice object
+ """
+ return device.CatFile('/sys/fs/selinux/enforce', max_size=None).strip() == '1'
+
+
+def _RestoreSELinuxContext(device, pkgpath):
+ """Restore SELinux context for files in a given pacakge.
+
+ This reads the tarball from pkgpath, and calls restorecon on device to
+ restore SELinux context for files listed in the tarball, assuming those files
+ are installed to /
+
+ Args:
+ device: a ChromiumOSDevice object
+ pkgpath: path to tarball
+ """
+ enforced = _IsSELinuxEnforced(device)
+ if enforced:
+ device.RunCommand(['setenforce', '0'])
+ pkgroot = os.path.join(device.work_dir, 'packages')
+ pkg_dirname = os.path.basename(os.path.dirname(pkgpath))
+ pkgpath_device = os.path.join(pkgroot, pkg_dirname, os.path.basename(pkgpath))
+ # Testing shows restorecon splits on newlines instead of spaces.
+ device.RunCommand(
+ ['cd', '/', '&&',
+ 'tar', 'tf', pkgpath_device, '|', 'restorecon', '-i', '-f', '-'],
+ remote_sudo=True)
+ if enforced:
+ device.RunCommand(['setenforce', '1'])
def _GetPackagesByCPV(cpvs, strip, sysroot):
@@ -914,6 +939,8 @@
"""Call _Emerge for each packge in pkgs."""
for pkg_path in _GetPackagesPaths(pkgs, strip, sysroot):
_Emerge(device, pkg_path, root, extra_args=emerge_args)
+ if _HasSELinux(device):
+ _RestoreSELinuxContext(device, pkg_path)
def _UnmergePackages(pkgs, device, root):
@@ -1024,7 +1051,13 @@
else:
func()
- _SetSELinuxPermissive(device)
+ if _HasSELinux(device):
+ if sum(x.count('selinux-policy') for x in pkgs):
+ logging.warning(
+ 'Deploying SELinux policy will not take effect until reboot. '
+ 'SELinux policy is loaded by init. Also, security contexts '
+ '(labels) in files will require manual relabeling by the user '
+ 'if your policy modifies the file contexts.')
logging.warning('Please restart any updated services on the device, '
'or just reboot it.')