2010-04-25 Chris Allegretta <chrisa@asty.org>

* files.c (do_writeout): Merge in 2.1/2.2 branch modification check and security fixes
         (in particular revs 4424 4467 4474 4490 4491 4494 4495 4496 4497 and 4500).  Addresses
         CVEs CVE-2010-1160 and CVE-2010-1161.



git-svn-id: svn://svn.savannah.gnu.org/nano/branches/nano_2_0_branch/nano@4505 35c25a1d-7b9e-4130-9fde-d3aeb78583b8
This commit is contained in:
Chris Allegretta 2010-04-25 07:25:41 +00:00
parent 59fc1570d3
commit 7f86c15ffb
3 changed files with 57 additions and 14 deletions

View File

@ -1,3 +1,8 @@
2010-04-25 Chris Allegretta <chrisa@asty.org>
* files.c (do_writeout): Merge in 2.1/2.2 branch modification check and security fixes
(in particular revs 4424 4467 4474 4490 4491 4494 4495 4496 4497 and 4500). Addresses
CVEs CVE-2010-1160 and CVE-2010-1161.
GNU nano 2.0.9 - 2008.09.06
2008-09-06 Chris Allegretta <chrisa@asty.org>
* po/* - Revert po files to 2.0.7 versions due to issues with 2.1 string differences.

View File

@ -1392,14 +1392,22 @@ bool write_file(const char *name, FILE *f_open, bool tmp, append_type
realexists = (stat(realname, &st) != -1);
#ifndef NANO_TINY
/* if we have not stat()d this file before (say, the user just
* specified it interactively), stat and save the value
* or else we will chase null pointers when we do
* modtime checks, preserve file times, etc. during backup */
if (openfile->current_stat == NULL && !tmp && realexists)
stat(realname, openfile->current_stat);
/* We backup only if the backup toggle is set, the file isn't
* temporary, and the file already exists. Furthermore, if we
* aren't appending, prepending, or writing a selection, we backup
* only if the file has not been modified by someone else since nano
* opened it. */
if (ISSET(BACKUP_FILE) && !tmp && realexists && ((append !=
OVERWRITE || openfile->mark_set) ||
openfile->current_stat->st_mtime == st.st_mtime)) {
OVERWRITE || openfile->mark_set) || (openfile->current_stat &&
openfile->current_stat->st_mtime == st.st_mtime))) {
int backup_fd;
FILE *backup_file;
char *backupname;
struct utimbuf filetime;
@ -1472,18 +1480,36 @@ bool write_file(const char *name, FILE *f_open, bool tmp, append_type
sprintf(backupname, "%s~", realname);
}
/* Open the destination backup file. Before we write to it, we
* set its permissions, so no unauthorized person can read it as
* we write. */
backup_file = fopen(backupname, "wb");
/* First, unlink any existing backups. Next, open the backup
file with O_CREAT and O_EXCL. If it succeeds, we
have a file descriptor to a new backup file. */
if (unlink(backupname) < 0 && errno != ENOENT) {
statusbar(_("Error writing backup file %s: %s"), backupname,
strerror(errno));
free(backupname);
goto cleanup_and_exit;
}
if (backup_file == NULL || chmod(backupname,
openfile->current_stat->st_mode) == -1) {
backup_fd = open(backupname, O_WRONLY | O_CREAT | O_EXCL | O_APPEND,
S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
/* Now we've got a safe file stream. If the previous open()
call failed, this will return NULL. */
backup_file = fdopen(backup_fd, "wb");
if (backup_fd < 0 || backup_file == NULL) {
statusbar(_("Error writing backup file %s: %s"), backupname,
strerror(errno));
free(backupname);
goto cleanup_and_exit;
}
if (fchmod(backup_fd, openfile->current_stat->st_mode) == -1 ||
fchown(backup_fd, openfile->current_stat->st_uid,
openfile->current_stat->st_gid) == -1 ) {
statusbar(_("Error writing %s: %s"), backupname,
strerror(errno));
free(backupname);
if (backup_file != NULL)
fclose(backup_file);
fclose(backup_file);
/* If we can't write to the backup, go on, since only saving
* the original file is better than saving nothing. */
goto skip_backup;
@ -1497,10 +1523,7 @@ bool write_file(const char *name, FILE *f_open, bool tmp, append_type
copy_status = copy_file(f, backup_file);
/* And set its metadata. */
if (copy_status != 0 || chown(backupname,
openfile->current_stat->st_uid,
openfile->current_stat->st_gid) == -1 ||
utime(backupname, &filetime) == -1) {
if (copy_status != 0 || utime(backupname, &filetime) == -1) {
if (copy_status == -1) {
statusbar(_("Error reading %s: %s"), realname,
strerror(errno));
@ -1999,6 +2022,18 @@ bool do_writeout(bool exiting)
continue;
}
}
#ifndef NANO_TINY
/* Complain if the file exists, the name hasn't changed, and the
stat information we had before does not match what we have now */
else if (name_exists && openfile->current_stat && (openfile->current_stat->st_mtime < st.st_mtime ||
openfile->current_stat->st_dev != st.st_dev || openfile->current_stat->st_ino != st.st_ino)) {
i = do_yesno_prompt(FALSE,
_("File was modified since you opened it, continue saving ? "));
if (i == 0 || i == -1)
continue;
}
#endif
}
/* Convert newlines to nulls, just before we save the

View File

@ -501,6 +501,9 @@ openfilestruct *make_new_opennode(void)
newnode->filebot = NULL;
newnode->edittop = NULL;
newnode->current = NULL;
#ifndef NANO_TINY
newnode->current_stat = NULL;
#endif
return newnode;
}