rpms/nano/F-11 nano-2.0.9-bz582434.patch, NONE, 1.1 nano-2.0.9-warnings.patch, NONE, 1.1 .cvsignore, 1.10, 1.11 nano.spec, 1.25, 1.26 sources, 1.10, 1.11 nano-2.0.6-open-macro.patch, 1.1, NONE

Kamil Dudka kdudka at fedoraproject.org
Thu Apr 15 19:08:50 UTC 2010


Author: kdudka

Update of /cvs/extras/rpms/nano/F-11
In directory cvs01.phx2.fedoraproject.org:/tmp/cvs-serv6788

Modified Files:
	.cvsignore nano.spec sources 
Added Files:
	nano-2.0.9-bz582434.patch nano-2.0.9-warnings.patch 
Removed Files:
	nano-2.0.6-open-macro.patch 
Log Message:
- new upstream bugfix release
- CVE-2010-1160, CVE-2010-1161 (#582739)

nano-2.0.9-bz582434.patch:
 ChangeLog   |   17 +++++++++++++++-
 src/files.c |   61 +++++++++++++++++++++++++++++++++++++++---------------------
 2 files changed, 56 insertions(+), 22 deletions(-)

--- NEW FILE nano-2.0.9-bz582434.patch ---
>From 04a5cd704424a18140c686dfc22873abf41d4e66 Mon Sep 17 00:00:00 2001
From: Kamil Dudka <kdudka at redhat.com>
Date: Thu, 15 Apr 2010 20:57:40 +0200
Subject: [PATCH] nano: multiple file editing insecurities (#582434)

CVE-2010-1160
CVE-2010-1161

Signed-off-by: Kamil Dudka <kdudka at redhat.com>
---
 ChangeLog   |   17 +++++++++++++++-
 src/files.c |   60 +++++++++++++++++++++++++++++++++++++++-------------------
 2 files changed, 56 insertions(+), 21 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 499a036..3a17c8e 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,9 +1,24 @@
+2010-04-09 Chris Allegretta <chrisa at asty.org>
+	* files.c (do_writeout): Better security fixes for backup file writing, 
+	  mangled from submission by Dan Rosenberg <dan.j.rosenberg at gmail>.
+
+2010-04-08 Chris Allegretta <chrisa at asty.org>
+	* files.c (do_writeout): Previous fixes should not cause a crash 
+	  when saving a new file.  Discovered by Mike Frysinger <vapier at gentoo.org>.
+
+2010-04-02 Chris Allegretta <chrisa at asty.org>
+	* files.c (do_writeout): Expand modification check to include both the
+	  original file's device ID and inode number as reasons to warn the 
+          user that the file has been modified.  Also abort on writing a backup
+	  file when its owner doesn't match the edited file. Based on security 
+	  analysis on nano by Dan Rosenberg.
+
 GNU nano 2.0.9 - 2008.09.06
 2008-09-06 Chris Allegretta <chrisa at asty.org>
 	* po/* - Revert po files to 2.0.7 versions due to issues with 2.1 string differences.
 
 GNU nano 2.0.8 - 2008.08.24
-008-08-08 Magnus Granberg <zorry at ume.nu> / Adam Conrad <?>
+2008-08-08 Magnus Granberg <zorry at ume.nu> / Adam Conrad <?>
         * files.c: (write_file): Add needed flags to open() calls when writing out files.  Fixes Savannah bug
           #23827: Compilation fails with -D_FORTIFY_SOURCE=2
 
diff --git a/src/files.c b/src/files.c
index eb079e0..56ac04b 100644
--- a/src/files.c
+++ b/src/files.c
@@ -1402,6 +1402,7 @@ bool write_file(const char *name, FILE *f_open, bool tmp, append_type
     if (ISSET(BACKUP_FILE) && !tmp && realexists && ((append !=
 	OVERWRITE || openfile->mark_set) ||
 	openfile->current_stat->st_mtime == st.st_mtime)) {
+	int backup_fd;
 	FILE *backup_file;
 	char *backupname;
 	struct utimbuf filetime;
@@ -1474,21 +1475,41 @@ 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) {
-	    statusbar(_("Error writing %s: %s"), backupname,
+	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 backup file %s: %s"), backupname,
 		strerror(errno));
 	    free(backupname);
-	    if (backup_file != NULL)
-		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;
+	    fclose(backup_file);
+	    /* If we can't write to the backup, DONT go on, since
+	       whatever caused the backup file to fail (e.g. disk
+	       full may well cause the real file write to fail, which
+	       means we could lose both the backup and the original! */
+	    goto cleanup_and_exit;
 	}
 
 #ifdef DEBUG
@@ -1499,20 +1520,19 @@ 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));
 		beep();
 	    } else
-		statusbar(_("Error writing %s: %s"), backupname,
+		statusbar(_("Error writing backup file %s: %s"), backupname,
 			strerror(errno));
-	    /* If we can't read from or write to the backup, go on,
-	     * since only saving the original file is better than saving
-	     * nothing. */
+	    /* If we can't write to the backup, DONT go on, since
+	       whatever caused the backup file to fail (e.g. disk
+	       full may well cause the real file write to fail, which
+	       means we could lose both the backup and the original! */
+	    goto cleanup_and_exit;
 	}
 
 	free(backupname);
-- 
1.6.6.1


nano-2.0.9-warnings.patch:
 chars.c |   43 ++++++++++++++++++++++++++++---------------
 files.c |    4 +++-
 2 files changed, 31 insertions(+), 16 deletions(-)

--- NEW FILE nano-2.0.9-warnings.patch ---
diff -rup nano-2.0.9.orig/src/chars.c nano-2.0.9/src/chars.c
--- nano-2.0.9.orig/src/chars.c	2008-04-02 05:49:33.000000000 +0200
+++ nano-2.0.9/src/chars.c	2009-09-21 13:22:25.976235192 +0200
@@ -79,6 +79,18 @@ bool is_byte(int c)
     return ((unsigned int)c == (unsigned char)c);
 }
 
+static void mbtowc_reset(void)
+{
+    int rv = mbtowc(NULL, NULL, 0);
+    (void) rv;
+}
+
+static void wctomb_reset(void)
+{
+    int rv = wctomb(NULL, 0);
+    (void) rv;
+}
+
 /* This function is equivalent to isalnum() for multibyte characters. */
 bool is_alnum_mbchar(const char *c)
 {
@@ -89,7 +101,7 @@ bool is_alnum_mbchar(const char *c)
 	wchar_t wc;
 
 	if (mbtowc(&wc, c, MB_CUR_MAX) < 0) {
-	    mbtowc(NULL, NULL, 0);
+	    mbtowc_reset();
 	    wc = bad_wchar;
 	}
 
@@ -109,7 +121,7 @@ bool is_blank_mbchar(const char *c)
 	wchar_t wc;
 
 	if (mbtowc(&wc, c, MB_CUR_MAX) < 0) {
-	    mbtowc(NULL, NULL, 0);
+	    mbtowc_reset();
 	    wc = bad_wchar;
 	}
 
@@ -156,7 +168,7 @@ bool is_cntrl_mbchar(const char *c)
 	wchar_t wc;
 
 	if (mbtowc(&wc, c, MB_CUR_MAX) < 0) {
-	    mbtowc(NULL, NULL, 0);
+	    mbtowc_reset();
 	    wc = bad_wchar;
 	}
 
@@ -177,7 +189,7 @@ bool is_punct_mbchar(const char *c)
 	int c_mb_len = mbtowc(&wc, c, MB_CUR_MAX);
 
 	if (c_mb_len < 0) {
-	    mbtowc(NULL, NULL, 0);
+	    mbtowc_reset();
 	    wc = bad_wchar;
 	}
 
@@ -243,14 +255,14 @@ char *control_mbrep(const char *c, char 
 	wchar_t wc;
 
 	if (mbtowc(&wc, c, MB_CUR_MAX) < 0) {
-	    mbtowc(NULL, NULL, 0);
+	    mbtowc_reset();
 	    *crep_len = bad_mbchar_len;
 	    strncpy(crep, bad_mbchar, *crep_len);
 	} else {
 	    *crep_len = wctomb(crep, control_wrep(wc));
 
 	    if (*crep_len < 0) {
-		wctomb(NULL, 0);
+		wctomb_reset();
 		*crep_len = 0;
 	    }
 	}
@@ -278,14 +290,14 @@ char *mbrep(const char *c, char *crep, i
 
 	/* Reject invalid Unicode characters. */
 	if (mbtowc(&wc, c, MB_CUR_MAX) < 0 || !is_valid_unicode(wc)) {
-	    mbtowc(NULL, NULL, 0);
+	    mbtowc_reset();
 	    *crep_len = bad_mbchar_len;
 	    strncpy(crep, bad_mbchar, *crep_len);
 	} else {
 	    *crep_len = wctomb(crep, wc);
 
 	    if (*crep_len < 0) {
-		wctomb(NULL, 0);
+		wctomb_reset();
 		*crep_len = 0;
 	    }
 	}
@@ -311,7 +323,7 @@ int mbwidth(const char *c)
 	int width;
 
 	if (mbtowc(&wc, c, MB_CUR_MAX) < 0) {
-	    mbtowc(NULL, NULL, 0);
+	    mbtowc_reset();
 	    wc = bad_wchar;
 	}
 
@@ -356,7 +368,7 @@ char *make_mbchar(long chr, int *chr_mb_
 
 	/* Reject invalid Unicode characters. */
 	if (*chr_mb_len < 0 || !is_valid_unicode((wchar_t)chr)) {
-	    wctomb(NULL, 0);
+	    wctomb_reset();
 	    *chr_mb_len = 0;
 	}
     } else {
@@ -388,7 +400,8 @@ int parse_mbchar(const char *buf, char *
 	/* If buf contains an invalid multibyte character, only
 	 * interpret buf's first byte. */
 	if (buf_mb_len < 0) {
-	    mblen(NULL, 0);
+	    int rv = mblen(NULL, 0);
+	    (void) rv;
 	    buf_mb_len = 1;
 	} else if (buf_mb_len == 0)
 	    buf_mb_len++;
@@ -545,7 +558,7 @@ int mbstrncasecmp(const char *s1, const 
 	    s1_mb_len = parse_mbchar(s1, s1_mb, NULL);
 
 	    if (mbtowc(&ws1, s1_mb, s1_mb_len) < 0) {
-		mbtowc(NULL, NULL, 0);
+		mbtowc_reset();
 		ws1 = (unsigned char)*s1_mb;
 		bad_s1_mb = TRUE;
 	    }
@@ -553,7 +566,7 @@ int mbstrncasecmp(const char *s1, const 
 	    s2_mb_len = parse_mbchar(s2, s2_mb, NULL);
 
 	    if (mbtowc(&ws2, s2_mb, s2_mb_len) < 0) {
-		mbtowc(NULL, NULL, 0);
+		mbtowc_reset();
 		ws2 = (unsigned char)*s2_mb;
 		bad_s2_mb = TRUE;
 	    }
@@ -781,7 +794,7 @@ char *mbstrchr(const char *s, const char
 	int c_mb_len = mbtowc(&wc, c, MB_CUR_MAX);
 
 	if (c_mb_len < 0) {
-	    mbtowc(NULL, NULL, 0);
+	    mbtowc_reset();
 	    wc = (unsigned char)*c;
 	    bad_c_mb = TRUE;
 	}
@@ -790,7 +803,7 @@ char *mbstrchr(const char *s, const char
 	    int s_mb_len = parse_mbchar(s, s_mb, NULL);
 
 	    if (mbtowc(&ws, s_mb, s_mb_len) < 0) {
-		mbtowc(NULL, NULL, 0);
+		mbtowc_reset();
 		ws = (unsigned char)*s;
 		bad_s_mb = TRUE;
 	    }
diff -rup nano-2.0.9.orig/src/files.c nano-2.0.9/src/files.c
--- nano-2.0.9.orig/src/files.c	2008-08-24 07:49:25.000000000 +0200
+++ nano-2.0.9/src/files.c	2009-09-21 13:24:50.585047697 +0200
@@ -1057,6 +1057,7 @@ char *get_full_path(const char *origpath
 	    free(d_there);
 	    d_there = NULL;
 	} else {
+	    int rv;
 	    free(d_there);
 
 	    /* Get the full path. */
@@ -1082,7 +1083,8 @@ char *get_full_path(const char *origpath
 	    /* Finally, go back to the path specified in d_here,
 	     * where we were before.  We don't check for a chdir()
 	     * error, since we can do nothing if we get one. */
-	    chdir(d_here);
+	    rv = chdir(d_here);
+	    (void) rv;
 
 	    /* Free d_here, since we're done using it. */
 	    free(d_here);


Index: .cvsignore
===================================================================
RCS file: /cvs/extras/rpms/nano/F-11/.cvsignore,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -p -r1.10 -r1.11
--- .cvsignore	3 Jun 2007 12:27:39 -0000	1.10
+++ .cvsignore	15 Apr 2010 19:08:50 -0000	1.11
@@ -1 +1 @@
-nano-2.0.6.tar.gz
+nano-2.0.9.tar.gz


Index: nano.spec
===================================================================
RCS file: /cvs/extras/rpms/nano/F-11/nano.spec,v
retrieving revision 1.25
retrieving revision 1.26
diff -u -p -r1.25 -r1.26
--- nano.spec	26 Feb 2009 04:13:32 -0000	1.25
+++ nano.spec	15 Apr 2010 19:08:50 -0000	1.26
@@ -1,12 +1,13 @@
 Summary:	A small text editor
 Name:		nano
-Version:	2.0.6
-Release:	6%{?dist}
+Version:	2.0.9
+Release:	1%{?dist}
 License:	GPLv2+
 Group:		Applications/Editors
 URL:		http://www.nano-editor.org
 Source:		http://www.nano-editor.org/dist/v1.3/%{name}-%{version}.tar.gz
-Patch0:		nano-2.0.6-open-macro.patch
+Patch1:		nano-2.0.9-warnings.patch
+Patch2:		nano-2.0.9-bz582434.patch
 BuildRoot:	%{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
 BuildRequires:	ncurses-devel, autoconf, gettext-devel, groff
 Requires(post):	 /sbin/install-info
@@ -17,9 +18,11 @@ GNU nano is a small and friendly text ed
 
 %prep
 %setup -q
-%patch0 -p1
+%patch1 -p1
+%patch2 -p1
 for f in doc/man/fr/{nano.1,nanorc.5,rnano.1} ; do
   iconv -f iso-8859-1 -t utf-8 -o $f.tmp $f && mv $f.tmp $f
+  touch $f.html
 done
 
 %build
@@ -59,6 +62,10 @@ rm -rf %{buildroot}
 %{_datadir}/nano
 
 %changelog
+* Thu Apr 15 2010 Kamil Dudka <kdudka at redhat.com> - 2.0.9-1
+- new upstream bugfix release
+- CVE-2010-1160, CVE-2010-1161 (#582739)
+
 * Wed Feb 25 2009 Fedora Release Engineering <rel-eng at lists.fedoraproject.org> - 2.0.6-6
 - Rebuilt for https://fedoraproject.org/wiki/Fedora_11_Mass_Rebuild
 


Index: sources
===================================================================
RCS file: /cvs/extras/rpms/nano/F-11/sources,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -p -r1.10 -r1.11
--- sources	3 Jun 2007 12:27:39 -0000	1.10
+++ sources	15 Apr 2010 19:08:50 -0000	1.11
@@ -1 +1 @@
-619107f0fc3c4383d668cef15aa3ca32  nano-2.0.6.tar.gz
+2be94dc43fb60fff4626a2401a977220  nano-2.0.9.tar.gz


--- nano-2.0.6-open-macro.patch DELETED ---



More information about the scm-commits mailing list