commit 2bb3523cff43f3b878036f8453da67a0855cf994 Author: overweight <5324761+overweight@user.noreply.gitee.com> Date: Mon Sep 30 11:14:16 2019 -0400 Package init diff --git a/bugfix-fix-pstree-coredump-due-pid-reuse.patch b/bugfix-fix-pstree-coredump-due-pid-reuse.patch new file mode 100644 index 0000000..72ed351 --- /dev/null +++ b/bugfix-fix-pstree-coredump-due-pid-reuse.patch @@ -0,0 +1,197 @@ +From 8677c615752235194f1a01925c9a591cdf8da821 Mon Sep 17 00:00:00 2001 +From: +Date: Wed, 8 May 2019 03:43:25 -0400 +Subject: [PATCH] fix pstree coredump due pid reuse + +From: huangkaibin +sign_off_by: XiaShuang + +pstree scans /proc directory to construct tree of all processes. +In scanning, if a pid or tid is already added to ps tree, and then exists, +and it is reused by another process or thread, there will be a loop in ps tree, +and will cause coredump in tree_equal function. +An example step is as below. +1. process A added to ps tree +2. process B added to ps tree as a child of Author +3. B exists and its pid is reused by process C(with same pid as B) +4. A exists and its pid is reused by process D(with same pid as A) as a child of process C +5. hence, A(pid1)->B(pid2)->C(pid2)->D(pid1)->B(pid)->... loop is constructed +This patch fix this problem by not adding processes with pid reused to ps tree. +--- + src/pstree.c | 108 ++++++++++++++++++++++++++++++++++++++--------------------- + 1 file changed, 70 insertions(+), 38 deletions(-) + +diff --git a/src/pstree.c b/src/pstree.c +index aaf3df7..b4880f8 100644 +--- a/src/pstree.c ++++ b/src/pstree.c +@@ -119,6 +119,8 @@ typedef struct _proc { + #define PFLAG_HILIGHT 0x01 + #define PFLAG_THREAD 0x02 + ++#define ISTHREAD(proc) ((proc)->flags & ~PFLAG_THREAD) ++ + typedef struct _child { + PROC *child; + struct _child *next; +@@ -574,15 +576,44 @@ rename_proc(PROC *this, const char *comm, uid_t uid) + } + } + +-static void ++static int has_proc_loop(const PROC *parent, const PROC *child) { ++ int ret = 0; ++ const PROC *raw_parent = parent; ++ if(child != NULL) { ++ while(parent != NULL) { ++ if(parent == child) { ++ ret = 1; ++ break ; ++ } ++ parent = parent->parent; ++ if(parent == raw_parent) ++ break ; ++ } ++ } ++ return ret; ++} ++ ++ ++static int + add_proc(const char *comm, pid_t pid, pid_t ppid, pid_t pgid, uid_t uid, + const char *args, int size, char isthread, security_context_t scontext) + { + PROC *this, *parent; ++ if (!(parent = find_proc(ppid))) { ++ parent = new_proc("?", ppid, 0, scontext); ++ } + + if (!(this = find_proc(pid))) + this = new_proc(comm, pid, uid, scontext); + else { ++ if(strcmp(this->comm, "?") != 0 || has_proc_loop(parent, this)) { ++ /*when comm is not ?, then it is not a placeholder process, and there ++ * comes the scenario of pid/tid reuse. ++ * or if it is a placeholder, but there contains a proc loop, ++ * it will not be added to ps tree. ++ */ ++ return -1; ++ } + rename_proc(this, comm, uid); + } + if (args) +@@ -592,13 +623,12 @@ add_proc(const char *comm, pid_t pid, pid_t ppid, pid_t pgid, uid_t uid, + this->pgid = pgid; + if (isthread) + this->flags |= PFLAG_THREAD; +- if (!(parent = find_proc(ppid))) { +- parent = new_proc("?", ppid, 0, scontext); +- } +- if (pid != 0) { ++ if (pid != 0 && !ISTHREAD(parent)) { ++ /*thread can not have any children. this can happen when a tid is reused as a pid*/ + add_child(parent, this); + this->parent = parent; + } ++ return 0; + } + + +@@ -918,7 +948,7 @@ static void read_proc(void) + char readbuf[BUFSIZ + 1]; + char *tmpptr, *endptr; + pid_t pid, ppid, pgid; +- int fd, size; ++ int fd, size, ret; + int empty; + security_context_t scontext = NULL; + #ifdef WITH_SELINUX +@@ -978,41 +1008,14 @@ static void read_proc(void) + struct dirent *dt; + char *taskpath; + int thread; +- +- /* handle process threads */ +- if (! hide_threads) { +- if (! (taskpath = malloc(strlen(path) + 10))) +- exit(2); +- sprintf(taskpath, "%s/task", path); +- +- if ((taskdir = opendir(taskpath)) != 0) { +- /* if we have this dir, we're on 2.6 */ +- while ((dt = readdir(taskdir)) != NULL) { +- if ((thread = atoi(dt->d_name)) != 0) { +- if (thread != pid) { +- char *threadname; +- threadname = get_threadname(pid, thread, comm); +- if (print_args) +- add_proc(threadname, thread, pid, pgid, st.st_uid, +- threadname, strlen (threadname) + 1, 1,scontext); +- else +- add_proc(threadname, thread, pid, pgid, st.st_uid, +- NULL, 0, 1, scontext); +- free(threadname); +- } +- } +- } +- (void) closedir(taskdir); +- } +- free(taskpath); +- } ++ char cmdline[128]; + + /* handle process */ + if (!print_args) +- add_proc(comm, pid, ppid, pgid, st.st_uid, NULL, 0, 0, scontext); ++ ret = add_proc(comm, pid, ppid, pgid, st.st_uid, NULL, 0, 0, scontext); + else { +- sprintf(path, "%s/%d/cmdline", PROC_BASE, pid); +- if ((fd = open(path, O_RDONLY)) < 0) { ++ sprintf(cmdline, "%s/%d/cmdline", PROC_BASE, pid); ++ if ((fd = open(cmdline, O_RDONLY)) < 0) { + /* If this fails then the process is gone. If a PID + * was specified on the command-line then we might + * not even be interested in the current process. +@@ -1037,9 +1040,38 @@ static void read_proc(void) + size--; + if (size) + buffer[size++] = 0; +- add_proc(comm, pid, ppid, pgid, st.st_uid, ++ ret = add_proc(comm, pid, ppid, pgid, st.st_uid, + buffer, size, 0, scontext); + } ++ if (ret >= 0) {/*do not add tids to ps tree when its parent process reuses pid/tid*/ ++ /* handle process threads */ ++ if (!hide_threads) { ++ if (! (taskpath = malloc(strlen(path) + 10))) ++ exit(2); ++ sprintf(taskpath, "%s/task", path); ++ ++ if ((taskdir = opendir(taskpath)) != 0) { ++ /* if we have this dir, we're on 2.6 */ ++ while ((dt = readdir(taskdir)) != NULL) { ++ if ((thread = atoi(dt->d_name)) != 0) { ++ if (thread != pid) { ++ char *threadname; ++ threadname = get_threadname(pid, thread, comm); ++ if (print_args) ++ add_proc(threadname, thread, pid, pgid, st.st_uid, ++ threadname, strlen (threadname) + 1, 1,scontext); ++ else ++ add_proc(threadname, thread, pid, pgid, st.st_uid, ++ NULL, 0, 1, scontext); ++ free(threadname); ++ } ++ } ++ } ++ (void) closedir(taskdir); ++ } ++ free(taskpath); ++ } ++ } + } + } + } +-- +1.8.3.1 + diff --git a/psmisc-23.1.tar.xz b/psmisc-23.1.tar.xz new file mode 100644 index 0000000..b0c403a Binary files /dev/null and b/psmisc-23.1.tar.xz differ diff --git a/psmisc.spec b/psmisc.spec new file mode 100644 index 0000000..b56b7bf --- /dev/null +++ b/psmisc.spec @@ -0,0 +1,51 @@ +Name: psmisc +Version: 23.1 +Release: 5 +Summary: Utilities for managing processes on your system +License: GPLv2+ +URL: https://gitlab.com/psmisc/psmisc +Source0: https://sourceforge.net/projects/%{name}/files/%{name}/%{name}-%{version}.tar.xz +BuildRequires: libselinux-devel gettext ncurses-devel autoconf automake gcc git + +Patch9001: bugfix-fix-pstree-coredump-due-pid-reuse.patch + +%description +This PSmisc package is a set of some small useful utilities that use the proc +filesystem. We're not about changing the world, but providing the system +administrator with some help in common tasks. + +%prep +%autosetup -n %{name}-%{version} -p1 -Sgit + +%build +%configure --prefix=%{_prefix} --enable-selinux +%make_build + +%install +%make_install +mkdir -p $RPM_BUILD_ROOT%{_sbindir} +mv $RPM_BUILD_ROOT%{_bindir}/fuser $RPM_BUILD_ROOT%{_sbindir} +%find_lang %name + +%files -f %{name}.lang +%{_sbindir}/fuser +%{_bindir}/* +%{_mandir}/man1/* +%license COPYING +%doc AUTHORS ChangeLog README + +%changelog +* Wed May 8 2019 xiashuang - 23.1-5 +- Type:bugfix +- ID:NA +- SUG:restart +- DESC:fix adapt patch error + +* Tue Jan 22 2019 xiashuang - 23.1-4 +- Type:bugfix +- ID:NA +- SUG:restart +- DESC:adapt patches from 7.3 + +* Mon Sep 10 2018 openEuler Buildteam - 23.1-3 +- Package init