aboutsummaryrefslogtreecommitdiffstats
path: root/main/busybox/CVE-2014-9645.patch
blob: 5661a960ae188eeb49c7251da492084468d7923c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
diff --git a/modutils/depmod.c b/modutils/depmod.c
index aa228ec..37a8482 100644
--- a/modutils/depmod.c
+++ b/modutils/depmod.c
@@ -33,7 +33,6 @@ typedef struct module_info {
 static int FAST_FUNC parse_module(const char *fname, struct stat *sb UNUSED_PARAM,
 				void *data, int depth UNUSED_PARAM)
 {
-	char modname[MODULE_NAME_LEN];
 	module_info **first = (module_info **) data;
 	char *image, *ptr;
 	module_info *info;
@@ -51,7 +50,10 @@ static int FAST_FUNC parse_module(const char *fname, struct stat *sb UNUSED_PARA
 
 	info->dnext = info->dprev = info;
 	info->name = xstrdup(fname + 2); /* skip "./" */
-	info->modname = xstrdup(filename2modname(fname, modname));
+	info->modname = filename2modname(
+			bb_get_last_path_component_nostrip(fname),
+			NULL
+	);
 	for (ptr = image; ptr < image + len - 10; ptr++) {
 		if (strncmp(ptr, "depends=", 8) == 0) {
 			char *u;
@@ -242,17 +244,19 @@ int depmod_main(int argc UNUSED_PARAM, char **argv)
 	if (!(option_mask32 & OPT_n))
 		xfreopen_write("modules.alias", stdout);
 	for (m = modules; m != NULL; m = m->next) {
+		char modname[MODULE_NAME_LEN];
 		const char *fname = bb_basename(m->name);
-		int fnlen = strchrnul(fname, '.') - fname;
+		filename2modname(fname, modname);
 		while (m->aliases) {
-			/* Last word can well be m->modname instead,
-			 * but depmod from module-init-tools 3.4
-			 * uses module basename, i.e., no s/-/_/g.
-			 * (pathname and .ko.* are still stripped)
-			 * Mimicking that... */
-			printf("alias %s %.*s\n",
+			/*
+			 * Last word used to be a basename
+			 * (filename with path and .ko.* stripped)
+			 * at the time of module-init-tools 3.4.
+			 * kmod v.12 uses module name, i.e., s/-/_/g.
+			 */
+			printf("alias %s %s\n",
 				(char*)llist_pop(&m->aliases),
-				fnlen, fname);
+				modname);
 		}
 	}
 #endif
@@ -260,12 +264,13 @@ int depmod_main(int argc UNUSED_PARAM, char **argv)
 	if (!(option_mask32 & OPT_n))
 		xfreopen_write("modules.symbols", stdout);
 	for (m = modules; m != NULL; m = m->next) {
+		char modname[MODULE_NAME_LEN];
 		const char *fname = bb_basename(m->name);
-		int fnlen = strchrnul(fname, '.') - fname;
+		filename2modname(fname, modname);
 		while (m->symbols) {
-			printf("alias symbol:%s %.*s\n",
+			printf("alias symbol:%s %s\n",
 				(char*)llist_pop(&m->symbols),
-				fnlen, fname);
+				modname);
 		}
 	}
 #endif
diff --git a/modutils/modinfo.c b/modutils/modinfo.c
index 7c978d1..ee37930 100644
--- a/modutils/modinfo.c
+++ b/modutils/modinfo.c
@@ -34,14 +34,14 @@ struct modinfo_env {
 	int tags;
 };
 
-static int display(const char *data, const char *pattern, int flag)
+static void display(const char *data, const char *pattern, int flag)
 {
 	if (flag) {
 		int n = printf("%s:", pattern);
 		while (n++ < 16)
 			bb_putchar(' ');
 	}
-	return printf("%s%c", data, (option_mask32 & OPT_0) ? '\0' : '\n');
+	printf("%s%c", data, (option_mask32 & OPT_0) ? '\0' : '\n');
 }
 
 static void modinfo(const char *path, const char *version,
@@ -104,7 +104,8 @@ static void modinfo(const char *path, const char *version,
 				/* field prefixes are 0x80 or 0x00 */
 				if ((ptr[-1] & 0x7F) == '\0') {
 					ptr += length + 1;
-					ptr += display(ptr, pattern, (1<<j) != tags);
+					display(ptr, pattern, (1<<j) != tags);
+					ptr += strlen(ptr);
 				}
 			}
 			++ptr;
@@ -153,7 +154,7 @@ int modinfo_main(int argc UNUSED_PARAM, char **argv)
 		if (colon == NULL)
 			continue;
 		*colon = '\0';
-		filename2modname(tokens[0], name);
+		filename2modname(bb_basename(tokens[0]), name);
 		for (i = 0; argv[i]; i++) {
 			if (fnmatch(argv[i], name, 0) == 0) {
 				modinfo(tokens[0], uts.release, &env);
diff --git a/modutils/modprobe.c b/modutils/modprobe.c
index 7f7446d..0e8aa9e 100644
--- a/modutils/modprobe.c
+++ b/modutils/modprobe.c
@@ -229,9 +232,14 @@ static ALWAYS_INLINE struct module_entry *get_or_add_modentry(const char *module
 {
 	return helper_get_module(module, 1);
 }
-static ALWAYS_INLINE struct module_entry *get_modentry(const char *module)
+/* So far this function always gets a module pathname, never an alias name.
+ * The crucial difference is that pathname needs dirname stripping,
+ * while alias name must NOT do it!
+ * Testcase where dirname stripping is likely to go wrong: "modprobe devname:snd/timer"
+ */
+static ALWAYS_INLINE struct module_entry *get_modentry(const char *pathname)
 {
-	return helper_get_module(module, 0);
+	return helper_get_module(bb_get_last_path_component_nostrip(pathname), 0);
 }
 
 static void add_probe(const char *name)
@@ -417,7 +425,7 @@ static int do_modprobe(struct module_entry *m)
 
 		rc = 0;
 		fn = llist_pop(&m->deps); /* we leak it */
-		m2 = get_or_add_modentry(fn);
+		m2 = get_or_add_modentry(bb_get_last_path_component_nostrip(fn));
 
 		if (option_mask32 & OPT_REMOVE) {
 			/* modprobe -r */
@@ -499,7 +507,7 @@ static void load_modules_dep(void)
 		colon = last_char_is(tokens[0], ':');
 		if (colon == NULL)
 			continue;
-		*colon = 0;
+		*colon = '\0';
 
 		m = get_modentry(tokens[0]);
 		if (m == NULL)
@@ -546,7 +554,6 @@ int modprobe_main(int argc UNUSED_PARAM, char **argv)
 
 	if (opt & OPT_LIST_ONLY) {
 		int i;
-		char name[MODULE_NAME_LEN];
 		char *colon, *tokens[2];
 		parser_t *p = config_open2(CONFIG_DEFAULT_DEPMOD_FILE, xfopen_for_read);
 
@@ -558,10 +565,14 @@ int modprobe_main(int argc UNUSED_PARAM, char **argv)
 			if (!colon)
 				continue;
 			*colon = '\0';
-			filename2modname(tokens[0], name);
 			if (!argv[0])
 				puts(tokens[0]);
 			else {
+				char name[MODULE_NAME_LEN];
+				filename2modname(
+					bb_get_last_path_component_nostrip(tokens[0]),
+					name
+				);
 				for (i = 0; argv[i]; i++) {
 					if (fnmatch(argv[i], name, 0) == 0) {
 						puts(tokens[0]);
diff --git a/modutils/modutils.c b/modutils/modutils.c
index 6187ca7..84300d9 100644
--- a/modutils/modutils.c
+++ b/modutils/modutils.c
@@ -47,18 +47,26 @@ int FAST_FUNC string_to_llist(char *string, llist_t **llist, const char *delim)
 
 char* FAST_FUNC filename2modname(const char *filename, char *modname)
 {
+	char local_modname[MODULE_NAME_LEN];
 	int i;
-	char *from;
+	const char *from;
 
 	if (filename == NULL)
 		return NULL;
 	if (modname == NULL)
-		modname = xmalloc(MODULE_NAME_LEN);
-	from = bb_get_last_path_component_nostrip(filename);
+		modname = local_modname;
+	// Disabled since otherwise "modprobe dir/name" would work
+	// as if it is "modprobe name". It is unclear why
+	// 'basenamization' was here in the first place.
+	//from = bb_get_last_path_component_nostrip(filename);
+	from = filename;
 	for (i = 0; i < (MODULE_NAME_LEN-1) && from[i] != '\0' && from[i] != '.'; i++)
 		modname[i] = (from[i] == '-') ? '_' : from[i];
 	modname[i] = '\0';
 
+	if (modname == local_modname)
+		return xstrdup(modname);
+
 	return modname;
 }