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