]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
libmount: (mount) improve syscalls status handling
authorKarel Zak <kzak@redhat.com>
Wed, 21 Sep 2022 09:39:13 +0000 (11:39 +0200)
committerKarel Zak <kzak@redhat.com>
Tue, 3 Jan 2023 11:58:42 +0000 (12:58 +0100)
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 <kzak@redhat.com>
libmount/src/context_mount.c
libmount/src/hook_mount.c
libmount/src/hook_mount_legacy.c
libmount/src/hooks.c
libmount/src/mountP.h

index 907cb657119d2b145fba7a3a5cadae9f9b53a901..15e2b61448dabbe45a086cc14b1794c9fbca7a41 100644 (file)
@@ -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);
 
index 4c60d267d47626c343e1b672be7973f4581aaa6a..ebc23f880eb734046218979d46adcc3c66d99d27 100644 (file)
 
 #include <inttypes.h>
 
+#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);
index a3b4b4347f5b7314e1b3caf69a23b8a74e9cc237..77603e5909a09a87c802e3df8afceeadb977bdb6 100644 (file)
@@ -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;
index 7ceff838ebc285d239b4cdc5ed94f2871b72796a..c467d420ba91998bca3e01805bca5fb1d6bc7ea9 100644 (file)
@@ -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;
 }
index ed3ef9845f292e1104653175a85a1820f46ab47b..54b12f42ae54b3d99c23b9c1c13e8160b8bd29ee 100644 (file)
@@ -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 */