util-linux/SOURCES/0067-libmount-add-missing-utab-options-after-helper-call.patch

189 lines
5.5 KiB
Diff

From bc5aaf0e8b9105e5abd6aa6ff28294a39f5822bc Mon Sep 17 00:00:00 2001
From: Karel Zak <kzak@redhat.com>
Date: Wed, 29 Nov 2023 12:37:52 +0100
Subject: libmount: add missing utab options after helper call
libmount is able to add missing entry to /run/mount/utab after
external /sbin/mouht.<type> helper execution. This is not enough, it's
possible that the helper write proper entry to the utab, but there is
missing some options expected by libmount (usually because the options
are irrelevant fro the helper.
Reproducer:
Create a stupid mount.foo which writes x-foo=123 to utab:
# echo -e '#!/bin/bash\n\n/bin/mount -i "$1" "$2" -o x-foo=123' > /sbin/mount.foo
# chmod +x /sbin/mount.foo
Run mount which needs to write x-bar=BAR options to utab and executes
the helper (due to "-t foo", /dev/sdc1 is ext4):
# mount -t foo /dev/sdc1 /mnt/test -o x-bar=BAR
old mount:
# cat /run/mount/utab
ID=121 SRC=/dev/sdc1 TARGET=/mnt/test ROOT=/ OPTS=x-foo=123
fixed mount:
# cat /run/mount/utab
ID=121 SRC=/dev/sdc1 TARGET=/mnt/test ROOT=/ OPTS=x-foo=123,x-bar=BAR
Addresses: https://issues.redhat.com/browse/RHEL-14612
Upstream: http://github.com/util-linux/util-linux/commit/477401f0de404aafbc7630f70c2f8b1d670e32f8
Fixes: https://github.com/util-linux/util-linux/issues/2554
Signed-off-by: Karel Zak <kzak@redhat.com>
---
libmount/src/tab_update.c | 81 +++++++++++++++++++++++++++++++++++----
1 file changed, 74 insertions(+), 7 deletions(-)
diff --git a/libmount/src/tab_update.c b/libmount/src/tab_update.c
index b68553515..f60f522ce 100644
--- a/libmount/src/tab_update.c
+++ b/libmount/src/tab_update.c
@@ -37,7 +37,9 @@ struct libmnt_update {
char *filename;
unsigned long mountflags;
int userspace_only;
- int ready;
+
+ unsigned int ready : 1,
+ missing_options : 1;
struct libmnt_table *mountinfo;
};
@@ -183,7 +185,7 @@ int mnt_update_set_fs(struct libmnt_update *upd, unsigned long mountflags,
mnt_unref_fs(upd->fs);
free(upd->target);
- upd->ready = FALSE;
+ upd->ready = 0;
upd->fs = NULL;
upd->target = NULL;
upd->mountflags = 0;
@@ -218,7 +220,7 @@ int mnt_update_set_fs(struct libmnt_update *upd, unsigned long mountflags,
DBG(UPDATE, ul_debugobj(upd, "ready"));
- upd->ready = TRUE;
+ upd->ready = 1;
return 0;
}
@@ -778,6 +780,7 @@ static int update_modify_target(struct libmnt_update *upd, struct libmnt_lock *l
return rc;
}
+/* replaces option in the table entry by new options from @udp */
static int update_modify_options(struct libmnt_update *upd, struct libmnt_lock *lc)
{
struct libmnt_table *tb = NULL;
@@ -820,6 +823,58 @@ static int update_modify_options(struct libmnt_update *upd, struct libmnt_lock *
return rc;
}
+/* add user options missing in the table entry by new options from @udp */
+static int update_add_options(struct libmnt_update *upd, struct libmnt_lock *lc)
+{
+ struct libmnt_table *tb = NULL;
+ int rc = 0;
+ struct libmnt_fs *fs;
+
+ assert(upd);
+ assert(upd->fs);
+
+ if (!upd->fs->user_optstr)
+ return 0;
+
+ DBG(UPDATE, ul_debugobj(upd, "%s: add options", upd->filename));
+
+ fs = upd->fs;
+
+ if (lc)
+ rc = mnt_lock_file(lc);
+ if (rc)
+ return -MNT_ERR_LOCK;
+
+ tb = __mnt_new_table_from_file(upd->filename, MNT_FMT_UTAB, 1);
+ if (tb) {
+ struct libmnt_fs *cur = mnt_table_find_target(tb,
+ mnt_fs_get_target(fs),
+ MNT_ITER_BACKWARD);
+ if (cur) {
+ char *u = NULL;
+
+ rc = mnt_optstr_get_missing(cur->user_optstr, upd->fs->user_optstr, &u);
+ if (!rc && u) {
+ DBG(UPDATE, ul_debugobj(upd, " add missing: %s", u));
+ rc = mnt_optstr_append_option(&cur->user_optstr, u, NULL);
+ }
+ if (!rc && u)
+ rc = update_table(upd, tb);
+
+ if (rc == 1) /* nothing is missing */
+ rc = 0;
+ } else
+ rc = add_file_entry(tb, upd); /* not found, add new */
+ }
+
+ if (lc)
+ mnt_unlock_file(lc);
+
+ mnt_unref_table(tb);
+ return rc;
+
+}
+
/**
* mnt_update_table:
* @upd: update
@@ -862,10 +917,12 @@ int mnt_update_table(struct libmnt_update *upd, struct libmnt_lock *lc)
rc = update_modify_target(upd, lc); /* move */
else if (upd->mountflags & MS_REMOUNT)
rc = update_modify_options(upd, lc); /* remount */
+ else if (upd->fs && upd->missing_options)
+ rc = update_add_options(upd, lc); /* mount by externel helper */
else if (upd->fs)
- rc = update_add_entry(upd, lc); /* mount */
+ rc = update_add_entry(upd, lc); /* mount */
- upd->ready = FALSE;
+ upd->ready = 1;
DBG(UPDATE, ul_debugobj(upd, "%s: update tab: done [rc=%d]",
upd->filename, rc));
if (lc != lc0)
@@ -908,16 +965,26 @@ int mnt_update_already_done(struct libmnt_update *upd, struct libmnt_lock *lc)
if (upd->fs) {
/* mount */
+ struct libmnt_fs *fs;
const char *tgt = mnt_fs_get_target(upd->fs);
const char *src = mnt_fs_get_bindsrc(upd->fs) ?
mnt_fs_get_bindsrc(upd->fs) :
mnt_fs_get_source(upd->fs);
- if (mnt_table_find_pair(tb, src, tgt, MNT_ITER_BACKWARD)) {
+ fs = mnt_table_find_pair(tb, src, tgt, MNT_ITER_BACKWARD);
+ if (fs) {
DBG(UPDATE, ul_debugobj(upd, "%s: found %s %s",
upd->filename, src, tgt));
+
+ /* Check if utab entry (probably writen by /sbin/mount.<type>
+ * helper) contains all options expected by this update */
+ if (mnt_optstr_get_missing(fs->user_optstr, upd->fs->user_optstr, NULL) == 0) {
+ upd->missing_options = 1;
+ DBG(UPDATE, ul_debugobj(upd, " missing options detected"));
+ }
+ } else
rc = 1;
- }
+
} else if (upd->target) {
/* umount */
if (!mnt_table_find_target(tb, upd->target, MNT_ITER_BACKWARD)) {
--
2.43.0