Wed Apr 24 21:59:39 2024 UTC (14d)
makefs: fix out-of-bounds fsnode count in fsnode_sort

Found by running './makefs img.dat cd9660'.

While here, apply more KNF.


(rillig)
diff -r1.38 -r1.39 src/usr.sbin/makefs/walk.c

cvs diff -r1.38 -r1.39 src/usr.sbin/makefs/walk.c (expand / switch to unified diff)

--- src/usr.sbin/makefs/walk.c 2024/04/24 14:23:37 1.38
+++ src/usr.sbin/makefs/walk.c 2024/04/24 21:59:39 1.39
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: walk.c,v 1.38 2024/04/24 14:23:37 christos Exp $ */ 1/* $NetBSD: walk.c,v 1.39 2024/04/24 21:59:39 rillig Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2001 Wasabi Systems, Inc. 4 * Copyright (c) 2001 Wasabi Systems, Inc.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * Written by Luke Mewburn for Wasabi Systems, Inc. 7 * Written by Luke Mewburn for Wasabi Systems, Inc.
8 * 8 *
9 * Redistribution and use in source and binary forms, with or without 9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions 10 * modification, are permitted provided that the following conditions
11 * are met: 11 * are met:
12 * 1. Redistributions of source code must retain the above copyright 12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer. 13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright 14 * 2. Redistributions in binary form must reproduce the above copyright
@@ -31,27 +31,27 @@ @@ -31,27 +31,27 @@
31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35 * POSSIBILITY OF SUCH DAMAGE. 35 * POSSIBILITY OF SUCH DAMAGE.
36 */ 36 */
37 37
38#if HAVE_NBTOOL_CONFIG_H 38#if HAVE_NBTOOL_CONFIG_H
39#include "nbtool_config.h" 39#include "nbtool_config.h"
40#endif 40#endif
41 41
42#include <sys/cdefs.h> 42#include <sys/cdefs.h>
43#if defined(__RCSID) && !defined(__lint) 43#if defined(__RCSID) && !defined(__lint)
44__RCSID("$NetBSD: walk.c,v 1.38 2024/04/24 14:23:37 christos Exp $"); 44__RCSID("$NetBSD: walk.c,v 1.39 2024/04/24 21:59:39 rillig Exp $");
45#endif /* !__lint */ 45#endif /* !__lint */
46 46
47#include <sys/param.h> 47#include <sys/param.h>
48#include <sys/stat.h> 48#include <sys/stat.h>
49 49
50#include <assert.h> 50#include <assert.h>
51#include <errno.h> 51#include <errno.h>
52#include <fcntl.h> 52#include <fcntl.h>
53#include <stdio.h> 53#include <stdio.h>
54#include <dirent.h> 54#include <dirent.h>
55#include <stdlib.h> 55#include <stdlib.h>
56#include <string.h> 56#include <string.h>
57#include <unistd.h> 57#include <unistd.h>
@@ -83,37 +83,36 @@ fsnode_cmp(const void *vleft, const void @@ -83,37 +83,36 @@ fsnode_cmp(const void *vleft, const void
83 return -1; 83 return -1;
84 if (strcmp(rname, ".") == 0) 84 if (strcmp(rname, ".") == 0)
85 return 1; 85 return 1;
86 return strcmp(lname, rname); 86 return strcmp(lname, rname);
87} 87}
88 88
89static fsnode * 89static fsnode *
90fsnode_sort(fsnode *first, const char *root, const char *dir) 90fsnode_sort(fsnode *first, const char *root, const char *dir)
91{ 91{
92 fsnode **list, **listptr; 92 fsnode **list, **listptr;
93 size_t num = 0; 93 size_t num = 0;
94 94
95 for (fsnode *tmp = first; tmp; tmp = tmp->next, num++) { 95 for (fsnode *tmp = first; tmp; tmp = tmp->next, num++) {
96 num++; 
97 if (debug & DEBUG_DUMP_FSNODES_VERBOSE) 96 if (debug & DEBUG_DUMP_FSNODES_VERBOSE)
98 printf("%s: pre sort: %s %s %s\n", 97 printf("%s: pre sort: %s %s %s\n",
99 __func__, root, dir, tmp->name); 98 __func__, root, dir, tmp->name);
100 } 99 }
101 100
102 list = listptr = ecalloc(num, sizeof(*list)); 101 list = listptr = ecalloc(num, sizeof(*list));
103 for (fsnode *tmp = first; tmp; tmp = tmp->next) 102 for (fsnode *tmp = first; tmp; tmp = tmp->next)
104 *listptr++ = tmp; 103 *listptr++ = tmp;
105 104
106 qsort (list, num, sizeof(*list), fsnode_cmp); 105 qsort(list, num, sizeof(*list), fsnode_cmp);
107 106
108 for (size_t i = 0; i < num - 1; ++i) 107 for (size_t i = 0; i < num - 1; ++i)
109 list[i]->next = list[i + 1]; 108 list[i]->next = list[i + 1];
110 list[num - 1]->next = NULL; 109 list[num - 1]->next = NULL;
111 first = list[0]; 110 first = list[0];
112 assert(strcmp(first->name, ".") == 0); 111 assert(strcmp(first->name, ".") == 0);
113 free(list); 112 free(list);
114 if (debug & DEBUG_DUMP_FSNODES_VERBOSE) 113 if (debug & DEBUG_DUMP_FSNODES_VERBOSE)
115 for (fsnode *tmp = first; tmp; tmp = tmp->next) 114 for (fsnode *tmp = first; tmp; tmp = tmp->next)
116 printf("%s: post sort: %s %s %s\n", 115 printf("%s: post sort: %s %s %s\n",
117 __func__, root, dir, tmp->name); 116 __func__, root, dir, tmp->name);
118 117
119 return first; 118 return first;
@@ -552,27 +551,27 @@ apply_specdir(const char *dir, NODE *spe @@ -552,27 +551,27 @@ apply_specdir(const char *dir, NODE *spe
552 curfsnode->child->first = curfsnode->child; 551 curfsnode->child->first = curfsnode->child;
553 } 552 }
554 if (curfsnode->type == S_IFLNK) { 553 if (curfsnode->type == S_IFLNK) {
555 assert(curnode->slink != NULL); 554 assert(curnode->slink != NULL);
556 /* for symlinks, copy the target */ 555 /* for symlinks, copy the target */
557 curfsnode->symlink = estrdup(curnode->slink); 556 curfsnode->symlink = estrdup(curnode->slink);
558 } 557 }
559 } 558 }
560 apply_specentry(dir, curnode, curfsnode); 559 apply_specentry(dir, curnode, curfsnode);
561 if (curnode->type == F_DIR) { 560 if (curnode->type == F_DIR) {
562 if (curfsnode->type != S_IFDIR) 561 if (curfsnode->type != S_IFDIR)
563 errx(EXIT_FAILURE, 562 errx(EXIT_FAILURE,
564 "`%s' is not a directory", path); 563 "`%s' is not a directory", path);
565 assert (curfsnode->child != NULL); 564 assert(curfsnode->child != NULL);
566 apply_specdir(path, curnode, curfsnode->child, speconly); 565 apply_specdir(path, curnode, curfsnode->child, speconly);
567 } 566 }
568 } 567 }
569} 568}
570 569
571static void 570static void
572apply_specentry(const char *dir, NODE *specnode, fsnode *dirnode) 571apply_specentry(const char *dir, NODE *specnode, fsnode *dirnode)
573{ 572{
574 573
575 assert(specnode != NULL); 574 assert(specnode != NULL);
576 assert(dirnode != NULL); 575 assert(dirnode != NULL);
577 576
578 if (nodetoino(specnode->type) != dirnode->type) 577 if (nodetoino(specnode->type) != dirnode->type)
@@ -666,34 +665,34 @@ dump_fsnodes(fsnode *root) @@ -666,34 +665,34 @@ dump_fsnodes(fsnode *root)
666 for (cur = root; cur != NULL; cur = cur->next) { 665 for (cur = root; cur != NULL; cur = cur->next) {
667 if (snprintf(path, sizeof(path), "%s/%s", cur->path, 666 if (snprintf(path, sizeof(path), "%s/%s", cur->path,
668 cur->name) >= (int)sizeof(path)) 667 cur->name) >= (int)sizeof(path))
669 errx(EXIT_FAILURE, "Pathname too long."); 668 errx(EXIT_FAILURE, "Pathname too long.");
670 669
671 if (debug & DEBUG_DUMP_FSNODES_VERBOSE) 670 if (debug & DEBUG_DUMP_FSNODES_VERBOSE)
672 printf("%s: cur=%8p parent=%8p first=%8p ", __func__, 671 printf("%s: cur=%8p parent=%8p first=%8p ", __func__,
673 cur, cur->parent, cur->first); 672 cur, cur->parent, cur->first);
674 printf("%7s: %s", inode_type(cur->type), path); 673 printf("%7s: %s", inode_type(cur->type), path);
675 if (S_ISLNK(cur->type)) { 674 if (S_ISLNK(cur->type)) {
676 assert(cur->symlink != NULL); 675 assert(cur->symlink != NULL);
677 printf(" -> %s", cur->symlink); 676 printf(" -> %s", cur->symlink);
678 } else { 677 } else {
679 assert (cur->symlink == NULL); 678 assert(cur->symlink == NULL);
680 } 679 }
681 if (cur->inode->nlink > 1) 680 if (cur->inode->nlink > 1)
682 printf(", nlinks=%d", cur->inode->nlink); 681 printf(", nlinks=%d", cur->inode->nlink);
683 putchar('\n'); 682 putchar('\n');
684 683
685 if (cur->child) { 684 if (cur->child) {
686 assert (cur->type == S_IFDIR); 685 assert(cur->type == S_IFDIR);
687 dump_fsnodes(cur->child); 686 dump_fsnodes(cur->child);
688 } 687 }
689 } 688 }
690 printf("%s: finished %s/%s\n", __func__, root->path, root->name); 689 printf("%s: finished %s/%s\n", __func__, root->path, root->name);
691} 690}
692 691
693 692
694/* 693/*
695 * inode_type -- 694 * inode_type --
696 * for a given inode type `mode', return a descriptive string. 695 * for a given inode type `mode', return a descriptive string.
697 * for most cases, uses inotype() from mtree/misc.c 696 * for most cases, uses inotype() from mtree/misc.c
698 */ 697 */
699const char * 698const char *