diff options
author | kientzle <kientzle@FreeBSD.org> | 2004-04-28 18:53:07 +0000 |
---|---|---|
committer | kientzle <kientzle@FreeBSD.org> | 2004-04-28 18:53:07 +0000 |
commit | 83ecd7781ef9028a17cdb24709202983677ba2d3 (patch) | |
tree | bc28f0fdcee4c29b3cf40a0c24a606d6f2681d38 /usr.bin | |
parent | 5cd0d2d78cf151e5ee04863528af046a883e494b (diff) | |
download | FreeBSD-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.c | 47 |
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); +} |