Skip to content

Commit

Permalink
Merge branch 'PR/libmount-errmsg' of github.com:karelzak/util-linux-work
Browse files Browse the repository at this point in the history
* 'PR/libmount-errmsg' of github.com:karelzak/util-linux-work:
  libmount: (loop) detect and report lost loop nodes
  libmount: add mnt_context_sprintf_errmsg()
  libmount: add functions to use error buffer
  libmount: use regular function to save/reset syscalls status
  • Loading branch information
karelzak committed May 27, 2024
2 parents 9f15d2d + 9f94d12 commit cbfcbbf
Show file tree
Hide file tree
Showing 7 changed files with 115 additions and 50 deletions.
78 changes: 75 additions & 3 deletions libmount/src/context.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
#include "namespace.h"
#include "match.h"

#include <stdarg.h>
#include <sys/wait.h>

/**
Expand Down Expand Up @@ -314,7 +315,7 @@ int mnt_context_reset_status(struct libmnt_context *cxt)
if (!cxt)
return -EINVAL;

reset_syscall_status(cxt);
mnt_context_syscall_reset_status(cxt);

cxt->syscall_status = 1; /* means not called yet */
cxt->helper_exec_status = 1;
Expand Down Expand Up @@ -2599,8 +2600,8 @@ int mnt_context_get_syscall_errno(struct libmnt_context *cxt)
*
* The @status should be 0 on success, or negative number on error (-errno).
*
* This function should only be used if the [u]mount(2) syscall is NOT called by
* libmount code.
* This function is intended for cases where mount/umount is called externally,
* rather than by libmount.
*
* Returns: 0 or negative number in case of error.
*/
Expand All @@ -2614,6 +2615,77 @@ int mnt_context_set_syscall_status(struct libmnt_context *cxt, int status)
return 0;
}

/* Use this for syscalls called from libmount */
void mnt_context_syscall_save_status( struct libmnt_context *cxt,
const char *syscallname,
int success)
{
if (!success) {
DBG(CXT, ul_debug("syscall '%s' [failed: %m]", syscallname));
cxt->syscall_status = -errno;
cxt->syscall_name = syscallname;
} else {
DBG(CXT, ul_debug("syscall '%s' [success]", syscallname));
cxt->syscall_status = 0;
}
}

void mnt_context_syscall_reset_status(struct libmnt_context *cxt)
{
DBG(CXT, ul_debug("reset syscall status"));
cxt->syscall_status = 0;
cxt->syscall_name = NULL;

free(cxt->errmsg);
cxt->errmsg = NULL;
}

int mnt_context_set_errmsg(struct libmnt_context *cxt, const char *msg)
{
char *p = NULL;

if (msg) {
p = strdup(msg);
if (!p)
return -ENOMEM;
}

free(cxt->errmsg);
cxt->errmsg = p;

return 0;
}

int mnt_context_append_errmsg(struct libmnt_context *cxt, const char *msg)
{
if (cxt->errmsg) {
int rc = strappend(&cxt->errmsg, "; ");
if (rc)
return rc;
}

return strappend(&cxt->errmsg, msg);
}

int mnt_context_sprintf_errmsg(struct libmnt_context *cxt, const char *msg, ...)
{
int rc;
va_list ap;
char *p = NULL;

va_start(ap, msg);
rc = vasprintf(&p, msg, ap);
va_end(ap);

if (rc < 0 || !p)
return rc;

free(cxt->errmsg);
cxt->errmsg = p;

return 0;
}

/**
* mnt_context_strerror
* @cxt: context
Expand Down
16 changes: 12 additions & 4 deletions libmount/src/context_mount.c
Original file line number Diff line number Diff line change
Expand Up @@ -1433,6 +1433,11 @@ int mnt_context_get_mount_excode(
mnt_context_get_user_mflags(cxt, &uflags); /* userspace flags */

if (!mnt_context_syscall_called(cxt)) {
if (buf && cxt->errmsg) {
xstrncpy(buf, cxt->errmsg, bufsz);
return MNT_EX_USAGE;
}

/*
* libmount errors (extra library checks)
*/
Expand Down Expand Up @@ -1572,10 +1577,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);
if (buf && cxt->errmsg) {
if (cxt->syscall_name)
snprintf(buf, bufsz, _("%s system call failed: %s"),
cxt->syscall_name, cxt->errmsg);
else
xstrncpy(buf, cxt->errmsg, bufsz);

return MNT_EX_FAIL;
}

Expand Down
8 changes: 8 additions & 0 deletions libmount/src/hook_loopdev.c
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,14 @@ static int setup_loopdev(struct libmnt_context *cxt,
goto done_no_deinit;
if (mnt_opt_has_value(loopopt)) {
rc = loopcxt_set_device(&lc, mnt_opt_get_value(loopopt));
if (rc == 0 && loopcxt_is_lost(&lc)) {
DBG(LOOP, ul_debugobj(cxt, "node lost"));

dev_t devno = loopcxt_get_devno(&lc);
mnt_context_sprintf_errmsg(cxt, _("device node %s (%u:%u) is lost"),
loopcxt_get_device(&lc), major(devno), minor(devno));
rc = -EINVAL;
}
if (rc == 0)
loopdev = loopcxt_get_device(&lc);
}
Expand Down
12 changes: 4 additions & 8 deletions libmount/src/hook_mount.c
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,7 @@ 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;
mnt_context_set_errmsg(cxt, NULL);

while ((rc = read(fd, buf, sizeof(buf))) != -1) {
if (rc > 0 && buf[rc - 1] == '\n')
Expand All @@ -80,10 +79,7 @@ static void save_fd_messages(struct libmnt_context *cxt, int fd)

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);
mnt_context_append_errmsg(cxt, ((char *) buf) + 2);
}
}

Expand All @@ -92,7 +88,7 @@ static void hookset_set_syscall_status(struct libmnt_context *cxt,
{
struct libmnt_sysapi *api;

set_syscall_status(cxt, name, x);
mnt_context_syscall_save_status(cxt, name, x);

if (!x) {
api = get_sysapi(cxt);
Expand Down Expand Up @@ -819,7 +815,7 @@ static int hook_prepare(struct libmnt_context *cxt,
/* we need to recover from this error, so hook_mount_legacy.c
* can try to continue */
DBG(HOOK, ul_debugobj(hs, "failed to init new API"));
reset_syscall_status(cxt);
mnt_context_syscall_reset_status(cxt);
hookset_deinit(cxt, hs);
return 1;
}
Expand Down
11 changes: 3 additions & 8 deletions libmount/src/hook_mount_legacy.c
Original file line number Diff line number Diff line change
Expand Up @@ -76,10 +76,8 @@ 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)) {
cxt->syscall_status = -errno;
cxt->syscall_name = "mount";
}
if (mnt_context_propagation_only(cxt))
mnt_context_syscall_save_status(cxt, "mount", rc == 0);

DBG(HOOK, ul_debugobj(hs, " mount(2) failed [errno=%d %m]", errno));
rc = -MNT_ERR_APPLYFLAGS;
Expand Down Expand Up @@ -240,10 +238,7 @@ static int hook_mount(struct libmnt_context *cxt,
options : "<none>"));

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));
mnt_context_syscall_save_status(cxt, "mount", 0);
rc = -cxt->syscall_status;
return rc;
}
Expand Down
9 changes: 4 additions & 5 deletions libmount/src/hook_subdir.c
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ static int do_mount_subdir(
DBG(HOOK, ul_debug("attach subdir %s", subdir));
fd = open_tree(api->fd_tree, subdir,
OPEN_TREE_CLOEXEC | OPEN_TREE_CLONE);
set_syscall_status(cxt, "open_tree", fd >= 0);
mnt_context_syscall_save_status(cxt, "open_tree", fd >= 0);
if (fd < 0)
rc = -errno;

Expand All @@ -201,7 +201,7 @@ static int do_mount_subdir(
setns(hsd->old_ns_fd, CLONE_NEWNS);

rc = move_mount(fd, "", AT_FDCWD, target, MOVE_MOUNT_F_EMPTY_PATH);
set_syscall_status(cxt, "move_mount", rc == 0);
mnt_context_syscall_save_status(cxt, "move_mount", rc == 0);
if (rc)
rc = -errno;

Expand All @@ -223,8 +223,7 @@ static int do_mount_subdir(
/* Classic mount(2) based way */
DBG(HOOK, ul_debug("mount subdir %s to %s", src, target));
rc = mount(src, target, NULL, MS_BIND, NULL);

set_syscall_status(cxt, "mount", rc == 0);
mnt_context_syscall_save_status(cxt, "mount", rc == 0);
if (rc)
rc = -errno;
free(src);
Expand All @@ -233,7 +232,7 @@ static int do_mount_subdir(
if (!rc) {
DBG(HOOK, ul_debug("umount old root %s", root));
rc = umount(root);
set_syscall_status(cxt, "umount", rc == 0);
mnt_context_syscall_save_status(cxt, "umount", rc == 0);
if (rc)
rc = -errno;
hsd->tmp_umounted = 1;
Expand Down
31 changes: 9 additions & 22 deletions libmount/src/mountP.h
Original file line number Diff line number Diff line change
Expand Up @@ -432,7 +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 */
char *errmsg; /* library or kernel message */

struct libmnt_ns ns_orig; /* original namespace */
struct libmnt_ns ns_tgt; /* target namespace */
Expand Down Expand Up @@ -480,27 +480,6 @@ struct libmnt_context
/* Flags usable with MS_BIND|MS_REMOUNT */
#define MNT_BIND_SETTABLE (MS_NOSUID|MS_NODEV|MS_NOEXEC|MS_NOATIME|MS_NODIRATIME|MS_RELATIME|MS_RDONLY|MS_NOSYMFOLLOW)

static inline void set_syscall_status(struct libmnt_context *cxt, const char *name, int x)
{
if (!x) {
DBG(CXT, ul_debug("syscall '%s' [%m]", name));
cxt->syscall_status = -errno;
cxt->syscall_name = name;
} else {
DBG(CXT, ul_debug("syscall '%s' [success]", name));
cxt->syscall_status = 0;
}
}

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 */
extern const struct libmnt_optmap *mnt_optmap_get_entry(
Expand Down Expand Up @@ -621,6 +600,10 @@ extern int __mnt_fs_set_target_ptr(struct libmnt_fs *fs, char *tgt)
__attribute__((nonnull(1)));

/* context.c */
extern void mnt_context_syscall_save_status(struct libmnt_context *cxt,
const char *syscallname, int success);
extern void mnt_context_syscall_reset_status(struct libmnt_context *cxt);

extern struct libmnt_context *mnt_copy_context(struct libmnt_context *o);
extern int mnt_context_utab_writable(struct libmnt_context *cxt);
extern const char *mnt_context_get_writable_tabpath(struct libmnt_context *cxt);
Expand All @@ -643,6 +626,10 @@ extern int mnt_context_update_tabs(struct libmnt_context *cxt);
extern int mnt_context_umount_setopt(struct libmnt_context *cxt, int c, char *arg);
extern int mnt_context_mount_setopt(struct libmnt_context *cxt, int c, char *arg);

extern int mnt_context_set_errmsg(struct libmnt_context *cxt, const char *msg);
extern int mnt_context_append_errmsg(struct libmnt_context *cxt, const char *msg);
extern int mnt_context_sprintf_errmsg(struct libmnt_context *cxt, const char *msg, ...);

extern int mnt_context_propagation_only(struct libmnt_context *cxt)
__attribute__((nonnull));

Expand Down

0 comments on commit cbfcbbf

Please sign in to comment.