unpack: count directory and symlink sizes

Also do not rely on unpack being called just once if we don't
have to and initialize counts.

Since we don't know directory size before populating with files,
we just accumulate the size on the second pass, but do not actually
check for the limit being reached. If there's any file after that,
that'll trip the check.
This commit is contained in:
Vincent Penquerc'h 2013-12-28 06:28:20 -05:00 committed by Marek Marczykowski-Górecki
parent 77d34c3096
commit af78e8d9e8

View File

@ -109,10 +109,15 @@ void process_one_file_dir(struct file_header *untrusted_hdr,
{ {
// fix perms only when the directory is sent for the second time // fix perms only when the directory is sent for the second time
// it allows to transfer r.x directory contents, as we create it rwx initially // it allows to transfer r.x directory contents, as we create it rwx initially
struct stat buf;
if (!mkdir(untrusted_name, 0700)) /* safe because of chroot */ if (!mkdir(untrusted_name, 0700)) /* safe because of chroot */
return; return;
if (errno != EEXIST) if (errno != EEXIST)
do_exit(errno, untrusted_name); do_exit(errno, untrusted_name);
if (stat(untrusted_name,&buf) < 0)
do_exit(errno, untrusted_name);
total_bytes += buf.st_size;
/* size accumulated after the fact, so don't check limit here */
fix_times_and_perms(untrusted_hdr, untrusted_name); fix_times_and_perms(untrusted_hdr, untrusted_name);
} }
@ -124,6 +129,9 @@ void process_one_file_link(struct file_header *untrusted_hdr,
if (untrusted_hdr->filelen > MAX_PATH_LENGTH - 1) if (untrusted_hdr->filelen > MAX_PATH_LENGTH - 1)
do_exit(ENAMETOOLONG, untrusted_name); do_exit(ENAMETOOLONG, untrusted_name);
filelen = untrusted_hdr->filelen; /* sanitized above */ filelen = untrusted_hdr->filelen; /* sanitized above */
total_bytes += filelen;
if (bytes_limit && total_bytes > bytes_limit)
do_exit(EDQUOT, untrusted_name);
if (!read_all_with_crc(0, untrusted_content, filelen)) if (!read_all_with_crc(0, untrusted_content, filelen))
do_exit(LEGAL_EOF, untrusted_name); // hopefully remote has produced error message do_exit(LEGAL_EOF, untrusted_name); // hopefully remote has produced error message
untrusted_content[filelen] = 0; untrusted_content[filelen] = 0;
@ -156,6 +164,7 @@ void process_one_file(struct file_header *untrusted_hdr)
int do_unpack() int do_unpack()
{ {
struct file_header untrusted_hdr; struct file_header untrusted_hdr;
total_bytes = total_files = 0;
/* initialize checksum */ /* initialize checksum */
crc32_sum = 0; crc32_sum = 0;
while (read_all_with_crc(0, &untrusted_hdr, sizeof untrusted_hdr)) { while (read_all_with_crc(0, &untrusted_hdr, sizeof untrusted_hdr)) {