Skip to content

Commit c97d1ca

Browse files
HuO50lian-bo
authored andcommitted
Fix the failure of opening "/dev/mem": Permission denied
The "/dev/mem" may be disabled(e.g kernel enables lockdown), which makes python-dmidecode has no permission to access the "/dev/mem". As a result, python-dmidecode will report an error as below: ** COLLECTED WARNINGS ** Failed to open memory buffer (/dev/mem): Permission denied No SMBIOS nor DMI entry point found, sorry. ** END OF WARNINGS ** Let's try to read the sysfs tables if the "/dev/mem" is unavailable. Resolves: #15 Signed-off-by: Zhongze Hu <[email protected]>
1 parent f0a089a commit c97d1ca

File tree

8 files changed

+703
-246
lines changed

8 files changed

+703
-246
lines changed

src/dmidecode.c

Lines changed: 89 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -5197,7 +5197,7 @@ dmi_codes_major *find_dmiMajor(const struct dmi_header *h)
51975197
return NULL;
51985198
}
51995199

5200-
static void dmi_table(Log_t *logp, int type, u32 base, u16 len, u16 num, u16 ver, const char *devmem, xmlNode *xmlnode)
5200+
static void dmi_table(Log_t *logp, int type, u32 base, u16 len, u16 num, u16 ver, const char *devmem, u32 flags, xmlNode *xmlnode)
52015201
{
52025202
static u8 version_added = 0;
52035203
u8 *buf;
@@ -5221,35 +5221,40 @@ static void dmi_table(Log_t *logp, int type, u32 base, u16 len, u16 num, u16 ver
52215221
info_n = NULL;
52225222
}
52235223

5224-
if((buf = mem_chunk(logp, base, len, devmem)) == NULL) {
5225-
log_append(logp, LOGFL_NODUPS, LOG_WARNING, "Table is unreachable, sorry."
5226-
#ifndef USE_MMAP
5227-
"Try compiling dmidecode with -DUSE_MMAP."
5228-
#endif
5229-
);
5230-
return;
5231-
}
5224+
if(flags & FLAG_NO_FILE_OFFSET){
5225+
/*
5226+
* When reading from sysfs or from a dump file, the file may be
5227+
* shorter than announced. For SMBIOS v3 this is expcted, as we
5228+
* only know the maximum table size, not the actual table size.
5229+
* For older implementations (and for SMBIOS v3 too), this
5230+
* would be the result of the kernel truncating the table on
5231+
* parse error.
5232+
*/
5233+
size_t size = len;
5234+
buf = read_file(logp, flags & FLAG_NO_FILE_OFFSET ? 0 : base, &size, devmem);
5235+
if (num && size != (size_t)len){
5236+
log_append(logp, LOGFL_NODUPS, LOG_WARNING, "Wrong DMI structures length: %i bytes announced, only %lu bytes available.\n", len, (unsigned long)size );
5237+
}
5238+
len = size;
5239+
} else {
5240+
buf = mem_chunk(logp, base, len, devmem);
5241+
}
5242+
5243+
if (ver > SUPPORTED_SMBIOS_VER){
5244+
log_append(logp, LOGFL_NODUPS, LOG_WARNING, "# SMBIOS implementations newer than version %u.%u are not\n", "# fully supported by this version of dmidecode.\n", SUPPORTED_SMBIOS_VER >> 8, SUPPORTED_SMBIOS_VER & 0xFF);
5245+
}
52325246

5233-
if (ver > SUPPORTED_SMBIOS_VER) {
5234-
log_append(logp, LOGFL_NODUPS, LOG_WARNING,
5235-
"# SMBIOS implementations newer than version %u.%u are not\n"
5236-
"# fully supported by this version of dmidecode.\n",
5237-
SUPPORTED_SMBIOS_VER >> 8, SUPPORTED_SMBIOS_VER & 0xFF);
5238-
}
5239-
// FIXME: This is hackerish ... rather try to avoid looping dmi_table() calls too much
52405247
if( version_added == 0 ) {
52415248
dmixml_AddAttribute(xmlnode, "smbios_version", "%u.%u", ver >> 8, ver & 0xFF);
52425249
version_added = 1;
52435250
}
52445251

5245-
data = buf;
5246-
while(i < num && data + 4 <= buf + len) { /* 4 is the length of an SMBIOS structure header */
5247-
5252+
data = buf;
5253+
while(i < num && data + 4 <= buf + len) { /* 4 is the length of an SMBIOS structure header */
52485254
u8 *next;
52495255
struct dmi_header h;
52505256

52515257
to_dmi_header(&h, data);
5252-
52535258
/*
52545259
** If a short entry is found (less than 4 bytes), not only it
52555260
** is invalid, but we cannot reliably locate the next entry.
@@ -5258,8 +5263,8 @@ static void dmi_table(Log_t *logp, int type, u32 base, u16 len, u16 num, u16 ver
52585263
*/
52595264
if(h.length < 4) {
52605265
log_append(logp, LOGFL_NORMAL, LOG_WARNING,
5261-
"Invalid entry length (%i) for type %i. DMI table is broken! Stop.",
5262-
(unsigned int)h.length, type);
5266+
"Invalid entry length (%i) for type %i. DMI table is broken! Stop.",
5267+
(unsigned int)h.length, type);
52635268
break;
52645269
}
52655270

@@ -5278,7 +5283,6 @@ static void dmi_table(Log_t *logp, int type, u32 base, u16 len, u16 num, u16 ver
52785283
next++;
52795284
}
52805285
next += 2;
5281-
52825286
xmlNode *handle_n = NULL;
52835287
if( h.type == type ) {
52845288
if(next - buf <= len) {
@@ -5309,6 +5313,7 @@ static void dmi_table(Log_t *logp, int type, u32 base, u16 len, u16 num, u16 ver
53095313
dmixml_AddAttribute(handle_n, "length", "%i", (next - buf));
53105314
dmixml_AddAttribute(handle_n, "expected_length", "%i", len);
53115315

5316+
53125317
log_append(logp, LOGFL_NODUPS, LOG_WARNING,
53135318
"DMI/SMBIOS type 0x%02X is exceeding the expected buffer "
53145319
"size by %i bytes. Will not decode this entry.",
@@ -5344,6 +5349,60 @@ static void dmi_table(Log_t *logp, int type, u32 base, u16 len, u16 num, u16 ver
53445349
free(buf);
53455350
}
53465351

5352+
int _smbios3_decode_check(u8 *buf){
5353+
int check = (!checksum(buf, buf[0x06])) ? 0 : 1;
5354+
return check;
5355+
}
5356+
5357+
xmlNode *smbios3_decode_get_version(u8 * buf, const char *devmem)
5358+
{
5359+
int check = _smbios3_decode_check(buf);
5360+
5361+
xmlNode *data_n = xmlNewNode(NULL, (xmlChar *) "DMIversion");
5362+
assert( data_n != NULL );
5363+
5364+
dmixml_AddAttribute(data_n, "type", "SMBIOS");
5365+
5366+
if(check == 1) {
5367+
u16 ver = (buf[0x07] << 16) + (buf[0x08] << 8) + buf[0x09];
5368+
5369+
dmixml_AddTextContent(data_n, "SMBIOS %i.%i.%i present", buf[0x07], buf[0x08], buf[0x09]);
5370+
dmixml_AddAttribute(data_n, "version", "%i.%i.%i", buf[0x07], buf[0x08],buf[0x09]);
5371+
} else if(check == 0) {
5372+
dmixml_AddTextContent(data_n, "No SMBIOS nor DMI entry point found");
5373+
dmixml_AddAttribute(data_n, "unknown", "1");
5374+
}
5375+
return data_n;
5376+
}
5377+
5378+
int smbios3_decode(Log_t *logp, int type, u8 *buf, const char *devmem, u32 flags, xmlNode *xmlnode)
5379+
{
5380+
u32 ver;
5381+
u64 offset;
5382+
5383+
/* Don't let checksum run beyond the buffer */
5384+
if (buf[0x06] > 0x20)
5385+
{
5386+
return 0;
5387+
}
5388+
5389+
int check = _smbios3_decode_check(buf);
5390+
if (check == 1)
5391+
{
5392+
ver = (buf[0x07] << 16) + (buf[0x08] << 8) + buf[0x09];
5393+
offset = QWORD(buf + 0x10);
5394+
5395+
if (!(flags & FLAG_NO_FILE_OFFSET) && offset.h && sizeof(off_t) < 8)
5396+
{
5397+
return 0;
5398+
}
5399+
5400+
dmi_table(logp, type, ((off_t)offset.h << 32) | offset.l, DWORD(buf+0x0C), 0, ver, devmem, flags | FLAG_STOP_AT_EOT, xmlnode);
5401+
}
5402+
5403+
return check;
5404+
}
5405+
53475406
int _smbios_decode_check(u8 * buf)
53485407
{
53495408
int check = (!checksum(buf, buf[0x05]) || memcmp(buf + 0x10, "_DMI_", 5) != 0 ||
@@ -5370,7 +5429,8 @@ xmlNode *smbios_decode_get_version(u8 * buf, const char *devmem)
53705429
_M = 0;
53715430
switch (ver) {
53725431
case 0x021F:
5373-
_m = 31;
5432+
case 0x0221:
5433+
_m = ver & 0xFF;
53745434
_M = 3;
53755435
ver = 0x0203;
53765436
break;
@@ -5396,7 +5456,7 @@ xmlNode *smbios_decode_get_version(u8 * buf, const char *devmem)
53965456
return data_n;
53975457
}
53985458

5399-
int smbios_decode(Log_t *logp, int type, u8 *buf, const char *devmem, xmlNode *xmlnode)
5459+
int smbios_decode(Log_t *logp, int type, u8 *buf, const char *devmem, u32 flags, xmlNode *xmlnode)
54005460
{
54015461
int check = _smbios_decode_check(buf);
54025462

@@ -5405,6 +5465,7 @@ int smbios_decode(Log_t *logp, int type, u8 *buf, const char *devmem, xmlNode *x
54055465

54065466
switch (ver) {
54075467
case 0x021F:
5468+
case 0x0221:
54085469
ver = 0x0203;
54095470
break;
54105471
case 0x0233:
@@ -5413,7 +5474,7 @@ int smbios_decode(Log_t *logp, int type, u8 *buf, const char *devmem, xmlNode *x
54135474
}
54145475
// printf(">>%d @ %d, %d<<\n", DWORD(buf+0x18), WORD(buf+0x16), WORD(buf+0x1C));
54155476
dmi_table(logp, type, DWORD(buf + 0x18), WORD(buf + 0x16), WORD(buf + 0x1C), ver, devmem,
5416-
xmlnode);
5477+
flags, xmlnode);
54175478
}
54185479
return check;
54195480
}
@@ -5451,13 +5512,13 @@ xmlNode *legacy_decode_get_version(u8 * buf, const char *devmem)
54515512
return data_n;
54525513
}
54535514

5454-
int legacy_decode(Log_t *logp, int type, u8 *buf, const char *devmem, xmlNode *xmlnode)
5515+
int legacy_decode(Log_t *logp, int type, u8 *buf, const char *devmem, u32 flags, xmlNode *xmlnode)
54555516
{
54565517
int check = _legacy_decode_check(buf);
54575518

54585519
if(check == 1)
54595520
dmi_table(logp, type, DWORD(buf + 0x08), WORD(buf + 0x06), WORD(buf + 0x0C),
5460-
((buf[0x0E] & 0xF0) << 4) + (buf[0x0E] & 0x0F), devmem, xmlnode);
5521+
((buf[0x0E] & 0xF0) << 4) + (buf[0x0E] & 0x0F), devmem, flags, xmlnode);
54615522
return check;
54625523
}
54635524

src/dmidecode.h

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,13 @@
2323
#include "dmihelper.h"
2424
#include "dmierror.h"
2525

26+
#define FLAG_NO_FILE_OFFSET (1 << 0)
27+
#define FLAG_STOP_AT_EOT (1 << 1)
28+
29+
#define SYS_FIRMWARE_DIR "/sys/firmware/dmi/tables"
30+
#define SYS_ENTRY_FILE SYS_FIRMWARE_DIR "/smbios_entry_point"
31+
#define SYS_TABLE_FILE SYS_FIRMWARE_DIR "/DMI"
32+
2633
struct dmi_header {
2734
u8 type;
2835
u8 length;
@@ -34,10 +41,12 @@ void dmi_dump(xmlNode *node, struct dmi_header * h);
3441
xmlNode *dmi_decode(xmlNode *parent_n, dmi_codes_major *dmiMajor, struct dmi_header * h, u16 ver);
3542
void to_dmi_header(struct dmi_header *h, u8 * data);
3643

44+
xmlNode *smbios3_decode_get_version(u8 * buf, const char *devmem);
3745
xmlNode *smbios_decode_get_version(u8 * buf, const char *devmem);
3846
xmlNode *legacy_decode_get_version(u8 * buf, const char *devmem);
39-
int smbios_decode(Log_t *logp, int type, u8 *buf, const char *devmem, xmlNode *xmlnode);
40-
int legacy_decode(Log_t *logp, int type, u8 *buf, const char *devmem, xmlNode *xmlnode);
47+
int smbios3_decode(Log_t *logp, int type, u8 *buf, const char *devmem, u32 flags, xmlNode *xmlnode);
48+
int smbios_decode(Log_t *logp, int type, u8 *buf, const char *devmem, u32 flags, xmlNode *xmlnode);
49+
int legacy_decode(Log_t *logp, int type, u8 *buf, const char *devmem, u32 flags, xmlNode *xmlnode);
4150

4251
const char *dmi_string(const struct dmi_header *dm, u8 s);
4352
void dmi_system_uuid(xmlNode *node, const u8 * p, u16 ver);

0 commit comments

Comments
 (0)