803fb7
From 210ec6353d3cab2029e1eb160671fea918c97814 Mon Sep 17 00:00:00 2001
803fb7
From: "Jason S. McMullan" <jason.mcmullan@gmail.com>
803fb7
Date: Fri, 22 May 2015 20:30:01 +0200
803fb7
Subject: [PATCH] udev/net_id: Only read the first 64 bytes of PCI config space
803fb7
803fb7
The original code used fread(), which on some libc implementions
803fb7
(ie glibc 2.17) would pre-read a full 4K (PAGE_SIZE) of the
803fb7
PCI config space, when only 64 bytes were requested.
803fb7
803fb7
I have recently come across PCIe hardware which responds with
803fb7
Completion Timeouts when accesses above 256 bytes are attempted.
803fb7
803fb7
This can cause server systems with GHES/AEPI support to cause
803fb7
and immediate kernel panic due to the failed PCI transaction.
803fb7
803fb7
This change replaces the buffered fread() with an explict
803fb7
unbuffered read() of 64 bytes, which corrects this issue by
803fb7
only reading the guaranteed first 64 bytes of PCIe config space.
803fb7
803fb7
(cherry picked from commit 0454229c100a2113ba82df55703436d6cb2c492b)
803fb7
803fb7
Cherry-picked from: 0454229
803fb7
Resolves: #1222517
803fb7
---
803fb7
 src/udev/udev-builtin-net_id.c | 9 +++++----
803fb7
 1 file changed, 5 insertions(+), 4 deletions(-)
803fb7
803fb7
diff --git a/src/udev/udev-builtin-net_id.c b/src/udev/udev-builtin-net_id.c
803fb7
index 66474f772..dd2886caf 100644
803fb7
--- a/src/udev/udev-builtin-net_id.c
803fb7
+++ b/src/udev/udev-builtin-net_id.c
803fb7
@@ -91,6 +91,7 @@
803fb7
 #include <stdlib.h>
803fb7
 #include <stdarg.h>
803fb7
 #include <unistd.h>
803fb7
+#include <fcntl.h>
803fb7
 #include <string.h>
803fb7
 #include <errno.h>
803fb7
 #include <net/if.h>
803fb7
@@ -166,15 +167,15 @@ static int dev_pci_onboard(struct udev_device *dev, struct netnames *names) {
803fb7
 
803fb7
 /* read the 256 bytes PCI configuration space to check the multi-function bit */
803fb7
 static bool is_pci_multifunction(struct udev_device *dev) {
803fb7
-        _cleanup_fclose_ FILE *f = NULL;
803fb7
+        _cleanup_close_ int fd = -1;
803fb7
         const char *filename;
803fb7
         uint8_t config[64];
803fb7
 
803fb7
         filename = strjoina(udev_device_get_syspath(dev), "/config");
803fb7
-        f = fopen(filename, "re");
803fb7
-        if (!f)
803fb7
+        fd = open(filename, O_RDONLY | O_CLOEXEC);
803fb7
+        if (fd < 0)
803fb7
                 return false;
803fb7
-        if (fread(&config, sizeof(config), 1, f) != 1)
803fb7
+        if (read(fd, &config, sizeof(config)) != sizeof(config))
803fb7
                 return false;
803fb7
 
803fb7
         /* bit 0-6 header type, bit 7 multi/single function device */