On 2010-03-15, at 12:59, Denys Vlasenko wrote:
On Sat, Mar 13, 2010 at 1:20 AM, J. Tang <[email protected]> wrote:
+static void parse_extended_header(archive_handle_t *archive_handle, off_t sz)
+{
+       char *buf, *p, *next_p, *keyword, *value;
+       off_t len;
+
+       /* prevent a malloc of 0 */
+       if (sz == 0) {
+ bb_error_msg("Malformed extended header: length is 0");
+               return;
+       }

Why do you think such header is malformed?

Excellent point; instead of a warning, the function should simply return.

+ /* forcibly add a newline at the end of the buffer, to prevent
+          any buffer overflows */
+       p = buf = xmalloc(sz);
+       buf[sz - 1] = '\n';
+
+       xread(archive_handle->src_fd, buf, sz);

(1) You just overwrote your "\n".

Not necessarily. A malformed or malicious tarball might not have a \n to terminate the record.

(2) Look at docs/tar_pax.txt example. There, sz == 52
and by reading only 52 bytes here, you fall out of sync with
tar's 512-byte blocks.

There is no syncing problem, because when parse_extended_header() returns, there is a "goto again" to realign itself.

+       do {
+               /* skip leading whitespace */
+               while (*p == ' ' || *p == '\t') {
+                       p++;
+               }

Maybe use p = skip_whitespace(p) ?

skip_whitespace() also skips newlines.

+               if (!isdigit(*p)) {
+ bb_error_msg("Malformed extended header: missing length");
+                       return;
+               }
+
+               /* scan for the length of the record */
+
+               errno = 0;
+               len = strtoul(p, &keyword, 10);
+               if ((errno == ERANGE) || ((p + len) > (buf + sz))) {
+ bb_error_msg("Malformed extended header: length is out of allowed range");
+                       return;
+               }

Use bb_strtou, it makes error checking much simpler.
You will be able to drop isdigit check too.

Fixed.


+               while (*p != '=' && *p != '\n') {
+                       p++;
+               }
+               if (*p != '=') {
+ bb_error_msg("Malformed extended header: missing equal sign");
+                       return;
+               }

Can you use strchrnul instead of this block?

I do not believe that strchrnul() is appropriate here, because the buffer is not necessarily null terminated. It is guaranteed to be newline terminated because of the explicit set after xmalloc().


+               while (*p != '\n') {
+                       p++;
+               }
+               *p = '\0';

strchr

Ibid.

+               if (strcmp(keyword, SELINUX_CONTEXT_KEYWORD) == 0) {
+                       /* free old context, in case context is given
+                          multiple times */
+                       if (setfscreatecon(value) < 0) {
+ bb_perror_msg("warning: cannot set label to %s", value);

Drop "warning:" and use "'%s'", not "%s".
Imagine how message would look if value == ""...

Fixed.

I will have a new patch later, once I am able to test the changes on the target platform.

--
Jason Tang  /  [email protected]


_______________________________________________
busybox mailing list
[email protected]
http://lists.busybox.net/mailman/listinfo/busybox

Reply via email to