`do_sys_open` vs `__x86_sys_open` when attaching kprobe - system-calls

I have tried running opensnoop.py but using
fnname_open='do_sys_open'
(which I have seen in other scripts) instead of
fnname_open = b.get_syscall_prefix().decode() + 'open'
# = '__x86_sys_open' on Ubuntu 18.04
but the script then stops printing file names. What is causing the difference?
When using attach_kprobe(event=fn) is fn a system call or an event?
Do you get list of possible syscall from /proc/kallsyms as described here?

A BPF program attached to __x86_sys_open won't have the same result if you attach it to do_sys_open instead because those two functions don't have the same prototype:
long do_sys_open(int dfd, const char __user *filename, int flags, umode_t mode);
long sys_open(const char __user *filename, int flags, umode_t mode);
So the filename argument, for example, won't be stored in the same register depending on which function you trace. You will need to edit the BPF program as well to fix this.

Related

Libfuzzer target for on-disk parsing

I'm currently integrating libFuzzer in a project which parses files on the hard drive. I have some prior experience with AFL, where a command line like this one was used:
afl-fuzz -m500 -i input/ -o output/ -t100 -- program_to_fuzz ##
...where ## was a path to the generated input.
Looking at libFuzzer however, I see that the fuzz targets look like this:
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
DoSomethingInterestingWithMyAPI(Data, Size);
return 0; // Non-zero return values are reserved for future use.
}
I understand that the input isn't provided in the form of a file, but as a buffer in-memory instead. The problem is that the program I'm trying to fuzz works with files and obtains its data through fread() calls. At no point in time is the whole input supposed to be loaded in memory (where, in the general case, it might not even fit); so there's not much I can do with a const uint8_t*.
Writing the buffer back to the hard drive to get back a file seems extremely inefficient. Is there a way around this?
You can do as in this example from google security team.
The buf_to_file defined here takes your buffer and returns a char* pathname you can then pass to you target:
(from https://github.com/google/security-research-pocs/blob/master/autofuzz/fuzz_utils.h#L27 )
// Write the data provided in buf to a new temporary file. This function is
// meant to be called by LLVMFuzzerTestOneInput() for fuzz targets that only
// take file names (and not data) as input.
//
// Return the path of the newly created file or NULL on error. The caller should
// eventually free the returned buffer (see delete_file).
extern "C" char *buf_to_file(const uint8_t *buf, size_t size);
Be sure to free the ressource with the delete_file function.
You could use LD_PRELOAD and override fread.

reading data from sysfs

I am trying to provide DMA via PCI. For that purpose I have an example of sysfs driver. I succesfully stored data to RAM but unfortunately I cant read them. I have a functions store_dmaread and show_dmaread. I acces them via c code like this. The write function works fine but the show function which I open via read() works (reads the DMA data, prints them) but the user space buffer is not visible in that function.
char buf[2] = {3,3};
fw = open("/sys/bus/pci/devices/0000\:01\:00.0/dmaread", O_RDWR);
read (fw,buf, 2);
write (fw, buf, 2);
close(fw);
the function in the driver looks like this:
static ssize_t show_dmaread(struct device *dev, struct device_attribute *attr, char *buf)
{
printk("User space buffer value %d \n", buf[0]) // PRINTS 0
// MORE CODE WHICH WORKS
}
static ssize_t store_dmaread(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
// WORKS FINE THE ATTRIBUTE CHANGES ITS VALUE
}
Thanks a lot for help
From your question, it appears you are expecting that the char * buf passed to your show_dmaread function points directly to the userspace buffer passed to read (or at the very least has been populated with the data in the user-side buffer):
However, looking in Documentation/filesystem/sysfs.txt it says:
sysfs allocates a buffer of size (PAGE_SIZE) and passes it to the
method. Sysfs will call the method exactly once for each read or
write. This forces the following behavior on the method
implementations:
On read(2), the show() method should fill the entire buffer. Recall that an attribute should only be exporting one value, or an
array of similar values, so this shouldn't be that expensive.
This allows userspace to do partial reads and forward seeks
arbitrarily over the entire file at will. If userspace seeks back to
zero or does a pread(2) with an offset of '0' the show() method will
be called again, rearmed, to fill the buffer.
Which leads me to believe you are getting a newly allocated buffer and that some other kernel code manages copying your buffer back over to userspace.

Mach Injection: System call open is not getting interposed when injecting in Excel

I hooked system calls open, read, write, lstat etc. using osxinj project. Injected this into TextEdit application provided by apple and everything worked fine. When I opened new file using textedit, opencallback was called and messages were logged in system.log file.
typedef int (*open_type)(const char *, int, mode_t);
open_type open_func = 0;
int opencallback(const char* path, int oflag, mode_t mode)
{
syslog(LOG_ALERT, "In open...");
int returnVal = open_func(path, oflag, mode);
syslog(LOG_ALERT,"Open, ends\n");
return returnVal;
}
Injected into Excel and tried to override open system call using below code:
void* func_ptr = dlsym( RTLD_NEXT, "open");
if (func_ptr)
{
open_func = (open_type)func_ptr;
mach_error_t me = mach_override_ptr( func_ptr,
(void*)&opencallback,
(void**)&open_func);
}
opencallback is called when injecting to TextEdit but it is not getting called when injected in Microsoft Excel. But code written on same lines for other system calls read, write, lstat are getting interposed when injected in Excel.
Any thoughts on why open is not getting interposed when injected to Excel.
Finally, I got my code running. I am posting answer hoping it might help somebody.
I hooked __open which is an alias for open and it worked fine for i386 application like excel.

Linux DD passing data to serial port ttyS0

Hi i want to pass a data from my char device driver to serial port ttyS0..
I have created a simple char driver module which reads and write and it's my first tym doing it.. i am using debian guest os...
e.g.
echo "hello" > /dev/mydev
now when /dev/mydev receives the data it will then alter the string into something like "hello too" which is passed to my serial port /dev/ttyS0..
how can i alter the string?.. is it possible to use if statement inside mydev?
e.g
if(string=="hello"){
alterstringTO: hello to;
pass "hello to" /dev/ttyS0;
like echoing in terminal..
echo "hello to" > /dev/ttyS0
}
Is that possible?... or is there any other way doing it?
Here some of the code..
ssize_t dev_read(struct file *filp, char *buf, size_t clen, loff_t *f_pos){
short cnt =0;
while(clen && (msg[Pos]!=0))
{
put_user(msg[Pos],buf++);
cnt++;
clen--;
Pos++;
}
return cnt;
}
ssize_t dev_write(struct file *filp, const char *buf, size_t clen, loff_t *f_pos){
short dec = clen-1;
short cnt=0;
memset(msg,0,50);
Pos=0;
while(clen>0)
{
msg[cnt++] = buf[dec--];
clen--;
}
return cnt;
}
Thanks in advance..
Just a comment on writing to the serial port:
Remember the Linux foundations, everything is a file in Linux. To write to the device driver from a program you need to open the file for writing and then you can fprintf whatever data you want. You can do that from user space as well (the recommended way)
Refer to the following man pages:
man fopen
man fread/fwrite
man fprintf
man fclose
I'm not exactly sure what you are trying to achieve here, as the question and the intent seems unclear to me. I'll provide some guidance, but recommend that you edit your question and make it more readable.
Your snippet to compare strings is not correct. You can learn more about how to compare strings in C in here.
Altering a string in C is a basic operation that you learn when you start working with strings. This should help you getting started.
As final remark, please note that programming for the kernel requires extra care. A small mistake may lead to a crash and loss of data. If you really must, then the book Linux Device Drivers 3rd Edition is freely available and can help you further.

Send Return Code back from child script to the Parent script

My child script can create a rc=110 when a FTPed file is not located. The Parent script sets the Error Handling RC=1. I want the Error Handling to set to the RC created in child script. Any ideas?
What operating system? In linux you can forward the paramenter using standard input/output using the | (pipe)
./script | ./binaryName
This forwards the output of ./script as the input of ./binaryName
and in your main:
int main(int argc, char **argv){
//Don't use argv[0]!
char* yourOutput = argv[1];
return 0;
}
I just realized your "parent" is a script too. Which language is this? All the languages I've worked with have a manner to get arguements like I just showed you in C++.