|
|
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 */
|