[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: booststrapping /usr-merged systems (was: Re: DEP 17: Improve support for directory aliasing in dpkg)



I know I haven't thought about this as much as others, so I might be naively missing something here.

Is the broader context here that this is an alternative to teaching dpkg about aliasing? That is, we just arrange the transition correctly such that we get out of the aliased situation as part of upgrading to trixie?

On 2023-06-09 13:47, Helmut Grohne wrote:
I caution that this protection mechanism of symlinks is a property of
the installation and not of dpkg. Depending on what dpkg is operating
on, we expect it to handle this or not. So we'd need a way to tell
whether an installation needs this kind of special handling.

Because you want to support non-usr-merged systems, e.g. for derivatives? They aren't going to want to delete /bin either, so I don't see how a special-case preventing deletion of /bin would be problematic.

On amd64, we'd upgrade libc6 before dpkg and then /lib64 would go
missing, because libc6 already is the last package that ships files in
/lib64.

Am I understanding the problem correctly?

1. src:libc "moves" /lib64/ld-linux-x86-64.so.2 to /usr/lib64/ld-linux-x86-64.so.2, i.e. it builds bin:libc6:amd64 such that it ships the latter path. 2. bin:libc6:amd64 gets upgraded before dpkg. The normal unpacking behavior of dpkg results in /lib64/ld-linux-x86-64.so.2 being deleted and since /lib64 is now empty, dpkg deletes /lib64. 3. Everything breaks, because /lib64/ld-linux-x86-64.so.2 is special in the ELF ABI.


What would happen if, for trixie only, bin:libc6 shipped two identical copies of ld-linux-x86-64.so.2, one in each of /lib64 and /usr/lib64?

Then at step 2, /lib64 does not get deleted and nothing breaks.

Later, whatever replaces /lib64 with a symlink needs to deal with this, but that's not significantly different than whatever it was going to do anyway, right? Just do this:

1. Whatever safety checks are appropriate.
2. Unless already verified to be identical by #1, hardlink /lib64/ld-linux-x86-64.so.2 to /usr/lib64/ld-linux-x86-64.so.2. This might be just a particular instance of the more general case of hardlink everything from /lib64 into /usr/lib64.
3. Unlink everything from /lib64.
4. Unlink /lib64.
5. Symlink /lib64 to /usr/lib64

However, note that this cannot be a shell script, as then step 3 would delete /lib64/ld-linux-x86-64.so.2 and everything after that would fail.

At that point, everything is fine, EXCEPT that dpkg now thinks it has a /lib64/ld-linux-x86-64.so.2 file installed, but really that is aliasing /usr/lib64/ld-linux-x86-64.so.2. When bin:lib6:amd64 is later upgraded (e.g. in forky) to a version that stops shipping /lib64/ld-linux-x86-64.so.2, dpkg will unlink /lib64/ld-linux-x86-64.so.2 and then everything breaks.

The fix to that is either whatever separate general case fix is being done for aliasing, or if the whole point is we are trying to avoid having that sort of thing at all, then just put in a special case that dpkg will not unlink /lib64/ld-linux-x86-64.so.2.

So we end up with something roughly like this in dpkg (please excuse syntax/pointer errors):

Wherever file deletions are handled, make this change:
- unlink(pathname);
+ special_unlink(pathname);

to use this:

char *SPECIAL_PATHS[] = {
    "/bin",
    "/lib",
    "/lib64",
    "/lib64/ld-linux-x86-64.so.2",
    "/sbin",
    NULL,
}

void special_unlink(const char *pathname) {
    const char **special;
    for (special = SPECIAL_PATHS ; *special ; special++) {
        if (strcmp(pathname, special) == 0) {
            return;
        }
    }
    unlink(pathname);
}

--
Richard

Attachment: OpenPGP_signature
Description: OpenPGP digital signature


Reply to: