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=916fa148466cec6f47793d47177bd32dfb05e489 commit 916fa148466cec6f47793d47177bd32dfb05e489 Author: Guillem Jover <[email protected]> AuthorDate: Thu Nov 7 02:18:47 2024 +0100 dpkg-deb: Add support for filesystem metadata checks This adds checks for unusual and/or unexpected ownership of the root directory for the to be built package. This will help catch invocations where the resulting filesystem metadata would be wrong and potentially a security issue, as the build has not been made with a root-equivalent runner, such as fakeroot, or preferably by passing the --root-owner-group option. This is part of the effort to default to rootless builds, and to try to help external packaging efforts that might not be using Debian tooling update their build scaffolding. --- src/at/deb-content.at | 26 +++++++++++++------------- src/at/deb-fields.at | 6 +++--- src/deb/build.c | 25 +++++++++++++++++++++++++ 3 files changed, 41 insertions(+), 16 deletions(-) diff --git a/src/at/deb-content.at b/src/at/deb-content.at index f475603f9..a192c9493 100644 --- a/src/at/deb-content.at +++ b/src/at/deb-content.at @@ -11,7 +11,7 @@ AT_DATA([pkg-conff-duped/test-conffile-2], [test init ]) AT_CHECK([ # Duplicate conffile entries should produce a warning. -dpkg-deb -b pkg-conff-duped +dpkg-deb --root-owner-group -b pkg-conff-duped ], [0], [ignore], [dpkg-deb: warning: conffile name '/test-conffile-1' is duplicated dpkg-deb: warning: ignoring 1 warning about the control file(s) ]) @@ -23,7 +23,7 @@ AT_DATA([pkg-conff-noeol/test-conffile-1], [test init AT_CHECK([ # Conffiles need a final newline to guarantee there's been no accidental # file truncation. -dpkg-deb -b pkg-conff-noeol pkg-conff-noeol.deb +dpkg-deb --root-owner-group -b pkg-conff-noeol pkg-conff-noeol.deb ], [2], [ignore], [dpkg-deb: error: conffile name '/test-conffile-1' is too long, or missing final newline ]) @@ -33,7 +33,7 @@ AT_DATA([pkg-conff-noabs/test-conffile-rel], [test init ]) AT_CHECK([ # Conffiles must use absolute pathnames. -dpkg-deb -b pkg-conff-noabs pkg-conff-noabs.deb +dpkg-deb --root-owner-group -b pkg-conff-noabs pkg-conff-noabs.deb ], [2], [ignore], [dpkg-deb: error: conffile name 'test-conffile-rel' is not an absolute pathname ]) @@ -41,7 +41,7 @@ DPKG_GEN_CONTROL([pkg-conff-empty]) printf " \n" >"pkg-conff-empty/DEBIAN/conffiles" AT_CHECK([ # Conffiles must not contain empty lines. -dpkg-deb -b pkg-conff-empty pkg-conff-empty.deb +dpkg-deb --root-owner-group -b pkg-conff-empty pkg-conff-empty.deb ], [2], [ignore], [dpkg-deb: error: empty and whitespace-only lines are not allowed in conffiles ]) @@ -49,7 +49,7 @@ DPKG_GEN_CONTROL([pkg-conff-space-prefix]) DPKG_GEN_CTRL_FILE([pkg-conff-space-prefix], [conffiles], [ /test-conffile]) AT_CHECK([ # Conffiles must not contain prefixed spaces. -dpkg-deb -b pkg-conff-space-prefix pkg-conff-space-prefix.deb +dpkg-deb --root-owner-group -b pkg-conff-space-prefix pkg-conff-space-prefix.deb ], [2], [ignore], [dpkg-deb: error: line with conffile filename '/test-conffile' has leading white spaces ]) @@ -57,7 +57,7 @@ DPKG_GEN_CONTROL([pkg-conff-unknown-flag]) DPKG_GEN_CTRL_FILE([pkg-conff-unknown-flag], [conffiles], [unknown-flag /test-conffile]) AT_CHECK([ # Conffiles marked with an unknown flag. -dpkg-deb -b pkg-conff-unknown-flag pkg-conff-unknown-flag.deb +dpkg-deb --root-owner-group -b pkg-conff-unknown-flag pkg-conff-unknown-flag.deb ], [2], [ignore], [dpkg-deb: error: unknown flag 'unknown-flag' for conffile '/test-conffile' ]) @@ -65,7 +65,7 @@ DPKG_GEN_CONTROL([pkg-conff-missing-pathname]) printf "unknown-flag \n" >"pkg-conff-missing-pathname/DEBIAN/conffiles" AT_CHECK([ # Conffiles need a pathname, in addition to a flag. -dpkg-deb -b pkg-conff-missing-pathname pkg-conff-missing-pathname.deb +dpkg-deb --root-owner-group -b pkg-conff-missing-pathname pkg-conff-missing-pathname.deb ], [2], [ignore], [dpkg-deb: error: conffile name missing after flag 'unknown-flag' ]) @@ -73,7 +73,7 @@ DPKG_GEN_CONTROL([pkg-conff-removed-missing]) DPKG_GEN_CTRL_FILE([pkg-conff-removed-missing], [conffiles], [remove-on-upgrade /test-conffile-missing]) AT_CHECK([ # Conffiles marked for removal must not be present. -dpkg-deb -b pkg-conff-removed-missing pkg-conff-removed-missing.deb +dpkg-deb --root-owner-group -b pkg-conff-removed-missing pkg-conff-removed-missing.deb ], [0], [ignore], []) DPKG_GEN_CONTROL([pkg-conff-removed-duped]) @@ -82,7 +82,7 @@ remove-on-upgrade /test-conffile-2 remove-on-upgrade /test-conffile-1]) AT_CHECK([ # Duplicate conffile entries should produce a warning. -dpkg-deb -b pkg-conff-removed-duped +dpkg-deb --root-owner-group -b pkg-conff-removed-duped ], [0], [ignore], [dpkg-deb: warning: conffile name '/test-conffile-1' is duplicated dpkg-deb: warning: ignoring 1 warning about the control file(s) ]) @@ -92,7 +92,7 @@ printf "remove-on-upgrade /test-conffile-1" >"pkg-conff-removed-noeol/DEBIAN/con AT_CHECK([ # Conffiles need a final newline to guarantee there has been no accidental # file truncation. -dpkg-deb -b pkg-conff-removed-noeol pkg-conff-removed-noeol.deb +dpkg-deb --root-owner-group -b pkg-conff-removed-noeol pkg-conff-removed-noeol.deb ], [2], [ignore], [dpkg-deb: error: conffile name 'remove-on-upgrade /test-conffile-1' is too long, or missing final newline ]) @@ -102,7 +102,7 @@ AT_DATA([pkg-conff-removed-noabs/test-conffile-rel], [test init ]) AT_CHECK([ # Conffiles must use absolute pathnames. -dpkg-deb -b pkg-conff-removed-noabs pkg-conff-removed-noabs.deb +dpkg-deb --root-owner-group -b pkg-conff-removed-noabs pkg-conff-removed-noabs.deb ], [2], [ignore], [dpkg-deb: error: conffile name 'test-conffile-rel' is not an absolute pathname ]) @@ -112,7 +112,7 @@ AT_DATA([pkg-conff-removed-present/test-conffile-present], [test init ]) AT_CHECK([ # Conffiles marked for removal must not be present. -dpkg-deb -b pkg-conff-removed-present pkg-conff-removed-present.deb +dpkg-deb --root-owner-group -b pkg-conff-removed-present pkg-conff-removed-present.deb ], [2], [ignore], [dpkg-deb: error: conffile '/test-conffile-present' is present but is requested to be removed ]) @@ -121,7 +121,7 @@ touch 'pkg-deb-newline/file newline' AT_CHECK([ # Cannot create package with newlines in filenames. -dpkg-deb -b pkg-deb-newline +dpkg-deb --root-owner-group -b pkg-deb-newline ], [2], [ignore], [dpkg-deb: error: newline not allowed in pathname './file newline' ]) diff --git a/src/at/deb-fields.at b/src/at/deb-fields.at index ccc733af9..89c3e0e84 100644 --- a/src/at/deb-fields.at +++ b/src/at/deb-fields.at @@ -3,7 +3,7 @@ AT_KEYWORDS([dpkg-deb deb fields]) DPKG_GEN_CONTROL([pkg-package-type-void]) AT_CHECK([ -dpkg-deb -b pkg-package-type-void +dpkg-deb --root-owner-group -b pkg-package-type-void # Test absence of Package-Type field. test -z "$(dpkg-deb -f pkg-package-type-void.deb Package-Type)" ], [0], [ignore]) @@ -12,7 +12,7 @@ DPKG_GEN_CONTROL([pkg-package-type-use]) DPKG_MOD_CONTROL([pkg-package-type-use], [s/^Package: .*$/$&\nPackage-Type: udeb/]) AT_CHECK([ -dpkg-deb -b pkg-package-type-use +dpkg-deb --root-owner-group -b pkg-package-type-use # Test presence of Package-Type field. test -n "$(dpkg-deb -f pkg-package-type-use.deb Package-Type)" ], [0], [ignore]) @@ -29,7 +29,7 @@ DPKG_MOD_CONTROL([pkg-obsolete-fields], DPKG_MOD_CONTROL([pkg-obsolete-fields], [s/^Package:.*$/$&\nRecommended: recommends/]) AT_CHECK([ -dpkg-deb -b pkg-obsolete-fields +dpkg-deb --root-owner-group -b pkg-obsolete-fields ], [0], [ignore], [dpkg-deb: warning: parsing file 'pkg-obsolete-fields/DEBIAN/control' near line 2 package 'pkg-obsolete-fields': obsolete 'Recommended' field used diff --git a/src/deb/build.c b/src/deb/build.c index fbf6f75e0..5a50056fe 100644 --- a/src/deb/build.c +++ b/src/deb/build.c @@ -385,6 +385,30 @@ check_ctrl_control(const char *ctrldir) return pkg; } +/** + * Check fsys permissions. + */ +static void +check_fsys_perms(const char *rootdir) +{ + struct stat st; + + if (opt_root_owner_group) + return; + + if (lstat(rootdir, &st)) + ohshite(_("cannot get root directory %s metadata"), rootdir); + if (!S_ISDIR(st.st_mode)) + ohshit(_("root pathname %s is not a directory"), rootdir); + if (st.st_uid != 0 || st.st_gid != 0) { + warning(_("root directory %s has unusual owner or group %u:%u"), + rootdir, st.st_uid, st.st_gid); + info(_("Hint: you might need to pass --root-owner-group, " + "see <%s> for further details"), + "https://wiki.debian.org/Teams/Dpkg/RootlessBuilds"); + } +} + /** * Perform some sanity checks on the to-be-built package. * @@ -401,6 +425,7 @@ check_build_files(const char *ctrldir, const char *rootdir) /* Start by reading in the control file so we can check its contents. */ pkg = check_ctrl_control(ctrldir); check_ctrl_perms(ctrldir); + check_fsys_perms(rootdir); check_conffiles(ctrldir, rootdir); warns = warning_get_count(); -- Dpkg.Org's dpkg

