Why does a yum package update replaces my yum-cron config files?

Written by:

Why does a yum package update replaces my yum-cron config files?
  • 0.00 / 5 5
0 votes, 0.00 avg. rating (0% score)

Usually, when applying package updates via yum update, rpm is ‘intelligent’ enough to respect my changes to configuration files under /etc.

(It basically looks at the mtime, compares it and depending on the outcome replaces the file with the new version, or just puts the new version beside it.)

But with one of the last yum/yum-cron updates on Centos 7, my custom yum-cron config files were replaced:

/etc/yum/yum-cron.conf
/etc/yum/yum-cron-hourly.conf

Now I am wondering why this happened exactly?

I mean, the answer must be in the source package – but I can’t find it there:

$ rpm -qi yum-cron | grep src
Source RPM  : yum-3.4.3-132.el7.centos.0.1.src.rpm
$ yumdownloader --source yum-3.4.3-132.el7.centos.0.1
$ grep '%.*yum-cron.*.conf' yum.spec
%config(noreplace) %{_sysconfdir}/yum/yum-cron.conf
%config(noreplace) %{_sysconfdir}/yum/yum-cron-hourly.conf

Looking at the spec file, in the yum-cron section, the config directive even has noreplace specified.

On the other hand, the ownership of the config files seems to be shared among the yum and the yum-cron binary packages:

$ rpm -ql yum-cron | grep 'yum-cron.*.conf'
/etc/yum/yum-cron-hourly.conf
/etc/yum/yum-cron.conf
$ rpm -ql yum | grep 'yum-cron.*.conf' 
/etc/yum/yum-cron-hourly.conf
/etc/yum/yum-cron.conf

How come?

I mean, I only see the yum-cron config files mentioned in the cron specific files section of the spec file …

See also the CentOS issue and the RHEL issue on this.

This is a problem in the way Red Hat created the package – the yum-cron.conf file should be marked as a config file (contrary to what your output indicates should be the case), but it is not (querying the installed package for config files does not list the yum-cron.conf file). The actual answer is to get it fixed by RH, the likely more useful answer is chattr +i. See also: http://serverfault.com/questions/744531/secure-yum-cron-conf-configuration-and-prevent-them-from-getting-auto-updated/744535#744535

John

This is due to the following line in the main %files section of the yum.spec file:

%(dirname %{compdir})

Meaning that rpm first substitutes %{compdir} and then executes dirname with the result as argument in a shell. The output is then added to the file list.

The compdir variable is defined like this:

%define compdir %(pkg-config --variable=completionsdir bash-completion)
%if "%{compdir}" == ""
%define compdir "/etc/bash_completion.d"
%endif

Assuming that bash-completion is installed at build time (on the build system), pkg-config thus returns perhaps:

/usr/share/bash-completion/completions

And thus adding

dirname /usr/share/bash-completion/completions
-> /usr/share/bash-completion

to the file list is ok (and makes sense if the yum package also installs helpers, i.e. under /usr/share/bash-completion/helpers).

The problematic case is when the bash-completion package is not installed at build time because then pkg-config returns the empty string, i.e.:

 compdir := /etc/bash_completion.d
 => dirname /etc/bash_completion.d
 -> /etc

Thus, the complete /etc directory from the package’s buildroot is recursively added to the file list.

Apparently, the box where the CentOS yum binary package was built didn’t have the bash-completion package installed. In fact, RHEL (and thus CentOS) does not even provide a bash-completion package.

This explains why the files

/etc/yum/yum-cron.conf
/etc/yum/yum-cron-hourly.conf

are owned by both the yum and the yum-cron package.

(And are only correctly marked by the yum-cron package.)

Addendum

The motivation for the conditionals is probably the idea to have one yum spec file for multiple rpm based distributions (e.g. different versions of Fedora, RHEL, …). Consequent, the spec file also conditionally build-depends and bash-completions only on non-RHEL systems:

%if ! 0%{?rhel}
# we don't have this in rhel yet...
BuildRequires: bash-completion
%endif

The change that introduced dirname was discussed on the yum mailinglist:

package also $(compdir)’s parent (not sure why, just in case)

The introduction of the conditional logic was also discussed:

Oh, and instead of hardcoding the completions dir, it’d be better to
get it from “pkg-config –variable=completionsdir bash-completion”.

Spec Fix

One fix is to move the dirname call into the right conditional branch, e.g.:

--- a/SPECS/yum.spec
+++ b/SPECS/yum.spec
@@ -28,7 +28,7 @@ BuildRequires: bash-completion

 # disable broken /usr/lib/rpm/brp-python-bytecompile
 %define __os_install_post %{nil}
-%define compdir %(pkg-config --variable=completionsdir bash-completion)
+%define compdir %(pkg-config --variable=completionsdir bash-completion | xargs -r dirname)
 %if "%{compdir}" == ""
 %define compdir "/etc/bash_completion.d"
 %endif
@@ -451,7 +451,7 @@ exit 0
 %dir %{_sysconfdir}/yum/fssnap.d
 %dir %{_sysconfdir}/yum/vars
 %config(noreplace) %{_sysconfdir}/logrotate.d/%{name}
-%(dirname %{compdir})
+%{compdir}
 %dir %{_datadir}/yum-cli
 %{_datadir}/yum-cli/*
 %exclude %{_datadir}/yum-cli/completion-helper.py?

maxschlepzig

Thanks for the detailed explanation maxschlepzig, but your proposed fix isn’t correct. It would result in comdir being set to /usr/share/bash-completion when bash-completion is installed. Files from there aren’t loaded, they have to be in /usr/share/bash-completion/completions. That would break being able to consistently use %{compdir} as an install path for completion files, which is the whole point of the macro.

The safest way to fix this is be explicit:

%if 0%{?fedora} >= 19 || 0%{?rhel} >= 7
%global compdir %{_datadir}/bash-completion/completions
%else
%global compdir %{_sysconfdir}/bash_completion.d
%endif

Then later in the %files section:

%if 0%{?fedora} >= 19 || 0%{?rhel} >= 7
%(dirname %{compdir})
%else
%{compdir}
%endif

carlwgeorge

Leave a Reply