--- crash-4.0-7.6/main.c 2009-02-05 11:18:43.000000000 -0500 +++ crash-4.0-7.7/main.c 2009-01-23 14:52:16.000000000 -0500 @@ -25,6 +25,7 @@ static int is_builtin_command(void); static int is_input_file(void); static void check_xen_hyper(void); +static void show_untrusted_files(void); static struct option long_options[] = { {"memory_module", required_argument, 0, 0}, @@ -493,6 +494,7 @@ { if (!(pc->flags & GDB_INIT)) { gdb_session_init(); + show_untrusted_files(); if (XEN_HYPER_MODE()) { #ifdef XEN_HYPERVISOR_ARCH machdep_init(POST_GDB); @@ -876,6 +878,8 @@ if ((afp = fopen(homerc, "r")) == NULL) error(INFO, "cannot open %s: %s\n", homerc, strerror(errno)); + else if (untrusted_file(afp, homerc)) + fclose(afp); else { while (fgets(buf, BUFSIZE, afp)) resolve_rc_cmd(buf, ALIAS_RCHOME); @@ -890,6 +894,8 @@ if ((afp = fopen(localrc, "r")) == NULL) error(INFO, "cannot open %s: %s\n", localrc, strerror(errno)); + else if (untrusted_file(afp, localrc)) + fclose(afp); else { while (fgets(buf, BUFSIZE, afp)) resolve_rc_cmd(buf, ALIAS_RCLOCAL); @@ -1409,3 +1415,46 @@ error(FATAL, XEN_HYPERVISOR_NOT_SUPPORTED); #endif } + +/* + * Reject untrusted .crashrc, $HOME/.crashrc, + * .gdbinit, and $HOME/.gdbinit files. + */ +static char *untrusted_file_list[4] = { 0 }; + +int +untrusted_file(FILE *filep, char *filename) +{ + struct stat sbuf; + int i; + + if (filep && (fstat(fileno(filep), &sbuf) == 0) && + (sbuf.st_uid == getuid()) && !(sbuf.st_mode & S_IWOTH)) + return FALSE; + + for (i = 0; i < 4; i++) { + if (!untrusted_file_list[i]) { + untrusted_file_list[i] = strdup(filename); + break; + } + } + + return TRUE; +} + +static void +show_untrusted_files(void) +{ + int i, cnt; + + for (i = cnt = 0; i < 4; i++) { + if (untrusted_file_list[i]) { + error(WARNING, "not using untrusted file: \"%s\"\n", + untrusted_file_list[i]); + free(untrusted_file_list[i]); + cnt++; + } + } + if (cnt) + fprintf(fp, "\n"); +} --- crash-4.0-7.6/tools.c 2009-02-05 11:18:44.000000000 -0500 +++ crash-4.0-7.7/tools.c 2009-01-26 14:54:54.000000000 -0500 @@ -1,8 +1,8 @@ /* tools.c - core analysis suite * * Copyright (C) 1999, 2000, 2001, 2002 Mission Critical Linux, Inc. - * Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008 David Anderson - * Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008 Red Hat, Inc. All rights reserved. + * Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 David Anderson + * Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Red Hat, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by --- crash-4.0-7.6/memory.c 2009-02-05 11:18:43.000000000 -0500 +++ crash-4.0-7.7/memory.c 2009-01-26 14:55:04.000000000 -0500 @@ -1,8 +1,8 @@ /* memory.c - core analysis suite * * Copyright (C) 1999, 2000, 2001, 2002 Mission Critical Linux, Inc. - * Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007 David Anderson - * Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007 Red Hat, Inc. All rights reserved. + * Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 David Anderson + * Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Red Hat, Inc. All rights reserved. * Copyright (C) 2002 Silicon Graphics, Inc. * * This program is free software; you can redistribute it and/or modify --- crash-4.0-7.6/filesys.c 2009-02-05 11:18:44.000000000 -0500 +++ crash-4.0-7.7/filesys.c 2009-02-04 15:01:56.000000000 -0500 @@ -1,8 +1,8 @@ /* filesys.c - core analysis suite * * Copyright (C) 1999, 2000, 2001, 2002 Mission Critical Linux, Inc. - * Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008 David Anderson - * Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008 Red Hat, Inc. All rights reserved. + * Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 David Anderson + * Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Red Hat, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -17,6 +17,7 @@ #include "defs.h" #include +#include static void show_mounts(ulong, int, struct task_context *); static int find_booted_kernel(void); @@ -936,9 +937,10 @@ { char command[BUFSIZE]; char buf[BUFSIZE]; - char *retbuf; + char *retbuf, *start, *end, *module; FILE *pipe; - int done; + regex_t regex; + int regex_used, done; if (!file_exists("/usr/bin/find", NULL) || !file_exists("/bin/echo", NULL) || @@ -957,20 +959,34 @@ done = FALSE; retbuf = NULL; + regex_used = ((start = strstr(file, "[")) && + (end = strstr(file, "]")) && (start < end) && + (regcomp(®ex, file, 0) == 0)); while (fgets(buf, BUFSIZE-1, pipe) || !done) { if (STREQ(buf, "search done\n")) { done = TRUE; break; } - if (!retbuf && + if (!retbuf && !regex_used && STREQ((char *)basename(strip_linefeeds(buf)), file)) { retbuf = GETBUF(strlen(buf)+1); strcpy(retbuf, buf); } + if (!retbuf && regex_used) { + module = basename(strip_linefeeds(buf)); + if (regexec(®ex, module, 0, NULL, 0) == 0) { + retbuf = GETBUF(strlen(buf)+1); + strcpy(retbuf, buf); + } + } } + if (regex_used) + regfree(®ex); + pclose(pipe); + return retbuf; } @@ -1857,35 +1873,35 @@ goto show_hit_rates; for (i = 0; i < FILE_CACHE; i++) - fprintf(stderr, " cached_file[%2d]: %lx (%ld)\n", + fprintf(fp, " cached_file[%2d]: %lx (%ld)\n", i, ft->cached_file[i], ft->cached_file_hits[i]); - fprintf(stderr, " file_cache: %lx\n", (ulong)ft->file_cache); - fprintf(stderr, " file_cache_index: %d\n", ft->file_cache_index); - fprintf(stderr, " file_cache_fills: %ld\n", ft->file_cache_fills); + fprintf(fp, " file_cache: %lx\n", (ulong)ft->file_cache); + fprintf(fp, " file_cache_index: %d\n", ft->file_cache_index); + fprintf(fp, " file_cache_fills: %ld\n", ft->file_cache_fills); for (i = 0; i < DENTRY_CACHE; i++) - fprintf(stderr, " cached_dentry[%2d]: %lx (%ld)\n", + fprintf(fp, " cached_dentry[%2d]: %lx (%ld)\n", i, ft->cached_dentry[i], ft->cached_dentry_hits[i]); - fprintf(stderr, " dentry_cache: %lx\n", (ulong)ft->dentry_cache); - fprintf(stderr, "dentry_cache_index: %d\n", ft->dentry_cache_index); - fprintf(stderr, "dentry_cache_fills: %ld\n", ft->dentry_cache_fills); + fprintf(fp, " dentry_cache: %lx\n", (ulong)ft->dentry_cache); + fprintf(fp, "dentry_cache_index: %d\n", ft->dentry_cache_index); + fprintf(fp, "dentry_cache_fills: %ld\n", ft->dentry_cache_fills); for (i = 0; i < INODE_CACHE; i++) - fprintf(stderr, " cached_inode[%2d]: %lx (%ld)\n", + fprintf(fp, " cached_inode[%2d]: %lx (%ld)\n", i, ft->cached_inode[i], ft->cached_inode_hits[i]); - fprintf(stderr, " inode_cache: %lx\n", (ulong)ft->inode_cache); - fprintf(stderr, " inode_cache_index: %d\n", ft->inode_cache_index); - fprintf(stderr, " inode_cache_fills: %ld\n", ft->inode_cache_fills); + fprintf(fp, " inode_cache: %lx\n", (ulong)ft->inode_cache); + fprintf(fp, " inode_cache_index: %d\n", ft->inode_cache_index); + fprintf(fp, " inode_cache_fills: %ld\n", ft->inode_cache_fills); show_hit_rates: if (ft->file_cache_fills) { for (i = fhits = 0; i < FILE_CACHE; i++) fhits += ft->cached_file_hits[i]; - fprintf(stderr, " file hit rate: %2ld%% (%ld of %ld)\n", + fprintf(fp, " file hit rate: %2ld%% (%ld of %ld)\n", (fhits * 100)/ft->file_cache_fills, fhits, ft->file_cache_fills); } @@ -1894,7 +1910,7 @@ for (i = dhits = 0; i < DENTRY_CACHE; i++) dhits += ft->cached_dentry_hits[i]; - fprintf(stderr, " dentry hit rate: %2ld%% (%ld of %ld)\n", + fprintf(fp, " dentry hit rate: %2ld%% (%ld of %ld)\n", (dhits * 100)/ft->dentry_cache_fills, dhits, ft->dentry_cache_fills); } @@ -1903,7 +1919,7 @@ for (i = ihits = 0; i < INODE_CACHE; i++) ihits += ft->cached_inode_hits[i]; - fprintf(stderr, " inode hit rate: %2ld%% (%ld of %ld)\n", + fprintf(fp, " inode hit rate: %2ld%% (%ld of %ld)\n", (ihits * 100)/ft->inode_cache_fills, ihits, ft->inode_cache_fills); } @@ -2365,6 +2381,8 @@ } for (i = 1; i < 4; i++) { + if (STREQ(arglist[i], "?")) + continue; vaddr = htol(arglist[i], FAULT_ON_ERROR, NULL); if (vaddr == ref->hexval) return TRUE; --- crash-4.0-7.6/help.c 2009-02-05 11:18:44.000000000 -0500 +++ crash-4.0-7.7/help.c 2009-01-26 14:57:23.000000000 -0500 @@ -1,8 +1,8 @@ /* help.c - core analysis suite * * Copyright (C) 1999, 2000, 2001, 2002 Mission Critical Linux, Inc. - * Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008 David Anderson - * Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008 Red Hat, Inc. All rights reserved. + * Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 David Anderson + * Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Red Hat, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -5214,7 +5214,7 @@ static char *version_info[] = { -"Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008 Red Hat, Inc.", +"Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Red Hat, Inc.", "Copyright (C) 2004, 2005, 2006 IBM Corporation", "Copyright (C) 1999-2006 Hewlett-Packard Co", "Copyright (C) 2005, 2006 Fujitsu Limited", --- crash-4.0-7.6/task.c 2009-02-05 11:18:44.000000000 -0500 +++ crash-4.0-7.7/task.c 2009-02-04 16:49:49.000000000 -0500 @@ -1,8 +1,8 @@ /* task.c - core analysis suite * * Copyright (C) 1999, 2000, 2001, 2002 Mission Critical Linux, Inc. - * Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008 David Anderson - * Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008 Red Hat, Inc. All rights reserved. + * Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 David Anderson + * Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Red Hat, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -102,6 +102,12 @@ struct gnu_request req; ulong active_pid; + if (!(tt->idle_threads = (ulong *)calloc(NR_CPUS, sizeof(ulong)))) + error(FATAL, "cannot malloc idle_threads array"); + if (DUMPFILE() && + !(tt->panic_threads = (ulong *)calloc(NR_CPUS, sizeof(ulong)))) + error(FATAL, "cannot malloc panic_threads array"); + if (kernel_symbol_exists("nr_tasks")) { /* * Figure out what maximum NR_TASKS would be by getting the @@ -469,6 +475,15 @@ int i; char *thread_info_buf; + if (!(tt->hardirq_ctx = (ulong *)calloc(NR_CPUS, sizeof(ulong)))) + error(FATAL, "cannot malloc hardirq_ctx space."); + if (!(tt->hardirq_tasks = (ulong *)calloc(NR_CPUS, sizeof(ulong)))) + error(FATAL, "cannot malloc hardirq_tasks space."); + if (!(tt->softirq_ctx = (ulong *)calloc(NR_CPUS, sizeof(ulong)))) + error(FATAL, "cannot malloc softirq_ctx space."); + if (!(tt->softirq_tasks = (ulong *)calloc(NR_CPUS, sizeof(ulong)))) + error(FATAL, "cannot malloc softirq_tasks space."); + thread_info_buf = GETBUF(SIZE(irq_ctx)); i = get_array_length("hardirq_ctx", NULL, 0); @@ -2902,7 +2917,7 @@ { int i, c; struct task_context *tcp; - char format[10]; + char format[15]; char buf[BUFSIZE]; tcp = FIRST_CONTEXT(); @@ -4530,6 +4545,10 @@ task = tt->panic_threads[tt->panic_processor]; if (symbol_exists("panic_ksp")) { + if (!(tt->panic_ksp = (ulong *) + calloc(NR_CPUS, sizeof(void *)))) + error(FATAL, + "cannot malloc panic_ksp array.\n"); readmem(symbol_value("panic_ksp"), KVADDR, tt->panic_ksp, sizeof(void *)*NR_CPUS, "panic_ksp array", @@ -4575,7 +4594,7 @@ ulong task; struct task_context *tc; - if ((task = tt->panic_threads[cpu])) + if (DUMPFILE() && (task = tt->panic_threads[cpu])) return task; tc = FIRST_CONTEXT(); @@ -5555,7 +5574,7 @@ void dump_task_table(int verbose) { - int i, nr_cpus; + int i, j, more, nr_cpus; struct task_context *tc; char buf[BUFSIZE]; int others, wrap, flen; @@ -5671,76 +5690,197 @@ fprintf(fp, " mm_struct: %lx\n", (ulong)tt->mm_struct); fprintf(fp, " init_pid_ns: %lx\n", tt->init_pid_ns); - fprintf(fp, " panic_threads:"); wrap = sizeof(void *) == SIZEOF_32BIT ? 8 : 4; flen = sizeof(void *) == SIZEOF_32BIT ? 8 : 16; nr_cpus = kt->kernel_NR_CPUS ? kt->kernel_NR_CPUS : NR_CPUS; + + fprintf(fp, " idle_threads:"); for (i = 0; i < nr_cpus; i++) { - if ((i % wrap) == 0) + if (!tt->idle_threads) { + fprintf(fp, " (unused)"); + break; + } + if ((i % wrap) == 0) { fprintf(fp, "\n "); - fprintf(fp, "%.*lx ", flen, tt->panic_threads[i]); + for (j = i, more = FALSE; j < nr_cpus; j++) { + if (tt->idle_threads[j]) { + more = TRUE; + break; + } + } + } + fprintf(fp, "%.*lx ", flen, tt->idle_threads[i]); + if (!more) { + fprintf(fp, "..."); + break; + } + } + fprintf(fp, "\n"); + + fprintf(fp, " active_set:"); + for (i = 0; i < nr_cpus; i++) { + if (!tt->active_set) { + fprintf(fp, " (unused)"); + break; + } + if ((i % wrap) == 0) { + fprintf(fp, "\n "); + for (j = i, more = FALSE; j < nr_cpus; j++) { + if (tt->active_set[j]) { + more = TRUE; + break; + } + } + } + fprintf(fp, "%.*lx ", flen, tt->active_set[i]); + if (!more) { + fprintf(fp, "..."); + break; + } + } + fprintf(fp, "\n"); + + fprintf(fp, " panic_threads:"); + for (i = 0; i < nr_cpus; i++) { + if (!tt->panic_threads) { + fprintf(fp, " (unused)"); + break; + } + if ((i % wrap) == 0) { + fprintf(fp, "\n "); + for (j = i, more = FALSE; j < nr_cpus; j++) { + if (tt->panic_threads[j]) { + more = TRUE; + break; + } + } + } + fprintf(fp, "%.*lx ", flen, tt->panic_threads[i]); + if (!more) { + fprintf(fp, "..."); + break; + } } fprintf(fp, "\n"); fprintf(fp, " panic_ksp:"); for (i = 0; i < nr_cpus; i++) { - if ((i % wrap) == 0) + if (!tt->panic_ksp) { + fprintf(fp, " (unused)"); + break; + } + if ((i % wrap) == 0) { fprintf(fp, "\n "); + for (j = i, more = FALSE; j < nr_cpus; j++) { + if (tt->panic_ksp[j]) { + more = TRUE; + break; + } + } + } fprintf(fp, "%.*lx ", flen, tt->panic_ksp[i]); + if (!more) { + fprintf(fp, "..."); + break; + } } fprintf(fp, "\n"); fprintf(fp, " hardirq_ctx:"); for (i = 0; i < nr_cpus; i++) { - if ((i % wrap) == 0) + if (!tt->hardirq_ctx) { + fprintf(fp, " (unused)"); + break; + } + if ((i % wrap) == 0) { fprintf(fp, "\n "); + for (j = i, more = FALSE; j < nr_cpus; j++) { + if (tt->hardirq_ctx[j]) { + more = TRUE; + break; + } + } + } fprintf(fp, "%.*lx ", flen, tt->hardirq_ctx[i]); + if (!more) { + fprintf(fp, "..."); + break; + } } fprintf(fp, "\n"); fprintf(fp, " hardirq_tasks:"); for (i = 0; i < nr_cpus; i++) { - if ((i % wrap) == 0) + if (!tt->hardirq_tasks) { + fprintf(fp, " (unused)"); + break; + } + if ((i % wrap) == 0) { fprintf(fp, "\n "); + for (j = i, more = FALSE; j < nr_cpus; j++) { + if (tt->hardirq_tasks[j]) { + more = TRUE; + break; + } + } + } fprintf(fp, "%.*lx ", flen, tt->hardirq_tasks[i]); + if (!more) { + fprintf(fp, "..."); + break; + } } fprintf(fp, "\n"); fprintf(fp, " softirq_ctx:"); for (i = 0; i < nr_cpus; i++) { - if ((i % wrap) == 0) + if (!tt->softirq_ctx) { + fprintf(fp, " (unused)"); + break; + } + if ((i % wrap) == 0) { fprintf(fp, "\n "); + for (j = i, more = FALSE; j < nr_cpus; j++) { + if (tt->softirq_ctx[j]) { + more = TRUE; + break; + } + } + } fprintf(fp, "%.*lx ", flen, tt->softirq_ctx[i]); + if (!more) { + fprintf(fp, "..."); + break; + } } fprintf(fp, "\n"); fprintf(fp, " softirq_tasks:"); for (i = 0; i < nr_cpus; i++) { - if ((i % wrap) == 0) + if (!tt->softirq_tasks) { + fprintf(fp, " (unused)"); + break; + } + if ((i % wrap) == 0) { fprintf(fp, "\n "); + for (j = i, more = FALSE; j < nr_cpus; j++) { + if (tt->softirq_tasks[j]) { + more = TRUE; + break; + } + } + } fprintf(fp, "%.*lx ", flen, tt->softirq_tasks[i]); + if (!more) { + fprintf(fp, "..."); + break; + } } fprintf(fp, "\n"); - fprintf(fp, " idle_threads:"); - for (i = 0; i < nr_cpus; i++) { - if ((i % wrap) == 0) - fprintf(fp, "\n "); - fprintf(fp, "%.*lx ", flen, tt->idle_threads[i]); - } - fprintf(fp, "\n"); - - fprintf(fp, " active_set:"); - for (i = 0; i < nr_cpus; i++) { - if ((i % wrap) == 0) - fprintf(fp, "\n "); - fprintf(fp, "%.*lx ", flen, tt->active_set[i]); - } - fprintf(fp, "\n"); - if (!verbose) return; @@ -5909,6 +6049,8 @@ { if (kt->runq_siblings == 1) return cpu; + else if (!(kt->__rq_idx)) + return 0; else return kt->__rq_idx[cpu]; } @@ -5921,6 +6063,8 @@ { if (kt->runq_siblings == 1) return 0; + else if (!(kt->__cpu_idx)) + return 0; else return kt->__cpu_idx[cpu]; } @@ -5987,7 +6131,10 @@ else return FALSE; - BZERO(tt->active_set, sizeof(ulong) * NR_CPUS); + + if (!(tt->active_set = (ulong *)calloc(NR_CPUS, sizeof(ulong)))) + error(FATAL, "cannot malloc active_set array"); + runqbuf = GETBUF(SIZE(runqueue)); cnt = 0; --- crash-4.0-7.6/kernel.c 2009-02-05 11:18:44.000000000 -0500 +++ crash-4.0-7.7/kernel.c 2009-02-04 16:53:05.000000000 -0500 @@ -1,8 +1,8 @@ /* kernel.c - core analysis suite * * Copyright (C) 1999, 2000, 2001, 2002 Mission Critical Linux, Inc. - * Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008 David Anderson - * Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008 Red Hat, Inc. All rights reserved. + * Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 David Anderson + * Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Red Hat, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -67,6 +67,9 @@ if (pc->flags & KERNEL_DEBUG_QUERY) return; + if (!(kt->cpu_flags = (ulong *)calloc(NR_CPUS, sizeof(ulong)))) + error(FATAL, "cannot malloc cpu_flags array"); + cpu_maps_init(); kt->stext = symbol_value("_stext"); @@ -210,6 +213,12 @@ NULL, 0); if (symbol_exists("__cpu_idx") && symbol_exists("__rq_idx")) { + if (!(kt->__cpu_idx = (long *) + calloc(NR_CPUS, sizeof(long)))) + error(FATAL, "cannot malloc __cpu_idx array"); + if (!(kt->__rq_idx = (long *) + calloc(NR_CPUS, sizeof(long)))) + error(FATAL, "cannot malloc __rq_idx array"); if (!readmem(symbol_value("__cpu_idx"), KVADDR, &kt->__cpu_idx[0], sizeof(long) * NR_CPUS, "__cpu_idx[NR_CPUS]", RETURN_ON_ERROR)) @@ -1828,6 +1837,12 @@ "-a option not supported on a live system\n"); for (c = 0; c < NR_CPUS; c++) { + if (setjmp(pc->foreach_loop_env)) { + free_all_bufs(); + continue; + } + pc->flags |= IN_FOREACH; + if ((tc = task_to_context(tt->panic_threads[c]))) { BT_SETUP(tc); if (!BT_REFERENCE_CHECK(bt)) @@ -1835,6 +1850,7 @@ back_trace(bt); } } + pc->flags &= ~IN_FOREACH; return; } @@ -3251,15 +3267,18 @@ * First look for a module based upon its reference name. * If that fails, try replacing any underscores in the * reference name with a dash. + * If that fails, because of intermingled dashes and underscores, + * try a regex expression. * * Example: module name "dm_mod" comes from "dm-mod.ko" objfile + * module name "dm_region_hash" comes from "dm-region_hash.ko" objfile */ static char * find_module_objfile(char *modref, char *filename, char *tree) { char * retbuf; char tmpref[BUFSIZE]; - int c; + int i, c; retbuf = module_objfile_search(modref, filename, tree); @@ -3271,6 +3290,20 @@ retbuf = module_objfile_search(tmpref, filename, tree); } + if (!retbuf && (count_chars(modref, '_') > 1)) { + for (i = c = 0; modref[i]; i++) { + if (modref[i] == '_') { + tmpref[c++] = '['; + tmpref[c++] = '_'; + tmpref[c++] = '-'; + tmpref[c++] = ']'; + } else + tmpref[c++] = modref[i]; + } + tmpref[c] = NULLCHAR; + retbuf = module_objfile_search(tmpref, filename, tree); + } + return retbuf; } @@ -3899,7 +3932,7 @@ void dump_kernel_table(int verbose) { - int i, nr_cpus; + int i, j, more, nr_cpus; struct new_utsname *uts; int others; @@ -4012,18 +4045,69 @@ fprintf(fp, " runq_siblings: %d\n", kt->runq_siblings); fprintf(fp, " __rq_idx[NR_CPUS]: "); nr_cpus = kt->kernel_NR_CPUS ? kt->kernel_NR_CPUS : NR_CPUS; - for (i = 0; i < nr_cpus; i++) + for (i = 0; i < nr_cpus; i++) { + if (!(kt->__rq_idx)) { + fprintf(fp, "(unused)"); + break; + } fprintf(fp, "%ld ", kt->__rq_idx[i]); + for (j = i, more = FALSE; j < nr_cpus; j++) { + if (kt->__rq_idx[j]) + more = TRUE; + } + if (!more) { + fprintf(fp, "..."); + break; + } + } fprintf(fp, "\n __cpu_idx[NR_CPUS]: "); - for (i = 0; i < nr_cpus; i++) + for (i = 0; i < nr_cpus; i++) { + if (!(kt->__cpu_idx)) { + fprintf(fp, "(unused)"); + break; + } fprintf(fp, "%ld ", kt->__cpu_idx[i]); + for (j = i, more = FALSE; j < nr_cpus; j++) { + if (kt->__cpu_idx[j]) + more = TRUE; + } + if (!more) { + fprintf(fp, "..."); + break; + } + } fprintf(fp, "\n __per_cpu_offset[NR_CPUS]:"); - for (i = 0; i < nr_cpus; i++) + for (i = 0; i < nr_cpus; i++) { fprintf(fp, "%s%.*lx ", (i % 4) == 0 ? "\n " : "", LONG_PRLEN, kt->__per_cpu_offset[i]); + if ((i % 4) == 0) { + for (j = i, more = FALSE; j < nr_cpus; j++) { + if (kt->__per_cpu_offset[j]) + more = TRUE; + } + } + if (!more) { + fprintf(fp, "..."); + break; + } + + } fprintf(fp, "\n cpu_flags[NR_CPUS]: "); - for (i = 0; i < nr_cpus; i++) + for (i = 0; i < nr_cpus; i++) { + if (!(kt->cpu_flags)) { + fprintf(fp, "(unused)\n"); + goto no_cpu_flags; + } fprintf(fp, "%lx ", kt->cpu_flags[i]); + for (j = i, more = FALSE; j < nr_cpus; j++) { + if (kt->cpu_flags[j]) + more = TRUE; + } + if (!more) { + fprintf(fp, "..."); + break; + } + } fprintf(fp, "\n"); fprintf(fp, " cpu_possible_map: "); if (kernel_symbol_exists("cpu_possible_map")) { @@ -4052,6 +4136,7 @@ fprintf(fp, "\n"); } else fprintf(fp, "(does not exist)\n"); +no_cpu_flags: others = 0; fprintf(fp, " xen_flags: %lx (", kt->xen_flags); if (kt->xen_flags & WRITABLE_PAGE_TABLES) --- crash-4.0-7.6/configure.c 2009-02-05 11:18:44.000000000 -0500 +++ crash-4.0-7.7/configure.c 2009-01-26 14:55:25.000000000 -0500 @@ -1,8 +1,8 @@ /* configure.c - core analysis suite * * Copyright (C) 1999, 2000, 2001, 2002 Mission Critical Linux, Inc. - * Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008 David Anderson - * Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008 Red Hat, Inc. All rights reserved. + * Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 David Anderson + * Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Red Hat, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by --- crash-4.0-7.6/x86.c 2009-02-05 11:18:44.000000000 -0500 +++ crash-4.0-7.7/x86.c 2009-02-04 15:30:50.000000000 -0500 @@ -1617,6 +1617,9 @@ x86_in_irqstack(ulong addr) { int c; + + if (!(tt->flags & IRQSTACKS)) + return 0; for (c = 0; c < NR_CPUS; c++) { if (tt->hardirq_ctx[c]) { --- crash-4.0-7.6/s390.c 2009-02-05 11:18:44.000000000 -0500 +++ crash-4.0-7.7/s390.c 2009-01-15 14:07:23.000000000 -0500 @@ -409,6 +409,10 @@ if (STREQ(name, "Letext") || STREQ(name, "gcc2_compiled.")) return FALSE; + /* reject L2^B symbols */ + if (strstr(name, "L2\002") == name) + return FALSE; + /* throw away all symbols containing a '.' */ for(i = 0; i < strlen(name);i++){ if(name[i] == '.') --- crash-4.0-7.6/s390x.c 2009-02-05 11:18:44.000000000 -0500 +++ crash-4.0-7.7/s390x.c 2009-01-15 14:07:23.000000000 -0500 @@ -418,6 +418,10 @@ if (STREQ(name, "Letext") || STREQ(name, "gcc2_compiled.")) return FALSE; + /* reject L2^B symbols */ + if (strstr(name, "L2\002") == name) + return FALSE; + /* throw away all symbols containing a '.' */ for(i = 0; i < strlen(name);i++){ if(name[i] == '.') --- crash-4.0-7.6/ppc64.c 2009-02-05 11:18:44.000000000 -0500 +++ crash-4.0-7.7/ppc64.c 2009-02-04 15:34:33.000000000 -0500 @@ -1150,6 +1150,9 @@ { int c; + if (!(tt->flags & IRQSTACKS)) + return 0; + for (c = 0; c < NR_CPUS; c++) { if (tt->hardirq_ctx[c]) { if ((addr >= tt->hardirq_ctx[c]) && --- crash-4.0-7.6/x86_64.c 2009-02-05 11:18:43.000000000 -0500 +++ crash-4.0-7.7/x86_64.c 2009-01-26 14:56:02.000000000 -0500 @@ -1,7 +1,7 @@ /* x86_64.c -- core analysis suite * - * Copyright (C) 2004, 2005, 2006, 2007 David Anderson - * Copyright (C) 2004, 2005, 2006, 2007 Red Hat, Inc. All rights reserved. + * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 David Anderson + * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Red Hat, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -2271,7 +2271,7 @@ #define STACK_TRANSITION_ERRMSG_E_P \ "cannot transition from exception stack to current process stack:\n exception stack pointer: %lx\n process stack pointer: %lx\n current_stack_base: %lx\n" #define STACK_TRANSITION_ERRMSG_I_P \ -"cannot transition from IRQ stack to current process stack:\n IRQ stack pointer: %lx\n process stack pointer: %lx\n current stack base: %lx" +"cannot transition from IRQ stack to current process stack:\n IRQ stack pointer: %lx\n process stack pointer: %lx\n current stack base: %lx\n" /* * Low-budget back tracer -- dump text return addresses, following call chain --- crash-4.0-7.6/symbols.c 2009-02-05 11:18:43.000000000 -0500 +++ crash-4.0-7.7/symbols.c 2009-01-29 15:33:13.000000000 -0500 @@ -1,8 +1,8 @@ /* symbols.c - core analysis suite * * Copyright (C) 1999, 2000, 2001, 2002 Mission Critical Linux, Inc. - * Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008 David Anderson - * Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008 Red Hat, Inc. All rights reserved. + * Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 David Anderson + * Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Red Hat, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -7992,8 +7992,11 @@ error(FATAL, "cannot determine object file format: %s\n", namelist); - if (!(bfd_get_file_flags(mbfd) & HAS_SYMS)) - error(FATAL, "no symbols in object file: %s\n", namelist); + if (LKCD_KERNTYPES() && (file_elf_version(namelist) == EV_DWARFEXTRACT)) + goto add_symbols; /* no symbols, add the debuginfo */ + + if (!(bfd_get_file_flags(mbfd) & HAS_SYMS)) + error(FATAL, "no symbols in object file: %s\n", namelist); symcount = bfd_read_minisymbols(mbfd, FALSE, &minisyms, &size); if (symcount < 0) --- crash-4.0-7.6/cmdline.c 2009-02-05 11:18:44.000000000 -0500 +++ crash-4.0-7.7/cmdline.c 2009-01-26 14:54:24.000000000 -0500 @@ -1,8 +1,8 @@ /* cmdline.c - core analysis suite * * Copyright (C) 1999, 2000, 2001, 2002 Mission Critical Linux, Inc. - * Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007 David Anderson - * Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007 Red Hat, Inc. All rights reserved. + * Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 David Anderson + * Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Red Hat, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by --- crash-4.0-7.6/lkcd_x86_trace.c 2009-02-05 11:18:44.000000000 -0500 +++ crash-4.0-7.7/lkcd_x86_trace.c 2009-01-26 14:54:36.000000000 -0500 @@ -5,8 +5,8 @@ /* * lkcd_x86_trace.c * - * Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008 David Anderson - * Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008 Red Hat, Inc. All rights reserved. + * Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 David Anderson + * Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Red Hat, Inc. All rights reserved. * * Adapted as noted from the following LKCD files: * --- crash-4.0-7.6/netdump.c 2009-02-05 11:18:44.000000000 -0500 +++ crash-4.0-7.7/netdump.c 2009-01-15 16:17:17.000000000 -0500 @@ -36,7 +36,14 @@ #define ELFREAD 0 #define MIN_PAGE_SIZE (4096) - + +/* + * PPC64 and IA64 architectures have configurable page sizes, + * which can differ from the host machine's page size. + */ +#define READ_PAGESIZE_FROM_VMCOREINFO() \ + (machine_type("IA64") || machine_type("PPC64")) + /* * Determine whether a file is a netdump/diskdump/kdump creation, * and if TRUE, initialize the vmcore_data structure. @@ -888,6 +895,8 @@ if (i) netdump_print("\n"); } netdump_print(" num_prstatus_notes: %d\n", nd->num_prstatus_notes); + netdump_print(" vmcoreinfo: %lx\n", (ulong)nd->vmcoreinfo); + netdump_print(" size_vmcoreinfo: %d\n", nd->size_vmcoreinfo); netdump_print(" nt_prstatus_percpu: "); wrap = sizeof(void *) == SIZEOF_32BIT ? 8 : 4; flen = sizeof(void *) == SIZEOF_32BIT ? 8 : 16; @@ -1392,6 +1401,96 @@ } /* + * VMCOREINFO + * + * This is a ELF note intented for makedumpfile that is exported by the + * kernel that crashes and presented as ELF note to the /proc/vmcore + * of the panic kernel. + */ + +#define VMCOREINFO_NOTE_NAME "VMCOREINFO" +#define VMCOREINFO_NOTE_NAME_BYTES (sizeof(VMCOREINFO_NOTE_NAME)) + +/* + * Reads a string value from VMCOREINFO. + * + * Returns a string (that has to be freed by the caller) that contains the + * value for key or NULL if the key has not been found. + */ +static char * +vmcoreinfo_read_string(const char *key) +{ + int i, j, end; + size_t value_length; + size_t key_length = strlen(key); + char *vmcoreinfo = (char *)nd->vmcoreinfo; + char *value = NULL; + + if (!nd->vmcoreinfo) + return NULL; + + /* the '+ 1' is the equal sign */ + for (i = 0; i < (nd->size_vmcoreinfo - key_length + 1); i++) { + /* + * We must also check if we're at the beginning of VMCOREINFO + * or the separating newline is there, and of course if we + * have a equal sign after the key. + */ + if ((strncmp(vmcoreinfo+i, key, key_length) == 0) && + (i == 0 || vmcoreinfo[i-1] == '\n') && + (vmcoreinfo[i+key_length] == '=')) { + + end = -1; + + /* Found -- search for the next newline. */ + for (j = i + key_length + 1; + j < nd->size_vmcoreinfo; j++) { + if (vmcoreinfo[j] == '\n') { + end = j; + break; + } + } + + /* + * If we didn't find an end, we assume it's the end + * of VMCOREINFO data. + */ + if (end == -1) { + /* Point after the end. */ + end = nd->size_vmcoreinfo + 1; + } + + value_length = end - (1+ i + key_length); + value = malloc(value_length); + if (value) + strncpy(value, vmcoreinfo + i + key_length + 1, + value_length); + break; + } + } + + return value; +} + +/* + * Reads an integer value from VMCOREINFO. + */ +static long +vmcoreinfo_read_integer(const char *key, long default_value) +{ + char *string; + long retval = default_value; + + string = vmcoreinfo_read_string(key); + if (string) { + retval = atol(string); + free(string); + } + + return retval; +} + +/* * Dump a note section header -- the actual data is defined by netdump */ @@ -1686,9 +1785,18 @@ if (store) error(WARNING, "unknown Xen n_type: %lx\n\n", note->n_type); - } else if (vmcoreinfo) + } else if (vmcoreinfo) { netdump_print("(unused)\n"); - else + + if (READ_PAGESIZE_FROM_VMCOREINFO() && store) { + nd->vmcoreinfo = (char *)nd->elf64 + offset + + (sizeof(Elf64_Nhdr) + + ((note->n_namesz + 3) & ~3)); + nd->size_vmcoreinfo = note->n_descsz; + nd->page_size = (uint) + vmcoreinfo_read_integer("PAGESIZE", 0); + } + } else netdump_print("(?)\n"); break; --- crash-4.0-7.6/diskdump.c 2009-02-05 11:18:44.000000000 -0500 +++ crash-4.0-7.7/diskdump.c 2009-01-15 16:17:17.000000000 -0500 @@ -107,7 +107,7 @@ struct disk_dump_sub_header *sub_header = NULL; struct kdump_sub_header *sub_header_kdump = NULL; int bitmap_len; - const int block_size = (int)sysconf(_SC_PAGESIZE); + int block_size = (int)sysconf(_SC_PAGESIZE); off_t offset; const off_t failed = (off_t)-1; ulong pfn; @@ -116,7 +116,8 @@ if (block_size < 0) return FALSE; - if ((header = malloc(block_size)) == NULL) +restart: + if ((header = realloc(header, block_size)) == NULL) error(FATAL, "diskdump / compressed kdump: cannot malloc block_size buffer\n"); if (lseek(dd->dfd, 0, SEEK_SET) == failed) { @@ -166,13 +167,15 @@ goto err; if (header->block_size != block_size) { - error(INFO, "%s: block size in the dump header does not match" - " with system page size\n", - DISKDUMP_VALID() ? "diskdump" : "compressed kdump"); - goto err; + block_size = header->block_size; + if (CRASHDEBUG(1)) + fprintf(fp, + "retrying with different block/page size: %d\n", + header->block_size); + goto restart; } - dd->block_size = block_size; - dd->block_shift = ffs(block_size) - 1; + dd->block_size = header->block_size; + dd->block_shift = ffs(header->block_size) - 1; if (sizeof(*header) + sizeof(void *) * header->nr_cpus > block_size || header->nr_cpus <= 0) { --- crash-4.0-7.6/unwind.c 2009-02-05 11:18:43.000000000 -0500 +++ crash-4.0-7.7/unwind.c 2009-01-23 10:30:52.000000000 -0500 @@ -1395,10 +1395,45 @@ unwind_init_v3(void) #endif { + int len; struct gnu_request request, *req; req = &request; + if (LKCD_KERNTYPES()) { + if ((len = STRUCT_SIZE("unw")) == 0) { + error(WARNING, + "cannot determine unw.tables offset; no struct unw\n"); + machdep->flags |= UNW_OUT_OF_SYNC; + return; + } + machdep->machspec->unw_tables_offset = + MEMBER_OFFSET("unw", "tables"); + if (MEMBER_EXISTS("unw", "r0")) + machdep->flags |= UNW_R0; + /* + * no verification of save_order, sw_off, preg_index as + * we're purely depending on the structure definition. + */ + if (MEMBER_EXISTS("unw", "pt_regs_offsets")) { + machdep->machspec->unw_pt_regs_offsets = + MEMBER_OFFSET("unw", "pt_regs_offsets") - + machdep->machspec->unw_tables_offset; + machdep->machspec->unw_kernel_table_offset = + MEMBER_OFFSET("unw", "kernel_table") - + machdep->machspec->unw_tables_offset; + machdep->flags |= UNW_PTREGS; + } + if (!load_unw_table(CLEAR_SCRIPT_CACHE)) { + error(WARNING, + "unwind_init: cannot read kernel unw table\n"); + machdep->flags |= UNW_OUT_OF_SYNC; + } + machdep->machspec->unw = (void *)&unw; + /* fall to common structure size verifications */ + goto verify; + } + if (get_symbol_type("unw", "tables", req) == TYPE_CODE_UNDEF) { /* * KLUDGE ALERT: @@ -1449,7 +1484,7 @@ machdep->machspec->unw = (void *)&unw; } - +verify: verify_common_struct("unw_frame_info", sizeof(struct unw_frame_info)); verify_common_struct("unw_table", sizeof(struct unw_table)); verify_common_struct("unw_table_entry", sizeof(struct unw_table_entry)); --- crash-4.0-7.6/defs.h 2009-02-05 11:18:44.000000000 -0500 +++ crash-4.0-7.7/defs.h 2009-02-05 10:43:34.000000000 -0500 @@ -1,8 +1,8 @@ /* defs.h - core analysis suite * * Copyright (C) 1999, 2000, 2001, 2002 Mission Critical Linux, Inc. - * Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008 David Anderson - * Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008 Red Hat, Inc. All rights reserved. + * Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 David Anderson + * Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Red Hat, Inc. All rights reserved. * Copyright (C) 2002 Silicon Graphics, Inc. * * This program is free software; you can redistribute it and/or modify @@ -64,7 +64,7 @@ #define NR_CPUS (256) #endif #ifdef X86_64 -#define NR_CPUS (256) +#define NR_CPUS (512) #endif #ifdef ALPHA #define NR_CPUS (64) @@ -76,7 +76,7 @@ #define NR_CPUS (4096) #endif #ifdef PPC64 -#define NR_CPUS (128) +#define NR_CPUS (1024) #endif #ifdef S390 #define NR_CPUS (64) @@ -512,10 +512,10 @@ uint gcc_version[3]; int runq_siblings; int kernel_NR_CPUS; - long __rq_idx[NR_CPUS]; - long __cpu_idx[NR_CPUS]; long __per_cpu_offset[NR_CPUS]; - ulong cpu_flags[NR_CPUS]; + long *__rq_idx; + long *__cpu_idx; + ulong *cpu_flags; #define POSSIBLE (0x1) #define PRESENT (0x2) #define ONLINE (0x4) @@ -602,14 +602,14 @@ ulong retries; ulong panicmsg; int panic_processor; - ulong idle_threads[NR_CPUS]; - ulong panic_threads[NR_CPUS]; - ulong panic_ksp[NR_CPUS]; - ulong active_set[NR_CPUS]; - ulong hardirq_ctx[NR_CPUS]; - ulong hardirq_tasks[NR_CPUS]; - ulong softirq_ctx[NR_CPUS]; - ulong softirq_tasks[NR_CPUS]; + ulong *idle_threads; + ulong *panic_threads; + ulong *active_set; + ulong *panic_ksp; + ulong *hardirq_ctx; + ulong *hardirq_tasks; + ulong *softirq_ctx; + ulong *softirq_tasks; ulong panic_task; ulong this_task; int pidhash_len; @@ -3143,6 +3143,7 @@ #define machdep_init(X) ppc64_init(X) #endif int clean_exit(int); +int untrusted_file(FILE *, char *); /* * cmdline.c --- crash-4.0-7.6/netdump.h 2009-02-05 11:18:43.000000000 -0500 +++ crash-4.0-7.7/netdump.h 2009-01-27 11:42:12.000000000 -0500 @@ -1,7 +1,7 @@ /* netdump.h * - * Copyright (C) 2002, 2003, 2004, 2005 David Anderson - * Copyright (C) 2002, 2003, 2004, 2005 Red Hat, Inc. All rights reserved. + * Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008 David Anderson + * Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008 Red Hat, Inc. All rights reserved. * * This software may be freely redistributed under the terms of the * GNU General Public License. @@ -66,6 +66,8 @@ uint num_prstatus_notes; void *nt_prstatus_percpu[NR_CPUS]; struct xen_kdump_data *xen_kdump_data; + void *vmcoreinfo; + uint size_vmcoreinfo; }; /* --- crash-4.0-7.6/gdb-6.1/gdb/Makefile.in 2009-02-05 11:18:44.000000000 -0500 +++ crash-4.0-7.7/gdb-6.1/gdb/Makefile.in 2009-01-22 15:33:12.000000000 -0500 @@ -2513,7 +2513,7 @@ $(expression_h) $(frame_h) $(value_h) $(language_h) $(filenames_h) \ $(objfiles_h) $(source_h) $(disasm_h) $(ui_out_h) $(top_h) \ $(cli_decode_h) $(cli_script_h) $(cli_setshow_h) $(cli_cmds_h) \ - $(tui_h) + $(tui_h) $(gdb_stat_h) $(CC) -c $(INTERNAL_CFLAGS) $(srcdir)/cli/cli-cmds.c cli-decode.o: $(srcdir)/cli/cli-decode.c $(defs_h) $(symtab_h) \ $(gdb_regex_h) $(gdb_string_h) $(ui_out_h) $(cli_cmds_h) \ --- crash-4.0-7.6/gdb-6.1/gdb/main.c 2009-02-05 11:18:44.000000000 -0500 +++ crash-4.0-7.7/gdb-6.1/gdb/main.c 2009-01-22 15:33:12.000000000 -0500 @@ -628,7 +628,7 @@ if (!inhibit_gdbinit) { - catch_command_errors (source_command, homeinit, 0, RETURN_MASK_ALL); + catch_command_errors (source_command, homeinit, -1, RETURN_MASK_ALL); } /* Do stats; no need to do them elsewhere since we'll only @@ -714,7 +714,7 @@ || memcmp ((char *) &homebuf, (char *) &cwdbuf, sizeof (struct stat))) if (!inhibit_gdbinit) { - catch_command_errors (source_command, gdbinit, 0, RETURN_MASK_ALL); + catch_command_errors (source_command, gdbinit, -1, RETURN_MASK_ALL); } for (i = 0; i < ncmd; i++) --- crash-4.0-7.6/gdb-6.1/gdb/dwarf2read.c 2009-02-05 11:18:44.000000000 -0500 +++ crash-4.0-7.7/gdb-6.1/gdb/dwarf2read.c 2009-01-22 16:09:48.000000000 -0500 @@ -7391,8 +7391,7 @@ When the result is a register number, the global isreg flag is set, otherwise it is cleared. - Note that stack[0] is unused except as a default error return. - Note that stack overflow is not yet handled. */ + Note that stack[0] is unused except as a default error return. */ static CORE_ADDR decode_locdesc (struct dwarf_block *blk, struct dwarf2_cu *cu) @@ -7409,7 +7408,7 @@ i = 0; stacki = 0; - stack[stacki] = 0; + stack[++stacki] = 0; isreg = 0; while (i < size) @@ -7591,6 +7590,16 @@ dwarf_stack_op_name (op)); return (stack[stacki]); } + /* Enforce maximum stack depth of size-1 to avoid ++stacki writing + outside of the allocated space. Also enforce minimum > 0. + -- wad@google.com 14 Aug 2006 */ + if (stacki >= sizeof (stack) / sizeof (*stack) - 1) + internal_error (__FILE__, __LINE__, + _("location description stack too deep: %d"), + stacki); + if (stacki <= 0) + internal_error (__FILE__, __LINE__, + _("location description stack too shallow")); } return (stack[stacki]); } --- crash-4.0-7.6/gdb-6.1.patch 2009-02-05 11:18:43.000000000 -0500 +++ crash-4.0-7.7/gdb-6.1.patch 2009-01-22 16:26:30.000000000 -0500 @@ -95,3 +95,225 @@ #include #include #include +--- gdb-6.1/gdb/cli/cli-cmds.c.orig ++++ gdb-6.1/gdb/cli/cli-cmds.c +@@ -37,6 +37,7 @@ + #include "objfiles.h" + #include "source.h" + #include "disasm.h" ++#include "gdb_stat.h" + + #include "ui-out.h" + +@@ -54,6 +55,8 @@ + #define GDBINIT_FILENAME ".gdbinit" + #endif + ++#include ++ + /* Prototypes for local command functions */ + + static void complete_command (char *, int); +@@ -441,12 +444,30 @@ source_command (char *args, int from_tty + stream = fopen (file, FOPEN_RT); + if (!stream) + { +- if (from_tty) ++ if (from_tty > 0) + perror_with_name (file); + else + return; + } + ++ if (from_tty == -1) ++ { ++ struct stat statbuf; ++ int fd = fileno (stream); ++ if (fstat (fd, &statbuf) < 0) ++ { ++ perror_with_name (file); ++ fclose (stream); ++ return; ++ } ++ if (statbuf.st_uid != getuid () || (statbuf.st_mode & S_IWOTH)) ++ { ++ extern void untrusted_file(FILE *, char *); untrusted_file(NULL, file); ++ fclose (stream); ++ return; ++ } ++ } ++ + script_from_file (stream, file); + + do_cleanups (old_cleanups); +--- gdb-6.1/gdb/dwarfread.c.orig ++++ gdb-6.1/gdb/dwarfread.c +@@ -2138,9 +2138,7 @@ decode_line_numbers (char *linetable) + + NOTES + +- Note that stack[0] is unused except as a default error return. +- Note that stack overflow is not yet handled. +- */ ++ Note that stack[0] is unused except as a default error return. */ + + static int + locval (struct dieinfo *dip) +@@ -2160,7 +2158,7 @@ locval (struct dieinfo *dip) + loc += nbytes; + end = loc + locsize; + stacki = 0; +- stack[stacki] = 0; ++ stack[++stacki] = 0; + dip->isreg = 0; + dip->offreg = 0; + dip->optimized_out = 1; +@@ -2224,6 +2222,16 @@ locval (struct dieinfo *dip) + stacki--; + break; + } ++ /* Enforce maximum stack depth of size-1 to avoid ++stacki writing ++ outside of the allocated space. Also enforce minimum > 0. ++ -- wad@google.com 14 Aug 2006 */ ++ if (stacki >= sizeof (stack) / sizeof (*stack) - 1) ++ internal_error (__FILE__, __LINE__, ++ _("location description stack too deep: %d"), ++ stacki); ++ if (stacki <= 0) ++ internal_error (__FILE__, __LINE__, ++ _("location description stack too shallow")); + } + return (stack[stacki]); + } +--- gdb-6.1/bfd/elfcode.h.orig ++++ gdb-6.1/bfd/elfcode.h +@@ -33,7 +33,7 @@ Foundation, Inc., 59 Temple Place - Suit + /* Problems and other issues to resolve. + + (1) BFD expects there to be some fixed number of "sections" in +- the object file. I.E. there is a "section_count" variable in the ++ the object file. I.E. there is a "section_count" variable in the + bfd structure which contains the number of sections. However, ELF + supports multiple "views" of a file. In particular, with current + implementations, executable files typically have two tables, a +@@ -629,8 +629,13 @@ elf_object_p (bfd *abfd) + + if (i_ehdrp->e_shoff != 0) + { ++ bfd_signed_vma where = i_ehdrp->e_shoff; ++ ++ if (where != (file_ptr) where) ++ goto got_wrong_format_error; ++ + /* Seek to the section header table in the file. */ +- if (bfd_seek (abfd, (file_ptr) i_ehdrp->e_shoff, SEEK_SET) != 0) ++ if (bfd_seek (abfd, (file_ptr) where, SEEK_SET) != 0) + goto got_no_match; + + /* Read the first section header at index 0, and convert to internal +@@ -642,11 +647,46 @@ elf_object_p (bfd *abfd) + /* If the section count is zero, the actual count is in the first + section header. */ + if (i_ehdrp->e_shnum == SHN_UNDEF) +- i_ehdrp->e_shnum = i_shdr.sh_size; ++ { ++ i_ehdrp->e_shnum = i_shdr.sh_size; ++ if (i_ehdrp->e_shnum != i_shdr.sh_size ++ || i_ehdrp->e_shnum == 0) ++ goto got_wrong_format_error; ++ } + + /* And similarly for the string table index. */ + if (i_ehdrp->e_shstrndx == SHN_XINDEX) +- i_ehdrp->e_shstrndx = i_shdr.sh_link; ++ { ++ i_ehdrp->e_shstrndx = i_shdr.sh_link; ++ if (i_ehdrp->e_shstrndx != i_shdr.sh_link) ++ goto got_wrong_format_error; ++ } ++ ++ /* Sanity check that we can read all of the section headers. ++ It ought to be good enough to just read the last one. */ ++ if (i_ehdrp->e_shnum != 1) ++ { ++ /* Check that we don't have a totally silly number of sections. */ ++ if (i_ehdrp->e_shnum > (unsigned int) -1 / sizeof (x_shdr) ++ || i_ehdrp->e_shnum > (unsigned int) -1 / sizeof (i_shdr)) ++ goto got_wrong_format_error; ++ ++ where += (i_ehdrp->e_shnum - 1) * sizeof (x_shdr); ++ if (where != (file_ptr) where) ++ goto got_wrong_format_error; ++ if ((bfd_size_type) where <= i_ehdrp->e_shoff) ++ goto got_wrong_format_error; ++ ++ if (bfd_seek (abfd, (file_ptr) where, SEEK_SET) != 0) ++ goto got_no_match; ++ if (bfd_bread (&x_shdr, sizeof x_shdr, abfd) != sizeof (x_shdr)) ++ goto got_no_match; ++ ++ /* Back to where we were. */ ++ where = i_ehdrp->e_shoff + sizeof (x_shdr); ++ if (bfd_seek (abfd, (file_ptr) where, SEEK_SET) != 0) ++ goto got_no_match; ++ } + } + + /* Allocate space for a copy of the section header table in +@@ -690,6 +730,20 @@ elf_object_p (bfd *abfd) + goto got_no_match; + elf_swap_shdr_in (abfd, &x_shdr, i_shdrp + shindex); + ++ /* Sanity check sh_link and sh_info. */ ++ if (i_shdrp[shindex].sh_link >= num_sec ++ || (i_shdrp[shindex].sh_link >= SHN_LORESERVE ++ && i_shdrp[shindex].sh_link <= SHN_HIRESERVE)) ++ goto got_wrong_format_error; ++ ++ if (((i_shdrp[shindex].sh_flags & SHF_INFO_LINK) ++ || i_shdrp[shindex].sh_type == SHT_RELA ++ || i_shdrp[shindex].sh_type == SHT_REL) ++ && (i_shdrp[shindex].sh_info >= num_sec ++ || (i_shdrp[shindex].sh_info >= SHN_LORESERVE ++ && i_shdrp[shindex].sh_info <= SHN_HIRESERVE))) ++ goto got_wrong_format_error; ++ + /* If the section is loaded, but not page aligned, clear + D_PAGED. */ + if (i_shdrp[shindex].sh_size != 0 +@@ -708,6 +762,17 @@ elf_object_p (bfd *abfd) + goto got_no_match; + } + ++ /* A further sanity check. */ ++ if (i_ehdrp->e_shnum != 0) ++ { ++ if (i_ehdrp->e_shstrndx >= elf_numsections (abfd) ++ || (i_ehdrp->e_shstrndx >= SHN_LORESERVE ++ && i_ehdrp->e_shstrndx <= SHN_HIRESERVE)) ++ goto got_wrong_format_error; ++ } ++ else if (i_ehdrp->e_shstrndx != 0) ++ goto got_wrong_format_error; ++ + /* Read in the program headers. */ + if (i_ehdrp->e_phnum == 0) + elf_tdata (abfd)->phdr = NULL; +@@ -1071,7 +1136,7 @@ elf_slurp_symbol_table (bfd *abfd, asymb + symcount); + + /* Slurp in the symbols without the version information, +- since that is more helpful than just quitting. */ ++ since that is more helpful than just quitting. */ + verhdr = NULL; + } + +@@ -1138,7 +1203,7 @@ elf_slurp_symbol_table (bfd *abfd, asymb + sym->symbol.section = bfd_abs_section_ptr; + + /* If this is a relocatable file, then the symbol value is +- already section relative. */ ++ already section relative. */ + if ((abfd->flags & (EXEC_P | DYNAMIC)) != 0) + sym->symbol.value -= sym->symbol.section->vma; +