From 81a719df6ea00ae13b21ce821a407eaf4d42dee6 Mon Sep 17 00:00:00 2001 From: mrg Date: Thu, 10 Aug 2023 20:36:28 +0000 Subject: [PATCH] avoid various use-after-free issues. create a ptrdiff_t offset between the start of an allocation region and some interesting pointer, so it can be adjusted with this offset after realloc() returns. for pdisk(), realloc() is a locally inlind malloc() and free() pair. for mail(1), this required a little bit more effort as the old pointer was passed into another file for fix-ups there, and that code needed to be adjusted for offset vs old pointer usage. found by GCC 12. --- external/bsd/pdisk/dist/io.c | 4 +++- usr.bin/find/misc.c | 8 +++++--- usr.bin/mail/extern.h | 6 +++--- usr.bin/mail/fio.c | 17 ++++++++++------- usr.bin/mail/thread.c | 11 +++++------ usr.bin/mail/thread.h | 4 ++-- usr.bin/rs/rs.c | 8 +++++--- usr.bin/sort/files.c | 7 ++++--- 8 files changed, 37 insertions(+), 28 deletions(-) diff --git a/external/bsd/pdisk/dist/io.c b/external/bsd/pdisk/dist/io.c index f11885d7a196..7cc72503c99e 100644 --- a/external/bsd/pdisk/dist/io.c +++ b/external/bsd/pdisk/dist/io.c @@ -328,6 +328,7 @@ get_string(int eos) char *ret_value; char *limit; int length; + ptrdiff_t off; ret_value = (char *) malloc(STRING_CHUNK); if (ret_value == NULL) { @@ -348,8 +349,9 @@ get_string(int eos) break; } strncpy(limit, ret_value, length); + off = s - ret_value; free(ret_value); - s = limit + (s - ret_value); + s = limit + off; ret_value = limit; length += STRING_CHUNK; limit = ret_value + length; diff --git a/usr.bin/find/misc.c b/usr.bin/find/misc.c index 21e5b9fc6f44..ebc563f1e414 100644 --- a/usr.bin/find/misc.c +++ b/usr.bin/find/misc.c @@ -1,4 +1,4 @@ -/* $NetBSD: misc.c,v 1.15 2022/01/22 14:08:19 christos Exp $ */ +/* $NetBSD: misc.c,v 1.16 2023/08/10 20:36:28 mrg Exp $ */ /*- * Copyright (c) 1990, 1993, 1994 @@ -37,7 +37,7 @@ #if 0 static char sccsid[] = "from: @(#)misc.c 8.2 (Berkeley) 4/1/94"; #else -__RCSID("$NetBSD: misc.c,v 1.15 2022/01/22 14:08:19 christos Exp $"); +__RCSID("$NetBSD: misc.c,v 1.16 2023/08/10 20:36:28 mrg Exp $"); #endif #endif /* not lint */ @@ -78,11 +78,13 @@ brace_subst(char *orig, char **store, char *path, size_t *len) nlen *= 2; if (nlen > *len) { + ptrdiff_t off = p - *store; + ostore = *store; if ((*store = realloc(ostore, nlen)) == NULL) err(1, "realloc"); *len = nlen; - p += *store - ostore; /* Relocate. */ + p = *store + off; /* Relocate. */ } memmove(p, path, plen); p += plen; diff --git a/usr.bin/mail/extern.h b/usr.bin/mail/extern.h index c6fd977ef20e..7c838b711e00 100644 --- a/usr.bin/mail/extern.h +++ b/usr.bin/mail/extern.h @@ -1,4 +1,4 @@ -/* $NetBSD: extern.h,v 1.35 2023/08/01 07:04:17 mrg Exp $ */ +/* $NetBSD: extern.h,v 1.36 2023/08/10 20:36:28 mrg Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -29,7 +29,7 @@ * SUCH DAMAGE. * * @(#)extern.h 8.2 (Berkeley) 4/20/95 - * $NetBSD: extern.h,v 1.35 2023/08/01 07:04:17 mrg Exp $ + * $NetBSD: extern.h,v 1.36 2023/08/10 20:36:28 mrg Exp $ */ #ifndef __EXTERN_H__ @@ -357,7 +357,7 @@ int get_msgCount(void); /* we trash these commands */ # define do_recursion() 0 # define thread_recursion(mp,fn,args) fn(mp,args) -# define thread_fix_old_links(nmessage,message,omsgCount) +# define thread_fix_old_links(nmessage,off,omsgCount) # define thread_fix_new_links(message,omsgCount,msgCount) #endif /* THREAD_SUPPORT */ diff --git a/usr.bin/mail/fio.c b/usr.bin/mail/fio.c index c752f5c873b3..3df59a580152 100644 --- a/usr.bin/mail/fio.c +++ b/usr.bin/mail/fio.c @@ -1,4 +1,4 @@ -/* $NetBSD: fio.c,v 1.43 2017/11/09 20:27:50 christos Exp $ */ +/* $NetBSD: fio.c,v 1.44 2023/08/10 20:36:28 mrg Exp $ */ /* * Copyright (c) 1980, 1993 @@ -34,7 +34,7 @@ #if 0 static char sccsid[] = "@(#)fio.c 8.2 (Berkeley) 4/20/95"; #else -__RCSID("$NetBSD: fio.c,v 1.43 2017/11/09 20:27:50 christos Exp $"); +__RCSID("$NetBSD: fio.c,v 1.44 2023/08/10 20:36:28 mrg Exp $"); #endif #endif /* not lint */ @@ -125,20 +125,23 @@ makemessage(FILE *f, int omsgCount, int nmsgCount) size_t size; struct message *omessage; /* old message structure array */ struct message *nmessage; + ptrdiff_t off; omessage = get_abs_message(1); size = (nmsgCount + 1) * sizeof(*nmessage); + + if (omsgCount == 0 || omessage == NULL) + off = 0; + else + off = dot - omessage; nmessage = realloc(omessage, size); if (nmessage == NULL) err(EXIT_FAILURE, "Insufficient memory for %d messages", nmsgCount); - if (omsgCount == 0 || omessage == NULL) - dot = nmessage; - else - dot = nmessage + (dot - omessage); + dot = nmessage + off; - thread_fix_old_links(nmessage, omessage, omsgCount); + thread_fix_old_links(nmessage, off, omsgCount); #ifndef THREAD_SUPPORT message = nmessage; diff --git a/usr.bin/mail/thread.c b/usr.bin/mail/thread.c index 1e9036fa4834..c245801bf8db 100644 --- a/usr.bin/mail/thread.c +++ b/usr.bin/mail/thread.c @@ -1,4 +1,4 @@ -/* $NetBSD: thread.c,v 1.14 2021/12/17 15:29:44 kre Exp $ */ +/* $NetBSD: thread.c,v 1.15 2023/08/10 20:36:28 mrg Exp $ */ /*- * Copyright (c) 2006 The NetBSD Foundation, Inc. @@ -37,7 +37,7 @@ #include #ifndef __lint__ -__RCSID("$NetBSD: thread.c,v 1.14 2021/12/17 15:29:44 kre Exp $"); +__RCSID("$NetBSD: thread.c,v 1.15 2023/08/10 20:36:28 mrg Exp $"); #endif /* not __lint__ */ #include @@ -440,10 +440,10 @@ redepth(struct thread_s *thread) * as it needs access to current_thread.t_head. */ PUBLIC void -thread_fix_old_links(struct message *nmessage, struct message *message, int omsgCount) +thread_fix_old_links(struct message *nmessage, ptrdiff_t off, int omsgCount) { int i; - if (nmessage == message) + if (off == 0) return; #ifndef NDEBUG @@ -451,8 +451,7 @@ thread_fix_old_links(struct message *nmessage, struct message *message, int omsg #endif # define FIX_LINK(p) do {\ - if (p)\ - p = nmessage + (p - message);\ + p = nmessage + off;\ } while (0) FIX_LINK(current_thread.t_head); diff --git a/usr.bin/mail/thread.h b/usr.bin/mail/thread.h index 7fecc4fa0a8f..0e9add17c985 100644 --- a/usr.bin/mail/thread.h +++ b/usr.bin/mail/thread.h @@ -1,4 +1,4 @@ -/* $NetBSD: thread.h,v 1.2 2008/04/28 20:24:14 martin Exp $ */ +/* $NetBSD: thread.h,v 1.3 2023/08/10 20:36:28 mrg Exp $ */ /*- * Copyright (c) 2006 The NetBSD Foundation, Inc. @@ -56,7 +56,7 @@ int get_abs_msgCount(void); /* * Support hooks used by other modules. */ -void thread_fix_old_links(struct message *, struct message *, int); +void thread_fix_old_links(struct message *, ptrdiff_t, int); void thread_fix_new_links(struct message *, int, int); int thread_hidden(void); int thread_depth(void); diff --git a/usr.bin/rs/rs.c b/usr.bin/rs/rs.c index a5bb7201234d..7845c50dd7e4 100644 --- a/usr.bin/rs/rs.c +++ b/usr.bin/rs/rs.c @@ -1,4 +1,4 @@ -/* $NetBSD: rs.c,v 1.16 2019/02/03 03:19:30 mrg Exp $ */ +/* $NetBSD: rs.c,v 1.17 2023/08/10 20:36:29 mrg Exp $ */ /*- * Copyright (c) 1993 @@ -39,7 +39,7 @@ __COPYRIGHT("@(#) Copyright (c) 1993\ #if 0 static char sccsid[] = "@(#)rs.c 8.1 (Berkeley) 6/6/93"; #else -__RCSID("$NetBSD: rs.c,v 1.16 2019/02/03 03:19:30 mrg Exp $"); +__RCSID("$NetBSD: rs.c,v 1.17 2023/08/10 20:36:29 mrg Exp $"); #endif #endif /* not lint */ @@ -376,13 +376,15 @@ static char ** getptrs(char **sp) { char **p; + ptrdiff_t off; allocsize += allocsize; + off = sp - elem; p = (char **)realloc(elem, allocsize * sizeof(char *)); if (p == (char **)0) err(1, "no memory"); - sp += (p - elem); + sp = p + off; endelem = (elem = p) + allocsize; return(sp); } diff --git a/usr.bin/sort/files.c b/usr.bin/sort/files.c index 7cb27c5385a3..aa15d6405405 100644 --- a/usr.bin/sort/files.c +++ b/usr.bin/sort/files.c @@ -1,4 +1,4 @@ -/* $NetBSD: files.c,v 1.42 2015/08/05 07:10:03 mrg Exp $ */ +/* $NetBSD: files.c,v 1.43 2023/08/10 20:36:29 mrg Exp $ */ /*- * Copyright (c) 2000-2003 The NetBSD Foundation, Inc. @@ -64,7 +64,7 @@ #include "sort.h" #include "fsort.h" -__RCSID("$NetBSD: files.c,v 1.42 2015/08/05 07:10:03 mrg Exp $"); +__RCSID("$NetBSD: files.c,v 1.43 2023/08/10 20:36:29 mrg Exp $"); #include @@ -199,13 +199,14 @@ seq(FILE *fp, u_char **line) /* Long line - double size of buffer */ /* XXX: Check here for stupidly long lines */ buf_size *= 2; + ptrdiff_t off = pos - buf; new_buf = realloc(buf, buf_size); if (!new_buf) err(2, "realloc of linebuf to %zu bytes failed", buf_size); end = new_buf + buf_size; - pos = new_buf + (pos - buf); + pos = new_buf + off; buf = new_buf; } }