mirror of
https://github.com/systemd/systemd.git
synced 2024-10-30 14:55:37 +03:00
Merge pull request #21196 from yuwata/process-util-nulstr
process-util: handle double NUL as the end of command line
This commit is contained in:
commit
a0af85e02c
@ -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) {
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user