firmware version management: add firmware_version()
RFC PATCH 1/2 firmware version management: add firmware_version()
It would be good if a driver knows which firmware version will be written to the hardware. I'm talking about external firmware files claimed by request_firmware().
We know so many different firmware files for bcm43xx and it becomes more and more complicated without some firmware version management.
This patch can create the md5sum of a firmware file. Then it looks into a table to figure out which version number is assigned to the hashcode. That table is placed in the driver code and an example for bcm43xx comes in my next mail. Any comments?
base/firmware_class.c renamed from linux-2.6.18rc1/drivers/base/firmware_class.c +29 -0
@@ -16,6 +16,8 @@#include <linux/interrupt.h> #include <linux/bitops.h> #include <linux/mutex.h> +#include <linux/scatterlist.h> +#include <linux/crypto.h> #include <linux/firmware.h> #include "base.h"
@@ -48,6 +50,32 @@struct timer_list timeout; }; +u32 firmware_version (const struct firmware *fw,struct firmware_files *elmnt) +{ +struct scatterlist sg; +struct crypto_tfm *tfm; +char sig[16 ]; + + tfm =crypto_alloc_tfm ("md5" ,0 ); +if (tfm ==NULL ) +return 0 ; + +sg_init_one (&sg, fw->data, fw->size); + +crypto_digest_init (tfm); +crypto_digest_update (tfm, &sg,1 ); +crypto_digest_final (tfm, sig); +crypto_free_tfm (tfm); + +while (elmnt->version) { +if (memcmp (sig, elmnt->signature,sizeof (sig)) ==0 ) +return elmnt->version; + elmnt++; + } + +return 0 ; +} +static void fw_load_abort (struct firmware_priv *fw_priv) {
@@ -605,6 +633,7 @@module_init (firmware_class_init);module_exit (firmware_class_exit); +EXPORT_SYMBOL (firmware_version);EXPORT_SYMBOL (release_firmware);EXPORT_SYMBOL (request_firmware);EXPORT_SYMBOL (request_firmware_nowait);
linux/firmware.h renamed from linux-2.6.18rc1/include/linux/firmware.h +5 -0
@@ -10,7 +10,12 @@size_t size;u8 *data; }; +struct firmware_files { +u8 signature[16 ]; +u32 version; +};struct device ; +u32 firmware_version (const struct firmware *fw,struct firmware_files *elmnt);int request_firmware (const struct firmware **fw,const char *name,struct device *device); int request_firmware_nowait(
base/Kconfig renamed from linux-2.6.18rc1/drivers/base/Kconfig +1 -0
@@ -21,6 +21,7 @@ config FW_LOADER tristate "Userspace firmware loading support" select HOTPLUG + select CRYPTO_MD5 ---help--- This option is provided for the case where no in-kernel-tree modules require userspace firmware loading support, but a module built outside
Quoted 11 lines · Martin Langer
It would be good if a driver knows which firmware version will be written to the hardware. I'm talking about external firmware files claimed by
request_firmware().We know so many different firmware files for bcm43xx and it becomes more and more complicated without some firmware version management.
This patch can create the md5sum of a firmware file. Then it looks into a table to figure out which version number is assigned to the hashcode. That table is placed in the driver code and an example for bcm43xx comes in my next mail. Any comments?
Hi,
why does this have to happen on the kernel side? Isn't it a lot easier and better to let the userspace side of things do this work, and even have a userspace file with the md5->version mapping? Or are there some practical considerations that make that hard to impossible?
(I personally don't care if the file comes with the kernel, that may be the most convenient thing, but it would be a userspace file that the userspace side of the firmware loader uses)
Hi Arjan,
Quoted 12 lines
Quoted 11 lines
It would be good if a driver knows which firmware version will be written to the hardware. I'm talking about external firmware files claimed by
request_firmware().We know so many different firmware files for bcm43xx and it becomes more and more complicated without some firmware version management.
This patch can create the md5sum of a firmware file. Then it looks into a table to figure out which version number is assigned to the hashcode. That table is placed in the driver code and an example for bcm43xx comes in my next mail. Any comments?
Quoted 4 lines
why does this have to happen on the kernel side? Isn't it a lot easier and better to let the userspace side of things do this work, and even have a userspace file with the
md5->versionmapping? Or are there some practical considerations that make that hard to impossible?
I fully agree that we shouldn't put firmware versioning into the kernel drivers. The pattern you give to request_firmware() can be mapped to any file on the file system. And you also have the link to the device object and I prefer you export a sysfs file for the version so that the helper application loading the firmware can pick the right file.
Regards
Marcel
Quoted 19 lines · Marcel Holtmann
Hi Arjan,
Quoted 12 lines
Quoted 11 lines
It would be good if a driver knows which firmware version will be written to the hardware. I'm talking about external firmware files claimed by
request_firmware().We know so many different firmware files for bcm43xx and it becomes more and more complicated without some firmware version management.
This patch can create the md5sum of a firmware file. Then it looks into a table to figure out which version number is assigned to the hashcode. That table is placed in the driver code and an example for bcm43xx comes in my next mail. Any comments?
Quoted 4 lines
why does this have to happen on the kernel side? Isn't it a lot easier and better to let the userspace side of things do this work, and even have a userspace file with the
md5->versionmapping? Or are there some practical considerations that make that hard to impossible?
Quoted 5 lines
I fully agree that we shouldn't put firmware versioning into the kernel drivers. The pattern you give to
request_firmware()can be mapped to any file on the file system. And you also have the link to the device object and I prefer you export a sysfs file for the version so that the helper application loading the firmware can pick the right file.
Bcm43xx has no helper application to upload the firmware. This is done in the driver. It's RAM based hardware without a Flash-ROM. The driver has to upload the firmware in the init phase after each reset.
The driver gets a firmware file from /lib/firmware/ without knowing which version this is. It's not possible to say enable this in the driver if you find a firmware x and disable that if it's only version y. That was my motivation to start thinking about firmware versioning.
But in the meantime I think it's a security issue, too. A driver should only accept firmware files with certified checksums. I guess it would be really difficult to enter a machine by firmware hijacking. So, I'm still in hope that this is only a paranoia on my side. But it's worth to think about it.
Martin
Hi Martin,
Quoted 23 lines
Quoted 17 lines
Quoted 12 lines
Quoted 11 lines
It would be good if a driver knows which firmware version will be written to the hardware. I'm talking about external firmware files claimed by
request_firmware().We know so many different firmware files for bcm43xx and it becomes more and more complicated without some firmware version management.
This patch can create the md5sum of a firmware file. Then it looks into a table to figure out which version number is assigned to the hashcode. That table is placed in the driver code and an example for bcm43xx comes in my next mail. Any comments?
Quoted 4 lines
why does this have to happen on the kernel side? Isn't it a lot easier and better to let the userspace side of things do this work, and even have a userspace file with the
md5->versionmapping? Or are there some practical considerations that make that hard to impossible?Quoted 5 lines
I fully agree that we shouldn't put firmware versioning into the kernel drivers. The pattern you give to
request_firmware()can be mapped to any file on the file system. And you also have the link to the device object and I prefer you export a sysfs file for the version so that the helper application loading the firmware can pick the right file.
Quoted 8 lines
Bcm43xx has no helper application to upload the firmware. This is done in the driver. It's RAM based hardware without a Flash-ROM. The driver has to upload the firmware in the init phase after each reset.
The driver gets a firmware file from
/lib/firmware/without knowing which version this is. It's not possible to say enable this in the driver if you find a firmware x and disable that if it's only version y. That was my motivation to start thinking about firmware versioning.
then this is driver specific and you should handle the versioning of the firmware in your driver. There is no need to bother firmware_class with that task.
Regards
Marcel
Quoted 35 lines · you
Quoted 19 lines · Marcel Holtmann
Hi Arjan,
Quoted 12 lines
Quoted 11 lines
It would be good if a driver knows which firmware version will be written to the hardware. I'm talking about external firmware files claimed by
request_firmware().We know so many different firmware files for bcm43xx and it becomes more and more complicated without some firmware version management.
This patch can create the md5sum of a firmware file. Then it looks into a table to figure out which version number is assigned to the hashcode. That table is placed in the driver code and an example for bcm43xx comes in my next mail. Any comments?
Quoted 4 lines
why does this have to happen on the kernel side? Isn't it a lot easier and better to let the userspace side of things do this work, and even have a userspace file with the
md5->versionmapping? Or are there some practical considerations that make that hard to impossible?Quoted 5 lines
I fully agree that we shouldn't put firmware versioning into the kernel drivers. The pattern you give to
request_firmware()can be mapped to any file on the file system. And you also have the link to the device object and I prefer you export a sysfs file for the version so that the helper application loading the firmware can pick the right file.Bcm43xx has no helper application to upload the firmware. This is done in the driver. It's RAM based hardware without a Flash-ROM. The driver has to upload the firmware in the init phase after each reset.
The driver gets a firmware file from
/lib/firmware/without knowing which version this is. It's not possible to say enable this in the driver if you find a firmware x and disable that if it's only version y. That was my motivation to start thinking about firmware versioning.
Quoted 5 lines
But in the meantime I think it's a security issue, too. A driver should only accept firmware files with certified checksums. I guess it would be really difficult to enter a machine by firmware hijacking. So, I'm still in hope that this is only a paranoia on my side. But it's worth to think about it.
I really think drivers should only allow firmware files that are known to work. This should be verified by a hardcoded checksum in the driver. I support Martin's patch.
The problem is (for bcm43xx):
If we load wrong firmware, the device sometimes does not work correctly (as the firmware was never tested by any developer). If we load wrong firmware, we can completely crash the machine. And no, we can't avoid this by some sanity checks. We have sanity checks there that catch the most obvious garbage, but it can never catch everything. So it is possible to MachineCheck the kernel from userspace, by providing wrong firmware. Only root can do that, but it is hard to diagnose that it's caused by faulty firmware. It is also possible to trigger some NULL pointer dereferences, because with a too-new firmware, the device will return different TX status reports to the driver. Yeah, we could add a if(foo!=NULL) there, but that would _still_ not be safe, because we still get garbage back. In a driver we simply _depend_ on the hardware to work correctly. As the hardware is equal to the firmware (from the driver pov), we depend on correct firmware for correct operation.
So what we want to do is: Dongle several known good firmwares (through the checksum) to a driver version.
Signature · 1 line
Greetings Michael.
Quoted 55 lines · Michael Buesch
Quoted 35 lines · you
Quoted 19 lines · Marcel Holtmann
Hi Arjan,
Quoted 12 lines
Quoted 11 lines
It would be good if a driver knows which firmware version will be written to the hardware. I'm talking about external firmware files claimed by
request_firmware().We know so many different firmware files for bcm43xx and it becomes more and more complicated without some firmware version management.
This patch can create the md5sum of a firmware file. Then it looks into a table to figure out which version number is assigned to the hashcode. That table is placed in the driver code and an example for bcm43xx comes in my next mail. Any comments?
Quoted 4 lines
why does this have to happen on the kernel side? Isn't it a lot easier and better to let the userspace side of things do this work, and even have a userspace file with the
md5->versionmapping? Or are there some practical considerations that make that hard to impossible?Quoted 5 lines
I fully agree that we shouldn't put firmware versioning into the kernel drivers. The pattern you give to
request_firmware()can be mapped to any file on the file system. And you also have the link to the device object and I prefer you export a sysfs file for the version so that the helper application loading the firmware can pick the right file.Bcm43xx has no helper application to upload the firmware. This is done in the driver. It's RAM based hardware without a Flash-ROM. The driver has to upload the firmware in the init phase after each reset.
The driver gets a firmware file from
/lib/firmware/without knowing which version this is. It's not possible to say enable this in the driver if you find a firmware x and disable that if it's only version y. That was my motivation to start thinking about firmware versioning.Quoted 5 lines
But in the meantime I think it's a security issue, too. A driver should only accept firmware files with certified checksums. I guess it would be really difficult to enter a machine by firmware hijacking. So, I'm still in hope that this is only a paranoia on my side. But it's worth to think about it.
I really think drivers should only allow firmware files that are known to work. This should be verified by a hardcoded checksum in the driver. I support Martin's patch.
The problem is (for bcm43xx):
If we load wrong firmware, the device sometimes does not work correctly (as the firmware was never tested by any developer). If we load wrong firmware, we can completely crash the machine. And no, we can't avoid this by some sanity checks. We have sanity checks there that catch the most obvious garbage, but it can never catch everything. So it is possible to MachineCheck the kernel from userspace, by providing wrong firmware. Only root can do that, but it is hard to diagnose that it's caused by faulty firmware. It is also possible to trigger some NULL pointer dereferences,
Quoted 8 lines
because with a too-new firmware, the device will return different TX status reports to the driver. Yeah, we could add a if(foo!=NULL) there, but that would _still_ not be safe, because we still get garbage back. In a driver we simply _depend_ on the hardware to work correctly. As the hardware is equal to the firmware (from the driver pov), we depend on correct firmware for correct operation.
So what we want to do is: Dongle several known good firmwares (through the checksum) to a driver version.
You can do this in the other direction from user space. Have the driver add a sysfs attribute containing a list of allowed MD5s for firmware images. Now modify /bin/firmware_helper to check the file against the valid list and abort if there is not a match.
Doing this in user space will make it easier for the user to debug what is happening when things fail.
Quoted 9 lines
--
Greetings Michael.
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Signature · 2 lines
Jon Smirl [email protected]
Hi Michael,
Quoted 38 lines
Quoted 32 lines
Quoted 17 lines
Quoted 12 lines
Quoted 11 lines
It would be good if a driver knows which firmware version will be written to the hardware. I'm talking about external firmware files claimed by
request_firmware().We know so many different firmware files for bcm43xx and it becomes more and more complicated without some firmware version management.
This patch can create the md5sum of a firmware file. Then it looks into a table to figure out which version number is assigned to the hashcode. That table is placed in the driver code and an example for bcm43xx comes in my next mail. Any comments?
Quoted 4 lines
why does this have to happen on the kernel side? Isn't it a lot easier and better to let the userspace side of things do this work, and even have a userspace file with the
md5->versionmapping? Or are there some practical considerations that make that hard to impossible?Quoted 5 lines
I fully agree that we shouldn't put firmware versioning into the kernel drivers. The pattern you give to
request_firmware()can be mapped to any file on the file system. And you also have the link to the device object and I prefer you export a sysfs file for the version so that the helper application loading the firmware can pick the right file.Bcm43xx has no helper application to upload the firmware. This is done in the driver. It's RAM based hardware without a Flash-ROM. The driver has to upload the firmware in the init phase after each reset.
The driver gets a firmware file from
/lib/firmware/without knowing which version this is. It's not possible to say enable this in the driver if you find a firmware x and disable that if it's only version y. That was my motivation to start thinking about firmware versioning.Quoted 5 lines
But in the meantime I think it's a security issue, too. A driver should only accept firmware files with certified checksums. I guess it would be really difficult to enter a machine by firmware hijacking. So, I'm still in hope that this is only a paranoia on my side. But it's worth to think about it.
Quoted 3 lines
I really think drivers should only allow firmware files that are known to work. This should be verified by a hardcoded checksum in the driver. I support Martin's patch.
this should be done in the driver. So why do you try to enhance the firmware_class to do this job. If your driver has special requirements for firmware checks, then implement them. I don't see any advantage of doing this kind of stuff in firmware_class at the moment.
Regards
Marcel
Quoted 26 lines · Martin Langer
Quoted 19 lines · Marcel Holtmann
Hi Arjan,
Quoted 12 lines
Quoted 11 lines
It would be good if a driver knows which firmware version will be written to the hardware. I'm talking about external firmware files claimed by
request_firmware().We know so many different firmware files for bcm43xx and it becomes more and more complicated without some firmware version management.
This patch can create the md5sum of a firmware file. Then it looks into a table to figure out which version number is assigned to the hashcode. That table is placed in the driver code and an example for bcm43xx comes in my next mail. Any comments?
Quoted 4 lines
why does this have to happen on the kernel side? Isn't it a lot easier and better to let the userspace side of things do this work, and even have a userspace file with the
md5->versionmapping? Or are there some practical considerations that make that hard to impossible?Quoted 5 lines
I fully agree that we shouldn't put firmware versioning into the kernel drivers. The pattern you give to
request_firmware()can be mapped to any file on the file system. And you also have the link to the device object and I prefer you export a sysfs file for the version so that the helper application loading the firmware can pick the right file.
Quoted 3 lines
Bcm43xx has no helper application to upload the firmware. This is done in the driver. It's RAM based hardware without a Flash-ROM. The driver has to upload the firmware in the init phase after each reset.
When your driver does request_firmware() I believe udev is triggering the /sbin/firmware_helper app.
rules.d/05-udev-early.rules:ACTION=="add", SUBSYSTEM=="firmware", ENV{FIRMWARE}=="*", RUN="/sbin/firmware_helper", OPTIONS="last_rule"
This app could be made smarter and set a version/checksum into two more sysfs attributes.
I also though that the firmware loader was going to be modified to load the firmware via a firmware attribute located in the device node instead of a global firmware attribute. But it doesn't look like that change has been made. If the loading were done inside the device node adding the version/checksum attributes would be more obvious. /sbin/firmware_helper could set these attributes while loading the file.
Quoted 19 lines
The driver gets a firmware file from
/lib/firmware/without knowing which version this is. It's not possible to say enable this in the driver if you find a firmware x and disable that if it's only version y. That was my motivation to start thinking about firmware versioning.But in the meantime I think it's a security issue, too. A driver should only accept firmware files with certified checksums. I guess it would be really difficult to enter a machine by firmware hijacking. So, I'm still in hope that this is only a paranoia on my side. But it's worth to think about it.
Martin
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Signature · 2 lines
Jon Smirl [email protected]
Quoted 20 lines · Martin Langer
Quoted 19 lines · Marcel Holtmann
Hi Arjan,
Quoted 16 lines
Quoted 11 lines
It would be good if a driver knows which firmware version will be written to the hardware. I'm talking about external firmware files claimed by
request_firmware().We know so many different firmware files for bcm43xx and it becomes more and more complicated without some firmware version management.
This patch can create the md5sum of a firmware file. Then it looks into a table to figure out which version number is assigned to the hashcode. That table is placed in the driver code and an example for bcm43xx comes in my next mail. Any comments?
why does this have to happen on the kernel side? Isn't it a lot easier and better to let the userspace side of things do this work, and even have a userspace file with the
md5->versionmapping? Or are there some practical considerations that make that hard to impossible?
Quoted 7 lines
Quoted 5 lines
I fully agree that we shouldn't put firmware versioning into the kernel drivers. The pattern you give to
request_firmware()can be mapped to any file on the file system. And you also have the link to the device object and I prefer you export a sysfs file for the version so that the helper application loading the firmware can pick the right file.Bcm43xx has no helper application to upload the firmware.
yes it does. bcm43xx asks userspace to upload firmware (via request_firmware() ) and a userspace app (udev most of the time) will upload it. That app, eg udev, can do the md5sum and checking it against a list of "known good" firmwares. Voila problem solved ;)
Quoted 27 lines · Arjan van de Ven
Quoted 26 lines · Martin Langer
Quoted 24 lines · Marcel Holtmann
Hi Arjan,
Quoted 12 lines
Quoted 11 lines
It would be good if a driver knows which firmware version will be written to the hardware. I'm talking about external firmware files claimed by
request_firmware().We know so many different firmware files for bcm43xx and it becomes more and more complicated without some firmware version management.
This patch can create the md5sum of a firmware file. Then it looks into a table to figure out which version number is assigned to the hashcode. That table is placed in the driver code and an example for bcm43xx comes in my next mail. Any comments?
Quoted 4 lines
why does this have to happen on the kernel side? Isn't it a lot easier and better to let the userspace side of things do this work, and even have a userspace file with the
md5->versionmapping? Or are there some practical considerations that make that hard to impossible?I fully agree that we shouldn't put firmware versioning into the kernel drivers. The pattern you give to
request_firmware()can be mapped to any file on the file system. And you also have the link to the device object and I prefer you export a sysfs file for the version so that the helper application loading the firmware can pick the right file.
Quoted 6 lines
Quoted 1 line
Bcm43xx has no helper application to upload the firmware.
yes it does. bcm43xx asks userspace to upload firmware (via
request_firmware()) and a userspace app (udev most of the time) will upload it. That app, eg udev, can do the md5sum and checking it against a list of "known good" firmwares. Voila problem solved ;)
I see. It's an interesting way that I didn't noticed. Thanks for the guidance.
Martin
Quoted 7 lines · you
Quoted 4 lines
yes it does. bcm43xx asks userspace to upload firmware (via
request_firmware()) and a userspace app (udev most of the time) will upload it. That app, eg udev, can do the md5sum and checking it against a list of "known good" firmwares. Voila problem solved ;)I see. It's an interesting way that I didn't noticed. Thanks for the guidance.
Nono, stop. Not too fast. :)
Where is this "list of "known good" firmwares" actually stored? In userspace (udev)? That would be guaranteed to be out of sync with the driver.
As said previously, we need to tie a specific driver version to one or more firmware versions. So the only sane place to put the MD5 sums (or whatever) in, is the driver. Otherwise it will not be in sync.
So, if we want to verify the checksum in userspace, we must export a list of known good checksums to userspace. Could be done through a sysfs file with a list of checksums.
cat /sys/foo/device/acceptable_firmwares
MD5: cbd8320a2a458d1cfad5420c6fa6a823
MD5: b812d7dd3d3b88fbc113e0bbf7e07c8d
That would also allow other hash algorithms in future while providing backward compat.
Signature · 1 line
Greetings Michael.
Quoted 6 lines · Michael Buesch
Quoted 5 lines · you
Quoted 4 lines
yes it does. bcm43xx asks userspace to upload firmware (via
request_firmware()) and a userspace app (udev most of the time) will upload it. That app, eg udev, can do the md5sum and checking it against a list of "known good" firmwares. Voila problem solved ;)
Quoted 7 lines
Quoted 2 lines
I see. It's an interesting way that I didn't noticed. Thanks for the guidance.
Nono, stop. Not too fast. :)
Where is this "list of "known good" firmwares" actually stored? In userspace (udev)? That would be guaranteed to be out of sync with the driver.
for all I care it's part of the kernel tarbal somehow
but a real file, not some in kernel memory eating thing