On 29 Sep 2004 14:53:08 -0400, 
Jim Houston <[EMAIL PROTECTED]> wrote:
>Attached is a patch which will fix the kdb symbol completion
>problem I described yesterday.  It replaces most of the symbol
>table handling with the version from the port I did last fall.

Your patch hits 7 files

 Makefile               |    5
 include/linux/module.h |   14 +
 kdb/kdbsupport.c       |  350 +++++++++++++++++++------------------------------
 kernel/kallsyms.c      |   48 +++---
 kernel/module.c        |   28 +++
 scripts/kallsyms.c     |   29 ++--
 7 files changed, 229 insertions(+), 245 deletions(-)

Too intrusive into the rest of the kernel.  Smaller and less intrusive
(only changes kdb) patch below.

>I have not looked at the code yet to check for the buffer
>overflow you described.  As long as the buffers are larger
>than the longest symbol in the kernel/module symbol tables
>I would not expect a problem.

Overflow could occur with a long command line and tab completion.  I
added a paranoid maximum length parameter to avoid this.

 include/linux/kdbprivate.h |    2 -
 kdb/kdb_io.c               |    5 ++--
 kdb/kdbsupport.c           |   46 ++++++++++++++++++++++++++++++++++++---------
 3 files changed, 41 insertions(+), 12 deletions(-)

Index: linux/include/linux/kdbprivate.h
===================================================================
--- linux.orig/include/linux/kdbprivate.h       Wed Sep 29 16:54:05 2004
+++ linux/include/linux/kdbprivate.h    Thu Sep 30 11:43:23 2004
@@ -91,7 +91,7 @@ typedef struct __ksymtab {
                unsigned long sym_end;
                } kdb_symtab_t;
 extern int kallsyms_symbol_next(char *prefix_name, int flag);
-extern int kallsyms_symbol_complete(char *prefix_name);
+extern int kallsyms_symbol_complete(char *prefix_name, int max_len);
 
        /*
         * Exported Symbols for kernel loadable modules to use.
Index: linux/kdb/kdb_io.c
===================================================================
--- linux.orig/kdb/kdb_io.c     Wed Sep 29 16:54:05 2004
+++ linux/kdb/kdb_io.c  Thu Sep 30 11:47:44 2004
@@ -316,8 +316,9 @@ kdb_read(char *buffer, size_t bufsize)
                                else
                                        p_tmp = tmpbuffer;
                                len = strlen(p_tmp);
+                               count = kallsyms_symbol_complete(p_tmp, 
sizeof(tmpbuffer) - (p_tmp - tmpbuffer));
                                if (tab == 2) {
-                                       if((count=kallsyms_symbol_complete(p_tmp))>0) {
+                                       if (count > 0) {
                                                kdb_printf("\n%d symbols are found.", 
count);
                                                if(count>dtab_count) {
                                                        count=dtab_count;
@@ -337,7 +338,7 @@ kdb_read(char *buffer, size_t bufsize)
                                        }
                                }
                                else {
-                                       if(kallsyms_symbol_complete(p_tmp)>0) {
+                                       if (count > 0) {
                                                len_tmp = strlen(p_tmp);
                                                strncpy(p_tmp+len_tmp,cp, 
lastchar-cp+1);
                                                len_tmp = strlen(p_tmp);
Index: linux/kdb/kdbsupport.c
===================================================================
--- linux.orig/kdb/kdbsupport.c Wed Sep 29 16:54:05 2004
+++ linux/kdb/kdbsupport.c      Thu Sep 30 12:11:30 2004
@@ -199,26 +199,52 @@ kdbnearsym(unsigned long addr, kdb_symta
  *
  * Parameters:
  *     prefix_name     prefix of a symbol name to lookup
+ *     max_len         maximum length that can be returned
  * Returns:
  *     Number of symbols which match the given prefix.
+ * Notes:
+ *     prefix_name is changed to contain the longest unique prefix that
+ *     starts with this prefix (tab completion).
  */
 
-int kallsyms_symbol_complete(char *prefix_name)
+static char ks_namebuf[128], ks_namebuf_prev[128];
+
+static void
+ksc_maximum(int number, int max_len, int *prev_len)
+{
+       /* Work out the longest name that matches the prefix */
+       int i;
+       if (number == 1) {
+               *prev_len = min_t(int, max_len-1, strlen(ks_namebuf));
+               memcpy(ks_namebuf_prev, ks_namebuf, *prev_len);
+               ks_namebuf_prev[*prev_len] = '\0';
+               return;
+       }
+       for (i = 0; i < *prev_len; ++i) {
+               if (ks_namebuf[i] != ks_namebuf_prev[i]) {
+                       *prev_len = i;
+                       ks_namebuf_prev[i] = '\0';
+                       break;
+               }
+       }
+}
+
+int kallsyms_symbol_complete(char *prefix_name, int max_len)
 {
        char *name = kallsyms_names;
        int i;
-       char namebuf[128];
-       int prefix_len = strlen(prefix_name);
+       int prefix_len = strlen(prefix_name), prev_len = 0;
        int number = 0;
 
        /* look into kernel symbols */
 
        for (i=0; i < kallsyms_num_syms; i++) {
                unsigned prefix = *name++;
-               strncpy(namebuf + prefix, name, 127 - prefix);
-               if (strncmp(namebuf, prefix_name, prefix_len) == 0) {
+               strncpy(ks_namebuf + prefix, name, 127 - prefix);
+               if (strncmp(ks_namebuf, prefix_name, prefix_len) == 0) {
                        /* found */
                        ++number;
+                       ksc_maximum(number, max_len, &prev_len);
                }
                name += strlen(name) + 1;
        }
@@ -234,11 +260,14 @@ int kallsyms_symbol_complete(char *prefi
                        if (strncmp(name, prefix_name, prefix_len) == 0) {
                                /* found */
                                ++number;
+                               ksc_maximum(number, max_len, &prev_len);
                        }
                }
        }
  }
 #endif /* CONFIG_MODULES */
+       if (prev_len > prefix_len)
+               memcpy(prefix_name, ks_namebuf_prev, prev_len+1);
        return number;
 }
 
@@ -256,7 +285,6 @@ int kallsyms_symbol_complete(char *prefi
 int kallsyms_symbol_next(char *prefix_name, int flag)
 {
        int prefix_len = strlen(prefix_name);
-       char namebuf[128];
        static int i;
        static char *name;
        static struct module *mod;
@@ -276,10 +304,10 @@ int kallsyms_symbol_next(char *prefix_na
                /* look into kernel symbols */
                for (; i < kallsyms_num_syms; i++) {
                        unsigned prefix = *name++;
-                       strncpy(namebuf + prefix, name, 127 - prefix);
-                       if (strncmp(namebuf, prefix_name, prefix_len) == 0) {
+                       strncpy(ks_namebuf + prefix, name, 127 - prefix);
+                       if (strncmp(ks_namebuf, prefix_name, prefix_len) == 0) {
                                /* found */
-                               strncpy(prefix_name, namebuf, strlen(namebuf)+1);
+                               strncpy(prefix_name, ks_namebuf, strlen(ks_namebuf)+1);
                                return(1);
                        }
                        name += strlen(name) + 1;

---------------------------
Use http://oss.sgi.com/ecartis to modify your settings or to unsubscribe.

Reply via email to