Package init
This commit is contained in:
commit
2bb3523cff
197
bugfix-fix-pstree-coredump-due-pid-reuse.patch
Normal file
197
bugfix-fix-pstree-coredump-due-pid-reuse.patch
Normal file
@ -0,0 +1,197 @@
|
||||
From 8677c615752235194f1a01925c9a591cdf8da821 Mon Sep 17 00:00:00 2001
|
||||
From: <XiaShuang1@huawei.com>
|
||||
Date: Wed, 8 May 2019 03:43:25 -0400
|
||||
Subject: [PATCH] fix pstree coredump due pid reuse
|
||||
|
||||
From: huangkaibin <huangkaibin@huawei.com>
|
||||
sign_off_by: XiaShuang <xiashuang1@huawei.com>
|
||||
|
||||
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
|
||||
|
||||
BIN
psmisc-23.1.tar.xz
Normal file
BIN
psmisc-23.1.tar.xz
Normal file
Binary file not shown.
51
psmisc.spec
Normal file
51
psmisc.spec
Normal file
@ -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 <xiashuang1@huawei.com> - 23.1-5
|
||||
- Type:bugfix
|
||||
- ID:NA
|
||||
- SUG:restart
|
||||
- DESC:fix adapt patch error
|
||||
|
||||
* Tue Jan 22 2019 xiashuang <xiashuang1@huawei.com> - 23.1-4
|
||||
- Type:bugfix
|
||||
- ID:NA
|
||||
- SUG:restart
|
||||
- DESC:adapt patches from 7.3
|
||||
|
||||
* Mon Sep 10 2018 openEuler Buildteam <buildteam@openeuler.org> - 23.1-3
|
||||
- Package init
|
||||
Loading…
x
Reference in New Issue
Block a user