diff --git a/0105-add-umount-information-and-time-tag.patch b/0105-add-umount-information-and-time-tag.patch new file mode 100644 index 0000000000000000000000000000000000000000..226338494bb3ab56f9b2c74f87551d52de97a389 --- /dev/null +++ b/0105-add-umount-information-and-time-tag.patch @@ -0,0 +1,436 @@ +From 41e04d676d9bbe45173c1eed3b4d69cde70ecded Mon Sep 17 00:00:00 2001 +From: 张越 +Date: Fri, 6 Dec 2024 14:44:16 +0800 +Subject: [PATCH] add umount information and time tag + +add umount information and time tag + +Change-Id: I1afe338537b8cd3740b4daa868b9a2a20a3646e7 +--- + sys-utils/umount.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 52 insertions(+) + +diff --git a/sys-utils/umount.c b/sys-utils/umount.c +index e579fb7..80c5131 100644 +--- a/sys-utils/umount.c ++++ b/sys-utils/umount.c +@@ -26,6 +26,9 @@ + #include + #include + #include ++#include ++#include ++#include + + #include + +@@ -42,6 +45,11 @@ + #define OPTUTILS_EXIT_CODE MNT_EX_USAGE + #include "optutils.h" + ++static int quiet; ++static struct ul_env_list *envs_removed; ++ ++void get_args(int argc, char **argv, char *str, int len); ++ + static int table_parser_errcb(struct libmnt_table *tb __attribute__((__unused__)), + const char *filename, int line) + { +@@ -51,7 +59,7 @@ + } + + +-static void __attribute__((__noreturn__)) print_version(void) ++static void __attribute__((__noreturn__)) umount_print_version(void) + { + const char *ver = NULL; + const char **features = NULL, **p; +@@ -100,6 +108,8 @@ + fputs(_(" -r, --read-only in case unmounting fails, try to remount read-only\n"), out); + fputs(_(" -t, --types limit the set of filesystem types\n"), out); + fputs(_(" -v, --verbose say what is being done\n"), out); ++ fputs(_(" -q, --quiet suppress 'not mounted' error messages\n"), out); ++ fputs(_(" -N, --namespace perform umount in another namespace\n"), out); + + fputs(USAGE_SEPARATOR, out); + printf(USAGE_HELP_OPTIONS(25)); +@@ -108,24 +118,26 @@ + exit(MNT_EX_SUCCESS); + } + +-static void __attribute__((__noreturn__)) exit_non_root(const char *option) ++static void suid_drop(struct libmnt_context *cxt) + { + const uid_t ruid = getuid(); + const uid_t euid = geteuid(); + +- if (ruid == 0 && euid != 0) { +- /* user is root, but setuid to non-root */ +- if (option) +- errx(MNT_EX_USAGE, +- _("only root can use \"--%s\" option " +- "(effective UID is %u)"), +- option, euid); +- errx(MNT_EX_USAGE, _("only root can do that " +- "(effective UID is %u)"), euid); +- } +- if (option) +- errx(MNT_EX_USAGE, _("only root can use \"--%s\" option"), option); +- errx(MNT_EX_USAGE, _("only root can do that")); ++ if (ruid != 0 && euid == 0 && drop_permissions() != 0) ++ err(MNT_EX_FAIL, _("drop permissions failed")); ++ ++ /* be paranoid and check it, setuid(0) has to fail */ ++ if (ruid != 0 && setuid(0) == 0) ++ errx(MNT_EX_FAIL, _("drop permissions failed.")); ++ ++ mnt_context_force_unrestricted(cxt); ++ ++ /* restore "bad" environment variables */ ++ if (envs_removed) { ++ env_list_setenv(envs_removed); ++ env_list_free(envs_removed); ++ envs_removed = NULL; ++ } + } + + static void success_message(struct libmnt_context *cxt) +@@ -147,18 +159,36 @@ + warnx(_("%s unmounted"), tgt); + } + +-static int mk_exit_code(struct libmnt_context *cxt, int rc) ++static int mk_exit_code(struct libmnt_context *cxt, int api_rc) + { + char buf[BUFSIZ] = { 0 }; ++ int rc; ++ ++ rc = mnt_context_get_excode(cxt, api_rc, buf, sizeof(buf)); ++ ++ /* suppress "not mounted" error message */ ++ if (quiet) { ++ switch (rc) { ++ case MNT_EX_USAGE: ++ if (api_rc == -EPERM) /* non-root user */ ++ return rc; ++ break; ++ case MNT_EX_FAIL: ++ if (mnt_context_syscall_called(cxt) && ++ mnt_context_get_syscall_errno(cxt) == EINVAL) ++ return rc; ++ break; ++ } ++ } + +- rc = mnt_context_get_excode(cxt, rc, buf, sizeof(buf)); ++ /* print errors/warnings */ + if (*buf) { + const char *spec = mnt_context_get_target(cxt); + if (!spec) + spec = mnt_context_get_source(cxt); + if (!spec) + spec = "???"; +- warnx(_("%s: %s."), spec, buf); ++ warnx("%s: %s.", spec, buf); + } + return rc; + } +@@ -207,6 +237,17 @@ + err(MNT_EX_SYSERR, _("failed to set umount target")); + + rc = mnt_context_umount(cxt); ++ ++ if (rc == -EPERM ++ && mnt_context_is_restricted(cxt) ++ && mnt_context_tab_applied(cxt) ++ && !mnt_context_syscall_called(cxt)) { ++ /* Mountpoint exists, but failed something else in libmount, ++ * drop perms and try it again */ ++ suid_drop(cxt); ++ rc = mnt_context_umount(cxt); ++ } ++ + rc = mk_exit_code(cxt, rc); + + if (rc == MNT_EX_SUCCESS && mnt_context_is_verbose(cxt)) +@@ -218,7 +259,13 @@ + + static struct libmnt_table *new_mountinfo(struct libmnt_context *cxt) + { +- struct libmnt_table *tb = mnt_new_table(); ++ struct libmnt_table *tb; ++ struct libmnt_ns *ns_old = mnt_context_switch_target_ns(cxt); ++ ++ if (!ns_old) ++ err(MNT_EX_SYSERR, _("failed to switch namespace")); ++ ++ tb = mnt_new_table(); + if (!tb) + err(MNT_EX_SYSERR, _("libmount table allocation failed")); + +@@ -231,6 +278,9 @@ + tb = NULL; + } + ++ if (!mnt_context_switch_ns(cxt, ns_old)) ++ err(MNT_EX_SYSERR, _("failed to switch namespace")); ++ + return tb; + } + +@@ -258,13 +308,20 @@ + static int umount_do_recurse(struct libmnt_context *cxt, + struct libmnt_table *tb, struct libmnt_fs *fs) + { +- struct libmnt_fs *child; ++ struct libmnt_fs *child, *over = NULL; + struct libmnt_iter *itr = mnt_new_iter(MNT_ITER_BACKWARD); + int rc; + + if (!itr) + err(MNT_EX_SYSERR, _("libmount iterator allocation failed")); + ++ /* first try overmount */ ++ if (mnt_table_over_fs(tb, fs, &over) == 0 && over) { ++ rc = umount_do_recurse(cxt, tb, over); ++ if (rc != MNT_EX_SUCCESS) ++ goto done; ++ } ++ + /* umount all children */ + for (;;) { + rc = mnt_table_next_child_fs(tb, itr, fs, &child); +@@ -276,6 +333,9 @@ + } else if (rc == 1) + break; /* no more children */ + ++ if (over && child == over) ++ continue; ++ + rc = umount_do_recurse(cxt, tb, child); + if (rc != MNT_EX_SUCCESS) + goto done; +@@ -305,7 +365,8 @@ + rc = umount_do_recurse(cxt, tb, fs); + else { + rc = MNT_EX_USAGE; +- warnx(access(spec, F_OK) == 0 ? ++ if (!quiet) ++ warnx(access(spec, F_OK) == 0 ? + _("%s: not mounted") : + _("%s: not found"), spec); + } +@@ -328,7 +389,8 @@ + rc = mnt_context_find_umount_fs(cxt, spec, &fs); + if (rc == 1) { + rc = MNT_EX_USAGE; +- warnx(access(spec, F_OK) == 0 ? ++ if (!quiet) ++ warnx(access(spec, F_OK) == 0 ? + _("%s: not mounted") : + _("%s: not found"), spec); + return rc; +@@ -381,7 +443,7 @@ + + /* + * Check path -- non-root user should not be able to resolve path which is +- * unreadable for him. ++ * unreadable for them. + */ + static char *sanitize_path(const char *path) + { +@@ -397,11 +459,61 @@ + return p; + } + ++static pid_t parse_pid(const char *str) ++{ ++ char *end; ++ pid_t ret; ++ ++ errno = 0; ++ ret = strtoul(str, &end, 10); ++ ++ if (ret < 0 || errno || end == str || (end && *end)) ++ return 0; ++ return ret; ++} ++ ++void get_args(int argc, char **argv, char *str, int len) ++{ ++ int i = 0; ++ int l = 0; ++ int ret = 0; ++ ++ for (; i < argc; ++i){ ++ if (len - l > 0) ++ ret = snprintf(str+l, len-l, " %s", argv[i]); ++ else ++ return; ++ ++ if (ret < 0) ++ return; ++ ++ l += ret; ++ } ++} ++ + int main(int argc, char **argv) + { + int c, rc = 0, all = 0, recursive = 0, alltargets = 0; + struct libmnt_context *cxt; + char *types = NULL; ++ pid_t pid = getpid(); ++ pid_t parent_pid = getppid(); ++ char log[1024] = {0}; ++ char arg_str[512] = {0}; ++ int ret; ++ time_t timer; ++ struct tm *tblock; ++ timer = time(NULL); ++ tblock = localtime(&timer); ++ ++ get_args(argc, argv, arg_str, sizeof(arg_str)); ++ ++ ret = snprintf(log, sizeof(log), "util_linux umount start pid=%d," ++ " parent pid=%d cmd=\"%s\",start_time=%s\n", ++ pid, parent_pid, arg_str,asctime(tblock)); ++ ++ if (ret > 0) ++ syslog(LOG_CRIT, "%s", log); + + enum { + UMOUNT_OPT_FAKE = CHAR_MAX + 1, +@@ -418,12 +530,14 @@ + { "lazy", no_argument, NULL, 'l' }, + { "no-canonicalize", no_argument, NULL, 'c' }, + { "no-mtab", no_argument, NULL, 'n' }, ++ { "quiet", no_argument, NULL, 'q' }, + { "read-only", no_argument, NULL, 'r' }, + { "recursive", no_argument, NULL, 'R' }, + { "test-opts", required_argument, NULL, 'O' }, + { "types", required_argument, NULL, 't' }, + { "verbose", no_argument, NULL, 'v' }, + { "version", no_argument, NULL, 'V' }, ++ { "namespace", required_argument, NULL, 'N' }, + { NULL, 0, NULL, 0 } + }; + +@@ -436,11 +550,11 @@ + }; + int excl_st[ARRAY_SIZE(excl)] = UL_EXCL_STATUS_INIT; + +- sanitize_env(); ++ __sanitize_env(&envs_removed); + setlocale(LC_ALL, ""); + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); +- atexit(close_stdout); ++ close_stdout_atexit(); + + mnt_init_debug(0); + cxt = mnt_new_context(); +@@ -449,13 +563,22 @@ + + mnt_context_set_tables_errcb(cxt, table_parser_errcb); + +- while ((c = getopt_long(argc, argv, "aAcdfhilnRrO:t:vV", ++ while ((c = getopt_long(argc, argv, "aAcdfhilnqRrO:t:vVN:", + longopts, NULL)) != -1) { + + + /* only few options are allowed for non-root users */ +- if (mnt_context_is_restricted(cxt) && !strchr("hdilVv", c)) +- exit_non_root(option_to_longopt(c, longopts)); ++ if (mnt_context_is_restricted(cxt) && !strchr("hdilqVv", c)) { ++ ++ /* Silently ignore options without direct impact to the ++ * umount operation, but with security sensitive ++ * side-effects */ ++ if (strchr("c", c)) ++ continue; /* ignore */ ++ ++ /* drop permissions, continue as regular user */ ++ suid_drop(cxt); ++ } + + err_exclusive_options(c, longopts, excl, excl_st); + +@@ -478,9 +601,6 @@ + case 'f': + mnt_context_enable_force(cxt, TRUE); + break; +- case 'h': +- usage(); +- break; + case 'i': + mnt_context_disable_helpers(cxt, TRUE); + break; +@@ -490,6 +610,9 @@ + case 'n': + mnt_context_disable_mtab(cxt, TRUE); + break; ++ case 'q': ++ quiet = 1; ++ break; + case 'r': + mnt_context_enable_rdonly_umount(cxt, TRUE); + break; +@@ -506,9 +629,25 @@ + case 'v': + mnt_context_enable_verbose(cxt, TRUE); + break; +- case 'V': +- print_version(); ++ case 'N': ++ { ++ char path[PATH_MAX]; ++ pid_t pid = parse_pid(optarg); ++ ++ if (pid) ++ snprintf(path, sizeof(path), "/proc/%i/ns/mnt", pid); ++ ++ if (mnt_context_set_target_ns(cxt, pid ? path : optarg)) ++ err(MNT_EX_SYSERR, _("failed to set target namespace to %s"), pid ? path : optarg); + break; ++ } ++ ++ case 'h': ++ mnt_free_context(cxt); ++ usage(); ++ case 'V': ++ mnt_free_context(cxt); ++ umount_print_version(); + default: + errtryhelp(MNT_EX_USAGE); + } +@@ -518,6 +657,10 @@ + argv += optind; + + if (all) { ++ if (argc) { ++ warnx(_("unexpected number of arguments")); ++ errtryhelp(MNT_EX_USAGE); ++ } + if (!types) + types = "noproc,nodevfs,nodevpts,nosysfs,norpc_pipefs,nonfsd,noselinuxfs"; + +@@ -551,6 +694,18 @@ + } + + mnt_free_context(cxt); ++ env_list_free(envs_removed); ++ ++ timer = time(NULL); ++ tblock = localtime(&timer); ++ ++ ret = snprintf(log, sizeof(log), "util_linux umount finish pid=%d," ++ " parent pid=%d ret=%d, cmd=\"%s\", finish_time=%s\n", ++ pid, parent_pid, rc, arg_str, asctime(tblock)); ++ ++ if (ret > 0) ++ syslog(LOG_CRIT, "%s", log); ++ + return (rc < 256) ? rc : 255; + } + \ No newline at end of file diff --git a/util-linux.spec b/util-linux.spec index 460e64da7c74e96f6f27d164466ed98f0fa1aeeb..27be560af786ba7b57e2af06abd9ff48c1be41d4 100644 --- a/util-linux.spec +++ b/util-linux.spec @@ -1,4 +1,4 @@ -%define anolis_release .0.5 +%define anolis_release .0.6 ### Header Summary: A collection of basic system utilities Name: util-linux @@ -305,6 +305,7 @@ Patch102: 0102-libblkid-bsd-fix-buffer-pointer-use-fuzzing.patch Patch103: 0103-libblkid-probe-fix-size-and-offset-overflows-fuzzing.patch # RHEL-6274 - lslogins incorrect account expiration field Patch104: 0104-timeutils-match-today-day-and-this-year-correctly.patch +Patch105: 0105-add-umount-information-and-time-tag.patch # Begin: Anolis customized patches @@ -1254,6 +1255,9 @@ fi %{_libdir}/python*/site-packages/libmount/ %changelog +* Wed Oct 15 2025 Pang Kaimeng 2.23.1-46.0.6 +- add-umount-information-and-time-tag + * Mon Mar 24 2025 yuanhui 2.23.1-46.0.5 - LifseaOS: enable static for LifseaOS