#1040467 file: /sys/firmware/acpi/bgrt/image strange behaviour

Package:
file
Source:
file
Description:
Recognize the type of data in a file using "magic" numbers
Submitter:
Date:
2023-07-23 22:09:04 UTC
Severity:
normal
Tags:
#1040467#5
Date:
2023-07-06 09:31:42 UTC
From:
To:
Dear Maintainer,

UEFI systems make the boot logo accessible for reading at the path /sys/firmware/acpi/bgrt/image

The file can be displayed directly using for example:
$ feh /sys/firmware/acpi/bgrt/image

Strange things happen when you copy this file elsewhere:
$ cp /sys/firmware/acpi/bgrt/image /tmp/image

and then run `file` on it:
$ file /sys/firmware/acpi/bgrt/image /tmp/image
/sys/firmware/acpi/bgrt/image: data
/tmp/image:                    PC bitmap, Windows 3.x format, 434 x 432 x 24, image size 565056, cbSize 565110, bits offset 54

If you diff those files, they are the same:
$ diff -s /sys/firmware/acpi/bgrt/image /tmp/image
Files /sys/firmware/acpi/bgrt/image and /tmp/image are identical

If you use the -d flag for `file`, it will produce internal debugging information:
$ file -d /sys/firmware/acpi/bgrt/image >/tmp/sys-firmware-acpi-bgrt-image.log 2>&1
$ file -d /tmp/image >/tmp/tmp-image.log 2>&1

If you then diff those logfiles, you can notice that that /tmp/sys-firmware-acpi-bgrt-image.log only uses nbytes=4096, whereas /tmp/tmp-image.log uses nbytes=565110. /tmp/sys-firmware-acpi-bgrt-image.log also fails to match the bitmap for unknown reason.

Please forward this bug upstream if it's not only on debian, thank you.

#1040467#10
Date:
2023-07-23 17:46:27 UTC
From:
To:
frank@gmail.com wrote...

While that particular sysfs file does not exist on my system, there's
already enough clue to get an idea what is happening here, and you
already almost got it:

(...)

This difference comes from the read() syscall file/libmagic does to get
the file content: When reading a file in /sys/, that call only reads
4096 bytes and returns an according result. However, some bits used to
identify the file are likely beyond that limit. To confirm, try file on
the first 4096 bytes only, this should again result in "data", or:

    $ dd if=/tmp/image bs=4096 count=1 | file -
    data

As a workaround, you could again use file(1) in a pipe, i.e.

    $ </sys/firmware/acpi/bgrt/image file -
    PC bitmap, Windows 3.x format, (...)

Feel free to confirm both.

This is (mostly) Linux-specific, still I'll take this to upstream.
Thanks for reporting.

    Christoph

#1040467#17
Date:
2023-07-23 22:06:43 UTC
From:
To:
Indeed if I only read 4096 bytes, I get:
1+0 records in
1+0 records out
4096 bytes (4.1 kB, 4.0 KiB) copied, 5.5761e-05 s, 73.5 MB/s
/dev/stdin: data

If I read the entire file size, except for the last byte, I still get:
$ dd if=/tmp/image bs=$(( $(stat --format=%s /tmp/image) - 1)) count=1 | file -
1+0 records in
1+0 records out
565109 bytes (565 kB, 552 KiB) copied, 0.00157071 s, 360 MB/s
/dev/stdin: data

Only when I read the whole file, then I get:
$ dd if=/tmp/image bs=$(stat --format=%s /tmp/image) count=1 | file -
1+0 records in
1+0 records out
565110 bytes (565 kB, 552 KiB) copied, 0.00156589 s, 361 MB/s
/dev/stdin: PC bitmap, Windows 3.x format, 434 x 432 x 24, image size 565056, cbSize 565110, bits offset 54

So it appears the very last byte is still important for correct detection of the image file through `file` and 4096 bytes will never be enough in this case.

For unknown reasons, this workaround does not work, because nbytes=4096 is still being used:
$ </sys/firmware/acpi/bgrt/image file -
/dev/stdin: data

But if I do "useless use of cat", then nbytes=565110 is used and it works:
$ cat /sys/firmware/acpi/bgrt/image | file -
/dev/stdin: PC bitmap, Windows 3.x format, 434 x 432 x 24, image size 565056, cbSize 565110, bits offset 54

So `file` still performs some special behavior when it detects that stdin comes from /sys