[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