]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
libmount: expose exec errors
authorKarel Zak <kzak@redhat.com>
Mon, 27 May 2024 12:04:31 +0000 (14:04 +0200)
committerKarel Zak <kzak@redhat.com>
Tue, 28 May 2024 08:14:38 +0000 (10:14 +0200)
* Introduce special exit status 126 to inform about failed execl of
  the /sbin/[u]mount.<type> helpers.

* Introduce MNT_ERR_EXEC as an API return code to inform about failed
  execl() calls.

* Add mount and umount messages for failed execl() calls.

* Add EXIT STATUS section to umount man page.

Addresses: https://github.com/util-linux/util-linux/pull/3063
Signed-off-by: Karel Zak <kzak@redhat.com>
libmount/src/context_mount.c
libmount/src/context_umount.c
libmount/src/libmount.h.in
sys-utils/mount.8.adoc
sys-utils/umount.8.adoc

index 53918c3fcae0e8208a31e6f979dd595887b84d80..6762877330a7f01e6c010bb7b1cce0712f6bedb9 100644 (file)
@@ -460,7 +460,7 @@ static int exec_helper(struct libmnt_context *cxt)
                                                        i, args[i]));
                DBG_FLUSH;
                execv(cxt->helper, (char * const *) args);
-               _exit(EXIT_FAILURE);
+               _exit(MNT_EX_EXEC);
        }
        default:
        {
@@ -469,14 +469,20 @@ static int exec_helper(struct libmnt_context *cxt)
                if (waitpid(pid, &st, 0) == (pid_t) -1) {
                        cxt->helper_status = -1;
                        rc = -errno;
+                       DBG(CXT, ul_debugobj(cxt, "waitpid failed [errno=%d]", -rc));
                } else {
                        cxt->helper_status = WIFEXITED(st) ? WEXITSTATUS(st) : -1;
                        cxt->helper_exec_status = rc = 0;
-               }
-               DBG(CXT, ul_debugobj(cxt, "%s executed [status=%d, rc=%d%s]",
+
+                       if (cxt->helper_status == MNT_EX_EXEC) {
+                               rc = -MNT_ERR_EXEC;
+                               DBG(CXT, ul_debugobj(cxt, "%s exec failed", cxt->helper));
+                       }
+
+                       DBG(CXT, ul_debugobj(cxt, "%s forked [status=%d, rc=%d]",
                                cxt->helper,
-                               cxt->helper_status, rc,
-                               rc ? " waitpid failed" : ""));
+                               cxt->helper_status, rc));
+               }
                break;
        }
 
@@ -1414,8 +1420,16 @@ int mnt_context_get_mount_excode(
                /*
                 * /sbin/mount.<type> called, return status
                 */
-               if (rc == -MNT_ERR_APPLYFLAGS && buf)
-                       snprintf(buf, bufsz, _("WARNING: failed to apply propagation flags"));
+               if (buf) {
+                       switch (rc) {
+                       case -MNT_ERR_APPLYFLAGS:
+                               snprintf(buf, bufsz, _("WARNING: failed to apply propagation flags"));
+                               break;
+                       case -MNT_ERR_EXEC:
+                               snprintf(buf, bufsz, _("failed to execute %s"), cxt->helper);
+                               break;
+                       }
+               }
 
                return mnt_context_get_helper_status(cxt);
        }
index bf70ed2ee762fc5d067d67106e61245e0340d66d..adfaf7fa6b3bd568147b99f23d4822d0e33325c1 100644 (file)
@@ -741,7 +741,7 @@ static int exec_helper(struct libmnt_context *cxt)
                                                        i, args[i]));
                DBG_FLUSH;
                execv(cxt->helper, (char * const *) args);
-               _exit(EXIT_FAILURE);
+               _exit(MNT_EX_EXEC);
        }
        default:
        {
@@ -750,14 +750,20 @@ static int exec_helper(struct libmnt_context *cxt)
                if (waitpid(pid, &st, 0) == (pid_t) -1) {
                        cxt->helper_status = -1;
                        rc = -errno;
+                       DBG(CXT, ul_debugobj(cxt, "waitpid failed [errno=%d]", -rc));
                } else {
                        cxt->helper_status = WIFEXITED(st) ? WEXITSTATUS(st) : -1;
                        cxt->helper_exec_status = rc = 0;
-               }
-               DBG(CXT, ul_debugobj(cxt, "%s executed [status=%d, rc=%d%s]",
+
+                       if (cxt->helper_status == MNT_EX_EXEC) {
+                               rc = -MNT_ERR_EXEC;
+                               DBG(CXT, ul_debugobj(cxt, "%s exec failed", cxt->helper));
+                       }
+
+                       DBG(CXT, ul_debugobj(cxt, "%s forked [status=%d, rc=%d]",
                                cxt->helper,
-                               cxt->helper_status, rc,
-                               rc ? " waitpid failed" : ""));
+                               cxt->helper_status, rc));
+               }
                break;
        }
 
@@ -1238,11 +1244,15 @@ int mnt_context_get_umount_excode(
                        char *buf,
                        size_t bufsz)
 {
-       if (mnt_context_helper_executed(cxt))
+       if (mnt_context_helper_executed(cxt)) {
                /*
                 * /sbin/umount.<type> called, return status
                 */
+               if (rc == -MNT_ERR_EXEC && buf)
+                       snprintf(buf, bufsz, _("failed to execute %s"), cxt->helper);
+
                return mnt_context_get_helper_status(cxt);
+       }
 
        if (rc == 0 && mnt_context_get_status(cxt) == 1)
                /*
index d893c26493bb8230d410c33bab51f518f5c1e546..0a2d821996efd175af25d98cd1abe39d9e630674 100644 (file)
@@ -241,6 +241,13 @@ enum {
  * filesystem mounted, but subsequent X-mount.idmap= failed
  */
 #define MNT_ERR_IDMAP    5013
+/**
+ * MNT_ERR_EXEC:
+ *
+ * failed to execute external program
+ */
+#define MNT_ERR_EXEC   5014
+
 
 
 /*
@@ -305,6 +312,12 @@ enum {
  */
 #define MNT_EX_SOMEOK  64
 
+/**
+ * MNT_EX_EXEC:
+ *
+ * [u]mount(8) exit code: external program execution failed
+ */
+#define MNT_EX_EXEC    126
 
 
 #ifndef __GNUC_PREREQ
index 43628adce58c945a1e4558782a7cd9071eecb5aa..4c9bef6f4f0f870886c019e721d6938a81261151 100644 (file)
@@ -1612,6 +1612,9 @@ some mount succeeded
 +
 The command *mount -a* returns 0 (all succeeded), 32 (all failed), or 64 (some failed, some succeeded).
 
+*126*::
+failed to execute external /sbin/mount.<type> mount helper (since util-linux v2.41)
+
 == EXTERNAL HELPERS
 
 The syntax of external mount helpers is:
@@ -1622,6 +1625,8 @@ where the _suffix_ is the filesystem type and the *-sfnvoN* options have the sam
 
 The command *mount* does not pass the mount options *unbindable*, *runbindable*, *private*, *rprivate*, *slave*, *rslave*, *shared*, *rshared*, *auto*, *noauto*, *comment*, *x-**, *loop*, *offset* and *sizelimit* to the mount.<suffix> helpers. All other options are used in a comma-separated list as an argument to the *-o* option.
 
+The exit status value of the helper is returned as the exit status of *mount*(8). The value 126 is sed if the mount helper program is found, but the execl() failed.
+
 == ENVIRONMENT
 
 *LIBMOUNT_FORCE_MOUNT2*={always|never|auto}::
index 47011316b9871929ad12bb6afeed198727c207f3..f9b96e1ff84f2f3f292fc13213f498417aded846 100644 (file)
@@ -127,6 +127,39 @@ The *umount* command will automatically detach loop device previously initialize
 
 In this case the device is initialized with "autoclear" flag (see *losetup*(8) output for more details), otherwise it's necessary to use the option *--detach-loop* or call *losetup -d* _device_. The autoclear feature is supported since Linux 2.6.25.
 
+== EXIT STATUS
+
+*umount* has the following exit status values (the bits can be ORed):
+
+*0*::
+success
+
+*1*::
+incorrect invocation or permissions
+
+*2*::
+system error (out of memory, cannot fork, no more loop devices)
+
+*4*::
+internal *mount* bug
+
+*8*::
+user interrupt
+
+*16*::
+problems writing or locking _/etc/mtab_
+
+*32*::
+mount failure
+
+*64*::
+some umount succeeded
++
+The command *umount -a* returns 0 (all succeeded), 32 (all failed), or 64 (some failed, some succeeded).
+
+*126*::
+failed to execute external /sbin/umount.<type> mount helper (since util-linux v2.41)
+
 == EXTERNAL HELPERS
 
 The syntax of external unmount helpers is:
@@ -147,6 +180,8 @@ A **helper=**__type__ marker in the _mtab_ file will redirect all unmount reques
 
 Note that _/etc/mtab_ is currently deprecated and *helper=* and other userspace mount options are maintained by *libmount*.
 
+The exit status value of the helper is returned as the exit status of *umount*(8). The value 126 is used if the mount helper program is found, but the execl() failed.
+
 == ENVIRONMENT
 
 *LIBMOUNT_FSTAB*=<path>::