From 8c971d2ce0ea1e26d9a9ebca56c5367ba88f86a3 Mon Sep 17 00:00:00 2001 From: DistroBaker Date: Nov 20 2020 18:06:30 +0000 Subject: Merged update from upstream sources This is an automated DistroBaker update from upstream sources. If you do not know what this is about or would like to opt out, contact the OSCI team. Source: https://src.fedoraproject.org/rpms/util-linux.git#5977e189d6cfbb091395521ccc6d4c680cc1298b --- diff --git a/0001-agetty-keep-freed-issue-file-pointer-zeroized.patch b/0001-agetty-keep-freed-issue-file-pointer-zeroized.patch deleted file mode 100644 index a5441b1..0000000 --- a/0001-agetty-keep-freed-issue-file-pointer-zeroized.patch +++ /dev/null @@ -1,55 +0,0 @@ -From 9418ba6d05feed6061f5343741b1bc56e7bde663 Mon Sep 17 00:00:00 2001 -From: Karel Zak -Date: Fri, 20 Dec 2019 15:05:33 +0100 -Subject: [PATCH] agetty: keep freed issue file pointer zeroized - -References: https://bugzilla.redhat.com/show_bug.cgi?id=1784536 -Signed-off-by: Karel Zak ---- - term-utils/agetty.c | 15 +++++++++++---- - 1 file changed, 11 insertions(+), 4 deletions(-) - -diff --git a/term-utils/agetty.c b/term-utils/agetty.c -index 3c20acc98..dfc4921f5 100644 ---- a/term-utils/agetty.c -+++ b/term-utils/agetty.c -@@ -1820,8 +1820,12 @@ static int issuefile_read_stream( - if (fstat(fileno(f), &st) || !S_ISREG(st.st_mode)) - return 1; - -- if (!ie->output) -- ie->output = open_memstream(&ie->mem, &ie->mem_sz); -+ if (!ie->output) { -+ free(ie->mem); -+ ie->mem_sz = 0; -+ ie->mem = NULL; -+ ie->output = open_memstream(&ie->mem, &ie->mem_sz); -+ } - - while ((c = getc(f)) != EOF) { - if (c == '\\') -@@ -1965,8 +1969,10 @@ done: - if (netlink_groups != 0) - open_netlink(); - #endif -- if (ie->output) -+ if (ie->output) { - fclose(ie->output); -+ ie->output = NULL; -+ } - } - - /* This is --show-issue backend, executed by normal user on the current -@@ -1985,7 +1991,8 @@ static void show_issue(struct options *op) - - if (ie.mem_sz) - write_all(STDOUT_FILENO, ie.mem, ie.mem_sz); -- -+ if (ie.output) -+ fclose(ie.output); - free(ie.mem); - } - --- -2.21.0 - diff --git a/0002-libmount-remove-read-mountinfo-workaround.patch b/0002-libmount-remove-read-mountinfo-workaround.patch deleted file mode 100644 index 38f8e34..0000000 --- a/0002-libmount-remove-read-mountinfo-workaround.patch +++ /dev/null @@ -1,396 +0,0 @@ -From 57898c3a7ee8fc5933cddd4526bb3980bef85a02 Mon Sep 17 00:00:00 2001 -From: Karel Zak -Date: Tue, 1 Sep 2020 10:15:14 +0200 -Subject: [PATCH] libmount: remove read-mountinfo workaround - -This workaround has been introduced by -http://github.com/karelzak/util-linux/commit/e4925f591c1bfb83719418b56b952830d15b77eb - -And originally requested by https://github.com/systemd/systemd/issues/10872 - -It seems we do not need it anymore as the problem should be fixed in kernel since 5.8 -(kernel commit 9f6c61f96f2d97cbb5f7fa85607bc398f843ff0f). - -Note that the libmount solution is very expensive as it repeats read() -many times (until we get consistent result) if kernel is busy with -mount table modification. This behaviour makes events management in -systemd (or other places) pretty difficult as read mountinfo takes -time on busy systems. - -Addresses: https://github.com/systemd/systemd/pull/16537 -Signed-off-by: Karel Zak ---- - configure.ac | 1 - - libmount/src/mountP.h | 2 - - libmount/src/tab_parse.c | 87 ++++---------------- - libmount/src/utils.c | 166 --------------------------------------- - 4 files changed, 15 insertions(+), 241 deletions(-) - -diff --git a/configure.ac b/configure.ac -index 2d178f3af..1e31ca3e2 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -504,7 +504,6 @@ AC_CHECK_FUNCS([ \ - err \ - errx \ - explicit_bzero \ -- fmemopen \ - fsync \ - utimensat \ - getdomainname \ -diff --git a/libmount/src/mountP.h b/libmount/src/mountP.h -index d8ba0abad..ee97c6b4a 100644 ---- a/libmount/src/mountP.h -+++ b/libmount/src/mountP.h -@@ -98,7 +98,6 @@ extern int mnt_valid_tagname(const char *tagname); - extern int append_string(char **a, const char *b); - - extern const char *mnt_statfs_get_fstype(struct statfs *vfs); --extern int is_procfs_fd(int fd); - extern int is_file_empty(const char *name); - - extern int mnt_is_readonly(const char *path) -@@ -124,7 +123,6 @@ extern void mnt_free_filesystems(char **filesystems); - extern char *mnt_get_kernel_cmdline_option(const char *name); - extern int mnt_stat_mountpoint(const char *target, struct stat *st); - extern int mnt_lstat_mountpoint(const char *target, struct stat *st); --extern FILE *mnt_get_procfs_memstream(int fd, char **membuf); - - /* tab.c */ - extern int is_mountinfo(struct libmnt_table *tb); -diff --git a/libmount/src/tab_parse.c b/libmount/src/tab_parse.c -index 329987bcb..ac12dce54 100644 ---- a/libmount/src/tab_parse.c -+++ b/libmount/src/tab_parse.c -@@ -694,7 +694,15 @@ static int kernel_fs_postparse(struct libmnt_table *tb, - return rc; - } - --static int __table_parse_stream(struct libmnt_table *tb, FILE *f, const char *filename) -+/** -+ * mnt_table_parse_stream: -+ * @tb: tab pointer -+ * @f: file stream -+ * @filename: filename used for debug and error messages -+ * -+ * Returns: 0 on success, negative number in case of error. -+ */ -+int mnt_table_parse_stream(struct libmnt_table *tb, FILE *f, const char *filename) - { - int rc = -1; - int flags = 0; -@@ -773,40 +781,6 @@ err: - return rc; - } - --/** -- * mnt_table_parse_stream: -- * @tb: tab pointer -- * @f: file stream -- * @filename: filename used for debug and error messages -- * -- * Returns: 0 on success, negative number in case of error. -- */ --int mnt_table_parse_stream(struct libmnt_table *tb, FILE *f, const char *filename) --{ -- int fd, rc; -- FILE *memf = NULL; -- char *membuf = NULL; -- -- /* -- * For /proc/#/{mountinfo,mount} we read all file to memory and use it -- * as memory stream. For more details see mnt_read_procfs_file(). -- */ -- if ((fd = fileno(f)) >= 0 -- && (tb->fmt == MNT_FMT_GUESS || -- tb->fmt == MNT_FMT_MOUNTINFO || -- tb->fmt == MNT_FMT_MTAB) -- && is_procfs_fd(fd) -- && (memf = mnt_get_procfs_memstream(fd, &membuf))) { -- -- rc = __table_parse_stream(tb, memf, filename); -- fclose(memf); -- free(membuf); -- } else -- rc = __table_parse_stream(tb, f, filename); -- -- return rc; --} -- - /** - * mnt_table_parse_file: - * @tb: tab pointer -@@ -822,49 +796,18 @@ int mnt_table_parse_stream(struct libmnt_table *tb, FILE *f, const char *filenam - int mnt_table_parse_file(struct libmnt_table *tb, const char *filename) - { - FILE *f; -- int rc, fd = -1; -+ int rc; - - if (!filename || !tb) - return -EINVAL; - -- /* -- * Try to use read()+poll() to realiably read all -- * /proc/#/{mount,mountinfo} file to memory -- */ -- if (tb->fmt != MNT_FMT_SWAPS -- && strncmp(filename, "/proc/", 6) == 0) { -- -- FILE *memf; -- char *membuf = NULL; -- -- fd = open(filename, O_RDONLY|O_CLOEXEC); -- if (fd < 0) { -- rc = -errno; -- goto done; -- } -- memf = mnt_get_procfs_memstream(fd, &membuf); -- if (memf) { -- rc = __table_parse_stream(tb, memf, filename); -- -- fclose(memf); -- free(membuf); -- close(fd); -- goto done; -- } -- /* else fallback to fopen/fdopen() */ -- } -- -- if (fd >= 0) -- f = fdopen(fd, "r" UL_CLOEXECSTR); -- else -- f = fopen(filename, "r" UL_CLOEXECSTR); -- -+ f = fopen(filename, "r" UL_CLOEXECSTR); - if (f) { -- rc = __table_parse_stream(tb, f, filename); -+ rc = mnt_table_parse_stream(tb, f, filename); - fclose(f); - } else - rc = -errno; --done: -+ - DBG(TAB, ul_debugobj(tb, "parsing done [filename=%s, rc=%d]", filename, rc)); - return rc; - } -@@ -921,7 +864,7 @@ static int __mnt_table_parse_dir(struct libmnt_table *tb, const char *dirname) - - f = fopen_at(dd, d->d_name, O_RDONLY|O_CLOEXEC, "r" UL_CLOEXECSTR); - if (f) { -- __table_parse_stream(tb, f, d->d_name); -+ mnt_table_parse_stream(tb, f, d->d_name); - fclose(f); - } - } -@@ -962,7 +905,7 @@ static int __mnt_table_parse_dir(struct libmnt_table *tb, const char *dirname) - f = fopen_at(dirfd(dir), d->d_name, - O_RDONLY|O_CLOEXEC, "r" UL_CLOEXECSTR); - if (f) { -- __table_parse_stream(tb, f, d->d_name); -+ mnt_table_parse_stream(tb, f, d->d_name); - fclose(f); - } - } -diff --git a/libmount/src/utils.c b/libmount/src/utils.c -index 92829ebb0..40b45f11d 100644 ---- a/libmount/src/utils.c -+++ b/libmount/src/utils.c -@@ -19,7 +19,6 @@ - #include - #include - #include --#include - #include - - #include "strutils.h" -@@ -448,13 +447,6 @@ const char *mnt_statfs_get_fstype(struct statfs *vfs) - return NULL; - } - --int is_procfs_fd(int fd) --{ -- struct statfs sfs; -- -- return fstatfs(fd, &sfs) == 0 && sfs.f_type == STATFS_PROC_MAGIC; --} -- - /** - * mnt_match_fstype: - * @type: filesystem type -@@ -1174,164 +1166,7 @@ done: - return 1; - } - --#if defined(HAVE_FMEMOPEN) || defined(TEST_PROGRAM) -- --/* -- * This function tries to minimize possible races when we read -- * /proc/#/{mountinfo,mount} files. -- * -- * The idea is to minimize number of read()s and check by poll() that during -- * the read the mount table has not been modified. If yes, than re-read it -- * (with some limitations to avoid never ending loop). -- * -- * Returns: <0 error, 0 success, 1 too many attempts -- */ --static int read_procfs_file(int fd, char **buf, size_t *bufsiz) --{ -- size_t bufmax = 0; -- int rc = 0, tries = 0, ninters = 0; -- char *bufptr = NULL; -- -- assert(buf); -- assert(bufsiz); -- -- *bufsiz = 0; -- *buf = NULL; -- -- do { -- ssize_t ret; -- -- if (!bufptr || bufmax == *bufsiz) { -- char *tmp; -- -- bufmax = bufmax ? bufmax * 2 : (16 * 1024); -- tmp = realloc(*buf, bufmax); -- if (!tmp) -- break; -- *buf = tmp; -- bufptr = tmp + *bufsiz; -- } -- -- errno = 0; -- ret = read(fd, bufptr, bufmax - *bufsiz); -- -- if (ret < 0) { -- /* error */ -- if ((errno == EAGAIN || errno == EINTR) && (ninters++ < 5)) { -- xusleep(200000); -- continue; -- } -- break; -- -- } if (ret > 0) { -- /* success -- verify no event during read */ -- struct pollfd fds[] = { -- { .fd = fd, .events = POLLPRI } -- }; -- -- rc = poll(fds, 1, 0); -- if (rc < 0) -- break; /* poll() error */ -- if (rc > 0) { -- /* event -- read all again */ -- if (lseek(fd, 0, SEEK_SET) != 0) -- break; -- *bufsiz = 0; -- bufptr = *buf; -- tries++; -- -- if (tries > 10) -- /* busy system? -- wait */ -- xusleep(10000); -- continue; -- } -- -- /* successful read() without active poll() */ -- (*bufsiz) += (size_t) ret; -- bufptr += ret; -- tries = ninters = 0; -- } else { -- /* end-of-file */ -- goto success; -- } -- } while (tries <= 100); -- -- rc = errno ? -errno : 1; -- free(*buf); -- return rc; -- --success: -- return 0; --} -- --/* -- * Create FILE stream for data from read_procfs_file() -- */ --FILE *mnt_get_procfs_memstream(int fd, char **membuf) --{ -- size_t sz = 0; -- off_t cur; -- -- *membuf = NULL; -- -- /* in case of error, rewind to the original position */ -- cur = lseek(fd, 0, SEEK_CUR); -- -- if (read_procfs_file(fd, membuf, &sz) == 0 && sz > 0) { -- FILE *memf = fmemopen(*membuf, sz, "r"); -- if (memf) -- return memf; /* success */ -- -- free(*membuf); -- *membuf = NULL; -- } -- -- /* error */ -- if (cur != (off_t) -1) -- lseek(fd, cur, SEEK_SET); -- return NULL; --} --#else --FILE *mnt_get_procfs_memstream(int fd __attribute((__unused__)), -- char **membuf __attribute((__unused__))) --{ -- return NULL; --} --#endif /* HAVE_FMEMOPEN */ -- -- - #ifdef TEST_PROGRAM --static int test_proc_read(struct libmnt_test *ts, int argc, char *argv[]) --{ -- char *buf = NULL; -- char *filename = argv[1]; -- size_t bufsiz = 0; -- int rc = 0, fd = open(filename, O_RDONLY); -- -- if (fd <= 0) { -- warn("%s: cannot open", filename); -- return -errno; -- } -- -- rc = read_procfs_file(fd, &buf, &bufsiz); -- close(fd); -- -- switch (rc) { -- case 0: -- fwrite(buf, 1, bufsiz, stdout); -- free(buf); -- break; -- case 1: -- warnx("too many attempts"); -- break; -- default: -- warn("%s: cannot read", filename); -- break; -- } -- -- return rc; --} -- - static int test_match_fstype(struct libmnt_test *ts, int argc, char *argv[]) - { - char *type = argv[1]; -@@ -1513,7 +1348,6 @@ int main(int argc, char *argv[]) - { "--guess-root", test_guess_root, "[]" }, - { "--mkdir", test_mkdir, "" }, - { "--statfs-type", test_statfs_type, "" }, -- { "--read-procfs", test_proc_read, "" }, - - { NULL } - }; --- -2.25.4 - diff --git a/2.36-login-lastlog-create.patch b/2.36-login-lastlog-create.patch deleted file mode 100644 index e2523d3..0000000 --- a/2.36-login-lastlog-create.patch +++ /dev/null @@ -1,12 +0,0 @@ -diff -up util-linux-2.36/login-utils/login.c.kzak util-linux-2.36/login-utils/login.c ---- util-linux-2.36/login-utils/login.c.kzak 2020-07-23 14:13:26.777030764 +0200 -+++ util-linux-2.36/login-utils/login.c 2020-07-23 14:11:22.793686983 +0200 -@@ -585,7 +585,7 @@ static void log_lastlog(struct login_con - sa.sa_handler = SIG_IGN; - sigaction(SIGXFSZ, &sa, &oldsa_xfsz); - -- fd = open(_PATH_LASTLOG, O_RDWR, 0); -+ fd = open(_PATH_LASTLOG, O_RDWR | O_CREAT, 0); - if (fd < 0) - goto done; - offset = cxt->pwd->pw_uid * sizeof(ll); diff --git a/column-fix-leading-space-characters-bug.patch b/column-fix-leading-space-characters-bug.patch deleted file mode 100644 index e612d34..0000000 --- a/column-fix-leading-space-characters-bug.patch +++ /dev/null @@ -1,148 +0,0 @@ -From 651c5d428c2ef103ee8c5b1a310d6f29f0304744 Mon Sep 17 00:00:00 2001 -From: Karel Zak -Date: Tue, 27 Mar 2018 10:40:13 +0200 -Subject: [PATCH] column: fix leading space characters bug - -The bug has been introduced during column(1) rewrite. The function -read_input() need to skip leading space only temporary to detect empty -lines, but the rest of the code has to use the original buffer (line). -I've tried to fix one of the symptoms by 5c7b67fbbf41c973ca8d49b1e8bdba22dbb917aa -(alter), but this solution is unnecessary and too complex. - -Changes: - -* don't ignore leading space -* remove unnecessary stuff introduced by 5c7b67fbbf41c973ca8d49b1e8bdba22dbb917aa -* fix regression test with incorrect separator - -Addresses: https://github.com/karelzak/util-linux/issues/575 -Addresses: https://bugzilla.redhat.com/show_bug.cgi?id=1560283 -Signed-off-by: Karel Zak ---- - tests/expected/column/table-input-separator-space | 2 +- - tests/ts/column/table | 2 +- - text-utils/column.c | 36 ++--------------------- - 4 files changed, 5 insertions(+), 38 deletions(-) - -diff --git a/tests/expected/column/table-input-separator-space b/tests/expected/column/table-input-separator-space -index 8a6513c11..25d9b5ab0 100644 ---- a/tests/expected/column/table-input-separator-space -+++ b/tests/expected/column/table-input-separator-space -@@ -1,5 +1,5 @@ - AAA BBBB C DDDD --BBB CCCC DDD -+ BBB CCCC DDD - AA BB DD - AAAA B CC D - AA CC DD -diff --git a/tests/ts/column/table b/tests/ts/column/table -index 27b52e7c8..5c89d5eaf 100755 ---- a/tests/ts/column/table -+++ b/tests/ts/column/table -@@ -37,7 +37,7 @@ $TS_CMD_COLUMN --separator ',' --table $TS_SELF/files/table-sep >> $TS_OUTPUT 2> - ts_finalize_subtest - - ts_init_subtest "input-separator-space" --$TS_CMD_COLUMN --separator ',' --table $TS_SELF/files/table-sep-space >> $TS_OUTPUT 2>&1 -+$TS_CMD_COLUMN --separator "$(echo -e '\t')" --table $TS_SELF/files/table-sep-space >> $TS_OUTPUT 2>&1 - ts_finalize_subtest - - ts_init_subtest "long" -diff --git a/text-utils/column.c b/text-utils/column.c -index 89d46d280..195814328 100644 ---- a/text-utils/column.c -+++ b/text-utils/column.c -@@ -86,7 +86,6 @@ struct column_control { - const char *tree_parent; - - wchar_t *input_separator; -- char *input_separator_raw; - const char *output_separator; - - wchar_t **ents; /* input entries */ -@@ -96,7 +95,6 @@ struct column_control { - unsigned int greedy :1, - json :1, - header_repeat :1, -- input_sep_space : 1, /* input separator contains space chars */ - tab_noheadings :1; - }; - -@@ -470,19 +468,7 @@ static int read_input(struct column_control *ctl, FILE *fp) - char *buf = NULL; - size_t bufsz = 0; - size_t maxents = 0; -- int rc = 0, is_space_sep = 0; -- -- /* Check if columns separator contains spaces chars */ -- if (ctl->mode == COLUMN_MODE_TABLE && ctl->input_separator_raw) { -- char *p; -- -- for (p = ctl->input_separator_raw; *p; p++) { -- if (isspace(*p)) { -- is_space_sep = 1; -- break; -- } -- } -- } -+ int rc = 0; - - /* Read input */ - do { -@@ -496,19 +482,6 @@ static int read_input(struct column_control *ctl, FILE *fp) - err(EXIT_FAILURE, _("read failed")); - } - str = (char *) skip_space(buf); -- -- /* The table columns separator could be a space. In this case -- * don't skip the separator if at begin of the line. For example: -- * -- * echo -e "\tcol1\tcol2\nrow\t1\t2" \ -- * | column -t -s "$(echo -e '\t')" --table-columns A,B,C -- */ -- if (is_space_sep && str > buf) { -- char *x = strpbrk(buf, ctl->input_separator_raw); -- if (x && x < str) -- str = x; -- } -- - if (str) { - p = strchr(str, '\n'); - if (p) -@@ -517,13 +490,13 @@ static int read_input(struct column_control *ctl, FILE *fp) - if (!str || !*str) - continue; - -- wcs = mbs_to_wcs(str); -+ wcs = mbs_to_wcs(buf); - if (!wcs) { - /* - * Convert broken sequences to \x and continue. - */ - size_t tmpsz = 0; -- char *tmp = mbs_invalid_encode(str, &tmpsz); -+ char *tmp = mbs_invalid_encode(buf, &tmpsz); - - if (!tmp) - err(EXIT_FAILURE, _("read failed")); -@@ -720,7 +693,6 @@ int main(int argc, char **argv) - - ctl.output_separator = " "; - ctl.input_separator = mbs_to_wcs("\t "); -- ctl.input_separator_raw = xstrdup("\t "); - - while ((c = getopt_long(argc, argv, "c:dE:eH:hi:JN:n:O:o:p:R:r:s:T:tVW:x", longopts, NULL)) != -1) { - -@@ -775,9 +747,7 @@ int main(int argc, char **argv) - break; - case 's': - free(ctl.input_separator); -- free(ctl.input_separator_raw); - ctl.input_separator = mbs_to_wcs(optarg); -- ctl.input_separator_raw = xstrdup(optarg); - ctl.greedy = 0; - break; - case 'T': --- -2.14.3 - diff --git a/libmount-don-t-use-symfollow-for-helpers-on-user-mou.patch b/libmount-don-t-use-symfollow-for-helpers-on-user-mou.patch new file mode 100644 index 0000000..edc7477 --- /dev/null +++ b/libmount-don-t-use-symfollow-for-helpers-on-user-mou.patch @@ -0,0 +1,40 @@ +From 76bb9b30cfcf54b59591a57a3d2a747e514469b2 Mon Sep 17 00:00:00 2001 +From: Karel Zak +Date: Thu, 19 Nov 2020 09:49:16 +0100 +Subject: [PATCH] libmount: don't use "symfollow" for helpers on user mounts + +Addresses: https://github.com/karelzak/util-linux/issues/1193 +Signed-off-by: Karel Zak +--- + libmount/src/context_mount.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/libmount/src/context_mount.c b/libmount/src/context_mount.c +index 8c394c1ff..dd1786176 100644 +--- a/libmount/src/context_mount.c ++++ b/libmount/src/context_mount.c +@@ -415,6 +415,9 @@ static int generate_helper_optstr(struct libmnt_context *cxt, char **optstr) + * string, because there is nothing like MS_EXEC (we only have + * MS_NOEXEC in mount flags and we don't care about the original + * mount string in libmount for VFS options). ++ * ++ * This use-case makes sense for MS_SECURE flags only (see ++ * mnt_optstr_get_flags() and mnt_context_merge_mflags()). + */ + if (!(cxt->mountflags & MS_NOEXEC)) + mnt_optstr_append_option(optstr, "exec", NULL); +@@ -422,11 +425,8 @@ static int generate_helper_optstr(struct libmnt_context *cxt, char **optstr) + mnt_optstr_append_option(optstr, "suid", NULL); + if (!(cxt->mountflags & MS_NODEV)) + mnt_optstr_append_option(optstr, "dev", NULL); +- if (!(cxt->mountflags & MS_NOSYMFOLLOW)) +- mnt_optstr_append_option(optstr, "symfollow", NULL); + } + +- + if (cxt->flags & MNT_FL_SAVED_USER) + rc = mnt_optstr_set_option(optstr, "user", cxt->orig_user); + if (rc) +-- +2.25.4 + diff --git a/libmount-remove-read-mountinfo-workaround.patch b/libmount-remove-read-mountinfo-workaround.patch new file mode 100644 index 0000000..38f8e34 --- /dev/null +++ b/libmount-remove-read-mountinfo-workaround.patch @@ -0,0 +1,396 @@ +From 57898c3a7ee8fc5933cddd4526bb3980bef85a02 Mon Sep 17 00:00:00 2001 +From: Karel Zak +Date: Tue, 1 Sep 2020 10:15:14 +0200 +Subject: [PATCH] libmount: remove read-mountinfo workaround + +This workaround has been introduced by +http://github.com/karelzak/util-linux/commit/e4925f591c1bfb83719418b56b952830d15b77eb + +And originally requested by https://github.com/systemd/systemd/issues/10872 + +It seems we do not need it anymore as the problem should be fixed in kernel since 5.8 +(kernel commit 9f6c61f96f2d97cbb5f7fa85607bc398f843ff0f). + +Note that the libmount solution is very expensive as it repeats read() +many times (until we get consistent result) if kernel is busy with +mount table modification. This behaviour makes events management in +systemd (or other places) pretty difficult as read mountinfo takes +time on busy systems. + +Addresses: https://github.com/systemd/systemd/pull/16537 +Signed-off-by: Karel Zak +--- + configure.ac | 1 - + libmount/src/mountP.h | 2 - + libmount/src/tab_parse.c | 87 ++++---------------- + libmount/src/utils.c | 166 --------------------------------------- + 4 files changed, 15 insertions(+), 241 deletions(-) + +diff --git a/configure.ac b/configure.ac +index 2d178f3af..1e31ca3e2 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -504,7 +504,6 @@ AC_CHECK_FUNCS([ \ + err \ + errx \ + explicit_bzero \ +- fmemopen \ + fsync \ + utimensat \ + getdomainname \ +diff --git a/libmount/src/mountP.h b/libmount/src/mountP.h +index d8ba0abad..ee97c6b4a 100644 +--- a/libmount/src/mountP.h ++++ b/libmount/src/mountP.h +@@ -98,7 +98,6 @@ extern int mnt_valid_tagname(const char *tagname); + extern int append_string(char **a, const char *b); + + extern const char *mnt_statfs_get_fstype(struct statfs *vfs); +-extern int is_procfs_fd(int fd); + extern int is_file_empty(const char *name); + + extern int mnt_is_readonly(const char *path) +@@ -124,7 +123,6 @@ extern void mnt_free_filesystems(char **filesystems); + extern char *mnt_get_kernel_cmdline_option(const char *name); + extern int mnt_stat_mountpoint(const char *target, struct stat *st); + extern int mnt_lstat_mountpoint(const char *target, struct stat *st); +-extern FILE *mnt_get_procfs_memstream(int fd, char **membuf); + + /* tab.c */ + extern int is_mountinfo(struct libmnt_table *tb); +diff --git a/libmount/src/tab_parse.c b/libmount/src/tab_parse.c +index 329987bcb..ac12dce54 100644 +--- a/libmount/src/tab_parse.c ++++ b/libmount/src/tab_parse.c +@@ -694,7 +694,15 @@ static int kernel_fs_postparse(struct libmnt_table *tb, + return rc; + } + +-static int __table_parse_stream(struct libmnt_table *tb, FILE *f, const char *filename) ++/** ++ * mnt_table_parse_stream: ++ * @tb: tab pointer ++ * @f: file stream ++ * @filename: filename used for debug and error messages ++ * ++ * Returns: 0 on success, negative number in case of error. ++ */ ++int mnt_table_parse_stream(struct libmnt_table *tb, FILE *f, const char *filename) + { + int rc = -1; + int flags = 0; +@@ -773,40 +781,6 @@ err: + return rc; + } + +-/** +- * mnt_table_parse_stream: +- * @tb: tab pointer +- * @f: file stream +- * @filename: filename used for debug and error messages +- * +- * Returns: 0 on success, negative number in case of error. +- */ +-int mnt_table_parse_stream(struct libmnt_table *tb, FILE *f, const char *filename) +-{ +- int fd, rc; +- FILE *memf = NULL; +- char *membuf = NULL; +- +- /* +- * For /proc/#/{mountinfo,mount} we read all file to memory and use it +- * as memory stream. For more details see mnt_read_procfs_file(). +- */ +- if ((fd = fileno(f)) >= 0 +- && (tb->fmt == MNT_FMT_GUESS || +- tb->fmt == MNT_FMT_MOUNTINFO || +- tb->fmt == MNT_FMT_MTAB) +- && is_procfs_fd(fd) +- && (memf = mnt_get_procfs_memstream(fd, &membuf))) { +- +- rc = __table_parse_stream(tb, memf, filename); +- fclose(memf); +- free(membuf); +- } else +- rc = __table_parse_stream(tb, f, filename); +- +- return rc; +-} +- + /** + * mnt_table_parse_file: + * @tb: tab pointer +@@ -822,49 +796,18 @@ int mnt_table_parse_stream(struct libmnt_table *tb, FILE *f, const char *filenam + int mnt_table_parse_file(struct libmnt_table *tb, const char *filename) + { + FILE *f; +- int rc, fd = -1; ++ int rc; + + if (!filename || !tb) + return -EINVAL; + +- /* +- * Try to use read()+poll() to realiably read all +- * /proc/#/{mount,mountinfo} file to memory +- */ +- if (tb->fmt != MNT_FMT_SWAPS +- && strncmp(filename, "/proc/", 6) == 0) { +- +- FILE *memf; +- char *membuf = NULL; +- +- fd = open(filename, O_RDONLY|O_CLOEXEC); +- if (fd < 0) { +- rc = -errno; +- goto done; +- } +- memf = mnt_get_procfs_memstream(fd, &membuf); +- if (memf) { +- rc = __table_parse_stream(tb, memf, filename); +- +- fclose(memf); +- free(membuf); +- close(fd); +- goto done; +- } +- /* else fallback to fopen/fdopen() */ +- } +- +- if (fd >= 0) +- f = fdopen(fd, "r" UL_CLOEXECSTR); +- else +- f = fopen(filename, "r" UL_CLOEXECSTR); +- ++ f = fopen(filename, "r" UL_CLOEXECSTR); + if (f) { +- rc = __table_parse_stream(tb, f, filename); ++ rc = mnt_table_parse_stream(tb, f, filename); + fclose(f); + } else + rc = -errno; +-done: ++ + DBG(TAB, ul_debugobj(tb, "parsing done [filename=%s, rc=%d]", filename, rc)); + return rc; + } +@@ -921,7 +864,7 @@ static int __mnt_table_parse_dir(struct libmnt_table *tb, const char *dirname) + + f = fopen_at(dd, d->d_name, O_RDONLY|O_CLOEXEC, "r" UL_CLOEXECSTR); + if (f) { +- __table_parse_stream(tb, f, d->d_name); ++ mnt_table_parse_stream(tb, f, d->d_name); + fclose(f); + } + } +@@ -962,7 +905,7 @@ static int __mnt_table_parse_dir(struct libmnt_table *tb, const char *dirname) + f = fopen_at(dirfd(dir), d->d_name, + O_RDONLY|O_CLOEXEC, "r" UL_CLOEXECSTR); + if (f) { +- __table_parse_stream(tb, f, d->d_name); ++ mnt_table_parse_stream(tb, f, d->d_name); + fclose(f); + } + } +diff --git a/libmount/src/utils.c b/libmount/src/utils.c +index 92829ebb0..40b45f11d 100644 +--- a/libmount/src/utils.c ++++ b/libmount/src/utils.c +@@ -19,7 +19,6 @@ + #include + #include + #include +-#include + #include + + #include "strutils.h" +@@ -448,13 +447,6 @@ const char *mnt_statfs_get_fstype(struct statfs *vfs) + return NULL; + } + +-int is_procfs_fd(int fd) +-{ +- struct statfs sfs; +- +- return fstatfs(fd, &sfs) == 0 && sfs.f_type == STATFS_PROC_MAGIC; +-} +- + /** + * mnt_match_fstype: + * @type: filesystem type +@@ -1174,164 +1166,7 @@ done: + return 1; + } + +-#if defined(HAVE_FMEMOPEN) || defined(TEST_PROGRAM) +- +-/* +- * This function tries to minimize possible races when we read +- * /proc/#/{mountinfo,mount} files. +- * +- * The idea is to minimize number of read()s and check by poll() that during +- * the read the mount table has not been modified. If yes, than re-read it +- * (with some limitations to avoid never ending loop). +- * +- * Returns: <0 error, 0 success, 1 too many attempts +- */ +-static int read_procfs_file(int fd, char **buf, size_t *bufsiz) +-{ +- size_t bufmax = 0; +- int rc = 0, tries = 0, ninters = 0; +- char *bufptr = NULL; +- +- assert(buf); +- assert(bufsiz); +- +- *bufsiz = 0; +- *buf = NULL; +- +- do { +- ssize_t ret; +- +- if (!bufptr || bufmax == *bufsiz) { +- char *tmp; +- +- bufmax = bufmax ? bufmax * 2 : (16 * 1024); +- tmp = realloc(*buf, bufmax); +- if (!tmp) +- break; +- *buf = tmp; +- bufptr = tmp + *bufsiz; +- } +- +- errno = 0; +- ret = read(fd, bufptr, bufmax - *bufsiz); +- +- if (ret < 0) { +- /* error */ +- if ((errno == EAGAIN || errno == EINTR) && (ninters++ < 5)) { +- xusleep(200000); +- continue; +- } +- break; +- +- } if (ret > 0) { +- /* success -- verify no event during read */ +- struct pollfd fds[] = { +- { .fd = fd, .events = POLLPRI } +- }; +- +- rc = poll(fds, 1, 0); +- if (rc < 0) +- break; /* poll() error */ +- if (rc > 0) { +- /* event -- read all again */ +- if (lseek(fd, 0, SEEK_SET) != 0) +- break; +- *bufsiz = 0; +- bufptr = *buf; +- tries++; +- +- if (tries > 10) +- /* busy system? -- wait */ +- xusleep(10000); +- continue; +- } +- +- /* successful read() without active poll() */ +- (*bufsiz) += (size_t) ret; +- bufptr += ret; +- tries = ninters = 0; +- } else { +- /* end-of-file */ +- goto success; +- } +- } while (tries <= 100); +- +- rc = errno ? -errno : 1; +- free(*buf); +- return rc; +- +-success: +- return 0; +-} +- +-/* +- * Create FILE stream for data from read_procfs_file() +- */ +-FILE *mnt_get_procfs_memstream(int fd, char **membuf) +-{ +- size_t sz = 0; +- off_t cur; +- +- *membuf = NULL; +- +- /* in case of error, rewind to the original position */ +- cur = lseek(fd, 0, SEEK_CUR); +- +- if (read_procfs_file(fd, membuf, &sz) == 0 && sz > 0) { +- FILE *memf = fmemopen(*membuf, sz, "r"); +- if (memf) +- return memf; /* success */ +- +- free(*membuf); +- *membuf = NULL; +- } +- +- /* error */ +- if (cur != (off_t) -1) +- lseek(fd, cur, SEEK_SET); +- return NULL; +-} +-#else +-FILE *mnt_get_procfs_memstream(int fd __attribute((__unused__)), +- char **membuf __attribute((__unused__))) +-{ +- return NULL; +-} +-#endif /* HAVE_FMEMOPEN */ +- +- + #ifdef TEST_PROGRAM +-static int test_proc_read(struct libmnt_test *ts, int argc, char *argv[]) +-{ +- char *buf = NULL; +- char *filename = argv[1]; +- size_t bufsiz = 0; +- int rc = 0, fd = open(filename, O_RDONLY); +- +- if (fd <= 0) { +- warn("%s: cannot open", filename); +- return -errno; +- } +- +- rc = read_procfs_file(fd, &buf, &bufsiz); +- close(fd); +- +- switch (rc) { +- case 0: +- fwrite(buf, 1, bufsiz, stdout); +- free(buf); +- break; +- case 1: +- warnx("too many attempts"); +- break; +- default: +- warn("%s: cannot read", filename); +- break; +- } +- +- return rc; +-} +- + static int test_match_fstype(struct libmnt_test *ts, int argc, char *argv[]) + { + char *type = argv[1]; +@@ -1513,7 +1348,6 @@ int main(int argc, char *argv[]) + { "--guess-root", test_guess_root, "[]" }, + { "--mkdir", test_mkdir, "" }, + { "--statfs-type", test_statfs_type, "" }, +- { "--read-procfs", test_proc_read, "" }, + + { NULL } + }; +-- +2.25.4 + diff --git a/login-lastlog-create.patch b/login-lastlog-create.patch new file mode 100644 index 0000000..e2523d3 --- /dev/null +++ b/login-lastlog-create.patch @@ -0,0 +1,12 @@ +diff -up util-linux-2.36/login-utils/login.c.kzak util-linux-2.36/login-utils/login.c +--- util-linux-2.36/login-utils/login.c.kzak 2020-07-23 14:13:26.777030764 +0200 ++++ util-linux-2.36/login-utils/login.c 2020-07-23 14:11:22.793686983 +0200 +@@ -585,7 +585,7 @@ static void log_lastlog(struct login_con + sa.sa_handler = SIG_IGN; + sigaction(SIGXFSZ, &sa, &oldsa_xfsz); + +- fd = open(_PATH_LASTLOG, O_RDWR, 0); ++ fd = open(_PATH_LASTLOG, O_RDWR | O_CREAT, 0); + if (fd < 0) + goto done; + offset = cxt->pwd->pw_uid * sizeof(ll); diff --git a/util-linux.spec b/util-linux.spec index 85cf53a..4541839 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.36.1 -Release: 1%{?dist} +Release: 2%{?dist} License: GPLv2 and GPLv2+ and LGPLv2+ and BSD with advertising and Public Domain URL: http://en.wikipedia.org/wiki/Util-linux @@ -103,10 +103,12 @@ Requires: libfdisk = %{version}-%{release} ### Ready for upstream? ### # 151635 - makeing /var/log/lastlog -Patch0: 2.36-login-lastlog-create.patch +Patch0: login-lastlog-create.patch # https://github.com/karelzak/util-linux/commit/57898c3a7ee8fc5933cddd4526bb3980bef85a02 # The workaround is unnecessary on Fedora with kernel >= 5.8. -Patch1: 0002-libmount-remove-read-mountinfo-workaround.patch +Patch1: libmount-remove-read-mountinfo-workaround.patch +# usptream patch, https://github.com/karelzak/util-linux/issues/1193 +Patch2: libmount-don-t-use-symfollow-for-helpers-on-user-mou.patch %description The util-linux package contains a large variety of low-level system @@ -939,6 +941,11 @@ fi %{_libdir}/python*/site-packages/libmount/ %changelog +* Thu Nov 19 2020 Karel Zak - 2.36.1-2 +- remove unused patches +- remove versions and seq.numbers from patch names +- fix mount "symfollow" issue (upstream patch) + * Mon Nov 16 2020 Karel Zak - 2.36.1-1 - upgrade to stable upstream 2.36.1 https://www.kernel.org/pub/linux/utils/util-linux/v2.36/v2.36.1-ReleaseNotes