Re: [Qemu-devel] [PATCH v5 1/4] firmware: introduce sysfs driver for QEMU's fw_cfg device
On 11/24/2015 09:55 AM, Gabriel L. Somlo wrote: > On Tue, Nov 24, 2015 at 04:14:50AM +0800, kbuild test robot wrote: >> >>drivers/firmware/qemu_fw_cfg.c: In function 'fw_cfg_cmdline_set': drivers/firmware/qemu_fw_cfg.c:510:7: warning: format '%lli' expects argument of type 'long long int *', but argument 3 has type 'phys_addr_t *' [-Wformat=] >> _off, _off, ); >> ^ > > Oh, I think I know why this happened: > > > So, I could use u64 instead of phys_addr_t and resource_size_t, and > keep "%lli" (or "%Li"), but then I'd have to check if the parsed value %Li is not POSIX. Don't use it (stick with %lli). > would overflow a 32-bit address value on arches where phys_addr_t is > u32, which would make things a bit more messy and awkward. > > I'm planning on #ifdef-ing the format string instead: > > #ifdef CONFIG_PHYS_ADDR_T_64BIT > #define PH_ADDR_SCAN_FMT "@%Li%n:%Li:%Li%n" > #else > #define PH_ADDR_SCAN_FMT "@%li%n:%li:%li%n" > #endif A more typical approach is akin to ; have PH_ADDR_FMT defined to either "lli" or "li", then write sscanf(str, "@%"PH_ADDR_FMT "%n:..., ...), using PH_ADDR_FMT multiple times. > ... > processed = sscanf(str, PH_ADDR_SCAN_FMT, >, , >_off, _off, ); Umm, why are you passing to more than one sscanf() %? That's (probably) undefined behavior. [In general, sscanf() is a horrid interface to use for parsing integers - it has undefined behavior if the input text would trigger integer overflow, making it safe to use ONLY on text that you control and can guarantee won't overflow. By the time you've figured out if untrusted text meets the requirement for safe parsing via sscanf(), you've practically already parsed it via safer strtol() and friends.] -- Eric Blake eblake redhat com+1-919-301-3266 Libvirt virtualization library http://libvirt.org signature.asc Description: OpenPGP digital signature
Re: [Qemu-devel] [PATCH v5 1/4] firmware: introduce sysfs driver for QEMU's fw_cfg device
On 11/24/15 18:38, Eric Blake wrote: > On 11/24/2015 09:55 AM, Gabriel L. Somlo wrote: >> On Tue, Nov 24, 2015 at 04:14:50AM +0800, kbuild test robot wrote: > >>> >>>drivers/firmware/qemu_fw_cfg.c: In function 'fw_cfg_cmdline_set': > drivers/firmware/qemu_fw_cfg.c:510:7: warning: format '%lli' expects > argument of type 'long long int *', but argument 3 has type 'phys_addr_t > *' [-Wformat=] >>> _off, _off, ); >>> ^ >> >> Oh, I think I know why this happened: >> > >> >> So, I could use u64 instead of phys_addr_t and resource_size_t, and >> keep "%lli" (or "%Li"), but then I'd have to check if the parsed value > > %Li is not POSIX. Don't use it (stick with %lli). > >> would overflow a 32-bit address value on arches where phys_addr_t is >> u32, which would make things a bit more messy and awkward. >> >> I'm planning on #ifdef-ing the format string instead: >> >> #ifdef CONFIG_PHYS_ADDR_T_64BIT >> #define PH_ADDR_SCAN_FMT "@%Li%n:%Li:%Li%n" >> #else >> #define PH_ADDR_SCAN_FMT "@%li%n:%li:%li%n" >> #endif > > A more typical approach is akin to ; have PH_ADDR_FMT > defined to either "lli" or "li", then write sscanf(str, "@%"PH_ADDR_FMT > "%n:..., ...), using PH_ADDR_FMT multiple times. > >> ... >> processed = sscanf(str, PH_ADDR_SCAN_FMT, >>, , >>_off, _off, ); > > Umm, why are you passing to more than one sscanf() %? That's > (probably) undefined behavior. > > [In general, sscanf() is a horrid interface to use for parsing integers > - it has undefined behavior if the input text would trigger integer > overflow, making it safe to use ONLY on text that you control and can > guarantee won't overflow. By the time you've figured out if untrusted > text meets the requirement for safe parsing via sscanf(), you've > practically already parsed it via safer strtol() and friends.] > Yes, but this is the kernel, which may or may not follow POSIX semantics. (And may or may not curse at POSIX in the process, either way! :)) Laszlo
Re: [Qemu-devel] [PATCH v5 1/4] firmware: introduce sysfs driver for QEMU's fw_cfg device
On Tue, Nov 24, 2015 at 10:38:18AM -0700, Eric Blake wrote: > On 11/24/2015 09:55 AM, Gabriel L. Somlo wrote: > > On Tue, Nov 24, 2015 at 04:14:50AM +0800, kbuild test robot wrote: > > >> > >>drivers/firmware/qemu_fw_cfg.c: In function 'fw_cfg_cmdline_set': > drivers/firmware/qemu_fw_cfg.c:510:7: warning: format '%lli' expects > argument of type 'long long int *', but argument 3 has type 'phys_addr_t > *' [-Wformat=] > >> _off, _off, ); > >> ^ > > > > Oh, I think I know why this happened: > > > > > > > So, I could use u64 instead of phys_addr_t and resource_size_t, and > > keep "%lli" (or "%Li"), but then I'd have to check if the parsed value > > %Li is not POSIX. Don't use it (stick with %lli). > > > would overflow a 32-bit address value on arches where phys_addr_t is > > u32, which would make things a bit more messy and awkward. > > > > I'm planning on #ifdef-ing the format string instead: > > > > #ifdef CONFIG_PHYS_ADDR_T_64BIT > > #define PH_ADDR_SCAN_FMT "@%Li%n:%Li:%Li%n" > > #else > > #define PH_ADDR_SCAN_FMT "@%li%n:%li:%li%n" > > #endif > > A more typical approach is akin to ; have PH_ADDR_FMT > defined to either "lli" or "li", then write sscanf(str, "@%"PH_ADDR_FMT > "%n:..., ...), using PH_ADDR_FMT multiple times. That sounds almost like it should be a separate patch against include/linux/types.h: diff --git a/include/linux/types.h b/include/linux/types.h index 70d8500..35be16e 100644 --- a/include/linux/types.h +++ b/include/linux/types.h @@ -160,8 +160,10 @@ typedef unsigned __bitwise__ oom_flags_t; #ifdef CONFIG_PHYS_ADDR_T_64BIT typedef u64 phys_addr_t; +#define __PHYS_ADDR_PREFIX "ll" #else typedef u32 phys_addr_t; +#define __PHYS_ADDR_PREFIX "l" #endif typedef phys_addr_t resource_size_t; But whether it's a good idea for me to detour from fw_cfg/sysfs into sorting this out with the kernel community right now, I don't know :) I'll just try to do it inside the fw_cfg sysfs driver for now, see how that goes... > > > ... > > processed = sscanf(str, PH_ADDR_SCAN_FMT, > >, , > >_off, _off, ); > > Umm, why are you passing to more than one sscanf() %? That's > (probably) undefined behavior. Input might end after reading 'base', in which case %n would store the next character's index in consumed, and evaluate (but otherwise ignore) the remaining pointer arguments (including the second ). Or, it might end after reading data_off, then the earlier value of consumed gets overwritten with the new (past data_off) index. I get to verify that str[index] is '\0', i.e. that there were no left-over, unprocessed characters, whether I got one or three items processed by scanf. I don't think passing '' in twice is a problem. I also didn't cleverly come up with this myself, but rather lifted it from drivers/virtio/virtio_mmio.c, so at least there's precedent :) > [In general, sscanf() is a horrid interface to use for parsing integers > - it has undefined behavior if the input text would trigger integer > overflow, making it safe to use ONLY on text that you control and can > guarantee won't overflow. By the time you've figured out if untrusted > text meets the requirement for safe parsing via sscanf(), you've > practically already parsed it via safer strtol() and friends.] Just like (I think) is the case with virtio_mmio, this is an optional feature to allow specifying a base address, range, and register offsets for fw_cfg via the insmod (or modprobe) command line, so one would already have to be root. Also, perfectly well-formated base and size values could be used to hose the system, which is why virtio_mmio (and also fw_cfg) leave this feature off by default, and recommend caution before one would turn it on. Thanks much, --Gabriel
Re: [Qemu-devel] [PATCH v5 1/4] firmware: introduce sysfs driver for QEMU's fw_cfg device
On Tue, Nov 24, 2015 at 04:14:50AM +0800, kbuild test robot wrote: > Hi Gabriel, > > [auto build test WARNING on v4.4-rc2] > [also build test WARNING on next-20151123] > [cannot apply to robh/for-next] > > url: > https://github.com/0day-ci/linux/commits/Gabriel-L-Somlo/SysFS-driver-for-QEMU-fw_cfg-device/20151124-000402 > config: arm-allyesconfig (attached as .config) > reproduce: > wget > https://git.kernel.org/cgit/linux/kernel/git/wfg/lkp-tests.git/plain/sbin/make.cross > -O ~/bin/make.cross > chmod +x ~/bin/make.cross > # save the attached .config to linux build tree > make.cross ARCH=arm > > All warnings (new ones prefixed by >>): > >drivers/firmware/qemu_fw_cfg.c: In function 'fw_cfg_cmdline_set': > >> drivers/firmware/qemu_fw_cfg.c:510:7: warning: format '%lli' expects > >> argument of type 'long long int *', but argument 3 has type 'phys_addr_t > >> *' [-Wformat=] > _off, _off, ); > ^ Oh, I think I know why this happened: ... phys_addr_t base; resource_size_t size, ctrl_off, data_off; ... /* get "@[::]" chunks */ processed = sscanf(str, "@%lli%n:%lli:%lli%n" , , _off, _off, ); ... On some architectures, phys_addr_t (and resource_size_t) are u32, rather than u64. In include/linux/types.h we have: ... #ifdef CONFIG_PHYS_ADDR_T_64BIT typedef u64 phys_addr_t; #else typedef u32 phys_addr_t; #endif ... So, I could use u64 instead of phys_addr_t and resource_size_t, and keep "%lli" (or "%Li"), but then I'd have to check if the parsed value would overflow a 32-bit address value on arches where phys_addr_t is u32, which would make things a bit more messy and awkward. I'm planning on #ifdef-ing the format string instead: #ifdef CONFIG_PHYS_ADDR_T_64BIT #define PH_ADDR_SCAN_FMT "@%Li%n:%Li:%Li%n" #else #define PH_ADDR_SCAN_FMT "@%li%n:%li:%li%n" #endif ... processed = sscanf(str, PH_ADDR_SCAN_FMT, , , _off, _off, ); This should make the warning go away, and be correct. Does that sound like a valid plan, or is there some other stylistic reason I should stay away from doing it that way ? thanks, --Gabriel > >> drivers/firmware/qemu_fw_cfg.c:510:7: warning: format '%lli' expects > >> argument of type 'long long int *', but argument 5 has type > >> 'resource_size_t *' [-Wformat=] >drivers/firmware/qemu_fw_cfg.c:510:7: warning: format '%lli' expects > argument of type 'long long int *', but argument 6 has type 'resource_size_t > *' [-Wformat=] >drivers/firmware/qemu_fw_cfg.c: In function 'fw_cfg_cmdline_get': > >> drivers/firmware/qemu_fw_cfg.c:563:5: warning: format '%llx' expects > >> argument of type 'long long unsigned int', but argument 4 has type > >> 'resource_size_t' [-Wformat=] > fw_cfg_cmdline_dev->resource[0].start); > ^ >drivers/firmware/qemu_fw_cfg.c:563:5: warning: format '%llx' expects > argument of type 'long long unsigned int', but argument 5 has type > 'resource_size_t' [-Wformat=] >drivers/firmware/qemu_fw_cfg.c:569:5: warning: format '%llx' expects > argument of type 'long long unsigned int', but argument 4 has type > 'resource_size_t' [-Wformat=] > fw_cfg_cmdline_dev->resource[2].start); > ^ >drivers/firmware/qemu_fw_cfg.c:569:5: warning: format '%llx' expects > argument of type 'long long unsigned int', but argument 5 has type > 'resource_size_t' [-Wformat=] > >> drivers/firmware/qemu_fw_cfg.c:569:5: warning: format '%llu' expects > >> argument of type 'long long unsigned int', but argument 6 has type > >> 'resource_size_t' [-Wformat=] >drivers/firmware/qemu_fw_cfg.c:569:5: warning: format '%llu' expects > argument of type 'long long unsigned int', but argument 7 has type > 'resource_size_t' [-Wformat=] > > vim +510 drivers/firmware/qemu_fw_cfg.c > >504/* consume "" portion of command line argument */ >505size = memparse(arg, ); >506 >507/* get "@[::]" chunks */ >508processed = sscanf(str, "@%lli%n:%lli:%lli%n", >509 , , > > 510 _off, _off, ); >511 >512/* sscanf() must process precisely 1 or 3 chunks: >513 * is mandatory, optionally followed by > >514 * and ; >515 * there must be no extra characters after the last > chunk, >516 * so str[consumed] must be '\0'. >517 */ >518if (str[consumed] || >519(processed != 1 && processed != 3)) >520return -EINVAL; >521 >522res[0].start = base; >523res[0].end = base + size - 1; >524res[0].flags = !strcmp(kp->name, "mmio")
Re: [Qemu-devel] [PATCH v5 1/4] firmware: introduce sysfs driver for QEMU's fw_cfg device
Hi Gabriel, [auto build test WARNING on v4.4-rc2] [also build test WARNING on next-20151123] [cannot apply to robh/for-next] url: https://github.com/0day-ci/linux/commits/Gabriel-L-Somlo/SysFS-driver-for-QEMU-fw_cfg-device/20151124-000402 config: arm-allyesconfig (attached as .config) reproduce: wget https://git.kernel.org/cgit/linux/kernel/git/wfg/lkp-tests.git/plain/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross # save the attached .config to linux build tree make.cross ARCH=arm All warnings (new ones prefixed by >>): drivers/firmware/qemu_fw_cfg.c: In function 'fw_cfg_cmdline_set': >> drivers/firmware/qemu_fw_cfg.c:510:7: warning: format '%lli' expects >> argument of type 'long long int *', but argument 3 has type 'phys_addr_t *' >> [-Wformat=] _off, _off, ); ^ >> drivers/firmware/qemu_fw_cfg.c:510:7: warning: format '%lli' expects >> argument of type 'long long int *', but argument 5 has type 'resource_size_t >> *' [-Wformat=] drivers/firmware/qemu_fw_cfg.c:510:7: warning: format '%lli' expects argument of type 'long long int *', but argument 6 has type 'resource_size_t *' [-Wformat=] drivers/firmware/qemu_fw_cfg.c: In function 'fw_cfg_cmdline_get': >> drivers/firmware/qemu_fw_cfg.c:563:5: warning: format '%llx' expects >> argument of type 'long long unsigned int', but argument 4 has type >> 'resource_size_t' [-Wformat=] fw_cfg_cmdline_dev->resource[0].start); ^ drivers/firmware/qemu_fw_cfg.c:563:5: warning: format '%llx' expects argument of type 'long long unsigned int', but argument 5 has type 'resource_size_t' [-Wformat=] drivers/firmware/qemu_fw_cfg.c:569:5: warning: format '%llx' expects argument of type 'long long unsigned int', but argument 4 has type 'resource_size_t' [-Wformat=] fw_cfg_cmdline_dev->resource[2].start); ^ drivers/firmware/qemu_fw_cfg.c:569:5: warning: format '%llx' expects argument of type 'long long unsigned int', but argument 5 has type 'resource_size_t' [-Wformat=] >> drivers/firmware/qemu_fw_cfg.c:569:5: warning: format '%llu' expects >> argument of type 'long long unsigned int', but argument 6 has type >> 'resource_size_t' [-Wformat=] drivers/firmware/qemu_fw_cfg.c:569:5: warning: format '%llu' expects argument of type 'long long unsigned int', but argument 7 has type 'resource_size_t' [-Wformat=] vim +510 drivers/firmware/qemu_fw_cfg.c 504 /* consume "" portion of command line argument */ 505 size = memparse(arg, ); 506 507 /* get "@[::]" chunks */ 508 processed = sscanf(str, "@%lli%n:%lli:%lli%n", 509 , , > 510 _off, _off, ); 511 512 /* sscanf() must process precisely 1 or 3 chunks: 513 * is mandatory, optionally followed by 514 * and ; 515 * there must be no extra characters after the last chunk, 516 * so str[consumed] must be '\0'. 517 */ 518 if (str[consumed] || 519 (processed != 1 && processed != 3)) 520 return -EINVAL; 521 522 res[0].start = base; 523 res[0].end = base + size - 1; 524 res[0].flags = !strcmp(kp->name, "mmio") ? IORESOURCE_MEM : 525 IORESOURCE_IO; 526 527 /* insert register offsets, if provided */ 528 if (processed > 1) { 529 res[1].name = "ctrl"; 530 res[1].start = ctrl_off; 531 res[1].flags = IORESOURCE_REG; 532 res[2].name = "data"; 533 res[2].start = data_off; 534 res[2].flags = IORESOURCE_REG; 535 } 536 537 /* "processed" happens to nicely match the number of resources 538 * we need to pass in to this platform device. 539 */ 540 fw_cfg_cmdline_dev = platform_device_register_simple("fw_cfg", 541 PLATFORM_DEVID_NONE, res, processed); 542 if (IS_ERR(fw_cfg_cmdline_dev)) 543 return PTR_ERR(fw_cfg_cmdline_dev); 544 545 return 0; 546 } 547 548 static int fw_cfg_cmdline_get(char *buf, const struct kernel_param *kp) 549 { 550 /* stay silent if device was not configured via the command 551 * line, or if the parameter name (ioport/mmio) doesn't match 552 * the device setting 553 */ 554 if (!fw_cfg_cmdline_dev || 555 (!strcmp(kp->name, "mmio") ^ 556 (fw_cfg_cmdline_dev->resource[0].flags == IORESOURCE_MEM))) 557 return 0; 558 559 switch (fw_cfg_cmdline_dev->num_resources) { 560 case 1: 561
[Qemu-devel] [PATCH v5 1/4] firmware: introduce sysfs driver for QEMU's fw_cfg device
From: Gabriel SomloMake fw_cfg entries of type "file" available via sysfs. Entries are listed under /sys/firmware/qemu_fw_cfg/by_key, in folders named after each entry's selector key. Filename, selector value, and size read-only attributes are included for each entry. Also, a "raw" attribute allows retrieval of the full binary content of each entry. The fw_cfg device can be instantiated automatically from ACPI or the Device Tree, or manually by using a kernel module (or command line) parameter, with a syntax outlined in the documentation file. Signed-off-by: Gabriel Somlo --- .../ABI/testing/sysfs-firmware-qemu_fw_cfg | 58 ++ drivers/firmware/Kconfig | 19 + drivers/firmware/Makefile | 1 + drivers/firmware/qemu_fw_cfg.c | 611 + 4 files changed, 689 insertions(+) create mode 100644 Documentation/ABI/testing/sysfs-firmware-qemu_fw_cfg create mode 100644 drivers/firmware/qemu_fw_cfg.c diff --git a/Documentation/ABI/testing/sysfs-firmware-qemu_fw_cfg b/Documentation/ABI/testing/sysfs-firmware-qemu_fw_cfg new file mode 100644 index 000..718fbac --- /dev/null +++ b/Documentation/ABI/testing/sysfs-firmware-qemu_fw_cfg @@ -0,0 +1,58 @@ +What: /sys/firmware/qemu_fw_cfg/ +Date: August 2015 +Contact: Gabriel Somlo +Description: + Several different architectures supported by QEMU (x86, arm, + sun4*, ppc/mac) are provisioned with a firmware configuration + (fw_cfg) device, originally intended as a way for the host to + provide configuration data to the guest firmware. Starting + with QEMU v2.4, arbitrary fw_cfg file entries may be specified + by the user on the command line, which makes fw_cfg additionally + useful as an out-of-band, asynchronous mechanism for providing + configuration data to the guest userspace. + + The authoritative guest-side hardware interface documentation + to the fw_cfg device ca be found in "docs/specs/fw_cfg.txt" in + the QEMU source tree. + + === SysFS fw_cfg Interface === + + The fw_cfg sysfs interface described in this document is only + intended to display discoverable blobs (i.e., those registered + with the file directory), as there is no way to determine the + presence or size of "legacy" blobs (with selector keys between + 0x0002 and 0x0018) programmatically. + + All fw_cfg information is shown under: + + /sys/firmware/qemu_fw_cfg/ + + The only legacy blob displayed is the fw_cfg device revision: + + /sys/firmware/qemu_fw_cfg/rev + + --- Discoverable fw_cfg blobs by selector key --- + + All discoverable blobs listed in the fw_cfg file directory are + displayed as entries named after their unique selector key + value, e.g.: + + /sys/firmware/qemu_fw_cfg/by_key/32 + /sys/firmware/qemu_fw_cfg/by_key/33 + /sys/firmware/qemu_fw_cfg/by_key/34 + ... + + Each such fw_cfg sysfs entry has the following values exported + as attributes: + + name: The 56-byte nul-terminated ASCII string used as the + blob's 'file name' in the fw_cfg directory. + size: The length of the blob, as given in the fw_cfg + directory. + key : The value of the blob's selector key as given in the + fw_cfg directory. This value is the same as used in + the parent directory name. + raw : The raw bytes of the blob, obtained by selecting the + entry via the control register, and reading a number + of bytes equal to the blob size from the data + register. diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig index cf478fe..3cf920a 100644 --- a/drivers/firmware/Kconfig +++ b/drivers/firmware/Kconfig @@ -161,6 +161,25 @@ config RASPBERRYPI_FIRMWARE This option enables support for communicating with the firmware on the Raspberry Pi. +config FW_CFG_SYSFS + tristate "QEMU fw_cfg device support in sysfs" + depends on SYSFS + default n + help + Say Y or M here to enable the exporting of the QEMU firmware + configuration (fw_cfg) file entries via sysfs. Entries are + found under /sys/firmware/fw_cfg when this option is enabled + and loaded. + +config FW_CFG_SYSFS_CMDLINE + bool "QEMU fw_cfg device parameter parsing" + depends on FW_CFG_SYSFS