Unpack, modify and pack initrd as a user

I’ve got a problem with rebuilding the initrd image as a user. Firstly, when I try to “unpack” the original initrd image:

cpio -idm < initrd-base 
cpio: dev/tty8: Cannot mknod: Operation not permitted
cpio: dev/tty3: Cannot mknod: Operation not permitted
cpio: dev/zero: Cannot mknod: Operation not permitted
cpio: dev/loop0: Cannot mknod: Operation not permitted
cpio: dev/loop4: Cannot mknod: Operation not permitted
cpio: dev/loop7: Cannot mknod: Operation not permitted
cpio: dev/loop5: Cannot mknod: Operation not permitted
cpio: dev/loop2: Cannot mknod: Operation not permitted
cpio: dev/tty9: Cannot mknod: Operation not permitted
cpio: dev/tty4: Cannot mknod: Operation not permitted
cpio: dev/null: Cannot mknod: Operation not permitted
cpio: dev/loop6: Cannot mknod: Operation not permitted
cpio: dev/loop1: Cannot mknod: Operation not permitted
cpio: dev/console: Cannot mknod: Operation not permitted
cpio: dev/loop3: Cannot mknod: Operation not permitted
cpio: dev/tty1: Cannot mknod: Operation not permitted
133336 blocks

How can I get rid of these warnings?

Secondly – I’m not sure how file ownership will be handled. After I unpack it it seems that everything belongs to the current user.

How will initrd look after repacking it? I prefer to not alter the standard access rights.

Asked By: Dejwi


Those errors are there because your user has not the permission to create nodes. Only root can create nodes other than fifos and sockets (see mknod documentation under EPERM)

When you repack again the initrd, those special file wouldn’t be in there.
To repack the initrd there is an option called --owner that can be used to set the owner for all files. BUT, only root can use this option.

The only way I see is, to copy the initrd to another system, where you have root access and do the operations there. After that copy it back.

Answered By: chaos

Since you’re using cpio, you’re actually making an initramfs, not an initrd. An initrd would be stored as a filesystem image, not as a cpio archive. Initrd and initramfs have similar roles in the Linux boot process, to provide some files that are available before the true root filesystem (and that are used to mount the true root filesystem); they are handled in rather different ways under the hood but this isn’t relevant here. Initrd is older and somewhat deprecated in favor of initramfs. Many build systems still use the file name initrd even though they’ve switched the content to an initramfs.

Root images usually contain device nodes and files that need specific permissions. The cpio command can only generate an archive based on files that exist in your filesystem, and you need root permission to create devices nodes or files belonging to root. The kernel source contains a tool usr/gen_init_cpio and a wrapper script scripts/gen_initramfs_list.sh that are provided precisely to generate an initramfs without having to create all the files on the filesystem, and thus to generate an initramfs without requiring any privilege. These programs are documented in the kernel source tree, in Documentation/filesystems/ramfs-rootfs-initramfs.txt and Documentation/early-userspace/README.

The normal way to build an initramfs is described in ramfs-rootfs-initramfs.txt in the section “Populating initramfs”. You write a text file containing a list of paths to create with their type (directory, regular, device node, etc.), permissions and other attributes. For regular files, you give the name of a local file with the content. Then run usr/gen_init_cpio on this file. When building a kernel, if you set the CONFIG_INITRAMFS_SOURCE option to a file name, an initramfs is generated by calling usr/gen_init_cpio on that file.

If you already have an initramfs image and want to modify it, use cpio -tv to list it, and reconstruct the ramfs description file based on that. If possible, get the initramfs description file from the original kernel source, to save you work. Extract the content of the regular files only in some directory. Then modify the regular files and the ramfs description file, and finally run usr/gen_init_cpio to generate a new initramfs.

Thank for your answers, they were useful, but I figure out my own solution.

Recreating the initrd image can be done with fakeroot-ng (and probably with fakeroot also).

The base idea of the tools it to wrap all system calls, so all programs executed within fakeroot environment thinks, they are run by a root.

I call part of my script within fakeroot environment – unpack initramfs, perform all changes and pack it again.

All privelages are set correctly, root is the owner of all files.

The fakeroot-ng is available at:

Answered By: Dejwi

If you need to unpack initramfs and repack it later you can use -s/-i options to store fakeroot environment in a file.

$ mkdir initrd
$ cd initrd
$ zcat ../initrd.gz | fakeroot -s ../initrd.fakeroot cpio -i

Now you have file with fakeroot environment containing something like that:


Look at your files:

$ stat dev/console
   File: 'dev/console'
   Size: 0               Blocks: 0          IO Block: 4096   regular empty file
 Device: fe05h/65029d    Inode: 20326045    Links: 1

I didn’t dig deeper but it seems you can create nesessary nodes just by

$ touch <file>
$ stat <file>
$ # put info about file into your fakeroot environment with your own params

To buils initramfs you just run

$ find | fakeroot -i ../initrd.fakeroot cpio -o -H newc | gzip -c > ../initrd.gz
Answered By: Woland
Categories: Answers Tags: , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.