From 76cf1251ffc050a7784b9e28e8516e7a23d5732a Mon Sep 17 00:00:00 2001 From: Kamil Dudka Date: Apr 15 2010 19:08:50 +0000 Subject: - new upstream bugfix release - CVE-2010-1160, CVE-2010-1161 (#582739) --- diff --git a/.cvsignore b/.cvsignore index 2295ac1..9356fb1 100644 --- a/.cvsignore +++ b/.cvsignore @@ -1 +1 @@ -nano-2.0.6.tar.gz +nano-2.0.9.tar.gz diff --git a/nano-2.0.6-open-macro.patch b/nano-2.0.6-open-macro.patch deleted file mode 100644 index 975e0f6..0000000 --- a/nano-2.0.6-open-macro.patch +++ /dev/null @@ -1,20 +0,0 @@ ---- nano-2.0.6/src/files.c~ 2007-04-21 21:33:56.000000000 +0100 -+++ nano-2.0.6/src/files.c 2007-08-22 18:52:11.000000000 +0100 -@@ -1518,7 +1518,7 @@ bool write_file(const char *name, FILE * - } - - if (f_open == NULL) { -- fd_source = open(realname, O_RDONLY | O_CREAT); -+ fd_source = open(realname, O_RDONLY | O_CREAT, 0600); - - if (fd_source != -1) { - f_source = fdopen(fd_source, "rb"); -@@ -1637,7 +1637,7 @@ bool write_file(const char *name, FILE * - int fd_source; - FILE *f_source = NULL; - -- fd_source = open(tempname, O_RDONLY | O_CREAT); -+ fd_source = open(tempname, O_RDONLY | O_CREAT, 0600); - - if (fd_source != -1) { - f_source = fdopen(fd_source, "rb"); diff --git a/nano-2.0.9-bz582434.patch b/nano-2.0.9-bz582434.patch new file mode 100644 index 0000000..02a14d3 --- /dev/null +++ b/nano-2.0.9-bz582434.patch @@ -0,0 +1,141 @@ +From 04a5cd704424a18140c686dfc22873abf41d4e66 Mon Sep 17 00:00:00 2001 +From: Kamil Dudka +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 +--- + 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 ++ * files.c (do_writeout): Better security fixes for backup file writing, ++ mangled from submission by Dan Rosenberg . ++ ++2010-04-08 Chris Allegretta ++ * files.c (do_writeout): Previous fixes should not cause a crash ++ when saving a new file. Discovered by Mike Frysinger . ++ ++2010-04-02 Chris Allegretta ++ * 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 + * 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 / Adam Conrad ++2008-08-08 Magnus Granberg / 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 + diff --git a/nano-2.0.9-warnings.patch b/nano-2.0.9-warnings.patch new file mode 100644 index 0000000..085a9a5 --- /dev/null +++ b/nano-2.0.9-warnings.patch @@ -0,0 +1,177 @@ +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); diff --git a/nano.spec b/nano.spec index f6d6573..b7c7f50 100644 --- a/nano.spec +++ b/nano.spec @@ -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 editor. %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 - 2.0.9-1 +- new upstream bugfix release +- CVE-2010-1160, CVE-2010-1161 (#582739) + * Wed Feb 25 2009 Fedora Release Engineering - 2.0.6-6 - Rebuilt for https://fedoraproject.org/wiki/Fedora_11_Mass_Rebuild diff --git a/sources b/sources index af72956..ec0ccff 100644 --- a/sources +++ b/sources @@ -1 +1 @@ -619107f0fc3c4383d668cef15aa3ca32 nano-2.0.6.tar.gz +2be94dc43fb60fff4626a2401a977220 nano-2.0.9.tar.gz