[pacman-dev] [RFC] Correct directory permissions if the extracting package is the only owner

Andrew Gregory andrew.gregory.8 at gmail.com
Tue Feb 3 05:46:17 UTC 2015


On 02/01/15 at 09:09pm, Allan McRae wrote:
> Adjusting permissions of directories in their install scripts results in
> warnings such as the following when the package update:
> 
> warning: directory ownership differs on /var/lib/postfix/
> filesystem: 73:0 package: 0:0
> 
> If the package being installed is the only owner of the directory, update
> the directory's permissions to those in the package file.
> 
> This also allows directory permissions for a package to be changed directly
> in the PKGBUILD file rather that requiring adjustment in an install scriptlet.
> 
> Signed-off-by: Allan McRae <allan at archlinux.org>
> ---
> 
> This does require searching through all installed packages filelist to see if
> any other directories own this file, which does create a slowdown in these
> error cases. Once the ability to use symbolic names for owners is added, this
> code path will run only if there is an acutal error or in the rare case that
> directory permissions are genuinely being changed.
> 
> Packages can currently avoid this being run by reverting their directory
> permission changes in pre_upgrade().
> 
> I'd like to push this to maint if people agree.  These "false" warnings are
> causing too many issues.
> 
>  lib/libalpm/add.c | 61 +++++++++++++++++++++++++++++++++++++++++--------------
>  1 file changed, 46 insertions(+), 15 deletions(-)

Constantly shuffling the owner between root and another user feels
very hackish to me just to avoid false positives.  Perhaps we should
just remove the warning until we have a proper way for packages to set
ownership.  If we do go ahead and reset ownership, I think it should
also respect noupgrade.  Style nitpicks below.

> diff --git a/lib/libalpm/add.c b/lib/libalpm/add.c
> index 82461ee..60db22f 100644
> --- a/lib/libalpm/add.c
> +++ b/lib/libalpm/add.c
> @@ -167,6 +167,20 @@ static int extract_db_file(alpm_handle_t *handle, struct archive *archive,
>  	return perform_extraction(handle, archive, entry, filename);
>  }
>  
> +static int other_directory_owners(alpm_handle_t *handle, const char *entryname, const char *pkgname) {

Wrap at 80 columns and move opening brace to its own line.

> +	alpm_list_t *packages = alpm_db_get_pkgcache(handle->db_local);
> +	alpm_list_t *i;
> +
> +	for(i = packages; i ; i = alpm_list_next(i)) {
> +		if(alpm_filelist_contains(alpm_pkg_get_files(i->data), entryname) &&
> +				strcmp(((alpm_pkg_t *)(i->data))->name, pkgname) != 0) {
> +			return 1;
> +		}
> +	}
> +
> +	return 0;
> +}
> +
>  static int extract_single_file(alpm_handle_t *handle, struct archive *archive,
>  		struct archive_entry *entry, alpm_pkg_t *newpkg, alpm_pkg_t *oldpkg)
>  {
> @@ -232,25 +246,42 @@ static int extract_single_file(alpm_handle_t *handle, struct archive *archive,
>  
>  		/* case 6: existing dir, ignore it */
>  		if(lsbuf.st_mode != entrymode) {
> -			/* if filesystem perms are different than pkg perms, warn user */
>  			mode_t mask = 07777;
> -			_alpm_log(handle, ALPM_LOG_WARNING, _("directory permissions differ on %s\n"
> -					"filesystem: %o  package: %o\n"), filename, lsbuf.st_mode & mask,
> -					entrymode & mask);
> -			alpm_logaction(handle, ALPM_CALLER_PREFIX,
> -					"warning: directory permissions differ on %s\n"
> -					"filesystem: %o  package: %o\n", filename, lsbuf.st_mode & mask,
> -					entrymode & mask);
> +			if(other_directory_owners(handle, entryname, newpkg->name) == 0) {
> +				/* no other package owns this directory, "extract" with correct permissions */
> +				if(chmod(filename, entrymode) != 0) {
> +					goto warn_permissions;
> +				}
> +			} else {
> +warn_permissions:

I would prefer this was written as a single condition:

 if(noupgrade || other_directory_owners(...) != 0 || chmod(...) != 0) {
  /* warn user */
 }

> +				/* if filesystem perms are different than pkg perms, warn user */
> +				_alpm_log(handle, ALPM_LOG_WARNING, _("directory permissions differ on %s\n"
> +						"filesystem: %o  package: %o\n"), filename, lsbuf.st_mode & mask,
> +						entrymode & mask);
> +				alpm_logaction(handle, ALPM_CALLER_PREFIX,
> +						"warning: directory permissions differ on %s\n"
> +						"filesystem: %o  package: %o\n", filename, lsbuf.st_mode & mask,
> +						entrymode & mask);
> +
> +			}
>  		}
>  
>  		if((entryuid != lsbuf.st_uid) || (entrygid != lsbuf.st_gid)) {
> -			_alpm_log(handle, ALPM_LOG_WARNING, _("directory ownership differs on %s\n"
> -					"filesystem: %u:%u  package: %u:%u\n"), filename,
> -					lsbuf.st_uid, lsbuf.st_gid, entryuid, entrygid);
> -			alpm_logaction(handle, ALPM_CALLER_PREFIX,
> -					"warning: directory ownership differs on %s\n"
> -					"filesystem: %u:%u  package: %u:%u\n", filename,
> -					lsbuf.st_uid, lsbuf.st_gid, entryuid, entrygid);
> +			if(other_directory_owners(handle, entryname, newpkg->name) == 0) {
> +				/* no other package owns this directory, "extract" with correct owners */
> +				if(chown(filename, entryuid, entrygid) != 0) {
> +					goto warn_owners;
> +				}
> +			} else {
> +warn_owners:

Same as above.

> +				_alpm_log(handle, ALPM_LOG_WARNING, _("directory ownership differs on %s\n"
> +						"filesystem: %u:%u  package: %u:%u\n"), filename,
> +						lsbuf.st_uid, lsbuf.st_gid, entryuid, entrygid);
> +				alpm_logaction(handle, ALPM_CALLER_PREFIX,
> +						"warning: directory ownership differs on %s\n"
> +						"filesystem: %u:%u  package: %u:%u\n", filename,
> +						lsbuf.st_uid, lsbuf.st_gid, entryuid, entrygid);
> +			}
>  		}
>  
>  		_alpm_log(handle, ALPM_LOG_DEBUG, "extract: skipping dir extraction of %s\n",
> -- 
> 2.2.2


More information about the pacman-dev mailing list