This is an automated email from the git hooks/post-receive script. guillem pushed a commit to branch main in repository dpkg.
View the commit online: https://git.dpkg.org/cgit/dpkg/dpkg.git/commit/?id=ed6bbd445dd8800308c67236ba35d08004c98e82 commit ed6bbd445dd8800308c67236ba35d08004c98e82 (HEAD -> main) Author: Guillem Jover <[email protected]> AuthorDate: Sat Jun 7 14:17:07 2025 +0200 dpkg-deb: Fix cleanup for control member with restricted directories When extracting a control member into a temporary directory, which is documented as being a safe operation even on untrusted data, the code in charge of the temporary directory cleanup does not sanitize the directory permissions, which is then unable to perform the «rm -rf» when running as a non-root user, leaving temporary files behind. Given automated and repeated execution of dpkg-deb commands on adversarial .deb packages or with well compressible files, placed inside a directory with permissions not allowing removal by a non-root user, this can end up with a DoS scenario due to causing disk quota exhaustion or disk full conditions. This is considered a minor issue, given the required conditions to trigger a problem with it, but an issue non the less given the documented security guarantees of the command. This has been an issue since the initial commit introducing dpkg-deb in C. We use an existing string for the error message to avoid new strings needing translation for stable branches, which make the error message less descriptive than what would be ideal. This will be improved in git HEAD. Reported-by: zhutyra on HackerOne Fixes: CVE-2025-6297 Stable-Candidate: 1.20.x 1.21.x 1.22.x --- src/at/deb-content.at | 32 ++++++++++++++++++++++++++++++++ src/deb/info.c | 20 ++++++++++++++++++++ 2 files changed, 52 insertions(+) diff --git a/src/at/deb-content.at b/src/at/deb-content.at index a192c9493..2b1d8b0f4 100644 --- a/src/at/deb-content.at +++ b/src/at/deb-content.at @@ -127,3 +127,35 @@ newline' ]) AT_CLEANUP + +AT_SETUP([dpkg-deb .deb extraction cleanup]) +AT_KEYWORDS([dpkg-deb deb extraction]) + +DPKG_GEN_CONTROL([pkg-ctrl-dir-perms]) +AT_CHECK([ +dpkg-deb --root-owner-group -Znone -b pkg-ctrl-dir-perms +DPKG_AR_EXTRACT([pkg-ctrl-dir-perms.deb]) +dpkg-deb -R pkg-ctrl-dir-perms.deb pkg-ctrl-dir-perms-bad +mkdir -p pkg-ctrl-dir-perms-bad/DEBIAN/rx-subdir/inner +touch pkg-ctrl-dir-perms-bad/DEBIAN/rx-subdir/inner/file +chmod 0555 pkg-ctrl-dir-perms-bad/DEBIAN +chmod 0555 pkg-ctrl-dir-perms-bad/DEBIAN/rx-subdir +chmod 0555 pkg-ctrl-dir-perms-bad/DEBIAN/rx-subdir/inner +$TAR cf control.tar --format=gnu --mtime @0 --clamp-mtime --owner root:0 --group root:0 -C pkg-ctrl-dir-perms-bad/DEBIAN . +DPKG_AR_GEN([pkg-ctrl-dir-perms.deb], [debian-binary control.tar data.tar]) +], [0], [dpkg-deb: building package 'pkg-ctrl-dir-perms' in 'pkg-ctrl-dir-perms.deb'. +]) +AT_CHECK([ +dpkg-deb --ctrl-tarfile pkg-ctrl-dir-perms.deb | $TAR tvf - +], [0], [dr-xr-xr-x root/root 0 1970-01-01 00:00 ./ +dr-xr-xr-x root/root 0 1970-01-01 00:00 ./rx-subdir/ +dr-xr-xr-x root/root 0 1970-01-01 00:00 ./rx-subdir/inner/ +-rw-r--r-- root/root 0 1970-01-01 00:00 ./rx-subdir/inner/file +-rw-r--r-- root/root 176 1970-01-01 00:00 ./control +]) +# Check that we can cleanup the temporarily extracted control.tar member. +AT_CHECK([ +dpkg-deb -I pkg-ctrl-dir-perms.deb +], [0], [ignore]) + +AT_CLEANUP diff --git a/src/deb/info.c b/src/deb/info.c index f3d57e2ce..396ea4d14 100644 --- a/src/deb/info.c +++ b/src/deb/info.c @@ -45,14 +45,34 @@ #include <dpkg/pkg-format.h> #include <dpkg/buffer.h> #include <dpkg/path.h> +#include <dpkg/treewalk.h> #include <dpkg/options.h> #include "dpkg-deb.h" +static int +cu_info_treewalk_fixup_dir(struct treenode *node) +{ + const char *nodename; + + if (!S_ISDIR(treenode_get_mode(node))) + return 0; + + nodename = treenode_get_pathname(node); + if (chmod(nodename, 0755) < 0) + ohshite(_("error setting permissions of '%.255s'"), nodename); + + return 0; +} + static void cu_info_prepare(int argc, void **argv) { char *dir; + struct treewalk_funcs cu_info_treewalk_funcs = { + .visit = cu_info_treewalk_fixup_dir, + }; dir = argv[0]; + treewalk(dir, TREEWALK_NONE, &cu_info_treewalk_funcs); path_remove_tree(dir); free(dir); } -- Dpkg.Org's dpkg

