Okay, now abort if the symlink isn't owned by the user, and some mode fixes
git-svn-id: svn://svn.savannah.gnu.org/nano/trunk/nano@364 35c25a1d-7b9e-4130-9fde-d3aeb78583b8master
parent
3ea0a8f1d6
commit
f7ee9e6996
|
@ -23,7 +23,8 @@ CVS code -
|
||||||
- files.c:
|
- files.c:
|
||||||
write_file()
|
write_file()
|
||||||
- Unsetting modified on temp files bug fixed (Rocco Corsi).
|
- Unsetting modified on temp files bug fixed (Rocco Corsi).
|
||||||
- Okay, if tmp == 1 and the file is a symlink, we return -1.
|
- Okay, if tmp == 1 and the file is a symlink the user doesn't
|
||||||
|
own, we return -1.
|
||||||
do_insertfile()
|
do_insertfile()
|
||||||
- Added call to real_name_from tilde, oops. Added check for
|
- Added call to real_name_from tilde, oops. Added check for
|
||||||
DISABLE_TABCOMP.
|
DISABLE_TABCOMP.
|
||||||
|
|
43
files.c
43
files.c
|
@ -301,7 +301,7 @@ int write_file(char *name, int tmp)
|
||||||
long size, lineswritten = 0;
|
long size, lineswritten = 0;
|
||||||
char buf[PATH_MAX + 1];
|
char buf[PATH_MAX + 1];
|
||||||
filestruct *fileptr;
|
filestruct *fileptr;
|
||||||
int fd, mask = 0;
|
int fd, mask = 0, realexists;
|
||||||
struct stat st;
|
struct stat st;
|
||||||
static char *realname = NULL;
|
static char *realname = NULL;
|
||||||
|
|
||||||
|
@ -321,16 +321,20 @@ int write_file(char *name, int tmp)
|
||||||
realname = mallocstrcpy(realname, name);
|
realname = mallocstrcpy(realname, name);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* Save the state of file at the end of the symlink */
|
||||||
|
realexists = stat(realname, &st);
|
||||||
|
|
||||||
/* Check to see if the file is a regular file and FOLLOW_SYMLINKS is
|
/* Check to see if the file is a regular file and FOLLOW_SYMLINKS is
|
||||||
set. If so then don't do the delete and recreate code which would
|
set. If so then don't do the delete and recreate code which would
|
||||||
cause unexpected behavior */
|
cause unexpected behavior */
|
||||||
lstat(realname, &st);
|
lstat(realname, &st);
|
||||||
|
|
||||||
/* New case: if it's a symlink and tmp is set, abort. It could be
|
/* New case: if it's a symlink and tmp is set AND the user does not
|
||||||
a symlink attack */
|
own the symlink, abort. It could be a symlink attack */
|
||||||
if (tmp && S_ISLNK(st.st_mode))
|
if (tmp && S_ISLNK(st.st_mode) && getuid() != st.st_uid)
|
||||||
return -1;
|
return -1;
|
||||||
else if (!tmp && (ISSET(FOLLOW_SYMLINKS) || !S_ISLNK(st.st_mode))) {
|
else if (ISSET(FOLLOW_SYMLINKS) || !S_ISLNK(st.st_mode)) {
|
||||||
|
|
||||||
/* Open the file and truncate it. Trust the symlink. */
|
/* Open the file and truncate it. Trust the symlink. */
|
||||||
if ((fd = open(realname, O_WRONLY | O_CREAT | O_TRUNC,
|
if ((fd = open(realname, O_WRONLY | O_CREAT | O_TRUNC,
|
||||||
|
@ -413,7 +417,7 @@ int write_file(char *name, int tmp)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ISSET(FOLLOW_SYMLINKS) || tmp) {
|
if (!ISSET(FOLLOW_SYMLINKS) || tmp) {
|
||||||
if (stat(realname, &st) == -1) {
|
if (realexists == -1) {
|
||||||
/* Use default umask as file permisions if file is a new file. */
|
/* Use default umask as file permisions if file is a new file. */
|
||||||
mask = umask(0);
|
mask = umask(0);
|
||||||
umask(mask);
|
umask(mask);
|
||||||
|
@ -426,7 +430,7 @@ int write_file(char *name, int tmp)
|
||||||
} else {
|
} else {
|
||||||
/* Use permissions from file we are overwriting. */
|
/* Use permissions from file we are overwriting. */
|
||||||
mask = st.st_mode;
|
mask = st.st_mode;
|
||||||
if (unlink(realname) == -1) {
|
if (!tmp && unlink(realname) == -1) {
|
||||||
if (errno != ENOENT) {
|
if (errno != ENOENT) {
|
||||||
statusbar(_("Could not open %s for writing: %s"),
|
statusbar(_("Could not open %s for writing: %s"),
|
||||||
realname, strerror(errno));
|
realname, strerror(errno));
|
||||||
|
@ -436,23 +440,24 @@ int write_file(char *name, int tmp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (link(buf, realname) != -1)
|
if (!tmp) {
|
||||||
unlink(buf);
|
if (link(buf, realname) != -1)
|
||||||
else if (errno != EPERM) {
|
unlink(buf);
|
||||||
statusbar(_("Could not open %s for writing: %s"),
|
else if (errno != EPERM) {
|
||||||
|
statusbar(_("Could not open %s for writing: %s"),
|
||||||
name, strerror(errno));
|
name, strerror(errno));
|
||||||
unlink(buf);
|
unlink(buf);
|
||||||
return -1;
|
return -1;
|
||||||
} else if (rename(buf, realname) == -1) { /* Try a rename?? */
|
} else if (rename(buf, realname) == -1) { /* Try a rename?? */
|
||||||
statusbar(_("Could not open %s for writing: %s"),
|
statusbar(_("Could not open %s for writing: %s"),
|
||||||
realname, strerror(errno));
|
realname, strerror(errno));
|
||||||
unlink(buf);
|
unlink(buf);
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (chmod(realname, mask) == -1) {
|
if (chmod(realname, mask) == -1)
|
||||||
statusbar(_("Could not set permissions %o on %s: %s"),
|
statusbar(_("Could not set permissions %o on %s: %s"),
|
||||||
mask, realname, strerror(errno));
|
mask, realname, strerror(errno));
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
if (!tmp) {
|
if (!tmp) {
|
||||||
|
|
Loading…
Reference in New Issue