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.