diff --git a/0056-logger-initialize-socket-credentials-contol-union.patch b/0056-logger-initialize-socket-credentials-contol-union.patch new file mode 100644 index 0000000..0873bd4 --- /dev/null +++ b/0056-logger-initialize-socket-credentials-contol-union.patch @@ -0,0 +1,29 @@ +From 57405630f51d256c87ecfb7271b4a297bb931d6e Mon Sep 17 00:00:00 2001 +From: Karel Zak +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 +--- + 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 + diff --git a/0057-logger-always-update-header-when-read-from-stdin.patch b/0057-logger-always-update-header-when-read-from-stdin.patch new file mode 100644 index 0000000..0aef285 --- /dev/null +++ b/0057-logger-always-update-header-when-read-from-stdin.patch @@ -0,0 +1,101 @@ +From 735d815603ac1f8575bddf92d37eb60fcd6d0766 Mon Sep 17 00:00:00 2001 +From: Karel Zak +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 +--- + 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 = ""; +- +- 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 reopens stdin making the below + * function to be used for file inputs. */ + logger_stdin(&ctl); ++ + logger_close(&ctl); + return EXIT_SUCCESS; + } +-- +2.43.0 + diff --git a/0058-libblkid-hfs-fix-label-use-fuzzing.patch b/0058-libblkid-hfs-fix-label-use-fuzzing.patch new file mode 100644 index 0000000..a64d391 --- /dev/null +++ b/0058-libblkid-hfs-fix-label-use-fuzzing.patch @@ -0,0 +1,32 @@ +From f7b0194f9858d0248399ada65e77540f74d74da7 Mon Sep 17 00:00:00 2001 +From: Karel Zak +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 +Signed-off-by: Karel Zak +--- + 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 + diff --git a/0059-libblkid-bsd-fix-buffer-pointer-use-fuzzing.patch b/0059-libblkid-bsd-fix-buffer-pointer-use-fuzzing.patch new file mode 100644 index 0000000..fbec6ca --- /dev/null +++ b/0059-libblkid-bsd-fix-buffer-pointer-use-fuzzing.patch @@ -0,0 +1,29 @@ +From c7ce4cca01425123ef93cb6b89b0a0fe76b2ec7a Mon Sep 17 00:00:00 2001 +From: Karel Zak +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 +Signed-off-by: Karel Zak +--- + 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 + diff --git a/0060-libblkid-mac-make-sure-block-size-is-large-enough-fu.patch b/0060-libblkid-mac-make-sure-block-size-is-large-enough-fu.patch new file mode 100644 index 0000000..a4c8372 --- /dev/null +++ b/0060-libblkid-mac-make-sure-block-size-is-large-enough-fu.patch @@ -0,0 +1,29 @@ +From 452dbbbc7b430a51790c23a24135868ae7697db6 Mon Sep 17 00:00:00 2001 +From: Karel Zak +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 +Signed-off-by: Karel Zak +--- + 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 + diff --git a/0061-libblkid-probe-fix-size-and-offset-overflows-fuzzing.patch b/0061-libblkid-probe-fix-size-and-offset-overflows-fuzzing.patch new file mode 100644 index 0000000..e06735c --- /dev/null +++ b/0061-libblkid-probe-fix-size-and-offset-overflows-fuzzing.patch @@ -0,0 +1,56 @@ +From 2fcbf867f00888216f7c4f57161b083ebdc8a836 Mon Sep 17 00:00:00 2001 +From: Karel Zak +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 +Signed-off-by: Karel Zak +--- + 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 + diff --git a/0062-lscpu-add-SCALMHZ-and-CPU-scaling-MHz.patch b/0062-lscpu-add-SCALMHZ-and-CPU-scaling-MHz.patch new file mode 100644 index 0000000..338639f --- /dev/null +++ b/0062-lscpu-add-SCALMHZ-and-CPU-scaling-MHz.patch @@ -0,0 +1,173 @@ +From 4559d65f2a00d57f7fa21339370bb93d89a69c46 Mon Sep 17 00:00:00 2001 +From: Karel Zak +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 +--- + 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 + diff --git a/0063-lscpu-read-MHZ-from-sys-.-cpufreq-scaling_cur_freq.patch b/0063-lscpu-read-MHZ-from-sys-.-cpufreq-scaling_cur_freq.patch new file mode 100644 index 0000000..1a2b105 --- /dev/null +++ b/0063-lscpu-read-MHZ-from-sys-.-cpufreq-scaling_cur_freq.patch @@ -0,0 +1,44 @@ +From 259178cd356109c861bf41ec32cea905faeabbca Mon Sep 17 00:00:00 2001 +From: Karel Zak +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 +--- + 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 + diff --git a/0064-lscpu-use-MHZ-as-number-to-be-locale-sensitive.patch b/0064-lscpu-use-MHZ-as-number-to-be-locale-sensitive.patch new file mode 100644 index 0000000..145d562 --- /dev/null +++ b/0064-lscpu-use-MHZ-as-number-to-be-locale-sensitive.patch @@ -0,0 +1,31 @@ +From 7049ee572ded1f139c83250c7c57c7fbfa89b658 Mon Sep 17 00:00:00 2001 +From: Karel Zak +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 +--- + 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 + diff --git a/0065-lscpu-use-locale-independent-strtod-when-read-from-k.patch b/0065-lscpu-use-locale-independent-strtod-when-read-from-k.patch new file mode 100644 index 0000000..16bf3b9 --- /dev/null +++ b/0065-lscpu-use-locale-independent-strtod-when-read-from-k.patch @@ -0,0 +1,59 @@ +From ec4cf328499dbcd8f51e2501076a0799b156d580 Mon Sep 17 00:00:00 2001 +From: Karel Zak +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 +--- + 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 + #endif + ++#include + #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 " : " + */ + 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 + diff --git a/0066-libmount-add-private-mnt_optstr_get_missing.patch b/0066-libmount-add-private-mnt_optstr_get_missing.patch new file mode 100644 index 0000000..13d354f --- /dev/null +++ b/0066-libmount-add-private-mnt_optstr_get_missing.patch @@ -0,0 +1,227 @@ +From c7abf1c87c44c54c16758e079dc3528a13d8e177 Mon Sep 17 00:00:00 2001 +From: Karel Zak +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 +--- + 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," [] prepend value to optstr" }, + { "--set", test_set, " [] (un)set value" }, + { "--get", test_get, " search name in optstr" }, ++ { "--missing",test_missing," what from wanted is missing" }, + { "--remove", test_remove, " remove name in optstr" }, + { "--dedup", test_dedup, " deduplicate name in optstr" }, + { "--split", test_split, " split into FS, VFS and userspace" }, +-- +2.43.0 + diff --git a/0067-libmount-add-missing-utab-options-after-helper-call.patch b/0067-libmount-add-missing-utab-options-after-helper-call.patch new file mode 100644 index 0000000..c92a674 --- /dev/null +++ b/0067-libmount-add-missing-utab-options-after-helper-call.patch @@ -0,0 +1,188 @@ +From bc5aaf0e8b9105e5abd6aa6ff28294a39f5822bc Mon Sep 17 00:00:00 2001 +From: Karel Zak +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. 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 +--- + 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. ++ * 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 + diff --git a/0068-libmount-add-mnt_context_within_helper-wrapper.patch b/0068-libmount-add-mnt_context_within_helper-wrapper.patch new file mode 100644 index 0000000..bc702fb --- /dev/null +++ b/0068-libmount-add-mnt_context_within_helper-wrapper.patch @@ -0,0 +1,69 @@ +From faa1764ca23f587fb7fc995a4b2bdf48c5c80147 Mon Sep 17 00:00:00 2001 +From: Karel Zak +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 +--- + 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. 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 + diff --git a/0069-libmount-introduce-run-mount-utab.event.patch b/0069-libmount-introduce-run-mount-utab.event.patch new file mode 100644 index 0000000..a243f5d --- /dev/null +++ b/0069-libmount-introduce-run-mount-utab.event.patch @@ -0,0 +1,145 @@ +From dfdd500a339804075900bd1af42e433cf8d8f632 Mon Sep 17 00:00:00 2001 +From: Karel Zak +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. 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 +--- + 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 + diff --git a/0070-libmount-don-t-assume-errno-after-failed-asprintf.patch b/0070-libmount-don-t-assume-errno-after-failed-asprintf.patch new file mode 100644 index 0000000..40b403d --- /dev/null +++ b/0070-libmount-don-t-assume-errno-after-failed-asprintf.patch @@ -0,0 +1,60 @@ +From 6a25b1d1d819bc215bff2ce7677a1976fca9d55a Mon Sep 17 00:00:00 2001 +From: Karel Zak +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 +Signed-off-by: Karel Zak +--- + 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 + diff --git a/0071-libmount-introduce-reference-counting-for-libmnt_loc.patch b/0071-libmount-introduce-reference-counting-for-libmnt_loc.patch new file mode 100644 index 0000000..02103a8 --- /dev/null +++ b/0071-libmount-introduce-reference-counting-for-libmnt_loc.patch @@ -0,0 +1,174 @@ +From 2ae4cd64f0bd535973fa3824c42e66c7e80dc09c Mon Sep 17 00:00:00 2001 +From: Karel Zak +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 +--- + 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 + +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~.) */ + 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 + diff --git a/0072-libmount-cleanup-locking-in-table-update-code.patch b/0072-libmount-cleanup-locking-in-table-update-code.patch new file mode 100644 index 0000000..68e133f --- /dev/null +++ b/0072-libmount-cleanup-locking-in-table-update-code.patch @@ -0,0 +1,352 @@ +From 317add745924e5a4ad186691eede19d5a7c5eb10 Mon Sep 17 00:00:00 2001 +From: Karel Zak +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 +--- + 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 + diff --git a/0073-libmount-add-utab.act-file.patch b/0073-libmount-add-utab.act-file.patch new file mode 100644 index 0000000..a087be7 --- /dev/null +++ b/0073-libmount-add-utab.act-file.patch @@ -0,0 +1,215 @@ +From 2e22136c0ef7fd5744460d783ef570525df42337 Mon Sep 17 00:00:00 2001 +From: Karel Zak +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 +--- + 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 + diff --git a/0074-libmount-ignore-unwanted-kernel-events-in-monitor.patch b/0074-libmount-ignore-unwanted-kernel-events-in-monitor.patch new file mode 100644 index 0000000..79b40cc --- /dev/null +++ b/0074-libmount-ignore-unwanted-kernel-events-in-monitor.patch @@ -0,0 +1,180 @@ +From e8de2e75d712dd9a750bde130b4367546b46a0bd Mon Sep 17 00:00:00 2001 +From: Karel Zak +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 +--- + 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 + +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, " monitor in epoll" }, +- { "--epoll-clean", test_epoll_cleanup, " monitor in epoll and clean events" }, +- { "--wait", test_wait, " monitor wait function" }, ++ { "--epoll", test_epoll, " monitor in epoll" }, ++ { "--epoll-clean", test_epoll_cleanup, " monitor in epoll and clean events" }, ++ { "--wait", test_wait, " monitor wait function" }, + { NULL } + }; + +-- +2.43.0 + diff --git a/0075-libmount-improve-act-file-close.patch b/0075-libmount-improve-act-file-close.patch new file mode 100644 index 0000000..6416185 --- /dev/null +++ b/0075-libmount-improve-act-file-close.patch @@ -0,0 +1,29 @@ +From be0d06e3f382d8ddcf7b870d58ed1cc9576e065a Mon Sep 17 00:00:00 2001 +From: Karel Zak +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 +--- + 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 + diff --git a/util-linux.spec b/util-linux.spec index 3cbf754..1e1ceff 100644 --- a/util-linux.spec +++ b/util-linux.spec @@ -2,7 +2,7 @@ Summary: A collection of basic system utilities Name: util-linux Version: 2.37.4 -Release: 15%{?dist} +Release: 16%{?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,34 @@ 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 + %description The util-linux package contains a large variety of low-level system @@ -1023,6 +1051,13 @@ fi %{_libdir}/python*/site-packages/libmount/ %changelog +* Wed Feb 07 2024 Karel Zak 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 2.37.4-15 - fix typo in patch for #2133396