Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'trace-v5.6-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace

Pull tracing and bootconfig updates:
"Fixes and changes to bootconfig before it goes live in a release.

Change in API of bootconfig (before it comes live in a release):
- Have a magic value "BOOTCONFIG" in initrd to know a bootconfig
exists
- Set CONFIG_BOOT_CONFIG to 'n' by default
- Show error if "bootconfig" on cmdline but not compiled in
- Prevent redefining the same value
- Have a way to append values
- Added a SELECT BLK_DEV_INITRD to fix a build failure

Synthetic event fixes:
- Switch to raw_smp_processor_id() for recording CPU value in preempt
section. (No care for what the value actually is)
- Fix samples always recording u64 values
- Fix endianess
- Check number of values matches number of fields
- Fix a printing bug

Fix of trace_printk() breaking postponed start up tests

Make a function static that is only used in a single file"

* tag 'trace-v5.6-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace:
bootconfig: Fix CONFIG_BOOTTIME_TRACING dependency issue
bootconfig: Add append value operator support
bootconfig: Prohibit re-defining value on same key
bootconfig: Print array as multiple commands for legacy command line
bootconfig: Reject subkey and value on same parent key
tools/bootconfig: Remove unneeded error message silencer
bootconfig: Add bootconfig magic word for indicating bootconfig explicitly
bootconfig: Set CONFIG_BOOT_CONFIG=n by default
tracing: Clear trace_state when starting trace
bootconfig: Mark boot_config_checksum() static
tracing: Disable trace_printk() on post poned tests
tracing: Have synthetic event test use raw_smp_processor_id()
tracing: Fix number printing bug in print_synth_event()
tracing: Check that number of vals matches number of synth event fields
tracing: Make synth_event trace functions endian-correct
tracing: Make sure synth_event_trace() example always uses u64

+274 -94
+31 -3
Documentation/admin-guide/bootconfig.rst
··· 62 62 In both styles, same key words are automatically merged when parsing it 63 63 at boot time. So you can append similar trees or key-values. 64 64 65 + Same-key Values 66 + --------------- 67 + 68 + It is prohibited that two or more values or arrays share a same-key. 69 + For example,:: 70 + 71 + foo = bar, baz 72 + foo = qux # !ERROR! we can not re-define same key 73 + 74 + If you want to append the value to existing key as an array member, 75 + you can use ``+=`` operator. For example:: 76 + 77 + foo = bar, baz 78 + foo += qux 79 + 80 + In this case, the key ``foo`` has ``bar``, ``baz`` and ``qux``. 81 + 82 + However, a sub-key and a value can not co-exist under a parent key. 83 + For example, following config is NOT allowed.:: 84 + 85 + foo = value1 86 + foo.bar = value2 # !ERROR! subkey "bar" and value "value1" can NOT co-exist 87 + 88 + 65 89 Comments 66 90 -------- 67 91 ··· 126 102 ============================== 127 103 128 104 Since the boot configuration file is loaded with initrd, it will be added 129 - to the end of the initrd (initramfs) image file. The Linux kernel decodes 130 - the last part of the initrd image in memory to get the boot configuration 131 - data. 105 + to the end of the initrd (initramfs) image file with size, checksum and 106 + 12-byte magic word as below. 107 + 108 + [initrd][bootconfig][size(u32)][checksum(u32)][#BOOTCONFIG\n] 109 + 110 + The Linux kernel decodes the last part of the initrd image in memory to 111 + get the boot configuration data. 132 112 Because of this "piggyback" method, there is no need to change or 133 113 update the boot loader and the kernel image itself. 134 114
+3
include/linux/bootconfig.h
··· 10 10 #include <linux/kernel.h> 11 11 #include <linux/types.h> 12 12 13 + #define BOOTCONFIG_MAGIC "#BOOTCONFIG\n" 14 + #define BOOTCONFIG_MAGIC_LEN 12 15 + 13 16 /* XBC tree node */ 14 17 struct xbc_node { 15 18 u16 next;
+2 -3
init/Kconfig
··· 1226 1226 1227 1227 config BOOT_CONFIG 1228 1228 bool "Boot config support" 1229 - depends on BLK_DEV_INITRD 1230 - default y 1229 + select BLK_DEV_INITRD 1231 1230 help 1232 1231 Extra boot config allows system admin to pass a config file as 1233 1232 complemental extension of kernel cmdline when booting. 1234 1233 The boot config file must be attached at the end of initramfs 1235 - with checksum and size. 1234 + with checksum, size and magic word. 1236 1235 See <file:Documentation/admin-guide/bootconfig.rst> for details. 1237 1236 1238 1237 If unsure, say Y.
+24 -18
init/main.c
··· 268 268 { 269 269 struct xbc_node *knode, *vnode; 270 270 char *end = buf + size; 271 - char c = '\"'; 272 271 const char *val; 273 272 int ret; 274 273 ··· 278 279 return ret; 279 280 280 281 vnode = xbc_node_get_child(knode); 281 - ret = snprintf(buf, rest(buf, end), "%s%c", xbc_namebuf, 282 - vnode ? '=' : ' '); 283 - if (ret < 0) 284 - return ret; 285 - buf += ret; 286 - if (!vnode) 287 - continue; 288 - 289 - c = '\"'; 290 - xbc_array_for_each_value(vnode, val) { 291 - ret = snprintf(buf, rest(buf, end), "%c%s", c, val); 282 + if (!vnode) { 283 + ret = snprintf(buf, rest(buf, end), "%s ", xbc_namebuf); 292 284 if (ret < 0) 293 285 return ret; 294 286 buf += ret; 295 - c = ','; 287 + continue; 296 288 } 297 - if (rest(buf, end) > 2) 298 - strcpy(buf, "\" "); 299 - buf += 2; 289 + xbc_array_for_each_value(vnode, val) { 290 + ret = snprintf(buf, rest(buf, end), "%s=\"%s\" ", 291 + xbc_namebuf, val); 292 + if (ret < 0) 293 + return ret; 294 + buf += ret; 295 + } 300 296 } 301 297 302 298 return buf - (end - size); ··· 329 335 return new_cmdline; 330 336 } 331 337 332 - u32 boot_config_checksum(unsigned char *p, u32 size) 338 + static u32 boot_config_checksum(unsigned char *p, u32 size) 333 339 { 334 340 u32 ret = 0; 335 341 ··· 368 374 if (!initrd_end) 369 375 goto not_found; 370 376 371 - hdr = (u32 *)(initrd_end - 8); 377 + data = (char *)initrd_end - BOOTCONFIG_MAGIC_LEN; 378 + if (memcmp(data, BOOTCONFIG_MAGIC, BOOTCONFIG_MAGIC_LEN)) 379 + goto not_found; 380 + 381 + hdr = (u32 *)(data - 8); 372 382 size = hdr[0]; 373 383 csum = hdr[1]; 374 384 ··· 416 418 } 417 419 #else 418 420 #define setup_boot_config(cmdline) do { } while (0) 421 + 422 + static int __init warn_bootconfig(char *str) 423 + { 424 + pr_warn("WARNING: 'bootconfig' found on the kernel command line but CONFIG_BOOTCONFIG is not set.\n"); 425 + return 0; 426 + } 427 + early_param("bootconfig", warn_bootconfig); 428 + 419 429 #endif 420 430 421 431 /* Change NUL term back to "=", to make "param" the whole string. */
+2 -2
kernel/trace/Kconfig
··· 143 143 144 144 config BOOTTIME_TRACING 145 145 bool "Boot-time Tracing support" 146 - depends on BOOT_CONFIG && TRACING 147 - default y 146 + depends on TRACING 147 + select BOOT_CONFIG 148 148 help 149 149 Enable developer to setup ftrace subsystem via supplemental 150 150 kernel cmdline at boot time for debugging (tracing) driver
+22 -22
kernel/trace/synth_event_gen_test.c
··· 111 111 /* Create some bogus values just for testing */ 112 112 113 113 vals[0] = 777; /* next_pid_field */ 114 - vals[1] = (u64)"hula hoops"; /* next_comm_field */ 114 + vals[1] = (u64)(long)"hula hoops"; /* next_comm_field */ 115 115 vals[2] = 1000000; /* ts_ns */ 116 116 vals[3] = 1000; /* ts_ms */ 117 - vals[4] = smp_processor_id(); /* cpu */ 118 - vals[5] = (u64)"thneed"; /* my_string_field */ 117 + vals[4] = raw_smp_processor_id(); /* cpu */ 118 + vals[5] = (u64)(long)"thneed"; /* my_string_field */ 119 119 vals[6] = 598; /* my_int_field */ 120 120 121 121 /* Now generate a gen_synth_test event */ ··· 218 218 /* Create some bogus values just for testing */ 219 219 220 220 vals[0] = 777; /* next_pid_field */ 221 - vals[1] = (u64)"tiddlywinks"; /* next_comm_field */ 221 + vals[1] = (u64)(long)"tiddlywinks"; /* next_comm_field */ 222 222 vals[2] = 1000000; /* ts_ns */ 223 223 vals[3] = 1000; /* ts_ms */ 224 - vals[4] = smp_processor_id(); /* cpu */ 225 - vals[5] = (u64)"thneed_2.0"; /* my_string_field */ 224 + vals[4] = raw_smp_processor_id(); /* cpu */ 225 + vals[5] = (u64)(long)"thneed_2.0"; /* my_string_field */ 226 226 vals[6] = 399; /* my_int_field */ 227 227 228 228 /* Now trace an empty_synth_test event */ ··· 290 290 /* Create some bogus values just for testing */ 291 291 292 292 vals[0] = 777; /* next_pid_field */ 293 - vals[1] = (u64)"tiddlywinks"; /* next_comm_field */ 293 + vals[1] = (u64)(long)"tiddlywinks"; /* next_comm_field */ 294 294 vals[2] = 1000000; /* ts_ns */ 295 295 vals[3] = 1000; /* ts_ms */ 296 - vals[4] = smp_processor_id(); /* cpu */ 297 - vals[5] = (u64)"thneed"; /* my_string_field */ 296 + vals[4] = raw_smp_processor_id(); /* cpu */ 297 + vals[5] = (u64)(long)"thneed"; /* my_string_field */ 298 298 vals[6] = 398; /* my_int_field */ 299 299 300 300 /* Now generate a create_synth_test event */ ··· 330 330 goto out; 331 331 332 332 /* next_comm_field */ 333 - ret = synth_event_add_next_val((u64)"slinky", &trace_state); 333 + ret = synth_event_add_next_val((u64)(long)"slinky", &trace_state); 334 334 if (ret) 335 335 goto out; 336 336 ··· 345 345 goto out; 346 346 347 347 /* cpu */ 348 - ret = synth_event_add_next_val(smp_processor_id(), &trace_state); 348 + ret = synth_event_add_next_val(raw_smp_processor_id(), &trace_state); 349 349 if (ret) 350 350 goto out; 351 351 352 352 /* my_string_field */ 353 - ret = synth_event_add_next_val((u64)"thneed_2.01", &trace_state); 353 + ret = synth_event_add_next_val((u64)(long)"thneed_2.01", &trace_state); 354 354 if (ret) 355 355 goto out; 356 356 ··· 388 388 if (ret) 389 389 goto out; 390 390 391 - ret = synth_event_add_val("cpu", smp_processor_id(), &trace_state); 391 + ret = synth_event_add_val("cpu", raw_smp_processor_id(), &trace_state); 392 392 if (ret) 393 393 goto out; 394 394 ··· 396 396 if (ret) 397 397 goto out; 398 398 399 - ret = synth_event_add_val("next_comm_field", (u64)"silly putty", 399 + ret = synth_event_add_val("next_comm_field", (u64)(long)"silly putty", 400 400 &trace_state); 401 401 if (ret) 402 402 goto out; 403 403 404 - ret = synth_event_add_val("my_string_field", (u64)"thneed_9", 404 + ret = synth_event_add_val("my_string_field", (u64)(long)"thneed_9", 405 405 &trace_state); 406 406 if (ret) 407 407 goto out; ··· 423 423 424 424 /* Trace some bogus values just for testing */ 425 425 ret = synth_event_trace(create_synth_test, 7, /* number of values */ 426 - 444, /* next_pid_field */ 427 - (u64)"clackers", /* next_comm_field */ 428 - 1000000, /* ts_ns */ 429 - 1000, /* ts_ms */ 430 - smp_processor_id(), /* cpu */ 431 - (u64)"Thneed", /* my_string_field */ 432 - 999); /* my_int_field */ 426 + (u64)444, /* next_pid_field */ 427 + (u64)(long)"clackers", /* next_comm_field */ 428 + (u64)1000000, /* ts_ns */ 429 + (u64)1000, /* ts_ms */ 430 + (u64)raw_smp_processor_id(), /* cpu */ 431 + (u64)(long)"Thneed", /* my_string_field */ 432 + (u64)999); /* my_int_field */ 433 433 return ret; 434 434 } 435 435
+2
kernel/trace/trace.c
··· 1837 1837 1838 1838 pr_info("Running postponed tracer tests:\n"); 1839 1839 1840 + tracing_selftest_running = true; 1840 1841 list_for_each_entry_safe(p, n, &postponed_selftests, list) { 1841 1842 /* This loop can take minutes when sanitizers are enabled, so 1842 1843 * lets make sure we allow RCU processing. ··· 1860 1859 list_del(&p->list); 1861 1860 kfree(p); 1862 1861 } 1862 + tracing_selftest_running = false; 1863 1863 1864 1864 out: 1865 1865 mutex_unlock(&trace_types_lock);
+101 -11
kernel/trace/trace_events_hist.c
··· 821 821 return fmt; 822 822 } 823 823 824 + static void print_synth_event_num_val(struct trace_seq *s, 825 + char *print_fmt, char *name, 826 + int size, u64 val, char *space) 827 + { 828 + switch (size) { 829 + case 1: 830 + trace_seq_printf(s, print_fmt, name, (u8)val, space); 831 + break; 832 + 833 + case 2: 834 + trace_seq_printf(s, print_fmt, name, (u16)val, space); 835 + break; 836 + 837 + case 4: 838 + trace_seq_printf(s, print_fmt, name, (u32)val, space); 839 + break; 840 + 841 + default: 842 + trace_seq_printf(s, print_fmt, name, val, space); 843 + break; 844 + } 845 + } 846 + 824 847 static enum print_line_t print_synth_event(struct trace_iterator *iter, 825 848 int flags, 826 849 struct trace_event *event) ··· 882 859 } else { 883 860 struct trace_print_flags __flags[] = { 884 861 __def_gfpflag_names, {-1, NULL} }; 862 + char *space = (i == se->n_fields - 1 ? "" : " "); 885 863 886 - trace_seq_printf(s, print_fmt, se->fields[i]->name, 887 - entry->fields[n_u64], 888 - i == se->n_fields - 1 ? "" : " "); 864 + print_synth_event_num_val(s, print_fmt, 865 + se->fields[i]->name, 866 + se->fields[i]->size, 867 + entry->fields[n_u64], 868 + space); 889 869 890 870 if (strcmp(se->fields[i]->type, "gfp_t") == 0) { 891 871 trace_seq_puts(s, " ("); ··· 1831 1805 int entry_size, fields_size = 0; 1832 1806 int ret = 0; 1833 1807 1808 + memset(trace_state, '\0', sizeof(*trace_state)); 1809 + 1834 1810 /* 1835 1811 * Normal event tracing doesn't get called at all unless the 1836 1812 * ENABLED bit is set (which attaches the probe thus allowing ··· 1913 1885 return ret; 1914 1886 } 1915 1887 1888 + if (n_vals != state.event->n_fields) { 1889 + ret = -EINVAL; 1890 + goto out; 1891 + } 1892 + 1916 1893 va_start(args, n_vals); 1917 1894 for (i = 0, n_u64 = 0; i < state.event->n_fields; i++) { 1918 1895 u64 val; ··· 1931 1898 strscpy(str_field, str_val, STR_VAR_LEN_MAX); 1932 1899 n_u64 += STR_VAR_LEN_MAX / sizeof(u64); 1933 1900 } else { 1934 - state.entry->fields[n_u64] = val; 1901 + struct synth_field *field = state.event->fields[i]; 1902 + 1903 + switch (field->size) { 1904 + case 1: 1905 + *(u8 *)&state.entry->fields[n_u64] = (u8)val; 1906 + break; 1907 + 1908 + case 2: 1909 + *(u16 *)&state.entry->fields[n_u64] = (u16)val; 1910 + break; 1911 + 1912 + case 4: 1913 + *(u32 *)&state.entry->fields[n_u64] = (u32)val; 1914 + break; 1915 + 1916 + default: 1917 + state.entry->fields[n_u64] = val; 1918 + break; 1919 + } 1935 1920 n_u64++; 1936 1921 } 1937 1922 } 1938 1923 va_end(args); 1939 - 1924 + out: 1940 1925 __synth_event_trace_end(&state); 1941 1926 1942 1927 return ret; ··· 1993 1942 return ret; 1994 1943 } 1995 1944 1945 + if (n_vals != state.event->n_fields) { 1946 + ret = -EINVAL; 1947 + goto out; 1948 + } 1949 + 1996 1950 for (i = 0, n_u64 = 0; i < state.event->n_fields; i++) { 1997 1951 if (state.event->fields[i]->is_string) { 1998 1952 char *str_val = (char *)(long)vals[i]; ··· 2006 1950 strscpy(str_field, str_val, STR_VAR_LEN_MAX); 2007 1951 n_u64 += STR_VAR_LEN_MAX / sizeof(u64); 2008 1952 } else { 2009 - state.entry->fields[n_u64] = vals[i]; 1953 + struct synth_field *field = state.event->fields[i]; 1954 + u64 val = vals[i]; 1955 + 1956 + switch (field->size) { 1957 + case 1: 1958 + *(u8 *)&state.entry->fields[n_u64] = (u8)val; 1959 + break; 1960 + 1961 + case 2: 1962 + *(u16 *)&state.entry->fields[n_u64] = (u16)val; 1963 + break; 1964 + 1965 + case 4: 1966 + *(u32 *)&state.entry->fields[n_u64] = (u32)val; 1967 + break; 1968 + 1969 + default: 1970 + state.entry->fields[n_u64] = val; 1971 + break; 1972 + } 2010 1973 n_u64++; 2011 1974 } 2012 1975 } 2013 - 1976 + out: 2014 1977 __synth_event_trace_end(&state); 2015 1978 2016 1979 return ret; ··· 2071 1996 2072 1997 if (!trace_state) 2073 1998 return -EINVAL; 2074 - 2075 - memset(trace_state, '\0', sizeof(*trace_state)); 2076 1999 2077 2000 ret = __synth_event_trace_start(file, trace_state); 2078 2001 if (ret == -ENOENT) ··· 2142 2069 2143 2070 str_field = (char *)&entry->fields[field->offset]; 2144 2071 strscpy(str_field, str_val, STR_VAR_LEN_MAX); 2145 - } else 2146 - entry->fields[field->offset] = val; 2072 + } else { 2073 + switch (field->size) { 2074 + case 1: 2075 + *(u8 *)&trace_state->entry->fields[field->offset] = (u8)val; 2076 + break; 2077 + 2078 + case 2: 2079 + *(u16 *)&trace_state->entry->fields[field->offset] = (u16)val; 2080 + break; 2081 + 2082 + case 4: 2083 + *(u32 *)&trace_state->entry->fields[field->offset] = (u32)val; 2084 + break; 2085 + 2086 + default: 2087 + trace_state->entry->fields[field->offset] = val; 2088 + break; 2089 + } 2090 + } 2147 2091 out: 2148 2092 return ret; 2149 2093 }
+27 -9
lib/bootconfig.c
··· 533 533 534 534 static int __init __xbc_add_key(char *k) 535 535 { 536 - struct xbc_node *node; 536 + struct xbc_node *node, *child; 537 537 538 538 if (!xbc_valid_keyword(k)) 539 539 return xbc_parse_error("Invalid keyword", k); ··· 543 543 544 544 if (!last_parent) /* the first level */ 545 545 node = find_match_node(xbc_nodes, k); 546 - else 547 - node = find_match_node(xbc_node_get_child(last_parent), k); 546 + else { 547 + child = xbc_node_get_child(last_parent); 548 + if (child && xbc_node_is_value(child)) 549 + return xbc_parse_error("Subkey is mixed with value", k); 550 + node = find_match_node(child, k); 551 + } 548 552 549 553 if (node) 550 554 last_parent = node; ··· 578 574 return __xbc_add_key(k); 579 575 } 580 576 581 - static int __init xbc_parse_kv(char **k, char *v) 577 + static int __init xbc_parse_kv(char **k, char *v, int op) 582 578 { 583 579 struct xbc_node *prev_parent = last_parent; 584 - struct xbc_node *node; 580 + struct xbc_node *child; 585 581 char *next; 586 582 int c, ret; 587 583 ··· 589 585 if (ret) 590 586 return ret; 591 587 588 + child = xbc_node_get_child(last_parent); 589 + if (child) { 590 + if (xbc_node_is_key(child)) 591 + return xbc_parse_error("Value is mixed with subkey", v); 592 + else if (op == '=') 593 + return xbc_parse_error("Value is redefined", v); 594 + } 595 + 592 596 c = __xbc_parse_value(&v, &next); 593 597 if (c < 0) 594 598 return c; 595 599 596 - node = xbc_add_sibling(v, XBC_VALUE); 597 - if (!node) 600 + if (!xbc_add_sibling(v, XBC_VALUE)) 598 601 return -ENOMEM; 599 602 600 603 if (c == ',') { /* Array */ ··· 774 763 775 764 p = buf; 776 765 do { 777 - q = strpbrk(p, "{}=;\n#"); 766 + q = strpbrk(p, "{}=+;\n#"); 778 767 if (!q) { 779 768 p = skip_spaces(p); 780 769 if (*p != '\0') ··· 785 774 c = *q; 786 775 *q++ = '\0'; 787 776 switch (c) { 777 + case '+': 778 + if (*q++ != '=') { 779 + ret = xbc_parse_error("Wrong '+' operator", 780 + q - 2); 781 + break; 782 + } 783 + /* Fall through */ 788 784 case '=': 789 - ret = xbc_parse_kv(&p, q); 785 + ret = xbc_parse_kv(&p, q, c); 790 786 break; 791 787 case '{': 792 788 ret = xbc_open_brace(&p, q);
+1 -4
tools/bootconfig/include/linux/printk.h
··· 4 4 5 5 #include <stdio.h> 6 6 7 - /* controllable printf */ 8 - extern int pr_output; 9 - #define printk(fmt, ...) \ 10 - (pr_output ? printf(fmt, ##__VA_ARGS__) : 0) 7 + #define printk(fmt, ...) printf(fmt, ##__VA_ARGS__) 11 8 12 9 #define pr_err printk 13 10 #define pr_warn printk
+32 -19
tools/bootconfig/main.c
··· 14 14 #include <linux/kernel.h> 15 15 #include <linux/bootconfig.h> 16 16 17 - int pr_output = 1; 18 - 19 17 static int xbc_show_array(struct xbc_node *node) 20 18 { 21 19 const char *val; ··· 129 131 struct stat stat; 130 132 int ret; 131 133 u32 size = 0, csum = 0, rcsum; 134 + char magic[BOOTCONFIG_MAGIC_LEN]; 132 135 133 136 ret = fstat(fd, &stat); 134 137 if (ret < 0) 135 138 return -errno; 136 139 137 - if (stat.st_size < 8) 140 + if (stat.st_size < 8 + BOOTCONFIG_MAGIC_LEN) 138 141 return 0; 139 142 140 - if (lseek(fd, -8, SEEK_END) < 0) { 143 + if (lseek(fd, -BOOTCONFIG_MAGIC_LEN, SEEK_END) < 0) { 144 + pr_err("Failed to lseek: %d\n", -errno); 145 + return -errno; 146 + } 147 + if (read(fd, magic, BOOTCONFIG_MAGIC_LEN) < 0) 148 + return -errno; 149 + /* Check the bootconfig magic bytes */ 150 + if (memcmp(magic, BOOTCONFIG_MAGIC, BOOTCONFIG_MAGIC_LEN) != 0) 151 + return 0; 152 + 153 + if (lseek(fd, -(8 + BOOTCONFIG_MAGIC_LEN), SEEK_END) < 0) { 141 154 pr_err("Failed to lseek: %d\n", -errno); 142 155 return -errno; 143 156 } ··· 159 150 if (read(fd, &csum, sizeof(u32)) < 0) 160 151 return -errno; 161 152 162 - /* Wrong size, maybe no boot config here */ 163 - if (stat.st_size < size + 8) 164 - return 0; 153 + /* Wrong size error */ 154 + if (stat.st_size < size + 8 + BOOTCONFIG_MAGIC_LEN) { 155 + pr_err("bootconfig size is too big\n"); 156 + return -E2BIG; 157 + } 165 158 166 - if (lseek(fd, stat.st_size - 8 - size, SEEK_SET) < 0) { 159 + if (lseek(fd, stat.st_size - (size + 8 + BOOTCONFIG_MAGIC_LEN), 160 + SEEK_SET) < 0) { 167 161 pr_err("Failed to lseek: %d\n", -errno); 168 162 return -errno; 169 163 } ··· 175 163 if (ret < 0) 176 164 return ret; 177 165 178 - /* Wrong Checksum, maybe no boot config here */ 166 + /* Wrong Checksum */ 179 167 rcsum = checksum((unsigned char *)*buf, size); 180 168 if (csum != rcsum) { 181 169 pr_err("checksum error: %d != %d\n", csum, rcsum); 182 - return 0; 170 + return -EINVAL; 183 171 } 184 172 185 173 ret = xbc_init(*buf); 186 - /* Wrong data, maybe no boot config here */ 174 + /* Wrong data */ 187 175 if (ret < 0) 188 - return 0; 176 + return ret; 189 177 190 178 return size; 191 179 } ··· 225 213 return -errno; 226 214 } 227 215 228 - /* 229 - * Suppress error messages in xbc_init() because it can be just a 230 - * data which concidentally matches the size and checksum footer. 231 - */ 232 - pr_output = 0; 233 216 size = load_xbc_from_initrd(fd, &buf); 234 - pr_output = 1; 235 217 if (size < 0) { 236 218 ret = size; 237 219 pr_err("Failed to load a boot config from initrd: %d\n", ret); 238 220 } else if (size > 0) { 239 221 ret = fstat(fd, &stat); 240 222 if (!ret) 241 - ret = ftruncate(fd, stat.st_size - size - 8); 223 + ret = ftruncate(fd, stat.st_size 224 + - size - 8 - BOOTCONFIG_MAGIC_LEN); 242 225 if (ret) 243 226 ret = -errno; 244 227 } /* Ignore if there is no boot config in initrd */ ··· 300 293 ret = write(fd, data, size + 8); 301 294 if (ret < 0) { 302 295 pr_err("Failed to apply a boot config: %d\n", ret); 296 + return ret; 297 + } 298 + /* Write a magic word of the bootconfig */ 299 + ret = write(fd, BOOTCONFIG_MAGIC, BOOTCONFIG_MAGIC_LEN); 300 + if (ret < 0) { 301 + pr_err("Failed to apply a boot config magic: %d\n", ret); 303 302 return ret; 304 303 } 305 304 close(fd);
+3
tools/bootconfig/samples/bad-mixed-kv1.bconf
··· 1 + # value -> subkey pattern 2 + key = value 3 + key.subkey = another-value
+3
tools/bootconfig/samples/bad-mixed-kv2.bconf
··· 1 + # subkey -> value pattern 2 + key.subkey = value 3 + key = another-value
+6
tools/bootconfig/samples/bad-samekey.bconf
··· 1 + # Same key value is not allowed 2 + key { 3 + foo = value 4 + bar = value2 5 + } 6 + key.foo = value
+15 -3
tools/bootconfig/test-bootconfig.sh
··· 9 9 NG=0 10 10 11 11 cleanup() { 12 - rm -f $INITRD $TEMPCONF 12 + rm -f $INITRD $TEMPCONF $OUTFILE 13 13 exit $NG 14 14 } 15 15 ··· 49 49 new_size=$(stat -c %s $INITRD) 50 50 51 51 echo "File size check" 52 - xpass test $new_size -eq $(expr $bconf_size + $initrd_size + 9) 52 + xpass test $new_size -eq $(expr $bconf_size + $initrd_size + 9 + 12) 53 53 54 54 echo "Apply command repeat test" 55 55 xpass $BOOTCONF -a $TEMPCONF $INITRD ··· 71 71 $BOOTCONF -a $TEMPCONF $INITRD > $OUTFILE 2>&1 72 72 xfail grep -i "failed" $OUTFILE 73 73 xfail grep -i "error" $OUTFILE 74 - rm $OUTFILE 75 74 76 75 echo "Max node number check" 77 76 ··· 94 95 truncate -s 32764 $TEMPCONF 95 96 echo "\"" >> $TEMPCONF # add 2 bytes + terminal ('\"\n\0') 96 97 xpass $BOOTCONF -a $TEMPCONF $INITRD 98 + 99 + echo "Adding same-key values" 100 + cat > $TEMPCONF << EOF 101 + key = bar, baz 102 + key += qux 103 + EOF 104 + echo > $INITRD 105 + 106 + xpass $BOOTCONF -a $TEMPCONF $INITRD 107 + $BOOTCONF $INITRD > $OUTFILE 108 + xpass grep -q "bar" $OUTFILE 109 + xpass grep -q "baz" $OUTFILE 110 + xpass grep -q "qux" $OUTFILE 97 111 98 112 echo "=== expected failure cases ===" 99 113 for i in samples/bad-* ; do