[CRIU] [PATCH] proc_parse: Fix task name parsing

Cyrill Gorcunov gorcunov at openvz.org
Tue Apr 17 03:41:49 EDT 2012


The task name may include spaces so %s
scanning format will fail (in particular
dumping rsyslogd fails since thread has
name "rs:main Q:Reg"). Fix it.

Signed-off-by: Cyrill Gorcunov <gorcunov at openvz.org>
---
 proc_parse.c |  109 ++++++++++++++++++++++++++++++++++++++++------------------
 1 files changed, 75 insertions(+), 34 deletions(-)

diff --git a/proc_parse.c b/proc_parse.c
index 021501d..4b178ba 100644
--- a/proc_parse.c
+++ b/proc_parse.c
@@ -186,50 +186,96 @@ err_bogus_mapping:
 
 int parse_pid_stat_small(pid_t pid, struct proc_pid_stat_small *s)
 {
-	FILE *f;
-	char *tok;
+	char buf[128];
+	char *tok, *p;
+	int fd;
 	int n;
 
-	f = fopen_proc(pid, "stat");
-	if (f == NULL)
+	fd = open_proc(pid, "stat");
+	if (fd < 0)
 		return -1;
 
-	memset(s, 0, sizeof(*s));
-	n = fscanf(f, "%d " PROC_TASK_COMM_LEN_FMT " %c %d %d %d",
-			&s->pid, s->comm, &s->state, &s->ppid, &s->pgid, &s->sid);
-
-	if (n < 6) {
-		pr_err("Parsing %d's stat failed (#fields do not match)\n", pid);
+	n = read(fd, buf, sizeof(buf));
+	if (n < 1) {
+		pr_err("stat for %d is corrupted\n", pid);
+		close(fd);
 		return -1;
 	}
+	close(fd);
 
-	s->comm[PROC_TASK_COMM_LEN-1] = '\0';
-	tok = strchr(s->comm, ')');
-	if (tok)
-		*tok = '\0';
-	fclose(f);
+	memset(s, 0, sizeof(*s));
+
+	tok = strchr(buf, ' ');
+	if (!tok)
+		goto err;
+	*tok++ = '\0';
+	if (*tok != '(')
+		goto err;
+
+	s->pid = atoi(buf);
+
+	p = strrchr(tok + 1, ')');
+	if (!p)
+		goto err;
+	*tok = '\0';
+	*p = '\0';
+
+	strncpy(s->comm, tok + 1, sizeof(s->comm));
+
+	n = sscanf(p + 1, " %c %d %d %d", &s->state, &s->ppid, &s->pgid, &s->sid);
+	if (n < 4)
+		goto err;
 
 	return 0;
+
+err:
+	pr_err("Parsing %d's stat failed (#fields do not match)\n", pid);
+	return -1;
 }
 
 int parse_pid_stat(pid_t pid, struct proc_pid_stat *s)
 {
-	FILE *f;
-	char *tok;
+	char buf[1024];
+	char *tok, *p;
+	int fd;
 	int n;
 
-	f = fopen_proc(pid, "stat");
-	if (f == NULL)
+	fd = open_proc(pid, "stat");
+	if (fd < 0)
+		return -1;
+
+	n = read(fd, buf, sizeof(buf));
+	if (n < 1) {
+		pr_err("stat for %d is corrupted\n", pid);
+		close(fd);
 		return -1;
+	}
+	close(fd);
 
 	memset(s, 0, sizeof(*s));
-	n = fscanf(f,
-	       "%d " PROC_TASK_COMM_LEN_FMT " %c %d %d %d %d %d %u %lu %lu %lu %lu "
+
+	tok = strchr(buf, ' ');
+	if (!tok)
+		goto err;
+	*tok++ = '\0';
+	if (*tok != '(')
+		goto err;
+
+	s->pid = atoi(buf);
+
+	p = strrchr(tok + 1, ')');
+	if (!p)
+		goto err;
+	*tok = '\0';
+	*p = '\0';
+
+	strncpy(s->comm, tok + 1, sizeof(s->comm));
+
+	n = sscanf(p + 1,
+	       " %c %d %d %d %d %d %u %lu %lu %lu %lu "
 	       "%lu %lu %ld %ld %ld %ld %d %d %llu %lu %ld %lu %lu %lu %lu "
 	       "%lu %lu %lu %lu %lu %lu %lu %lu %lu %d %d %u %u %llu %lu %ld "
 	       "%lu %lu %lu %lu %lu %lu %lu %d",
-		&s->pid,
-		s->comm,
 		&s->state,
 		&s->ppid,
 		&s->pgid,
@@ -280,19 +326,14 @@ int parse_pid_stat(pid_t pid, struct proc_pid_stat *s)
 		&s->env_start,
 		&s->env_end,
 		&s->exit_code);
-
-	if (n < 52) {
-		pr_err("Parsing %d's stat failed (#fields do not match)\n", pid);
-		return -1;
-	}
-
-	s->comm[PROC_TASK_COMM_LEN-1] = '\0';
-	tok = strchr(s->comm, ')');
-	if (tok)
-		*tok = '\0';
-	fclose(f);
+	if (n < 50)
+		goto err;
 
 	return 0;
+
+err:
+	pr_err("Parsing %d's stat failed (#fields do not match)\n", pid);
+	return -1;
 }
 
 static int ids_parse(char *str, unsigned int *arr)
-- 
1.7.7.6



More information about the CRIU mailing list