[PATCH] fix symbol completion

Keith Owens kaos at sgi.com
Wed Sep 29 19:18:56 PDT 2004


On 29 Sep 2004 14:53:08 -0400, 
Jim Houston <jim.houston at comcast.net> 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.


More information about the kdb mailing list