Is there a way to inject code into an ELF binary without ptrace, I can't use it since the program I'm writing this for is using GDB and I don't want to stop the process for the while it's injecting. I read it's possible by using /proc/pid/mem but I couldn't quite find anything about how to do it. I don't want to use LD_PRELOAD either since it would require restarting the program and I'd want to do it during runtime.
EDIT: I can't use ptrace since the process might already be attached to by gdb
/proc/pid/mem behaves like an image of the process's memory. To read/write the process's memory, just open /proc/pid/mem, then lseek to the desired address and read() or write() however many bytes you want.
For instance, to overwrite the byte at address 0x12345 in the process with 0x90, you can just do
fd = open("/proc/XXX/mem", O_RDWR);
lseek(fd, 0x12345, SEEK_SET);
unsigned char new = 0x90;
write(fd, &new, 1);
On a 32-bit system, use lseek64 instead (and add #define _LARGEFILE64_SOURCE before the standard includes).
Note that accessing /proc/XXX/mem requires the same permissions as to ptrace the process. In particular, on some systems you may need to be root.
I decided I'd use process_vm_writev, which seems to work I don't know why it didn't want to write to /proc/pid/mem which is odd.
/**
* #brief write_process_memory Writes to the memory of a given process
* #param pid Program pid
* #param address The base memory address
* #param buffer Buffer to write
* #param n How many bytes to write
* #return Returns bytes written
*/
ssize_t write_process_memory(pid_t pid, void *address, void *buffer, ssize_t n) {
struct iovec local, remote;
/* this might have to be made so that if n > _SC_PAGESIZE
* local would be split into multiple locals, similar to how
* read_process_memory works, no fucking clue though if it's necessary */
remote.iov_base = address;
remote.iov_len = n;
local.iov_base = buffer;
local.iov_len = n;
ssize_t amount_read = process_vm_writev(pid, &local, 1, &remote, 1, 0);
return amount_read;
}
Related
The script file has over 6000 bytes which is copied into a buffer.The contents of the buffer are then written to the device connected to the serial port.However the write function only returns 4608 bytes whereas the buffer contains 6117 bytes.I'm unable to understand why this happens.
{
FILE *ptr;
long numbytes;
int i;
ptr=fopen("compass_script(1).4th","r");//Opening the script file
if(ptr==NULL)
return 1;
fseek(ptr,0,SEEK_END);
numbytes = ftell(ptr);//Number of bytes in the script
printf("number of bytes in the calibration script %ld\n",numbytes);
//Number of bytes in the script is 6117.
fseek(ptr,0,SEEK_SET);
char writebuffer[numbytes];//Creating a buffer to copy the file
if(writebuffer == NULL)
return 1;
int s=fread(writebuffer,sizeof(char),numbytes,ptr);
//Transferring contents into the buffer
perror("fread");
fclose(ptr);
fd = open("/dev/ttyUSB3",O_RDWR | O_NOCTTY | O_NONBLOCK);
//Opening serial port
speed_t baud=B115200;
struct termios serialset;//Setting a baud rate for communication
tcgetattr(fd,&serialset);
cfsetispeed(&serialset,baud);
cfsetospeed(&serialset,baud);
tcsetattr(fd,TCSANOW,&serialset);
long bytesw=0;
tcflush(fd,TCIFLUSH);
printf("\nnumbytes %ld",numbytes);
bytesw=write(fd,writebuffer,numbytes);
//Writing the script into the device connected to the serial port
printf("bytes written%ld\n",bytesw);//Only 4608 bytes are written
close (fd);
return 0;
}
Well, that's the specification. When you write to a file, your process normally is blocked until the whole data is written. And this means your process will run again only when all the data has been written to the disk buffers. This is not true for devices, as the device driver is the responsible of determining how much data is to be written in one pass. This means that, depending on the device driver, you'll get all data driven, only part of it, or even none at all. That simply depends on the device, and how the driver implements its control.
On the floor, device drivers normally have a limited amount of memory to fill buffers and are capable of a limited amount of data to be accepted. There are two policies here, the driver can block the process until more buffer space is available to process it, or it can return with a partial write only.
It's your program resposibility to accept a partial read and continue writing the rest of the buffer, or to pass back the problem to the client module and return only a partial write again. This approach is the most flexible one, and is the one implemented everywhere. Now you have a reason for your partial write, but the ball is on your roof, you have to decide what to do next.
Also, be careful, as you use long for the ftell() function call return value and int for the fwrite() function call... Although your amount of data is not huge and it's not probable that this values cannot be converted to long and int respectively, the return type of both calls is size_t and ssize_t resp. (like the speed_t type you use for the baudrate values) long can be 32bit and size_t a 64bit type.
The best thing you can do is to ensure the whole buffer is written by some code snippet like the next one:
char *p = buffer;
while (numbytes > 0) {
ssize_t n = write(fd, p, numbytes);
if (n < 0) {
perror("write");
/* driver signals some error */
return 1;
}
/* writing 0 bytes is weird, but possible, consider putting
* some code here to cope for that possibility. */
/* n >= 0 */
/* update pointer and numbytes */
p += n;
numbytes -= n;
}
/* if we get here, we have written all numbytes */
I'm trying to write a linux kernel module that can dump the contents of other modules to a /proc file (for analysis). In principle it works but it seems I run into some buffer limit or the like. I'm still rather new to Linux kernel development so I would also appreciate any suggestions not concerning the particular problem.
The memory that is used to store the module is allocated in this function:
char *get_module_dump(int module_num)
{
struct module *mod = unhiddenModules[module_num];
char *buffer;
buffer = kmalloc(mod->core_size * sizeof(char), GFP_KERNEL);
memcpy((void *)buffer, (void *)startOf(mod), mod->core_size);
return buffer;
}
'unhiddenModules' is an array of module structs
Then it is handed over to the proc creation here:
void create_module_dump_proc(int module_number)
{
struct proc_dir_entry *dump_module_proc;
dump_size = unhiddenModules[module_number]->core_size;
module_buffer = get_module_dump(module_number);
sprintf(current_dump_file_name, "%s_dump", unhiddenModules[module_number]->name);
dump_module_proc = proc_create_data(current_dump_file_name, 0, dump_proc_folder, &dump_fops, module_buffer);
}
The proc read function is as follows:
ssize_t dump_proc_read(struct file *filp, char *buf, size_t count, loff_t *offp)
{
char *data;
ssize_t ret;
data = PDE_DATA(file_inode(filp));
ret = copy_to_user(buf, data, dump_size);
*offp += dump_size - ret;
if (*offp > dump_size)
return 0;
else
return dump_size;
}
Smaller Modules are dumped correctly but if the module is larger than 126,796 bytes only the first 126,796 bytes are written and this error is displayed when reading from the proc file:
*** Error in `cat': free(): invalid next size (fast): 0x0000000001f4a040 ***
I've seem to run into some limit but I couldn't find anything on it. The error seems to be related so memory leaks but the buffer should be large enough so I don't see where this actually happens.
The procfs has a limit of PAGE_SIZE (one page) for read and write operations. Usually seq_file is used to iterate over the entries (modules in your case ?) to read and/or write smaller chunks. Since you are running into problems with only larger data, I suspect this is the case here.
Please have a look here and here if you are not familiar with seq_files.
A suspicious thing is that in dump_proc_read you are not using "count" parameter. I would have expected copy_to_user to take "count" as third argument instead of "dump_size" (and in subsequent calculations too). The way you do, always dump_size bytes are copied to user space, regardless the data size the application was expecting. The bigger dump_size is, the larger the user area that gets corrupted.
I'm using Sun RPC to implement a simple pseudo-distributed storage system. I have three instances of the same server, and one client on the same machine.
Server RPC implementation goes something like this:
char **
fileread64k_1_svc(char *filename, long offset, struct svc_req *rqstp)
{
static char * readResult;
//chunkName is a function of (fileName, offset)
FILE *chunkFile = fopen(chunkName, "r");
readResult = (char *) malloc(sizeof(char) * (CHUNKSIZE + 2));
fread(readResult, 1, CHUNKSIZE, chunkFile);
readResult[CHUNKSIZE] = '\0';
fclose(chunkFile);
return &readResult;
}
I give my client a list of files to read, and the client creates 3 threads (one for each instance of the server) and the threads distribute the files among them, and call the read RPC like this:
while all files are not read:
//pthread_mutex_lock(&lock);
char **out = fileread64k_1(fileName, offset, servers[id]);
//char *outData = *out;
//pthread_mutex_unlock(&lock);
But the data in out is replaced by another thread before I have a chance to process it. If I enable the commented lines (the mutex and the outData variable), I get the data in outData and I seem to be able to safely use it.
Can anyone explain why this happens and if there is a better workaround?
Because "readResult" is declared static. That means that all invocations of the method use the same space in memory for that variable, including concurrent invocations in different threads.
The problem should be taken care of if you just don't declare readResult as static -- but in that case, you won't be able to return its address, you should return the value of readResult itself.
Incidentally, which code has the responsibility of free()ing the allocated memory?
static ssize_t device_read (struct file* filp, char *bufStoreData, size_t bufCount, loff_t* curOffset)
{
printk(KERN_INFO"reading from the device");
ret = copy_to_user(bufStoreData,virtual_device.data,bufCount);
return ret;
}
does copy_to_user returns number of bytes remaining to read or number of bytes read?
whats the use of bufcount if i am using cat
if all the data is not read in single call how it can read the remaining data?Is this responsibility of application to issue system call again or the driver works automatically?
I need to understand this basic concept.
copy_to_user() returns the number of bytes that couldn't be copied to user space. If the complete buffer could be copied, it returns 0.
Normally, if !=0, means that there was some sort of memory problem (writting past a legal memory address), so these situations should be detected and reported to the user.
static ssize_t device_read (struct file* filp, char *bufStoreData,
size_t bufCount, loff_t* curOffset)
{
size_t bytes_to_copy;
printk(KERN_INFO"reading from the device");
/* do stuff to get device data into virtual_device.data . Also
update virtual_device.datasize */
bytes_to_copy = (virtual_device.datasize <= bufCount)?
virtual_device.datasize : bufCount;
/* note that I'm not using bufCount, but an hypothetical field in
virtual_device that gives me how much data the device has ready
for the user. I choose the lower of both */
/* Also recall that if the number of bytes requested by the user is
less than the number of bytes the device has generated, then the
next read should return the remainder of the device data, so the
driver should carry the count of how many bytes have been copied
to the user and how many are left. This is not covered in this
example. */
ret = copy_to_user(bufStoreData,virtual_device.data, bytes_to_copy);
if (ret != 0)
return -EPERM; /* if copy was not successful, report it */
return bytes_to_copy;
}
When the user issues ret = read (fd, buffer, sizebuff); it expects one of these things and should react accordingly:
ret is equal to sizebuff. That means that read could return all the data the user requested. Nothing else to do here.
ret is positive, but less than sizebuff. That means that the read gave the user some data, but not as much as he requested. The user process must re-issue the read syscall to retrieve the remaining data, if needed. Something like: ret = read (fd, buffer+ret, sizebuff-ret);
ret is 0. This means that the device has no more data to send. It's the EOF condition. User process should close the device.
ret is < 0. This is an error condition. User process must check errno and take appropiate measures.
Your device driver will have to return an appropiate value in device_read according to what happened to the device when it was read.
On the other hand, a process like cat expects to read as much as 4096 bytes per read call. If the device sends less than that, it will print the received data and will ask for more. cat will only stop if it receives a signal (Ctrl-C for example), or if a read call returns an unrecoverable error (such as ENODEVICE, which should be generated by your driver if such condition arises), or if reads 0 bytes (EOF condition).
A rather silly device that returns "Hello, world" to the user process. It employs some global data that must be reset in device_open function. Note that if several processes are going to use your device at the same time, these global data must be turned into instance data (using file->private_data). This device_read example shows how to deal with device buffers and user buffers, and how to keep track of bytes sent to the user, so the device never sends more data than it has, never sends more data than the user requests, and when the device runs out of data, it returns 0 to the user.
int curindx = 0; /* should be reset upon calling device_open */
static ssize_t device_read (struct file* filp, char *bufStoreData,
size_t bufCount, loff_t* curOffset)
{
size_t bytes_to_copy;
char device_data[]="Hello, world!\n";
size_t remaindersize;
remaindersize = strlen(device_data) - curindx;
bytes_to_copy = (remaindersize <= bufCount)?
remaindersize : bufCount;
ret = copy_to_user(bufStoreData,device_data+curindx, bytes_to_copy);
if (ret != 0)
return -EPERM; /* if copy was not successful, report it */
curindx += bytes_to_copy;
return bytes_to_copy;
}
1) does copy_to_user returns number of bytes remaining to read or number of bytes read?
copy_to_user returns a number of bytes that could not be copied.
2) whats the use of bufcount if i am using cat
bufCount is a number of bytes user can read. In other words, it's a buffer size of user space application. I guess cat uses multiple of PAGE_SIZE for buffer size, actually you can check it yourself by adding printk to your device_read() function:
print(KERN_INFO "bufCount=%ld\n", bufCount);
3) if all the data is not read in single call how it can read the remaining data? Is this responsibility of application to issue system call again or the driver works automatically?
User space programs use read() system call to read data from files (including block and character devices) which returns 0 only if the end of file is reached. That's how they know when to stop. So, yes, it's responsibility of user-space program to read remaining data (if it needs to).
ssize_t ret;
...
while ((ret = read(fd, buf, bufsize)) > 0) {...};
if (ret < 0)
error();
On the other hand, the responsibility of device driver is to correctly maintain offsets inside its internal structures and return values that make sense.
P/S:
I'd recommend you to read a book "Linux device drivers" which is freely available in internet (http://lwn.net/Kernel/LDD3/) and touches these topics in details.
as stated in: http://www.kernel.org/doc/htmldocs/kernel-hacking.html#routines-copy this functions "can" sleep.
So, do I always have to do a lock (e.g. with mutexes) when using this functions or are there exceptions?
I'm currently working on a module and saw some Kernel Oops at my system, but cannot reproduce them. I have a feeling they are fired because I'm currently do no locking around copy_[to/from]_user(). Maybe I'm wrong, but it smells like it has something to do with it.
I have something like:
static unsigned char user_buffer[BUFFER_SIZE];
static ssize_t mcom_write (struct file *file, const char *buf, size_t length, loff_t *offset) {
ssize_t retval;
size_t writeCount = (length < BUFFER_SIZE) ? length : BUFFER_SIZE;
memset((void*)&user_buffer, 0x00, sizeof user_buffer);
if (copy_from_user((void*)&user_buffer, buf, writeCount)) {
retval = -EFAULT;
return retval;
}
*offset += writeCount;
retval = writeCount;
cleanupNewline(user_buffer);
dispatch(user_buffer);
return retval;
}
Is this save to do so or do I need locking it from other accesses, while copy_from_user is running?
It's a char device I read and write from, and if a special packet in the network is received, there can be concurrent access to this buffer.
You need to do locking iff the kernel side data structure that you are copying to or from might go away otherwise - but it is that data structure you should be taking a lock on.
I am guessing your function mcom_write is a procfs write function (or similar) right? In that case, you most likely are writing to the procfs file, your program being blocked until mcom_write returns, so even if copy_[to/from]_user sleeps, your program wouldn't change the buffer.
You haven't stated how your program works so it is hard to say anything. If your program is multithreaded and one thread writes while another can change its data, then yes, you need locking, but between the threads of the user-space program not your kernel module.
If you have one thread writing, then your write to the procfs file would be blocked until mcom_write finishes so no locking is needed and your problem is somewhere else (unless there is something else that is wrong with this function, but it's not with copy_from_user)