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!". 
   # ./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(a)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(a)redhat.com
 
https://www.redhat.com/mailman/listinfo/crash-utility