Blame SOURCES/0216-udev-net_id-Only-read-the-first-64-bytes-of-PCI-conf.patch

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