b41f97a782
of the filename is a symbolic link. Note: in some cases the file may still be opened which can in itself be a problem. This solves the security hole where the bad-guy creates a symbolic link named /tmp/screen-exchange pointing to a file that s/he wishes root to clobber.
65 lines
1.6 KiB
Plaintext
65 lines
1.6 KiB
Plaintext
--- fileio.c.~1~ Thu May 1 08:50:25 1997
|
|
+++ fileio.c Mon Jul 27 17:49:58 1998
|
|
@@ -291,6 +291,52 @@
|
|
DoCommand(args);
|
|
}
|
|
|
|
+/*
|
|
+ * Attempt to determine if we're opening the named file or if it
|
|
+ * has been replaced by a symbolic link to someplace not nice.
|
|
+ * Algorithm is:
|
|
+ *
|
|
+ * 1) lstat( name );
|
|
+ * if a symbolic link don't even try the open
|
|
+ * 2) fd = open( name );
|
|
+ * 3) fstat( fd );
|
|
+ * 4) lstat( name );
|
|
+ * 5) if fstat st_dev and st_ino don't match the lstat values
|
|
+ * then we lost a race and someone added a link between
|
|
+ * the first lstat and the open. Close the file and
|
|
+ * log an error. Note: this can still cause problems;
|
|
+ * e.g. a link to /dev/st0 will cause a tape to be
|
|
+ * rewound when the file is closed.
|
|
+ */
|
|
+static FILE *
|
|
+NoLinkOpen( char * fn, char * mode )
|
|
+{
|
|
+ struct stat linkstat;
|
|
+ struct stat filestat;
|
|
+ FILE * f;
|
|
+
|
|
+ if ( lstat( fn, &linkstat ) == 0 &&
|
|
+ linkstat.st_mode == S_IFLNK )
|
|
+ goto err;
|
|
+
|
|
+ f = fopen( fn, mode );
|
|
+ if ( ! f )
|
|
+ return 0;
|
|
+
|
|
+ if ( fstat( fileno( f ), &filestat ) == 0 &&
|
|
+ lstat( fn, &linkstat ) == 0 &&
|
|
+ linkstat.st_mode != S_IFLNK &&
|
|
+ linkstat.st_dev == filestat.st_dev &&
|
|
+ linkstat.st_ino == filestat.st_ino )
|
|
+ return f;
|
|
+
|
|
+ fclose( f );
|
|
+
|
|
+ err:
|
|
+ Msg(0, "Warning: file not opened, \"%s\" is a symbolic link.", fn);
|
|
+ return 0;
|
|
+}
|
|
+
|
|
void
|
|
WriteFile(dump)
|
|
int dump;
|
|
@@ -337,7 +383,7 @@
|
|
if (UserContext() > 0)
|
|
{
|
|
debug("Writefile: usercontext\n");
|
|
- if ((f = fopen(fn, mode)) == NULL)
|
|
+ if ((f = NoLinkOpen(fn, mode)) == NULL)
|
|
{
|
|
debug2("WriteFile: fopen(%s,\"%s\") failed\n", fn, mode);
|
|
UserReturn(0);
|