Refuse to extract entries with '..' in pathname.
Pointed out by: David Schultz
This commit is contained in:
parent
5c462188a4
commit
ec3c314996
@ -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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user