From d207f3d734a56d29057bd9cf079aab976c42176d Mon Sep 17 00:00:00 2001 From: yangmingtaip Date: Tue, 15 Feb 2022 20:23:34 +0800 Subject: [PATCH 1/3] fix CVE-2021-3997 and CVE-2021-33910 (cherry picked from commit 85f5ccb87604c04323553346f60ed2e64034260f) --- ...-fsync-after-removing-directory-tree.patch | 40 +++ ...m_rf_children-split-out-body-of-dire.patch | 321 ++++++++++++++++++ ...p-over-nested-directories-instead-of.patch | 273 +++++++++++++++ ...refactor-rm_rf-to-shorten-code-a-bit.patch | 100 ++++++ ...actor-rm_rf_children_inner-to-shorte.patch | 68 ++++ ...-st-may-have-been-used-uninitialized.patch | 28 ++ backport-fix-CVE-2021-33910.patch | 66 ++++ systemd.spec | 14 +- 8 files changed, 907 insertions(+), 3 deletions(-) create mode 100644 backport-CVE-2021-3997-rm-rf-optionally-fsync-after-removing-directory-tree.patch create mode 100644 backport-CVE-2021-3997-rm-rf-refactor-rm_rf_children-split-out-body-of-dire.patch create mode 100644 backport-CVE-2021-3997-shared-rm-rf-loop-over-nested-directories-instead-of.patch create mode 100644 backport-CVE-2021-3997-shared-rm_rf-refactor-rm_rf-to-shorten-code-a-bit.patch create mode 100644 backport-CVE-2021-3997-shared-rm_rf-refactor-rm_rf_children_inner-to-shorte.patch create mode 100644 backport-CVE-2021-3997-tmpfiles-st-may-have-been-used-uninitialized.patch create mode 100644 backport-fix-CVE-2021-33910.patch diff --git a/backport-CVE-2021-3997-rm-rf-optionally-fsync-after-removing-directory-tree.patch b/backport-CVE-2021-3997-rm-rf-optionally-fsync-after-removing-directory-tree.patch new file mode 100644 index 0000000..941da27 --- /dev/null +++ b/backport-CVE-2021-3997-rm-rf-optionally-fsync-after-removing-directory-tree.patch @@ -0,0 +1,40 @@ +From 2426beacca09d84091759be45b25c88116302184 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Tue, 5 Oct 2021 10:32:56 +0200 +Subject: [PATCH 2/6] rm-rf: optionally fsync() after removing directory tree + +(cherry picked from commit bdfe7ada0d4d66e6d6e65f2822acbb1ec230f9c2) +--- + src/shared/rm-rf.c | 3 +++ + src/shared/rm-rf.h | 1 + + 2 files changed, 4 insertions(+) + +diff --git a/src/shared/rm-rf.c b/src/shared/rm-rf.c +index dffb9cf6ee..5ef7c662dd 100644 +--- a/src/shared/rm-rf.c ++++ b/src/shared/rm-rf.c +@@ -250,6 +250,9 @@ int rm_rf_children( + ret = r; + } + ++ if (FLAGS_SET(flags, REMOVE_SYNCFS) && syncfs(dirfd(d)) < 0 && ret >= 0) ++ ret = -errno; ++ + return ret; + } + +diff --git a/src/shared/rm-rf.h b/src/shared/rm-rf.h +index 577a2795e0..24fd9a2aa2 100644 +--- a/src/shared/rm-rf.h ++++ b/src/shared/rm-rf.h +@@ -14,6 +14,7 @@ typedef enum RemoveFlags { + REMOVE_MISSING_OK = 1 << 4, /* If the top-level directory is missing, ignore the ENOENT for it */ + REMOVE_CHMOD = 1 << 5, /* chmod() for write access if we cannot delete or access something */ + REMOVE_CHMOD_RESTORE = 1 << 6, /* Restore the old mode before returning */ ++ REMOVE_SYNCFS = 1 << 7, /* syncfs() the root of the specified directory after removing everything in it */ + } RemoveFlags; + + int unlinkat_harder(int dfd, const char *filename, int unlink_flags, RemoveFlags remove_flags); +-- +2.27.0 + diff --git a/backport-CVE-2021-3997-rm-rf-refactor-rm_rf_children-split-out-body-of-dire.patch b/backport-CVE-2021-3997-rm-rf-refactor-rm_rf_children-split-out-body-of-dire.patch new file mode 100644 index 0000000..d7222c4 --- /dev/null +++ b/backport-CVE-2021-3997-rm-rf-refactor-rm_rf_children-split-out-body-of-dire.patch @@ -0,0 +1,321 @@ +From ca4a0e7d41f0b2a1fe2f99dbc3763187c16cf7ab Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Tue, 26 Jan 2021 16:30:06 +0100 +Subject: [PATCH 1/6] rm-rf: refactor rm_rf_children(), split out body of + directory iteration loop + +This splits out rm_rf_children_inner() as body of the loop. We can use +that to implement rm_rf_child() for deleting one specific entry in a +directory. + +(cherry picked from commit 1f0fb7d544711248cba34615e43c5a76bc902d74) +--- + src/shared/rm-rf.c | 223 ++++++++++++++++++++++++++------------------- + src/shared/rm-rf.h | 3 +- + 2 files changed, 131 insertions(+), 95 deletions(-) + +diff --git a/src/shared/rm-rf.c b/src/shared/rm-rf.c +index 900a7fb5ff..dffb9cf6ee 100644 +--- a/src/shared/rm-rf.c ++++ b/src/shared/rm-rf.c +@@ -19,6 +19,9 @@ + #include "stat-util.h" + #include "string-util.h" + ++/* We treat tmpfs/ramfs + cgroupfs as non-physical file sytems. cgroupfs is similar to tmpfs in a way after ++ * all: we can create arbitrary directory hierarchies in it, and hence can also use rm_rf() on it to remove ++ * those again. */ + static bool is_physical_fs(const struct statfs *sfs) { + return !is_temporary_fs(sfs) && !is_cgroup_fs(sfs); + } +@@ -113,133 +116,145 @@ int fstatat_harder(int dfd, + return 0; + } + +-int rm_rf_children(int fd, RemoveFlags flags, struct stat *root_dev) { +- _cleanup_closedir_ DIR *d = NULL; +- struct dirent *de; +- int ret = 0, r; +- struct statfs sfs; ++static int rm_rf_children_inner( ++ int fd, ++ const char *fname, ++ int is_dir, ++ RemoveFlags flags, ++ const struct stat *root_dev) { + +- assert(fd >= 0); ++ struct stat st; ++ int r; + +- /* This returns the first error we run into, but nevertheless tries to go on. This closes the passed +- * fd, in all cases, including on failure.. */ ++ assert(fd >= 0); ++ assert(fname); + +- if (!(flags & REMOVE_PHYSICAL)) { ++ if (is_dir < 0 || (is_dir > 0 && (root_dev || (flags & REMOVE_SUBVOLUME)))) { + +- r = fstatfs(fd, &sfs); +- if (r < 0) { +- safe_close(fd); +- return -errno; +- } ++ r = fstatat_harder(fd, fname, &st, AT_SYMLINK_NOFOLLOW, flags); ++ if (r < 0) ++ return r; + +- if (is_physical_fs(&sfs)) { +- /* We refuse to clean physical file systems with this call, +- * unless explicitly requested. This is extra paranoia just +- * to be sure we never ever remove non-state data. */ +- _cleanup_free_ char *path = NULL; ++ is_dir = S_ISDIR(st.st_mode); ++ } + +- (void) fd_get_path(fd, &path); +- log_error("Attempted to remove disk file system under \"%s\", and we can't allow that.", +- strna(path)); ++ if (is_dir) { ++ _cleanup_close_ int subdir_fd = -1; ++ int q; + +- safe_close(fd); +- return -EPERM; +- } +- } ++ /* if root_dev is set, remove subdirectories only if device is same */ ++ if (root_dev && st.st_dev != root_dev->st_dev) ++ return 0; + +- d = fdopendir(fd); +- if (!d) { +- safe_close(fd); +- return errno == ENOENT ? 0 : -errno; +- } ++ /* Stop at mount points */ ++ r = fd_is_mount_point(fd, fname, 0); ++ if (r < 0) ++ return r; ++ if (r > 0) ++ return 0; + +- FOREACH_DIRENT_ALL(de, d, return -errno) { +- bool is_dir; +- struct stat st; ++ if ((flags & REMOVE_SUBVOLUME) && btrfs_might_be_subvol(&st)) { + +- if (dot_or_dot_dot(de->d_name)) +- continue; ++ /* This could be a subvolume, try to remove it */ + +- if (de->d_type == DT_UNKNOWN || +- (de->d_type == DT_DIR && (root_dev || (flags & REMOVE_SUBVOLUME)))) { +- r = fstatat_harder(fd, de->d_name, &st, AT_SYMLINK_NOFOLLOW, flags); ++ r = btrfs_subvol_remove_fd(fd, fname, BTRFS_REMOVE_RECURSIVE|BTRFS_REMOVE_QUOTA); + if (r < 0) { +- if (ret == 0 && r != -ENOENT) +- ret = r; +- continue; +- } ++ if (!IN_SET(r, -ENOTTY, -EINVAL)) ++ return r; + +- is_dir = S_ISDIR(st.st_mode); +- } else +- is_dir = de->d_type == DT_DIR; ++ /* ENOTTY, then it wasn't a btrfs subvolume, continue below. */ ++ } else ++ /* It was a subvolume, done. */ ++ return 1; ++ } + +- if (is_dir) { +- _cleanup_close_ int subdir_fd = -1; ++ subdir_fd = openat(fd, fname, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW|O_NOATIME); ++ if (subdir_fd < 0) ++ return -errno; + +- /* if root_dev is set, remove subdirectories only if device is same */ +- if (root_dev && st.st_dev != root_dev->st_dev) +- continue; ++ /* We pass REMOVE_PHYSICAL here, to avoid doing the fstatfs() to check the file system type ++ * again for each directory */ ++ q = rm_rf_children(TAKE_FD(subdir_fd), flags | REMOVE_PHYSICAL, root_dev); + +- subdir_fd = openat(fd, de->d_name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW|O_NOATIME); +- if (subdir_fd < 0) { +- if (ret == 0 && errno != ENOENT) +- ret = -errno; +- continue; +- } ++ r = unlinkat_harder(fd, fname, AT_REMOVEDIR, flags); ++ if (r < 0) ++ return r; ++ if (q < 0) ++ return q; + +- /* Stop at mount points */ +- r = fd_is_mount_point(fd, de->d_name, 0); +- if (r < 0) { +- if (ret == 0 && r != -ENOENT) +- ret = r; ++ return 1; + +- continue; +- } +- if (r > 0) +- continue; ++ } else if (!(flags & REMOVE_ONLY_DIRECTORIES)) { ++ r = unlinkat_harder(fd, fname, 0, flags); ++ if (r < 0) ++ return r; + +- if ((flags & REMOVE_SUBVOLUME) && btrfs_might_be_subvol(&st)) { ++ return 1; ++ } + +- /* This could be a subvolume, try to remove it */ ++ return 0; ++} + +- r = btrfs_subvol_remove_fd(fd, de->d_name, BTRFS_REMOVE_RECURSIVE|BTRFS_REMOVE_QUOTA); +- if (r < 0) { +- if (!IN_SET(r, -ENOTTY, -EINVAL)) { +- if (ret == 0) +- ret = r; ++int rm_rf_children( ++ int fd, ++ RemoveFlags flags, ++ const struct stat *root_dev) { + +- continue; +- } ++ _cleanup_closedir_ DIR *d = NULL; ++ struct dirent *de; ++ int ret = 0, r; + +- /* ENOTTY, then it wasn't a btrfs subvolume, continue below. */ +- } else +- /* It was a subvolume, continue. */ +- continue; +- } ++ assert(fd >= 0); ++ ++ /* This returns the first error we run into, but nevertheless tries to go on. This closes the passed ++ * fd, in all cases, including on failure. */ ++ ++ d = fdopendir(fd); ++ if (!d) { ++ safe_close(fd); ++ return -errno; ++ } + +- /* We pass REMOVE_PHYSICAL here, to avoid doing the fstatfs() to check the file +- * system type again for each directory */ +- r = rm_rf_children(TAKE_FD(subdir_fd), flags | REMOVE_PHYSICAL, root_dev); +- if (r < 0 && ret == 0) +- ret = r; ++ if (!(flags & REMOVE_PHYSICAL)) { ++ struct statfs sfs; + +- r = unlinkat_harder(fd, de->d_name, AT_REMOVEDIR, flags); +- if (r < 0 && r != -ENOENT && ret == 0) +- ret = r; ++ if (fstatfs(dirfd(d), &sfs) < 0) ++ return -errno; ++ ++ if (is_physical_fs(&sfs)) { ++ /* We refuse to clean physical file systems with this call, unless explicitly ++ * requested. This is extra paranoia just to be sure we never ever remove non-state ++ * data. */ + +- } else if (!(flags & REMOVE_ONLY_DIRECTORIES)) { ++ _cleanup_free_ char *path = NULL; + +- r = unlinkat_harder(fd, de->d_name, 0, flags); +- if (r < 0 && r != -ENOENT && ret == 0) +- ret = r; ++ (void) fd_get_path(fd, &path); ++ return log_error_errno(SYNTHETIC_ERRNO(EPERM), ++ "Attempted to remove disk file system under \"%s\", and we can't allow that.", ++ strna(path)); + } + } ++ ++ FOREACH_DIRENT_ALL(de, d, return -errno) { ++ int is_dir; ++ ++ if (dot_or_dot_dot(de->d_name)) ++ continue; ++ ++ is_dir = ++ de->d_type == DT_UNKNOWN ? -1 : ++ de->d_type == DT_DIR; ++ ++ r = rm_rf_children_inner(dirfd(d), de->d_name, is_dir, flags, root_dev); ++ if (r < 0 && r != -ENOENT && ret == 0) ++ ret = r; ++ } ++ + return ret; + } + + int rm_rf(const char *path, RemoveFlags flags) { + int fd, r; +- struct statfs s; + + assert(path); + +@@ -284,9 +299,10 @@ int rm_rf(const char *path, RemoveFlags flags) { + if (FLAGS_SET(flags, REMOVE_ROOT)) { + + if (!FLAGS_SET(flags, REMOVE_PHYSICAL)) { ++ struct statfs s; ++ + if (statfs(path, &s) < 0) + return -errno; +- + if (is_physical_fs(&s)) + return log_error_errno(SYNTHETIC_ERRNO(EPERM), + "Attempted to remove files from a disk file system under \"%s\", refusing.", +@@ -314,3 +330,22 @@ int rm_rf(const char *path, RemoveFlags flags) { + + return r; + } ++ ++int rm_rf_child(int fd, const char *name, RemoveFlags flags) { ++ ++ /* Removes one specific child of the specified directory */ ++ ++ if (fd < 0) ++ return -EBADF; ++ ++ if (!filename_is_valid(name)) ++ return -EINVAL; ++ ++ if ((flags & (REMOVE_ROOT|REMOVE_MISSING_OK)) != 0) /* Doesn't really make sense here, we are not supposed to remove 'fd' anyway */ ++ return -EINVAL; ++ ++ if (FLAGS_SET(flags, REMOVE_ONLY_DIRECTORIES|REMOVE_SUBVOLUME)) ++ return -EINVAL; ++ ++ return rm_rf_children_inner(fd, name, -1, flags, NULL); ++} +diff --git a/src/shared/rm-rf.h b/src/shared/rm-rf.h +index 40f0894c96..577a2795e0 100644 +--- a/src/shared/rm-rf.h ++++ b/src/shared/rm-rf.h +@@ -23,7 +23,8 @@ int fstatat_harder(int dfd, + int fstatat_flags, + RemoveFlags remove_flags); + +-int rm_rf_children(int fd, RemoveFlags flags, struct stat *root_dev); ++int rm_rf_children(int fd, RemoveFlags flags, const struct stat *root_dev); ++int rm_rf_child(int fd, const char *name, RemoveFlags flags); + int rm_rf(const char *path, RemoveFlags flags); + + /* Useful for usage with _cleanup_(), destroys a directory and frees the pointer */ +-- +2.27.0 + diff --git a/backport-CVE-2021-3997-shared-rm-rf-loop-over-nested-directories-instead-of.patch b/backport-CVE-2021-3997-shared-rm-rf-loop-over-nested-directories-instead-of.patch new file mode 100644 index 0000000..803a078 --- /dev/null +++ b/backport-CVE-2021-3997-shared-rm-rf-loop-over-nested-directories-instead-of.patch @@ -0,0 +1,273 @@ +From 6a28f8b55904c818b25e4db2e1511faac79fd471 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= +Date: Tue, 30 Nov 2021 22:29:05 +0100 +Subject: [PATCH 6/6] shared/rm-rf: loop over nested directories instead of + instead of recursing + +To remove directory structures, we need to remove the innermost items first, +and then recursively remove higher-level directories. We would recursively +descend into directories and invoke rm_rf_children and rm_rm_children_inner. +This is problematic when too many directories are nested. + +Instead, let's create a "TODO" queue. In the the queue, for each level we +hold the DIR* object we were working on, and the name of the directory. This +allows us to leave a partially-processed directory, and restart the removal +loop one level down. When done with the inner directory, we use the name to +unlinkat() it from the parent, and proceed with the removal of other items. + +Because the nesting is increased by one level, it is best to view this patch +with -b/--ignore-space-change. + +This fixes CVE-2021-3997, https://bugzilla.redhat.com/show_bug.cgi?id=2024639. +The issue was reported and patches reviewed by Qualys Team. +Mauro Matteo Cascella and Riccardo Schirone from Red Hat handled the disclosure. + +(cherry picked from commit 5b1cf7a9be37e20133c0208005274ce4a5b5c6a1) +(cherry picked from commit 911516e1614e435755814ada5fc6064fa107a105) +--- + src/shared/rm-rf.c | 161 +++++++++++++++++++++++++++++++-------------- + 1 file changed, 113 insertions(+), 48 deletions(-) + +diff --git a/src/shared/rm-rf.c b/src/shared/rm-rf.c +index 1bd2431d8a..954686ffc9 100644 +--- a/src/shared/rm-rf.c ++++ b/src/shared/rm-rf.c +@@ -52,7 +52,6 @@ static int patch_dirfd_mode( + } + + int unlinkat_harder(int dfd, const char *filename, int unlink_flags, RemoveFlags remove_flags) { +- + mode_t old_mode; + int r; + +@@ -116,12 +115,13 @@ int fstatat_harder(int dfd, + return 0; + } + +-static int rm_rf_children_inner( ++static int rm_rf_inner_child( + int fd, + const char *fname, + int is_dir, + RemoveFlags flags, +- const struct stat *root_dev) { ++ const struct stat *root_dev, ++ bool allow_recursion) { + + struct stat st; + int r, q = 0; +@@ -141,9 +141,7 @@ static int rm_rf_children_inner( + } + + if (is_dir) { +- _cleanup_close_ int subdir_fd = -1; +- +- /* if root_dev is set, remove subdirectories only if device is same */ ++ /* If root_dev is set, remove subdirectories only if device is same */ + if (root_dev && st.st_dev != root_dev->st_dev) + return 0; + +@@ -155,7 +153,6 @@ static int rm_rf_children_inner( + return 0; + + if ((flags & REMOVE_SUBVOLUME) && btrfs_might_be_subvol(&st)) { +- + /* This could be a subvolume, try to remove it */ + + r = btrfs_subvol_remove_fd(fd, fname, BTRFS_REMOVE_RECURSIVE|BTRFS_REMOVE_QUOTA); +@@ -169,13 +166,16 @@ static int rm_rf_children_inner( + return 1; + } + +- subdir_fd = openat(fd, fname, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW|O_NOATIME); ++ if (!allow_recursion) ++ return -EISDIR; ++ ++ int subdir_fd = openat(fd, fname, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW|O_NOATIME); + if (subdir_fd < 0) + return -errno; + + /* We pass REMOVE_PHYSICAL here, to avoid doing the fstatfs() to check the file system type + * again for each directory */ +- q = rm_rf_children(TAKE_FD(subdir_fd), flags | REMOVE_PHYSICAL, root_dev); ++ q = rm_rf_children(subdir_fd, flags | REMOVE_PHYSICAL, root_dev); + + } else if (flags & REMOVE_ONLY_DIRECTORIES) + return 0; +@@ -188,63 +188,128 @@ static int rm_rf_children_inner( + return 1; + } + ++typedef struct TodoEntry { ++ DIR *dir; /* A directory that we were operating on. */ ++ char *dirname; /* The filename of that directory itself. */ ++} TodoEntry; ++ ++static void free_todo_entries(TodoEntry **todos) { ++ for (TodoEntry *x = *todos; x && x->dir; x++) { ++ closedir(x->dir); ++ free(x->dirname); ++ } ++ ++ freep(todos); ++} ++ + int rm_rf_children( + int fd, + RemoveFlags flags, + const struct stat *root_dev) { + +- _cleanup_closedir_ DIR *d = NULL; +- struct dirent *de; ++ _cleanup_(free_todo_entries) TodoEntry *todos = NULL; ++ size_t n_todo = 0; ++ _cleanup_free_ char *dirname = NULL; /* Set when we are recursing and want to delete ourselves */ + int ret = 0, r; + +- assert(fd >= 0); ++ /* Return the first error we run into, but nevertheless try to go on. ++ * The passed fd is closed in all cases, including on failure. */ ++ ++ for (;;) { /* This loop corresponds to the directory nesting level. */ ++ _cleanup_closedir_ DIR *d = NULL; ++ ++ if (n_todo > 0) { ++ /* We know that we are in recursion here, because n_todo is set. ++ * We need to remove the inner directory we were operating on. */ ++ assert(dirname); ++ r = unlinkat_harder(dirfd(todos[n_todo-1].dir), dirname, AT_REMOVEDIR, flags); ++ if (r < 0 && r != -ENOENT && ret == 0) ++ ret = r; ++ dirname = mfree(dirname); ++ ++ /* And now let's back out one level up */ ++ n_todo --; ++ d = TAKE_PTR(todos[n_todo].dir); ++ dirname = TAKE_PTR(todos[n_todo].dirname); ++ ++ assert(d); ++ fd = dirfd(d); /* Retrieve the file descriptor from the DIR object */ ++ assert(fd >= 0); ++ } else { ++ next_fd: ++ assert(fd >= 0); ++ d = fdopendir(fd); ++ if (!d) { ++ safe_close(fd); ++ return -errno; ++ } ++ fd = dirfd(d); /* We donated the fd to fdopendir(). Let's make sure we sure we have ++ * the right descriptor even if it were to internally invalidate the ++ * one we passed. */ ++ ++ if (!(flags & REMOVE_PHYSICAL)) { ++ struct statfs sfs; ++ ++ if (fstatfs(fd, &sfs) < 0) ++ return -errno; ++ ++ if (is_physical_fs(&sfs)) { ++ /* We refuse to clean physical file systems with this call, unless ++ * explicitly requested. This is extra paranoia just to be sure we ++ * never ever remove non-state data. */ ++ ++ _cleanup_free_ char *path = NULL; ++ ++ (void) fd_get_path(fd, &path); ++ return log_error_errno(SYNTHETIC_ERRNO(EPERM), ++ "Attempted to remove disk file system under \"%s\", and we can't allow that.", ++ strna(path)); ++ } ++ } ++ } + +- /* This returns the first error we run into, but nevertheless tries to go on. This closes the passed +- * fd, in all cases, including on failure. */ ++ struct dirent *de; ++ FOREACH_DIRENT_ALL(de, d, return -errno) { ++ int is_dir; + +- d = fdopendir(fd); +- if (!d) { +- safe_close(fd); +- return -errno; +- } ++ if (dot_or_dot_dot(de->d_name)) ++ continue; + +- if (!(flags & REMOVE_PHYSICAL)) { +- struct statfs sfs; ++ is_dir = de->d_type == DT_UNKNOWN ? -1 : de->d_type == DT_DIR; + +- if (fstatfs(dirfd(d), &sfs) < 0) +- return -errno; ++ r = rm_rf_inner_child(fd, de->d_name, is_dir, flags, root_dev, false); ++ if (r == -EISDIR) { ++ /* Push the current working state onto the todo list */ + +- if (is_physical_fs(&sfs)) { +- /* We refuse to clean physical file systems with this call, unless explicitly +- * requested. This is extra paranoia just to be sure we never ever remove non-state +- * data. */ ++ if (!GREEDY_REALLOC0(todos, n_todo + 2)) ++ return log_oom(); + +- _cleanup_free_ char *path = NULL; ++ _cleanup_free_ char *newdirname = strdup(de->d_name); ++ if (!newdirname) ++ return log_oom(); + +- (void) fd_get_path(fd, &path); +- return log_error_errno(SYNTHETIC_ERRNO(EPERM), +- "Attempted to remove disk file system under \"%s\", and we can't allow that.", +- strna(path)); +- } +- } ++ int newfd = openat(fd, de->d_name, ++ O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW|O_NOATIME); ++ if (newfd >= 0) { ++ todos[n_todo++] = (TodoEntry) { TAKE_PTR(d), TAKE_PTR(dirname) }; ++ fd = newfd; ++ dirname = TAKE_PTR(newdirname); + +- FOREACH_DIRENT_ALL(de, d, return -errno) { +- int is_dir; ++ goto next_fd; + +- if (dot_or_dot_dot(de->d_name)) +- continue; ++ } else if (errno != -ENOENT && ret == 0) ++ ret = -errno; + +- is_dir = +- de->d_type == DT_UNKNOWN ? -1 : +- de->d_type == DT_DIR; ++ } else if (r < 0 && r != -ENOENT && ret == 0) ++ ret = r; ++ } + +- r = rm_rf_children_inner(dirfd(d), de->d_name, is_dir, flags, root_dev); +- if (r < 0 && r != -ENOENT && ret == 0) +- ret = r; +- } ++ if (FLAGS_SET(flags, REMOVE_SYNCFS) && syncfs(fd) < 0 && ret >= 0) ++ ret = -errno; + +- if (FLAGS_SET(flags, REMOVE_SYNCFS) && syncfs(dirfd(d)) < 0 && ret >= 0) +- ret = -errno; ++ if (n_todo == 0) ++ break; ++ } + + return ret; + } +@@ -337,5 +402,5 @@ int rm_rf_child(int fd, const char *name, RemoveFlags flags) { + if (FLAGS_SET(flags, REMOVE_ONLY_DIRECTORIES|REMOVE_SUBVOLUME)) + return -EINVAL; + +- return rm_rf_children_inner(fd, name, -1, flags, NULL); ++ return rm_rf_inner_child(fd, name, -1, flags, NULL, true); + } +-- +2.27.0 + diff --git a/backport-CVE-2021-3997-shared-rm_rf-refactor-rm_rf-to-shorten-code-a-bit.patch b/backport-CVE-2021-3997-shared-rm_rf-refactor-rm_rf-to-shorten-code-a-bit.patch new file mode 100644 index 0000000..ee920f6 --- /dev/null +++ b/backport-CVE-2021-3997-shared-rm_rf-refactor-rm_rf-to-shorten-code-a-bit.patch @@ -0,0 +1,100 @@ +From 811b137d6137cc3e8932599e6ef9254ba43ff5eb Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= +Date: Tue, 23 Nov 2021 16:56:42 +0100 +Subject: [PATCH 5/6] shared/rm_rf: refactor rm_rf() to shorten code a bit + +(cherry picked from commit 84ced330020c0bae57bd4628f1f44eec91304e69) +(cherry picked from commit 664529efa9431edc043126013ea54e6c399ae2d3) +--- + src/shared/rm-rf.c | 54 +++++++++++++++++++++------------------------- + 1 file changed, 24 insertions(+), 30 deletions(-) + +diff --git a/src/shared/rm-rf.c b/src/shared/rm-rf.c +index 7362954116..1bd2431d8a 100644 +--- a/src/shared/rm-rf.c ++++ b/src/shared/rm-rf.c +@@ -250,7 +250,7 @@ int rm_rf_children( + } + + int rm_rf(const char *path, RemoveFlags flags) { +- int fd, r; ++ int fd, r, q = 0; + + assert(path); + +@@ -282,49 +282,43 @@ int rm_rf(const char *path, RemoveFlags flags) { + } + + fd = open(path, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW|O_NOATIME); +- if (fd < 0) { ++ if (fd >= 0) { ++ /* We have a dir */ ++ r = rm_rf_children(fd, flags, NULL); ++ ++ if (FLAGS_SET(flags, REMOVE_ROOT) && rmdir(path) < 0) ++ q = -errno; ++ } else { + if (FLAGS_SET(flags, REMOVE_MISSING_OK) && errno == ENOENT) + return 0; + + if (!IN_SET(errno, ENOTDIR, ELOOP)) + return -errno; + +- if (FLAGS_SET(flags, REMOVE_ONLY_DIRECTORIES)) ++ if (FLAGS_SET(flags, REMOVE_ONLY_DIRECTORIES) || !FLAGS_SET(flags, REMOVE_ROOT)) + return 0; + +- if (FLAGS_SET(flags, REMOVE_ROOT)) { +- +- if (!FLAGS_SET(flags, REMOVE_PHYSICAL)) { +- struct statfs s; +- +- if (statfs(path, &s) < 0) +- return -errno; +- if (is_physical_fs(&s)) +- return log_error_errno(SYNTHETIC_ERRNO(EPERM), +- "Attempted to remove files from a disk file system under \"%s\", refusing.", +- path); +- } +- +- if (unlink(path) < 0) { +- if (FLAGS_SET(flags, REMOVE_MISSING_OK) && errno == ENOENT) +- return 0; ++ if (!FLAGS_SET(flags, REMOVE_PHYSICAL)) { ++ struct statfs s; + ++ if (statfs(path, &s) < 0) + return -errno; +- } ++ if (is_physical_fs(&s)) ++ return log_error_errno(SYNTHETIC_ERRNO(EPERM), ++ "Attempted to remove files from a disk file system under \"%s\", refusing.", ++ path); + } + +- return 0; ++ r = 0; ++ if (unlink(path) < 0) ++ q = -errno; + } + +- r = rm_rf_children(fd, flags, NULL); +- +- if (FLAGS_SET(flags, REMOVE_ROOT) && +- rmdir(path) < 0 && +- r >= 0 && +- (!FLAGS_SET(flags, REMOVE_MISSING_OK) || errno != ENOENT)) +- r = -errno; +- +- return r; ++ if (r < 0) ++ return r; ++ if (q < 0 && (q != -ENOENT || !FLAGS_SET(flags, REMOVE_MISSING_OK))) ++ return q; ++ return 0; + } + + int rm_rf_child(int fd, const char *name, RemoveFlags flags) { +-- +2.27.0 + diff --git a/backport-CVE-2021-3997-shared-rm_rf-refactor-rm_rf_children_inner-to-shorte.patch b/backport-CVE-2021-3997-shared-rm_rf-refactor-rm_rf_children_inner-to-shorte.patch new file mode 100644 index 0000000..b81bd34 --- /dev/null +++ b/backport-CVE-2021-3997-shared-rm_rf-refactor-rm_rf_children_inner-to-shorte.patch @@ -0,0 +1,68 @@ +From 89395b63f04f1acc0db533c32637ea20379f97c0 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= +Date: Tue, 23 Nov 2021 15:55:45 +0100 +Subject: [PATCH 4/6] shared/rm_rf: refactor rm_rf_children_inner() to shorten + code a bit + +(cherry picked from commit 3bac86abfa1b1720180840ffb9d06b3d54841c11) +(cherry picked from commit 47741ff9eae6311a03e4d3d837128191826a4a3a) +--- + src/shared/rm-rf.c | 27 +++++++++------------------ + 1 file changed, 9 insertions(+), 18 deletions(-) + +diff --git a/src/shared/rm-rf.c b/src/shared/rm-rf.c +index 19f37e0f19..7362954116 100644 +--- a/src/shared/rm-rf.c ++++ b/src/shared/rm-rf.c +@@ -124,7 +124,7 @@ static int rm_rf_children_inner( + const struct stat *root_dev) { + + struct stat st; +- int r; ++ int r, q = 0; + + assert(fd >= 0); + assert(fname); +@@ -142,7 +142,6 @@ static int rm_rf_children_inner( + + if (is_dir) { + _cleanup_close_ int subdir_fd = -1; +- int q; + + /* if root_dev is set, remove subdirectories only if device is same */ + if (root_dev && st.st_dev != root_dev->st_dev) +@@ -178,23 +177,15 @@ static int rm_rf_children_inner( + * again for each directory */ + q = rm_rf_children(TAKE_FD(subdir_fd), flags | REMOVE_PHYSICAL, root_dev); + +- r = unlinkat_harder(fd, fname, AT_REMOVEDIR, flags); +- if (r < 0) +- return r; +- if (q < 0) +- return q; +- +- return 1; +- +- } else if (!(flags & REMOVE_ONLY_DIRECTORIES)) { +- r = unlinkat_harder(fd, fname, 0, flags); +- if (r < 0) +- return r; +- +- return 1; +- } ++ } else if (flags & REMOVE_ONLY_DIRECTORIES) ++ return 0; + +- return 0; ++ r = unlinkat_harder(fd, fname, is_dir ? AT_REMOVEDIR : 0, flags); ++ if (r < 0) ++ return r; ++ if (q < 0) ++ return q; ++ return 1; + } + + int rm_rf_children( +-- +2.27.0 + diff --git a/backport-CVE-2021-3997-tmpfiles-st-may-have-been-used-uninitialized.patch b/backport-CVE-2021-3997-tmpfiles-st-may-have-been-used-uninitialized.patch new file mode 100644 index 0000000..4bb3fc8 --- /dev/null +++ b/backport-CVE-2021-3997-tmpfiles-st-may-have-been-used-uninitialized.patch @@ -0,0 +1,28 @@ +From 7563de501246dccf5a9ea229933481aa1e7bd5c9 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= +Date: Tue, 23 Nov 2021 15:05:58 +0100 +Subject: [PATCH 3/6] tmpfiles: 'st' may have been used uninitialized + +(cherry picked from commit 160dadc0350c77d612aa9d5569f57d9bc84c3dca) +--- + src/shared/rm-rf.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/src/shared/rm-rf.c b/src/shared/rm-rf.c +index 5ef7c662dd..19f37e0f19 100644 +--- a/src/shared/rm-rf.c ++++ b/src/shared/rm-rf.c +@@ -129,7 +129,9 @@ static int rm_rf_children_inner( + assert(fd >= 0); + assert(fname); + +- if (is_dir < 0 || (is_dir > 0 && (root_dev || (flags & REMOVE_SUBVOLUME)))) { ++ if (is_dir < 0 || ++ root_dev || ++ (is_dir > 0 && (root_dev || (flags & REMOVE_SUBVOLUME)))) { + + r = fstatat_harder(fd, fname, &st, AT_SYMLINK_NOFOLLOW, flags); + if (r < 0) +-- +2.27.0 + diff --git a/backport-fix-CVE-2021-33910.patch b/backport-fix-CVE-2021-33910.patch new file mode 100644 index 0000000..e0a971f --- /dev/null +++ b/backport-fix-CVE-2021-33910.patch @@ -0,0 +1,66 @@ +From 441e0115646d54f080e5c3bb0ba477c892861ab9 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= +Date: Wed, 23 Jun 2021 11:46:41 +0200 +Subject: [PATCH] basic/unit-name: do not use strdupa() on a path + +The path may have unbounded length, for example through a fuse mount. + +CVE-2021-33910: attacked controlled alloca() leads to crash in systemd and +ultimately a kernel panic. Systemd parses the content of /proc/self/mountinfo +and each mountpoint is passed to mount_setup_unit(), which calls +unit_name_path_escape() underneath. A local attacker who is able to mount a +filesystem with a very long path can crash systemd and the whole system. + +https://bugzilla.redhat.com/show_bug.cgi?id=1970887 + +The resulting string length is bounded by UNIT_NAME_MAX, which is 256. But we +can't easily check the length after simplification before doing the +simplification, which in turns uses a copy of the string we can write to. +So we can't reject paths that are too long before doing the duplication. +Hence the most obvious solution is to switch back to strdup(), as before +7410616cd9dbbec97cf98d75324da5cda2b2f7a2. + +https://github.com/systemd/systemd/pull/20256/commits/441e0115646d54f080e5c3bb0ba477c892861ab9 +--- + src/basic/unit-name.c | 13 +++++-------- + 1 file changed, 5 insertions(+), 8 deletions(-) + +diff --git a/src/basic/unit-name.c b/src/basic/unit-name.c +index 532f8fa..024b8a5 100644 +--- a/src/basic/unit-name.c ++++ b/src/basic/unit-name.c +@@ -378,12 +378,13 @@ int unit_name_unescape(const char *f, char **ret) { + } + + int unit_name_path_escape(const char *f, char **ret) { +- char *p, *s; ++ _cleanup_free_ char *p = NULL; ++ char *s; + + assert(f); + assert(ret); + +- p = strdupa(f); ++ p = strdup(f); + if (!p) + return -ENOMEM; + +@@ -395,13 +396,9 @@ int unit_name_path_escape(const char *f, char **ret) { + if (!path_is_normalized(p)) + return -EINVAL; + +- /* Truncate trailing slashes */ ++ /* Truncate trailing slashes and skip leading slashes */ + delete_trailing_chars(p, "/"); +- +- /* Truncate leading slashes */ +- p = skip_leading_chars(p, "/"); +- +- s = unit_name_escape(p); ++ s = unit_name_escape(skip_leading_chars(p, "/")); + } + if (!s) + return -ENOMEM; +-- +2.23.0 + diff --git a/systemd.spec b/systemd.spec index 2aebd7e..8ccf79e 100644 --- a/systemd.spec +++ b/systemd.spec @@ -20,7 +20,7 @@ Name: systemd Url: https://www.freedesktop.org/wiki/Software/systemd Version: 249 -Release: 4 +Release: 5 License: MIT and LGPLv2+ and GPLv2+ Summary: System and Service Manager @@ -69,8 +69,13 @@ Patch6000: backport-core-fix-free-undefined-pointer-when-strdup-failed-i.pa Patch6001: backport-fix-ConditionDirectoryNotEmpty-when-it-comes-to-a-No.patch Patch6002: backport-fix-ConditionPathIsReadWrite-when-path-does-not-exis.patch Patch6003: backport-fix-DirectoryNotEmpty-when-it-comes-to-a-Non-directo.patch - -#openEuler +Patch6004: backport-CVE-2021-3997-rm-rf-refactor-rm_rf_children-split-out-body-of-dire.patch +Patch6005: backport-CVE-2021-3997-rm-rf-optionally-fsync-after-removing-directory-tree.patch +Patch6006: backport-CVE-2021-3997-tmpfiles-st-may-have-been-used-uninitialized.patch +Patch6007: backport-CVE-2021-3997-shared-rm_rf-refactor-rm_rf_children_inner-to-shorte.patch +Patch6008: backport-CVE-2021-3997-shared-rm_rf-refactor-rm_rf-to-shorten-code-a-bit.patch +Patch6009: backport-CVE-2021-3997-shared-rm-rf-loop-over-nested-directories-instead-of.patch +patch6010: backport-fix-CVE-2021-33910.patch BuildRequires: gcc, gcc-c++ BuildRequires: libcap-devel, libmount-devel, pam-devel, libselinux-devel @@ -1705,6 +1710,9 @@ fi %{_unitdir}/systemd-userdbd.socket %changelog +* Tue Feb 15 2021 yangmingtai - 249-5 +- fix CVE-2021-3997 and CVE-2021-33910 + * Tue Feb 8 2021 yangmingtai - 249-4 - fix ConditionDirectoryNotEmpty,ConditionPathIsReadWrite and DirectoryNotEmpty From 29ef298a480062da7cb0d27066803d3dc7ae2a46 Mon Sep 17 00:00:00 2001 From: yangmingtaip Date: Tue, 15 Feb 2022 20:40:25 +0800 Subject: [PATCH 2/3] nop_job of a unit must also be coldpluged after deserization (cherry picked from commit c247e37e3466bbd39d2a52d6afca3cd399e171e4) --- ...lso-be-coldpluged-after-deserization.patch | 53 +++++++++++++++++++ systemd.spec | 6 ++- 2 files changed, 58 insertions(+), 1 deletion(-) create mode 100644 0018-nop_job-of-a-unit-must-also-be-coldpluged-after-deserization.patch diff --git a/0018-nop_job-of-a-unit-must-also-be-coldpluged-after-deserization.patch b/0018-nop_job-of-a-unit-must-also-be-coldpluged-after-deserization.patch new file mode 100644 index 0000000..afca3e7 --- /dev/null +++ b/0018-nop_job-of-a-unit-must-also-be-coldpluged-after-deserization.patch @@ -0,0 +1,53 @@ +From 07e13151c566588b5f679e2576d3dfc2125c6e7c Mon Sep 17 00:00:00 2001 +From: huangkaibin +Date: Sun, 22 Apr 2018 18:49:19 +0800 +Subject: [PATCH] systemd-core: nop_job of a unit must also be coldpluged +after deserization. + +When a unit is not in-active, and systemctl try-restart is executed for +this unit, +systemd will do nothing for it and just accept it as a nop_job for the +unit. +When then nop-job is still in the running queue, then daemon-reload is +performed, this nop job +will be dropped from the unit since it is not coldpluged in the +unit_coldplug function. +After then, the systemctl try-restart command will hang forever since no +JOB_DONE dbus signal will be sent +to it from systemd. +This patch fix this problem by do coldplug for the nop_job in +unit_coldplug function. +--- + src/core/unit.c | 16 +++++++++++----- + 1 file changed, 11 insertions(+), 5 deletions(-) + +diff --git a/src/core/unit.c b/src/core/unit.c +index 0a2f3c8..b9bd102 100644 +--- a/src/core/unit.c ++++ b/src/core/unit.c +@@ -3601,11 +3601,17 @@ int unit_coldplug(Unit *u) { + r = q; + } + +- uj = u->job ?: u->nop_job; +- if (uj) { +- q = job_coldplug(uj); +- if (q < 0 && r >= 0) +- r = q; ++ if (u->job || u->nop_job) { ++ if (u->job) { ++ q = job_coldplug(u->job); ++ if (q < 0 && r >= 0) ++ r = q; ++ } ++ if (u->nop_job) { ++ q = job_coldplug(u->nop_job); ++ if (q < 0 && r >= 0) ++ r = q; ++ } + } + + return r; +-- +2.27.0 + diff --git a/systemd.spec b/systemd.spec index 8ccf79e..0676ada 100644 --- a/systemd.spec +++ b/systemd.spec @@ -20,7 +20,7 @@ Name: systemd Url: https://www.freedesktop.org/wiki/Software/systemd Version: 249 -Release: 5 +Release: 6 License: MIT and LGPLv2+ and GPLv2+ Summary: System and Service Manager @@ -63,6 +63,7 @@ Patch0014: 0014-journal-don-t-enable-systemd-journald-audit.socket-b.patch Patch0015: 0015-systemd-change-time-log-level.patch Patch0016: 0016-fix-capsh-drop-but-ping-success.patch Patch0017: 0017-resolved-create-etc-resolv.conf-symlink-at-runtime.patch +patch0018: 0018-nop_job-of-a-unit-must-also-be-coldpluged-after-deserization.patch #backport Patch6000: backport-core-fix-free-undefined-pointer-when-strdup-failed-i.patch @@ -1710,6 +1711,9 @@ fi %{_unitdir}/systemd-userdbd.socket %changelog +* Tue Feb 15 2021 yangmingtai - 249-6 +- nop_job of a unit must also be coldpluged after deserization + * Tue Feb 15 2021 yangmingtai - 249-5 - fix CVE-2021-3997 and CVE-2021-33910 From c6fc5454b93ec7f9159d74cfb097aeec639e03a7 Mon Sep 17 00:00:00 2001 From: yangmingtaip Date: Tue, 15 Feb 2022 21:02:26 +0800 Subject: [PATCH 3/3] delete udev-compat subpackage (cherry picked from commit 41ae3b25c57ac91bebe419a238fdd33067b7638f) --- systemd.spec | 53 +++++++++++++--------------------------------------- 1 file changed, 13 insertions(+), 40 deletions(-) diff --git a/systemd.spec b/systemd.spec index 0676ada..fae4adb 100644 --- a/systemd.spec +++ b/systemd.spec @@ -20,7 +20,7 @@ Name: systemd Url: https://www.freedesktop.org/wiki/Software/systemd Version: 249 -Release: 6 +Release: 7 License: MIT and LGPLv2+ and GPLv2+ Summary: System and Service Manager @@ -37,14 +37,14 @@ Source11: 20-grubby.install Source12: systemd-user Source13: rc.local -Source100: udev-40-openEuler.rules -Source101: udev-55-persistent-net-generator.rules -Source102: udev-56-net-sriov-names.rules -Source103: udev-61-openeuler-persistent-storage.rules -Source104: net-set-sriov-names -Source105: rule_generator.functions -Source106: write_net_rules -Source107: detect_virt +Source100: udev-40-openEuler.rules +Source101: udev-55-persistent-net-generator.rules +Source102: udev-56-net-sriov-names.rules +Source103: udev-61-openeuler-persistent-storage.rules +Source104: net-set-sriov-names +Source105: rule_generator.functions +Source106: write_net_rules +Source107: detect_virt Patch0001: 0001-update-rtc-with-system-clock-when-shutdown.patch Patch0002: 0002-udev-add-actions-while-rename-netif-failed.patch @@ -211,20 +211,6 @@ Obsoletes: %{name}-journal-gateway < 227-7 Programs to forward journal entries over the network, using encrypted HTTP, and to write journal files from serialized journal contents. -%package udev-compat -Summary: Udev rules compatibility with NetworkManager -Requires: %{name} = %{version}-%{release} -License: LGPLv2+ -Requires(pre): /usr/bin/getent -Requires(post): systemd -Requires(preun): systemd -Requires(postun): systemd - -%description udev-compat -systemd-udev-compat is a set of udev rules which conflict with NetworkManager. -If users choose to use the network-scripts to manager the network, the package can be used -to do somethings when down or up nics or disk. - %package oomd Summary: Systemd oomd feature Requires: %{name} = %{version}-%{release} @@ -505,13 +491,6 @@ install -m 0644 %{SOURCE13} %{buildroot}%{_sysconfdir}/rc.d/rc.local ln -s rc.d/rc.local %{buildroot}%{_sysconfdir}/rc.local install -m 0644 %{SOURCE100} %{buildroot}/%{_udevrulesdir}/40-openEuler.rules -install -m 0644 %{SOURCE101} %{buildroot}/%{_udevrulesdir}/55-persistent-net-generator.rules -install -m 0644 %{SOURCE102} %{buildroot}/%{_udevrulesdir}/56-net-sriov-names.rules -install -m 0644 %{SOURCE103} %{buildroot}/%{_udevrulesdir}/61-openeuler-persistent-storage.rules -install -m 0755 %{SOURCE104} %{buildroot}/usr/lib/udev -install -m 0755 %{SOURCE105} %{buildroot}/usr/lib/udev -install -m 0755 %{SOURCE106} %{buildroot}/usr/lib/udev -install -m 0755 %{SOURCE107} %{buildroot}/usr/lib/udev # remove rpath info for file in $(find %{buildroot}/ -executable -type f -exec file {} ';' | grep "\" | awk -F ':' '{print $1}') @@ -1606,15 +1585,6 @@ fi %config(noreplace) /etc/systemd/journal-remote.conf %config(noreplace) /etc/systemd/journal-upload.conf -%files udev-compat -%{_udevrulesdir}/55-persistent-net-generator.rules -%{_udevrulesdir}/56-net-sriov-names.rules -%{_udevrulesdir}/61-openeuler-persistent-storage.rules -/usr/lib/udev/rule_generator.functions -/usr/lib/udev/write_net_rules -/usr/lib/udev/net-set-sriov-names -/usr/lib/udev/detect_virt - %files oomd /etc/systemd/oomd.conf /usr/bin/oomctl @@ -1711,6 +1681,9 @@ fi %{_unitdir}/systemd-userdbd.socket %changelog +* Tue Feb 15 2021 yangmingtai - 249-7 +- disable rename function of net interface + * Tue Feb 15 2021 yangmingtai - 249-6 - nop_job of a unit must also be coldpluged after deserization @@ -1747,7 +1720,7 @@ fi * Mon Aug 16 2021 yangmingtai - 248-8 - udev: exec daemon-reload after installation -* Fri Jul 22 2021 yangmingtai - 248-7 +* Thu Jul 22 2021 yangmingtai - 248-7 - fix CVE-2021-33910 * Thu Jun 03 2021 shenyangyang - 248-6