summaryrefslogtreecommitdiffstats
path: root/usr.bin
diff options
context:
space:
mode:
authorkientzle <kientzle@FreeBSD.org>2004-04-28 18:53:07 +0000
committerkientzle <kientzle@FreeBSD.org>2004-04-28 18:53:07 +0000
commit83ecd7781ef9028a17cdb24709202983677ba2d3 (patch)
treebc28f0fdcee4c29b3cf40a0c24a606d6f2681d38 /usr.bin
parent5cd0d2d78cf151e5ee04863528af046a883e494b (diff)
downloadFreeBSD-src-83ecd7781ef9028a17cdb24709202983677ba2d3.zip
FreeBSD-src-83ecd7781ef9028a17cdb24709202983677ba2d3.tar.gz
Refuse to extract entries with '..' in pathname.
Pointed out by: David Schultz
Diffstat (limited to 'usr.bin')
-rw-r--r--usr.bin/tar/read.c47
1 files changed, 40 insertions, 7 deletions
diff --git a/usr.bin/tar/read.c b/usr.bin/tar/read.c
index 684a7ae..3023ddb 100644
--- a/usr.bin/tar/read.c
+++ b/usr.bin/tar/read.c
@@ -46,6 +46,7 @@ __FBSDID("$FreeBSD$");
static void list_item_verbose(struct bsdtar *, struct archive_entry *);
static void read_archive(struct bsdtar *bsdtar, char mode);
+static int security_problem(struct bsdtar *, struct archive_entry *);
void
tar_mode_t(struct bsdtar *bsdtar)
@@ -68,7 +69,6 @@ read_archive(struct bsdtar *bsdtar, char mode)
struct archive *a;
struct archive_entry *entry;
int format;
- const char *name;
int r;
while (*bsdtar->argv) {
@@ -123,12 +123,6 @@ read_archive(struct bsdtar *bsdtar, char mode)
if (excluded(bsdtar, archive_entry_pathname(entry)))
continue;
- name = archive_entry_pathname(entry);
- if (name[0] == '/' && !bsdtar->option_absolute_paths) {
- name++;
- archive_entry_set_pathname(entry, name);
- }
-
if (mode == 't') {
if (bsdtar->verbose < 2)
safe_fprintf(stdout, "%s",
@@ -156,6 +150,9 @@ read_archive(struct bsdtar *bsdtar, char mode)
!yes("extract '%s'", archive_entry_pathname(entry)))
continue;
+ if (security_problem(bsdtar, entry))
+ continue;
+
/*
* Format here is from SUSv2, including the
* deferred '\n'.
@@ -287,3 +284,39 @@ list_item_verbose(struct bsdtar *bsdtar, struct archive_entry *entry)
else if (S_ISLNK(st->st_mode)) /* Symbolic link */
safe_fprintf(out, " -> %s", archive_entry_symlink(entry));
}
+
+/*
+ * Check for a variety of security issues. Fix what we can here,
+ * generate warnings as appropriate, return non-zero to prevent
+ * this entry from being extracted.
+ */
+int
+security_problem(struct bsdtar *bsdtar, struct archive_entry *entry)
+{
+ const char *name, *p;
+
+ /* Strip leading '/' unless -P is specified. */
+ name = archive_entry_pathname(entry);
+ if (name[0] == '/' && !bsdtar->option_absolute_paths) {
+ /* XXX gtar generates a warning the first time this happens. */
+ name++;
+ archive_entry_set_pathname(entry, name);
+ }
+
+ /* Reject any archive entry with '..' as a path element. */
+ p = name;
+ while (p != NULL && p[0] != '\0') {
+ if (p[0] == '.' && p[1] == '.' &&
+ (p[2] == '\0' || p[2] == '/')) {
+ bsdtar_warnc(0,"pathname contains ..; skipping %s",
+ name);
+ return (1);
+ }
+ while (*p != '/' && *p != '\0')
+ p++;
+ if (*p != '\0')
+ p++;
+ }
+
+ return (0);
+}
OpenPOWER on IntegriCloud