summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--debian/changelog3
-rw-r--r--dpkg-deb/dpkg-deb.h2
-rw-r--r--dpkg-deb/extract.c16
3 files changed, 13 insertions, 8 deletions
diff --git a/debian/changelog b/debian/changelog
index 8ed5546f1..03893d071 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -13,6 +13,9 @@ dpkg (1.19.1) UNRELEASED; urgency=medium
be needed. Reported by Niels Thykier <niels@thykier.net>.
* Add color support to dpkg-maintscript-helper (a shell script).
* Fix warning by including <sys/sysmacros.h> for makedev() in libdpkg.
+ * Fix directory traversal with dpkg-deb --raw-extract, by guaranteeing
+ that the DEBIAN pathname does not exist. Closes: #879982
+ Reported by Jakub Wilk <jwilk@jwilk.net>.
* Perl modules:
- Check that $tarname is defined before use in Dpkg::Source::Package::V1.
Thanks to Christoph Biedl <debian.axhn@manchmal.in-ulm.de>.
diff --git a/dpkg-deb/dpkg-deb.h b/dpkg-deb/dpkg-deb.h
index 6fd8f2b0a..a5e8d39ce 100644
--- a/dpkg-deb/dpkg-deb.h
+++ b/dpkg-deb/dpkg-deb.h
@@ -54,6 +54,8 @@ enum dpkg_tar_options {
DPKG_TAR_PERMS = DPKG_BIT(2),
/** Do not set tar mtime on extract. */
DPKG_TAR_NOMTIME = DPKG_BIT(3),
+ /** Guarantee extraction into a new directory, abort if it exists. */
+ DPKG_TAR_CREATE_DIR = DPKG_BIT(4),
};
void extracthalf(const char *debar, const char *dir,
diff --git a/dpkg-deb/extract.c b/dpkg-deb/extract.c
index ddb8709cd..dba15dedb 100644
--- a/dpkg-deb/extract.c
+++ b/dpkg-deb/extract.c
@@ -336,15 +336,15 @@ extracthalf(const char *debar, const char *dir,
unsetenv("TAR_OPTIONS");
if (dir) {
- if (chdir(dir)) {
- if (errno != ENOENT)
- ohshite(_("failed to chdir to directory"));
-
- if (mkdir(dir, 0777))
+ if (mkdir(dir, 0777) != 0) {
+ if (errno != EEXIST)
ohshite(_("failed to create directory"));
- if (chdir(dir))
- ohshite(_("failed to chdir to directory after creating it"));
+
+ if (taroption & DPKG_TAR_CREATE_DIR)
+ ohshite(_("unexpected pre-existing pathname %s"), dir);
}
+ if (chdir(dir) != 0)
+ ohshite(_("failed to chdir to directory"));
}
command_exec(&cmd);
@@ -490,7 +490,7 @@ do_raw_extract(const char *const *argv)
data_options |= DPKG_TAR_LIST;
extracthalf(debar, dir, data_options, 0);
- extracthalf(debar, control_dir, DPKG_TAR_EXTRACT, 1);
+ extracthalf(debar, control_dir, DPKG_TAR_EXTRACT | DPKG_TAR_CREATE_DIR, 1);
free(control_dir);