Hi!

On Fri, 2026-03-27 at 16:17:02 +0000, Barak A. Pearlmutter wrote:
> Package: dpkg
> Version: 1.23.7

> I have a cool script that downloads a .deb file using curl, grovels the
> Version out of the beginning of the file, and aborts the download if
> it's not a new version. This is useful because Zoom just has a URL
> zoom_amd64.deb with no version number until you look inside. The script
> is at https://github.com/barak/zoom-ubuntu-repo/blob/master/zoom-up
> and the salient bash lines, simplified, are
> 
>   touch tmp/zoom
>   curl https://zoom.us/client/latest/zoom_amd64.deb >> tmp/zoom &
>   ...
>   v=$(dpkg --field <(tail --follow --bytes=+0 tmp/zoom) Version)
> 
> which gets the new version into $v ASAP so it can be tested and the
> download aborted as appropriate.

I'm wondering whether «wget -N» or the equivalent curl incantation
would not be an easier way to handle this? Perhaps you'd need to keep
the inode/device or a checksum of the file and compare before and
after. If so, that would mean dpkg-deb would stop being involved. :)

Of course all these still seems like a workaround for that vendor not
providing a proper repository, with properly named binary packages.
But I assume getting them to fix that is unfeasible? (But maybe worth
trying anyway?)

> This used to work fine, but with a new version of dpkg it gets
> 
>   dpkg-deb: error: archive '/dev/fd/63' is truncated or corrupt,
> expected more data than available (35724 > 0)

Yes, this was part of a set of changes in 1.23.6 to fix a security
issue due to insufficient validation, which is something I've had
pending for some time now, also to detect way earlier and be able to
give a proper error message when a truncated or partially downloaded
package is passed to dpkg (see f.ex. #929100).

> ISSUE
> 
> What's going on is that the new version of dpkg-deb does a seek on its
> file argument, which fails if it's not a real file.  You can see it
> here:
> 
>   $ dpkg --field /var/cache/apt/archives/task-ssh-server_3.86_all.deb Version
>   3.86
> 
>   $ dpkg --field <(cat
> /var/cache/apt/archives/task-ssh-server_3.86_all.deb) Version
>   dpkg-deb: error: archive '/dev/fd/63' is truncated or corrupt,
> expected more data than available (608 > 0)
> 
>   $ shasum /var/cache/apt/archives/task-ssh-server_3.86_all.deb
>   2454b0c8bec4b9f30efc5ef9a28e7dbfc76a3c65
> /var/cache/apt/archives/task-ssh-server_3.86_all.deb
> 
>   $ shasum <(cat /var/cache/apt/archives/task-ssh-server_3.86_all.deb)
>   2454b0c8bec4b9f30efc5ef9a28e7dbfc76a3c65  /dev/fd/63
> 
> It would be nice if dpkg-deb would continue to allow a non-seekable
> argument, so my lazy pipe stream trick would continue to work.

I didn't expect this to break anything!¹ And while I could change the
current check to take into account whether the archive file is a
pipe/socket/fifo and then ignore it when the archive size is 0, my plan
has been to switch the code to perform two passes anyway. One to analyze
the entire ar container for correctness, then perform a seek to extract
the requested member data, because at least for dpkg driving dpkg-deb
there's already a requirement that it cannot use pipes/fifos/sockets
for archives, due to it calling dpkg-deb multiple times (first to
extract the control member then the data member).

To st correct expectations, my first inclination right now would be to
declare that streaming is not supported. But I'll ponder a bit what it
would take to add support for such "streaming" mode in that new two
pass pre-analysis paradigm, and whether that would make sense, given
the potential security risks, where dpkg-deb is the one tool where it
is supposed to be able to handle untrusted .deb data (see the SECURITY
section in its man page), in contrast to dpkg, where the assumption is
that the archives are trusted.

¹ I guess this reminds me a bit of https://xkcd.com/1172/. :D

Thanks,
Guillem

Reply via email to