blob: 819720a3f2881a60ae8e1266b9b7a79f36c3b6e7 [file] [log] [blame]
Brad Bishopc342db32019-05-15 21:57:59 -04001From 547c3710a1493d2fd6bb56b819cf162db433756a Mon Sep 17 00:00:00 2001
2From: Richard Purdie <richard.purdie@linuxfoundation.org>
3Date: Wed, 9 Mar 2016 22:49:02 +0000
4Subject: [PATCH] qemu: Limit paths searched during user mode emulation
5
6By default qemu builds a complete list of directories within the user
7emulation sysroot (-L option). The OE sysroot directory is large and
8this is confusing, for example it indexes all pkgdata. In particular this
9confuses strace of qemu binaries with tons of irrelevant paths.
10
11This patch stops the code indexing up front and instead only indexes
12things if/as/when it needs to. This drastically reduces the files it
13reads and reduces memory usage and cleans up strace.
14
15It would also avoid the infinite directory traversal bug in [YOCTO #6996]
16although the code could still be vulnerable if it parsed those specific
17paths.
18
19RP
202016/3/9
21Upstream-Status: Pending
22
23---
24 util/path.c | 44 ++++++++++++++++++++++----------------------
25 1 file changed, 22 insertions(+), 22 deletions(-)
26
27diff --git a/util/path.c b/util/path.c
28index 7f9fc272..a416cd4a 100644
29--- a/util/path.c
30+++ b/util/path.c
31@@ -15,6 +15,7 @@ struct pathelem
32 char *name;
33 /* Full path name, eg. /usr/gnemul/x86-linux/lib. */
34 char *pathname;
35+ int populated_entries;
36 struct pathelem *parent;
37 /* Children */
38 unsigned int num_entries;
39@@ -45,6 +46,7 @@ static struct pathelem *new_entry(const char *root,
40 new->name = g_strdup(name);
41 new->pathname = g_strdup_printf("%s/%s", root, name);
42 new->num_entries = 0;
43+ new->populated_entries = 0;
44 return new;
45 }
46
47@@ -53,15 +55,16 @@ static struct pathelem *new_entry(const char *root,
48 /* Not all systems provide this feature */
49 #if defined(DT_DIR) && defined(DT_UNKNOWN) && defined(DT_LNK)
50 # define dirent_type(dirent) ((dirent)->d_type)
51-# define is_dir_maybe(type) \
52- ((type) == DT_DIR || (type) == DT_UNKNOWN || (type) == DT_LNK)
53+# define is_not_dir(type) \
54+ ((type) != DT_DIR && (type) != DT_UNKNOWN && (type) != DT_LNK)
55 #else
56 # define dirent_type(dirent) (1)
57-# define is_dir_maybe(type) (type)
58+# define is_not_dir(type) (0)
59 #endif
60
61 static struct pathelem *add_dir_maybe(struct pathelem *path)
62 {
63+ unsigned int i;
64 DIR *dir;
65
66 if ((dir = opendir(path->pathname)) != NULL) {
67@@ -74,6 +77,11 @@ static struct pathelem *add_dir_maybe(struct pathelem *path)
68 }
69 closedir(dir);
70 }
71+
72+ for (i = 0; i < path->num_entries; i++)
73+ (path->entries[i])->parent = path;
74+
75+ path->populated_entries = 1;
76 return path;
77 }
78
79@@ -89,26 +97,16 @@ static struct pathelem *add_entry(struct pathelem *root, const char *name,
80 e = &root->entries[root->num_entries-1];
81
82 *e = new_entry(root->pathname, root, name);
83- if (is_dir_maybe(type)) {
84- *e = add_dir_maybe(*e);
85+ if (is_not_dir(type)) {
86+ (*e)->populated_entries = 1;
87 }
88
89 return root;
90 }
91
92-/* This needs to be done after tree is stabilized (ie. no more reallocs!). */
93-static void set_parents(struct pathelem *child, struct pathelem *parent)
94-{
95- unsigned int i;
96-
97- child->parent = parent;
98- for (i = 0; i < child->num_entries; i++)
99- set_parents(child->entries[i], child);
100-}
101-
102 /* FIXME: Doesn't handle DIR/.. where DIR is not in emulated dir. */
103 static const char *
104-follow_path(const struct pathelem *cursor, const char *name)
105+follow_path(struct pathelem *cursor, struct pathelem **source, const char *name)
106 {
107 unsigned int i, namelen;
108
109@@ -119,14 +117,18 @@ follow_path(const struct pathelem *cursor, const char *name)
110 return cursor->pathname;
111
112 if (strneq(name, namelen, ".."))
113- return follow_path(cursor->parent, name + namelen);
114+ return follow_path(cursor->parent, &cursor->parent, name + namelen);
115
116 if (strneq(name, namelen, "."))
117- return follow_path(cursor, name + namelen);
118+ return follow_path(cursor, source, name + namelen);
119+
120+ if (!cursor->populated_entries)
121+ *source = add_dir_maybe(cursor);
122+ cursor = *source;
123
124 for (i = 0; i < cursor->num_entries; i++)
125 if (strneq(name, namelen, cursor->entries[i]->name))
126- return follow_path(cursor->entries[i], name + namelen);
127+ return follow_path(cursor->entries[i], &cursor->entries[i], name + namelen);
128
129 /* Not found */
130 return NULL;
131@@ -160,8 +162,6 @@ void init_paths(const char *prefix)
132 g_free(base->name);
133 g_free(base);
134 base = NULL;
135- } else {
136- set_parents(base, base);
137 }
138 }
139
140@@ -173,5 +173,5 @@ const char *path(const char *name)
141 if (!base || !name || name[0] != '/')
142 return name;
143
144- return follow_path(base, name) ?: name;
145+ return follow_path(base, &base, name) ?: name;
146 }