Index | Thread | Search

From:
Mark Kettenis <mark.kettenis@xs4all.nl>
Subject:
Re: pax(1): localtime(3) can fail
To:
Florian Obser <florian@openbsd.org>
Cc:
tech@openbsd.org
Date:
Sat, 27 Apr 2024 20:45:56 +0200

Download raw body.

Thread
> From: Florian Obser <florian@openbsd.org>
> Date: Sat, 27 Apr 2024 16:18:18 +0200
> 
> A time_t very far in the future (and past) is not representable by
> struct tm and localtime(3) returns NULL, leading to a segfault
> 
> Core was generated by `pax'.
> Program terminated with signal SIGSEGV, Segmentation fault.
> #0  _fmt (format=0x88eb4dfbd4a "b %e  %Y", t=0x0, pt=0x761f8811dd40 "\001",
>     ptlim=0x761f8811dd80 "drwxr-xr-x ", warnp=0x761f8811dd04)
>     at /usr/src/lib/libc/time/strftime.c:159
> 159                                     pt = _add((t->tm_mon < 0 ||
> (gdb) bt
> #0  _fmt (format=0x88eb4dfbd4a "b %e  %Y", t=0x0, pt=0x761f8811dd40 "\001",
>     ptlim=0x761f8811dd80 "drwxr-xr-x ", warnp=0x761f8811dd04)
>     at /usr/src/lib/libc/time/strftime.c:159
> #1  0x0000089112ad9f2a in _libc_strftime (s=0x761f8811dd40 "\001", maxsize=64,
>     format=<optimized out>, t=0x0) at /usr/src/lib/libc/time/strftime.c:118
> #2  0x0000088eb4e11c6f in ls_list (arcn=0x761f8811ddf0, now=1714210446,
>     fp=0x89112b7cdc8 <__sF+152>) at /usr/src/bin/pax/gen_subs.c:106
> #3  0x0000088eb4e04010 in list () at /usr/src/bin/pax/ar_subs.c:127
> #4  0x0000088eb4e1cb18 in main (argc=3, argv=0x761f8811f7c8)
>     at /usr/src/bin/pax/pax.c:326
> (gdb) frame 2                                                 13:09:54 [117/446]
> #2  0x0000088eb4e11c6f in ls_list (arcn=0x761f8811ddf0, now=1714210446,
>     fp=0x89112b7cdc8 <__sF+152>) at /usr/src/bin/pax/gen_subs.c:106
> 106             if (strftime(f_date, sizeof(f_date), TIMEFMT(sbp->st_mtime, now)
> ,
> (gdb) p sbp->st_mtime
> value has been optimized out
> (gdb) p arcn->sb
> $2 = {st_mode = 16877, st_dev = 0, st_ino = 0, st_nlink = 2, st_uid = 1000,
>   st_gid = 1000, st_rdev = 0, st_atim = {tv_sec = 1714200723,
>     tv_nsec = 879795667}, st_mtim = {tv_sec = 1714200723888079566,
>     tv_nsec = 0}, st_ctim = {tv_sec = 1714200723, tv_nsec = 880795660},
>   st_size = 0, st_blocks = 0, st_blksize = 0, st_flags = 0, st_gen = 0,
>   __st_birthtim = {tv_sec = 0, tv_nsec = 0}}
> 
> I found this with afl using the gnu tar test suite as input, I'll attach
> a broken test file that triggers the segfault with "pax -vf pax_broken"
> 
> OK?
> 
> diff --git gen_subs.c gen_subs.c
> index 42c70804fb7..f3a8cb775a1 100644
> --- gen_subs.c
> +++ gen_subs.c
> @@ -75,6 +75,7 @@ void
>  ls_list(ARCHD *arcn, time_t now, FILE *fp)
>  {
>  	struct stat *sbp;
> +	struct tm * tm;

No space after '*'.

>  	char f_mode[MODELEN];
>  	char f_date[DATELEN];
>  	int term;
> @@ -103,8 +104,10 @@ ls_list(ARCHD *arcn, time_t now, FILE *fp)
>  	/*
>  	 * print file mode, link count, uid, gid and time
>  	 */
> -	if (strftime(f_date, sizeof(f_date), TIMEFMT(sbp->st_mtime, now),
> -	    localtime(&(sbp->st_mtime))) == 0)
> +	if ((tm = localtime(&(sbp->st_mtime))) == NULL)
> +		f_date[0] = '\0';
> +	else if (strftime(f_date, sizeof(f_date), TIMEFMT(sbp->st_mtime, now),
> +	    tm) == 0)
>  		f_date[0] = '\0';
>  	(void)fprintf(fp, "%s%2u %-*.*s %-*.*s ", f_mode, sbp->st_nlink,
>  		NAME_WIDTH, UT_NAMESIZE, user_from_uid(sbp->st_uid, 0),
> @@ -146,6 +149,7 @@ ls_list(ARCHD *arcn, time_t now, FILE *fp)
>  void
>  ls_tty(ARCHD *arcn)
>  {
> +	struct tm * tm;

Likewise.

>  	char f_date[DATELEN];
>  	char f_mode[MODELEN];
>  	time_t now = time(NULL);
> @@ -153,8 +157,10 @@ ls_tty(ARCHD *arcn)
>  	/*
>  	 * convert time to string, and print
>  	 */
> -	if (strftime(f_date, DATELEN, TIMEFMT(arcn->sb.st_mtime, now),
> -	    localtime(&(arcn->sb.st_mtime))) == 0)
> +	if ((tm = localtime(&(arcn->sb.st_mtime))) == NULL)
> +		f_date[0] = '\0';
> +	else if (strftime(f_date, DATELEN, TIMEFMT(arcn->sb.st_mtime, now),
> +	    tm) == 0)
>  		f_date[0] = '\0';
>  	strmode(arcn->sb.st_mode, f_mode);
>  	tty_prnt("%s%s %s\n", f_mode, f_date, arcn->name);
> 
> 
> [2:application/octet-stream Show Save:pax_broken (10kB)]
> 
> 
> [3:text/plain Hide]
> 
> 
> -- 
> In my defence, I have been left unsupervised.