From: Karel Zak Date: Mon, 26 Feb 2024 11:44:10 +0000 (+0100) Subject: libmount: report kernel message from new API X-Git-Tag: v2.42-start~512^2 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=9da5644e414cdc318f0311260dabc6035c85b58e;p=thirdparty%2Futil-linux.git libmount: report kernel message from new API This is a very minimalistic implementation for v2.40 designed to print error messages from the kernel. It exclusively displays errors, and the patch does not introduce any new library interface for this purpose. Instead, it simply replaces hardcoded messages within libmount with kernel messages. It's worth noting that the final implementation will necessitate per-hook error handling in libmount and likely a new library API to access other types of messages (warnings, notices, etc.). Signed-off-by: Karel Zak --- diff --git a/libmount/src/context.c b/libmount/src/context.c index d9310c453..6a1b99578 100644 --- a/libmount/src/context.c +++ b/libmount/src/context.c @@ -314,6 +314,8 @@ int mnt_context_reset_status(struct libmnt_context *cxt) if (!cxt) return -EINVAL; + reset_syscall_status(cxt); + cxt->syscall_status = 1; /* means not called yet */ cxt->helper_exec_status = 1; cxt->helper_status = 0; diff --git a/libmount/src/context_mount.c b/libmount/src/context_mount.c index b8302f9fc..478a9fde4 100644 --- a/libmount/src/context_mount.c +++ b/libmount/src/context_mount.c @@ -1571,6 +1571,13 @@ int mnt_context_get_mount_excode( */ syserr = mnt_context_get_syscall_errno(cxt); + if (buf && cxt->syscall_errmsg) { + snprintf(buf, bufsz, _("%s system call failed: %s"), + cxt->syscall_name ? : "mount", + cxt->syscall_errmsg); + return MNT_EX_FAIL; + } + switch(syserr) { case EPERM: if (!buf) diff --git a/libmount/src/hook_mount.c b/libmount/src/hook_mount.c index 961cc8745..92438966c 100644 --- a/libmount/src/hook_mount.c +++ b/libmount/src/hook_mount.c @@ -65,19 +65,29 @@ static void close_sysapi_fds(struct libmnt_sysapi *api) api->fd_tree = api->fd_fs = -1; } -static void debug_fs_fd_messages(int fd) +static void save_fd_messages(struct libmnt_context *cxt, int fd) { uint8_t buf[BUFSIZ]; int rc; + free(cxt->syscall_errmsg); + cxt->syscall_errmsg = NULL; + while ((rc = read(fd, buf, sizeof(buf))) != -1) { if (rc > 0 && buf[rc - 1] == '\n') buf[rc - 1] = '\0'; - DBG(CXT, ul_debug("message from kernel: %*s", rc, buf)); + DBG(CXT, ul_debug("message from kernel: \"%*s\"", rc, buf)); + + if (rc < 3 || strncmp((char *) buf, "e ", 2) != 0) + continue; + if (cxt->syscall_errmsg) + strappend(&cxt->syscall_errmsg, "; "); + + strappend(&cxt->syscall_errmsg, ((char *) buf) + 2); } } -static void set_syscall_status_cxt_log(struct libmnt_context *cxt, +static void hookset_set_syscall_status(struct libmnt_context *cxt, const char *name, int x) { struct libmnt_sysapi *api; @@ -86,13 +96,11 @@ static void set_syscall_status_cxt_log(struct libmnt_context *cxt, if (!x) { api = get_sysapi(cxt); - if (api) - debug_fs_fd_messages(api->fd_fs); + if (api && api->fd_fs >= 0) + save_fd_messages(cxt, api->fd_fs); } } -#define set_syscall_status set_syscall_status_cxt_log - /* * This hookset uses 'struct libmnt_sysapi' (mountP.h) as hookset data. */ @@ -176,7 +184,7 @@ static inline int fsconfig_set_value( } else rc = fsconfig(fd, FSCONFIG_SET_FLAG, name, NULL, 0); - set_syscall_status(cxt, "fsconfig", rc == 0); + hookset_set_syscall_status(cxt, "fsconfig", rc == 0); return rc; } @@ -241,7 +249,7 @@ static int open_fs_configuration_context(struct libmnt_context *cxt, DBG(HOOK, ul_debug(" fsopen(%s)", type)); api->fd_fs = fsopen(type, FSOPEN_CLOEXEC); - set_syscall_status(cxt, "fsopen", api->fd_fs >= 0); + hookset_set_syscall_status(cxt, "fsopen", api->fd_fs >= 0); if (api->fd_fs < 0) return -errno; api->is_new_fs = 1; @@ -280,7 +288,7 @@ static int open_mount_tree(struct libmnt_context *cxt, const char *path, unsigne oflg & OPEN_TREE_CLONE ? " clone" : "", oflg & AT_RECURSIVE ? " recursive" : "")); fd = open_tree(AT_FDCWD, path, oflg); - set_syscall_status(cxt, "open_tree", fd >= 0); + hookset_set_syscall_status(cxt, "open_tree", fd >= 0); return fd; } @@ -320,19 +328,19 @@ static int hook_create_mount(struct libmnt_context *cxt, 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); + hookset_set_syscall_status(cxt, "fsconfig", rc == 0); if (!rc) rc = configure_superblock(cxt, hs, api->fd_fs, 0); 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); + hookset_set_syscall_status(cxt, "fsconfig", rc == 0); } if (!rc) { api->fd_tree = fsmount(api->fd_fs, FSMOUNT_CLOEXEC, 0); - set_syscall_status(cxt, "fsmount", api->fd_tree >= 0); + hookset_set_syscall_status(cxt, "fsmount", api->fd_tree >= 0); if (api->fd_tree < 0) rc = -errno; } @@ -381,7 +389,7 @@ static int hook_reconfigure_mount(struct libmnt_context *cxt, if (api->fd_fs < 0) { api->fd_fs = fspick(api->fd_tree, "", FSPICK_EMPTY_PATH | FSPICK_NO_AUTOMOUNT); - set_syscall_status(cxt, "fspick", api->fd_fs >= 0); + hookset_set_syscall_status(cxt, "fspick", api->fd_fs >= 0); if (api->fd_fs < 0) return -errno; } @@ -390,7 +398,7 @@ static int hook_reconfigure_mount(struct libmnt_context *cxt, if (!rc) { DBG(HOOK, ul_debugobj(hs, "re-configurate FS")); rc = fsconfig(api->fd_fs, FSCONFIG_CMD_RECONFIGURE, NULL, NULL, 0); - set_syscall_status(cxt, "fsconfig", rc == 0); + hookset_set_syscall_status(cxt, "fsconfig", rc == 0); } DBG(HOOK, ul_debugobj(hs, "reconf FS done [rc=%d]", rc)); @@ -428,7 +436,7 @@ static int set_vfsflags(struct libmnt_context *cxt, errno = 0; rc = mount_setattr(api->fd_tree, "", callflags, &attr, sizeof(attr)); - set_syscall_status(cxt, "mount_setattr", rc == 0); + hookset_set_syscall_status(cxt, "mount_setattr", rc == 0); if (rc && errno == EINVAL) return -MNT_ERR_APPLYFLAGS; @@ -520,7 +528,7 @@ static int hook_set_propagation(struct libmnt_context *cxt, (uint64_t) attr.propagation)); rc = mount_setattr(api->fd_tree, "", flgs, &attr, sizeof(attr)); - set_syscall_status(cxt, "mount_setattr", rc == 0); + hookset_set_syscall_status(cxt, "mount_setattr", rc == 0); if (rc && errno == EINVAL) return -MNT_ERR_APPLYFLAGS; @@ -562,7 +570,7 @@ static int hook_attach_target(struct libmnt_context *cxt, } rc = move_mount(api->fd_tree, "", AT_FDCWD, target, MOVE_MOUNT_F_EMPTY_PATH); - set_syscall_status(cxt, "move_mount", rc == 0); + hookset_set_syscall_status(cxt, "move_mount", rc == 0); return rc == 0 ? 0 : -errno; } @@ -648,7 +656,7 @@ static int init_sysapi(struct libmnt_context *cxt, else if (!fsopen_is_supported()) { errno = ENOSYS; rc = -errno; - set_syscall_status(cxt, "fsopen", rc == 0); + hookset_set_syscall_status(cxt, "fsopen", rc == 0); } if (rc < 0) goto fail; diff --git a/libmount/src/mountP.h b/libmount/src/mountP.h index 9bca4ea77..458aa1a00 100644 --- a/libmount/src/mountP.h +++ b/libmount/src/mountP.h @@ -432,6 +432,7 @@ struct libmnt_context int syscall_status; /* 1: not called yet, 0: success, <0: -errno */ const char *syscall_name; /* failed syscall name */ + char *syscall_errmsg; /* message from kernel */ struct libmnt_ns ns_orig; /* original namespace */ struct libmnt_ns ns_tgt; /* target namespace */ @@ -496,6 +497,9 @@ static inline void reset_syscall_status(struct libmnt_context *cxt) DBG(CXT, ul_debug("reset syscall status")); cxt->syscall_status = 0; cxt->syscall_name = NULL; + + free(cxt->syscall_errmsg); + cxt->syscall_errmsg = NULL; } /* optmap.c */