2

I'm doing a project that needs to generate a vm image file which will then be used as qemu bootable disk image. Previously, our product is like an modified linux system and is made into a USB installation drive and then boot and install into an bare metal machine. But now we want to get rid of the hardware and run it in virtual machines, that's why we need an image file.

Instead of using the existing USB drive to install the system in qemu then shutdown the vm and get the image, we were asked to make an out-of-box image file directly, and skip all the booting and installing on real machine or virtual machine but still get a installed image, so that we can just deliver this image and people can load this image as a ready-to-use virtual machine image.

But during all the procedure, I can NOT use any command that requires root privilege! Don't ask why, there's a whole bunch of restrictions to our project, I just can't use root privilege, no sudo, no su, just anything only a regular user can do....

The part I already achieved is using the latest version of mke2fs -d command to populate a tree of folders and files into different partitions of this image file like this

suppose after the image is booted, we have these folder structure

$ ls /
$ bin dev boot  home lib32   mnt  proc  run srv  tmp var  boot  data   etc  lib lib64  opt  root  sbin  sys  usr  

some of the folders are mounted by different partitions

extract a single partition from image

dd if=image of=partitionN skip=offset_of_partition_N count=size_of_partition_N bs=512 conv=sparse

populate a folder into the partition

mke2fs -d root_dir/etc partitionN

put the partition back into image

dd if=partitionN of=image seek=offset_of_partition_N count=size_of_partition_N bs=512 conv=sparse,notrunc

We have the first partition in the image as the boot partition, which contains the 'boot' folder and will be mounted under /boot once it is booted.

And this boot partition is an EFI compatible partition(which actually seems to be a FAT32 format), since our project needs it to be this way.

BUT After get all partitions successfully populated into the image, I can not find a way to install grub for this bootable image. And that's the most damn important step that needed to make this image bootable.

All solutions I found on the web suggest loop mount the image's boot partition, which I can not do because without root privilege I can't loop mount the image.

So does any one have any idea how to do this?

I tried to understand how grub write raw values into mbr, and how to find stage1 and stage2 from the values inside mbr, and how to figure out the sector list at the end of stage2's first sector, but that's so crazy and I eventually failed to get this trick work.

Community
  • 1
  • 1
skywalker
  • 45
  • 3
  • SInce it's an insane and arbitraty requirement, why not sidestep it? You do know that `sudo` isn't magic? It's just a convenient way of executing something with root permission. Installing grub doesn't require `sudo` but it does require the root permission. E.g. just run `su` and run `mount` from that root shell. – MSalters Jun 27 '16 at 10:40
  • 1
    Thanks for the reply. I'm sorry the word 'sudo' caused the misunderstanding, I should've used the phrase 'root privilege'. So what I meant was how to achieve the goal without any privileges, just using a regular user. Does this mean it is impossible for a regular user without root permission? – skywalker Jun 28 '16 at 01:35
  • tried this? https://www.normalesup.org/~george/comp/live_iso_usb/ – Ctc Jun 28 '16 at 01:47
  • @skywalker: I don't see a way around it. I'd just hand the project back to the higher-ups and say that the restrictions prevent you from finishing it. Don't use computers to try to solve bugs in the company. – MSalters Jun 28 '16 at 06:58
  • This question appears to be off-topic for Stack Overflow as defined in the [help]. It may be better suited to the [unix.se] Stack Exchange site. – Toby Speight Nov 02 '17 at 18:23
  • The only part that you need is the first 1MB of data that holds the pre-partition gap that grub stores the stage 1.5 (core.img) inside. You can do this once in an environment with root, and then dd the first 1MB in and out of the images that you are building in the environment without privileges. – Andrew May 29 '18 at 13:58
  • @MSalters this doesn't seem insane to me, actually it is a pretty standard requirement when the build runs on a build-server without root privilege. I am not 100% sure, but I think it can be achieved with yocto's wic tool. – Étienne Mar 22 '20 at 13:07
  • No qemu? Why? It solves the problem instantly. – Joshua Jul 13 '22 at 23:19
  • @Joshua Yep, no qemu because the build process doesn't have that privilege. But since I've already left that company, I will never consider this if I have a clean start for a project and an option for container. – skywalker Jul 15 '22 at 14:31
  • @skywalker: I can run qemu with no privileges. It costs a 10x slowdown but can boot kernel and run grub2 just fine. – Joshua Jul 15 '22 at 19:53
  • @Joshua But how do you go inside such VM over console (no ssh) then apply a series of disk operations along with installation scripts inside VM using an automatically invoked build script outside of qemu? – skywalker Jul 17 '22 at 17:06
  • @skywalker: `cpio` based initrd with /linuxrc that mounts the image, runs grub2, unmounts the image, and shuts down. No keyboard activity required. `qemu-system-x86_64 -kernel bzImage -hda rootdisk.img -initrd initrd.cpio.gz` – Joshua Jul 17 '22 at 21:04

1 Answers1

0

Disclaimer: if facing this problem myself I would attack the problem directly by making a grub2-mbr-image installer myself. It's a true attack on the problem and would make a better answer, and more on topic for this site; however it's more hours of research than I'm willing to put into it for a stackverflow answer.

There's an extra trick here. We can get success/error code back by using a virtual floppy disk. There's no need to ship the floppy disk driver. You can build it as a module and include it only in the cpio image.

If we are willing to forgo the kqemu component and pay the 10x slowdown price, we can start qemu with -hda image.img, -kernel bzImage and -initrd initrd.cpio.gz and it will boot that. You need an X server (which you can provide with Xvnc) but no privileges a normal user doesn't have. Assuming / and /boot are the same, /linuxrc looks like this:

#!/bin/sh
insmod /lib/modules/kernel/floppy.ko
mount /dev/hda1 -t ext2 /mnt
PATH=/bin:/usr/bin:/usr/sbin:/sbin chroot /mnt grub2-install
RESULT=$?
umount /dev/hda1
mount /dev/fda -t fat /mnt
echo -n $RESULT > /mnt/errorcode
umount /mnt
poweroff

And you can get your error code back with mcopy to read the floppy disk image.

If qemu is not available, you can build a i586 compatible kernel and use dosbox-x instead and start the kernel using loadlin.exe. This actually works. If you try it with modern stuff it just dies because stuff demands i686 now; but you can build the grub install tool itself targeting i586 and just use an old kernel to boot to do the install. https://www.vogons.org/viewtopic.php?t=53531

Joshua
  • 40,822
  • 8
  • 72
  • 132