import CS util-linux-2.37.4-18.el9

This commit is contained in:
eabdullin 2024-03-28 11:58:38 +00:00
parent ab7442d252
commit 50bb1600d4
22 changed files with 2372 additions and 1 deletions

View File

@ -0,0 +1,29 @@
From 57405630f51d256c87ecfb7271b4a297bb931d6e Mon Sep 17 00:00:00 2001
From: Karel Zak <kzak@redhat.com>
Date: Mon, 26 Jun 2023 11:56:23 +0200
Subject: logger: initialize socket credentials contol union
Addresses: https://issues.redhat.com/browse/RHEL-16048
Upstream: http://github.com/util-linux/util-linux/commit/3a4d70419c97f64f60c0eda4720e64d17b3b071
Addresses: https://github.com/util-linux/util-linux/issues/2336
Signed-off-by: Karel Zak <kzak@redhat.com>
---
misc-utils/logger.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/misc-utils/logger.c b/misc-utils/logger.c
index 43284caeb..cdce019d5 100644
--- a/misc-utils/logger.c
+++ b/misc-utils/logger.c
@@ -470,7 +470,7 @@ static void write_output(struct logger_ctl *ctl, const char *const msg)
union {
struct cmsghdr cmh;
char control[CMSG_SPACE(sizeof(struct ucred))];
- } cbuf;
+ } cbuf = { .control = { 0 } };
#endif
/* 4) add extra \n to make sure message is terminated */
--
2.43.0

View File

@ -0,0 +1,101 @@
From 735d815603ac1f8575bddf92d37eb60fcd6d0766 Mon Sep 17 00:00:00 2001
From: Karel Zak <kzak@redhat.com>
Date: Tue, 1 Nov 2022 10:30:06 +0100
Subject: logger: always update header when read from stdin
The current code updates the header only when the priority has been
changed. It's incorrect because wanted is a valid header or each entry
(don't forget that logger for stdin use-case is used in pipe to log
long-time running processes).
This patch also fixes the initial timestamp; it was originally generated
on logger startup, it now generates the header on the first message.
$ (sleep 2; date; sleep 2; date; sleep 2; date) | logger --stderr --no-act
old:
<13>Nov 1 10:42:14 kzak: Tue Nov 1 10:42:16 AM CET 2022
<13>Nov 1 10:42:14 kzak: Tue Nov 1 10:42:18 AM CET 2022
<13>Nov 1 10:42:14 kzak: Tue Nov 1 10:42:20 AM CET 2022
new:
<13>Nov 1 10:19:02 kzak: Tue Nov 1 10:19:02 AM CET 2022
<13>Nov 1 10:19:04 kzak: Tue Nov 1 10:19:04 AM CET 2022
<13>Nov 1 10:19:06 kzak: Tue Nov 1 10:19:06 AM CET 2022
Addresses: https://issues.redhat.com/browse/RHEL-21257
Upstream: http://github.com/util-linux/util-linux/commit/96ccdc00e1fcf1684f9734a189baf90e00ff0c9a
Fixes: https://github.com/util-linux/util-linux/issues/1866
Signed-off-by: Karel Zak <kzak@redhat.com>
---
misc-utils/logger.c | 19 +++++--------------
1 file changed, 5 insertions(+), 14 deletions(-)
diff --git a/misc-utils/logger.c b/misc-utils/logger.c
index cdce019d5..53ff03ff6 100644
--- a/misc-utils/logger.c
+++ b/misc-utils/logger.c
@@ -920,8 +920,6 @@ static void logger_open(struct logger_ctl *ctl)
ctl->tag = xgetlogin();
if (!ctl->tag)
ctl->tag = "<someone>";
-
- generate_syslog_header(ctl);
}
/* re-open; usually after failed connection */
@@ -971,11 +969,8 @@ static void logger_stdin(struct logger_ctl *ctl)
{
/* note: we re-generate the syslog header for each log message to
* update header timestamps and to reflect possible priority changes.
- * The initial header is generated by logger_open().
*/
- int has_header = 1;
int default_priority = ctl->pri;
- int last_pri = default_priority;
char *buf = xmalloc(ctl->max_message_size + 2 + 2);
int pri;
int c;
@@ -1002,10 +997,6 @@ static void logger_stdin(struct logger_ctl *ctl)
} else
ctl->pri = default_priority;
- if (ctl->pri != last_pri) {
- generate_syslog_header(ctl);
- last_pri = ctl->pri;
- }
if (c != EOF && c != '\n')
c = getchar();
}
@@ -1017,10 +1008,8 @@ static void logger_stdin(struct logger_ctl *ctl)
buf[i] = '\0';
if (i > 0 || !ctl->skip_empty_lines) {
- if (!has_header)
- generate_syslog_header(ctl);
+ generate_syslog_header(ctl);
write_output(ctl, buf);
- has_header = 0;
}
if (c == '\n') /* discard line terminator */
@@ -1296,12 +1285,14 @@ int main(int argc, char **argv)
abort();
}
logger_open(&ctl);
- if (0 < argc)
+ if (0 < argc) {
+ generate_syslog_header(&ctl);
logger_command_line(&ctl, argv);
- else
+ } else
/* Note. --file <arg> reopens stdin making the below
* function to be used for file inputs. */
logger_stdin(&ctl);
+
logger_close(&ctl);
return EXIT_SUCCESS;
}
--
2.43.0

View File

@ -0,0 +1,32 @@
From f7b0194f9858d0248399ada65e77540f74d74da7 Mon Sep 17 00:00:00 2001
From: Karel Zak <kzak@redhat.com>
Date: Thu, 2 Jun 2022 16:02:54 +0200
Subject: libblkid: (hfs) fix label use [fuzzing]
Addresses: https://issues.redhat.com/browse/RHEL-16071
Upstream: http://github.com/util-linux/util-linux/commit/74e48269ee9a15e230e25d0e3d2e50f5b0ba2b04
Reported-by: Thibault Guittet <tguittet@redhat.com>
Signed-off-by: Karel Zak <kzak@redhat.com>
---
libblkid/src/superblocks/hfs.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/libblkid/src/superblocks/hfs.c b/libblkid/src/superblocks/hfs.c
index 9674b1481..68cb30edb 100644
--- a/libblkid/src/superblocks/hfs.c
+++ b/libblkid/src/superblocks/hfs.c
@@ -173,7 +173,10 @@ static int probe_hfs(blkid_probe pr, const struct blkid_idmag *mag)
hfs_set_uuid(pr, hfs->finder_info.id, sizeof(hfs->finder_info.id));
- blkid_probe_set_label(pr, hfs->label, hfs->label_len);
+ size = hfs->label_len;
+ if ((size_t) size > sizeof(hfs->label))
+ size = sizeof(hfs->label);
+ blkid_probe_set_label(pr, hfs->label, size);
return 0;
}
--
2.43.0

View File

@ -0,0 +1,29 @@
From c7ce4cca01425123ef93cb6b89b0a0fe76b2ec7a Mon Sep 17 00:00:00 2001
From: Karel Zak <kzak@redhat.com>
Date: Thu, 2 Jun 2022 16:02:54 +0200
Subject: libblkid: (bsd) fix buffer pointer use [fuzzing]
Addresses: https://issues.redhat.com/browse/RHEL-16071
Upstream: http://github.com/util-linux/util-linux/commit/0a0630133055c3b3daa3072a3fd9944a1a149401
Reported-by: Thibault Guittet <tguittet@redhat.com>
Signed-off-by: Karel Zak <kzak@redhat.com>
---
libblkid/src/partitions/bsd.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libblkid/src/partitions/bsd.c b/libblkid/src/partitions/bsd.c
index c74517334..7a0b23195 100644
--- a/libblkid/src/partitions/bsd.c
+++ b/libblkid/src/partitions/bsd.c
@@ -50,7 +50,7 @@ static int probe_bsd_pt(blkid_probe pr, const struct blkid_idmag *mag)
goto nothing;
}
- l = (struct bsd_disklabel *) data + BLKID_MAG_LASTOFFSET(mag);
+ l = (struct bsd_disklabel *) (data + BLKID_MAG_LASTOFFSET(mag));
ls = blkid_probe_get_partlist(pr);
if (!ls)
--
2.43.0

View File

@ -0,0 +1,29 @@
From 452dbbbc7b430a51790c23a24135868ae7697db6 Mon Sep 17 00:00:00 2001
From: Karel Zak <kzak@redhat.com>
Date: Thu, 2 Jun 2022 16:02:54 +0200
Subject: libblkid: (mac) make sure block size is large enough [fuzzing]
Addresses: https://issues.redhat.com/browse/RHEL-16071
Upstream: http://github.com/util-linux/util-linux/commit/4e12fbca62be10b09503cecc7507757874043474
Reported-by: Thibault Guittet <tguittet@redhat.com>
Signed-off-by: Karel Zak <kzak@redhat.com>
---
libblkid/src/partitions/mac.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/libblkid/src/partitions/mac.c b/libblkid/src/partitions/mac.c
index 092d31d32..75a558b0a 100644
--- a/libblkid/src/partitions/mac.c
+++ b/libblkid/src/partitions/mac.c
@@ -93,6 +93,8 @@ static int probe_mac_pt(blkid_probe pr,
}
block_size = be16_to_cpu(md->block_size);
+ if (block_size < sizeof(struct mac_partition))
+ goto nothing;
/* The partition map always begins at physical block 1,
* the second block on the disk.
--
2.43.0

View File

@ -0,0 +1,56 @@
From 2fcbf867f00888216f7c4f57161b083ebdc8a836 Mon Sep 17 00:00:00 2001
From: Karel Zak <kzak@redhat.com>
Date: Thu, 2 Jun 2022 16:02:54 +0200
Subject: libblkid: (probe) fix size and offset overflows [fuzzing]
Addresses: https://issues.redhat.com/browse/RHEL-16071
Upstream: http://github.com/util-linux/util-linux/commit/106de261469e1001243d5b81ed895762fb34b2ba
Reported-by: Thibault Guittet <tguittet@redhat.com>
Signed-off-by: Karel Zak <kzak@redhat.com>
---
libblkid/src/probe.c | 17 ++++++++++++++---
1 file changed, 14 insertions(+), 3 deletions(-)
diff --git a/libblkid/src/probe.c b/libblkid/src/probe.c
index d317dc19a..c2bcea616 100644
--- a/libblkid/src/probe.c
+++ b/libblkid/src/probe.c
@@ -612,6 +612,11 @@ static int hide_buffer(blkid_probe pr, uint64_t off, uint64_t len)
struct list_head *p;
int ct = 0;
+ if (UINT64_MAX - len < off) {
+ DBG(BUFFER, ul_debug("\t hide-buffer overflow (ignore)"));
+ return -EINVAL;
+ }
+
list_for_each(p, &pr->buffers) {
struct blkid_bufinfo *x =
list_entry(p, struct blkid_bufinfo, bufs);
@@ -647,14 +652,20 @@ unsigned char *blkid_probe_get_buffer(blkid_probe pr, uint64_t off, uint64_t len
DBG(BUFFER, ul_debug("\t>>>> off=%ju, real-off=%ju (probe <%ju..%ju>, len=%ju",
off, real_off, pr->off, pr->off + pr->size, len));
*/
-
if (pr->size == 0) {
errno = EINVAL;
return NULL;
}
- if (len == 0 || (!S_ISCHR(pr->mode) && pr->off + pr->size < real_off + len)) {
- DBG(BUFFER, ul_debug("\t ignore: request out of probing area"));
+ if (UINT64_MAX - len < off || UINT64_MAX - len < real_off) {
+ DBG(BUFFER, ul_debug("\t read-buffer overflow (ignore)"));
+ return NULL;
+ }
+
+ if (len == 0
+ || (!S_ISCHR(pr->mode) && (pr->size < off || pr->size < len))
+ || (!S_ISCHR(pr->mode) && (pr->off + pr->size < real_off + len))) {
+ DBG(BUFFER, ul_debug("\t read-buffer out of probing area (ignore)"));
errno = 0;
return NULL;
}
--
2.43.0

View File

@ -0,0 +1,173 @@
From 4559d65f2a00d57f7fa21339370bb93d89a69c46 Mon Sep 17 00:00:00 2001
From: Karel Zak <kzak@redhat.com>
Date: Mon, 24 May 2021 12:24:33 +0200
Subject: lscpu: add SCALMHZ% and "CPU scaling MHz:"
$ lscpu
...
Model name: Intel(R) Core(TM) i7-4790K CPU @ 4.00GHz
CPU family: 6
Model: 60
Thread(s) per core: 2
Core(s) per socket: 4
Socket(s): 1
Stepping: 3
CPU(s) scaling MHz: 61%
CPU max MHz: 4400.0000
CPU min MHz: 800.0000
...
$ lscpu -e=CPU,MAXMHZ,MINMHZ,MHZ,SCALMHZ%
CPU MAXMHZ MINMHZ MHZ SCALMHZ%
0 4400.0000 800.0000 2800.000 64%
1 4400.0000 800.0000 4000.146 91%
2 4400.0000 800.0000 2800.000 64%
3 4400.0000 800.0000 2800.000 64%
4 4400.0000 800.0000 2800.000 64%
5 4400.0000 800.0000 4400.000 100%
6 4400.0000 800.0000 800.000 18%
7 4400.0000 800.0000 2800.000 64%
iAddresses: https://issues.redhat.com/browse/RHEL-12783
Upstream: http://github.com/util-linux/util-linux/commit/9b9e4f5d06be55f4b9e1a52b448055933df92c6b
Addresses: https://github.com/karelzak/util-linux/issues/1314
Signed-off-by: Karel Zak <kzak@redhat.com>
---
Documentation/TODO | 1 +
sys-utils/lscpu-cputype.c | 6 ++++++
sys-utils/lscpu-topology.c | 21 +++++++++++++++++++++
sys-utils/lscpu.c | 9 +++++++++
sys-utils/lscpu.h | 4 +++-
5 files changed, 40 insertions(+), 1 deletion(-)
diff --git a/Documentation/TODO b/Documentation/TODO
index 33ffa189d..e382e4b97 100644
--- a/Documentation/TODO
+++ b/Documentation/TODO
@@ -53,6 +53,7 @@ cal
lscpu
-----
+ - add --freq output to visualise CPU use, see https://github.com/karelzak/util-linux/issues/1314
- read cpuid and uname information from file if --sysroot is specified, then
we can prepare regression tests completely independent on hw and architecture.
diff --git a/sys-utils/lscpu-cputype.c b/sys-utils/lscpu-cputype.c
index 7b5b109c9..dd0c86084 100644
--- a/sys-utils/lscpu-cputype.c
+++ b/sys-utils/lscpu-cputype.c
@@ -530,6 +530,12 @@ int lscpu_read_cpuinfo(struct lscpu_cxt *cxt)
pr->curr_type->static_mhz = xstrdup(value);
if (pattern->id == PAT_BOGOMIPS_CPU && pr->curr_type && !pr->curr_type->bogomips)
pr->curr_type->bogomips = xstrdup(value);
+ if (pattern->id == PAT_MHZ && pr->curr_cpu && value) {
+ errno = 0;
+ pr->curr_cpu->mhz_cur_freq = strtof(value, NULL);
+ if (errno)
+ pr->curr_cpu->mhz_cur_freq = 0;
+ }
break;
case CPUINFO_LINE_CPUTYPE:
if (pr->curr_type && is_different_cputype(pr->curr_type, pattern->offset, value)) {
diff --git a/sys-utils/lscpu-topology.c b/sys-utils/lscpu-topology.c
index f4e8181b7..bba727643 100644
--- a/sys-utils/lscpu-topology.c
+++ b/sys-utils/lscpu-topology.c
@@ -588,6 +588,27 @@ float lsblk_cputype_get_minmhz(struct lscpu_cxt *cxt, struct lscpu_cputype *ct)
return res;
}
+/* returns scaling (use) of CPUs freq. in percent */
+float lsblk_cputype_get_scalmhz(struct lscpu_cxt *cxt, struct lscpu_cputype *ct)
+{
+ size_t i;
+ float fmax = 0, fcur = 0;
+
+ for (i = 0; i < cxt->npossibles; i++) {
+ struct lscpu_cpu *cpu = cxt->cpus[i];
+
+ if (!cpu || cpu->type != ct || !is_cpu_present(cxt, cpu))
+ continue;
+ if (cpu->mhz_max_freq <= 0.0 || cpu->mhz_cur_freq <= 0.0)
+ continue;
+ fmax += cpu->mhz_max_freq;
+ fcur += cpu->mhz_cur_freq;
+ }
+ if (fcur <= 0.0)
+ return 0.0;
+ return fcur / fmax * 100;
+}
+
int lscpu_read_topology(struct lscpu_cxt *cxt)
{
size_t i;
diff --git a/sys-utils/lscpu.c b/sys-utils/lscpu.c
index 8829098aa..47dd9d72f 100644
--- a/sys-utils/lscpu.c
+++ b/sys-utils/lscpu.c
@@ -105,6 +105,7 @@ enum {
COL_CPU_CONFIGURED,
COL_CPU_ONLINE,
COL_CPU_MHZ,
+ COL_CPU_SCALMHZ,
COL_CPU_MAXMHZ,
COL_CPU_MINMHZ,
};
@@ -150,6 +151,7 @@ static struct lscpu_coldesc coldescs_cpu[] =
[COL_CPU_CONFIGURED] = { "CONFIGURED", N_("shows if the hypervisor has allocated the CPU") },
[COL_CPU_ONLINE] = { "ONLINE", N_("shows if Linux currently makes use of the CPU"), SCOLS_FL_RIGHT },
[COL_CPU_MHZ] = { "MHZ", N_("shows the currently MHz of the CPU"), SCOLS_FL_RIGHT },
+ [COL_CPU_SCALMHZ] = { "SCALMHZ%", N_("shows scaling percentage of the CPU frequency"), SCOLS_FL_RIGHT },
[COL_CPU_MAXMHZ] = { "MAXMHZ", N_("shows the maximum MHz of the CPU"), SCOLS_FL_RIGHT },
[COL_CPU_MINMHZ] = { "MINMHZ", N_("shows the minimum MHz of the CPU"), SCOLS_FL_RIGHT }
};
@@ -425,6 +427,10 @@ static char *get_cell_data(
if (cpu->mhz)
xstrncpy(buf, cpu->mhz, bufsz);
break;
+ case COL_CPU_SCALMHZ:
+ if (cpu->mhz_cur_freq && cpu->mhz_max_freq)
+ snprintf(buf, bufsz, "%.0f%%", cpu->mhz_cur_freq / cpu->mhz_max_freq * 100);
+ break;
case COL_CPU_MAXMHZ:
if (cpu->mhz_max_freq)
snprintf(buf, bufsz, "%.4f", cpu->mhz_max_freq);
@@ -890,6 +896,9 @@ print_summary_cputype(struct lscpu_cxt *cxt,
add_summary_s(tb, sec, _("CPU static MHz:"), ct->static_mhz);
if (ct->has_freq) {
+ float scal = lsblk_cputype_get_scalmhz(cxt, ct);
+ if (scal > 0.0)
+ add_summary_x(tb, sec, _("CPU(s) scaling MHz:"), "%.0f%%", scal);
add_summary_x(tb, sec, _("CPU max MHz:"), "%.4f", lsblk_cputype_get_maxmhz(cxt, ct));
add_summary_x(tb, sec, _("CPU min MHz:"), "%.4f", lsblk_cputype_get_minmhz(cxt, ct));
}
diff --git a/sys-utils/lscpu.h b/sys-utils/lscpu.h
index e52c77c22..62f532581 100644
--- a/sys-utils/lscpu.h
+++ b/sys-utils/lscpu.h
@@ -127,11 +127,12 @@ struct lscpu_cpu {
int logical_id;
char *bogomips; /* per-CPU bogomips */
- char *mhz; /* max freq from cpuinfo */
+ char *mhz; /* freq from cpuinfo */
char *dynamic_mhz; /* from cpuinf for s390 */
char *static_mhz; /* from cpuinf for s390 */
float mhz_max_freq; /* realtime freq from /sys/.../cpuinfo_max_freq */
float mhz_min_freq; /* realtime freq from /sys/.../cpuinfo_min_freq */
+ float mhz_cur_freq;
int coreid;
int socketid;
@@ -280,6 +281,7 @@ void lscpu_cputype_free_topology(struct lscpu_cputype *ct);
float lsblk_cputype_get_maxmhz(struct lscpu_cxt *cxt, struct lscpu_cputype *ct);
float lsblk_cputype_get_minmhz(struct lscpu_cxt *cxt, struct lscpu_cputype *ct);
+float lsblk_cputype_get_scalmhz(struct lscpu_cxt *cxt, struct lscpu_cputype *ct);
struct lscpu_arch *lscpu_read_architecture(struct lscpu_cxt *cxt);
void lscpu_free_architecture(struct lscpu_arch *ar);
--
2.43.0

View File

@ -0,0 +1,44 @@
From 259178cd356109c861bf41ec32cea905faeabbca Mon Sep 17 00:00:00 2001
From: Karel Zak <kzak@redhat.com>
Date: Tue, 25 May 2021 13:23:39 +0200
Subject: lscpu: read MHZ from /sys/.../cpufreq/scaling_cur_freq
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
This is more portable and provides more stable results than
/proc/cpuinfo.
Addresses: https://issues.redhat.com/browse/RHEL-12783
Upstream: http://github.com/util-linux/util-linux/commit/f2d08d4ddc9bc601107df28dd8e4598cf2e0b420
Fixes: https://github.com/karelzak/util-linux/pull/1317
Co-Author: Thomas Weißschuh
Signed-off-by: Karel Zak <kzak@redhat.com>
---
sys-utils/lscpu-topology.c | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/sys-utils/lscpu-topology.c b/sys-utils/lscpu-topology.c
index bba727643..fe4da7cd5 100644
--- a/sys-utils/lscpu-topology.c
+++ b/sys-utils/lscpu-topology.c
@@ -551,6 +551,16 @@ static int read_mhz(struct lscpu_cxt *cxt, struct lscpu_cpu *cpu)
if (ul_path_readf_s32(sys, &mhz, "cpu%d/cpufreq/cpuinfo_min_freq", num) == 0)
cpu->mhz_min_freq = (float) mhz / 1000;
+ /* The default current-frequency value comes is from /proc/cpuinfo (if
+ * available). This /proc value is usually based on MSR registers
+ * (APERF/APERF) and it changes pretty often. It seems better to read
+ * frequency from cpufreq subsystem that provides the current frequency
+ * for the current policy. There is also cpuinfo_cur_freq in sysfs, but
+ * it's not always available.
+ */
+ if (ul_path_readf_s32(sys, &mhz, "cpu%d/cpufreq/scaling_cur_freq", num) == 0)
+ cpu->mhz_cur_freq = (float) mhz / 1000;
+
if (cpu->type && (cpu->mhz_min_freq || cpu->mhz_max_freq))
cpu->type->has_freq = 1;
--
2.43.0

View File

@ -0,0 +1,31 @@
From 7049ee572ded1f139c83250c7c57c7fbfa89b658 Mon Sep 17 00:00:00 2001
From: Karel Zak <kzak@redhat.com>
Date: Mon, 24 May 2021 13:19:47 +0200
Subject: lscpu: use MHZ as number to be locale sensitive
Addresses: https://issues.redhat.com/browse/RHEL-12783
Upstream: http://github.com/util-linux/util-linux/commit/ff6513c74e7fc97e2297b12dddb58d9b6513fcaf
Fixes: https://github.com/karelzak/util-linux/issues/1316
Signed-off-by: Karel Zak <kzak@redhat.com>
---
sys-utils/lscpu.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/sys-utils/lscpu.c b/sys-utils/lscpu.c
index 47dd9d72f..c1ac4cc7c 100644
--- a/sys-utils/lscpu.c
+++ b/sys-utils/lscpu.c
@@ -424,8 +424,8 @@ static char *get_cell_data(
is_cpu_online(cxt, cpu) ? _("yes") : _("no"));
break;
case COL_CPU_MHZ:
- if (cpu->mhz)
- xstrncpy(buf, cpu->mhz, bufsz);
+ if (cpu->mhz_cur_freq)
+ snprintf(buf, bufsz, "%.4f", cpu->mhz_cur_freq);
break;
case COL_CPU_SCALMHZ:
if (cpu->mhz_cur_freq && cpu->mhz_max_freq)
--
2.43.0

View File

@ -0,0 +1,59 @@
From ec4cf328499dbcd8f51e2501076a0799b156d580 Mon Sep 17 00:00:00 2001
From: Karel Zak <kzak@redhat.com>
Date: Tue, 25 May 2021 11:32:51 +0200
Subject: lscpu: use locale-independent strtod() when read from kernel
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Addresses: https://issues.redhat.com/browse/RHEL-12783
Upstream: http://github.com/util-linux/util-linux/commit/0b538002dad7bb5e178740191961bcc69509a80d
Upstream: http://github.com/util-linux/util-linux/commit/670b10ae363d40fbe7dfd3c2e9c3f8044bf630f1
Reported-by: Thomas Weißschuh
Signed-off-by: Karel Zak <kzak@redhat.com>
---
sys-utils/lscpu-cputype.c | 17 ++++++++++++++++-
1 file changed, 16 insertions(+), 1 deletion(-)
diff --git a/sys-utils/lscpu-cputype.c b/sys-utils/lscpu-cputype.c
index dd0c86084..bf6a7068c 100644
--- a/sys-utils/lscpu-cputype.c
+++ b/sys-utils/lscpu-cputype.c
@@ -6,10 +6,25 @@
# include <librtas.h>
#endif
+#include <locale.h>
#include "lscpu.h"
#include "fileutils.h"
+/* Simplified backport from upstrem to RHEL */
+static volatile locale_t c_locale;
+
+static double c_strtod(char const *str, char **end)
+{
+ if (!c_locale)
+ c_locale = newlocale(LC_ALL_MASK, "C", (locale_t) 0);
+ if (c_locale)
+ return strtod_l(str, end, c_locale);
+
+ return strtod(str, end);
+}
+
+
/* Lookup a pattern and get the value for format "<pattern> : <key>"
*/
int lookup(char *line, char *pattern, char **value)
@@ -532,7 +547,7 @@ int lscpu_read_cpuinfo(struct lscpu_cxt *cxt)
pr->curr_type->bogomips = xstrdup(value);
if (pattern->id == PAT_MHZ && pr->curr_cpu && value) {
errno = 0;
- pr->curr_cpu->mhz_cur_freq = strtof(value, NULL);
+ pr->curr_cpu->mhz_cur_freq = (float) c_strtod(value, NULL);
if (errno)
pr->curr_cpu->mhz_cur_freq = 0;
}
--
2.43.0

View File

@ -0,0 +1,227 @@
From c7abf1c87c44c54c16758e079dc3528a13d8e177 Mon Sep 17 00:00:00 2001
From: Karel Zak <kzak@redhat.com>
Date: Wed, 29 Nov 2023 12:19:55 +0100
Subject: libmount: add private mnt_optstr_get_missing()
The function compares two options strings and returns options which
are missing.
Addresses: https://issues.redhat.com/browse/RHEL-14612
Upstream: http://github.com/util-linux/util-linux/commit/722e4d47a9a21f09a6a719a0f510f29f12497ce5
Signed-off-by: Karel Zak <kzak@redhat.com>
---
libmount/src/mountP.h | 1 +
libmount/src/optstr.c | 104 ++++++++++++++++++++++++++++++++++++------
2 files changed, 92 insertions(+), 13 deletions(-)
diff --git a/libmount/src/mountP.h b/libmount/src/mountP.h
index 22442ec55..30fac593a 100644
--- a/libmount/src/mountP.h
+++ b/libmount/src/mountP.h
@@ -401,6 +401,7 @@ extern const struct libmnt_optmap *mnt_optmap_get_entry(
/* optstr.c */
extern int mnt_optstr_get_uid(const char *optstr, const char *name, uid_t *uid);
extern int mnt_optstr_remove_option_at(char **optstr, char *begin, char *end);
+extern int mnt_optstr_get_missing(const char *optstr, const char *wanted, char **missing);
extern int mnt_optstr_fix_gid(char **optstr, char *value, size_t valsz, char **next);
extern int mnt_optstr_fix_uid(char **optstr, char *value, size_t valsz, char **next);
extern int mnt_optstr_fix_secontext(char **optstr, char *value, size_t valsz, char **next);
diff --git a/libmount/src/optstr.c b/libmount/src/optstr.c
index 16800f571..a274e39b3 100644
--- a/libmount/src/optstr.c
+++ b/libmount/src/optstr.c
@@ -121,13 +121,16 @@ error:
* Locates the first option that matches @name. The @end is set to the
* char behind the option (it means ',' or \0).
*
+ * @ol is optional.
+ *
* Returns negative number on parse error, 1 when not found and 0 on success.
*/
-static int mnt_optstr_locate_option(char *optstr, const char *name,
+static int mnt_optstr_locate_option(char *optstr,
+ const char *name, size_t namesz,
struct libmnt_optloc *ol)
{
char *n;
- size_t namesz, nsz;
+ size_t nsz;
int rc;
if (!optstr)
@@ -135,25 +138,30 @@ static int mnt_optstr_locate_option(char *optstr, const char *name,
assert(name);
- namesz = strlen(name);
+ if (!namesz)
+ namesz = strlen(name);
+ if (!namesz)
+ return 1;
do {
rc = mnt_optstr_parse_next(&optstr, &n, &nsz,
- &ol->value, &ol->valsz);
+ ol ? &ol->value : NULL,
+ ol ? &ol->valsz : NULL);
if (rc)
break;
if (namesz == nsz && strncmp(n, name, nsz) == 0) {
- ol->begin = n;
- ol->end = *(optstr - 1) == ',' ? optstr - 1 : optstr;
- ol->namesz = nsz;
+ if (ol) {
+ ol->begin = n;
+ ol->end = *(optstr - 1) == ',' ? optstr - 1 : optstr;
+ ol->namesz = nsz;
+ }
return 0;
}
} while(1);
return rc;
}
-
/**
* mnt_optstr_next_option:
* @optstr: option string, returns the position of the next option
@@ -284,7 +292,7 @@ int mnt_optstr_get_option(const char *optstr, const char *name,
if (!optstr || !name)
return -EINVAL;
- rc = mnt_optstr_locate_option((char *) optstr, name, &ol);
+ rc = mnt_optstr_locate_option((char *) optstr, name, 0, &ol);
if (!rc) {
if (value)
*value = ol.value;
@@ -316,7 +324,7 @@ int mnt_optstr_deduplicate_option(char **optstr, const char *name)
do {
struct libmnt_optloc ol = MNT_INIT_OPTLOC;
- rc = mnt_optstr_locate_option(opt, name, &ol);
+ rc = mnt_optstr_locate_option(opt, name, 0, &ol);
if (!rc) {
if (begin) {
/* remove the previous instance */
@@ -429,7 +437,7 @@ int mnt_optstr_set_option(char **optstr, const char *name, const char *value)
return -EINVAL;
if (*optstr)
- rc = mnt_optstr_locate_option(*optstr, name, &ol);
+ rc = mnt_optstr_locate_option(*optstr, name, 0, &ol);
if (rc < 0)
return rc; /* parse error */
if (rc == 1)
@@ -472,7 +480,7 @@ int mnt_optstr_remove_option(char **optstr, const char *name)
if (!optstr || !name)
return -EINVAL;
- rc = mnt_optstr_locate_option(*optstr, name, &ol);
+ rc = mnt_optstr_locate_option(*optstr, name, 0, &ol);
if (rc != 0)
return rc;
@@ -632,6 +640,52 @@ int mnt_optstr_get_options(const char *optstr, char **subset,
return rc;
}
+/*
+ * @optstr: string with comma separated list of options
+ * @wanted: options expected in @optstr
+ * @missing: returns options from @wanted which missing in @optstr (optional)
+ *
+ * Retursn: <0 on error, 0 on missing options, 1 if nothing is missing
+ */
+int mnt_optstr_get_missing(const char *optstr, const char *wanted, char **missing)
+{
+ char *name, *val, *str = (char *) wanted;
+ size_t namesz = 0, valsz = 0;
+ struct ul_buffer buf = UL_INIT_BUFFER;
+ int rc = 0;
+
+ if (!wanted)
+ return 1;
+ if (missing) {
+ /* caller wants data, prepare buffer */
+ ul_buffer_set_chunksize(&buf, strlen(wanted) + 3); /* to call realloc() only once */
+ *missing = NULL;
+ }
+
+ while (!mnt_optstr_next_option(&str, &name, &namesz, &val, &valsz)) {
+
+ rc = mnt_optstr_locate_option((char *) optstr, name, namesz, NULL);
+ if (rc == 1) { /* not found */
+ if (!missing)
+ return 0;
+ rc = __buffer_append_option(&buf, name, namesz, val, valsz);
+ }
+
+ if (rc < 0)
+ break;
+ rc = 0;
+ }
+
+ if (!rc && missing) {
+ if (ul_buffer_is_empty(&buf))
+ rc = 1;
+ else
+ *missing = ul_buffer_get_data(&buf);
+ } else
+ ul_buffer_free_data(&buf);
+
+ return rc;
+}
/**
* mnt_optstr_get_flags:
@@ -1055,7 +1109,7 @@ int mnt_optstr_fix_user(char **optstr)
DBG(CXT, ul_debug("fixing user"));
- rc = mnt_optstr_locate_option(*optstr, "user", &ol);
+ rc = mnt_optstr_locate_option(*optstr, "user", 0, &ol);
if (rc)
return rc == 1 ? 0 : rc; /* 1: user= not found */
@@ -1378,6 +1432,29 @@ static int test_get(struct libmnt_test *ts, int argc, char *argv[])
return rc;
}
+static int test_missing(struct libmnt_test *ts, int argc, char *argv[])
+{
+ const char *optstr;
+ const char *wanted;
+ char *missing = NULL;
+ int rc;
+
+ if (argc < 2)
+ return -EINVAL;
+ optstr = argv[1];
+ wanted = argv[2];
+
+ rc = mnt_optstr_get_missing(optstr, wanted, &missing);
+ if (rc == 0)
+ printf("missing: %s\n", missing);
+ else if (rc == 1) {
+ printf("nothing\n");
+ rc = 0;
+ } else
+ printf("parse error: %s\n", optstr);
+ return rc;
+}
+
static int test_remove(struct libmnt_test *ts, int argc, char *argv[])
{
const char *name;
@@ -1456,6 +1533,7 @@ int main(int argc, char *argv[])
{ "--prepend",test_prepend,"<optstr> <name> [<value>] prepend value to optstr" },
{ "--set", test_set, "<optstr> <name> [<value>] (un)set value" },
{ "--get", test_get, "<optstr> <name> search name in optstr" },
+ { "--missing",test_missing,"<optstr> <wanted> what from wanted is missing" },
{ "--remove", test_remove, "<optstr> <name> remove name in optstr" },
{ "--dedup", test_dedup, "<optstr> <name> deduplicate name in optstr" },
{ "--split", test_split, "<optstr> split into FS, VFS and userspace" },
--
2.43.0

View File

@ -0,0 +1,188 @@
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

View File

@ -0,0 +1,69 @@
From faa1764ca23f587fb7fc995a4b2bdf48c5c80147 Mon Sep 17 00:00:00 2001
From: Karel Zak <kzak@redhat.com>
Date: Wed, 3 Jan 2024 12:38:21 +0100
Subject: libmount: add mnt_context_within_helper() wrapper
Addresses: https://issues.redhat.com/browse/RHEL-14612
Upstream: http://github.com/util-linux/util-linux/commit/0f9b2438c927d2787bf43b693809af3719e15646
Signed-off-by: Karel Zak <kzak@redhat.com>
---
libmount/src/context.c | 9 ++++++++-
libmount/src/context_umount.c | 2 +-
libmount/src/mountP.h | 1 +
3 files changed, 10 insertions(+), 2 deletions(-)
diff --git a/libmount/src/context.c b/libmount/src/context.c
index 3b32224e3..71b8d730a 100644
--- a/libmount/src/context.c
+++ b/libmount/src/context.c
@@ -2799,7 +2799,6 @@ int mnt_context_get_excode(
return rc;
}
-
/**
* mnt_context_init_helper
* @cxt: mount context
@@ -2835,6 +2834,14 @@ int mnt_context_init_helper(struct libmnt_context *cxt, int action,
return rc;
}
+/*
+ * libmount used in /sbin/[u]mount.<type> helper
+ */
+int mnt_context_within_helper(struct libmnt_context *cxt)
+{
+ return cxt && (cxt->flags & MNT_FL_HELPER);
+}
+
/**
* mnt_context_helper_setopt:
* @cxt: context
diff --git a/libmount/src/context_umount.c b/libmount/src/context_umount.c
index 8773c65ff..ba1e35456 100644
--- a/libmount/src/context_umount.c
+++ b/libmount/src/context_umount.c
@@ -272,7 +272,7 @@ static int lookup_umount_fs_by_statfs(struct libmnt_context *cxt, const char *tg
*/
if (mnt_context_is_restricted(cxt)
|| *tgt != '/'
- || (cxt->flags & MNT_FL_HELPER)
+ || mnt_context_within_helper(cxt)
|| mnt_context_mtab_writable(cxt)
|| mnt_context_is_force(cxt)
|| mnt_context_is_lazy(cxt)
diff --git a/libmount/src/mountP.h b/libmount/src/mountP.h
index 30fac593a..4b4c5de1e 100644
--- a/libmount/src/mountP.h
+++ b/libmount/src/mountP.h
@@ -423,6 +423,7 @@ extern const char *mnt_context_get_writable_tabpath(struct libmnt_context *cxt);
extern int mnt_context_get_mtab_for_target(struct libmnt_context *cxt,
struct libmnt_table **mtab, const char *tgt);
+extern int mnt_context_within_helper(struct libmnt_context *cxt);
extern int mnt_context_prepare_srcpath(struct libmnt_context *cxt);
extern int mnt_context_prepare_target(struct libmnt_context *cxt);
--
2.43.0

View File

@ -0,0 +1,145 @@
From dfdd500a339804075900bd1af42e433cf8d8f632 Mon Sep 17 00:00:00 2001
From: Karel Zak <kzak@redhat.com>
Date: Wed, 3 Jan 2024 14:13:28 +0100
Subject: libmount: introduce /run/mount/utab.event
The mnt_monitor_...() API uses /run/mount/utab.lock to monitor utab
changes. The same file is used to control access to the utab file.
The utab can be updated more than once during one mount(8) call, for
example, one update is done in /sbin/mount.nfs and next in mount(8).
This situation triggers two (e.g. inotify) events when monitoring is
based on the lock file.
It seems better to introduce separate file to trigger the event and do
not trigger this event in /sbin/mount.<type> helpers.
Addresses: https://issues.redhat.com/browse/RHEL-14612
Upstream: http://github.com/util-linux/util-linux/commit/544824929a740ed5f8108c752872c7f082f301cf
References: 477401f0de404aafbc7630f70c2f8b1d670e32f8
Signed-off-by: Karel Zak <kzak@redhat.com>
---
libmount/src/context.c | 6 ++++--
libmount/src/monitor.c | 16 +++++++---------
libmount/src/mountP.h | 1 +
libmount/src/tab_update.c | 19 +++++++++++++++++++
4 files changed, 31 insertions(+), 11 deletions(-)
diff --git a/libmount/src/context.c b/libmount/src/context.c
index 71b8d730a..c03b0ea64 100644
--- a/libmount/src/context.c
+++ b/libmount/src/context.c
@@ -2293,7 +2293,7 @@ int mnt_context_update_tabs(struct libmnt_context *cxt)
if (mnt_update_already_done(cxt->update, cxt->lock)) {
DBG(CXT, ul_debugobj(cxt, "don't update: error evaluate or already updated"));
- goto end;
+ goto emit;
}
} else if (cxt->helper) {
DBG(CXT, ul_debugobj(cxt, "don't update: external helper"));
@@ -2317,7 +2317,9 @@ int mnt_context_update_tabs(struct libmnt_context *cxt)
cxt->mountflags & MS_RDONLY);
rc = mnt_update_table(cxt->update, cxt->lock);
-
+emit:
+ if (rc == 0 && !mnt_context_within_helper(cxt))
+ mnt_update_emit_event(cxt->update);
end:
if (!mnt_context_switch_ns(cxt, ns_old))
return -MNT_ERR_NAMESPACE;
diff --git a/libmount/src/monitor.c b/libmount/src/monitor.c
index dada02ed3..4db56c2e0 100644
--- a/libmount/src/monitor.c
+++ b/libmount/src/monitor.c
@@ -224,18 +224,16 @@ static int userspace_add_watch(struct monitor_entry *me, int *final, int *fd)
assert(me->path);
/*
- * libmount uses rename(2) to atomically update utab, monitor
- * rename changes is too tricky. It seems better to monitor utab
- * lockfile close.
+ * libmount uses utab.event file to monitor and control utab updates
*/
- if (asprintf(&filename, "%s.lock", me->path) <= 0) {
+ if (asprintf(&filename, "%s.event", me->path) <= 0) {
rc = -errno;
goto done;
}
- /* try lock file if already exists */
+ /* try event file if already exists */
errno = 0;
- wd = inotify_add_watch(me->fd, filename, IN_CLOSE_NOWRITE);
+ wd = inotify_add_watch(me->fd, filename, IN_CLOSE_WRITE);
if (wd >= 0) {
DBG(MONITOR, ul_debug(" added inotify watch for %s [fd=%d]", filename, wd));
rc = 0;
@@ -254,7 +252,7 @@ static int userspace_add_watch(struct monitor_entry *me, int *final, int *fd)
if (!*filename)
break;
- /* try directory where is the lock file */
+ /* try directory where is the event file */
errno = 0;
wd = inotify_add_watch(me->fd, filename, IN_CREATE|IN_ISDIR);
if (wd >= 0) {
@@ -337,10 +335,10 @@ static int userspace_event_verify(struct libmnt_monitor *mn,
e = (const struct inotify_event *) p;
DBG(MONITOR, ul_debugobj(mn, " inotify event 0x%x [%s]\n", e->mask, e->len ? e->name : ""));
- if (e->mask & IN_CLOSE_NOWRITE)
+ if (e->mask & IN_CLOSE_WRITE)
status = 1;
else {
- /* event on lock file */
+ /* add watch for the event file */
userspace_add_watch(me, &status, &fd);
if (fd != e->wd) {
diff --git a/libmount/src/mountP.h b/libmount/src/mountP.h
index 4b4c5de1e..99b913c99 100644
--- a/libmount/src/mountP.h
+++ b/libmount/src/mountP.h
@@ -476,6 +476,7 @@ extern int mnt_context_deferred_delete_veritydev(struct libmnt_context *cxt);
/* tab_update.c */
extern int mnt_update_set_filename(struct libmnt_update *upd,
const char *filename, int userspace_only);
+extern int mnt_update_emit_event(struct libmnt_update *upd);
extern int mnt_update_already_done(struct libmnt_update *upd,
struct libmnt_lock *lc);
diff --git a/libmount/src/tab_update.c b/libmount/src/tab_update.c
index f60f522ce..5ae369b74 100644
--- a/libmount/src/tab_update.c
+++ b/libmount/src/tab_update.c
@@ -1003,6 +1003,25 @@ done:
return rc;
}
+int mnt_update_emit_event(struct libmnt_update *upd)
+{
+ char *filename;
+ int fd;
+
+ if (!upd || !upd->filename)
+ return -EINVAL;
+
+ if (asprintf(&filename, "%s.event", upd->filename) <= 0)
+ return -errno;
+
+ fd = open(filename, O_WRONLY|O_CREAT|O_CLOEXEC,
+ S_IWUSR|S_IRUSR|S_IRGRP|S_IROTH);
+ free(filename);
+ if (fd < 0)
+ return -errno;
+ close(fd);
+ return 0;
+}
#ifdef TEST_PROGRAM
--
2.43.0

View File

@ -0,0 +1,60 @@
From 6a25b1d1d819bc215bff2ce7677a1976fca9d55a Mon Sep 17 00:00:00 2001
From: Karel Zak <kzak@redhat.com>
Date: Mon, 8 Jan 2024 10:32:54 +0100
Subject: libmount: don't assume errno after failed asprintf()
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Addresses: https://issues.redhat.com/browse/RHEL-14612
Upstream: http://github.com/util-linux/util-linux/commit/a002df07ac15c370381cb44f06afeaa333685780
Reported-by: Thomas Weißschuh <thomas@t-8ch.de>
Signed-off-by: Karel Zak <kzak@redhat.com>
---
libmount/src/monitor.c | 2 +-
libmount/src/tab_update.c | 2 +-
libmount/src/utils.c | 2 +-
3 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/libmount/src/monitor.c b/libmount/src/monitor.c
index 4db56c2e0..040a5ee11 100644
--- a/libmount/src/monitor.c
+++ b/libmount/src/monitor.c
@@ -227,7 +227,7 @@ static int userspace_add_watch(struct monitor_entry *me, int *final, int *fd)
* libmount uses utab.event file to monitor and control utab updates
*/
if (asprintf(&filename, "%s.event", me->path) <= 0) {
- rc = -errno;
+ rc = -ENOMEM;
goto done;
}
diff --git a/libmount/src/tab_update.c b/libmount/src/tab_update.c
index 5ae369b74..70013a205 100644
--- a/libmount/src/tab_update.c
+++ b/libmount/src/tab_update.c
@@ -1012,7 +1012,7 @@ int mnt_update_emit_event(struct libmnt_update *upd)
return -EINVAL;
if (asprintf(&filename, "%s.event", upd->filename) <= 0)
- return -errno;
+ return -ENOMEM;
fd = open(filename, O_WRONLY|O_CREAT|O_CLOEXEC,
S_IWUSR|S_IRUSR|S_IRGRP|S_IROTH);
diff --git a/libmount/src/utils.c b/libmount/src/utils.c
index 35afce32c..897c42bf5 100644
--- a/libmount/src/utils.c
+++ b/libmount/src/utils.c
@@ -915,7 +915,7 @@ int mnt_open_uniq_filename(const char *filename, char **name)
rc = asprintf(&n, "%s.XXXXXX", filename);
if (rc <= 0)
- return -errno;
+ return -ENOMEM;
/* This is for very old glibc and for compatibility with Posix, which says
* nothing about mkstemp() mode. All sane glibc use secure mode (0600).
--
2.43.0

View File

@ -0,0 +1,174 @@
From 2ae4cd64f0bd535973fa3824c42e66c7e80dc09c Mon Sep 17 00:00:00 2001
From: Karel Zak <kzak@redhat.com>
Date: Fri, 19 Jan 2024 12:15:48 +0100
Subject: libmount: introduce reference counting for libmnt_lock
Addresses: https://issues.redhat.com/browse/RHEL-14612
Upstream: http://github.com/util-linux/util-linux/commit/87938635348a788ffd10cdbfb9055eddc2ed7a9f
Signed-off-by: Karel Zak <kzak@redhat.com>
---
libmount/docs/libmount-sections.txt | 2 ++
libmount/src/context.c | 3 +-
libmount/src/libmount.h.in | 2 ++
libmount/src/libmount.sym | 8 +++++
libmount/src/lock.c | 49 ++++++++++++++++++++++++++---
5 files changed, 58 insertions(+), 6 deletions(-)
diff --git a/libmount/docs/libmount-sections.txt b/libmount/docs/libmount-sections.txt
index 89b2b1e8b..d9263b8ad 100644
--- a/libmount/docs/libmount-sections.txt
+++ b/libmount/docs/libmount-sections.txt
@@ -297,6 +297,8 @@ libmnt_lock
mnt_free_lock
mnt_lock_file
mnt_new_lock
+mnt_ref_lock
+mnt_unref_lock
mnt_unlock_file
mnt_lock_block_signals
</SECTION>
diff --git a/libmount/src/context.c b/libmount/src/context.c
index c03b0ea64..ca7ea70d0 100644
--- a/libmount/src/context.c
+++ b/libmount/src/context.c
@@ -101,9 +101,8 @@ void mnt_free_context(struct libmnt_context *cxt)
mnt_unref_cache(cxt->cache);
mnt_unref_fs(cxt->fs);
mnt_unref_fs(cxt->fs_template);
-
mnt_context_clear_loopdev(cxt);
- mnt_free_lock(cxt->lock);
+ mnt_unref_lock(cxt->lock);
mnt_free_update(cxt->update);
mnt_context_set_target_ns(cxt, NULL);
diff --git a/libmount/src/libmount.h.in b/libmount/src/libmount.h.in
index 2d4d044e9..a51ac1ea5 100644
--- a/libmount/src/libmount.h.in
+++ b/libmount/src/libmount.h.in
@@ -417,6 +417,8 @@ extern const struct libmnt_optmap *mnt_get_builtin_optmap(int id);
/* lock.c */
extern struct libmnt_lock *mnt_new_lock(const char *datafile, pid_t id)
__ul_attribute__((warn_unused_result));
+extern void mnt_ref_lock(struct libmnt_lock *ml);
+extern void mnt_unref_lock(struct libmnt_lock *ml);
extern void mnt_free_lock(struct libmnt_lock *ml);
extern void mnt_unlock_file(struct libmnt_lock *ml);
diff --git a/libmount/src/libmount.sym b/libmount/src/libmount.sym
index 85e89ad02..88bce5c4b 100644
--- a/libmount/src/libmount.sym
+++ b/libmount/src/libmount.sym
@@ -361,3 +361,11 @@ MOUNT_2_37 {
mnt_fs_get_vfs_options_all;
mnt_table_over_fs;
} MOUNT_2_35;
+
+/*
+ * Backport from v2.40 to RHEL
+ */
+MOUNT_2_40 {
+ mnt_ref_lock;
+ mnt_unref_lock;
+} MOUNT_2_37;
diff --git a/libmount/src/lock.c b/libmount/src/lock.c
index fac64b63b..62353e215 100644
--- a/libmount/src/lock.c
+++ b/libmount/src/lock.c
@@ -36,6 +36,7 @@
* lock handler
*/
struct libmnt_lock {
+ int refcount; /* reference counter */
char *lockfile; /* path to lock file (e.g. /etc/mtab~) */
char *linkfile; /* path to link file (e.g. /etc/mtab~.<id>) */
int lockfile_fd; /* lock file descriptor */
@@ -82,6 +83,7 @@ struct libmnt_lock *mnt_new_lock(const char *datafile, pid_t id)
if (!ml)
goto err;
+ ml->refcount = 1;
ml->lockfile_fd = -1;
ml->linkfile = ln;
ml->lockfile = lo;
@@ -100,18 +102,57 @@ err:
* mnt_free_lock:
* @ml: struct libmnt_lock handler
*
- * Deallocates mnt_lock.
+ * Deallocates libmnt_lock. This function does not care about reference count. Don't
+ * use this function directly -- it's better to use mnt_unref_lock().
+ *
+ * The reference counting is supported since util-linux v2.40.
*/
void mnt_free_lock(struct libmnt_lock *ml)
{
if (!ml)
return;
- DBG(LOCKS, ul_debugobj(ml, "free%s", ml->locked ? " !!! LOCKED !!!" : ""));
+
+ DBG(LOCKS, ul_debugobj(ml, "free%s [refcount=%d]",
+ ml->locked ? " !!! LOCKED !!!" : "",
+ ml->refcount));
free(ml->lockfile);
free(ml->linkfile);
free(ml);
}
+/**
+ * mnt_ref_lock:
+ * @ml: lock pointer
+ *
+ * Increments reference counter.
+ *
+ * Since: 2.40
+ */
+void mnt_ref_lock(struct libmnt_lock *ml)
+{
+ if (ml) {
+ ml->refcount++;
+ /*DBG(FS, ul_debugobj(fs, "ref=%d", ml->refcount));*/
+ }
+}
+
+/**
+ * mnt_unref_lock:
+ * @ml: lock pointer
+ *
+ * De-increments reference counter, on zero the @ml is automatically
+ * deallocated by mnt_free_lock).
+ */
+void mnt_unref_lock(struct libmnt_lock *ml)
+{
+ if (ml) {
+ ml->refcount--;
+ /*DBG(FS, ul_debugobj(fs, "unref=%d", ml->refcount));*/
+ if (ml->refcount <= 0)
+ mnt_free_lock(ml);
+ }
+}
+
/**
* mnt_lock_block_signals:
* @ml: struct libmnt_lock handler
@@ -620,7 +661,7 @@ static void clean_lock(void)
if (!lock)
return;
mnt_unlock_file(lock);
- mnt_free_lock(lock);
+ mnt_unref_lock(lock);
}
static void __attribute__((__noreturn__)) sig_handler(int sig)
@@ -700,7 +741,7 @@ static int test_lock(struct libmnt_test *ts, int argc, char *argv[])
increment_data(datafile, verbose, l);
mnt_unlock_file(lock);
- mnt_free_lock(lock);
+ mnt_unref_lock(lock);
lock = NULL;
/* The mount command usually finishes after a mtab update. We
--
2.43.0

View File

@ -0,0 +1,352 @@
From 317add745924e5a4ad186691eede19d5a7c5eb10 Mon Sep 17 00:00:00 2001
From: Karel Zak <kzak@redhat.com>
Date: Fri, 19 Jan 2024 12:58:50 +0100
Subject: libmount: cleanup locking in table update code
* use reference counting for libmnt_lock
* remove lock use from mnt_update_already_done(), it's read-only
operation and utab update is atomic (based on rename(2))
* keep the lock instance mandatory for all low-level update_*
functions. The lock is always initialized, so all the 'if(lc)'
are unnecessary.
Addresses: https://issues.redhat.com/browse/RHEL-14612
Upstream: http://github.com/util-linux/util-linux/commit/b94b5929a63df9786020e0329e94d2f35f3993ae
Signed-off-by: Karel Zak <kzak@redhat.com>
---
libmount/src/context.c | 2 +-
libmount/src/mountP.h | 3 +-
libmount/src/tab_update.c | 118 +++++++++++++++++---------------------
3 files changed, 56 insertions(+), 67 deletions(-)
diff --git a/libmount/src/context.c b/libmount/src/context.c
index ca7ea70d0..06ac50dc2 100644
--- a/libmount/src/context.c
+++ b/libmount/src/context.c
@@ -2290,7 +2290,7 @@ int mnt_context_update_tabs(struct libmnt_context *cxt)
&& mnt_context_get_helper_status(cxt) == 0
&& mnt_context_utab_writable(cxt)) {
- if (mnt_update_already_done(cxt->update, cxt->lock)) {
+ if (mnt_update_already_done(cxt->update)) {
DBG(CXT, ul_debugobj(cxt, "don't update: error evaluate or already updated"));
goto emit;
}
diff --git a/libmount/src/mountP.h b/libmount/src/mountP.h
index 99b913c99..eddc82bde 100644
--- a/libmount/src/mountP.h
+++ b/libmount/src/mountP.h
@@ -477,8 +477,7 @@ extern int mnt_context_deferred_delete_veritydev(struct libmnt_context *cxt);
extern int mnt_update_set_filename(struct libmnt_update *upd,
const char *filename, int userspace_only);
extern int mnt_update_emit_event(struct libmnt_update *upd);
-extern int mnt_update_already_done(struct libmnt_update *upd,
- struct libmnt_lock *lc);
+extern int mnt_update_already_done(struct libmnt_update *upd);
#if __linux__
/* btrfs.c */
diff --git a/libmount/src/tab_update.c b/libmount/src/tab_update.c
index 70013a205..25a734e9d 100644
--- a/libmount/src/tab_update.c
+++ b/libmount/src/tab_update.c
@@ -42,6 +42,7 @@ struct libmnt_update {
missing_options : 1;
struct libmnt_table *mountinfo;
+ struct libmnt_lock *lock;
};
static int set_fs_root(struct libmnt_update *upd, struct libmnt_fs *fs, unsigned long mountflags);
@@ -77,6 +78,7 @@ void mnt_free_update(struct libmnt_update *upd)
DBG(UPDATE, ul_debugobj(upd, "free"));
+ mnt_unref_lock(upd->lock);
mnt_unref_fs(upd->fs);
mnt_unref_table(upd->mountinfo);
free(upd->target);
@@ -691,18 +693,18 @@ static int add_file_entry(struct libmnt_table *tb, struct libmnt_update *upd)
return update_table(upd, tb);
}
-static int update_add_entry(struct libmnt_update *upd, struct libmnt_lock *lc)
+static int update_add_entry(struct libmnt_update *upd)
{
struct libmnt_table *tb;
int rc = 0;
assert(upd);
assert(upd->fs);
+ assert(upd->lock);
DBG(UPDATE, ul_debugobj(upd, "%s: add entry", upd->filename));
- if (lc)
- rc = mnt_lock_file(lc);
+ rc = mnt_lock_file(upd->lock);
if (rc)
return -MNT_ERR_LOCK;
@@ -710,25 +712,24 @@ static int update_add_entry(struct libmnt_update *upd, struct libmnt_lock *lc)
upd->userspace_only ? MNT_FMT_UTAB : MNT_FMT_MTAB, 1);
if (tb)
rc = add_file_entry(tb, upd);
- if (lc)
- mnt_unlock_file(lc);
+ mnt_unlock_file(upd->lock);
mnt_unref_table(tb);
return rc;
}
-static int update_remove_entry(struct libmnt_update *upd, struct libmnt_lock *lc)
+static int update_remove_entry(struct libmnt_update *upd)
{
struct libmnt_table *tb;
int rc = 0;
assert(upd);
assert(upd->target);
+ assert(upd->lock);
DBG(UPDATE, ul_debugobj(upd, "%s: remove entry", upd->filename));
- if (lc)
- rc = mnt_lock_file(lc);
+ rc = mnt_lock_file(upd->lock);
if (rc)
return -MNT_ERR_LOCK;
@@ -741,23 +742,22 @@ static int update_remove_entry(struct libmnt_update *upd, struct libmnt_lock *lc
rc = update_table(upd, tb);
}
}
- if (lc)
- mnt_unlock_file(lc);
+ mnt_unlock_file(upd->lock);
mnt_unref_table(tb);
return rc;
}
-static int update_modify_target(struct libmnt_update *upd, struct libmnt_lock *lc)
+static int update_modify_target(struct libmnt_update *upd)
{
struct libmnt_table *tb = NULL;
int rc = 0;
assert(upd);
+ assert(upd->lock);
DBG(UPDATE, ul_debugobj(upd, "%s: modify target", upd->filename));
- if (lc)
- rc = mnt_lock_file(lc);
+ rc = mnt_lock_file(upd->lock);
if (rc)
return -MNT_ERR_LOCK;
@@ -773,15 +773,13 @@ static int update_modify_target(struct libmnt_update *upd, struct libmnt_lock *l
}
}
- if (lc)
- mnt_unlock_file(lc);
-
+ mnt_unlock_file(upd->lock);
mnt_unref_table(tb);
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)
+static int update_modify_options(struct libmnt_update *upd)
{
struct libmnt_table *tb = NULL;
int rc = 0;
@@ -789,13 +787,13 @@ static int update_modify_options(struct libmnt_update *upd, struct libmnt_lock *
assert(upd);
assert(upd->fs);
+ assert(upd->lock);
DBG(UPDATE, ul_debugobj(upd, "%s: modify options", upd->filename));
fs = upd->fs;
- if (lc)
- rc = mnt_lock_file(lc);
+ rc = mnt_lock_file(upd->lock);
if (rc)
return -MNT_ERR_LOCK;
@@ -816,15 +814,13 @@ static int update_modify_options(struct libmnt_update *upd, struct libmnt_lock *
rc = add_file_entry(tb, upd); /* not found, add new */
}
- if (lc)
- mnt_unlock_file(lc);
-
+ mnt_unlock_file(upd->lock);
mnt_unref_table(tb);
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)
+static int update_add_options(struct libmnt_update *upd)
{
struct libmnt_table *tb = NULL;
int rc = 0;
@@ -832,6 +828,7 @@ static int update_add_options(struct libmnt_update *upd, struct libmnt_lock *lc)
assert(upd);
assert(upd->fs);
+ assert(upd->lock);
if (!upd->fs->user_optstr)
return 0;
@@ -840,8 +837,7 @@ static int update_add_options(struct libmnt_update *upd, struct libmnt_lock *lc)
fs = upd->fs;
- if (lc)
- rc = mnt_lock_file(lc);
+ rc = mnt_lock_file(upd->lock);
if (rc)
return -MNT_ERR_LOCK;
@@ -867,14 +863,33 @@ static int update_add_options(struct libmnt_update *upd, struct libmnt_lock *lc)
rc = add_file_entry(tb, upd); /* not found, add new */
}
- if (lc)
- mnt_unlock_file(lc);
-
+ mnt_unlock_file(upd->lock);
mnt_unref_table(tb);
return rc;
}
+static int update_init_lock(struct libmnt_update *upd, struct libmnt_lock *lc)
+{
+ assert(upd);
+
+ if (lc) {
+ mnt_unref_lock(upd->lock);
+ mnt_ref_lock(lc);
+ upd->lock = lc;
+ } else if (!upd->lock) {
+ upd->lock = mnt_new_lock(upd->filename, 0);
+ if (!upd->lock)
+ return -ENOMEM;
+ mnt_lock_block_signals(upd->lock, TRUE);
+ }
+
+ if (upd->userspace_only)
+ mnt_lock_use_simplelock(upd->lock, TRUE); /* use flock */
+
+ return 0;
+}
+
/**
* mnt_update_table:
* @upd: update
@@ -891,7 +906,6 @@ static int update_add_options(struct libmnt_update *upd, struct libmnt_lock *lc)
*/
int mnt_update_table(struct libmnt_update *upd, struct libmnt_lock *lc)
{
- struct libmnt_lock *lc0 = lc;
int rc = -EINVAL;
if (!upd || !upd->filename)
@@ -903,37 +917,32 @@ int mnt_update_table(struct libmnt_update *upd, struct libmnt_lock *lc)
if (upd->fs) {
DBG(UPDATE, mnt_fs_print_debug(upd->fs, stderr));
}
- if (!lc) {
- lc = mnt_new_lock(upd->filename, 0);
- if (lc)
- mnt_lock_block_signals(lc, TRUE);
- }
- if (lc && upd->userspace_only)
- mnt_lock_use_simplelock(lc, TRUE); /* use flock */
+
+ rc = update_init_lock(upd, lc);
+ if (rc)
+ goto done;
if (!upd->fs && upd->target)
- rc = update_remove_entry(upd, lc); /* umount */
+ rc = update_remove_entry(upd); /* umount */
else if (upd->mountflags & MS_MOVE)
- rc = update_modify_target(upd, lc); /* move */
+ rc = update_modify_target(upd); /* move */
else if (upd->mountflags & MS_REMOUNT)
- rc = update_modify_options(upd, lc); /* remount */
+ rc = update_modify_options(upd); /* remount */
else if (upd->fs && upd->missing_options)
- rc = update_add_options(upd, lc); /* mount by externel helper */
+ rc = update_add_options(upd); /* mount by externel helper */
else if (upd->fs)
- rc = update_add_entry(upd, lc); /* mount */
+ rc = update_add_entry(upd); /* mount */
upd->ready = 1;
+done:
DBG(UPDATE, ul_debugobj(upd, "%s: update tab: done [rc=%d]",
upd->filename, rc));
- if (lc != lc0)
- mnt_free_lock(lc);
return rc;
}
-int mnt_update_already_done(struct libmnt_update *upd, struct libmnt_lock *lc)
+int mnt_update_already_done(struct libmnt_update *upd)
{
struct libmnt_table *tb = NULL;
- struct libmnt_lock *lc0 = lc;
int rc = 0;
if (!upd || !upd->filename || (!upd->fs && !upd->target))
@@ -941,25 +950,8 @@ int mnt_update_already_done(struct libmnt_update *upd, struct libmnt_lock *lc)
DBG(UPDATE, ul_debugobj(upd, "%s: checking for previous update", upd->filename));
- if (!lc) {
- lc = mnt_new_lock(upd->filename, 0);
- if (lc)
- mnt_lock_block_signals(lc, TRUE);
- }
- if (lc && upd->userspace_only)
- mnt_lock_use_simplelock(lc, TRUE); /* use flock */
- if (lc) {
- rc = mnt_lock_file(lc);
- if (rc) {
- rc = -MNT_ERR_LOCK;
- goto done;
- }
- }
-
tb = __mnt_new_table_from_file(upd->filename,
upd->userspace_only ? MNT_FMT_UTAB : MNT_FMT_MTAB, 1);
- if (lc)
- mnt_unlock_file(lc);
if (!tb)
goto done;
@@ -996,8 +988,6 @@ int mnt_update_already_done(struct libmnt_update *upd, struct libmnt_lock *lc)
mnt_unref_table(tb);
done:
- if (lc && lc != lc0)
- mnt_free_lock(lc);
DBG(UPDATE, ul_debugobj(upd, "%s: previous update check done [rc=%d]",
upd->filename, rc));
return rc;
--
2.43.0

View File

@ -0,0 +1,215 @@
From 2e22136c0ef7fd5744460d783ef570525df42337 Mon Sep 17 00:00:00 2001
From: Karel Zak <kzak@redhat.com>
Date: Mon, 22 Jan 2024 12:56:24 +0100
Subject: libmount: add utab.act file
The file exists when libmount works with utab, and more steps are
expected during a single mount operation (more kernel events, more
updates to utab, etc.).
It is possible to monitor the file through the mnt_monitor_...() API
by a simple access() after any event. No locks are expected in
monitor, making it usable for non-root users without any security
impact. The monitor can ignore events if the file exist.
Addresses: https://issues.redhat.com/browse/RHEL-14612
Upstream: http://github.com/util-linux/util-linux/commit/9218c9678a6aa9b163705364246ed128e94fabb7
Signed-off-by: Karel Zak <kzak@redhat.com>
---
libmount/src/context.c | 7 +++
libmount/src/mountP.h | 2 +
libmount/src/tab_update.c | 109 ++++++++++++++++++++++++++++++++++++++
3 files changed, 118 insertions(+)
diff --git a/libmount/src/context.c b/libmount/src/context.c
index 06ac50dc2..27e06a19c 100644
--- a/libmount/src/context.c
+++ b/libmount/src/context.c
@@ -2261,6 +2261,10 @@ int mnt_context_prepare_update(struct libmnt_context *cxt)
rc = mnt_update_set_fs(cxt->update, cxt->mountflags,
NULL, cxt->fs);
+ if (mnt_update_is_ready(cxt->update)) {
+ DBG(CXT, ul_debugobj(cxt, "update is ready"));
+ mnt_update_start(cxt->update);
+ }
return rc < 0 ? rc : 0;
}
@@ -2319,7 +2323,10 @@ int mnt_context_update_tabs(struct libmnt_context *cxt)
emit:
if (rc == 0 && !mnt_context_within_helper(cxt))
mnt_update_emit_event(cxt->update);
+
end:
+ mnt_update_end(cxt->update);
+
if (!mnt_context_switch_ns(cxt, ns_old))
return -MNT_ERR_NAMESPACE;
return rc;
diff --git a/libmount/src/mountP.h b/libmount/src/mountP.h
index eddc82bde..505d70808 100644
--- a/libmount/src/mountP.h
+++ b/libmount/src/mountP.h
@@ -478,6 +478,8 @@ extern int mnt_update_set_filename(struct libmnt_update *upd,
const char *filename, int userspace_only);
extern int mnt_update_emit_event(struct libmnt_update *upd);
extern int mnt_update_already_done(struct libmnt_update *upd);
+extern int mnt_update_start(struct libmnt_update *upd);
+extern int mnt_update_end(struct libmnt_update *upd);
#if __linux__
/* btrfs.c */
diff --git a/libmount/src/tab_update.c b/libmount/src/tab_update.c
index 25a734e9d..7b088c025 100644
--- a/libmount/src/tab_update.c
+++ b/libmount/src/tab_update.c
@@ -38,6 +38,9 @@ struct libmnt_update {
unsigned long mountflags;
int userspace_only;
+ int act_fd;
+ char *act_filename;
+
unsigned int ready : 1,
missing_options : 1;
@@ -61,6 +64,7 @@ struct libmnt_update *mnt_new_update(void)
if (!upd)
return NULL;
+ upd->act_fd = -1;
DBG(UPDATE, ul_debugobj(upd, "allocate"));
return upd;
}
@@ -81,8 +85,11 @@ void mnt_free_update(struct libmnt_update *upd)
mnt_unref_lock(upd->lock);
mnt_unref_fs(upd->fs);
mnt_unref_table(upd->mountinfo);
+ if (upd->act_fd >= 0)
+ close(upd->act_fd);
free(upd->target);
free(upd->filename);
+ free(upd->act_filename);
free(upd);
}
@@ -1004,6 +1011,8 @@ int mnt_update_emit_event(struct libmnt_update *upd)
if (asprintf(&filename, "%s.event", upd->filename) <= 0)
return -ENOMEM;
+ DBG(UPDATE, ul_debugobj(upd, "emitting utab event"));
+
fd = open(filename, O_WRONLY|O_CREAT|O_CLOEXEC,
S_IWUSR|S_IRUSR|S_IRGRP|S_IROTH);
free(filename);
@@ -1013,6 +1022,106 @@ int mnt_update_emit_event(struct libmnt_update *upd)
return 0;
}
+/*
+ * Let's use /run/mount/utab.act file to report to libmount monitor that
+ * libmount is working with utab. In this case, the monitor can ignore all
+ * events from kernel until entire mount (with all steps) is done.
+ *
+ * For example mount NFS with x-* options, means
+ * - create utab.act and mark it as used (by LOCK_SH)
+ * - exec /sbin/mount.nfs
+ * - call mount(2) (kernel event on /proc/self/mounts)
+ * - utab update (NFS stuff)
+ * - utab update (add x-* userspace options)
+ * - unlink utab.act (if not use anyone else)
+ * - release event by /run/mount/utab.event
+ *
+ * Note, this is used only when utab is in the game (x-* options).
+ */
+int mnt_update_start(struct libmnt_update *upd)
+{
+ int rc = 0;
+ mode_t oldmask;
+
+ if (!upd || !upd->filename)
+ return -EINVAL;
+
+ if (!upd->act_filename &&
+ asprintf(&upd->act_filename, "%s.act", upd->filename) <= 0)
+ return -ENOMEM;
+
+ /* Use exclusive lock to avoid some other proces will remove the the
+ * file before it's marked as used by LOCK_SH (below) */
+ rc = update_init_lock(upd, NULL);
+ if (rc)
+ return rc;
+
+ rc = mnt_lock_file(upd->lock);
+ if (rc)
+ return -MNT_ERR_LOCK;
+
+ DBG(UPDATE, ul_debugobj(upd, "creating act file"));
+
+ oldmask = umask(S_IRGRP|S_IWGRP|S_IXGRP|S_IROTH|S_IWOTH|S_IXOTH);
+ upd->act_fd = open(upd->act_filename, O_WRONLY|O_CREAT|O_CLOEXEC, S_IRUSR|S_IWUSR);
+ umask(oldmask);
+
+ if (upd->act_fd < 0) {
+ rc = -errno;
+ goto fail;
+ }
+
+ /* mark the file as used */
+ rc = flock(upd->act_fd, LOCK_SH);
+ if (rc) {
+ rc = -errno;
+ goto fail;
+ }
+
+ mnt_unlock_file(upd->lock);
+ return 0;
+fail:
+ DBG(UPDATE, ul_debugobj(upd, "act file failed [rc=%d]", rc));
+ mnt_unlock_file(upd->lock);
+ unlink(upd->act_filename);
+ close(upd->act_fd);
+ upd->act_fd = -1;
+ return rc;
+}
+
+int mnt_update_end(struct libmnt_update *upd)
+{
+ int rc;
+
+ if (!upd || upd->act_fd < 0)
+ return -EINVAL;
+
+ DBG(UPDATE, ul_debugobj(upd, "removing act file"));
+
+ /* make sure nobody else will use the file */
+ rc = mnt_lock_file(upd->lock);
+ if (rc)
+ return -MNT_ERR_LOCK;
+
+ /* mark the file as unused */
+ flock(upd->act_fd, LOCK_UN);
+ errno = 0;
+
+ /* check if nobody else need the file (if yes, then the file is under LOCK_SH) )*/
+ if (flock(upd->act_fd, LOCK_EX | LOCK_NB) != 0) {
+ if (errno == EWOULDBLOCK)
+ DBG(UPDATE, ul_debugobj(upd, "act file used, no unlink"));
+ } else {
+ DBG(UPDATE, ul_debugobj(upd, "unlinking act file"));
+ unlink(upd->act_filename);
+ }
+
+ mnt_unlock_file(upd->lock);
+ close(upd->act_fd);
+ upd->act_fd = -1;
+ return 0;
+}
+
#ifdef TEST_PROGRAM
static int update(const char *target, struct libmnt_fs *fs, unsigned long mountflags)
--
2.43.0

View File

@ -0,0 +1,180 @@
From e8de2e75d712dd9a750bde130b4367546b46a0bd Mon Sep 17 00:00:00 2001
From: Karel Zak <kzak@redhat.com>
Date: Mon, 22 Jan 2024 13:04:44 +0100
Subject: libmount: ignore unwanted kernel events in monitor
If the mount operation requires multiple steps, it's optimal for the
libmount monitor to ignore the steps until we get a complete mount
(reported by the utab.event file).
This commit adds a new API function, mnt_monitor_veil_kernel(), to
ignore unwanted kernel mount events.
Note that this only makes sense when the application monitors kernel
and userspace events simultaneously.
Addresses: https://issues.redhat.com/browse/RHEL-14612
Upstream: http://github.com/util-linux/util-linux/commit/a2b5a4e0adf9543843bb0aef94d21e7105cf8159
Signed-off-by: Karel Zak <kzak@redhat.com>
---
libmount/docs/libmount-sections.txt | 1 +
libmount/src/libmount.h.in | 2 ++
libmount/src/libmount.sym | 1 +
libmount/src/monitor.c | 55 ++++++++++++++++++++++++++---
4 files changed, 54 insertions(+), 5 deletions(-)
diff --git a/libmount/docs/libmount-sections.txt b/libmount/docs/libmount-sections.txt
index d9263b8ad..43bb80f1c 100644
--- a/libmount/docs/libmount-sections.txt
+++ b/libmount/docs/libmount-sections.txt
@@ -449,5 +449,6 @@ mnt_monitor_get_fd
mnt_monitor_close_fd
mnt_monitor_next_change
mnt_monitor_event_cleanup
+mnt_monitor_veil_kernel
mnt_monitor_wait
</SECTION>
diff --git a/libmount/src/libmount.h.in b/libmount/src/libmount.h.in
index a51ac1ea5..b57b6bcd6 100644
--- a/libmount/src/libmount.h.in
+++ b/libmount/src/libmount.h.in
@@ -671,6 +671,8 @@ extern int mnt_monitor_enable_kernel(struct libmnt_monitor *mn, int enable);
extern int mnt_monitor_enable_userspace(struct libmnt_monitor *mn,
int enable, const char *filename);
+extern int mnt_monitor_veil_kernel(struct libmnt_monitor *mn, int enable);
+
extern int mnt_monitor_get_fd(struct libmnt_monitor *mn);
extern int mnt_monitor_close_fd(struct libmnt_monitor *mn);
extern int mnt_monitor_wait(struct libmnt_monitor *mn, int timeout);
diff --git a/libmount/src/libmount.sym b/libmount/src/libmount.sym
index 88bce5c4b..13071b9cd 100644
--- a/libmount/src/libmount.sym
+++ b/libmount/src/libmount.sym
@@ -368,4 +368,5 @@ MOUNT_2_37 {
MOUNT_2_40 {
mnt_ref_lock;
mnt_unref_lock;
+ mnt_monitor_veil_kernel;
} MOUNT_2_37;
diff --git a/libmount/src/monitor.c b/libmount/src/monitor.c
index 040a5ee11..b5cc7e768 100644
--- a/libmount/src/monitor.c
+++ b/libmount/src/monitor.c
@@ -64,6 +64,8 @@ struct libmnt_monitor {
int fd; /* public monitor file descriptor */
struct list_head ents;
+
+ unsigned int kernel_veiled: 1;
};
struct monitor_opers {
@@ -469,12 +471,28 @@ err:
return rc;
}
+static int kernel_event_verify(struct libmnt_monitor *mn,
+ struct monitor_entry *me)
+{
+ int status = 1;
+
+ if (!mn || !me || me->fd < 0)
+ return 0;
+
+ if (mn->kernel_veiled && access(MNT_PATH_UTAB ".act", F_OK) == 0) {
+ status = 0;
+ DBG(MONITOR, ul_debugobj(mn, "kernel event veiled"));
+ }
+ return status;
+}
+
/*
* kernel monitor operations
*/
static const struct monitor_opers kernel_opers = {
.op_get_fd = kernel_monitor_get_fd,
.op_close_fd = kernel_monitor_close_fd,
+ .op_event_verify = kernel_event_verify
};
/**
@@ -543,6 +561,28 @@ err:
return rc;
}
+/**
+ * mnt_monitor_veil_kernel:
+ * @mn: monitor instance
+ * @enable: 1 or 0
+ *
+ * Force monitor to ignore kernel events if the same mount/umount operation
+ * will generate an userspace event later. The kernel-only mount operation will
+ * be not affected.
+ *
+ * Return: 0 on success and <0 on error.
+ *
+ * Since: 2.40
+ */
+int mnt_monitor_veil_kernel(struct libmnt_monitor *mn, int enable)
+{
+ if (!mn)
+ return -EINVAL;
+
+ mn->kernel_veiled = enable ? 1 : 0;
+ return 0;
+}
+
/*
* Add/Remove monitor entry to/from monitor epoll.
*/
@@ -850,6 +890,8 @@ static struct libmnt_monitor *create_test_monitor(int argc, char *argv[])
warn("failed to initialize kernel monitor");
goto err;
}
+ } else if (strcmp(argv[i], "veil") == 0) {
+ mnt_monitor_veil_kernel(mn, 1);
}
}
if (i == 1) {
@@ -896,12 +938,14 @@ static int __test_epoll(struct libmnt_test *ts, int argc, char *argv[], int clea
goto done;
}
- printf("waiting for changes...\n");
do {
const char *filename = NULL;
struct epoll_event events[1];
- int n = epoll_wait(efd, events, 1, -1);
+ int n;
+
+ printf("waiting for changes...\n");
+ n = epoll_wait(efd, events, 1, -1);
if (n < 0) {
rc = -errno;
warn("polling error");
@@ -958,6 +1002,7 @@ static int test_wait(struct libmnt_test *ts, int argc, char *argv[])
while (mnt_monitor_next_change(mn, &filename, NULL) == 0)
printf(" %s: change detected\n", filename);
+ printf("waiting for changes...\n");
}
mnt_unref_monitor(mn);
return 0;
@@ -966,9 +1011,9 @@ static int test_wait(struct libmnt_test *ts, int argc, char *argv[])
int main(int argc, char *argv[])
{
struct libmnt_test tss[] = {
- { "--epoll", test_epoll, "<userspace kernel ...> monitor in epoll" },
- { "--epoll-clean", test_epoll_cleanup, "<userspace kernel ...> monitor in epoll and clean events" },
- { "--wait", test_wait, "<userspace kernel ...> monitor wait function" },
+ { "--epoll", test_epoll, "<userspace kernel veil ...> monitor in epoll" },
+ { "--epoll-clean", test_epoll_cleanup, "<userspace kernel veil ...> monitor in epoll and clean events" },
+ { "--wait", test_wait, "<userspace kernel veil ...> monitor wait function" },
{ NULL }
};
--
2.43.0

View File

@ -0,0 +1,29 @@
From be0d06e3f382d8ddcf7b870d58ed1cc9576e065a Mon Sep 17 00:00:00 2001
From: Karel Zak <kzak@redhat.com>
Date: Wed, 24 Jan 2024 09:54:19 +0100
Subject: libmount: improve act file close
Addresses: https://issues.redhat.com/browse/RHEL-14612
Upstream: http://github.com/util-linux/util-linux/commit/630dd235bce560476e0e3a92984091f1e50157c1
Signed-off-by: Karel Zak <kzak@redhat.com>
---
libmount/src/tab_update.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/libmount/src/tab_update.c b/libmount/src/tab_update.c
index 7b088c025..8a50b5a01 100644
--- a/libmount/src/tab_update.c
+++ b/libmount/src/tab_update.c
@@ -1084,7 +1084,8 @@ fail:
DBG(UPDATE, ul_debugobj(upd, "act file failed [rc=%d]", rc));
mnt_unlock_file(upd->lock);
unlink(upd->act_filename);
- close(upd->act_fd);
+ if (upd->act_fd >= 0)
+ close(upd->act_fd);
upd->act_fd = -1;
return rc;
}
--
2.43.0

View File

@ -0,0 +1,106 @@
From a2a2e7129a418693bfe63bf35fc5d4ea38210f58 Mon Sep 17 00:00:00 2001
From: Karel Zak <kzak@redhat.com>
Date: Thu, 8 Feb 2024 10:36:08 +0100
Subject: lscpu: update tests, follow max freq for scaling
Addresses: https://issues.redhat.com/browse/RHEL-12783
Signed-off-by: Karel Zak <kzak@redhat.com>
---
sys-utils/lscpu-topology.c | 3 +++
tests/expected/lscpu/lscpu-armv7 | 1 +
tests/expected/lscpu/lscpu-vbox-win | 1 +
tests/expected/lscpu/lscpu-vmware_fpe | 1 +
tests/expected/lscpu/lscpu-x86_64-64cpu | 1 +
tests/expected/lscpu/lscpu-x86_64-dell_e4310 | 1 +
tests/expected/lscpu/lscpu-x86_64-epyc_7451 | 1 +
7 files changed, 9 insertions(+)
diff --git a/sys-utils/lscpu-topology.c b/sys-utils/lscpu-topology.c
index fe4da7cd5..23021df72 100644
--- a/sys-utils/lscpu-topology.c
+++ b/sys-utils/lscpu-topology.c
@@ -561,6 +561,9 @@ static int read_mhz(struct lscpu_cxt *cxt, struct lscpu_cpu *cpu)
if (ul_path_readf_s32(sys, &mhz, "cpu%d/cpufreq/scaling_cur_freq", num) == 0)
cpu->mhz_cur_freq = (float) mhz / 1000;
+ if (cpu->mhz_cur_freq > cpu->mhz_max_freq)
+ cpu->mhz_cur_freq = cpu->mhz_max_freq;
+
if (cpu->type && (cpu->mhz_min_freq || cpu->mhz_max_freq))
cpu->type->has_freq = 1;
diff --git a/tests/expected/lscpu/lscpu-armv7 b/tests/expected/lscpu/lscpu-armv7
index 7f1c726c1..27deb8099 100644
--- a/tests/expected/lscpu/lscpu-armv7
+++ b/tests/expected/lscpu/lscpu-armv7
@@ -7,6 +7,7 @@ Thread(s) per core: 1
Core(s) per socket: 2
Socket(s): 1
Stepping: r0p4
+CPU(s) scaling MHz: 12%
CPU max MHz: 1700.0000
CPU min MHz: 200.0000
BogoMIPS: 1694.10
diff --git a/tests/expected/lscpu/lscpu-vbox-win b/tests/expected/lscpu/lscpu-vbox-win
index ab8a25c2c..bc0ed4cb6 100644
--- a/tests/expected/lscpu/lscpu-vbox-win
+++ b/tests/expected/lscpu/lscpu-vbox-win
@@ -10,6 +10,7 @@ Thread(s) per core: 1
Core(s) per socket: 2
Socket(s): 1
Stepping: 9
+CPU(s) scaling MHz: 42%
CPU max MHz: 3800.0000
CPU min MHz: 1600.0000
BogoMIPS: 3355.62
diff --git a/tests/expected/lscpu/lscpu-vmware_fpe b/tests/expected/lscpu/lscpu-vmware_fpe
index 363bdd931..80a51b1ae 100644
--- a/tests/expected/lscpu/lscpu-vmware_fpe
+++ b/tests/expected/lscpu/lscpu-vmware_fpe
@@ -11,6 +11,7 @@ Core(s) per socket: 4
Socket(s): 2
Stepping: 0
Frequency boost: enabled
+CPU(s) scaling MHz: 52%
CPU max MHz: 3200.0000
CPU min MHz: 1400.0000
BogoMIPS: 6399.69
diff --git a/tests/expected/lscpu/lscpu-x86_64-64cpu b/tests/expected/lscpu/lscpu-x86_64-64cpu
index cd84ad46a..b5b6c85c3 100644
--- a/tests/expected/lscpu/lscpu-x86_64-64cpu
+++ b/tests/expected/lscpu/lscpu-x86_64-64cpu
@@ -10,6 +10,7 @@ Thread(s) per core: 2
Core(s) per socket: 8
Socket(s): 4
Stepping: 6
+CPU(s) scaling MHz: 54%
CPU max MHz: 1996.0000
CPU min MHz: 1064.0000
BogoMIPS: 3990.31
diff --git a/tests/expected/lscpu/lscpu-x86_64-dell_e4310 b/tests/expected/lscpu/lscpu-x86_64-dell_e4310
index a0a9962c7..f7f0291c9 100644
--- a/tests/expected/lscpu/lscpu-x86_64-dell_e4310
+++ b/tests/expected/lscpu/lscpu-x86_64-dell_e4310
@@ -10,6 +10,7 @@ Thread(s) per core: 2
Core(s) per socket: 2
Socket(s): 1
Stepping: 5
+CPU(s) scaling MHz: 59%
CPU max MHz: 2667.0000
CPU min MHz: 1199.0000
BogoMIPS: 5319.92
diff --git a/tests/expected/lscpu/lscpu-x86_64-epyc_7451 b/tests/expected/lscpu/lscpu-x86_64-epyc_7451
index 6e5085e84..335f391b5 100644
--- a/tests/expected/lscpu/lscpu-x86_64-epyc_7451
+++ b/tests/expected/lscpu/lscpu-x86_64-epyc_7451
@@ -11,6 +11,7 @@ Core(s) per socket: 24
Socket(s): 2
Stepping: 2
Frequency boost: enabled
+CPU(s) scaling MHz: 100%
CPU max MHz: 2300.0000
CPU min MHz: 1200.0000
BogoMIPS: 4590.83
--
2.43.0

View File

@ -2,7 +2,7 @@
Summary: A collection of basic system utilities
Name: util-linux
Version: 2.37.4
Release: 15%{?dist}
Release: 18%{?dist}
License: GPLv2 and GPLv2+ and LGPLv2+ and BSD with advertising and Public Domain
URL: http://en.wikipedia.org/wiki/Util-linux
@ -189,6 +189,36 @@ Patch54: 0054-sfdisk-add-hint-about-duplicate-UUIDs-when-use-dump.patch
# 2180414 - Backport hint about systemd daemon-reload
Patch55: 0055-tests-don-t-write-mount-hint-to-terminal.patch
### RHEL-9.4.0
#
# RHEL-16048 - uninitialized memory in SCM_CREDENTIALS in logger(1)
Patch56: 0056-logger-initialize-socket-credentials-contol-union.patch
# RHEL-21257 - logger sending process start time not current time with log messages
Patch57: 0057-logger-always-update-header-when-read-from-stdin.patch
# RHEL-16071 - issues in libblkid
Patch58: 0058-libblkid-hfs-fix-label-use-fuzzing.patch
Patch59: 0059-libblkid-bsd-fix-buffer-pointer-use-fuzzing.patch
Patch60: 0060-libblkid-mac-make-sure-block-size-is-large-enough-fu.patch
Patch61: 0061-libblkid-probe-fix-size-and-offset-overflows-fuzzing.patch
# RHEL-12783 - lscpu -e doesn't show the current real frequency value
Patch62: 0062-lscpu-add-SCALMHZ-and-CPU-scaling-MHz.patch
Patch63: 0063-lscpu-read-MHZ-from-sys-.-cpufreq-scaling_cur_freq.patch
Patch64: 0064-lscpu-use-MHZ-as-number-to-be-locale-sensitive.patch
Patch65: 0065-lscpu-use-locale-independent-strtod-when-read-from-k.patch
# RHEL-14612 - Userspace mount options are not preserved for NFS
Patch66: 0066-libmount-add-private-mnt_optstr_get_missing.patch
Patch67: 0067-libmount-add-missing-utab-options-after-helper-call.patch
Patch68: 0068-libmount-add-mnt_context_within_helper-wrapper.patch
Patch69: 0069-libmount-introduce-run-mount-utab.event.patch
Patch70: 0070-libmount-don-t-assume-errno-after-failed-asprintf.patch
Patch71: 0071-libmount-introduce-reference-counting-for-libmnt_loc.patch
Patch72: 0072-libmount-cleanup-locking-in-table-update-code.patch
Patch73: 0073-libmount-add-utab.act-file.patch
Patch74: 0074-libmount-ignore-unwanted-kernel-events-in-monitor.patch
Patch75: 0075-libmount-improve-act-file-close.patch
# RHEL-12783 - lscpu: update tests, follow max freq for scaling
Patch76: 0076-lscpu-update-tests-follow-max-freq-for-scaling.patch
%description
The util-linux package contains a large variety of low-level system
@ -1023,6 +1053,19 @@ fi
%{_libdir}/python*/site-packages/libmount/
%changelog
* Thu Feb 08 2024 Karel Zak <kzak@redhat.com> 2.37.4-18
- lscpu: another tests update (RHEL-12783)
* Thu Feb 08 2024 Karel Zak <kzak@redhat.com> 2.37.4-17
- lscpu: update tests, follow max freq for scaling (RHEL-12783)
* Wed Feb 07 2024 Karel Zak <kzak@redhat.com> 2.37.4-16
- fix RHEL-16048 - uninitialized memory in SCM_CREDENTIALS in logger(1)
- fix RHEL-21257 - logger sending process start time not current time with log messages
- fix RHEL-16071 - issues in libblkid
- fix RHEL-12783 - lscpu -e doesn't show the current real frequency value
- fix RHEL-14612 - Userspace mount options are not preserved for NFS
* Thu Aug 24 2023 Karel Zak <kzak@redhat.com> 2.37.4-15
- fix typo in patch for #2133396