Source: tin
Source-Version: 1:2.6.5~20250806-1
I believe that the bug you reported is fixed in the latest version of
tin, which is due to be installed in the Debian FTP archive.
It includes the following fix for the issue:
=== modified file 'configure.in'
--- old/configure.in 2025-04-09 12:22:56 +0000
+++ new/configure.in 2025-04-14 10:10:38 +0000
@@ -1536,6 +1536,7 @@
isascii \
lockf \
lrand48 \
+ lstat \
memcmp \
memcpy \
memmove \
@@ -1549,8 +1550,9 @@
posix_close \
putenv \
random \
+ realpath \
+ resizeterm \
rewinddir \
- resizeterm \
select \
setenv \
setlocale \
=== modified file 'include/autoconf.hin'
--- old/include/autoconf.hin 2025-04-09 12:22:56 +0000
+++ new/include/autoconf.hin 2025-04-14 10:10:38 +0000
@@ -270,6 +270,7 @@
# undef HAVE_IS_XTERM
# undef HAVE_LINK
# undef HAVE_LOCKF
+# undef HAVE_LSTAT
# undef HAVE_MEMCMP
# undef HAVE_MEMCPY
# undef HAVE_MEMMOVE
@@ -283,6 +284,7 @@
# undef HAVE_POLL
# undef HAVE_POSIX_CLOSE
# undef HAVE_PUTENV
+# undef HAVE_REALPATH
# undef HAVE_RESIZETERM
# undef HAVE_REWINDDIR
# undef HAVE_SELECT
=== modified file 'src/newsrc.c'
--- old/src/newsrc.c 2025-02-07 05:31:38 +0000
+++ new/src/newsrc.c 2025-04-14 10:10:38 +0000
@@ -453,6 +453,7 @@
char dirbuf[PATH_LEN];
char filebuf[PATH_LEN];
struct stat statbuf;
+ FILE *fp_in, *fp_out;
#ifdef NNTP_ABLE
if (read_news_via_nntp && !read_saved_news && nntp_tcp_port !=
IPPORT_NNTP)
@@ -467,12 +468,114 @@
if (stat(dirbuf, &statbuf) == -1) {
if (my_mkdir(dirbuf, (mode_t) (S_IRWXU)) == -1)
- /* Can't create directory: Fall back on Homedir */
+ /* Can't create directory: Fall back to homedir */
joinpath(filebuf, sizeof(filebuf), homedir,
OLDNEWSRC_FILE);
}
+#if defined(HAVE_REALPATH) && (defined(O_NOFOLLOW) || defined(HAVE_LSTAT))
+ /*
+ * preserve symlink if target is below homedir (dedian bug #151113)
+ *
+ * requires realpath(3) as readlink(3) doesn't canonicalize;
+ * prefer the O_NOFOLLOW path as that avoids TOCTOU
+ *
+ * TODO: return errno
+ */
+ {
+ t_bool islink = FALSE;
+# ifdef O_NOFOLLOW
+ int fd;
+# endif /* O_NOFOLLOW */
+
+ if ((fp_in = tin_fopen(newsrc , "r")) == NULL)
+ return;
+
+# ifdef O_NOFOLLOW
+ if ((fd = open(filebuf, (O_RDWR|O_CREAT|O_APPEND|O_NOFOLLOW),
(S_IRUSR|S_IWUSR))) == -1) {
+ if ((fd = open(filebuf, (O_RDWR|O_CREAT|O_APPEND),
(S_IRUSR|S_IWUSR))) == -1) {
+ fclose(fp_in);
+ perror_message(_(txt_cannot_open), filebuf);
+ return;
+ }
+ islink = TRUE;
+ }
+
+ if ((fp_out = fdopen(fd, "a+")) == NULL) {
+# ifdef HAVE_POSIX_CLOSE
+ posix_close(fd, 0);
+# else
+ close(fd);
+# endif /* HAVE_POSIX_CLOSE */
+ fclose(fp_in);
+ perror_message(_(txt_cannot_open), filebuf);
+ return;
+ }
+# else
+ /* TOCTOU */
+ if ((fp_out = fopen(filebuf, "a+")) == NULL) {
+ fclose(fp_in);
+ perror_message(_(txt_cannot_open), filebuf);
+ return;
+ }
+
+ if (lstat(filebuf, &statbuf) != 0) {
+ fclose(fp_in);
+ fclose(fp_out);
+ perror_message(_(txt_cannot_open), filebuf);
+ return;
+ }
+
+ if (S_ISLNK(statbuf.st_mode))
+ islink = TRUE;
+
+# endif /* O_NOFOLLOW */
+
+ if (islink) {
+ char target[PATH_LEN] = { '\0' };
+
+ if (realpath(filebuf, target) == NULL) {
+ fclose(fp_in);
+ fclose(fp_out);
+ return;
+ } else {
+ joinpath(dirbuf, sizeof(dirbuf), homedir, "");
/* ensure homedir is '/'-terminated */
+
+ if (strncmp(dirbuf, target, strlen(dirbuf))) {
/* disallow symlinks outside homedir */
+# ifdef DEBUG
+ if (debug & DEBUG_NEWSRC) {
+ char *debug_mesg;
+ int n;
+
+ if ((n = snprintf(NULL, 0,
"overwriting %s-link \"%s\", target \"%s\" not below \"%s\"", OLDNEWSRC_FILE,
filebuf, target, dirbuf)) > 0) {
+ debug_mesg =
my_malloc(++n);
+ snprintf(debug_mesg, n,
"overwriting %s-link \"%s\", target \"%s\" not below \"%s\"", OLDNEWSRC_FILE,
filebuf, target, dirbuf);
+
debug_print_comment(debug_mesg);
+ error_message(2,
"Warning: %s", debug_mesg);
+ free(debug_mesg);
+ }
+ }
+# endif /* DEBUG */
+ fclose(fp_in);
+ fclose(fp_out);
+ if (!backup_file(newsrc, filebuf))
+ error_message(2,
_(txt_filesystem_full_backup), newsrc);
+ return;
+ }
+ }
+ }
+
+ if (ftruncate(fileno(fp_out), 0L) == 0)
+ copy_fp(fp_in, fp_out);
+
+ fclose(fp_in);
+ fclose(fp_out);
+ }
+#else
if (!backup_file(newsrc, filebuf))
error_message(2, _(txt_filesystem_full_backup), newsrc);
+#endif /* HAVE_REALPATH && (O_NOFOLLOW || HAVE_LSTAT) */
+
+ return;
}