summaryrefslogtreecommitdiff
path: root/bin/pax/pat_rep.c
diff options
context:
space:
mode:
authorPhilip Guenther <guenther@cvs.openbsd.org>2015-03-09 04:23:30 +0000
committerPhilip Guenther <guenther@cvs.openbsd.org>2015-03-09 04:23:30 +0000
commitb6b3f50a9ed5827544d33f45b4ea05a0c5df9e34 (patch)
treeb683fe8f50a6acb13f707f6b0670867d3a56dc9a /bin/pax/pat_rep.c
parenta86810706f7590c416472a4fe7763693a8532531 (diff)
Unrevert post-unlock:
* Prevent an archive from esacaping the current directory by itself: when extracting a symlink whose value is absolute or contains ".." components, just create a zero-length normal file (with additional tracking of the mode and hardlinks to the symlink) until everything else is extracted, then go back and replace it with the requested link (if it's still that zero-length placeholder). * For tar without -P, if a path in the archive has any ".." components then strip everything up to and including the last of them (if it ends in ".." then it becomes ".") This mostly follows GNU tar's behavior, except for 'tar tf' and 'tar xvf' we report the modified path that would be/was actually created instead of the raw path from the archive Above two fixes prompted by a report from Daniel Cegielka (daniel.cegielka (at) gmail.com) * For directories whose times or mode will be fixed up in the clean-up pass, record their dev+ino and then use open(O_DIRECTORY)+fstat() to verify that we're updating the correct directory before using futimens() and fchmod(). * Correct buffer overflow in handling of pax extension headers, caught by the memcpy() overlap check. previously ok millert@ deraadt@
Diffstat (limited to 'bin/pax/pat_rep.c')
-rw-r--r--bin/pax/pat_rep.c45
1 files changed, 44 insertions, 1 deletions
diff --git a/bin/pax/pat_rep.c b/bin/pax/pat_rep.c
index 55def38fa9c..92696b38dc8 100644
--- a/bin/pax/pat_rep.c
+++ b/bin/pax/pat_rep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pat_rep.c,v 1.37 2015/02/21 22:48:23 guenther Exp $ */
+/* $OpenBSD: pat_rep.c,v 1.38 2015/03/09 04:23:29 guenther Exp $ */
/* $NetBSD: pat_rep.c,v 1.4 1995/03/21 09:07:33 cgd Exp $ */
/*-
@@ -583,6 +583,25 @@ range_match(char *pattern, int test)
}
/*
+ * has_dotdot()
+ * Returns true iff the supplied path contains a ".." component.
+ */
+
+int
+has_dotdot(const char *path)
+{
+ const char *p = path;
+
+ while ((p = strstr(p, "..")) != NULL) {
+ if ((p == path || p[-1] == '/') &&
+ (p[2] == '/' || p[2] == '\0'))
+ return (1);
+ p += 2;
+ }
+ return (0);
+}
+
+/*
* mod_name()
* modify a selected file name. first attempt to apply replacement string
* expressions, then apply interactive file rename. We apply replacement
@@ -632,6 +651,30 @@ mod_name(ARCHD *arcn)
paxwarn(0, "Removing leading / from absolute path names in the archive");
}
}
+ if (rmleadslash) {
+ const char *last = NULL;
+ const char *p = arcn->name;
+
+ while ((p = strstr(p, "..")) != NULL) {
+ if ((p == arcn->name || p[-1] == '/') &&
+ (p[2] == '/' || p[2] == '\0'))
+ last = p + 2;
+ p += 2;
+ }
+ if (last != NULL) {
+ last++;
+ paxwarn(1, "Removing leading \"%.*s\"",
+ (int)(last - arcn->name), arcn->name);
+ arcn->nlen = strlen(last);
+ if (arcn->nlen > 0)
+ memmove(arcn->name, last, arcn->nlen + 1);
+ else {
+ arcn->name[0] = '.';
+ arcn->name[1] = '\0';
+ arcn->nlen = 1;
+ }
+ }
+ }
/*
* IMPORTANT: We have a problem. what do we do with symlinks?