Branch data Line data Source code
1 : : /*
2 : : * Many of the syscalls used in this file expect some of the arguments
3 : : * to be __user pointers not __kernel pointers. To limit the sparse
4 : : * noise, turn off sparse checking for this file.
5 : : */
6 : : #ifdef __CHECKER__
7 : : #undef __CHECKER__
8 : : #warning "Sparse checking disabled for this file"
9 : : #endif
10 : :
11 : : #include <linux/init.h>
12 : : #include <linux/fs.h>
13 : : #include <linux/slab.h>
14 : : #include <linux/types.h>
15 : : #include <linux/fcntl.h>
16 : : #include <linux/delay.h>
17 : : #include <linux/string.h>
18 : : #include <linux/dirent.h>
19 : : #include <linux/syscalls.h>
20 : : #include <linux/utime.h>
21 : :
22 : : static __initdata char *message;
23 : 0 : static void __init error(char *x)
24 : : {
25 [ # # ]: 0 : if (!message)
26 : 0 : message = x;
27 : 0 : }
28 : :
29 : : /* link hash */
30 : :
31 : : #define N_ALIGN(len) ((((len) + 1) & ~3) + 2)
32 : :
33 : : static __initdata struct hash {
34 : : int ino, minor, major;
35 : : umode_t mode;
36 : : struct hash *next;
37 : : char name[N_ALIGN(PATH_MAX)];
38 : : } *head[32];
39 : :
40 : : static inline int hash(int major, int minor, int ino)
41 : : {
42 : 0 : unsigned long tmp = ino + minor + (major << 3);
43 : 0 : tmp += tmp >> 5;
44 : 0 : return tmp & 31;
45 : : }
46 : :
47 : 0 : static char __init *find_link(int major, int minor, int ino,
48 : : umode_t mode, char *name)
49 : : {
50 : : struct hash **p, *q;
51 [ # # ]: 0 : for (p = head + hash(major, minor, ino); *p; p = &(*p)->next) {
52 [ # # ]: 0 : if ((*p)->ino != ino)
53 : 0 : continue;
54 [ # # ]: 0 : if ((*p)->minor != minor)
55 : 0 : continue;
56 [ # # ]: 0 : if ((*p)->major != major)
57 : 0 : continue;
58 [ # # ]: 0 : if (((*p)->mode ^ mode) & S_IFMT)
59 : 0 : continue;
60 : 0 : return (*p)->name;
61 : : }
62 : : q = kmalloc(sizeof(struct hash), GFP_KERNEL);
63 [ # # ]: 0 : if (!q)
64 : 0 : panic("can't allocate link hash entry");
65 : 0 : q->major = major;
66 : 0 : q->minor = minor;
67 : 0 : q->ino = ino;
68 : 0 : q->mode = mode;
69 : 0 : strcpy(q->name, name);
70 : 0 : q->next = NULL;
71 : 0 : *p = q;
72 : 0 : return NULL;
73 : : }
74 : :
75 : 0 : static void __init free_hash(void)
76 : : {
77 : : struct hash **p, *q;
78 [ # # ]: 0 : for (p = head; p < head + 32; p++) {
79 [ # # ]: 0 : while (*p) {
80 : : q = *p;
81 : 0 : *p = q->next;
82 : 0 : kfree(q);
83 : : }
84 : : }
85 : 0 : }
86 : :
87 : 0 : static long __init do_utime(char *filename, time_t mtime)
88 : : {
89 : : struct timespec t[2];
90 : :
91 : 0 : t[0].tv_sec = mtime;
92 : 0 : t[0].tv_nsec = 0;
93 : 0 : t[1].tv_sec = mtime;
94 : 0 : t[1].tv_nsec = 0;
95 : :
96 : 0 : return do_utimes(AT_FDCWD, filename, t, AT_SYMLINK_NOFOLLOW);
97 : : }
98 : :
99 : : static __initdata LIST_HEAD(dir_list);
100 : : struct dir_entry {
101 : : struct list_head list;
102 : : char *name;
103 : : time_t mtime;
104 : : };
105 : :
106 : 0 : static void __init dir_add(const char *name, time_t mtime)
107 : : {
108 : : struct dir_entry *de = kmalloc(sizeof(struct dir_entry), GFP_KERNEL);
109 [ # # ]: 0 : if (!de)
110 : 0 : panic("can't allocate dir_entry buffer");
111 : 0 : INIT_LIST_HEAD(&de->list);
112 : 0 : de->name = kstrdup(name, GFP_KERNEL);
113 : 0 : de->mtime = mtime;
114 : : list_add(&de->list, &dir_list);
115 : 0 : }
116 : :
117 : 0 : static void __init dir_utime(void)
118 : : {
119 : : struct dir_entry *de, *tmp;
120 [ # # ]: 0 : list_for_each_entry_safe(de, tmp, &dir_list, list) {
121 : : list_del(&de->list);
122 : 0 : do_utime(de->name, de->mtime);
123 : 0 : kfree(de->name);
124 : 0 : kfree(de);
125 : : }
126 : 0 : }
127 : :
128 : : static __initdata time_t mtime;
129 : :
130 : : /* cpio header parsing */
131 : :
132 : : static __initdata unsigned long ino, major, minor, nlink;
133 : : static __initdata umode_t mode;
134 : : static __initdata unsigned long body_len, name_len;
135 : : static __initdata uid_t uid;
136 : : static __initdata gid_t gid;
137 : : static __initdata unsigned rdev;
138 : :
139 : 0 : static void __init parse_header(char *s)
140 : : {
141 : : unsigned long parsed[12];
142 : : char buf[9];
143 : : int i;
144 : :
145 : 0 : buf[8] = '\0';
146 [ # # ]: 0 : for (i = 0, s += 6; i < 12; i++, s += 8) {
147 : 0 : memcpy(buf, s, 8);
148 : 0 : parsed[i] = simple_strtoul(buf, NULL, 16);
149 : : }
150 : 0 : ino = parsed[0];
151 : 0 : mode = parsed[1];
152 : 0 : uid = parsed[2];
153 : 0 : gid = parsed[3];
154 : 0 : nlink = parsed[4];
155 : 0 : mtime = parsed[5];
156 : 0 : body_len = parsed[6];
157 : 0 : major = parsed[7];
158 : 0 : minor = parsed[8];
159 : 0 : rdev = new_encode_dev(MKDEV(parsed[9], parsed[10]));
160 : 0 : name_len = parsed[11];
161 : 0 : }
162 : :
163 : : /* FSM */
164 : :
165 : : static __initdata enum state {
166 : : Start,
167 : : Collect,
168 : : GotHeader,
169 : : SkipIt,
170 : : GotName,
171 : : CopyFile,
172 : : GotSymlink,
173 : : Reset
174 : : } state, next_state;
175 : :
176 : : static __initdata char *victim;
177 : : static __initdata unsigned count;
178 : : static __initdata loff_t this_header, next_header;
179 : :
180 : : static inline void __init eat(unsigned n)
181 : : {
182 : 0 : victim += n;
183 : 0 : this_header += n;
184 : 0 : count -= n;
185 : : }
186 : :
187 : : static __initdata char *vcollected;
188 : : static __initdata char *collected;
189 : : static __initdata int remains;
190 : : static __initdata char *collect;
191 : :
192 : 0 : static void __init read_into(char *buf, unsigned size, enum state next)
193 : : {
194 [ # # ]: 0 : if (count >= size) {
195 : 0 : collected = victim;
196 : : eat(size);
197 : 0 : state = next;
198 : : } else {
199 : 0 : collect = collected = buf;
200 : 0 : remains = size;
201 : 0 : next_state = next;
202 : 0 : state = Collect;
203 : : }
204 : 0 : }
205 : :
206 : : static __initdata char *header_buf, *symlink_buf, *name_buf;
207 : :
208 : 0 : static int __init do_start(void)
209 : : {
210 : 0 : read_into(header_buf, 110, GotHeader);
211 : 0 : return 0;
212 : : }
213 : :
214 : 0 : static int __init do_collect(void)
215 : : {
216 : 0 : unsigned n = remains;
217 [ # # ]: 0 : if (count < n)
218 : : n = count;
219 : 0 : memcpy(collect, victim, n);
220 : : eat(n);
221 : 0 : collect += n;
222 [ # # ]: 0 : if ((remains -= n) != 0)
223 : : return 1;
224 : 0 : state = next_state;
225 : 0 : return 0;
226 : : }
227 : :
228 : 0 : static int __init do_header(void)
229 : : {
230 [ # # ]: 0 : if (memcmp(collected, "070707", 6)==0) {
231 : 0 : error("incorrect cpio method used: use -H newc option");
232 : 0 : return 1;
233 : : }
234 [ # # ]: 0 : if (memcmp(collected, "070701", 6)) {
235 : 0 : error("no cpio magic");
236 : 0 : return 1;
237 : : }
238 : 0 : parse_header(collected);
239 : 0 : next_header = this_header + N_ALIGN(name_len) + body_len;
240 : 0 : next_header = (next_header + 3) & ~3;
241 : 0 : state = SkipIt;
242 [ # # ]: 0 : if (name_len <= 0 || name_len > PATH_MAX)
243 : : return 0;
244 [ # # ]: 0 : if (S_ISLNK(mode)) {
245 [ # # ]: 0 : if (body_len > PATH_MAX)
246 : : return 0;
247 : 0 : collect = collected = symlink_buf;
248 : 0 : remains = N_ALIGN(name_len) + body_len;
249 : 0 : next_state = GotSymlink;
250 : 0 : state = Collect;
251 : 0 : return 0;
252 : : }
253 [ # # ][ # # ]: 0 : if (S_ISREG(mode) || !body_len)
254 : 0 : read_into(name_buf, N_ALIGN(name_len), GotName);
255 : : return 0;
256 : : }
257 : :
258 : 0 : static int __init do_skip(void)
259 : : {
260 [ # # ]: 0 : if (this_header + count < next_header) {
261 : : eat(count);
262 : 0 : return 1;
263 : : } else {
264 : 0 : eat(next_header - this_header);
265 : 0 : state = next_state;
266 : 0 : return 0;
267 : : }
268 : : }
269 : :
270 : 0 : static int __init do_reset(void)
271 : : {
272 [ # # ][ # # ]: 0 : while(count && *victim == '\0')
273 : : eat(1);
274 [ # # ][ # # ]: 0 : if (count && (this_header & 3))
275 : 0 : error("broken padding");
276 : 0 : return 1;
277 : : }
278 : :
279 : 0 : static int __init maybe_link(void)
280 : : {
281 [ # # ]: 0 : if (nlink >= 2) {
282 : 0 : char *old = find_link(major, minor, ino, mode, collected);
283 [ # # ]: 0 : if (old)
284 [ # # ]: 0 : return (sys_link(old, collected) < 0) ? -1 : 1;
285 : : }
286 : : return 0;
287 : : }
288 : :
289 : 0 : static void __init clean_path(char *path, umode_t mode)
290 : : {
291 : : struct stat st;
292 : :
293 [ # # ][ # # ]: 0 : if (!sys_newlstat(path, &st) && (st.st_mode^mode) & S_IFMT) {
294 [ # # ]: 0 : if (S_ISDIR(st.st_mode))
295 : 0 : sys_rmdir(path);
296 : : else
297 : 0 : sys_unlink(path);
298 : : }
299 : 0 : }
300 : :
301 : : static __initdata int wfd;
302 : :
303 : 0 : static int __init do_name(void)
304 : : {
305 : 0 : state = SkipIt;
306 : 0 : next_state = Reset;
307 [ # # ]: 0 : if (strcmp(collected, "TRAILER!!!") == 0) {
308 : 0 : free_hash();
309 : 0 : return 0;
310 : : }
311 : 0 : clean_path(collected, mode);
312 [ # # ]: 0 : if (S_ISREG(mode)) {
313 : 0 : int ml = maybe_link();
314 [ # # ]: 0 : if (ml >= 0) {
315 : : int openflags = O_WRONLY|O_CREAT;
316 [ # # ]: 0 : if (ml != 1)
317 : : openflags |= O_TRUNC;
318 : 0 : wfd = sys_open(collected, openflags, mode);
319 : :
320 [ # # ]: 0 : if (wfd >= 0) {
321 : 0 : sys_fchown(wfd, uid, gid);
322 : 0 : sys_fchmod(wfd, mode);
323 [ # # ]: 0 : if (body_len)
324 : 0 : sys_ftruncate(wfd, body_len);
325 : 0 : vcollected = kstrdup(collected, GFP_KERNEL);
326 : 0 : state = CopyFile;
327 : : }
328 : : }
329 [ # # ]: 0 : } else if (S_ISDIR(mode)) {
330 : 0 : sys_mkdir(collected, mode);
331 : 0 : sys_chown(collected, uid, gid);
332 : 0 : sys_chmod(collected, mode);
333 : 0 : dir_add(collected, mtime);
334 [ # # ][ # # ]: 0 : } else if (S_ISBLK(mode) || S_ISCHR(mode) ||
335 [ # # ]: 0 : S_ISFIFO(mode) || S_ISSOCK(mode)) {
336 [ # # ]: 0 : if (maybe_link() == 0) {
337 : 0 : sys_mknod(collected, mode, rdev);
338 : 0 : sys_chown(collected, uid, gid);
339 : 0 : sys_chmod(collected, mode);
340 : 0 : do_utime(collected, mtime);
341 : : }
342 : : }
343 : : return 0;
344 : : }
345 : :
346 : 0 : static int __init do_copy(void)
347 : : {
348 [ # # ]: 0 : if (count >= body_len) {
349 : 0 : sys_write(wfd, victim, body_len);
350 : 0 : sys_close(wfd);
351 : 0 : do_utime(vcollected, mtime);
352 : 0 : kfree(vcollected);
353 : 0 : eat(body_len);
354 : 0 : state = SkipIt;
355 : 0 : return 0;
356 : : } else {
357 : 0 : sys_write(wfd, victim, count);
358 : 0 : body_len -= count;
359 : : eat(count);
360 : 0 : return 1;
361 : : }
362 : : }
363 : :
364 : 0 : static int __init do_symlink(void)
365 : : {
366 : 0 : collected[N_ALIGN(name_len) + body_len] = '\0';
367 : 0 : clean_path(collected, 0);
368 : 0 : sys_symlink(collected + N_ALIGN(name_len), collected);
369 : 0 : sys_lchown(collected, uid, gid);
370 : 0 : do_utime(collected, mtime);
371 : 0 : state = SkipIt;
372 : 0 : next_state = Reset;
373 : 0 : return 0;
374 : : }
375 : :
376 : : static __initdata int (*actions[])(void) = {
377 : : [Start] = do_start,
378 : : [Collect] = do_collect,
379 : : [GotHeader] = do_header,
380 : : [SkipIt] = do_skip,
381 : : [GotName] = do_name,
382 : : [CopyFile] = do_copy,
383 : : [GotSymlink] = do_symlink,
384 : : [Reset] = do_reset,
385 : : };
386 : :
387 : 0 : static int __init write_buffer(char *buf, unsigned len)
388 : : {
389 : 0 : count = len;
390 : 0 : victim = buf;
391 : :
392 [ # # ]: 0 : while (!actions[state]())
393 : : ;
394 : 0 : return len - count;
395 : : }
396 : :
397 : 0 : static int __init flush_buffer(void *bufv, unsigned len)
398 : : {
399 : : char *buf = (char *) bufv;
400 : : int written;
401 : 0 : int origLen = len;
402 [ # # ]: 0 : if (message)
403 : : return -1;
404 [ # # ][ # # ]: 0 : while ((written = write_buffer(buf, len)) < len && !message) {
405 : 0 : char c = buf[written];
406 [ # # ]: 0 : if (c == '0') {
407 : : buf += written;
408 : 0 : len -= written;
409 : 0 : state = Start;
410 [ # # ]: 0 : } else if (c == 0) {
411 : : buf += written;
412 : 0 : len -= written;
413 : 0 : state = Reset;
414 : : } else
415 : 0 : error("junk in compressed archive");
416 : : }
417 : : return origLen;
418 : : }
419 : :
420 : : static unsigned my_inptr; /* index of next byte to be processed in inbuf */
421 : :
422 : : #include <linux/decompress/generic.h>
423 : :
424 : 0 : static char * __init unpack_to_rootfs(char *buf, unsigned len)
425 : : {
426 : : int written, res;
427 : : decompress_fn decompress;
428 : : const char *compress_name;
429 : : static __initdata char msg_buf[64];
430 : :
431 : 0 : header_buf = kmalloc(110, GFP_KERNEL);
432 : 0 : symlink_buf = kmalloc(PATH_MAX + N_ALIGN(PATH_MAX) + 1, GFP_KERNEL);
433 : 0 : name_buf = kmalloc(N_ALIGN(PATH_MAX), GFP_KERNEL);
434 : :
435 [ # # ][ # # ]: 0 : if (!header_buf || !symlink_buf || !name_buf)
[ # # ]
436 : 0 : panic("can't allocate buffers");
437 : :
438 : 0 : state = Start;
439 : 0 : this_header = 0;
440 : 0 : message = NULL;
441 [ # # ][ # # ]: 0 : while (!message && len) {
442 : 0 : loff_t saved_offset = this_header;
443 [ # # ][ # # ]: 0 : if (*buf == '0' && !(this_header & 3)) {
444 : 0 : state = Start;
445 : 0 : written = write_buffer(buf, len);
446 : 0 : buf += written;
447 : 0 : len -= written;
448 : 0 : continue;
449 : : }
450 [ # # ]: 0 : if (!*buf) {
451 : 0 : buf++;
452 : 0 : len--;
453 : 0 : this_header++;
454 : 0 : continue;
455 : : }
456 : 0 : this_header = 0;
457 : 0 : decompress = decompress_method(buf, len, &compress_name);
458 [ # # ]: 0 : if (decompress) {
459 : 0 : res = decompress(buf, len, NULL, flush_buffer, NULL,
460 : : &my_inptr, error);
461 [ # # ]: 0 : if (res)
462 : 0 : error("decompressor failed");
463 [ # # ]: 0 : } else if (compress_name) {
464 [ # # ]: 0 : if (!message) {
465 : 0 : snprintf(msg_buf, sizeof msg_buf,
466 : : "compression method %s not configured",
467 : : compress_name);
468 : 0 : message = msg_buf;
469 : : }
470 : : } else
471 : 0 : error("junk in compressed archive");
472 [ # # ]: 0 : if (state != Reset)
473 : 0 : error("junk in compressed archive");
474 : 0 : this_header = saved_offset + my_inptr;
475 : 0 : buf += my_inptr;
476 : 0 : len -= my_inptr;
477 : : }
478 : 0 : dir_utime();
479 : 0 : kfree(name_buf);
480 : 0 : kfree(symlink_buf);
481 : 0 : kfree(header_buf);
482 : 0 : return message;
483 : : }
484 : :
485 : : static int __initdata do_retain_initrd;
486 : :
487 : 0 : static int __init retain_initrd_param(char *str)
488 : : {
489 [ # # ]: 0 : if (*str)
490 : : return 0;
491 : 0 : do_retain_initrd = 1;
492 : 0 : return 1;
493 : : }
494 : : __setup("retain_initrd", retain_initrd_param);
495 : :
496 : : extern char __initramfs_start[];
497 : : extern unsigned long __initramfs_size;
498 : : #include <linux/initrd.h>
499 : : #include <linux/kexec.h>
500 : :
501 : 0 : static void __init free_initrd(void)
502 : : {
503 : : #ifdef CONFIG_KEXEC
504 : : unsigned long crashk_start = (unsigned long)__va(crashk_res.start);
505 : : unsigned long crashk_end = (unsigned long)__va(crashk_res.end);
506 : : #endif
507 [ # # ]: 0 : if (do_retain_initrd)
508 : : goto skip;
509 : :
510 : : #ifdef CONFIG_KEXEC
511 : : /*
512 : : * If the initrd region is overlapped with crashkernel reserved region,
513 : : * free only memory that is not part of crashkernel region.
514 : : */
515 : : if (initrd_start < crashk_end && initrd_end > crashk_start) {
516 : : /*
517 : : * Initialize initrd memory region since the kexec boot does
518 : : * not do.
519 : : */
520 : : memset((void *)initrd_start, 0, initrd_end - initrd_start);
521 : : if (initrd_start < crashk_start)
522 : : free_initrd_mem(initrd_start, crashk_start);
523 : : if (initrd_end > crashk_end)
524 : : free_initrd_mem(crashk_end, initrd_end);
525 : : } else
526 : : #endif
527 : 0 : free_initrd_mem(initrd_start, initrd_end);
528 : : skip:
529 : 0 : initrd_start = 0;
530 : 0 : initrd_end = 0;
531 : 0 : }
532 : :
533 : : #ifdef CONFIG_BLK_DEV_RAM
534 : : #define BUF_SIZE 1024
535 : 0 : static void __init clean_rootfs(void)
536 : : {
537 : : int fd;
538 : : void *buf;
539 : : struct linux_dirent64 *dirp;
540 : : int num;
541 : :
542 : 0 : fd = sys_open("/", O_RDONLY, 0);
543 [ # # ]: 0 : WARN_ON(fd < 0);
544 [ # # ]: 0 : if (fd < 0)
545 : : return;
546 : : buf = kzalloc(BUF_SIZE, GFP_KERNEL);
547 [ # # ]: 0 : WARN_ON(!buf);
548 [ # # ]: 0 : if (!buf) {
549 : 0 : sys_close(fd);
550 : 0 : return;
551 : : }
552 : :
553 : : dirp = buf;
554 : 0 : num = sys_getdents64(fd, dirp, BUF_SIZE);
555 [ # # ]: 0 : while (num > 0) {
556 [ # # ]: 0 : while (num > 0) {
557 : : struct stat st;
558 : : int ret;
559 : :
560 : 0 : ret = sys_newlstat(dirp->d_name, &st);
561 [ # # ][ # # ]: 0 : WARN_ON_ONCE(ret);
[ # # ]
562 [ # # ]: 0 : if (!ret) {
563 [ # # ]: 0 : if (S_ISDIR(st.st_mode))
564 : 0 : sys_rmdir(dirp->d_name);
565 : : else
566 : 0 : sys_unlink(dirp->d_name);
567 : : }
568 : :
569 : 0 : num -= dirp->d_reclen;
570 : 0 : dirp = (void *)dirp + dirp->d_reclen;
571 : : }
572 : : dirp = buf;
573 : 0 : memset(buf, 0, BUF_SIZE);
574 : 0 : num = sys_getdents64(fd, dirp, BUF_SIZE);
575 : : }
576 : :
577 : 0 : sys_close(fd);
578 : 0 : kfree(buf);
579 : : }
580 : : #endif
581 : :
582 : 0 : static int __init populate_rootfs(void)
583 : : {
584 : 0 : char *err = unpack_to_rootfs(__initramfs_start, __initramfs_size);
585 [ # # ]: 0 : if (err)
586 : 0 : panic(err); /* Failed to decompress INTERNAL initramfs */
587 [ # # ]: 0 : if (initrd_start) {
588 : : #ifdef CONFIG_BLK_DEV_RAM
589 : : int fd;
590 : 0 : printk(KERN_INFO "Trying to unpack rootfs image as initramfs...\n");
591 : 0 : err = unpack_to_rootfs((char *)initrd_start,
592 : 0 : initrd_end - initrd_start);
593 [ # # ]: 0 : if (!err) {
594 : 0 : free_initrd();
595 : 0 : goto done;
596 : : } else {
597 : 0 : clean_rootfs();
598 : 0 : unpack_to_rootfs(__initramfs_start, __initramfs_size);
599 : : }
600 : 0 : printk(KERN_INFO "rootfs image is not initramfs (%s)"
601 : : "; looks like an initrd\n", err);
602 : 0 : fd = sys_open("/initrd.image",
603 : : O_WRONLY|O_CREAT, 0700);
604 [ # # ]: 0 : if (fd >= 0) {
605 : 0 : sys_write(fd, (char *)initrd_start,
606 : 0 : initrd_end - initrd_start);
607 : 0 : sys_close(fd);
608 : 0 : free_initrd();
609 : : }
610 : : done:
611 : : #else
612 : : printk(KERN_INFO "Unpacking initramfs...\n");
613 : : err = unpack_to_rootfs((char *)initrd_start,
614 : : initrd_end - initrd_start);
615 : : if (err)
616 : : printk(KERN_EMERG "Initramfs unpacking failed: %s\n", err);
617 : : free_initrd();
618 : : #endif
619 : : /*
620 : : * Try loading default modules from initramfs. This gives
621 : : * us a chance to load before device_initcalls.
622 : : */
623 : 0 : load_default_modules();
624 : : }
625 : 0 : return 0;
626 : : }
627 : : rootfs_initcall(populate_rootfs);
|