rsync 3.2.x in Groovy depends on broken libxxhash 0.7.x

Bug #1934992 reported by Walter
10
This bug affects 1 person
Affects Status Importance Assigned to Milestone
xxhash (Ubuntu)
Fix Released
Low
Unassigned
Groovy
Won't Fix
Undecided
Unassigned

Bug Description

**NOTE: This ticket has been moved/altered. Original problem referred to rsync behaviour with libxxhash0. New subject is the changed ABI of libxxhash0.**

Original-Subject: rsync 3.2.x in Groovy depends on broken libxxhash 0.7.x

Actual problem: libxxhash0 in Focal exposes 128-bit xxhash (xxh128) symbols which behave differently on versions of libxxhash0 in Groovy and above.

In xxhash 0.7.x there is this notice:

https://github.com/Cyan4973/xxHash/blob/173e50be0509c6fb6c1bb74d95049ef61d7fdced/xxhash.h#L465-L476

> The XXH3 algorithm is still in development.
> The results it produces may still change in future versions.
>
> Results produced by v0.7.x are not comparable with results
> from v0.7.y. However, the API is completely stable, and it
> can safely be used for ephemeral data (local sessions).
>
> Avoid storing values in long-term storage until the
> algorithm is finalized. XXH3's return values will be
> officially finalized upon reaching v0.8.0.

Unfortunately these ended up as usable symbols in xxhash 0.7.x in Debian:

> XXH128@Base 0.7.0
(etc..)

This means that those linking against libxxhash0 would get a binary dependency on 0.7.0. But behaviour of xxh128 differs between 0.7 and 0.8. So if you're linking against xxh128 from 0.8.x, it should binary-depend on >=0.8 and not >=0.7. (And if possible, you should not use xxh128 at all in 0.7.x.)

The following Debian changeset fixes this for newer libxxhash0 builds:

https://github.com/norbusan/debian-xxhash/commit/b51053c86952dd13573b08344101172c88de847f

> debian/libxxhash0.symbols
> - XXH128@Base 0.7.0
> + XXH128@Base 0.8.0

But, this is not fully resolved until:

- that Debian change lands in libxxhash0 in Ubuntu;
- packages linking against libxxhash0 (e.g. rsync) are rebuilt against this newer package, so the Depends is bumped to >=0.8;
- xxh128 in libxxhash0 in Focal is clearly marked as ephemeral (or removed altogether; this applies to xxh128 symbols libxxhash0 and an `xxh128sum` binary in the xxhash package)

Cheers,
Walter Doekes
OSSO B.V.

---vvv--- Original ticket below ---vvv---

**Problem**

  $ rsync root@focal-system:/etc/.pwd.lock .
  ERROR: .pwd.lock failed verification -- update discarded.
  rsync error: some files/attrs were not transferred
    (see previous errors)
    (code 23) at main.c(1816) [generator=3.2.3]

  $ rsync root@focal-system:/etc/.pwd.lock . --debug=all
  opening connection using: ssh -l root focal-system rsync \
    --server --sender \
    -e.LsfxCIvu . /etc/.pwd.lock (10 args)
  (Client) Protocol versions: remote=31, negotiated=31
  Client negotiated checksum: xxh128
  ...

**Cause**

  focal-system# dpkg -l | grep -E 'libxxhash|rsync'
  ii libxxhash0:amd64 0.7.3-1 amd64
  ii rsync 3.2.3-2ubuntu1 amd64

**Why this affects only us and not more people?**

On Ubuntu/Focal, there is no rsync 3.2.3, only 3.1.3-8. But because we need the lz4 compression support we've fetched a newer rsync (from Groovy).

However: the rsync 3.2.3 depends on libxxhash0 0.7.1+, while in fact it needs 0.8+.

**Details**

On a Ubuntu/Focal system we have installed a rsync 3.2.3 package from Ubuntu/Groovy because we need the lz4 compression support.

focal-system# apt-cache show rsync
Package: rsync
...
Version: 3.2.3-2ubuntu1
Depends: lsb-base, libacl1 (>= 2.2.23), libc6 (>= 2.15),
  liblz4-1 (>= 0.0~r130), libpopt0 (>= 1.14), libssl1.1 (>= 1.1.0),
  libxxhash0 (>= 0.7.1), libzstd1 (>= 1.3.8), zlib1g (>= 1:1.1.4)
...

Alongside this we had libxxhash0 0.7.3-1 from Focal:

focal-system# apt-cache policy libxxhash0
libxxhash0:
  Installed: 0.7.3-1
  Candidate: 0.7.3-1
  Version table:
 *** 0.7.3-1 500
        500 http://ARCHIVE/ubuntu focal/universe amd64 Packages
        100 /var/lib/dpkg/status

According to the dependencies, this should work. But the combination does not, as this quote from the rsync maintainer would tell you:
https://github.com/WayneD/rsync/issues/122#issuecomment-737690913
> Yeah, Cyan4973 could have told you that the 128-bit xxhash only
> just stabilized in its 0.8.0 release, so anything older than
> that isn't compatible.

**The fix**

As the maintainer points out, version 0.7 is not stable (= broken for our intents and purposes) and thus not fit for use with rsync 3.2.

I would argue that it's a good idea to bump the dependency of rsync 3.2.3 on Groovy to libxxhash0>=0.8

After all, in Groovy there is a libxxhash0 0.8.0-1ubuntu1.20.10.1, so that would not be a problem. And it would fix issues for those mixing and matching packages.

Thanks!

Walter Doekes
OSSO B.V.

(*) possible patch:

$ diff -pu debian/control{.orig,}
--- debian/control.orig 2021-07-08 09:56:57.646861644 +0200
+++ debian/control 2021-07-08 09:57:38.499029903 +0200
@@ -8,7 +8,7 @@ Build-Depends: debhelper-compat (= 13),
                libacl1-dev,
                libpopt-dev,
                liblz4-dev,
- libxxhash-dev,
+ libxxhash-dev (>= 0.8),
                libzstd-dev,
                zlib1g-dev,
                libssl-dev

Revision history for this message
Wayne Davison (wayned) wrote :

You misread my comments. It's only the 128-bit hash that depends on 0.8.0. The 0.7 version works fine with rsync, giving it the 64-bit and 32-bit hashes.

Revision history for this message
Wayne Davison (wayned) wrote :

That said, of course, 0.8.0 is the better choice for the most possible features (if it is available).

Revision history for this message
Walter (wdoekes) wrote :

Hi Wayne! Thanks for commenting.

> It's only the 128-bit hash that depends on 0.8.0.
> The 0.7 version works fine with rsync, giving it
> the 64-bit and 32-bit hashes.

Yes. Except it seems that if you switch the libxxhash0 from 0.8 to 0.7, you get different behaviour.

rsync doesn't check what kind of xxh128 is produced, so we end up with a mismatch.

Steps to reproduce:

  wget -q https://launchpad.net/ubuntu/+archive/primary/+files/rsync_3.2.3-2ubuntu1_amd64.deb

  wget -q https://launchpad.net/ubuntu/+archive/primary/+files/libxxhash0_0.7.3-1_amd64.deb

  wget -q https://launchpad.net/ubuntu/+archive/primary/+files/libxxhash0_0.8.0-1ubuntu1.20.10.1_amd64.deb

focal-node-1:

  sudo dpkg -i libxxhash0_0.7.3-1_amd64.deb \
    rsync_3.2.3-2ubuntu1_amd64.deb
  touch empty-file.txt
  echo A > non-empty-file.txt

focal-node-2:

  sudo dpkg -i rsync_3.2.3-2ubuntu1_amd64.deb \
    libxxhash0_0.8.0-1ubuntu1.20.10.1_amd64.deb
  rsync -v --debug=nstr \
    focal-node-1:*empty-file.txt \
    .

Result:

  Client negotiated checksum: xxh128
  empty-file.txt
  WARNING: empty-file.txt failed verification
    -- update discarded (will try again).
  non-empty-file.txt
  WARNING: non-empty-file.txt failed verification
    -- update discarded (will try again).
  empty-file.txt
  ERROR: empty-file.txt failed verification
    -- update discarded.
  non-empty-file.txt
  ERROR: non-empty-file.txt failed verification
    -- update discarded.

  sent 104 bytes received 255 bytes 239.33 bytes/sec
  total size is 2 speedup is 0.01
  rsync error: some files/attrs were not transferred
    (see previous errors) (code 23) at main.c(1816)
    [generator=3.2.3]

focal-node-2:

  $ ls *empty*
  ls: cannot access '*empty*': No such file or directory

I don't mind if I don't get xxh128 and get some poorer hash. But I _do_ mind if I get a hash that produces different results.

If I install libxxhash0 0.7.3 on both: things work.

If I install libxxhash0 0.8.x on both: things work.

But when there is a mismatch, things break. And uselessly too. I ended up syncing lots of GBs multiple times because our job kept retrying.

I hope that clarifies the situation.

Walter

P.S. Alternative solutions could be:
- not exporting xxh128 functions from libxxhash0 0.7.3 (but it might be a bit late for that);
- checking that xxh128 produces sane values in rsync before choosing that option.

Revision history for this message
Utkarsh Gupta (utkarsh) wrote :

Hello Walter,

Thanks for filling the bug and helping in making the Ubuntu server better.

However, if I get everything right, I think you're mistaken about how it works and I am sorry but what you're trying to do is not correct! You cannot just decide to take one of the package from another release and the other from another release. That is not how it works, I am afraid :/

If you do a fresh installation of rsync on Groovy, everything works fine! See here:

$ lxc launch images:ubuntu/groovy groovy-rsync
$ lxc shell groovy-rsync
# apt update && apt install rsync
  ### here you'll see that the right version of libxxhash gets installed.
      (cf: `Setting up libxxhash0:amd64 (0.8.0-1ubuntu1.20.10.1) ...)
# ls -lah /usr/lib/x86_64-linux-gnu/libxxhash.so.0
lrwxrwxrwx 1 root root 18 Jan 12 11:17 /usr/lib/x86_64-linux-gnu/libxxhash.so.0 -> libxxhash.so.0.8.0

...which is linked against the right version. Further libxxhash-dev/0.8.0-1 is not in Focal but in Groovy, so the patch will not be right to apply in Focal. That said, I agree that it'd have been nice to have that version constraints but I don't see this as something that'd cause problems unless somebody tries to do some sort of manual intervention. :)

Given this, I am inclined towards believing that this is not really a bug in rsync but a "local" issue (that is, manually installing a version of rsync from Groovy to Focal and expecting it to work w/ libxxhash-dev). So I am setting this to "Incomplete" for now, leaving some space for discussion - in case I wrongly interpreted your problem and thus this report.

But should you feel that it's still a bug, please set the status back to "New" along with some reasoning (and hopefully a reproducer!) as to why you think that it's indeed a bug rather than a local issue. Thank you, again! \o/

Changed in rsync (Ubuntu):
status: New → Incomplete
Revision history for this message
Walter (wdoekes) wrote :

How about this case:

- I make a hypothetical package that depends on libxxhash < 0.8 because I want the "broken/old" xxh128 support;

- I have libxxhash 0.7.3 (that came with Focal);

- I have rsync 3.1.x (that came with Focal);

- Now I release-upgrade my system from Focal to Groovy;

- I get all kinds of new packages, including rsync 3.2.3;

- Dependency resolution fixes that I _don't_ get libxxhash 0.8 _because_ I have:

- (a) my hypothetical package pinned and it depends on libxxhash<0.8;

- (b) rsync that depends on libxxhash>=0.7.1.

- The dependencies are all still satisfied and I get to keep libxxhash=0.7.3.

In this new situation I have completed the upgrade to Groovy. As long as my hypothetical package that depends on libxxhash <0.8 exists, Ubuntu will not upgrade libxxhash.

And then I'm in the same situation as I am now:

root@groovy-rsync:~# apt-mark hold hypothetical-pkg
hypothetical-pkg set on hold.

root@groovy-rsync:~# apt-cache show hypothetical-pkg | grep ^Depe
Depends: libxxhash0 (<= 0.8)

root@groovy-rsync:~# apt-get install rsync
Reading package lists... Done
Building dependency tree
Reading state information... Done
Suggested packages:
  openssh-server
The following NEW packages will be installed:
  rsync

root@groovy-rsync:~# dpkg -l | grep -E 'rsync|libxxhash'
hi hypothetical-pkg 1.0
ii libxxhash0:amd64 0.7.3-1
ii rsync 3.2.3-2ubuntu1

root@groovy-rsync:~# apt-get dist-upgrade
Reading package lists... Done
Building dependency tree
Reading state information... Done
Calculating upgrade... Done
The following packages have been kept back:
  libxxhash0
0 upgraded, 0 newly installed, 0 to remove and 1 not upgraded.

This may not be the commonest of cases. But this would be an impossible situation if rsync_3.2.3 simply depended on 0.8+ instead of on 0.7.1+. (An impossible situation is good in this case, because you have to choose between either hypothetical-pkg or rsync.)

So, I still feel that this is a bug in the rsync control file in Groovy. Not a bug in the rsync source.

(Ok, in fact, I think it's ultimately a bug in soname-version/symbol handling of libxxhash. But that's not where the problem manifests itself.)

I'll leave it as is if you still feel it should be closed. But at least it has some visibility/presence on the internet so others are helped if they also run into this issue.

Cheers :)
Walter

Changed in rsync (Ubuntu):
status: Incomplete → New
Revision history for this message
Robie Basak (racb) wrote :

Sorry, the use cases you describe are not supported by Ubuntu.

You're welcome to hack your system as you wish, but that doesn't mean that we will necessarily make changes in Ubuntu to accommodate that. We do try to be helpful, of course. And in this case I agree that it is a bug that rsync doesn't depend on a higher version of libxxhash automatically. That's something we should fix, but it is of low priority but I don't expect such a fix to be backported to Groovy because, as presented at the moment, this doesn't meet our threshold of disrupting users to achieve such a change. See https://wiki.ubuntu.com/StableReleaseUpdates for details of our policies in this area.

In particular:

> - I make a hypothetical package that depends on libxxhash < 0.8 because I want the "broken/old" xxh128 support

Such a hypothetical package does not exist in the Ubuntu archive in practice. Adding third party packages is not something that Ubuntu can realistically support. The scenario you present is exactly why we don't support third party packages in the general case: they break distribution release upgrades.

> - libxxhash-dev,
> + libxxhash-dev (>= 0.8),

I don't think your patch will work as-is. You've changed the build dependency versioning, not the binary package dependency versioning. I suspect what needs adjusting is the symbols file in the xxhash source (debian/libxxhash0.symbols). However this needs further investigation and the low priority of this issue means that I'm not going to spend any more time on this unless a more important and supported use case is presented here.

> (Ok, in fact, I think it's ultimately a bug in soname-version/symbol handling of libxxhash. But that's not where the problem manifests itself.)

Right. We track bugs and their fixes by following the status of a fix against the root cause. So I'm going to reassign the bug to that package as it seems likely to me that this is where the problem lies.

> I'll leave it as is if you still feel it should be closed.

I agree that it's not correct that the binary dependency is wrong, so this bug can remain open if somebody wants to volunteer a fix. However, I suggest you find the fix and send it to wherever the problem originates in our ecosystem (maybe Debian? Or perhaps xxhash upstream?). Unless a supported use case is presented, I think it's unlikely that we'll carry a patch for this in Ubuntu.

> But at least it has some visibility/presence on the internet so others are helped if they also run into this issue.

Sure. People affected by this are welcome to coordinate in this bug.

I'm going to explicitly mark a Groovy task as Won't Fix to make it clear that we don't expect any change will be made in Groovy to fix this. The bug remains open to being fixed in a future Ubuntu release if a volunteer takes the appropriate steps to get the issue resolved at its actual origin.

affects: rsync (Ubuntu) → xxhash (Ubuntu)
Changed in xxhash (Ubuntu Groovy):
status: New → Won't Fix
Changed in xxhash (Ubuntu):
status: New → Triaged
importance: Undecided → Low
Revision history for this message
Robie Basak (racb) wrote :

> So I'm going to reassign the bug to that package as it seems likely to me that this is where the problem lies.

Actually I'm not sure it's a symbol versioning issue now. Looking at your error, perhaps it's a protocol negotiation issue in rsync? Either way, it needs further investigation by a volunteer, and the rest of my previous comment stands - I'd appreciate a fix at the origin of the problem, and that would go into a subsequent Ubuntu release - but I don't think it's appropriate to fix in Groovy based on the use case presented.

Revision history for this message
Wayne Davison (wayned) wrote :

Anyone who has an rsync that supports the xxh128 hash using the xxhash 0.7 library did something very bad in their build. An rsync compiled with that library only supports xxh64 & xxh32. Thus, this described mismatch never occurs in a stock rsync (the 128-bit hash was unstable in xxhash 0.7, and thus rsync doesn't use it).

Revision history for this message
Wayne Davison (wayned) wrote :

To be clear, if you have xxhash 0.7 and "rsync -V" reports xxh128 in the checksum list, fix the rsync build by getting rid of any patch that enabled that unsupported hash.

Revision history for this message
Walter (wdoekes) wrote :

Thanks, Robie, for the excellent response.

> Actually I'm not sure it's a symbol versioning issue now.

Maybe this example can persuade you that there is a problem between (lib)xxhash in Focal and in Groovy:

  focal$ xxh128sum <(echo -n)
  07fd4e968e916ae11f17545bce1061f1 /dev/fd/63

  groovy$ xxh128sum <(echo -n)
  99aa06d3014798d86001c324468d497f /dev/fd/63

> I suggest you find the fix and send it to wherever
> the problem originates in our ecosystem (maybe Debian?
> Or perhaps xxhash upstream?). Unless a supported
> use case is presented, I think it's unlikely that
> we'll carry a patch for this in Ubuntu.

I think I can safely say now that the problem originates in the Debian package:

if the symbols file is altered as I have done here [1] the problem goes away:
[1] https://github.com/norbusan/debian-xxhash/issues/3
```
--- a/debian/libxxhash0.symbols
+++ b/debian/libxxhash0.symbols
@@ -1,9 +1,9 @@
 libxxhash.so.0 libxxhash0 #MINVER#
- XXH128@Base 0.7.0
- XXH128_canonicalFromHash@Base 0.7.1
+ XXH128@Base 0.8.0
+ XXH128_canonicalFromHash@Base 0.8.0
...
```
A rebuild of rsync against a libxxhash0 with the above symbol changes will properly Depend on 0.8.0+.

I am just not intimately familiar with the rules for these symbol files, so I'm not 100% sure if the above changes are "legal". Can you shed some light on this?

> I'd appreciate a fix at the origin of the problem,
> and that would go into a subsequent Ubuntu release

Well. If we get the symbols file updated so it says 0.8.0, then subsequent updates from Debian would trickle into Ubuntu. Then any _new_ builds (of for example rsync) against the updated libxxhash library package would get the dependencies fixed.

That does leave the problem of libxxhash 0.7.x on Ubuntu/Focal:

- it has a broken xxh128sum binary
- it exposes access to old/invalid xxh128 functions leading to possible future problems when people start upgrading their libxxhash0

To remedy that, I would suggest a rebuild of xxhash + libxxhash0 on Focal where all xxh128 symbols/functionality is removed/blacklisted.

I could do some quilting that simply `#if 0`'s the relevant code. Is this something that would be accepted?

Walter (wdoekes)
description: updated
Revision history for this message
Robie Basak (racb) wrote :

Thank you for the further investigation.

It sounds like upstream broke ABI between libxxhash0 0.7 and libxxhash0 0.8 but did not bump the soname when they did so. Perhaps that's because upstream still considers this experimental as it has a version < 1.0, or perhaps that was a mistake. For a proper fix in the development release, I'd expect upstream to bump the soname to make the symbol's behaviour unambiguous. Without that, proper ABI compatibility is impossible since different distributions and releases will have different behaviour for the same soname and symbol depending on the version used to build the library.

> To remedy that, I would suggest a rebuild of xxhash + libxxhash0 on Focal where all xxh128 symbols/functionality is removed/blacklisted.

I'm not convinced. The use case you've presented is still of low/unsupported priority and not properly resolved upstream. On the other hand, we try not to break ABI in a stable release. And as pointed out:

> Results produced by v0.7.x are not comparable with results
> from v0.7.y. However, the API is completely stable, and it
> can safely be used for ephemeral data (local sessions).

...so if a user has built against libxxhash for such a use case that is supported by upstream, your proposal for changing Focal would break them.

Leaving Focal as-is still seems like the least-worst answer to me.

Revision history for this message
Walter (wdoekes) wrote :

> ...so if a user has built against libxxhash for such
> a use case that is supported by upstream, your proposal
> for changing Focal would break them.

*shrug*

I'd rather have my build break now than succeed and get harder to debug issues with failing cross device communication.

Well, I've done my part. Let me know if there's something I can do. I'll consider this closed on my end :)

Revision history for this message
Launchpad Janitor (janitor) wrote :

This bug was fixed in the package xxhash - 0.8.1-1

---------------
xxhash (0.8.1-1) unstable; urgency=medium

  * New maintainer. Closes: #1003524.
  * debian/copyright: Update copyright holder years for debian/*.
  * debian/control: Document Rules Requires Root as no.
  * Update package to use debhelper-compat = 13.
  * Bump Standards-Version to 4.6.0. No changes required.

 -- Josue Ortega <email address hidden> Fri, 14 Jan 2022 08:49:06 -0600

Changed in xxhash (Ubuntu):
status: Triaged → Fix Released
To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.