From: Karel Zak Date: Wed, 21 Sep 2022 09:39:13 +0000 (+0200) Subject: libmount: (mount) improve syscalls status handling X-Git-Tag: v2.39-rc1~258 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=11afc49b49d51c534317cafd96ace66ca6845cf6;p=thirdparty%2Futil-linux.git libmount: (mount) improve syscalls status handling The new kernel API is composed from more syscalls, but libmount originally assumes one syscall and one place where we need to remember return value of the syscall. It seems the best will be to set the status after each mount related syscall call (fsopen(), move_mount(), ...) until we reach error or end of mount process. For better error messages the last failed mount related syscall name will be recorded in cxt->syscall_name. Signed-off-by: Karel Zak --- diff --git a/libmount/src/context_mount.c b/libmount/src/context_mount.c index 907cb65711..15e2b61448 100644 --- a/libmount/src/context_mount.c +++ b/libmount/src/context_mount.c @@ -864,7 +864,6 @@ int mnt_context_do_mount(struct libmnt_context *cxt) assert(cxt); assert(cxt->fs); assert(cxt->helper_exec_status == 1); - assert(cxt->syscall_status == 1); assert((cxt->flags & MNT_FL_MOUNTFLAGS_MERGED)); assert((cxt->flags & MNT_FL_PREPARED)); assert((cxt->action == MNT_ACT_MOUNT)); @@ -1029,7 +1028,6 @@ int mnt_context_mount(struct libmnt_context *cxt) assert(cxt); assert(cxt->fs); assert(cxt->helper_exec_status == 1); - assert(cxt->syscall_status == 1); ns_old = mnt_context_switch_target_ns(cxt); if (!ns_old) @@ -1579,7 +1577,7 @@ int mnt_context_get_mount_excode( } /* - * mount(2) errors + * mount(2) and other mount related syscalls errors */ syserr = mnt_context_get_syscall_errno(cxt); diff --git a/libmount/src/hook_mount.c b/libmount/src/hook_mount.c index 4c60d267d4..ebc23f880e 100644 --- a/libmount/src/hook_mount.c +++ b/libmount/src/hook_mount.c @@ -47,6 +47,15 @@ #include +#define set_syscall_status(_cxt, _name, _x) __extension__ ({ \ + if (!(_x)) { \ + (_cxt)->syscall_status = -errno; \ + (_cxt)->syscall_name = (_name); \ + } else \ + (_cxt)->syscall_status = 0; \ + }) + + /* * This hookset uses 'struct libmnt_sysapi' (mountP.h) as hookset data. */ @@ -57,6 +66,7 @@ static void free_hookset_data( struct libmnt_context *cxt, if (!api) return; + if (api->fd_fs >= 0) close(api->fd_fs); if (api->fd_tree >= 0) @@ -111,6 +121,7 @@ static int set_vfs_flags(int fd, struct libmnt_context *cxt, int recursive) struct mount_attr attr = { .attr_clr = 0 }; unsigned int callflags = AT_EMPTY_PATH; uint64_t mask = 0; + int rc; ol= mnt_context_get_optlist(cxt); if (!ol) @@ -122,12 +133,10 @@ static int set_vfs_flags(int fd, struct libmnt_context *cxt, int recursive) callflags |= AT_RECURSIVE; DBG(HOOK, ul_debug(" mount_setattr(set=0x%" PRIx64")", mask)); - if (mount_setattr(fd, "", callflags, &attr, sizeof(attr))) { - cxt->syscall_status = -errno; - return -errno; - } + rc = mount_setattr(fd, "", callflags, &attr, sizeof(attr)); + set_syscall_status(cxt, "move_setattr", rc == 0); - return 0; + return rc == 0 ? 0 : -errno; } static int is_recursive_bind(struct libmnt_context *cxt) @@ -146,6 +155,7 @@ static int hook_attach_target(struct libmnt_context *cxt, { struct libmnt_sysapi *api; const char *target; + int rc; DBG(HOOK, ul_debugobj(hs, "attach")); @@ -158,12 +168,11 @@ static int hook_attach_target(struct libmnt_context *cxt, return -EINVAL; DBG(HOOK, ul_debugobj(hs, " move_mount(to=%s)", target)); - if (move_mount(api->fd_tree, "", AT_FDCWD, target, MOVE_MOUNT_F_EMPTY_PATH)) { - cxt->syscall_status = -errno; - return -errno; - } - return 0; + rc = move_mount(api->fd_tree, "", AT_FDCWD, target, MOVE_MOUNT_F_EMPTY_PATH); + set_syscall_status(cxt, "move_mount", rc == 0); + + return rc == 0 ? 0 : -errno; } static int hook_bind_setflags(struct libmnt_context *cxt, @@ -296,10 +305,10 @@ static int hook_prepare(struct libmnt_context *cxt, DBG(HOOK, ul_debugobj(hs, "fsopen(%s)", type)); api->fd_fs = fsopen(type, FSOPEN_CLOEXEC); - if (api->fd_fs < 0) { - cxt->syscall_status = -errno; + set_syscall_status(cxt, "fsopen", api->fd_fs >= 0); + + if (api->fd_fs < 0) goto nothing; - } } if (mnt_context_is_fake(cxt)) @@ -313,10 +322,10 @@ static int hook_prepare(struct libmnt_context *cxt, DBG(HOOK, ul_debugobj(hs, "open_tree(path=%s, flags=0x%lx)", tree_path, open_flags)); api->fd_tree = open_tree(AT_FDCWD, tree_path, open_flags); - if (api->fd_tree <= 0) { - cxt->syscall_status = -errno; + set_syscall_status(cxt, "open_tree", api->fd_tree >= 0); + + if (api->fd_tree <= 0) goto nothing; - } } return mnt_context_append_hook(cxt, hs, next_stage, NULL, next_hook); diff --git a/libmount/src/hook_mount_legacy.c b/libmount/src/hook_mount_legacy.c index a3b4b4347f..77603e5909 100644 --- a/libmount/src/hook_mount_legacy.c +++ b/libmount/src/hook_mount_legacy.c @@ -82,8 +82,10 @@ static int hook_propagation(struct libmnt_context *cxt, if (rc) { /* Update global syscall status if only this function called */ - if (mnt_context_propagation_only(cxt)) + if (mnt_context_propagation_only(cxt)) { cxt->syscall_status = -errno; + cxt->syscall_name = "mount"; + } DBG(HOOK, ul_debugobj(hs, " mount(2) failed [errno=%d %m]", errno)); rc = -MNT_ERR_APPLYFLAGS; @@ -256,6 +258,7 @@ static int hook_mount(struct libmnt_context *cxt, if (mount(src, target, type, flags, options)) { cxt->syscall_status = -errno; + cxt->syscall_name = "mount"; DBG(HOOK, ul_debugobj(hs, " mount(2) failed [errno=%d %m]", -cxt->syscall_status)); rc = -cxt->syscall_status; diff --git a/libmount/src/hooks.c b/libmount/src/hooks.c index 7ceff838eb..c467d420ba 100644 --- a/libmount/src/hooks.c +++ b/libmount/src/hooks.c @@ -312,6 +312,7 @@ int mnt_context_call_hooks(struct libmnt_context *cxt, int stage) } done: - DBG(CXT, ul_debugobj(cxt, "<--- DONE-STAGE %s [rc=%d]", stagenames[stage], rc)); + DBG(CXT, ul_debugobj(cxt, "<--- DONE-STAGE %s [rc=%d status=%d]", + stagenames[stage], rc, cxt->syscall_status)); return rc; } diff --git a/libmount/src/mountP.h b/libmount/src/mountP.h index ed3ef9845f..54b12f42ae 100644 --- a/libmount/src/mountP.h +++ b/libmount/src/mountP.h @@ -416,6 +416,7 @@ struct libmnt_context pid_t pid; /* 0=parent; PID=child */ int syscall_status; /* 1: not called yet, 0: success, <0: -errno */ + const char *syscall_name; /* failed syscall name */ struct libmnt_ns ns_orig; /* original namespace */ struct libmnt_ns ns_tgt; /* target namespace */