13

I'd like to create a filesystem image as a non-root user, the problem I'm facing is that the way I'm currently doing it, it needs a mount and as a non-root can't do a mount.

This is what I'm now doing:

#!/bin/sh

IMG="app.ext4"
LBL="PIHU_APP"
MNT="/mnt/PIHU_APP"
APP="/home/buildroot/board/arctura/PIHU_APP/application"

#64MB:
dd if=/dev/zero of=$IMG bs=4096 count=16384

mkfs.ext4 $IMG
e2label $IMG $LBL

mkdir -p $MNT
mount -o loop $IMG $MNT
cp -r $APP $MNT
sync
umount $MNT

I have full root access, so I can setup/prepare anything, but the script will be executed from a non-root account.

However, I have a feeling there may be a better way that might not even need mounting, but I'm not sure..

4
  • you may need to allow this user to mount from sudoers method ... or if your distribution as a mount group assign that user in that group to allow him to mount without sudo // another approch is to make iso file from your source directory & copy it with dd or other method to the disk image your are creating ... depending of end-use of it
    – francois P
    Feb 13, 2018 at 21:15
  • fusermount might interest you Feb 13, 2018 at 21:16
  • I’m sure I used losetup as an unprivileged user, and after attaching it, I just made partitions with cfdisk as normal. Can’t remember which groups I was a member of, but wasn’t in staff. Try losetup
    – user2497
    Feb 13, 2018 at 21:28
  • @GerardH.Pille.. Description in the man page started out hopeful. Man page failed to explain me how to use it.
    – svenema
    Feb 14, 2018 at 18:40

5 Answers 5

12

mke2fs -d minimal runnable example without sudo

mke2fs is part of the e2fsprogs package. It is written by the famous Linux kernel filesystem developer Theodore Ts'o who is at Google as of 2018, and the source upstream is under kernel.org at: https://git.kernel.org/pub/scm/fs/ext2/e2fsprogs Therefore, that repository can be considered a reference userland implementation of ext file system operations:

#!/usr/bin/env bash
set -eu

root_dir=root
img_file=img.ext2

# Create a test directory to convert to ext2.
mkdir -p "$root_dir"
echo asdf > "${root_dir}/qwer"

# Create a 32M ext2 without sudo.
# If 32M is not enough for the contents of the directory,
# it will fail.
rm -f "$img_file"
mke2fs \
  -L '' \
  -N 0 \
  -O ^64bit \
  -d "$root_dir" \
  -m 5 \
  -r 1 \
  -t ext2 \
  "$img_file" \
  32M \
;

# Test the ext2 by mounting it with sudo.
# sudo is only used for testing.
mountpoint=mnt
mkdir -p "$mountpoint"
sudo mount "$img_file" "$mountpoint"
sudo ls -l "$mountpoint"
sudo cmp "${mountpoint}/qwer" "${root_dir}/qwer"
sudo umount "$mountpoint"

GitHub upstream.

The key option is -d, which selects which directory to use for the image , and it is a relatively new addition to v1.43 in commit 0d4deba22e2aa95ad958b44972dc933fd0ebbc59

Therefore it works on Ubuntu 18.04 out of the box, which has e2fsprogs 1.44.1-1, but not Ubuntu 16.04, which is at 1.42.13.

However, we can do just like Buildroot and compile it from source easily on Ubuntu 16.04 with:

git clone git://git.kernel.org/pub/scm/fs/ext2/e2fsprogs.git
cd e2fsprogs
git checkout v1.44.4
./configure
make -j`nproc`
./misc/mke2fs -h

If mke2fs fails with:

__populate_fs: Operation not supported while setting xattrs for "qwer"
mke2fs: Operation not supported while populating file system

when add the option:

-E no_copy_xattrs

This is required for example when the root directory is in NFS or tmpfs instead of extX as those file systems don't seem to have extended properties.

mke2fs is often symlinked to mkfs.extX, and man mke2fs says that if you use call if with such symlink then -t is implied.

How I found this out and how to solve any future problems: Buildroot generates ext2 images without sudo as shown here, so I just ran the build with V=1 and extracted the commands from the image generation part that comes right at the end. Good old copy paste has never failed me.

TODO: describe how to solve the following problems:

Multiple partitions in one image file

See this: https://stackoverflow.com/questions/10949169/how-to-create-a-multi-partition-sd-image-without-root-privileges/52850819#52850819

1
  • 2
    For creating root-owned files it seems you can use the root_owner[=uid:gid] extended option (-E), although I couldn't see how to get more fine-grained control (e.g. multiple users).
    – Keeely
    Mar 11, 2019 at 0:26
7

Does it have to be ext4?

If alternatives are possible, you could try your luck with

  • mksquashfs, produces a read-only compressed filesystem from userspace
  • mkisofs, produces a read-only filesystem commonly used for optical media
  • cpio, tar, ... archives that need to be extracted first

Otherwise, to make ext4 in userspace a reality, you have to

  • go crazy with debugfs
  • boot a kernel in a userspace vm
  • find another pure userspace utility that knows to handle ext4 images

Regarding debugfs, most filesystems don't even have such utilities, you lucked out.

User session:

$ truncate -s 64M app.ext4
$ /sbin/mkfs.ext4 app.ext4
Creating filesystem with 65536 1k blocks and 16384 inodes
$ /sbin/debugfs -w app.ext4
debugfs:  mkdir this_is_crazy
debugfs:  cd this_is_crazy
debugfs:  write /proc/config.gz config.gz
Allocated inode: 13

Root session: (just to check if it worked)

# mount -o loop app.ext4 loop/
# cd loop/
# ls
lost+found  this_is_crazy
# md5sum this_is_crazy/config.gz /proc/config.gz 
7b414ad844272a9e3c31931037fe0495  this_is_crazy/config.gz
7b414ad844272a9e3c31931037fe0495  /proc/config.gz

So, it's possible and it works.

However, the most practical option should still be to use root in some fashion anyway.

2
  • Doesn't have to be ext4, ext2 or ext3 are OK too. But like you said, this isn't very practical ;-)
    – svenema
    Feb 17, 2018 at 11:00
  • 1
    mke2fs form e2fsprogs, to which debugfs also belongs, now has the -d option, which does exactly what the OP asked, including for ext4: unix.stackexchange.com/a/475484/32558 Oct 15, 2018 at 18:51
2

sudo is made for exactly this type of problem, you need to give the user permission to run the mount command in the /etc/sudoers file

then in your script you can prepend the mount command with sudo:

sudo mount -o loop $IMG $MNT

You can configure the rule so that it does not require a password

3
  • Note that giving any user the right to run mount under sudo pretty much allows that user to own the entire machine. Feb 14, 2018 at 0:50
  • yes, so this would be my last resort option
    – svenema
    Feb 14, 2018 at 18:19
  • sudo allows you to restrict which commands (and arguments) the user can execute. More information here superuser.com/questions/735172/… Feb 15, 2018 at 14:19
2

You can add it to fstab with the user option, so that it's mountable by a user.

/path/to/app.ext4 /mount/point ext4 loop,user,noauto 0 0

Then your user can create the file and just run:

mount /mount/point
0

virt-make-fs command can meet all your requirements

sudo yum install -y /usr/bin/virt-make-fs
virt-make-fs -s 64M -t ext4 $APP $IMG --label=$LBL

see also: https://libguestfs.org/virt-make-fs.1.html

1
  • What does this do? Please edit and explain your code. Mar 11, 2022 at 11:35

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .