Package: usrmerge
Version: 25
Severity: serious
Justification: violates policy section 10.7.4
Control: affects -1 + debianutils dash
X-Debbugs-Cc: jo...@debian.org, cl...@debian.org, andre...@debian.org, 
debian-rele...@lists.debian.org

Hi,

I think that it is quite obvious that /etc/shells is debianutils'
territory. When I found that on some systems /etc/shells was out of sync
with /var/lib/shells.state, I was quite puzzled until I noticed that
usrmerge messes with this file. This really is debianutils'
configuration file and usrmerge has no business in touching it in
uncoordinated ways. Refer to policy section 10.7.4 for details, so
usrmerge is technically rc-buggy. However, usrmerge does have reason to
touch it, so the solution is not simply to drop convert-etc-shells with
no replacement.

Let us dive a bit into how an essential system can come to be.

1. We start either merged (e.g. debootstrap or mmdebstrap with
   --hook-dir=.../merged-usr) or unmerged (mmdebstrap without hook or
   an old debootstrap --no-merged-usr).

2. We either install usrmerge or usr-is-merged. Though we cannot
   combine starting unmerged with usr-is-merged for obvious reasons.

3. The last invocation of update-shells happens before or after
   usrmerge.postinst. (Not relevant in case of usr-is-merged)

So what happens in these cases?

If and only if usrmerge is used, convert-etc-shells turns /bin/sh into
/usr/bin/sh. So whenever we start out merged and use usr-is-merged,
/usr/bin/sh goes missing.

If usrmerge is used, the order of entries in /etc/shells depends on
whether update-shells is run after it or not. Likewise
/var/lib/shells.state also depends. This is not some mmdebstrap-specific
problem. You can easily observe this with debootstrap --no-merged-usr
and installing usrmerge vs just doing debootstrap.

This is bad from a reproducibility point of view and it is rooted in
usrmerge not cooperating with other packages, but instead doing things
behind their back, which happens to violate policy.

So how to fix this?

For one thing, the /bin/sh difference is rooted in the fact that /bin/sh
is a standard value of debianutils and not managed using shells.d even
though dash ships plain /bin/sh these days. I think dash should just add
/bin/sh to /usr/share/debianutils/shells.d/dash and we'd be done as all
entries in shells.d are correctly managed wrt. merged-/usr by
update-shells.

The next thing is that convert-etc-shells needs to go away from
usrmerge. In the age of systems with usr-is-merged, there is no
convert-etc-shells (as there is no usrmerge), so it must work without
somehow anyway. When you run update-shells after a merge, it will pick
up the merged shell locations (for shells managed in shells.d) and add
them to /etc/shells. So usrmerge should ensure that update-shells is
called after having performed the merge. This is the only way to get
reproducibility. (That doesn't quite answer yet when to run it, how to
run it, nor whether that makes convert-etc-shells unnecessary though.)

Then we still have add-shell and remove-shell and most packages using
them induce policy violations (reverting admin changes on upgrade), so
we want to change them to the shells.d mechanism in the long run, but
that's not where we are today and especially not what we can rely on in
bookworm. So for these entries, we still do need convert-etc-shells and
indeed we cannot just delete it. convert-etc-shells compensates for the
difference in behaviour of add-shell pre-merge vs post-merge.

I think the best solution here would be merging convert-etc-shells into
update-shells. Whenever we run update-shells, it should check whether
the system is already merged and when it is, perform the equivalent to
convert-etc-shells. Then usrmerge can just install an empty (except for
a comment) /usr/share/debianutils/shells.d/usrmerge to trigger
update-shells and things become fully reproducible in all cases, because
no matter how we started, we will run update-shells post merge and
that'll do the right thing. And since usrmerge now uses the tools
provided by debianutils, this fully resolves the policy violation. Also
note that usr-is-merged does not have to invoke the trigger as
debianutils is configured after /usr is merged.

So unless I am mistaken, this leads to the following action items:
 * update-shells absorbs convert-etc-shells.
 * dash adds /bin/sh to shells.d/dash.
 * usrmerge creates an empty shells.d/usrmerge file.
 * usrmerge depends on a version of debianutils that has absorbed
   convert-etc-shells.

Does that make sense to you? I haven't actually implemented and tested
this yet. Do you see any obvious flaws in the arguments or the proposed
solution?

I'm Ccing release managers as it looks like we're starting a transition
of an essential package right in the middle of the freeze. Not good, but
this looks still manageable to me.

Helmut

Reply via email to