mirror of
https://github.com/valitydev/osquery-1.git
synced 2024-11-07 18:08:53 +00:00
Adding mem to Linux filesystem lib
This commit is contained in:
parent
b7852650c2
commit
6b6649bbd4
@ -191,5 +191,29 @@ Status procDescriptors(const std::string& process,
|
||||
Status procReadDescriptor(const std::string& process,
|
||||
const std::string& descriptor,
|
||||
std::string& result);
|
||||
|
||||
/**
|
||||
* @brief Read bytes from Linux's raw memory.
|
||||
*
|
||||
* Most Linux kernels include a device node /dev/mem that allows priviledged
|
||||
* users to map or seek/read pages of physical memory.
|
||||
* osquery discourages the use of physical memory reads for security and
|
||||
* performance reasons and must first try safer methods for data parsing
|
||||
* such as /sys and /proc.
|
||||
*
|
||||
* A platform user may disable physical memory reads:
|
||||
* --disable_memory=true
|
||||
* This flag/option will cause readRawMemory to forcefully fail.
|
||||
*
|
||||
* @param base The absolute memory address to read from. This does not need
|
||||
* to be page alined, readRawMem will take care of alignment and only
|
||||
* return the requested start address and size.
|
||||
* @param length The length of the buffer with a max of 0x10000.
|
||||
* @param buffer The output buffer, caller is responsible for resources if
|
||||
* readRawMem returns success.
|
||||
* @return status The status of the read.
|
||||
*/
|
||||
Status readRawMem(size_t base, size_t length, void** buffer);
|
||||
|
||||
#endif
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ if(APPLE)
|
||||
ADD_OSQUERY_CORE_LINK("-framework Foundation")
|
||||
elseif(UBUNTU OR CENTOS)
|
||||
ADD_OSQUERY_CORE_LIBRARY(osquery_filesystem_linux
|
||||
linux/mem.cpp
|
||||
linux/proc.cpp
|
||||
)
|
||||
endif()
|
||||
|
115
osquery/filesystem/linux/mem.cpp
Normal file
115
osquery/filesystem/linux/mem.cpp
Normal file
@ -0,0 +1,115 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <sys/mman.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <osquery/filesystem.h>
|
||||
#include <osquery/flags.h>
|
||||
#include <osquery/logger.h>
|
||||
|
||||
namespace osquery {
|
||||
|
||||
#define kLinuxMaxMemRead 0x10000
|
||||
|
||||
const std::string kLinuxMemPath = "/dev/mem";
|
||||
|
||||
DEFINE_osquery_flag(bool,
|
||||
disable_memory,
|
||||
false,
|
||||
"Disable physical memory reads.");
|
||||
|
||||
int readMem(int fd, size_t base, size_t length, uint8_t* buffer) {
|
||||
if (lseek(fd, base, SEEK_SET) == -1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Read from raw memory until an unrecoverable read error or the requested
|
||||
// bytes are read.
|
||||
size_t total_read = 0;
|
||||
size_t bytes_read = 0;
|
||||
while (total_read != length && bytes_read != 0) {
|
||||
bytes_read = read(fd, buffer + total_read, length - total_read);
|
||||
if (bytes_read == -1) {
|
||||
if (errno != EINTR) {
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
total_read += bytes_read;
|
||||
}
|
||||
}
|
||||
|
||||
// The read finished without reading the requested number of bytes.
|
||||
if (total_read != length) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Status readRawMem(size_t base, size_t length, void** buffer) {
|
||||
*buffer = 0;
|
||||
|
||||
if (!FLAGS_disable_memory) {
|
||||
return Status(1, "Configuration has disabled physical memory reads");
|
||||
}
|
||||
|
||||
if (length > kLinuxMaxMemRead) {
|
||||
return Status(1, "Cowardly refusing to read a large number of bytes");
|
||||
}
|
||||
|
||||
auto status = isReadable(kLinuxMemPath);
|
||||
if (!status.ok()) {
|
||||
// For non-su users *hopefully* raw memory is not readable.
|
||||
return status;
|
||||
}
|
||||
|
||||
int fd = open(kLinuxMemPath.c_str(), O_RDONLY);
|
||||
if (fd < 0) {
|
||||
return Status(1, std::string("Cannot open ") + kLinuxMemPath);
|
||||
}
|
||||
|
||||
if ((*buffer = malloc(length)) == nullptr) {
|
||||
close(fd);
|
||||
return Status(1, "Cannot allocate memory for read");
|
||||
}
|
||||
|
||||
#ifdef _SC_PAGESIZE
|
||||
size_t offset = base % sysconf(_SC_PAGESIZE);
|
||||
#else
|
||||
// getpagesize() is more or less deprecated.
|
||||
size_t offset = base % getpagesize();
|
||||
#endif
|
||||
|
||||
// Use memmap for maximum portability over read().
|
||||
auto map = mmap(0, offset + length, PROT_READ, MAP_SHARED, fd, base - offset);
|
||||
if (map == MAP_FAILED) {
|
||||
// Could fallback to a lseek/read.
|
||||
if (readMem(fd, base, length, (uint8_t*)*buffer) == -1) {
|
||||
close(fd);
|
||||
free(*buffer);
|
||||
return Status(1, "Cannot memory map or seek/read memory");
|
||||
}
|
||||
} else {
|
||||
// Memory map succeeded, copy and unmap.
|
||||
memcpy(*buffer, (uint8_t*)map + offset, length);
|
||||
if (munmap(map, offset + length) == -1) {
|
||||
LOG(WARNING) << "Unable to unmap raw memory";
|
||||
}
|
||||
}
|
||||
|
||||
close(fd);
|
||||
return Status(0, "OK");
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user