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