[Crash-utility] [PATCH] fix "ps -a" for tasks whose arg_start was moved
Dave Anderson
anderson at redhat.com
Fri Apr 20 20:19:46 UTC 2018
----- Original Message -----
> When a task used prctl(PR_SET_MM, PR_SET_MM_ARG_{START,END}, ...)
> (e.g. the systemd's child "(sd-pam)" in Fedora), the "ps -a" option
> could fail with "ps: cannot allocate any more memory!".
Good catch! Queued for crash-7.2.2:
https://github.com/crash-utility/crash/commit/4e8c1f3720c7bc3ca074c816332edf2a865dc681
Thanks,
Dave
>
> # ./crash -d 1
> ...
> crash> ps -a 1591
> ...
> PID: 1591 TASK: ffff9c7077d7b1c0 CPU: 1 COMMAND: "(sd-pam)"
> arg_start: 7f2f544de000 arg_end: 7f2f544de009 (9)
> env_start: 7ffcff12af88 env_end: 7ffcff12afdf (87)
> ...
> smallest: 16
> largest: 883333320672
> embedded: 2
> max_embedded: 3
> mallocs: 22
> frees: 22
> reqs/total: 912/1766672402731
> average size: 1937140792
> ps: cannot allocate any more memory!
>
> This happens because it assumes that the ranges of arg and env are
> contiguous.
>
> buf = GETBUF(env_end - arg_start + 1);
>
> This patch devides the GETBUF() into two times for arg and env.
>
> Signed-off-by: Kazuhito Hagio <k-hagio at ab.jp.nec.com>
> ---
> task.c | 94
> +++++++++++++++++++++++++++++++++++++-----------------------------
> 1 file changed, 53 insertions(+), 41 deletions(-)
>
> diff --git a/task.c b/task.c
> index 2418e4c..55242c5 100644
> --- a/task.c
> +++ b/task.c
> @@ -3865,6 +3865,44 @@ show_milliseconds(struct task_context *tc, struct
> psinfo *psi)
> }
> }
>
> +static char *
> +read_arg_string(struct task_context *tc, char *buf, ulong start, ulong end)
> +{
> + physaddr_t paddr;
> + ulong uvaddr, size, cnt;
> + char *bufptr;
> +
> + uvaddr = start;
> + size = end - start;
> + bufptr = buf;
> +
> + while (size > 0) {
> + if (!uvtop(tc, uvaddr, &paddr, 0)) {
> + error(INFO, "cannot access user stack address: %lx\n\n",
> + uvaddr);
> + return NULL;
> + }
> +
> + cnt = PAGESIZE() - PAGEOFFSET(uvaddr);
> +
> + if (cnt > size)
> + cnt = size;
> +
> + if (!readmem(paddr, PHYSADDR, bufptr, cnt,
> + "user stack contents", RETURN_ON_ERROR|QUIET)) {
> + error(INFO, "cannot access user stack address: %lx\n\n",
> + uvaddr);
> + return NULL;
> + }
> +
> + uvaddr += cnt;
> + bufptr += cnt;
> + size -= cnt;
> + }
> +
> + return bufptr;
> +}
> +
> /*
> * Show the argv and envp strings pointed to by mm_struct->arg_start
> * and mm_struct->env_start. The user addresses need to broken up
> @@ -3875,10 +3913,7 @@ static void
> show_task_args(struct task_context *tc)
> {
> ulong arg_start, arg_end, env_start, env_end;
> - char *buf, *bufptr, *p1;
> - char *as, *ae, *es, *ee;
> - physaddr_t paddr;
> - ulong uvaddr, size, cnt;
> + char *buf, *p1, *end;
> int c, d;
>
> print_task_header(fp, tc, 0);
> @@ -3910,43 +3945,13 @@ show_task_args(struct task_context *tc)
> env_start, env_end, env_end - env_start);
> }
>
> - buf = GETBUF(env_end - arg_start + 1);
> -
> - uvaddr = arg_start;
> - size = env_end - arg_start;
> - bufptr = buf;
> -
> - while (size > 0) {
> - if (!uvtop(tc, uvaddr, &paddr, 0)) {
> - error(INFO, "cannot access user stack address: %lx\n\n",
> - uvaddr);
> - goto bailout;
> - }
> -
> - cnt = PAGESIZE() - PAGEOFFSET(uvaddr);
> -
> - if (cnt > size)
> - cnt = size;
> -
> - if (!readmem(paddr, PHYSADDR, bufptr, cnt,
> - "user stack contents", RETURN_ON_ERROR|QUIET)) {
> - error(INFO, "cannot access user stack address: %lx\n\n",
> - uvaddr);
> - goto bailout;
> - }
> -
> - uvaddr += cnt;
> - bufptr += cnt;
> - size -= cnt;
> - }
> -
> - as = buf;
> - ae = &buf[arg_end - arg_start];
> - es = &buf[env_start - arg_start];
> - ee = &buf[env_end - arg_start];
> + buf = GETBUF(arg_end - arg_start + 1);
> + end = read_arg_string(tc, buf, arg_start, arg_end);
> + if (!end)
> + goto bailout;
>
> fprintf(fp, "ARG: ");
> - for (p1 = as, c = 0; p1 < ae; p1++) {
> + for (p1 = buf, c = 0; p1 < end; p1++) {
> if (*p1 == NULLCHAR) {
> if (c)
> fprintf(fp, " ");
> @@ -3957,14 +3962,21 @@ show_task_args(struct task_context *tc)
> }
> }
>
> + FREEBUF(buf);
> +
> + buf = GETBUF(env_end - env_start + 1);
> + end = read_arg_string(tc, buf, env_start, env_end);
> + if (!end)
> + goto bailout;
> +
> fprintf(fp, "\nENV: ");
> - for (p1 = es, c = d = 0; p1 < ee; p1++) {
> + for (p1 = buf, c = d = 0; p1 < end; p1++) {
> if (*p1 == NULLCHAR) {
> if (c)
> fprintf(fp, "\n");
> c = 0;
> } else {
> - fprintf(fp, "%s%c", !c && (p1 != es) ? " " : "", *p1);
> + fprintf(fp, "%s%c", !c && (p1 != buf) ? " " : "", *p1);
> c++, d++;
> }
> }
> --
> 1.8.3.1
>
> --
> Crash-utility mailing list
> Crash-utility at redhat.com
> https://www.redhat.com/mailman/listinfo/crash-utility
>
More information about the Crash-utility
mailing list