LCOV - code coverage report
Current view: top level - init - initramfs.c (source / functions) Hit Total Coverage
Test: landlock.info Lines: 149 354 42.1 %
Date: 2021-04-22 12:43:58 Functions: 17 28 60.7 %

          Line data    Source code
       1             : // SPDX-License-Identifier: GPL-2.0
       2             : #include <linux/init.h>
       3             : #include <linux/fs.h>
       4             : #include <linux/slab.h>
       5             : #include <linux/types.h>
       6             : #include <linux/fcntl.h>
       7             : #include <linux/delay.h>
       8             : #include <linux/string.h>
       9             : #include <linux/dirent.h>
      10             : #include <linux/syscalls.h>
      11             : #include <linux/utime.h>
      12             : #include <linux/file.h>
      13             : #include <linux/memblock.h>
      14             : #include <linux/mm.h>
      15             : #include <linux/namei.h>
      16             : #include <linux/init_syscalls.h>
      17             : 
      18           0 : static ssize_t __init xwrite(struct file *file, const char *p, size_t count,
      19             :                 loff_t *pos)
      20             : {
      21           0 :         ssize_t out = 0;
      22             : 
      23             :         /* sys_write only can write MAX_RW_COUNT aka 2G-4K bytes at most */
      24           0 :         while (count) {
      25           0 :                 ssize_t rv = kernel_write(file, p, count, pos);
      26             : 
      27           0 :                 if (rv < 0) {
      28           0 :                         if (rv == -EINTR || rv == -EAGAIN)
      29           0 :                                 continue;
      30           0 :                         return out ? out : rv;
      31           0 :                 } else if (rv == 0)
      32             :                         break;
      33             : 
      34           0 :                 p += rv;
      35           0 :                 out += rv;
      36           0 :                 count -= rv;
      37             :         }
      38             : 
      39             :         return out;
      40             : }
      41             : 
      42             : static __initdata char *message;
      43           0 : static void __init error(char *x)
      44             : {
      45           0 :         if (!message)
      46           0 :                 message = x;
      47           0 : }
      48             : 
      49           0 : static void panic_show_mem(const char *fmt, ...)
      50             : {
      51           0 :         va_list args;
      52             : 
      53           0 :         show_mem(0, NULL);
      54           0 :         va_start(args, fmt);
      55           0 :         panic(fmt, args);
      56             :         va_end(args);
      57             : }
      58             : 
      59             : /* link hash */
      60             : 
      61             : #define N_ALIGN(len) ((((len) + 1) & ~3) + 2)
      62             : 
      63             : static __initdata struct hash {
      64             :         int ino, minor, major;
      65             :         umode_t mode;
      66             :         struct hash *next;
      67             :         char name[N_ALIGN(PATH_MAX)];
      68             : } *head[32];
      69             : 
      70           0 : static inline int hash(int major, int minor, int ino)
      71             : {
      72           0 :         unsigned long tmp = ino + minor + (major << 3);
      73           0 :         tmp += tmp >> 5;
      74           0 :         return tmp & 31;
      75             : }
      76             : 
      77           0 : static char __init *find_link(int major, int minor, int ino,
      78             :                               umode_t mode, char *name)
      79             : {
      80           0 :         struct hash **p, *q;
      81           0 :         for (p = head + hash(major, minor, ino); *p; p = &(*p)->next) {
      82           0 :                 if ((*p)->ino != ino)
      83           0 :                         continue;
      84           0 :                 if ((*p)->minor != minor)
      85           0 :                         continue;
      86           0 :                 if ((*p)->major != major)
      87           0 :                         continue;
      88           0 :                 if (((*p)->mode ^ mode) & S_IFMT)
      89           0 :                         continue;
      90           0 :                 return (*p)->name;
      91             :         }
      92           0 :         q = kmalloc(sizeof(struct hash), GFP_KERNEL);
      93           0 :         if (!q)
      94           0 :                 panic_show_mem("can't allocate link hash entry");
      95           0 :         q->major = major;
      96           0 :         q->minor = minor;
      97           0 :         q->ino = ino;
      98           0 :         q->mode = mode;
      99           0 :         strcpy(q->name, name);
     100           0 :         q->next = NULL;
     101           0 :         *p = q;
     102           0 :         return NULL;
     103             : }
     104             : 
     105           1 : static void __init free_hash(void)
     106             : {
     107           1 :         struct hash **p, *q;
     108          33 :         for (p = head; p < head + 32; p++) {
     109          32 :                 while (*p) {
     110           0 :                         q = *p;
     111           0 :                         *p = q->next;
     112           0 :                         kfree(q);
     113             :                 }
     114             :         }
     115           1 : }
     116             : 
     117           3 : static long __init do_utime(char *filename, time64_t mtime)
     118             : {
     119           3 :         struct timespec64 t[2];
     120             : 
     121           3 :         t[0].tv_sec = mtime;
     122           3 :         t[0].tv_nsec = 0;
     123           3 :         t[1].tv_sec = mtime;
     124           3 :         t[1].tv_nsec = 0;
     125           3 :         return init_utimes(filename, t);
     126             : }
     127             : 
     128             : static __initdata LIST_HEAD(dir_list);
     129             : struct dir_entry {
     130             :         struct list_head list;
     131             :         char *name;
     132             :         time64_t mtime;
     133             : };
     134             : 
     135           2 : static void __init dir_add(const char *name, time64_t mtime)
     136             : {
     137           2 :         struct dir_entry *de = kmalloc(sizeof(struct dir_entry), GFP_KERNEL);
     138           2 :         if (!de)
     139           0 :                 panic_show_mem("can't allocate dir_entry buffer");
     140           2 :         INIT_LIST_HEAD(&de->list);
     141           2 :         de->name = kstrdup(name, GFP_KERNEL);
     142           2 :         de->mtime = mtime;
     143           2 :         list_add(&de->list, &dir_list);
     144           2 : }
     145             : 
     146           1 : static void __init dir_utime(void)
     147             : {
     148           1 :         struct dir_entry *de, *tmp;
     149           3 :         list_for_each_entry_safe(de, tmp, &dir_list, list) {
     150           2 :                 list_del(&de->list);
     151           2 :                 do_utime(de->name, de->mtime);
     152           2 :                 kfree(de->name);
     153           2 :                 kfree(de);
     154             :         }
     155           1 : }
     156             : 
     157             : static __initdata time64_t mtime;
     158             : 
     159             : /* cpio header parsing */
     160             : 
     161             : static __initdata unsigned long ino, major, minor, nlink;
     162             : static __initdata umode_t mode;
     163             : static __initdata unsigned long body_len, name_len;
     164             : static __initdata uid_t uid;
     165             : static __initdata gid_t gid;
     166             : static __initdata unsigned rdev;
     167             : 
     168           4 : static void __init parse_header(char *s)
     169             : {
     170           4 :         unsigned long parsed[12];
     171           4 :         char buf[9];
     172           4 :         int i;
     173             : 
     174           4 :         buf[8] = '\0';
     175          52 :         for (i = 0, s += 6; i < 12; i++, s += 8) {
     176          48 :                 memcpy(buf, s, 8);
     177          48 :                 parsed[i] = simple_strtoul(buf, NULL, 16);
     178             :         }
     179           4 :         ino = parsed[0];
     180           4 :         mode = parsed[1];
     181           4 :         uid = parsed[2];
     182           4 :         gid = parsed[3];
     183           4 :         nlink = parsed[4];
     184           4 :         mtime = parsed[5]; /* breaks in y2106 */
     185           4 :         body_len = parsed[6];
     186           4 :         major = parsed[7];
     187           4 :         minor = parsed[8];
     188           4 :         rdev = new_encode_dev(MKDEV(parsed[9], parsed[10]));
     189           4 :         name_len = parsed[11];
     190           4 : }
     191             : 
     192             : /* FSM */
     193             : 
     194             : static __initdata enum state {
     195             :         Start,
     196             :         Collect,
     197             :         GotHeader,
     198             :         SkipIt,
     199             :         GotName,
     200             :         CopyFile,
     201             :         GotSymlink,
     202             :         Reset
     203             : } state, next_state;
     204             : 
     205             : static __initdata char *victim;
     206             : static unsigned long byte_count __initdata;
     207             : static __initdata loff_t this_header, next_header;
     208             : 
     209          44 : static inline void __init eat(unsigned n)
     210             : {
     211          44 :         victim += n;
     212          44 :         this_header += n;
     213          44 :         byte_count -= n;
     214          44 : }
     215             : 
     216             : static __initdata char *collected;
     217             : static long remains __initdata;
     218             : static __initdata char *collect;
     219             : 
     220           8 : static void __init read_into(char *buf, unsigned size, enum state next)
     221             : {
     222           8 :         if (byte_count >= size) {
     223           8 :                 collected = victim;
     224           8 :                 eat(size);
     225           8 :                 state = next;
     226             :         } else {
     227           0 :                 collect = collected = buf;
     228           0 :                 remains = size;
     229           0 :                 next_state = next;
     230           0 :                 state = Collect;
     231             :         }
     232           8 : }
     233             : 
     234             : static __initdata char *header_buf, *symlink_buf, *name_buf;
     235             : 
     236           4 : static int __init do_start(void)
     237             : {
     238           4 :         read_into(header_buf, 110, GotHeader);
     239           4 :         return 0;
     240             : }
     241             : 
     242           0 : static int __init do_collect(void)
     243             : {
     244           0 :         unsigned long n = remains;
     245           0 :         if (byte_count < n)
     246             :                 n = byte_count;
     247           0 :         memcpy(collect, victim, n);
     248           0 :         eat(n);
     249           0 :         collect += n;
     250           0 :         if ((remains -= n) != 0)
     251             :                 return 1;
     252           0 :         state = next_state;
     253           0 :         return 0;
     254             : }
     255             : 
     256           4 : static int __init do_header(void)
     257             : {
     258           4 :         if (memcmp(collected, "070707", 6)==0) {
     259           0 :                 error("incorrect cpio method used: use -H newc option");
     260           0 :                 return 1;
     261             :         }
     262           4 :         if (memcmp(collected, "070701", 6)) {
     263           0 :                 error("no cpio magic");
     264           0 :                 return 1;
     265             :         }
     266           4 :         parse_header(collected);
     267           4 :         next_header = this_header + N_ALIGN(name_len) + body_len;
     268           4 :         next_header = (next_header + 3) & ~3;
     269           4 :         state = SkipIt;
     270           4 :         if (name_len <= 0 || name_len > PATH_MAX)
     271             :                 return 0;
     272           4 :         if (S_ISLNK(mode)) {
     273           0 :                 if (body_len > PATH_MAX)
     274             :                         return 0;
     275           0 :                 collect = collected = symlink_buf;
     276           0 :                 remains = N_ALIGN(name_len) + body_len;
     277           0 :                 next_state = GotSymlink;
     278           0 :                 state = Collect;
     279           0 :                 return 0;
     280             :         }
     281           4 :         if (S_ISREG(mode) || !body_len)
     282           4 :                 read_into(name_buf, N_ALIGN(name_len), GotName);
     283             :         return 0;
     284             : }
     285             : 
     286           4 : static int __init do_skip(void)
     287             : {
     288           4 :         if (this_header + byte_count < next_header) {
     289           0 :                 eat(byte_count);
     290           0 :                 return 1;
     291             :         } else {
     292           4 :                 eat(next_header - this_header);
     293           4 :                 state = next_state;
     294           4 :                 return 0;
     295             :         }
     296             : }
     297             : 
     298           4 : static int __init do_reset(void)
     299             : {
     300          36 :         while (byte_count && *victim == '\0')
     301          32 :                 eat(1);
     302           4 :         if (byte_count && (this_header & 3))
     303           0 :                 error("broken padding");
     304           4 :         return 1;
     305             : }
     306             : 
     307           3 : static void __init clean_path(char *path, umode_t fmode)
     308             : {
     309           3 :         struct kstat st;
     310             : 
     311           3 :         if (!init_stat(path, &st, AT_SYMLINK_NOFOLLOW) &&
     312           0 :             (st.mode ^ fmode) & S_IFMT) {
     313           0 :                 if (S_ISDIR(st.mode))
     314           0 :                         init_rmdir(path);
     315             :                 else
     316           0 :                         init_unlink(path);
     317             :         }
     318           3 : }
     319             : 
     320           1 : static int __init maybe_link(void)
     321             : {
     322           1 :         if (nlink >= 2) {
     323           0 :                 char *old = find_link(major, minor, ino, mode, collected);
     324           0 :                 if (old) {
     325           0 :                         clean_path(collected, 0);
     326           0 :                         return (init_link(old, collected) < 0) ? -1 : 1;
     327             :                 }
     328             :         }
     329             :         return 0;
     330             : }
     331             : 
     332             : static __initdata struct file *wfile;
     333             : static __initdata loff_t wfile_pos;
     334             : 
     335           4 : static int __init do_name(void)
     336             : {
     337           4 :         state = SkipIt;
     338           4 :         next_state = Reset;
     339           4 :         if (strcmp(collected, "TRAILER!!!") == 0) {
     340           1 :                 free_hash();
     341           1 :                 return 0;
     342             :         }
     343           3 :         clean_path(collected, mode);
     344           3 :         if (S_ISREG(mode)) {
     345           0 :                 int ml = maybe_link();
     346           0 :                 if (ml >= 0) {
     347           0 :                         int openflags = O_WRONLY|O_CREAT;
     348           0 :                         if (ml != 1)
     349           0 :                                 openflags |= O_TRUNC;
     350           0 :                         wfile = filp_open(collected, openflags, mode);
     351           0 :                         if (IS_ERR(wfile))
     352             :                                 return 0;
     353           0 :                         wfile_pos = 0;
     354             : 
     355           0 :                         vfs_fchown(wfile, uid, gid);
     356           0 :                         vfs_fchmod(wfile, mode);
     357           0 :                         if (body_len)
     358           0 :                                 vfs_truncate(&wfile->f_path, body_len);
     359           0 :                         state = CopyFile;
     360             :                 }
     361           3 :         } else if (S_ISDIR(mode)) {
     362           2 :                 init_mkdir(collected, mode);
     363           2 :                 init_chown(collected, uid, gid, 0);
     364           2 :                 init_chmod(collected, mode);
     365           2 :                 dir_add(collected, mtime);
     366           1 :         } else if (S_ISBLK(mode) || S_ISCHR(mode) ||
     367           0 :                    S_ISFIFO(mode) || S_ISSOCK(mode)) {
     368           1 :                 if (maybe_link() == 0) {
     369           1 :                         init_mknod(collected, mode, rdev);
     370           1 :                         init_chown(collected, uid, gid, 0);
     371           1 :                         init_chmod(collected, mode);
     372           1 :                         do_utime(collected, mtime);
     373             :                 }
     374             :         }
     375             :         return 0;
     376             : }
     377             : 
     378           0 : static int __init do_copy(void)
     379             : {
     380           0 :         if (byte_count >= body_len) {
     381           0 :                 struct timespec64 t[2] = { };
     382           0 :                 if (xwrite(wfile, victim, body_len, &wfile_pos) != body_len)
     383           0 :                         error("write error");
     384             : 
     385           0 :                 t[0].tv_sec = mtime;
     386           0 :                 t[1].tv_sec = mtime;
     387           0 :                 vfs_utimes(&wfile->f_path, t);
     388             : 
     389           0 :                 fput(wfile);
     390           0 :                 eat(body_len);
     391           0 :                 state = SkipIt;
     392           0 :                 return 0;
     393             :         } else {
     394           0 :                 if (xwrite(wfile, victim, byte_count, &wfile_pos) != byte_count)
     395           0 :                         error("write error");
     396           0 :                 body_len -= byte_count;
     397           0 :                 eat(byte_count);
     398           0 :                 return 1;
     399             :         }
     400             : }
     401             : 
     402           0 : static int __init do_symlink(void)
     403             : {
     404           0 :         collected[N_ALIGN(name_len) + body_len] = '\0';
     405           0 :         clean_path(collected, 0);
     406           0 :         init_symlink(collected + N_ALIGN(name_len), collected);
     407           0 :         init_chown(collected, uid, gid, AT_SYMLINK_NOFOLLOW);
     408           0 :         do_utime(collected, mtime);
     409           0 :         state = SkipIt;
     410           0 :         next_state = Reset;
     411           0 :         return 0;
     412             : }
     413             : 
     414             : static __initdata int (*actions[])(void) = {
     415             :         [Start]         = do_start,
     416             :         [Collect]       = do_collect,
     417             :         [GotHeader]     = do_header,
     418             :         [SkipIt]        = do_skip,
     419             :         [GotName]       = do_name,
     420             :         [CopyFile]      = do_copy,
     421             :         [GotSymlink]    = do_symlink,
     422             :         [Reset]         = do_reset,
     423             : };
     424             : 
     425           4 : static long __init write_buffer(char *buf, unsigned long len)
     426             : {
     427           4 :         byte_count = len;
     428           4 :         victim = buf;
     429             : 
     430          24 :         while (!actions[state]())
     431          20 :                 ;
     432           4 :         return len - byte_count;
     433             : }
     434             : 
     435           0 : static long __init flush_buffer(void *bufv, unsigned long len)
     436             : {
     437           0 :         char *buf = (char *) bufv;
     438           0 :         long written;
     439           0 :         long origLen = len;
     440           0 :         if (message)
     441             :                 return -1;
     442           0 :         while ((written = write_buffer(buf, len)) < len && !message) {
     443           0 :                 char c = buf[written];
     444           0 :                 if (c == '0') {
     445           0 :                         buf += written;
     446           0 :                         len -= written;
     447           0 :                         state = Start;
     448           0 :                 } else if (c == 0) {
     449           0 :                         buf += written;
     450           0 :                         len -= written;
     451           0 :                         state = Reset;
     452             :                 } else
     453           0 :                         error("junk within compressed archive");
     454             :         }
     455             :         return origLen;
     456             : }
     457             : 
     458             : static unsigned long my_inptr; /* index of next byte to be processed in inbuf */
     459             : 
     460             : #include <linux/decompress/generic.h>
     461             : 
     462           1 : static char * __init unpack_to_rootfs(char *buf, unsigned long len)
     463             : {
     464           1 :         long written;
     465           1 :         decompress_fn decompress;
     466           1 :         const char *compress_name;
     467           1 :         static __initdata char msg_buf[64];
     468             : 
     469           1 :         header_buf = kmalloc(110, GFP_KERNEL);
     470           1 :         symlink_buf = kmalloc(PATH_MAX + N_ALIGN(PATH_MAX) + 1, GFP_KERNEL);
     471           1 :         name_buf = kmalloc(N_ALIGN(PATH_MAX), GFP_KERNEL);
     472             : 
     473           1 :         if (!header_buf || !symlink_buf || !name_buf)
     474           0 :                 panic_show_mem("can't allocate buffers");
     475             : 
     476           1 :         state = Start;
     477           1 :         this_header = 0;
     478           1 :         message = NULL;
     479           5 :         while (!message && len) {
     480           4 :                 loff_t saved_offset = this_header;
     481           4 :                 if (*buf == '0' && !(this_header & 3)) {
     482           4 :                         state = Start;
     483           4 :                         written = write_buffer(buf, len);
     484           4 :                         buf += written;
     485           4 :                         len -= written;
     486           4 :                         continue;
     487             :                 }
     488           0 :                 if (!*buf) {
     489           0 :                         buf++;
     490           0 :                         len--;
     491           0 :                         this_header++;
     492           0 :                         continue;
     493             :                 }
     494           0 :                 this_header = 0;
     495           0 :                 decompress = decompress_method(buf, len, &compress_name);
     496           0 :                 pr_debug("Detected %s compressed data\n", compress_name);
     497           0 :                 if (decompress) {
     498           0 :                         int res = decompress(buf, len, NULL, flush_buffer, NULL,
     499             :                                    &my_inptr, error);
     500           0 :                         if (res)
     501           0 :                                 error("decompressor failed");
     502           0 :                 } else if (compress_name) {
     503           0 :                         if (!message) {
     504           0 :                                 snprintf(msg_buf, sizeof msg_buf,
     505             :                                          "compression method %s not configured",
     506             :                                          compress_name);
     507           0 :                                 message = msg_buf;
     508             :                         }
     509             :                 } else
     510           0 :                         error("invalid magic at start of compressed archive");
     511           0 :                 if (state != Reset)
     512           0 :                         error("junk at the end of compressed archive");
     513           0 :                 this_header = saved_offset + my_inptr;
     514           0 :                 buf += my_inptr;
     515           0 :                 len -= my_inptr;
     516             :         }
     517           1 :         dir_utime();
     518           1 :         kfree(name_buf);
     519           1 :         kfree(symlink_buf);
     520           1 :         kfree(header_buf);
     521           1 :         return message;
     522             : }
     523             : 
     524             : static int __initdata do_retain_initrd;
     525             : 
     526           0 : static int __init retain_initrd_param(char *str)
     527             : {
     528           0 :         if (*str)
     529             :                 return 0;
     530           0 :         do_retain_initrd = 1;
     531           0 :         return 1;
     532             : }
     533             : __setup("retain_initrd", retain_initrd_param);
     534             : 
     535             : #ifdef CONFIG_ARCH_HAS_KEEPINITRD
     536             : static int __init keepinitrd_setup(char *__unused)
     537             : {
     538             :         do_retain_initrd = 1;
     539             :         return 1;
     540             : }
     541             : __setup("keepinitrd", keepinitrd_setup);
     542             : #endif
     543             : 
     544             : extern char __initramfs_start[];
     545             : extern unsigned long __initramfs_size;
     546             : #include <linux/initrd.h>
     547             : #include <linux/kexec.h>
     548             : 
     549           0 : void __init reserve_initrd_mem(void)
     550             : {
     551           0 :         phys_addr_t start;
     552           0 :         unsigned long size;
     553             : 
     554             :         /* Ignore the virtul address computed during device tree parsing */
     555           0 :         initrd_start = initrd_end = 0;
     556             : 
     557           0 :         if (!phys_initrd_size)
     558             :                 return;
     559             :         /*
     560             :          * Round the memory region to page boundaries as per free_initrd_mem()
     561             :          * This allows us to detect whether the pages overlapping the initrd
     562             :          * are in use, but more importantly, reserves the entire set of pages
     563             :          * as we don't want these pages allocated for other purposes.
     564             :          */
     565           0 :         start = round_down(phys_initrd_start, PAGE_SIZE);
     566           0 :         size = phys_initrd_size + (phys_initrd_start - start);
     567           0 :         size = round_up(size, PAGE_SIZE);
     568             : 
     569           0 :         if (!memblock_is_region_memory(start, size)) {
     570           0 :                 pr_err("INITRD: 0x%08llx+0x%08lx is not a memory region",
     571             :                        (u64)start, size);
     572           0 :                 goto disable;
     573             :         }
     574             : 
     575           0 :         if (memblock_is_region_reserved(start, size)) {
     576           0 :                 pr_err("INITRD: 0x%08llx+0x%08lx overlaps in-use memory region\n",
     577             :                        (u64)start, size);
     578           0 :                 goto disable;
     579             :         }
     580             : 
     581           0 :         memblock_reserve(start, size);
     582             :         /* Now convert initrd to virtual addresses */
     583           0 :         initrd_start = (unsigned long)__va(phys_initrd_start);
     584           0 :         initrd_end = initrd_start + phys_initrd_size;
     585           0 :         initrd_below_start_ok = 1;
     586             : 
     587           0 :         return;
     588           0 : disable:
     589           0 :         pr_cont(" - disabling initrd\n");
     590           0 :         initrd_start = 0;
     591           0 :         initrd_end = 0;
     592             : }
     593             : 
     594           0 : void __weak __init free_initrd_mem(unsigned long start, unsigned long end)
     595             : {
     596             : #ifdef CONFIG_ARCH_KEEP_MEMBLOCK
     597             :         unsigned long aligned_start = ALIGN_DOWN(start, PAGE_SIZE);
     598             :         unsigned long aligned_end = ALIGN(end, PAGE_SIZE);
     599             : 
     600             :         memblock_free(__pa(aligned_start), aligned_end - aligned_start);
     601             : #endif
     602             : 
     603           0 :         free_reserved_area((void *)start, (void *)end, POISON_FREE_INITMEM,
     604             :                         "initrd");
     605           0 : }
     606             : 
     607             : #ifdef CONFIG_KEXEC_CORE
     608             : static bool __init kexec_free_initrd(void)
     609             : {
     610             :         unsigned long crashk_start = (unsigned long)__va(crashk_res.start);
     611             :         unsigned long crashk_end   = (unsigned long)__va(crashk_res.end);
     612             : 
     613             :         /*
     614             :          * If the initrd region is overlapped with crashkernel reserved region,
     615             :          * free only memory that is not part of crashkernel region.
     616             :          */
     617             :         if (initrd_start >= crashk_end || initrd_end <= crashk_start)
     618             :                 return false;
     619             : 
     620             :         /*
     621             :          * Initialize initrd memory region since the kexec boot does not do.
     622             :          */
     623             :         memset((void *)initrd_start, 0, initrd_end - initrd_start);
     624             :         if (initrd_start < crashk_start)
     625             :                 free_initrd_mem(initrd_start, crashk_start);
     626             :         if (initrd_end > crashk_end)
     627             :                 free_initrd_mem(crashk_end, initrd_end);
     628             :         return true;
     629             : }
     630             : #else
     631           0 : static inline bool kexec_free_initrd(void)
     632             : {
     633           0 :         return false;
     634             : }
     635             : #endif /* CONFIG_KEXEC_CORE */
     636             : 
     637             : #ifdef CONFIG_BLK_DEV_RAM
     638             : static void __init populate_initrd_image(char *err)
     639             : {
     640             :         ssize_t written;
     641             :         struct file *file;
     642             :         loff_t pos = 0;
     643             : 
     644             :         unpack_to_rootfs(__initramfs_start, __initramfs_size);
     645             : 
     646             :         printk(KERN_INFO "rootfs image is not initramfs (%s); looks like an initrd\n",
     647             :                         err);
     648             :         file = filp_open("/initrd.image", O_WRONLY | O_CREAT, 0700);
     649             :         if (IS_ERR(file))
     650             :                 return;
     651             : 
     652             :         written = xwrite(file, (char *)initrd_start, initrd_end - initrd_start,
     653             :                         &pos);
     654             :         if (written != initrd_end - initrd_start)
     655             :                 pr_err("/initrd.image: incomplete write (%zd != %ld)\n",
     656             :                        written, initrd_end - initrd_start);
     657             :         fput(file);
     658             : }
     659             : #endif /* CONFIG_BLK_DEV_RAM */
     660             : 
     661           1 : static int __init populate_rootfs(void)
     662             : {
     663             :         /* Load the built in initramfs */
     664           1 :         char *err = unpack_to_rootfs(__initramfs_start, __initramfs_size);
     665           1 :         if (err)
     666           0 :                 panic_show_mem("%s", err); /* Failed to decompress INTERNAL initramfs */
     667             : 
     668           1 :         if (!initrd_start || IS_ENABLED(CONFIG_INITRAMFS_FORCE))
     669           1 :                 goto done;
     670             : 
     671           0 :         if (IS_ENABLED(CONFIG_BLK_DEV_RAM))
     672             :                 printk(KERN_INFO "Trying to unpack rootfs image as initramfs...\n");
     673             :         else
     674           0 :                 printk(KERN_INFO "Unpacking initramfs...\n");
     675             : 
     676           0 :         err = unpack_to_rootfs((char *)initrd_start, initrd_end - initrd_start);
     677           0 :         if (err) {
     678             : #ifdef CONFIG_BLK_DEV_RAM
     679             :                 populate_initrd_image(err);
     680             : #else
     681           0 :                 printk(KERN_EMERG "Initramfs unpacking failed: %s\n", err);
     682             : #endif
     683             :         }
     684             : 
     685           0 : done:
     686             :         /*
     687             :          * If the initrd region is overlapped with crashkernel reserved region,
     688             :          * free only memory that is not part of crashkernel region.
     689             :          */
     690           1 :         if (!do_retain_initrd && initrd_start && !kexec_free_initrd())
     691           0 :                 free_initrd_mem(initrd_start, initrd_end);
     692           1 :         initrd_start = 0;
     693           1 :         initrd_end = 0;
     694             : 
     695           1 :         flush_delayed_fput();
     696           1 :         return 0;
     697             : }
     698             : rootfs_initcall(populate_rootfs);

Generated by: LCOV version 1.14