lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <CAPeXnHsn=VBExn0haFdxqbZT-j8fXROaVe0zVLqK9ooJmev2bQ@mail.gmail.com>
Date:	Tue, 12 May 2015 11:42:57 -0700
From:	Matthew Garrett <matthew.garrett@...eos.com>
To:	Ingo Molnar <mingo@...nel.org>
Cc:	Matthew Garrett <mjg59@...f.ucam.org>, x86@...nel.org,
	hpa@...or.com, mingo@...hat.com, tglx@...utronix.de,
	Linux Kernel Mailing List <linux-kernel@...r.kernel.org>,
	Matthew Garrett <mjg59@...eos.com>
Subject: Re: [PATCH V2] x86: Allow built-in command line to work in early
 kernel init

Ok, maybe something more like this? It even gets rid of some of the
#ifdefs in setup.c.

diff --git a/Documentation/x86/zero-page.txt b/Documentation/x86/zero-page.txt
index 82fbdbc..22eaecf 100644
--- a/Documentation/x86/zero-page.txt
+++ b/Documentation/x86/zero-page.txt
@@ -12,6 +12,7 @@ Offset    Proto    Name        Meaning
 000/040    ALL    screen_info    Text mode or frame buffer information
                 (struct screen_info)
 040/014    ALL    apm_bios_info    APM BIOS information (struct apm_bios_info)
+054/004    ALL    setup_flags    Flags passed from early kernel setup
 058/008    ALL    tboot_addr      Physical address of tboot shared page
 060/010    ALL    ist_info    Intel SpeedStep (IST) BIOS support information
                 (struct ist_info)
diff --git a/arch/x86/boot/boot.h b/arch/x86/boot/boot.h
index bd49ec6..3718244 100644
--- a/arch/x86/boot/boot.h
+++ b/arch/x86/boot/boot.h
@@ -273,6 +273,7 @@ void intcall(u8 int_no, const struct biosregs
*ireg, struct biosregs *oreg);
 /* cmdline.c */
 int __cmdline_find_option(unsigned long cmdline_ptr, const char
*option, char *buffer, int bufsize);
 int __cmdline_find_option_bool(unsigned long cmdline_ptr, const char *option);
+int __cmdline_init(unsigned long cmdline_ptr, struct boot_params *params);
 static inline int cmdline_find_option(const char *option, char
*buffer, int bufsize)
 {
     unsigned long cmd_line_ptr = boot_params.hdr.cmd_line_ptr;
@@ -293,6 +294,15 @@ static inline int cmdline_find_option_bool(const
char *option)
     return __cmdline_find_option_bool(cmd_line_ptr, option);
 }

+static inline int cmdline_init(void)
+{
+    unsigned long cmd_line_ptr = boot_params.hdr.cmd_line_ptr;
+
+    if (cmd_line_ptr >= 0x100000)
+        return -1;      /* inaccessible */
+
+    return __cmdline_init(cmd_line_ptr, &boot_params);
+}
 /* cpu.c, cpucheck.c */
 int check_cpu(int *cpu_level_ptr, int *req_level_ptr, u32 **err_flags_ptr);
 int validate_cpu(void);
diff --git a/arch/x86/boot/cmdline.c b/arch/x86/boot/cmdline.c
index 625d21b..9ddffd0 100644
--- a/arch/x86/boot/cmdline.c
+++ b/arch/x86/boot/cmdline.c
@@ -12,8 +12,15 @@
  * Simple command-line parser for early boot.
  */

+#include <asm/cmdline_append.h>
 #include "boot.h"

+#ifdef CONFIG_CMDLINE_BOOL
+static char builtin_cmdline[] = CONFIG_CMDLINE;
+#else
+static char *builtin_cmdline;
+#endif
+
 static inline int myisspace(u8 c)
 {
     return c <= ' ';    /* Close enough approximation */
@@ -156,3 +163,38 @@ int __cmdline_find_option_bool(unsigned long
cmdline_ptr, const char *option)

     return 0;    /* Buffer overrun */
 }
+
+int __cmdline_init(unsigned long cmdline_ptr, struct boot_params *params)
+{
+    addr_t cptr;
+    int i = 0;
+
+    if (!builtin_cmdline)
+        return 0;
+
+    if (!cmdline_ptr)
+        return -1;      /* No command line */
+
+    set_fs(cmdline_ptr >> 4);
+    cptr = cmdline_ptr & 0xf;
+
+    if (append_cmdline) {
+        while (cptr < 0x10000) {
+            char c = rdfs8(cptr);
+            if (!c) {
+                wrfs8(' ', cptr++);
+                break;
+            }
+            cptr++;
+        }
+    }
+
+    while (builtin_cmdline[i] && cptr < 0xffff)
+        wrfs8(builtin_cmdline[i++], cptr++);
+
+    wrfs8('\0', cptr);
+
+    params->setup_flags |= SETUP_CMDLINE_APPENDED;
+
+    return 0;
+}
diff --git a/arch/x86/boot/compressed/cmdline.c
b/arch/x86/boot/compressed/cmdline.c
index b68e303..4348828 100644
--- a/arch/x86/boot/compressed/cmdline.c
+++ b/arch/x86/boot/compressed/cmdline.c
@@ -1,6 +1,6 @@
 #include "misc.h"

-#if CONFIG_EARLY_PRINTK || CONFIG_RANDOMIZE_BASE
+#if CONFIG_EARLY_PRINTK || CONFIG_RANDOMIZE_BASE || CONFIG_CMDLINE_BOOL

 static unsigned long fs;
 static inline void set_fs(unsigned long seg)
@@ -12,6 +12,10 @@ static inline char rdfs8(addr_t addr)
 {
     return *((char *)(fs + addr));
 }
+static inline void wrfs8(u8 v, addr_t addr)
+{
+    *((char *)(fs + addr)) = v;
+}
 #include "../cmdline.c"
 static unsigned long get_cmd_line_ptr(void)
 {
@@ -30,4 +34,15 @@ int cmdline_find_option_bool(const char *option)
     return __cmdline_find_option_bool(get_cmd_line_ptr(), option);
 }

+int cmdline_init(void)
+{
+    if (!(real_mode->setup_flags & SETUP_CMDLINE_APPENDED))
+        return __cmdline_init(get_cmd_line_ptr(), real_mode);
+    return 0;
+}
+#else
+int cmdline_init(void)
+{
+    return 0;
+}
 #endif
diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c
index 48304b8..e44146d 100644
--- a/arch/x86/boot/compressed/eboot.c
+++ b/arch/x86/boot/compressed/eboot.c
@@ -9,6 +9,7 @@

 #include <linux/efi.h>
 #include <linux/pci.h>
+#include <asm/cmdline_append.h>
 #include <asm/efi.h>
 #include <asm/setup.h>
 #include <asm/desc.h>
@@ -1112,6 +1113,9 @@ struct boot_params *make_boot_params(struct efi_config *c)
     /* Fill in upper bits of command line address, NOP on 32 bit  */
     boot_params->ext_cmd_line_ptr = (u64)(unsigned long)cmdline_ptr >> 32;

+    if (append_cmdline)
+        boot_params->setup_flags |= SETUP_CMDLINE_APPENDED;
+
     hdr->ramdisk_image = 0;
     hdr->ramdisk_size = 0;

diff --git a/arch/x86/boot/compressed/misc.c b/arch/x86/boot/compressed/misc.c
index a107b93..832c9a8 100644
--- a/arch/x86/boot/compressed/misc.c
+++ b/arch/x86/boot/compressed/misc.c
@@ -393,6 +393,8 @@ asmlinkage __visible void *decompress_kernel(void
*rmode, memptr heap,
     lines = real_mode->screen_info.orig_video_lines;
     cols = real_mode->screen_info.orig_video_cols;

+    cmdline_init();
+
     console_init();
     debug_putstr("early console in decompress_kernel\n");

diff --git a/arch/x86/boot/compressed/misc.h b/arch/x86/boot/compressed/misc.h
index 89dd0d7..1584397 100644
--- a/arch/x86/boot/compressed/misc.h
+++ b/arch/x86/boot/compressed/misc.h
@@ -48,10 +48,11 @@ static inline void debug_putstr(const char *s)

 #endif

-#if CONFIG_EARLY_PRINTK || CONFIG_RANDOMIZE_BASE
+#if CONFIG_EARLY_PRINTK || CONFIG_RANDOMIZE_BASE || CONFIG_CMDLINE_BOOL
 /* cmdline.c */
 int cmdline_find_option(const char *option, char *buffer, int bufsize);
 int cmdline_find_option_bool(const char *option);
+int cmdline_init(void);
 #endif


diff --git a/arch/x86/boot/main.c b/arch/x86/boot/main.c
index fd6c9f2..7c24862 100644
--- a/arch/x86/boot/main.c
+++ b/arch/x86/boot/main.c
@@ -137,6 +137,9 @@ void main(void)
     /* First, copy the boot header into the "zeropage" */
     copy_boot_params();

+    /* Handle built-in command line */
+    cmdline_init();
+
     /* Initialize the early-boot console */
     console_init();
     if (cmdline_find_option_bool("debug"))
diff --git a/arch/x86/include/asm/cmdline_append.h
b/arch/x86/include/asm/cmdline_append.h
new file mode 100644
index 0000000..a57bf7e
--- /dev/null
+++ b/arch/x86/include/asm/cmdline_append.h
@@ -0,0 +1,10 @@
+#ifndef _ASM_X86_CMDLINE_APPEND_H
+#define _ASM_X86_CMDLINE_APPEND_H
+
+#ifdef CONFIG_CMDLINE_OVERRIDE
+static char append_cmdline;
+#else
+static char append_cmdline = 1;
+#endif
+
+#endif /* _ASM_X86_CMDLINE_APPEND_H */
diff --git a/arch/x86/include/uapi/asm/bootparam.h
b/arch/x86/include/uapi/asm/bootparam.h
index ab456dc..3fda079 100644
--- a/arch/x86/include/uapi/asm/bootparam.h
+++ b/arch/x86/include/uapi/asm/bootparam.h
@@ -27,6 +27,9 @@
 #define XLF_EFI_HANDOVER_64        (1<<3)
 #define XLF_EFI_KEXEC            (1<<4)

+/* setup_flags */
+#define SETUP_CMDLINE_APPENDED        (1<<0)
+
 #ifndef __ASSEMBLY__

 #include <linux/types.h>
@@ -114,7 +117,7 @@ struct efi_info {
 struct boot_params {
     struct screen_info screen_info;            /* 0x000 */
     struct apm_bios_info apm_bios_info;        /* 0x040 */
-    __u8  _pad2[4];                    /* 0x054 */
+    __u32 setup_flags;                /* 0x054 */
     __u64  tboot_addr;                /* 0x058 */
     struct ist_info ist_info;            /* 0x060 */
     __u8  _pad3[16];                /* 0x070 */
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
index d74ac33..4c6456d 100644
--- a/arch/x86/kernel/setup.c
+++ b/arch/x86/kernel/setup.c
@@ -112,6 +112,7 @@
 #include <asm/alternative.h>
 #include <asm/prom.h>

+#include <asm/cmdline_append.h>
 /*
  * max_low_pfn_mapped: highest direct mapped pfn under 4GB
  * max_pfn_mapped:     highest direct mapped pfn over 4GB
@@ -234,6 +235,8 @@ unsigned long saved_video_mode;
 static char __initdata command_line[COMMAND_LINE_SIZE];
 #ifdef CONFIG_CMDLINE_BOOL
 static char __initdata builtin_cmdline[COMMAND_LINE_SIZE] = CONFIG_CMDLINE;
+#else
+static char *builtin_cmdline;
 #endif

 #if defined(CONFIG_EDD) || defined(CONFIG_EDD_MODULE)
@@ -973,18 +976,21 @@ void __init setup_arch(char **cmdline_p)
     bss_resource.start = __pa_symbol(__bss_start);
     bss_resource.end = __pa_symbol(__bss_stop)-1;

-#ifdef CONFIG_CMDLINE_BOOL
-#ifdef CONFIG_CMDLINE_OVERRIDE
-    strlcpy(boot_command_line, builtin_cmdline, COMMAND_LINE_SIZE);
-#else
-    if (builtin_cmdline[0]) {
-        /* append boot loader cmdline to builtin */
-        strlcat(builtin_cmdline, " ", COMMAND_LINE_SIZE);
-        strlcat(builtin_cmdline, boot_command_line, COMMAND_LINE_SIZE);
-        strlcpy(boot_command_line, builtin_cmdline, COMMAND_LINE_SIZE);
+    if (builtin_cmdline) {
+        /* Fix up the command line if an earlier stage hasn't */
+        if (!(boot_params.setup_flags & SETUP_CMDLINE_APPENDED)) {
+            if (append_cmdline) {
+                /* append boot loader cmdline to builtin */
+                strlcat(builtin_cmdline, " ",
+                    COMMAND_LINE_SIZE);
+                strlcat(builtin_cmdline, boot_command_line,
+                    COMMAND_LINE_SIZE);
+            }
+
+            strlcpy(boot_command_line, builtin_cmdline,
+                    COMMAND_LINE_SIZE);
+        }
     }
-#endif
-#endif

     strlcpy(command_line, boot_command_line, COMMAND_LINE_SIZE);
     *cmdline_p = command_line;
diff --git a/drivers/firmware/efi/libstub/efi-stub-helper.c
b/drivers/firmware/efi/libstub/efi-stub-helper.c
index f07d4a6..743e4a5 100644
--- a/drivers/firmware/efi/libstub/efi-stub-helper.c
+++ b/drivers/firmware/efi/libstub/efi-stub-helper.c
@@ -12,9 +12,22 @@

 #include <linux/efi.h>
 #include <asm/efi.h>
+#include <asm/setup.h>

 #include "efistub.h"

+#ifdef CONFIG_CMDLINE_BOOL
+static char builtin_cmdline[] = CONFIG_CMDLINE;
+#else
+static char* builtin_cmdline;
+#endif
+
+#ifdef CONFIG_CMDLINE_OVERRIDE
+static bool append_cmdline;
+#else
+static bool append_cmdline = true;
+#endif
+
 /*
  * Some firmware implementations have problems reading files in one go.
  * A read chunk size of 1MB seems to work for most platforms.
@@ -649,6 +662,21 @@ static u8 *efi_utf16_to_utf8(u8 *dst, const u16
*src, int n)
     return dst;
 }

+static size_t efi_strlcat(char *dest, const char *src, size_t count)
+{
+    size_t dsize = strlen(dest);
+    size_t len = strlen(src);
+    size_t res = dsize + len;
+
+    dest += dsize;
+    count -= dsize;
+    if (len >= count)
+        len = count-1;
+    memcpy(dest, src, len);
+    dest[len] = 0;
+    return res;
+}
+
 /*
  * Convert the unicode UEFI command line to ASCII to pass to kernel.
  * Size of memory allocated return in *cmd_line_len.
@@ -658,42 +686,72 @@ char *efi_convert_cmdline(efi_system_table_t
*sys_table_arg,
               efi_loaded_image_t *image,
               int *cmd_line_len)
 {
+    unsigned long cmdline_addr = 0;
+    int i;
+    efi_status_t status;
     const u16 *s2;
     u8 *s1 = NULL;
-    unsigned long cmdline_addr = 0;
     int load_options_chars = image->load_options_size / 2; /* UTF-16 */
     const u16 *options = image->load_options;
     int options_bytes = 0;  /* UTF-8 bytes */
     int options_chars = 0;  /* UTF-16 chars */
-    efi_status_t status;
     u16 zero = 0;

-    if (options) {
-        s2 = options;
-        while (*s2 && *s2 != '\n'
-               && options_chars < load_options_chars) {
-            options_bytes += efi_utf8_bytes(*s2++);
-            options_chars++;
+    if (!builtin_cmdline || append_cmdline) {
+        if (options) {
+            s2 = options;
+            while (*s2 && *s2 != '\n'
+                   && options_chars < load_options_chars) {
+                options_bytes += efi_utf8_bytes(*s2++);
+                options_chars++;
+            }
+        }
+
+        if (!options_chars) {
+            /* No command line options, so return empty string*/
+            options = &zero;
         }
-    }

-    if (!options_chars) {
-        /* No command line options, so return empty string*/
-        options = &zero;
-    }
+        options_bytes++;    /* NUL termination */

-    options_bytes++;    /* NUL termination */
+        if (builtin_cmdline) {
+            /* Add length of the built-in command line + space */
+            options_bytes += strlen(builtin_cmdline);
+            options_bytes++;
+        }

-    status = efi_low_alloc(sys_table_arg, options_bytes, 0, &cmdline_addr);
-    if (status != EFI_SUCCESS)
-        return NULL;
+        status = efi_low_alloc(sys_table_arg, options_bytes, 0,
+                       &cmdline_addr);

-    s1 = (u8 *)cmdline_addr;
-    s2 = (const u16 *)options;
+        if (status != EFI_SUCCESS)
+            return NULL;

-    s1 = efi_utf16_to_utf8(s1, s2, options_chars);
-    *s1 = '\0';
+        s1 = (u8 *)cmdline_addr;
+        s2 = (const u16 *)options;
+
+        s1 = efi_utf16_to_utf8(s1, s2, options_chars);
+        *s1 = '\0';
+
+        if (builtin_cmdline) {
+            efi_strlcat((char *)cmdline_addr, " ",
+                    COMMAND_LINE_SIZE);
+            efi_strlcat((char *)cmdline_addr, builtin_cmdline,
+                    COMMAND_LINE_SIZE);
+        }
+        *cmd_line_len = options_bytes;
+    } else {
+        /* Ignore the provided command line, use the built-in one */
+        status = efi_low_alloc(sys_table_arg, strlen(builtin_cmdline),
+                       0, &cmdline_addr);
+        if (status != EFI_SUCCESS)
+            return NULL;
+        while (builtin_cmdline[i] && i < COMMAND_LINE_SIZE) {
+            ((char *)cmdline_addr)[i] = builtin_cmdline[i];
+            i++;
+        }
+        ((char *)cmdline_addr)[i] = '\0';
+        *cmd_line_len = strlen(builtin_cmdline);
+    }

-    *cmd_line_len = options_bytes;
     return (char *)cmdline_addr;
 }

-- 
Matthew Garrett | matthew.garrett@...eos.com
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ