diff --git a/SOURCES/0037-fstrim-don-t-trigger-autofs.patch b/SOURCES/0037-fstrim-don-t-trigger-autofs.patch new file mode 100644 index 0000000..81ae76a --- /dev/null +++ b/SOURCES/0037-fstrim-don-t-trigger-autofs.patch @@ -0,0 +1,93 @@ +From 07ed253a49cbe80c15d43ed3800206f99d15b43e Mon Sep 17 00:00:00 2001 +From: Karel Zak +Date: Mon, 4 Oct 2021 11:14:01 +0200 +Subject: fstrim: don't trigger autofs + +- ignore read-only entries +- ignore autofs entries (for example from /proc/self/mountinfo) +- ignore autofs mountpoints where automounter has not been triggered yet + +Fixes: https://github.com/karelzak/util-linux/issues/1463 +Signed-off-by: Karel Zak +Addresses: https://bugzilla.redhat.com/show_bug.cgi?id=2165981 +--- + sys-utils/fstrim.8.adoc | 2 +- + sys-utils/fstrim.c | 28 +++++++++++++++++++++++++++- + 2 files changed, 28 insertions(+), 2 deletions(-) + +diff --git a/sys-utils/fstrim.8.adoc b/sys-utils/fstrim.8.adoc +index 66671c293..d2f3b05be 100644 +--- a/sys-utils/fstrim.8.adoc ++++ b/sys-utils/fstrim.8.adoc +@@ -29,7 +29,7 @@ Running *fstrim* frequently, or even using *mount -o discard*, might negatively + The _offset_, _length_, and _minimum-size_ arguments may be followed by the multiplicative suffixes KiB (=1024), MiB (=1024*1024), and so on for GiB, TiB, PiB, EiB, ZiB and YiB (the "iB" is optional, e.g., "K" has the same meaning as "KiB") or the suffixes KB (=1000), MB (=1000*1000), and so on for GB, TB, PB, EB, ZB and YB. + + *-A, --fstab*:: +-Trim all mounted filesystems mentioned in _/etc/fstab_ on devices that support the discard operation. The root filesystem is determined from kernel command line if missing in the file. The other supplied options, like *--offset*, *--length* and *--minimum*, are applied to all these devices. Errors from filesystems that do not support the discard operation, read-only devices and read-only filesystems are silently ignored. ++Trim all mounted filesystems mentioned in _/etc/fstab_ on devices that support the discard operation. The root filesystem is determined from kernel command line if missing in the file. The other supplied options, like *--offset*, *--length* and *--minimum*, are applied to all these devices. Errors from filesystems that do not support the discard operation, read-only devices, autofs and read-only filesystems are silently ignored. + + *-a, --all*:: + Trim all mounted filesystems on devices that support the discard operation. The other supplied options, like *--offset*, *--length* and *--minimum*, are applied to all these devices. Errors from filesystems that do not support the discard operation, read-only devices and read-only filesystems are silently ignored. +diff --git a/sys-utils/fstrim.c b/sys-utils/fstrim.c +index d2aec4f71..ea787f42c 100644 +--- a/sys-utils/fstrim.c ++++ b/sys-utils/fstrim.c +@@ -35,6 +35,7 @@ + + #include + #include ++#include + #include + + #include "nls.h" +@@ -45,6 +46,7 @@ + #include "pathnames.h" + #include "sysfs.h" + #include "optutils.h" ++#include "statfs_magic.h" + + #include + +@@ -207,6 +209,30 @@ fail: + return 1; + } + ++static int is_unwanted_fs(struct libmnt_fs *fs, const char *tgt) ++{ ++ struct statfs vfs; ++ int fd, rc; ++ ++ if (mnt_fs_is_pseudofs(fs)) ++ return 1; ++ if (mnt_fs_is_netfs(fs)) ++ return 1; ++ if (mnt_fs_is_swaparea(fs)) ++ return 1; ++ if (mnt_fs_match_fstype(fs, "autofs")) ++ return 1; ++ if (mnt_fs_match_options(fs, "ro")) ++ return 1; ++ ++ fd = open(tgt, O_PATH); ++ if (!fd) ++ return 1; ++ rc = fstatfs(fd, &vfs) != 0 || vfs.f_type == STATFS_AUTOFS_MAGIC; ++ close(fd); ++ ++ return rc; ++} + + static int uniq_fs_target_cmp( + struct libmnt_table *tb __attribute__((__unused__)), +@@ -292,7 +318,7 @@ static int fstrim_all_from_file(struct fstrim_control *ctl, const char *filename + const char *src = mnt_fs_get_srcpath(fs), + *tgt = mnt_fs_get_target(fs); + +- if (!tgt || mnt_fs_is_pseudofs(fs) || mnt_fs_is_netfs(fs)) { ++ if (!tgt || is_unwanted_fs(fs, tgt)) { + mnt_table_remove_fs(tab, fs); + continue; + } +-- +2.39.1 + diff --git a/SOURCES/0038-fstrim-fix-typo.patch b/SOURCES/0038-fstrim-fix-typo.patch new file mode 100644 index 0000000..a23d034 --- /dev/null +++ b/SOURCES/0038-fstrim-fix-typo.patch @@ -0,0 +1,28 @@ +From 825f9a8eb7800c572d4ded17dd202249312e3240 Mon Sep 17 00:00:00 2001 +From: Karel Zak +Date: Mon, 4 Oct 2021 11:14:01 +0200 +Subject: fstrim: fix typo + +Addresses: https://github.com/karelzak/util-linux/issues/1463 +Signed-off-by: Karel Zak +Addresses: https://bugzilla.redhat.com/show_bug.cgi?id=2165981 +--- + sys-utils/fstrim.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/sys-utils/fstrim.c b/sys-utils/fstrim.c +index ea787f42c..88397f0ec 100644 +--- a/sys-utils/fstrim.c ++++ b/sys-utils/fstrim.c +@@ -226,7 +226,7 @@ static int is_unwanted_fs(struct libmnt_fs *fs, const char *tgt) + return 1; + + fd = open(tgt, O_PATH); +- if (!fd) ++ if (fd < 0) + return 1; + rc = fstatfs(fd, &vfs) != 0 || vfs.f_type == STATFS_AUTOFS_MAGIC; + close(fd); +-- +2.39.1 + diff --git a/SOURCES/0039-fstrim-Remove-all-skipped-entries-before-de-duplicat.patch b/SOURCES/0039-fstrim-Remove-all-skipped-entries-before-de-duplicat.patch new file mode 100644 index 0000000..cc0cd95 --- /dev/null +++ b/SOURCES/0039-fstrim-Remove-all-skipped-entries-before-de-duplicat.patch @@ -0,0 +1,114 @@ +From c76c1e5d7d3b043549f69c8dc8d6b878b1db0231 Mon Sep 17 00:00:00 2001 +From: Scott Shambarger +Date: Thu, 12 May 2022 16:27:26 -0700 +Subject: fstrim: Remove all skipped entries before de-duplication + +When processing fstab entries, de-duplication is performed based on the +source before all tests on the target have been checked, resulting in +some entries being skipped when a removed duplicate with a different +target would not have been. + +The fix is to move all the target checks before the source +de-duplication. + +Addresses: #1686 +Signed-off-by: Scott Shambarger +Addresses: https://bugzilla.redhat.com/show_bug.cgi?id=2165981 +--- + sys-utils/fstrim.c | 53 ++++++++++++++++++++++++++-------------------- + 1 file changed, 30 insertions(+), 23 deletions(-) + +diff --git a/sys-utils/fstrim.c b/sys-utils/fstrim.c +index 88397f0ec..0b05e590e 100644 +--- a/sys-utils/fstrim.c ++++ b/sys-utils/fstrim.c +@@ -230,8 +230,17 @@ static int is_unwanted_fs(struct libmnt_fs *fs, const char *tgt) + return 1; + rc = fstatfs(fd, &vfs) != 0 || vfs.f_type == STATFS_AUTOFS_MAGIC; + close(fd); ++ if (rc) ++ return 1; + +- return rc; ++ /* FITRIM on read-only filesystem can fail, and it can fail */ ++ if (access(tgt, W_OK) != 0) { ++ if (errno == EROFS) ++ return 1; ++ if (errno == EACCES) ++ return 1; ++ } ++ return 0; + } + + static int uniq_fs_target_cmp( +@@ -317,6 +326,8 @@ static int fstrim_all_from_file(struct fstrim_control *ctl, const char *filename + while (mnt_table_next_fs(tab, itr, &fs) == 0) { + const char *src = mnt_fs_get_srcpath(fs), + *tgt = mnt_fs_get_target(fs); ++ char *path; ++ int rc = 1; + + if (!tgt || is_unwanted_fs(fs, tgt)) { + mnt_table_remove_fs(tab, fs); +@@ -339,19 +350,6 @@ static int fstrim_all_from_file(struct fstrim_control *ctl, const char *filename + mnt_table_remove_fs(tab, fs); + continue; + } +- } +- +- /* de-duplicate by source */ +- mnt_table_uniq_fs(tab, MNT_UNIQ_FORWARD, uniq_fs_source_cmp); +- +- mnt_reset_iter(itr, MNT_ITER_BACKWARD); +- +- /* Do FITRIM */ +- while (mnt_table_next_fs(tab, itr, &fs) == 0) { +- const char *src = mnt_fs_get_srcpath(fs), +- *tgt = mnt_fs_get_target(fs); +- char *path; +- int rc = 1; + + /* Is it really accessible mountpoint? Not all mountpoints are + * accessible (maybe over mounted by another filesystem) */ +@@ -359,20 +357,29 @@ static int fstrim_all_from_file(struct fstrim_control *ctl, const char *filename + if (path && streq_paths(path, tgt)) + rc = 0; + free(path); +- if (rc) ++ if (rc) { ++ mnt_table_remove_fs(tab, fs); + continue; /* overlaying mount */ +- +- /* FITRIM on read-only filesystem can fail, and it can fail */ +- if (access(tgt, W_OK) != 0) { +- if (errno == EROFS) +- continue; +- if (errno == EACCES) +- continue; + } + + if (!is_directory(tgt, 1) || +- !has_discard(src, &wholedisk)) ++ !has_discard(src, &wholedisk)) { ++ mnt_table_remove_fs(tab, fs); + continue; ++ } ++ } ++ ++ /* de-duplicate by source */ ++ mnt_table_uniq_fs(tab, MNT_UNIQ_FORWARD, uniq_fs_source_cmp); ++ ++ mnt_reset_iter(itr, MNT_ITER_BACKWARD); ++ ++ /* Do FITRIM */ ++ while (mnt_table_next_fs(tab, itr, &fs) == 0) { ++ const char *src = mnt_fs_get_srcpath(fs), ++ *tgt = mnt_fs_get_target(fs); ++ int rc; ++ + cnt++; + + /* +-- +2.39.1 + diff --git a/SOURCES/0040-libuuid-Implement-continuous-clock-handling-for-time.patch b/SOURCES/0040-libuuid-Implement-continuous-clock-handling-for-time.patch new file mode 100644 index 0000000..cd62656 --- /dev/null +++ b/SOURCES/0040-libuuid-Implement-continuous-clock-handling-for-time.patch @@ -0,0 +1,339 @@ +From a3b3df8d0891ff83b61f62020652798d365299c0 Mon Sep 17 00:00:00 2001 +From: Michael Trapp +Date: Mon, 20 Jun 2022 17:10:36 +0200 +Subject: libuuid: Implement continuous clock handling for time based UUIDs + +In a uuidd setup, the daemon is a singleton and can maintain it's own +resources for time based UUID generation. This requires a dedicated +'clock sequence range' but does not need any further lock/update of +the LIBUUID_CLOCK_FILE from uuidd. The range of available clock values +is extended by a continuous handling of the clock updates - instead of +updating the value to the current timestamp, it is incremented by +the number of requested UUIDs. + +Upstream: http://github.com/util-linux/util-linux/commit/3cfba7d39b66eff4307218fefd8bb34bb1621f83 +Addresses: https://bugzilla.redhat.com/show_bug.cgi?id=2141970 +Signed-off-by: Karel Zak +--- + libuuid/src/gen_uuid.c | 91 ++++++++++++++++++++++++++++++++++++++--- + libuuid/src/libuuid.sym | 1 + + libuuid/src/uuidd.h | 1 + + misc-utils/uuidd.8.adoc | 3 ++ + misc-utils/uuidd.c | 54 +++++++++++++++++++++--- + 5 files changed, 140 insertions(+), 10 deletions(-) + +diff --git a/libuuid/src/gen_uuid.c b/libuuid/src/gen_uuid.c +index d353fa1a0..ac682a1d8 100644 +--- a/libuuid/src/gen_uuid.c ++++ b/libuuid/src/gen_uuid.c +@@ -209,6 +209,8 @@ static int get_node_id(unsigned char *node_id) + + /* Assume that the gettimeofday() has microsecond granularity */ + #define MAX_ADJUSTMENT 10 ++/* Reserve a clock_seq value for the 'continuous clock' implementation */ ++#define CLOCK_SEQ_CONT 0 + + /* + * Get clock from global sequence clock counter. +@@ -275,8 +277,10 @@ static int get_clock(uint32_t *clock_high, uint32_t *clock_low, + } + + if ((last.tv_sec == 0) && (last.tv_usec == 0)) { +- ul_random_get_bytes(&clock_seq, sizeof(clock_seq)); +- clock_seq &= 0x3FFF; ++ do { ++ ul_random_get_bytes(&clock_seq, sizeof(clock_seq)); ++ clock_seq &= 0x3FFF; ++ } while (clock_seq == CLOCK_SEQ_CONT); + gettimeofday(&last, NULL); + last.tv_sec--; + } +@@ -286,7 +290,9 @@ try_again: + if ((tv.tv_sec < last.tv_sec) || + ((tv.tv_sec == last.tv_sec) && + (tv.tv_usec < last.tv_usec))) { +- clock_seq = (clock_seq+1) & 0x3FFF; ++ do { ++ clock_seq = (clock_seq+1) & 0x3FFF; ++ } while (clock_seq == CLOCK_SEQ_CONT); + adjustment = 0; + last = tv; + } else if ((tv.tv_sec == last.tv_sec) && +@@ -331,6 +337,64 @@ try_again: + return ret; + } + ++/* ++ * Get current time in 100ns ticks. ++ */ ++static uint64_t get_clock_counter(void) ++{ ++ struct timeval tv; ++ uint64_t clock_reg; ++ ++ gettimeofday(&tv, NULL); ++ clock_reg = tv.tv_usec*10; ++ clock_reg += ((uint64_t) tv.tv_sec) * 10000000ULL; ++ ++ return clock_reg; ++} ++ ++/* ++ * Get continuous clock value. ++ * ++ * Return -1 if there is no further clock counter available, ++ * otherwise return 0. ++ * ++ * This implementation doesn't deliver clock counters based on ++ * the current time because last_clock_reg is only incremented ++ * by the number of requested UUIDs. ++ * max_clock_offset is used to limit the offset of last_clock_reg. ++ */ ++static int get_clock_cont(uint32_t *clock_high, ++ uint32_t *clock_low, ++ int num, ++ uint32_t max_clock_offset) ++{ ++ /* 100ns based time offset according to RFC 4122. 4.1.4. */ ++ const uint64_t reg_offset = (((uint64_t) 0x01B21DD2) << 32) + 0x13814000; ++ static uint64_t last_clock_reg = 0; ++ uint64_t clock_reg; ++ ++ if (last_clock_reg == 0) ++ last_clock_reg = get_clock_counter(); ++ ++ clock_reg = get_clock_counter(); ++ if (max_clock_offset) { ++ uint64_t clock_offset = max_clock_offset * 10000000ULL; ++ if (last_clock_reg < (clock_reg - clock_offset)) ++ last_clock_reg = clock_reg - clock_offset; ++ } ++ ++ clock_reg += MAX_ADJUSTMENT; ++ ++ if ((last_clock_reg + num) >= clock_reg) ++ return -1; ++ ++ *clock_high = (last_clock_reg + reg_offset) >> 32; ++ *clock_low = last_clock_reg + reg_offset; ++ last_clock_reg += num; ++ ++ return 0; ++} ++ + #if defined(HAVE_UUIDD) && defined(HAVE_SYS_UN_H) + + /* +@@ -403,7 +467,7 @@ static int get_uuid_via_daemon(int op __attribute__((__unused__)), + } + #endif + +-int __uuid_generate_time(uuid_t out, int *num) ++static int __uuid_generate_time_internal(uuid_t out, int *num, uint32_t cont_offset) + { + static unsigned char node_id[6]; + static int has_init = 0; +@@ -423,7 +487,14 @@ int __uuid_generate_time(uuid_t out, int *num) + } + has_init = 1; + } +- ret = get_clock(&clock_mid, &uu.time_low, &uu.clock_seq, num); ++ if (cont_offset) { ++ ret = get_clock_cont(&clock_mid, &uu.time_low, *num, cont_offset); ++ uu.clock_seq = CLOCK_SEQ_CONT; ++ if (ret != 0) /* fallback to previous implpementation */ ++ ret = get_clock(&clock_mid, &uu.time_low, &uu.clock_seq, num); ++ } else { ++ ret = get_clock(&clock_mid, &uu.time_low, &uu.clock_seq, num); ++ } + uu.clock_seq |= 0x8000; + uu.time_mid = (uint16_t) clock_mid; + uu.time_hi_and_version = ((clock_mid >> 16) & 0x0FFF) | 0x1000; +@@ -432,6 +503,16 @@ int __uuid_generate_time(uuid_t out, int *num) + return ret; + } + ++int __uuid_generate_time(uuid_t out, int *num) ++{ ++ return __uuid_generate_time_internal(out, num, 0); ++} ++ ++int __uuid_generate_time_cont(uuid_t out, int *num, uint32_t cont_offset) ++{ ++ return __uuid_generate_time_internal(out, num, cont_offset); ++} ++ + /* + * Generate time-based UUID and store it to @out + * +diff --git a/libuuid/src/libuuid.sym b/libuuid/src/libuuid.sym +index 342453368..96372a857 100644 +--- a/libuuid/src/libuuid.sym ++++ b/libuuid/src/libuuid.sym +@@ -60,6 +60,7 @@ global: + UUIDD_PRIVATE { + global: + __uuid_generate_time; ++ __uuid_generate_time_cont; + __uuid_generate_random; + local: + *; +diff --git a/libuuid/src/uuidd.h b/libuuid/src/uuidd.h +index fbe821ff3..f76acc8b2 100644 +--- a/libuuid/src/uuidd.h ++++ b/libuuid/src/uuidd.h +@@ -49,6 +49,7 @@ + #define UUIDD_MAX_OP UUIDD_OP_BULK_RANDOM_UUID + + extern int __uuid_generate_time(uuid_t out, int *num); ++extern int __uuid_generate_time_cont(uuid_t out, int *num, uint32_t cont); + extern int __uuid_generate_random(uuid_t out, int *num); + + #endif /* _UUID_UUID_H */ +diff --git a/misc-utils/uuidd.8.adoc b/misc-utils/uuidd.8.adoc +index 77ee2b3e6..c87125901 100644 +--- a/misc-utils/uuidd.8.adoc ++++ b/misc-utils/uuidd.8.adoc +@@ -24,6 +24,9 @@ The *uuidd* daemon is used by the UUID library to generate universally unique id + + == OPTIONS + ++*-C*, *--cont-clock* _opt_arg_:: ++Activate continuous clock handling for time based UUIDs. *uuidd* could use all possible clock values, beginning with the daemon's start time. The optional argument can be used to set a value for the max_clock_offset. This gurantees, that a clock value of a UUID will always be within the range of the max_clock_offset. '-C' or '--cont-clock' enables the feature with a default max_clock_offset of 2 hours. '-C[hd]' or '--cont-clock=[hd]' enables the feature with a max_clock_offset of NUM seconds. In case of an appended h or d, the NUM value is read in hours or days. The minimum value is 60 seconds, the maximum value is 365 days. ++ + *-d*, *--debug*:: + Run uuidd in debugging mode. This prevents uuidd from running as a daemon. + +diff --git a/misc-utils/uuidd.c b/misc-utils/uuidd.c +index 78a37d2e8..b859ccb8c 100644 +--- a/misc-utils/uuidd.c ++++ b/misc-utils/uuidd.c +@@ -72,6 +72,8 @@ struct uuidd_cxt_t { + const char *cleanup_pidfile; + const char *cleanup_socket; + uint32_t timeout; ++ uint32_t cont_clock_offset; ++ + unsigned int debug: 1, + quiet: 1, + no_fork: 1, +@@ -106,6 +108,8 @@ static void __attribute__((__noreturn__)) usage(void) + fputs(_(" -P, --no-pid do not create pid file\n"), out); + fputs(_(" -F, --no-fork do not daemonize using double-fork\n"), out); + fputs(_(" -S, --socket-activation do not create listening socket\n"), out); ++ fputs(_(" -C, --cont-clock[=[hd]]\n"), out); ++ fputs(_(" activate continuous clock handling\n"), out); + fputs(_(" -d, --debug run in debugging mode\n"), out); + fputs(_(" -q, --quiet turn on quiet mode\n"), out); + fputs(USAGE_SEPARATOR, out); +@@ -438,6 +442,15 @@ static void server_loop(const char *socket_path, const char *pidfile_path, + pfd[POLLFD_SOCKET].fd = s; + pfd[POLLFD_SIGNAL].events = pfd[POLLFD_SOCKET].events = POLLIN | POLLERR | POLLHUP; + ++ num = 1; ++ if (uuidd_cxt->cont_clock_offset) { ++ /* trigger initialization */ ++ (void) __uuid_generate_time_cont(uu, &num, uuidd_cxt->cont_clock_offset); ++ if (uuidd_cxt->debug) ++ fprintf(stderr, _("max_clock_offset = %u sec\n"), ++ uuidd_cxt->cont_clock_offset); ++ } ++ + while (1) { + ret = poll(pfd, ARRAY_SIZE(pfd), + uuidd_cxt->timeout ? +@@ -494,7 +507,8 @@ static void server_loop(const char *socket_path, const char *pidfile_path, + break; + case UUIDD_OP_TIME_UUID: + num = 1; +- if (__uuid_generate_time(uu, &num) < 0 && !uuidd_cxt->quiet) ++ ret = __uuid_generate_time_cont(uu, &num, uuidd_cxt->cont_clock_offset); ++ if (ret < 0 && !uuidd_cxt->quiet) + warnx(_("failed to open/lock clock counter")); + if (uuidd_cxt->debug) { + uuid_unparse(uu, str); +@@ -505,7 +519,8 @@ static void server_loop(const char *socket_path, const char *pidfile_path, + break; + case UUIDD_OP_RANDOM_UUID: + num = 1; +- if (__uuid_generate_time(uu, &num) < 0 && !uuidd_cxt->quiet) ++ ret = __uuid_generate_time_cont(uu, &num, uuidd_cxt->cont_clock_offset); ++ if (ret < 0 && !uuidd_cxt->quiet) + warnx(_("failed to open/lock clock counter")); + if (uuidd_cxt->debug) { + uuid_unparse(uu, str); +@@ -515,7 +530,8 @@ static void server_loop(const char *socket_path, const char *pidfile_path, + reply_len = sizeof(uu); + break; + case UUIDD_OP_BULK_TIME_UUID: +- if (__uuid_generate_time(uu, &num) < 0 && !uuidd_cxt->quiet) ++ ret = __uuid_generate_time_cont(uu, &num, uuidd_cxt->cont_clock_offset); ++ if (ret < 0 && !uuidd_cxt->quiet) + warnx(_("failed to open/lock clock counter")); + if (uuidd_cxt->debug) { + uuid_unparse(uu, str); +@@ -567,6 +583,27 @@ static void __attribute__ ((__noreturn__)) unexpected_size(int size) + errx(EXIT_FAILURE, _("Unexpected reply length from server %d"), size); + } + ++static uint32_t parse_cont_clock(char *arg) ++{ ++ uint32_t min_val = 60, ++ max_val = (3600 * 24 * 365), ++ factor = 1; ++ char *p = &arg[strlen(arg)-1]; ++ ++ if ('h' == *p) { ++ *p = '\0'; ++ factor = 3600; ++ min_val = 1; ++ } ++ if ('d' == *p) { ++ *p = '\0'; ++ factor = 24 * 3600; ++ min_val = 1; ++ } ++ return factor * str2num_or_err(optarg, 10, _("failed to parse --cont-clock/-C"), ++ min_val, max_val / factor); ++} ++ + static void parse_options(int argc, char **argv, struct uuidd_cxt_t *uuidd_cxt, + struct uuidd_options_t *uuidd_opts) + { +@@ -581,6 +618,7 @@ static void parse_options(int argc, char **argv, struct uuidd_cxt_t *uuidd_cxt, + {"no-pid", no_argument, NULL, 'P'}, + {"no-fork", no_argument, NULL, 'F'}, + {"socket-activation", no_argument, NULL, 'S'}, ++ {"cont-clock", optional_argument, NULL, 'C'}, + {"debug", no_argument, NULL, 'd'}, + {"quiet", no_argument, NULL, 'q'}, + {"version", no_argument, NULL, 'V'}, +@@ -596,9 +634,15 @@ static void parse_options(int argc, char **argv, struct uuidd_cxt_t *uuidd_cxt, + int excl_st[ARRAY_SIZE(excl)] = UL_EXCL_STATUS_INIT; + int c; + +- while ((c = getopt_long(argc, argv, "p:s:T:krtn:PFSdqVh", longopts, NULL)) != -1) { ++ while ((c = getopt_long(argc, argv, "p:s:T:krtn:PFSC::dqVh", longopts, NULL)) != -1) { + err_exclusive_options(c, longopts, excl, excl_st); + switch (c) { ++ case 'C': ++ if (optarg != NULL) ++ uuidd_cxt->cont_clock_offset = parse_cont_clock(optarg); ++ else ++ uuidd_cxt->cont_clock_offset = 7200; /* default 2h */ ++ break; + case 'd': + uuidd_cxt->debug = 1; + break; +@@ -673,7 +717,7 @@ int main(int argc, char **argv) + char *cp; + int ret; + +- struct uuidd_cxt_t uuidd_cxt = { .timeout = 0 }; ++ struct uuidd_cxt_t uuidd_cxt = { .timeout = 0, .cont_clock_offset = 0 }; + struct uuidd_options_t uuidd_opts = { .socket_path = UUIDD_SOCKET_PATH }; + + setlocale(LC_ALL, ""); +-- +2.39.1 + diff --git a/SOURCES/0041-libuuid-check-clock-value-from-LIBUUID_CLOCK_FILE.patch b/SOURCES/0041-libuuid-check-clock-value-from-LIBUUID_CLOCK_FILE.patch new file mode 100644 index 0000000..d660b49 --- /dev/null +++ b/SOURCES/0041-libuuid-check-clock-value-from-LIBUUID_CLOCK_FILE.patch @@ -0,0 +1,35 @@ +From cede4c481ba0f8fa4256341a0acca33f826fca4f Mon Sep 17 00:00:00 2001 +From: Michael Trapp +Date: Tue, 2 Aug 2022 14:16:43 +0200 +Subject: libuuid: check clock value from LIBUUID_CLOCK_FILE + +The clock value from the LIBUUID_CLOCK_FILE must be checked in +case of an update of libuuid. If clock==CLOCK_SEQ_CONT it must +be set to a new value. + +Upstream: http://github.com/util-linux/util-linux/commit/5d1424d85ac9e2a1369ee920038825c154ee5443 +Addresses: https://bugzilla.redhat.com/show_bug.cgi?id=2141970 +Signed-off-by: Karel Zak +--- + libuuid/src/gen_uuid.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/libuuid/src/gen_uuid.c b/libuuid/src/gen_uuid.c +index ac682a1d8..f05db467e 100644 +--- a/libuuid/src/gen_uuid.c ++++ b/libuuid/src/gen_uuid.c +@@ -274,6 +274,11 @@ static int get_clock(uint32_t *clock_high, uint32_t *clock_low, + last.tv_usec = tv2; + adjustment = a; + } ++ // reset in case of reserved CLOCK_SEQ_CONT ++ if (clock_seq == CLOCK_SEQ_CONT) { ++ last.tv_sec = 0; ++ last.tv_usec = 0; ++ } + } + + if ((last.tv_sec == 0) && (last.tv_usec == 0)) { +-- +2.39.1 + diff --git a/SOURCES/0042-uuidd-fix-random-UUIDs.patch b/SOURCES/0042-uuidd-fix-random-UUIDs.patch new file mode 100644 index 0000000..5d824fc --- /dev/null +++ b/SOURCES/0042-uuidd-fix-random-UUIDs.patch @@ -0,0 +1,34 @@ +From cae4f3f433e4a308f70103e166c6afad30b59ca7 Mon Sep 17 00:00:00 2001 +From: Karel Zak +Date: Mon, 10 Oct 2022 09:37:51 +0200 +Subject: uuidd: fix random UUIDs + +Commit f27876f introduces copy & past bug and replaces +__uuid_generate_random() with __uuid_generate_time(). + +Fixes: https://github.com/util-linux/util-linux/issues/1837 +Signed-off-by: Karel Zak +Addresses: https://bugzilla.redhat.com/show_bug.cgi?id=2133385 +Upstream: http://github.com/util-linux/util-linux/commit/b408a291d39e9b637f6104eb4e1f8e60816421e2 +--- + misc-utils/uuidd.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +diff --git a/misc-utils/uuidd.c b/misc-utils/uuidd.c +index b859ccb8c..489d6b79a 100644 +--- a/misc-utils/uuidd.c ++++ b/misc-utils/uuidd.c +@@ -519,9 +519,7 @@ static void server_loop(const char *socket_path, const char *pidfile_path, + break; + case UUIDD_OP_RANDOM_UUID: + num = 1; +- ret = __uuid_generate_time_cont(uu, &num, uuidd_cxt->cont_clock_offset); +- if (ret < 0 && !uuidd_cxt->quiet) +- warnx(_("failed to open/lock clock counter")); ++ __uuid_generate_random(uu, &num); + if (uuidd_cxt->debug) { + uuid_unparse(uu, str); + fprintf(stderr, _("Generated random UUID: %s\n"), str); +-- +2.39.1 + diff --git a/SOURCES/0043-agetty-resolve-tty-name-even-if-stdin-is-specified.patch b/SOURCES/0043-agetty-resolve-tty-name-even-if-stdin-is-specified.patch new file mode 100644 index 0000000..57a3749 --- /dev/null +++ b/SOURCES/0043-agetty-resolve-tty-name-even-if-stdin-is-specified.patch @@ -0,0 +1,106 @@ +From b77ac3951932d2ea8bdba2b800380b3e70f8eca2 Mon Sep 17 00:00:00 2001 +From: tamz +Date: Thu, 6 Jan 2022 11:56:58 +0100 +Subject: agetty: resolve tty name even if stdin is specified + +[kzak@redhat.com: - use "const" for options->tty (and friends) + as expected by get_terminal_name()] + +Addresses: https://github.com/util-linux/util-linux/issues/1546 +Signed-off-by: tamz +Signed-off-by: Karel Zak +Addresses: https://bugzilla.redhat.com/show_bug.cgi?id=2156946 +Upstream: http://github.com/util-linux/util-linux/commit/47831cc02ac0d71c335caecef1753f4c8861277c +--- + term-utils/agetty.c | 26 ++++++++++++++++++-------- + 1 file changed, 18 insertions(+), 8 deletions(-) + +diff --git a/term-utils/agetty.c b/term-utils/agetty.c +index 3b3d5101a..e65cbdeaf 100644 +--- a/term-utils/agetty.c ++++ b/term-utils/agetty.c +@@ -186,8 +186,8 @@ struct options { + char *chroot; /* Chroot before the login */ + char *login; /* login program */ + char *logopt; /* options for login program */ +- char *tty; /* name of tty */ +- char *vcline; /* line of virtual console */ ++ const char *tty; /* name of tty */ ++ const char *vcline; /* line of virtual console */ + char *term; /* terminal type */ + char *initstring; /* modem init string */ + char *issue; /* alternative issue file or directory */ +@@ -199,6 +199,7 @@ struct options { + int numspeed; /* number of baud rates to try */ + int clocal; /* CLOCAL_MODE_* */ + int kbmode; /* Keyboard mode if virtual console */ ++ int tty_is_stdin; /* is the tty the standard input stream */ + speed_t speeds[MAX_SPEED]; /* baud rates to be tried */ + }; + +@@ -315,7 +316,7 @@ static void init_special_char(char* arg, struct options *op); + static void parse_args(int argc, char **argv, struct options *op); + static void parse_speeds(struct options *op, char *arg); + static void update_utmp(struct options *op); +-static void open_tty(char *tty, struct termios *tp, struct options *op); ++static void open_tty(const char *tty, struct termios *tp, struct options *op); + static void termio_init(struct options *op, struct termios *tp); + static void reset_vc(const struct options *op, struct termios *tp, int canon); + static void auto_baud(struct termios *tp); +@@ -918,6 +919,15 @@ static void parse_args(int argc, char **argv, struct options *op) + } + } + ++ /* resolve the tty path in case it was provided as stdin */ ++ if (strcmp(op->tty, "-") == 0) { ++ op->tty_is_stdin = 1; ++ int fd = get_terminal_name(NULL, &op->tty, NULL); ++ if (fd < 0) { ++ log_warn(_("could not get terminal name: %d"), fd); ++ } ++ } ++ + /* On virtual console remember the line which is used for */ + if (strncmp(op->tty, "tty", 3) == 0 && + strspn(op->tty + 3, "0123456789") == strlen(op->tty+3)) +@@ -958,8 +968,8 @@ static void update_utmp(struct options *op) + time_t t; + pid_t pid = getpid(); + pid_t sid = getsid(0); +- char *vcline = op->vcline; +- char *line = op->tty; ++ const char *vcline = op->vcline; ++ const char *line = op->tty; + struct utmpx *utp; + + /* +@@ -998,7 +1008,7 @@ static void update_utmp(struct options *op) + str2memcpy(ut.ut_id, vcline, sizeof(ut.ut_id)); + else { + size_t len = strlen(line); +- char * ptr; ++ const char * ptr; + if (len >= sizeof(ut.ut_id)) + ptr = line + len - sizeof(ut.ut_id); + else +@@ -1026,7 +1036,7 @@ static void update_utmp(struct options *op) + #endif /* SYSV_STYLE */ + + /* Set up tty as stdin, stdout & stderr. */ +-static void open_tty(char *tty, struct termios *tp, struct options *op) ++static void open_tty(const char *tty, struct termios *tp, struct options *op) + { + const pid_t pid = getpid(); + int closed = 0; +@@ -1036,7 +1046,7 @@ static void open_tty(char *tty, struct termios *tp, struct options *op) + + /* Set up new standard input, unless we are given an already opened port. */ + +- if (strcmp(tty, "-") != 0) { ++ if (!op->tty_is_stdin) { + char buf[PATH_MAX+1]; + struct group *gr = NULL; + struct stat st; +-- +2.39.1 + diff --git a/SOURCES/0044-last-use-snprintf-rather-than-sprintf.patch b/SOURCES/0044-last-use-snprintf-rather-than-sprintf.patch new file mode 100644 index 0000000..cfd28ae --- /dev/null +++ b/SOURCES/0044-last-use-snprintf-rather-than-sprintf.patch @@ -0,0 +1,112 @@ +From d4a05cc653c9e251a04afa9bd4f5a75777029445 Mon Sep 17 00:00:00 2001 +From: Karel Zak +Date: Thu, 2 Feb 2023 15:46:43 +0100 +Subject: last: use snprintf() rather than sprintf() + +Signed-off-by: Karel Zak +Upstream: http://github.com/util-linux/util-linux/commit/79fb7e18f45e84c6f1a030b5df56cb2bdad26df0 +Upstream: http://github.com/util-linux/util-linux/commit/6cd0043221b31a344db8f5dcb82822a2519a2e74 +Addresses: https://bugzilla.redhat.com/show_bug.cgi?id=2166653 +--- + login-utils/last.c | 38 +++++++++++++++++++------------------- + 1 file changed, 19 insertions(+), 19 deletions(-) + +diff --git a/login-utils/last.c b/login-utils/last.c +index f3272caeb..7f4421c89 100644 +--- a/login-utils/last.c ++++ b/login-utils/last.c +@@ -463,48 +463,48 @@ static int list(const struct last_control *ctl, struct utmpx *p, time_t logout_t + + if (logout_time == currentdate) { + if (ctl->time_fmt > LAST_TIMEFTM_SHORT) { +- sprintf(logouttime, " still running"); ++ snprintf(logouttime, sizeof(logouttime), " still running"); + length[0] = 0; + } else { +- sprintf(logouttime, " still"); +- sprintf(length, "running"); ++ snprintf(logouttime, sizeof(logouttime), " still"); ++ snprintf(length, sizeof(length), "running"); + } + } else if (days) { +- sprintf(length, "(%d+%02d:%02d)", days, abs(hours), abs(mins)); /* hours and mins always shown as positive (w/o minus sign!) even if secs < 0 */ ++ snprintf(length, sizeof(length), "(%d+%02d:%02d)", days, abs(hours), abs(mins)); /* hours and mins always shown as positive (w/o minus sign!) even if secs < 0 */ + } else if (hours) { +- sprintf(length, " (%02d:%02d)", hours, abs(mins)); /* mins always shown as positive (w/o minus sign!) even if secs < 0 */ ++ snprintf(length, sizeof(length), " (%02d:%02d)", hours, abs(mins)); /* mins always shown as positive (w/o minus sign!) even if secs < 0 */ + } else if (secs >= 0) { +- sprintf(length, " (%02d:%02d)", hours, mins); ++ snprintf(length, sizeof(length), " (%02d:%02d)", hours, mins); + } else { +- sprintf(length, " (-00:%02d)", abs(mins)); /* mins always shown as positive (w/o minus sign!) even if secs < 0 */ ++ snprintf(length, sizeof(length), " (-00:%02d)", abs(mins)); /* mins always shown as positive (w/o minus sign!) even if secs < 0 */ + } + + switch(what) { + case R_CRASH: +- sprintf(logouttime, "- crash"); ++ snprintf(logouttime, sizeof(logouttime), "- crash"); + break; + case R_DOWN: +- sprintf(logouttime, "- down "); ++ snprintf(logouttime, sizeof(logouttime), "- down "); + break; + case R_NOW: + if (ctl->time_fmt > LAST_TIMEFTM_SHORT) { +- sprintf(logouttime, " still logged in"); ++ snprintf(logouttime, sizeof(logouttime), " still logged in"); + length[0] = 0; + } else { +- sprintf(logouttime, " still"); +- sprintf(length, "logged in"); ++ snprintf(logouttime, sizeof(logouttime), " still"); ++ snprintf(length, sizeof(length), "logged in"); + } + break; + case R_PHANTOM: + if (ctl->time_fmt > LAST_TIMEFTM_SHORT) { +- sprintf(logouttime, " gone - no logout"); ++ snprintf(logouttime, sizeof(logouttime), " gone - no logout"); + length[0] = 0; + } else if (ctl->time_fmt == LAST_TIMEFTM_SHORT) { +- sprintf(logouttime, " gone"); +- sprintf(length, "- no logout"); ++ snprintf(logouttime, sizeof(logouttime), " gone"); ++ snprintf(length, sizeof(length), "- no logout"); + } else { + logouttime[0] = 0; +- sprintf(length, "no logout"); ++ snprintf(length, sizeof(length), "no logout"); + } + break; + case R_TIMECHANGE: +@@ -756,7 +756,7 @@ static void process_wtmp_file(const struct last_control *ctl, + else { + if (ut.ut_type != DEAD_PROCESS && + ut.ut_user[0] && ut.ut_line[0] && +- strcmp(ut.ut_user, "LOGIN") != 0) ++ strncmp(ut.ut_user, "LOGIN", 5) != 0) + ut.ut_type = USER_PROCESS; + /* + * Even worse, applications that write ghost +@@ -769,7 +769,7 @@ static void process_wtmp_file(const struct last_control *ctl, + /* + * Clock changes. + */ +- if (strcmp(ut.ut_user, "date") == 0) { ++ if (strncmp(ut.ut_user, "date", 4) == 0) { + if (ut.ut_line[0] == '|') + ut.ut_type = OLD_TIME; + if (ut.ut_line[0] == '{') +@@ -804,7 +804,7 @@ static void process_wtmp_file(const struct last_control *ctl, + case RUN_LVL: + x = ut.ut_pid & 255; + if (ctl->extended) { +- sprintf(ut.ut_line, "(to lvl %c)", x); ++ snprintf(ut.ut_line, sizeof(ut.ut_line), "(to lvl %c)", x); + quit = list(ctl, &ut, lastrch, R_NORMAL); + } + if (x == '0' || x == '6') { +-- +2.39.1 + diff --git a/SPECS/util-linux.spec b/SPECS/util-linux.spec index 70740b3..e16e9ae 100644 --- a/SPECS/util-linux.spec +++ b/SPECS/util-linux.spec @@ -2,7 +2,7 @@ Summary: A collection of basic system utilities Name: util-linux Version: 2.37.4 -Release: 9%{?dist} +Release: 10%{?dist} License: GPLv2 and GPLv2+ and LGPLv2+ and BSD with advertising and Public Domain URL: http://en.wikipedia.org/wiki/Util-linux @@ -150,6 +150,22 @@ Patch35: 0035-tests-add-udevadm-settle-to-loop-overlap-test.patch # 2094216 - lslogins reports incorrect "Password is locked" status Patch36: 0036-lslogins-support-more-password-methods.patch +### RHEL-9.2.0 +# +# 2165981 - fstrim -av fails to trim root filesystem on Red Hat Coreos +Patch37: 0037-fstrim-don-t-trigger-autofs.patch +Patch38: 0038-fstrim-fix-typo.patch +Patch39: 0039-fstrim-Remove-all-skipped-entries-before-de-duplicat.patch +# 2141970 - Add --cont-clock feature for libuuid and uuidd [rhel-9] +Patch40: 0040-libuuid-Implement-continuous-clock-handling-for-time.patch +Patch41: 0041-libuuid-check-clock-value-from-LIBUUID_CLOCK_FILE.patch +# 2133385 - uuidd returns time-based UUIDs when asked for random UUIDs. +Patch42: 0042-uuidd-fix-random-UUIDs.patch +# 2156946 - "agetty" does not handle the \l sequence in /etc/issue correctly +Patch43: 0043-agetty-resolve-tty-name-even-if-stdin-is-specified.patch +# 2166653 - last(1) should be more robust with work with strings +Patch44: 0044-last-use-snprintf-rather-than-sprintf.patch + %description The util-linux package contains a large variety of low-level system @@ -393,13 +409,13 @@ mkdir -p ${RPM_BUILD_ROOT}%{_bindir} mkdir -p ${RPM_BUILD_ROOT}%{_mandir}/man{1,6,8,5} mkdir -p ${RPM_BUILD_ROOT}%{_sbindir} mkdir -p ${RPM_BUILD_ROOT}%{_sysconfdir}/{pam.d,security/console.apps} -mkdir -p ${RPM_BUILD_ROOT}/usr/lib/tmpfiles.d +mkdir -p ${RPM_BUILD_ROOT}%{_tmpfilesdir} # install util-linux %make_install # And a dirs uuidd needs that the makefiles don't create -install -m 644 %{SOURCE4} ${RPM_BUILD_ROOT}/usr/lib/tmpfiles.d/uuidd.conf +install -m 644 %{SOURCE4} ${RPM_BUILD_ROOT}%{_tmpfilesdir}/uuidd.conf install -d ${RPM_BUILD_ROOT}/run/uuidd install -d ${RPM_BUILD_ROOT}/var/lib/libuuid @@ -984,6 +1000,15 @@ fi %{_libdir}/python*/site-packages/libmount/ %changelog +* Tue Feb 07 2023 Karel Zak 2.37.4-10 +- fix #2165981 - fstrim -av fails to trim root filesystem on Red Hat Coreos +- fix #2141970 - add --cont-clock feature for libuuid and uuidd +- fix #2133385 - uuidd returns time-based UUIDs when asked for random UUIDs. +- fix #2156946 - agetty does not handle the \l sequence in /etc/issue correctly +- fix #2166653 - last(1) should be more robust with work with strings +- fix #2120246 - use {_tmpfilesdir} also in install section +- fix #2134143 - publish libsmartcols-devel subpackages to C9S yum repos + * Wed Aug 24 2022 Karel Zak 2.37.4-9 - improve lslogins pasword validator (related #2094216)