[4463] in Kerberos
"krb5_rc_io_move" does the unexpected
daemon@ATHENA.MIT.EDU (Jim Miller)
Mon Jan 9 18:08:05 1995
From: jim@bilbo.suite.com (Jim Miller)
Date: Mon, 9 Jan 95 16:45:27 -0600
To: krb5-bugs@MIT.EDU
Cc: kerberos@MIT.EDU
Reply-To: Jim_Miller@suite.com
This bug report is for KRB5, beta 4, patchlevel 3.
The function "krb5_rc_io_move" does something it shouldn't. Here's the
code:
krb5_error_code krb5_rc_io_move (new, old)
krb5_rc_iostuff *new;
krb5_rc_iostuff *old;
{
if (rename(old->fn,new->fn) == -1) /* MUST be atomic! */
return KRB5_RC_IO_UNKNOWN;
(void) krb5_rc_io_close(new); <- ** frees new->fn
new->fn = old->fn; <- ** new's original fn is lost
new->fd = old->fd;
return 0;
}
Currently, the only place that "krb5_rc_io_move" is called is at the end
of "krb5_rc_dfl_expunge". In this case, "new" is the rcache you're trying
to expunge and "old" is the temporary rcache with a funny temporary name.
The intent of the call to "krb5_rc_io_move" is to rename the expunged tmp
rcache to the same name as the original un-expunged rcache, wiping out the
original file. The wipe out happens as planned, but a side effect is that
the "new" rcache struct (which is supposed to be the origianal rcache) is
given "tmp's" funny temporary file name. "new's" original name is lost.
This screws up "krb5_rc_destroy" because it tries to unlink the file named
in the rcache struct, but because of "krb5_rc_io_move", the name is the
funny temporary file name which doesn't exist anymore (it got renamed).
Solution:
"krb5_rc_io_move" needs to preserve the name held in "new->fn". Something
like the following should do the trick:
-------------------------------------------------
krb5_error_code krb5_rc_io_move (new, old)
krb5_rc_iostuff *new;
krb5_rc_iostuff *old;
{
char *tmp_fn;
if (rename(old->fn,new->fn) == -1) /* MUST be atomic! */
return KRB5_RC_IO_UNKNOWN;
tmp_fn = new->fn;
new->fn = 0; /* zero to prevent freeing */
(void) krb5_rc_io_close(new); /* modified to check for 0 fn */
new->fn = tmp_fn; /* preserve original fn */
new->fd = old->fd;
return 0;
}
-------------------------------------------------
krb5_error_code krb5_rc_io_close (d)
krb5_rc_iostuff *d;
{
if (d->fn) { <- *** new: only frees if non-NULL
FREE(d->fn);
d->fn = NULL;
}
if (close(d->fd) == -1) /* can't happen */
return KRB5_RC_IO_UNKNOWN;
return 0;
}
-------------------------------------------------
Jim_Miller@suite.com