Fixed buffer overflow for cmdline strings of length >= 80

This commit is contained in:
Corbin Hughes
2015-10-04 02:54:24 -05:00
parent 580c412099
commit e798b3e3ce
3 changed files with 56 additions and 40 deletions

View File

@@ -39,6 +39,12 @@
extern bool bughuntmode; extern bool bughuntmode;
// Not sure, but assuming there's no more PID's than go into 64 unsigned bits..
const int MAX_PID_LENGTH = 20;
// Max length of filenames in /proc/<pid>/fd/*. These are numeric, so 10 digits seems like a safe assumption.
const int MAX_FDLINK = 10;
/* maps from inode to program-struct */ /* maps from inode to program-struct */
std::map <unsigned long, prg_node *> inodeproc; std::map <unsigned long, prg_node *> inodeproc;
@@ -73,46 +79,59 @@ int str2int (const char * ptr) {
return retval; return retval;
} }
// Not sure, but assuming there's no more PID's than go into 64 unsigned bits.. static std::string read_file (int fd) {
#define MAX_PID_LENGTH 20 char buf[255];
std::string content;
char * getprogname (pid_t pid) { for (int length; (length = read(fd, buf, sizeof(buf))) > 0;) {
int bufsize = 80; if (length < 0) {
char buffer [bufsize]; std::fprintf(stderr, "Error reading file: %s\n", std::strerror(errno));
std::exit(34);
}
content.append(buf, length);
}
int maxfilenamelen = 14 + MAX_PID_LENGTH + 1; return content;
char filename[maxfilenamelen]; }
static std::string read_file (const char* filepath) {
int fd = open(filepath, O_RDONLY);
snprintf (filename, maxfilenamelen, "/proc/%d/cmdline", pid);
int fd = open(filename, O_RDONLY);
if (fd < 0) { if (fd < 0) {
fprintf (stderr, "Error opening %s: %s\n", filename, strerror(errno)); std::fprintf(stderr, "Error opening %s: %s\n", filepath, std::strerror(errno));
exit(3); std::exit(3);
return NULL; return NULL;
} }
int length = read (fd, buffer, bufsize);
std::string contents = read_file(fd);
if (close(fd)) { if (close(fd)) {
std::cout << "Error closing file: " << strerror(errno) << std::endl; std::fprintf(stderr, "Error opening %s: %s\n", filepath, std::strerror(errno));
exit(34); std::exit(34);
}
if (length < bufsize - 1)
buffer[length]='\0';
return strdup(buffer);
} }
void setnode (unsigned long inode, pid_t pid) return contents;
{ }
std::string getprogname (pid_t pid) {
const int maxfilenamelen = 14 + MAX_PID_LENGTH + 1;
char filename[maxfilenamelen];
std::snprintf(filename, maxfilenamelen, "/proc/%d/cmdline", pid);
return read_file(filename);
}
void setnode (unsigned long inode, pid_t pid) {
prg_node * current_value = inodeproc[inode]; prg_node * current_value = inodeproc[inode];
if (current_value == NULL || current_value->pid != pid) { if (current_value == NULL || current_value->pid != pid) {
prg_node * newnode = (prg_node *) malloc (sizeof (struct prg_node)); prg_node * newnode = new prg_node;
newnode->inode = inode; newnode->inode = inode;
newnode->pid = pid; newnode->pid = pid;
newnode->name = getprogname(pid); newnode->name = getprogname(pid);
inodeproc[inode] = newnode; inodeproc[inode] = newnode;
free(current_value); delete current_value;
} }
} }
@@ -122,9 +141,6 @@ void get_info_by_linkname (const char * pid, const char * linkname) {
} }
} }
// Max length of filenames in /proc/<pid>/fd/*. These are numeric, so 10 digits seems like a safe assumption.
#define MAX_FDLINK 10
/* updates the `inodeproc' inode-to-prg_node /* updates the `inodeproc' inode-to-prg_node
* for all inodes belonging to this PID * for all inodes belonging to this PID
* (/proc/pid/fd/42) * (/proc/pid/fd/42)

View File

@@ -30,7 +30,7 @@
struct prg_node { struct prg_node {
long inode; long inode;
pid_t pid; pid_t pid;
char * name; std::string name;
}; };
struct prg_node * findPID (unsigned long inode); struct prg_node * findPID (unsigned long inode);

View File

@@ -165,7 +165,7 @@ Process * getProcess (unsigned long inode, const char * devicename)
if (proc != NULL) if (proc != NULL)
return proc; return proc;
Process * newproc = new Process (inode, devicename, node->name); Process * newproc = new Process (inode, devicename, node->name.c_str());
newproc->pid = node->pid; newproc->pid = node->pid;
char procdir [100]; char procdir [100];