From 77bc38ced48a4e098e18546e456029731ea0588e Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Thu, 16 Feb 2023 13:44:24 +0100 Subject: [PATCH] libmount: add fsconfig() btrfs workaround The new kernel mount API is not properly implemented in all FS drivers. See strace output: fsconfig(3, FSCONFIG_SET_STRING, "source", "/dev/sda", 0) = 0 fsconfig(3, FSCONFIG_SET_STRING, "context", "system_u:object_r:root_t:s0", 0) = 0 fsconfig(3, FSCONFIG_CMD_CREATE, NULL, NULL, 0) = -1 EINVAL (Invalid argument) Reported-by: Shinichiro Kawasaki Signed-off-by: Karel Zak --- libmount/src/context.c | 2 ++ libmount/src/context_mount.c | 3 +++ libmount/src/hook_mount.c | 22 ++++++++++++++++++++-- libmount/src/mountP.h | 1 + 4 files changed, 26 insertions(+), 2 deletions(-) diff --git a/libmount/src/context.c b/libmount/src/context.c index 972853b3fe..8db6b69500 100644 --- a/libmount/src/context.c +++ b/libmount/src/context.c @@ -165,6 +165,7 @@ int mnt_reset_context(struct libmnt_context *cxt) cxt->mountdata = NULL; cxt->flags = MNT_FL_DEFAULT; cxt->noautofs = 1; + cxt->has_selinux_opt = 0; cxt->map_linux = mnt_get_builtin_optmap(MNT_LINUX_MAP); cxt->map_userspace = mnt_get_builtin_optmap(MNT_USERSPACE_MAP); @@ -288,6 +289,7 @@ struct libmnt_context *mnt_copy_context(struct libmnt_context *o) n->table_fltrcb_data = o->table_fltrcb_data; n->noautofs = o->noautofs; + n->has_selinux_opt = o->has_selinux_opt; return n; failed: diff --git a/libmount/src/context_mount.c b/libmount/src/context_mount.c index d81741ea5c..7491ec205b 100644 --- a/libmount/src/context_mount.c +++ b/libmount/src/context_mount.c @@ -169,6 +169,9 @@ static int fix_optstr(struct libmnt_context *cxt) rc = mnt_opt_set_quoted_value(opt, raw); if (raw) freecon(raw); + + /* temporary for broken fsconfig() syscall */ + cxt->has_selinux_opt = 1; } if (rc) goto done; diff --git a/libmount/src/hook_mount.c b/libmount/src/hook_mount.c index 09a1f3f325..c60c3513b5 100644 --- a/libmount/src/hook_mount.c +++ b/libmount/src/hook_mount.c @@ -120,7 +120,7 @@ static int configure_superblock(struct libmnt_context *cxt, struct libmnt_opt *opt; int rc; - DBG(HOOK, ul_debugobj(hs, " configure FS")); + DBG(HOOK, ul_debugobj(hs, " config FS")); ol = mnt_context_get_optlist(cxt); if (!ol) @@ -150,6 +150,7 @@ static int configure_superblock(struct libmnt_context *cxt, return -errno; } + DBG(HOOK, ul_debugobj(hs, " config done [rc=0]")); return 0; } @@ -231,7 +232,7 @@ static int hook_create_mount(struct libmnt_context *cxt, if (!src) return -EINVAL; - DBG(HOOK, ul_debugobj(hs, "create FS instance")); + DBG(HOOK, ul_debugobj(hs, "init FS")); rc = fsconfig(api->fd_fs, FSCONFIG_SET_STRING, "source", src, 0); set_syscall_status(cxt, "fsconfig", rc == 0); @@ -239,6 +240,7 @@ static int hook_create_mount(struct libmnt_context *cxt, if (!rc) rc = configure_superblock(cxt, hs, api->fd_fs); if (!rc) { + DBG(HOOK, ul_debugobj(hs, "create FS")); rc = fsconfig(api->fd_fs, FSCONFIG_CMD_CREATE, NULL, NULL, 0); set_syscall_status(cxt, "fsconfig", rc == 0); } @@ -551,6 +553,22 @@ static int hook_prepare(struct libmnt_context *cxt, assert(cxt); assert(hs == &hookset_mount); + /* + * The current kernel btrfs driver does not completely implement + * fsconfig() as it does not work with selinux stuff. + * + * Don't use the new mount API in this situation. Let's hope this issue + * is temporary. + */ + { + const char *type = mnt_fs_get_fstype(cxt->fs); + + if (type && strcmp(type, "btrfs") == 0 && cxt->has_selinux_opt) { + DBG(HOOK, ul_debugobj(hs, "don't use new API (btrfs issue)")); + return 0; + } + } + DBG(HOOK, ul_debugobj(hs, "prepare mount")); ol = mnt_context_get_optlist(cxt); diff --git a/libmount/src/mountP.h b/libmount/src/mountP.h index 0d341c65a6..80015f94c3 100644 --- a/libmount/src/mountP.h +++ b/libmount/src/mountP.h @@ -427,6 +427,7 @@ struct libmnt_context unsigned int enabled_textdomain : 1; /* bindtextdomain() called */ unsigned int noautofs : 1; /* ignore autofs mounts */ + unsigned int has_selinux_opt : 1; /* temporary for broken fsconfig() syscall */ struct list_head hooksets_datas; /* global hooksets data */ struct list_head hooksets_hooks; /* global hooksets data */ -- 2.47.2