[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: /init/main.c issue



On Mon, 2 Jan 2017, Sticky Chocolate wrote:
I found a issue with some functions in /init/main.c of the linux kernel.
They all involve the problem of the use of strcpy(I found that 3 functions
use strcpy) . I thought maby this could lead to buffer overflow. Im not
completely sure

Well, let's do a quick analysis...

__________________________________________________________________________________________________

main.c:ln 839,col 59
static void __init do_initcall_level(int level)
{
   initcall_t *fn;

   strcpy(initcall_command_line, saved_command_line);

initcall_command_line is defined as a static char * and saved_command_line is defined as a char *. At this point we don't know how much space is allocated for either of them, but I'll get back to this one line in a bit.

   parse_args(initcall_level_names[level],
          initcall_command_line, __start___param,
          __stop___param - __start___param,
          level, level,
          NULL, &repair_env_string);

   for (fn = initcall_levels[level]; fn < initcall_levels[level+1]; fn++)
       do_one_initcall(*fn);
}
__________________________________________________________________________________________________

line:ln 699,col 55

static int __init initcall_blacklist(char *str)
{
   char *str_entry;
   struct blacklist_entry *entry;

   /* str argument is a comma-separated list of functions */
   do {
       str_entry = strsep(&str, ",");
       if (str_entry) {
           pr_debug("blacklisting initcall %s\n", str_entry);
           entry = alloc_bootmem(sizeof(*entry));
           entry->buf = alloc_bootmem(strlen(str_entry) + 1);
           strcpy(entry->buf, str_entry);

First strlen(str_entry) + 1 bytes are allocated for entry->buf (in other words enough bytes for str_entry and the following '\0') and then str_entry is copied to entry->buf, which is obviously large enough since we just allocated enough bytes for str_entry and the '\0'. No problem here...

           list_add(&entry->next, &blacklisted_initcalls);
       }
   } while (str_entry);

   return 0;
}
____________________________________________________________________________________________________________________________________________________

line:ln 368,ln 369,col 55, col 51

static void __init setup_command_line(char *command_line)
{
   saved_command_line =
       memblock_virt_alloc(strlen(boot_command_line) + 1, 0);
   initcall_command_line =
       memblock_virt_alloc(strlen(boot_command_line) + 1, 0);
   static_command_line = memblock_virt_alloc(strlen(command_line) + 1, 0);
   strcpy(saved_command_line, boot_command_line);
   strcpy(static_command_line, command_line);

strlen(boot_command_line) + 1 bytes are allocated for saved_command_line and initcall_command_line. In other words, they are the same size. That will be important in a bit.

strlen(command_line) + 1 bytes are allocated for static_command_line.

boot_coomand_line is copied to saved_command_line, which we just allocated enough space for. No problem here...

command_line is copied to static_command_line. Again, we just allocated enough space for this. No problem here either...

Ok, back to saved_command_line, initcall_command_line and the first strcpy() you mentioned:

   strcpy(initcall_command_line, saved_command_line);

Since saved_command_line and initcall_command_line are the same size, a string that fits in saved_command_line will also fit in initcall_command_line, so no problem there either. (Unless one of them are reallocated at another point in the code. I haven't checked that.)

}


TL;DR: No problems as far as I can tell...

--
Povl Ole


Reply to: