e2fsprogs: fuse2fs bugfix and new 'fakeroot' feature
cover e2fsprogs: fuse2fs bugfix and new 'fakeroot' feature
From: Nick Clark <[email protected]>
Hi all,
I wrote a couple of patches for fuse2fs (from the e2fsprogs collection). One is a minor bugfix to the displayed name in the mount command's output, and the other is a new 'fakeroot' mount option, as described below.
When building cross-compiled Linux systems (for use on routers, consumer devices, etc), it's often necessary to build rootfs filesystem images. This commit adds a new 'fakeroot' mount option that gives a user full control over the mounted filesystem, within the confines of FUSE.
When used, the new option allows treats allowed users as uid 0 for the purposes of permission checks (within the mounted filesystem). This allows the owner of a .img file to mount the file and make whatever changes they want to any files inside of the image.
If the option is left disabled at mount-time, fuse2fs acts the same as before - only root can edit "root"-owned files inside of the image. But when enabled, fuse2fs becomes a powerful tool to build/modify filesystem images.
What do you all think?
-Nick
Nicholas Clark (2):
Fuse2fs: fix 'mount' entry in some cases.
Fuse2fs: add fakeroot option.
acinclude.m4 | 47 ++++++++++++++++ configure | 134 ++++++++++++++++++++++++++++++++++++++++++++++ configure.ac | 4 ++ lib/config.h.in | 6 +++ misc/fuse2fs.1.in | 3 ++ misc/fuse2fs.c | 31 ++++++++--- 6 files changed, 217 insertions(+), 8 deletions(-)
Signature · 1 line
2.17.1
PATCH RESEND 1/2 Fuse2fs: fix 'mount' entry in some cases.
From: Nicholas Clark <[email protected]>
FUSE's parser allows command-line options to be specified before or after the device/image and mount-path. This commit changes the value of the fsname mount option to be correct even if options are specified before the target device/image.
--- misc/fuse2fs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
misc/fuse2fs.c +1 -1
@@ -3845,7 +3845,7 @@ int main(int argc, char *argv[])/* Set up default fuse parameters */ snprintf (extra_args,BUFSIZ ,"-okernel_cache,subtype=ext4,use_ino," "fsname=%s,attr_timeout=0" FUSE_PLATFORM_OPTS , - argv[1 ]); + fctx.device);if (fctx.no_default_opts ==0 )fuse_opt_add_arg (&args, extra_args);
Signature · 1 line
2.17.1
Re: [PATCH RESEND 1/2] Fuse2fs: fix 'mount' entry in some cases.
Quoted 8 lines · On Sun, Oct 14, 2018 at 09:00:24AM -0600, [email protected] wrote:
From: Nicholas Clark <[email protected]>
FUSE's parser allows command-line options to be specified before or after the device/image and mount-path. This commit changes the value of the fsname mount option to be correct even if options are specified before the target device/image.
Signed-off-by Nicholas Clark <[email protected]>
Applied (to the maint branch), thanks.
- Ted
PATCH RESEND 2/2 Fuse2fs: add fakeroot option.
In reply to [email protected]From: Nicholas Clark <[email protected]>
Add a new 'fakeroot' option to fuse2fs. When enabled, fuse2fs will will pretend to be root when checking file permssions. This allows fuse2fs to be used for building/modifying rootfs images as an unprivileged user.
As per the maintainer's request, nosuid and nodev are automatically enabled when fakeroot is selected (on platforms that support them) to help prevent accidental misuse.
--- acinclude.m4 | 47 ++++++++++++++++ configure | 134 ++++++++++++++++++++++++++++++++++++++++++++++ configure.ac | 4 ++ lib/config.h.in | 6 +++ misc/fuse2fs.1.in | 3 ++ misc/fuse2fs.c | 29 +++++++--- 6 files changed, 216 insertions(+), 7 deletions(-)
acinclude.m4 +47 -0
@@ -133,3 +133,50 @@ dnl If there was a GNU version, then set @ifGNUmake@ to the empty string, '#' ot AC_SUBST(ifGNUmake) AC_SUBST(ifNotGNUmake) ] ) + +# AX_CHECK_MOUNT_OPT: an autoconf macro to check for generic filesystem- +# agnostic 'mount' options. Written by Nicholas Clark. Looks for constants in +# sys/mount.h to predict whether the 'mount' utility will support a specific +# mounting option. +# +# This macro can be used to check for the presence of 'nodev' (or other mount +# options), which isn't uniformly implemented in the BSD family at the time of +# this writing. Tested on FreeBSD, NetBSD, OpenBSD, and Linux. +# +# Usage: +# +# AX_CHECK_MOUNT_OPT(option) +# +# Defines HAVE_MOUNT_$OPTION (in uppercase) if the option exists, and sets +# ac_cv_mount_$option (in original case) otherwise. +# +# Copyright (c) 2018 Nicholas Clark <[email protected]> +# +# Copying and distribution of this file, with or without modification, are +# permitted in any medium without royalty or attribution requirement. + +AC_DEFUN([AX_CHECK_MOUNT_OPT], [__AX_CHECK_MOUNT_OPT(m4_tolower([$1]),m4_toupper([$1]))]) +AC_DEFUN([__AX_CHECK_MOUNT_OPT], +[ + AS_IF([test "x$ac_cv_header_sys_mount_h" = x], + [AC_CHECK_HEADERS([sys/mount.h])]) + AS_IF([test "x$ac_cv_header_sys_mount_h" = xno], + [AC_MSG_FAILURE([error: sys/mount.h not present on your system!])]) + AS_ECHO_N("checking for mount '$1' option... ") + AC_TRY_COMPILE( + [#include <sys/mount.h>], + [void *temp = (void *)(MS_$2); (void) temp;], + [AC_DEFINE(HAVE_MOUNT_$2, 1, [Define to 1 if mount supports $1.]) + AS_VAR_SET(ac_cv_mount_$1, yes) + AS_ECHO("yes")], + [AC_TRY_COMPILE( + [#include <sys/mount.h>], + [void *temp = (void *)(MNT_$2); (void) temp;], + [AC_DEFINE(HAVE_MOUNT_$2, 1, [Define to 1 if mount supports $1.]) + AS_VAR_SET(ac_cv_mount_$1, yes) + AS_ECHO("yes")], + [AS_VAR_SET(ac_cv_mount_$1, no) + AS_ECHO("no")] + )] + ) +])
configure +134 -0
140 lines not on this page · raw message
configure.ac +4 -0
@@ -1315,6 +1315,10 @@ linux*) ;; esac dnl +dnl Check the available mount options +dnl +AX_CHECK_MOUNT_OPT(nosuid) +AX_CHECK_MOUNT_OPT(nodev) dnl Enable LTO for all packages dnl AC_ARG_ENABLE([lto],
lib/config.h.in +6 -0
@@ -313,6 +313,12 @@ /* Define to 1 if you have the <mntent.h> header file. */ #undef HAVE_MNTENT_H +/* Define to 1 if mount supports nodev. */ +#undef HAVE_MOUNT_NODEV + +/* Define to 1 if mount supports nosuid. */ +#undef HAVE_MOUNT_NOSUID + /* Define to 1 if you have the `msync' function. */ #undef HAVE_MSYNC
misc/fuse2fs.1.in +3 -0
@@ -42,6 +42,9 @@ dump core on error \fB-o\fR minixdf minix-style df .TP +\fB-o\fR fakeroot +pretend to be root for permission checks +.TP \fB-o\fR no_default_opts do not include default fuse options .TP
misc/fuse2fs.c +22 -7
@@ -322,6 +322,7 @@ struct fuse2fs {int no_default_opts;int panic_on_error;int minixdf; +int fakeroot;int alloc_all_blocks;FILE *err_fp;unsigned int next_generation;
@@ -630,6 +631,7 @@ static int fs_writeable(ext2_filsys fs)static int check_inum_access (ext2_filsys fs,ext2_ino_t ino,mode_t mask) {struct fuse_context *ctxt =fuse_get_context (); +struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;struct ext2_inode inode;mode_t perms;errcode_t err;
@@ -659,7 +661,7 @@ static int check_inum_access(ext2_filsys fs, ext2_ino_t ino, mode_t mask)return -EACCES ;/* Figure out what root's allowed to do */ -if (ctxt->uid ==0 ) { +if (ff->fakeroot || ctxt->uid ==0 ) {/* Non-file access always ok */ if (!LINUX_S_ISREG (inode.i_mode))return 0 ;
@@ -1905,7 +1907,7 @@ static int op_chmod(const char *path, mode_t mode) goto out; } -if (ctxt->uid !=0 && ctxt->uid != inode.i_uid) { +if (!ff->fakeroot && ctxt->uid !=0 && ctxt->uid != inode.i_uid) { ret = -EPERM ; goto out; }
@@ -1915,7 +1917,7 @@ static int op_chmod(const char *path, mode_t mode)* of the user's groups, but FUSE only tells us about the primary * group. */ -if (ctxt->uid !=0 && ctxt->gid != inode.i_gid) +if (!ff->fakeroot && ctxt->uid !=0 && ctxt->gid != inode.i_gid) mode &= ~S_ISGID ; inode.i_mode &= ~0xFFF ;
@@ -1968,7 +1970,7 @@ static int op_chown(const char *path, uid_t owner, gid_t group)/* FUSE seems to feed us ~0 to mean "don't change" */ if (owner != (uid_t ) ~0 ) {/* Only root gets to change UID. */ -if (ctxt->uid !=0 && +if (!ff->fakeroot && ctxt->uid !=0 && !(inode.i_uid == ctxt->uid && owner == ctxt->uid)) { ret = -EPERM ; goto out;
@@ -1978,7 +1980,7 @@ static int op_chown(const char *path, uid_t owner, gid_t group)if (group != (gid_t ) ~0 ) {/* Only root or the owner get to change GID. */ -if (ctxt->uid !=0 && inode.i_uid != ctxt->uid) { +if (!ff->fakeroot && ctxt->uid !=0 && inode.i_uid != ctxt->uid) { ret = -EPERM ; goto out; }
@@ -3120,6 +3122,7 @@ static int ioctl_setflags(ext2_filsys fs, struct fuse2fs_file_handle *fh,int ret;__u32 flags = *(__u32 *)data;struct fuse_context *ctxt =fuse_get_context (); +struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;FUSE2FS_CHECK_MAGIC (fs, fh,FUSE2FS_FILE_MAGIC );dbg_printf ("%s: ino=%d\n" , __func__, fh->ino);
@@ -3129,7 +3132,7 @@ static int ioctl_setflags(ext2_filsys fs, struct fuse2fs_file_handle *fh,if (err)return translate_error (fs, fh->ino, err); -if (ctxt->uid !=0 && inode.i_uid != ctxt->uid) +if (!ff->fakeroot && ctxt->uid !=0 && inode.i_uid != ctxt->uid)return -EPERM ;if ((inode.i_flags ^ flags) & ~FUSE2FS_MODIFIABLE_IFLAGS )
@@ -3176,6 +3179,7 @@ static int ioctl_setversion(ext2_filsys fs, struct fuse2fs_file_handle *fh,int ret;__u32 generation = *(__u32 *)data;struct fuse_context *ctxt =fuse_get_context (); +struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;FUSE2FS_CHECK_MAGIC (fs, fh,FUSE2FS_FILE_MAGIC );dbg_printf ("%s: ino=%d\n" , __func__, fh->ino);
@@ -3185,7 +3189,7 @@ static int ioctl_setversion(ext2_filsys fs, struct fuse2fs_file_handle *fh,if (err)return translate_error (fs, fh->ino, err); -if (ctxt->uid !=0 && inode.i_uid != ctxt->uid) +if (!ff->fakeroot && ctxt->uid !=0 && inode.i_uid != ctxt->uid)return -EPERM ; inode.i_generation = generation;
@@ -3655,6 +3659,7 @@ static struct fuse_opt fuse2fs_opts[] = {FUSE2FS_OPT ("ro" , ro,1 ),FUSE2FS_OPT ("errors=panic" , panic_on_error,1 ),FUSE2FS_OPT ("minixdf" , minixdf,1 ), +FUSE2FS_OPT ("fakeroot" , fakeroot,1 ),FUSE2FS_OPT ("fuse2fs_debug" , debug,1 ), FUSE2FS_OPT("no_default_opts", no_default_opts, 1),
@@ -3693,6 +3698,7 @@ static int fuse2fs_opt_proc(void *data, const char *arg," -o ro read-only mount\n" " -o errors=panic dump core on error\n" " -o minixdf minix-style df\n" +" -o fakeroot pretend to be root for permission checks\n" " -o no_default_opts do not include default fuse options\n" " -o fuse2fs_debug enable fuse2fs debugging\n" "\n",
@@ -3849,6 +3855,15 @@ int main(int argc, char *argv[])if (fctx.no_default_opts ==0 )fuse_opt_add_arg (&args, extra_args); +if (fctx.fakeroot) { +#ifdef HAVE_MOUNT_NODEV +fuse_opt_add_arg (&args,"-onodev" ); +#endif +#ifdef HAVE_MOUNT_NOSUID +fuse_opt_add_arg (&args,"-onosuid" ); +#endif + } +if (fctx.debug) {int i;
Signature · 1 line
2.17.1
Theodore Y. Ts'o
AppliedRe: [PATCH RESEND 2/2] Fuse2fs: add fakeroot option.
Quoted 7 lines · On Sun, Oct 14, 2018 at 09:00:25AM -0600, [email protected] wrote:
From: Nicholas Clark <[email protected]>
Add a new 'fakeroot' option to fuse2fs. When enabled, fuse2fs will will pretend to be root when checking file permssions. This allows fuse2fs to be used for building/modifying rootfs images as an unprivileged user.
Quoted 5 lines
As per the maintainer's request, nosuid and nodev are automatically enabled when fakeroot is selected (on platforms that support them) to help prevent accidental misuse.
Signed-off-by Nicholas Clark <[email protected]>
Applied, thanks!
- Ted