From 655c8668bc561a3b17c5b5490480bd15e611412b Mon Sep 17 00:00:00 2001 From: Zac Medico Date: Wed, 27 Mar 2013 01:21:46 -0700 Subject: [PATCH] PORTAGE_XATTR_EXCLUDE="security.*", bug #461868 --- cnf/make.globals | 5 +- man/make.conf.5 | 11 ++- .../ebuild/_config/special_env_vars.py | 3 +- pym/portage/util/movefile.py | 75 +++++++++++++++++-- 4 files changed, 83 insertions(+), 11 deletions(-) diff --git a/cnf/make.globals b/cnf/make.globals index 80a68f7d6..f0597c123 100644 --- a/cnf/make.globals +++ b/cnf/make.globals @@ -1,4 +1,4 @@ -# Copyright 1999-2011 Gentoo Foundation +# Copyright 1999-2013 Gentoo Foundation # Distributed under the terms of the GNU General Public License v2 # System-wide defaults for the Portage system @@ -123,6 +123,9 @@ PORTAGE_ELOG_MAILFROM="portage@localhost" # Signing command used by repoman PORTAGE_GPG_SIGNING_COMMAND="gpg --sign --digest-algo SHA256 --clearsign --yes --default-key \"\${PORTAGE_GPG_KEY}\" --homedir \"\${PORTAGE_GPG_DIR}\" \"\${FILE}\"" +# Security labels are special, see bug #461868. +PORTAGE_XATTR_EXCLUDE="security.*" + # ***************************** # ** DO NOT EDIT THIS FILE ** # *************************************************** diff --git a/man/make.conf.5 b/man/make.conf.5 index 42a5b254d..5e35546ae 100644 --- a/man/make.conf.5 +++ b/man/make.conf.5 @@ -1,4 +1,4 @@ -.TH "MAKE.CONF" "5" "Jan 2013" "Portage VERSION" "Portage" +.TH "MAKE.CONF" "5" "Mar 2013" "Portage VERSION" "Portage" .SH "NAME" make.conf \- custom settings for Portage .SH "SYNOPSIS" @@ -573,7 +573,8 @@ Enable GPG verification when using \fIemerge\-webrsync\fR. .TP .B xattr Preserve extended attributes (filesystem-stored metadata) when installing -files (see \fBattr\fR(1)). +files (see \fBattr\fR(1)). The \fBPORTAGE_XATTR_EXCLUDE\fR variable may be +used to exclude specific attributes from being preserved. .RE .TP .B FETCHCOMMAND @@ -859,6 +860,12 @@ Defaults to portage. \fBPORTAGE_WORKDIR_MODE\fR = \fI"0700"\fR This variable controls permissions for \fIWORKDIR\fR (see \fBebuild\fR(5)). .TP +\fBPORTAGE_XATTR_EXCLUDE\fR = \fI[space delimited list of fnmatch patterns]\fR +This variable may be used to exclude specific attributes from being preserved +when \fBxattr\fR is in \fBFEATURES\fR. +.br +Defaults to "security.*" (security labels are special, see bug #461868). +.TP \fBPORTDIR\fR = \fI[path]\fR Defines the location of the Portage tree. This is the repository for all profile information as well as all ebuilds. If you change this, you must update diff --git a/pym/portage/package/ebuild/_config/special_env_vars.py b/pym/portage/package/ebuild/_config/special_env_vars.py index 8e85a4686..0b4dc39a2 100644 --- a/pym/portage/package/ebuild/_config/special_env_vars.py +++ b/pym/portage/package/ebuild/_config/special_env_vars.py @@ -170,7 +170,8 @@ environ_filter += [ "PORTAGE_RO_DISTDIRS", "PORTAGE_RSYNC_EXTRA_OPTS", "PORTAGE_RSYNC_OPTS", "PORTAGE_RSYNC_RETRIES", "PORTAGE_SYNC_STALE", - "PORTAGE_USE", "PORT_LOGDIR", "PORT_LOGDIR_CLEAN", + "PORTAGE_USE", "PORTAGE_XATTR_EXCLUDE", + "PORT_LOGDIR", "PORT_LOGDIR_CLEAN", "QUICKPKG_DEFAULT_OPTS", "REPOMAN_DEFAULT_OPTS", "RESUMECOMMAND", "RESUMECOMMAND_FTP", "RESUMECOMMAND_HTTP", "RESUMECOMMAND_HTTPS", diff --git a/pym/portage/util/movefile.py b/pym/portage/util/movefile.py index bf95f1a40..8a7a2b6a6 100644 --- a/pym/portage/util/movefile.py +++ b/pym/portage/util/movefile.py @@ -6,6 +6,7 @@ from __future__ import unicode_literals __all__ = ['movefile'] import errno +import fnmatch import os as _os import shutil as _shutil import stat @@ -27,10 +28,59 @@ def _apply_stat(src_stat, dest): _os.chown(dest, src_stat.st_uid, src_stat.st_gid) _os.chmod(dest, stat.S_IMODE(src_stat.st_mode)) +_xattr_excluder_cache = {} + +def _get_xattr_excluder(pattern): + + try: + value = _xattr_excluder_cache[pattern] + except KeyError: + value = _xattr_excluder(pattern) + _xattr_excluder_cache[pattern] = value + + return value + +class _xattr_excluder(object): + + __slots__ = ('_pattern_split',) + + def __init__(self, pattern): + + if pattern is None: + self._pattern_split = None + else: + pattern = pattern.split() + if not pattern: + self._pattern_split = None + else: + pattern.sort() + self._pattern_split = tuple(pattern) + + def __call__(self, attr): + + if self._pattern_split is None: + return False + + match = fnmatch.fnmatch + for x in self._pattern_split: + if match(attr, x): + return True + + return False + if hasattr(_os, "getxattr"): # Python >=3.3 and GNU/Linux - def _copyxattr(src, dest): - for attr in _os.listxattr(src): + def _copyxattr(src, dest, exclude=None): + + attrs = _os.listxattr(src) + if attrs: + if exclude is not None and isinstance(attrs[0], bytes): + exclude = exclude.encode(_encodings['fs']) + exclude = _get_xattr_excluder(exclude) + + for attr in attrs: + if exclude(attr): + continue try: _os.setxattr(dest, attr, _os.getxattr(src, attr)) raise_exception = False @@ -44,8 +94,17 @@ else: except ImportError: xattr = None if xattr is not None: - def _copyxattr(src, dest): - for attr in xattr.list(src): + def _copyxattr(src, dest, exclude=None): + + attrs = xattr.list(src) + if attrs: + if exclude is not None and isinstance(attrs[0], bytes): + exclude = exclude.encode(_encodings['fs']) + exclude = _get_xattr_excluder(exclude) + + for attr in attrs: + if exclude(attr): + continue try: xattr.set(dest, attr, xattr.get(src, attr)) raise_exception = False @@ -63,7 +122,8 @@ else: _has_getfattr_and_setfattr = False _devnull.close() if _has_getfattr_and_setfattr: - def _copyxattr(src, dest): + def _copyxattr(src, dest, exclude=None): + # TODO: implement exclude getfattr_process = subprocess.Popen(["getfattr", "-d", "--absolute-names", src], stdout=subprocess.PIPE) getfattr_process.wait() extended_attributes = getfattr_process.stdout.readlines() @@ -75,7 +135,7 @@ else: if setfattr_process.returncode != 0: raise OperationNotSupported("Filesystem containing file '%s' does not support extended attributes" % dest) else: - def _copyxattr(src, dest): + def _copyxattr(src, dest, exclude=None): pass def movefile(src, dest, newmtime=None, sstat=None, mysettings=None, @@ -246,7 +306,8 @@ def movefile(src, dest, newmtime=None, sstat=None, mysettings=None, _copyfile(src_bytes, dest_tmp_bytes) if xattr_enabled: try: - _copyxattr(src_bytes, dest_tmp_bytes) + _copyxattr(src_bytes, dest_tmp_bytes, + exclude=mysettings.get("PORTAGE_XATTR_EXCLUDE", "security.*")) except SystemExit: raise except: -- 2.26.2