[Yum-devel] [PATCH] Fix rpm chroot insanity, so we can access the history DB from unInstStop() cb.

James Antill james at fedoraproject.org
Thu Jun 23 13:17:26 UTC 2011


On Thu, 2011-06-23 at 09:03 +0300, Panu Matilainen wrote:
> On 06/23/2011 01:42 AM, James Antill wrote:
> >   So the problem is that AGAIN, when we log stuff for installed rpms we
> > do it in _instCloseFile, which is outside the chroot ... but when we log
> > stuff for erase rpms we do it in _unInstStop, which is inside the
> > chroot.
> >   sqlite will open it's journal file, which is it has a working path for
> > from outside the chroot ... being inside the chroot breaks this, which
> > results in complete failure of everything.
> >
> >   Proposed fix is to move out of the chroot, before we call the
> > history/sqlite APIs, and then move back out again ... basically what rpm
> > does. Seems to work.
> > ---
> >   yum/rpmtrans.py |    6 ++++++
> >   1 files changed, 6 insertions(+), 0 deletions(-)
> >
> > diff --git a/yum/rpmtrans.py b/yum/rpmtrans.py
> > index 400d729..e0b7058 100644
> > --- a/yum/rpmtrans.py
> > +++ b/yum/rpmtrans.py
> > @@ -551,9 +551,15 @@ class RPMTransaction:
> >           if txmbr is not None:
> >               self._scriptout(txmbr.po)
> >
> > +            #  Note that we are now back outside the smegging chroot, which
>                                              ^^^^^^^
> 
> Should be inside, right?

 Yeh, I was a bit confused about ... mainly thinking in terms. of "in
chroot('.') and in chroot('/var/lib/mock/...')".

> > +            # confuses the heck out of sqlite when it tries to open it's journal
> > +            # file. So let's have fun:
> > +            os.chroot(".")
> >               pid   = self.base.history.pkg2pid(txmbr.po)
> >               state = self.base.history.txmbr2state(txmbr)
> >               self.base.history.trans_data_pid_end(pid, state)
> > +            os.chroot(self.base.conf.installroot)
> > +
> >               self.ts_done(txmbr.po, txmbr.output_state)
> >           else:
> >               self._scriptout(name)
> 
> Lets just say I'm not at all comfortable with the idea of chroot 
> switcheroo behind rpms back in a callback.

 I'm more than happy to do something else, but I can't think of any
better things to do:

1. Change the sqlite code in some way so that we can run from inside and
outside the chroot ... seems much more complicated, and more fragile.

2. Change the sqlite code so we have "two" DBs, one for inside and one
for outside the chroot ... oh, god no, please make it stop :).

3. Change the sqlite code so we keep the journal open over all the
rpmtrans calls (but delete it afterwards). I'm not sure this is
possible, and even if it is I'm not sure sqlite will be happy with the
chroot's even then.

4. Sync. the callbacks (or where we call the history code) so the APIs
are called from the same place (preferably outside) ... AFAIK this isn't
possible.

...do you like any of the above better? Or have more options?

> Of course rpm can't prevent anybody from doing this, if you really 
> intend to go this way then at least be careful about it: you'll only 
> want to chroot if the operation was chrooted to begin with.

 Yeh, I thought of that almost immediately after posting ... and that's
already in rawhide.

>  Since either 
> chroot failing (unlikely but possible technically) would cause an 
> exception and a sudden death I guess there's no need for error checking. 
> The process cwd might be in a bit of a la-la-land between the chroot 
> calls but at least current sqlite doesn't seem to use cwd for anything 
> so maybe it doesn't matter...

 Yeh, I thought of skipping the history calls if the first chroot
fails ... but it seemed added complexity for something that can pretty
much never happen, at least for a "how crazy is this, and does anyone
have a better idea" post.



More information about the Yum-devel mailing list