Package: tar
Version: 1.20-1+lenny1
Severity: important
Tag: patch
According to the changelog, the latest version of tar package in
lenny replaced rmt source with the one from paxutils for
security reasons. Unfortunately, it also made it impossible to
use tar and rmt together.
Here's what happens if one tries to tar to a remote file (ssh
plays the role of rsh, as is common nowadays):
$ tar cf localhost:foo.tar a-file
Password:
<... hangs forever ...>
Here's what the rmt binary is doing at the other end:
...
fstat64(0, {st_mode=S_IFIFO|0600, st_size=0, ...}) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) =
0xb77f5000
read(0, "Ofoo.tar\n65 O_WRONLY|O_CREAT\n"..., 4096) = 29
fstat64(1, {st_mode=S_IFIFO|0600, st_size=0, ...}) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) =
0xb77f4000
read(0,
<... hangs forever ...>
So, rmt receives the O command from tar, does not respond and
expects more commands. And tar keeps awaiting the response to
the O command. Both hang indefinitely.
After looking at the new rmt source code, it is rather puzzling
how that rmt from paxutils could ever work. The problem is that
it uses stdio for its stdout, and by default that is block
buffered. Let's try fixing that for stdout, and to boot, for
the debug file output of the new rmt, that has the same problem:
--- tar-1.20/rmt/rmt.c 2010-09-22 12:12:15.000000000 +1200
+++ tar-1.20/rmt/rmt.c 2010-09-22 12:16:09.000000000 +1200
@@ -696,6 +696,7 @@ parse_opt (int key, char *arg, struct ar
dbgout = fopen (arg, "w");
if (!dbgout)
error (EXIT_FAILURE, errno, _("cannot open %s"), arg);
+ setlinebuf(dbgout);
break;
case ARGP_KEY_FINI:
@@ -745,6 +746,7 @@ main (int argc, char **argv)
int idx;
int stop = 0;
+ setlinebuf(stdout);
program_name = argv[0];
// argp_version_setup ("rmt", rmt_authors);
That isn't enough, however:
$ tar cf localhost:foo.tar a-file
Password:
tar: localhost\:foo.tar: Cannot open: Invalid argument
tar: Error is not recoverable: exiting now
This further problem is now revealed by strace of the rmt side:
...
fstat64(0, {st_mode=S_IFIFO|0600, st_size=0, ...}) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) =
0xb77bf000
read(0, "Ofoo.tar\n65 O_WRONLY|O_CREAT\n"..., 4096) = 29
fstat64(1, {st_mode=S_IFIFO|0600, st_size=0, ...}) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) =
0xb77be000
write(1, "E22\n"..., 4) = 4
write(1, "invalid open mode\n"..., 18) = 18
read(0, ""..., 4096) = 0
exit_group(0) = ?
The decode_open_flag() function in the rmt from paxutils can not
cope with the `65 O_WRONLY|O_CREAT' value of the `mode' argument
(as rmt(8) calls it) that tar emits. The coexistence of numeric
and symbolic flag values breaks it. More quick fixing:
--- tar-1.20/rmt/rmt.c 2010-09-22 12:12:15.000000000 +1200
+++ tar-1.20/rmt/rmt.c 2010-09-22 12:16:09.000000000 +1200
@@ -238,8 +238,14 @@ decode_open_flag (const char *mstr, int
if (*mstr == 0)
break;
else if (c_isdigit (*mstr))
- v = strtol (mstr, (char**) &p, 10);
- else if (xlat_kw (mstr, "O_", open_flag_kw, &v, &p))
+ {
+ *pmode = strtol (mstr, (char**) &mstr, 10);
+ if (*mstr && !c_isblank (*mstr))
+ rmt_error_message (EINVAL, "invalid open mode");
+ continue;
+ }
+
+ if (xlat_kw (mstr, "O_", open_flag_kw, &v, &p))
{
rmt_error_message (EINVAL, "invalid open mode");
return 1;
@@ -265,7 +271,8 @@ decode_open_flag (const char *mstr, int
return 1;
}
}
- *pmode = mode;
+ if (mode)
+ *pmode = mode;
return 0;
}
Now my remote tar backups seem to work again, as they did with
tar 1.20-1 and earlier.
Whatever is best to do (applying fixes like the above to the rmt
from paxutils, properly porting the original security fix from a
safe version of tar upstream, or something yet different), but
anyhow, rmt in lenny had better work at all.
Cheers,
--
/Awesome Walrus <[email protected]>
--
To UNSUBSCRIBE, email to [email protected]
with a subject of "unsubscribe". Trouble? Contact [email protected]