aboutsummaryrefslogtreecommitdiff
path: root/gnu
diff options
context:
space:
mode:
Diffstat (limited to 'gnu')
-rw-r--r--gnu/usr.bin/cpio/copyout.c111
-rw-r--r--gnu/usr.bin/tar/create.c34
-rw-r--r--gnu/usr.bin/tar/tar.c2
3 files changed, 142 insertions, 5 deletions
diff --git a/gnu/usr.bin/cpio/copyout.c b/gnu/usr.bin/cpio/copyout.c
index 35682e1b7453..933e4dad0778 100644
--- a/gnu/usr.bin/cpio/copyout.c
+++ b/gnu/usr.bin/cpio/copyout.c
@@ -35,6 +35,7 @@ static void add_link_defer ();
static void writeout_other_defers ();
static void writeout_final_defers();
static void writeout_defered_file ();
+static int check_rdev ();
/* Write out header FILE_HDR, including the file name, to file
descriptor OUT_DES. */
@@ -337,6 +338,21 @@ process_copy_out ()
error (0, 0, "%s: file name too long", file_hdr.c_name);
continue;
}
+ switch (check_rdev (&file_hdr))
+ {
+ case 1:
+ error (0, 0, "%s not dumped: major number would be truncated",
+ file_hdr.c_name);
+ continue;
+ case 2:
+ error (0, 0, "%s not dumped: minor number would be truncated",
+ file_hdr.c_name);
+ continue;
+ case 4:
+ error (0, 0, "%s not dumped: device number would be truncated",
+ file_hdr.c_name);
+ continue;
+ }
/* Copy the named file to the output. */
switch (file_hdr.c_mode & CP_IFMT)
@@ -799,3 +815,98 @@ writeout_defered_file (header, out_file_des)
}
return;
}
+
+static int
+check_rdev (file_hdr)
+ struct new_cpio_header *file_hdr;
+{
+ if (archive_format == arf_newascii || archive_format == arf_crcascii)
+ {
+ if ((file_hdr->c_rdev_maj & 0xFFFFFFFF) != file_hdr->c_rdev_maj)
+ return 1;
+ if ((file_hdr->c_rdev_min & 0xFFFFFFFF) != file_hdr->c_rdev_min)
+ return 2;
+ }
+ else if (archive_format == arf_oldascii || archive_format == arf_hpoldascii)
+ {
+#ifndef __MSDOS__
+ dev_t rdev;
+
+ rdev = makedev (file_hdr->c_rdev_maj, file_hdr->c_rdev_min);
+ if (archive_format == arf_oldascii)
+ {
+ if ((rdev & 0xFFFF) != rdev)
+ return 4;
+ }
+ else
+ {
+ switch (file_hdr->c_mode & CP_IFMT)
+ {
+ case CP_IFCHR:
+ case CP_IFBLK:
+#ifdef CP_IFSOCK
+ case CP_IFSOCK:
+#endif
+#ifdef CP_IFIFO
+ case CP_IFIFO:
+#endif
+ /* We could handle one more bit if longs are >= 33 bits. */
+ if ((rdev & 037777777777) != rdev)
+ return 4;
+ break;
+ default:
+ if ((rdev & 0xFFFF) != rdev)
+ return 4;
+ break;
+ }
+ }
+#endif
+ }
+ else if (archive_format == arf_tar || archive_format == arf_ustar)
+ {
+ /* The major and minor formats are limited to 7 octal digits in ustar
+ format, and to_oct () adds a gratuitous trailing blank to further
+ limit the format to 6 octal digits. */
+ if ((file_hdr->c_rdev_maj & 0777777) != file_hdr->c_rdev_maj)
+ return 1;
+ if ((file_hdr->c_rdev_min & 0777777) != file_hdr->c_rdev_min)
+ return 2;
+ }
+ else
+ {
+#ifndef __MSDOS__
+ dev_t rdev;
+
+ rdev = makedev (file_hdr->c_rdev_maj, file_hdr->c_rdev_min);
+ if (archive_format != arf_hpbinary)
+ {
+ if ((rdev & 0xFFFF) != rdev)
+ return 4;
+ }
+ else
+ {
+ switch (file_hdr->c_mode & CP_IFMT)
+ {
+ case CP_IFCHR:
+ case CP_IFBLK:
+#ifdef CP_IFSOCK
+ case CP_IFSOCK:
+#endif
+#ifdef CP_IFIFO
+ case CP_IFIFO:
+#endif
+ if ((rdev & 0xFFFFFFFF) != rdev)
+ return 4;
+ file_hdr->c_filesize = rdev;
+ rdev = makedev (0, 1);
+ break;
+ default:
+ if ((rdev & 0xFFFF) != rdev)
+ return 4;
+ break;
+ }
+ }
+#endif
+ }
+ return 0;
+}
diff --git a/gnu/usr.bin/tar/create.c b/gnu/usr.bin/tar/create.c
index 5d1b71c94b6d..c3be00cb1a1d 100644
--- a/gnu/usr.bin/tar/create.c
+++ b/gnu/usr.bin/tar/create.c
@@ -875,10 +875,20 @@ dump_file (p, curdev, toplevel)
#if defined(S_IFBLK) || defined(S_IFCHR)
if (type != LF_FIFO)
{
- to_oct ((long) major (hstat.st_rdev), 8,
- header->header.devmajor);
- to_oct ((long) minor (hstat.st_rdev), 8,
- header->header.devminor);
+ if (checked_to_oct ((long) major (hstat.st_rdev), 8,
+ header->header.devmajor))
+ {
+ msg ("%s: major number too large; not dumped", p);
+ critical_error = 1;
+ goto badfile;
+ }
+ if (checked_to_oct ((long) minor (hstat.st_rdev), 8,
+ header->header.devminor))
+ {
+ msg ("%s: minor number too large; not dumped", p);
+ critical_error = 1;
+ goto badfile;
+ }
}
#endif
@@ -1397,6 +1407,22 @@ to_oct (value, digs, where)
/*
+ * Call to_oct (), then return nonzero iff the conversion failed.
+ */
+int
+checked_to_oct (value, digs, where)
+ register long value;
+ register int digs;
+ register char *where;
+{
+ long from_oct ();
+
+ to_oct (value, digs, where);
+ return from_oct (digs, where) != value;
+}
+
+
+/*
* Write the EOT record(s).
* We actually zero at least one record, through the end of the block.
* Old tar writes garbage after two zeroed records -- and PDtar used to.
diff --git a/gnu/usr.bin/tar/tar.c b/gnu/usr.bin/tar/tar.c
index 638598667e6b..84e2b94283ce 100644
--- a/gnu/usr.bin/tar/tar.c
+++ b/gnu/usr.bin/tar/tar.c
@@ -281,7 +281,7 @@ main (argc, argv)
}
if (f_volno_file)
closeout_volume_number ();
- exit (errors);
+ exit (errors ? EX_ARGSBAD : 0); /* FIXME (should be EX_NONDESCRIPT) */
/* NOTREACHED */
}