summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYu Watanabe <watanabe.yu+github@gmail.com>2021-12-07 08:29:34 +0900
committerGitHub <noreply@github.com>2021-12-07 08:29:34 +0900
commita0af85e02c773feead75941ad2b3fd8ff7c30f39 (patch)
tree50ed7e9a341c4b9ccd0cd1ff392ebaa8cc33daa8
parent051ea718f26dffe60c6864e6314068ab25062a9c (diff)
parentaa9de5b1c0ed9cd7ae0dec0dcaf19c18be846d7e (diff)
downloadsystemd-a0af85e02c773feead75941ad2b3fd8ff7c30f39.tar.gz
Merge pull request #21196 from yuwata/process-util-nulstr
process-util: handle double NUL as the end of command line
-rw-r--r--src/basic/process-util.c73
-rw-r--r--src/basic/process-util.h22
-rw-r--r--src/test/test-process-util.c8
3 files changed, 56 insertions, 47 deletions
diff --git a/src/basic/process-util.c b/src/basic/process-util.c
index bdadec4072..1b96d3ca85 100644
--- a/src/basic/process-util.c
+++ b/src/basic/process-util.c
@@ -181,13 +181,13 @@ static int get_process_cmdline_nulstr(
return r;
}
-int get_process_cmdline(pid_t pid, size_t max_columns, ProcessCmdlineFlags flags, char **line) {
+int get_process_cmdline(pid_t pid, size_t max_columns, ProcessCmdlineFlags flags, char **ret) {
_cleanup_free_ char *t = NULL;
size_t k;
char *ans;
- assert(line);
assert(pid >= 0);
+ assert(ret);
/* Retrieve and format a commandline. See above for discussion of retrieval options.
*
@@ -214,11 +214,17 @@ int get_process_cmdline(pid_t pid, size_t max_columns, ProcessCmdlineFlags flags
assert(!(flags & PROCESS_CMDLINE_USE_LOCALE));
_cleanup_strv_free_ char **args = NULL;
+ char **p;
args = strv_parse_nulstr(t, k);
if (!args)
return -ENOMEM;
+ /* Drop trailing empty strings. See issue #21186. */
+ STRV_FOREACH_BACKWARDS(p, args)
+ if (isempty(*p))
+ *p = mfree(*p);
+
ans = quote_command_line(args, shflags);
if (!ans)
return -ENOMEM;
@@ -240,7 +246,7 @@ int get_process_cmdline(pid_t pid, size_t max_columns, ProcessCmdlineFlags flags
ans = str_realloc(ans);
}
- *line = ans;
+ *ret = ans;
return 0;
}
@@ -447,29 +453,29 @@ int is_kernel_thread(pid_t pid) {
return !!(flags & PF_KTHREAD);
}
-int get_process_capeff(pid_t pid, char **capeff) {
+int get_process_capeff(pid_t pid, char **ret) {
const char *p;
int r;
- assert(capeff);
assert(pid >= 0);
+ assert(ret);
p = procfs_file_alloca(pid, "status");
- r = get_proc_field(p, "CapEff", WHITESPACE, capeff);
+ r = get_proc_field(p, "CapEff", WHITESPACE, ret);
if (r == -ENOENT)
return -ESRCH;
return r;
}
-static int get_process_link_contents(const char *proc_file, char **name) {
+static int get_process_link_contents(const char *proc_file, char **ret) {
int r;
assert(proc_file);
- assert(name);
+ assert(ret);
- r = readlink_malloc(proc_file, name);
+ r = readlink_malloc(proc_file, ret);
if (r == -ENOENT)
return -ESRCH;
if (r < 0)
@@ -478,32 +484,33 @@ static int get_process_link_contents(const char *proc_file, char **name) {
return 0;
}
-int get_process_exe(pid_t pid, char **name) {
+int get_process_exe(pid_t pid, char **ret) {
const char *p;
char *d;
int r;
assert(pid >= 0);
+ assert(ret);
p = procfs_file_alloca(pid, "exe");
- r = get_process_link_contents(p, name);
+ r = get_process_link_contents(p, ret);
if (r < 0)
return r;
- d = endswith(*name, " (deleted)");
+ d = endswith(*ret, " (deleted)");
if (d)
*d = '\0';
return 0;
}
-static int get_process_id(pid_t pid, const char *field, uid_t *uid) {
+static int get_process_id(pid_t pid, const char *field, uid_t *ret) {
_cleanup_fclose_ FILE *f = NULL;
const char *p;
int r;
assert(field);
- assert(uid);
+ assert(ret);
if (pid < 0)
return -EINVAL;
@@ -533,60 +540,62 @@ static int get_process_id(pid_t pid, const char *field, uid_t *uid) {
l[strcspn(l, WHITESPACE)] = 0;
- return parse_uid(l, uid);
+ return parse_uid(l, ret);
}
}
return -EIO;
}
-int get_process_uid(pid_t pid, uid_t *uid) {
+int get_process_uid(pid_t pid, uid_t *ret) {
if (pid == 0 || pid == getpid_cached()) {
- *uid = getuid();
+ *ret = getuid();
return 0;
}
- return get_process_id(pid, "Uid:", uid);
+ return get_process_id(pid, "Uid:", ret);
}
-int get_process_gid(pid_t pid, gid_t *gid) {
+int get_process_gid(pid_t pid, gid_t *ret) {
if (pid == 0 || pid == getpid_cached()) {
- *gid = getgid();
+ *ret = getgid();
return 0;
}
assert_cc(sizeof(uid_t) == sizeof(gid_t));
- return get_process_id(pid, "Gid:", gid);
+ return get_process_id(pid, "Gid:", ret);
}
-int get_process_cwd(pid_t pid, char **cwd) {
+int get_process_cwd(pid_t pid, char **ret) {
const char *p;
assert(pid >= 0);
+ assert(ret);
if (pid == 0 || pid == getpid_cached())
- return safe_getcwd(cwd);
+ return safe_getcwd(ret);
p = procfs_file_alloca(pid, "cwd");
- return get_process_link_contents(p, cwd);
+ return get_process_link_contents(p, ret);
}
-int get_process_root(pid_t pid, char **root) {
+int get_process_root(pid_t pid, char **ret) {
const char *p;
assert(pid >= 0);
+ assert(ret);
p = procfs_file_alloca(pid, "root");
- return get_process_link_contents(p, root);
+ return get_process_link_contents(p, ret);
}
#define ENVIRONMENT_BLOCK_MAX (5U*1024U*1024U)
-int get_process_environ(pid_t pid, char **env) {
+int get_process_environ(pid_t pid, char **ret) {
_cleanup_fclose_ FILE *f = NULL;
_cleanup_free_ char *outcome = NULL;
size_t sz = 0;
@@ -594,7 +603,7 @@ int get_process_environ(pid_t pid, char **env) {
int r;
assert(pid >= 0);
- assert(env);
+ assert(ret);
p = procfs_file_alloca(pid, "environ");
@@ -626,7 +635,7 @@ int get_process_environ(pid_t pid, char **env) {
}
outcome[sz] = '\0';
- *env = TAKE_PTR(outcome);
+ *ret = TAKE_PTR(outcome);
return 0;
}
@@ -685,13 +694,13 @@ int get_process_ppid(pid_t pid, pid_t *ret) {
return 0;
}
-int get_process_umask(pid_t pid, mode_t *umask) {
+int get_process_umask(pid_t pid, mode_t *ret) {
_cleanup_free_ char *m = NULL;
const char *p;
int r;
- assert(umask);
assert(pid >= 0);
+ assert(ret);
p = procfs_file_alloca(pid, "status");
@@ -699,7 +708,7 @@ int get_process_umask(pid_t pid, mode_t *umask) {
if (r == -ENOENT)
return -ESRCH;
- return parse_mode(m, umask);
+ return parse_mode(m, ret);
}
int wait_for_terminate(pid_t pid, siginfo_t *status) {
diff --git a/src/basic/process-util.h b/src/basic/process-util.h
index c312e05d9c..f22ff76ee8 100644
--- a/src/basic/process-util.h
+++ b/src/basic/process-util.h
@@ -38,17 +38,17 @@ typedef enum ProcessCmdlineFlags {
PROCESS_CMDLINE_QUOTE_POSIX = 1 << 3,
} ProcessCmdlineFlags;
-int get_process_comm(pid_t pid, char **name);
-int get_process_cmdline(pid_t pid, size_t max_columns, ProcessCmdlineFlags flags, char **line);
-int get_process_exe(pid_t pid, char **name);
-int get_process_uid(pid_t pid, uid_t *uid);
-int get_process_gid(pid_t pid, gid_t *gid);
-int get_process_capeff(pid_t pid, char **capeff);
-int get_process_cwd(pid_t pid, char **cwd);
-int get_process_root(pid_t pid, char **root);
-int get_process_environ(pid_t pid, char **environ);
-int get_process_ppid(pid_t pid, pid_t *ppid);
-int get_process_umask(pid_t pid, mode_t *umask);
+int get_process_comm(pid_t pid, char **ret);
+int get_process_cmdline(pid_t pid, size_t max_columns, ProcessCmdlineFlags flags, char **ret);
+int get_process_exe(pid_t pid, char **ret);
+int get_process_uid(pid_t pid, uid_t *ret);
+int get_process_gid(pid_t pid, gid_t *ret);
+int get_process_capeff(pid_t pid, char **ret);
+int get_process_cwd(pid_t pid, char **ret);
+int get_process_root(pid_t pid, char **ret);
+int get_process_environ(pid_t pid, char **ret);
+int get_process_ppid(pid_t pid, pid_t *ret);
+int get_process_umask(pid_t pid, mode_t *ret);
int wait_for_terminate(pid_t pid, siginfo_t *status);
diff --git a/src/test/test-process-util.c b/src/test/test-process-util.c
index a180f3f9b4..ab093a7457 100644
--- a/src/test/test-process-util.c
+++ b/src/test/test-process-util.c
@@ -484,8 +484,8 @@ TEST(get_process_cmdline_harder) {
/* Test with multiple arguments that do require quoting */
#define CMDLINE1 "foo\0'bar'\0\"bar$\"\0x y z\0!``\0"
-#define EXPECT1 "foo \"'bar'\" \"\\\"bar\\$\\\"\" \"x y z\" \"!\\`\\`\" \"\""
-#define EXPECT1p "foo $'\\'bar\\'' $'\"bar$\"' $'x y z' $'!``' \"\""
+#define EXPECT1 "foo \"'bar'\" \"\\\"bar\\$\\\"\" \"x y z\" \"!\\`\\`\""
+#define EXPECT1p "foo $'\\'bar\\'' $'\"bar$\"' $'x y z' $'!``'"
assert_se(lseek(fd, SEEK_SET, 0) == 0);
assert_se(write(fd, CMDLINE1, sizeof CMDLINE1) == sizeof CMDLINE1);
assert_se(ftruncate(fd, sizeof CMDLINE1) == 0);
@@ -503,8 +503,8 @@ TEST(get_process_cmdline_harder) {
line = mfree(line);
#define CMDLINE2 "foo\0\1\2\3\0\0"
-#define EXPECT2 "foo \"\\001\\002\\003\" \"\" \"\""
-#define EXPECT2p "foo $'\\001\\002\\003' \"\" \"\""
+#define EXPECT2 "foo \"\\001\\002\\003\""
+#define EXPECT2p "foo $'\\001\\002\\003'"
assert_se(lseek(fd, SEEK_SET, 0) == 0);
assert_se(write(fd, CMDLINE2, sizeof CMDLINE2) == sizeof CMDLINE2);
assert_se(ftruncate(fd, sizeof CMDLINE2) == 0);