write a kld in FreeBSD - freebsd

I'm writing a new KLD in FreeBSD.
I have a C file like this:
Question about writing my own system call in FreeBSD -- but my code's functionality is a bit different. I'm initializing a variable in kernelspace and my function name is my_KLD.
I can load it without problem with "kldload", but I have a problem: I'm going to use this kld through another C file.
The file structure is like this:
int
main(int argc, char **argv)
{
f ( atoi(argv[1]) ;
}
f ( int x) {
printf("hi\n");
int syscall_num ;
struct module_stat stat ;
stat.version = sizeof(stat) ;
modstat (modfind("my_KLD") , &stat) ;
syscall_num = stat.data.intval ;
return syscall (syscall_num , x ) ;
}
But when I call this file with argument x
the result is :
hi
Bad System call (core dumped)
What else should I do?

In addition to the comment from Srh BlueOcean, you should also check the value returned by modfind(). You're assuming it can find your KLD and that's a big assumption. The KLD may not be loaded for whatever reason.
I find smaller steps are better, so call modfind and print out the integer ID to see if it is positive or negative (-1 is an error).
Something like this:
int modid;
if ((modid = modfind("my_KLD")) < 0) {
perror("modfind failed");
exit(1);
}
if (modstat(modid, &stat) < 0) {
perror("modstat failed");
exit(1);
}
The perror() function will provide you with an error message and you can check the man-page to determine what caused the error. For example, ENOENT is "The module was not found (probably not loaded)."

Related

Why does the syscall "process_vm_readv" sets errno to "success"?

I am trying to implement a debugger in Python 3. The main idea is pretty simple: wrap the syscall "process_vm_readv" with ctypes and then call it on other process.
I also created a small dummy C++ program for me to debug with this tool. Here's the source for both of them:
Debugger
#!/usr/bin/python3
import typing
import ctypes
import os
libc = ctypes.cdll.LoadLibrary("libc.so.6")
def _error_checker(result, function, arguments):
if result == -1:
errno = ctypes.get_errno()
raise OSError(errno, os.strerror(errno))
class IOBuffer(ctypes.Structure): # iovec struct
_fields_ = [("base", ctypes.c_void_p),
("size", ctypes.c_size_t)]
_read_process_memory = libc.process_vm_readv
_read_process_memory.restype = ctypes.c_ssize_t
_read_process_memory.errcheck = _error_checker
_read_process_memory.args = [ctypes.c_ulong, ctypes.POINTER(IOBuffer),
ctypes.c_ulong, ctypes.POINTER(IOBuffer),
ctypes.c_ulong, ctypes.c_ulong]
def read_process_memory(pid: int, base: int, size: int) -> typing.Tuple[int, bytes]:
buffer = (ctypes.c_char * size)()
local = IOBuffer(ctypes.addressof(buffer), size)
remote = IOBuffer(base, size)
return _read_process_memory(pid, local, 1, remote, 1, 0), buffer.raw
Dummy Program
#include <iostream>
#include <stdio.h>
using namespace std;
int main(void){
int a = 99;
int c;
while((c = getchar()) != EOF)
cout << "int a=" << a << ";\t&a=" << &a << endl;
return 0;
}
My problem lies in the fact that whenever I call "read_process_memory" with my dummy program's pid, the memory address it supplies me and the number 4 (the size of an int) as arguments - which should work - the wrapped syscall returns -1 (error). When that happens, errcheck reports the errno for that operation, which always ends up being zero. "Error Success". Due to this unhelpful error message I don't know how to fix this issue. Do you guys have any thoughts on how this can be fixed?
Due to this unhelpful error message I don't know how to fix this issue
You can always find out the real error returned by the kernel with strace. Something like this should work:
strace -e process_vm_readv python test.py
As suggested by Employed Russian's answer, I ran my debugging tool with strace -e process_vm_readv prepended in the command line. It gave me the following error:
process_vm_readv(3464,
[{iov_base=NULL, iov_len=0},
{iov_base=NULL, iov_len=0},
{iov_base=0x7f9d39c0c4f8, iov_len=140313255527400},
{iov_base=0xfffffffffffffffa, iov_len=4}],
4, 0x1, 140726046508276, 4)
= -1 EINVAL (Invalid argument)
After fiddling around with the code for a bit, I got this error to be gone, by changing the read_process_memory function to:
def read_process_memory(pid: int, base: int, size: int) -> typing.Tuple[int, bytes]:
buffer = (ctypes.c_char * size)()
local = (IOBuffer * 1)()
local[0].base, local[0].size = ctypes.addressof(buffer), size
remote = (IOBuffer * 1)()
remote[0].base, remote[0].size = base, size
return _read_process_memory(pid, local, 1, remote, 1, 0), buffer.raw
My only problem now was that strace was throwing at me the following error:
process_vm_readv(3464,
[{iov_base=0x7fedc6f64450, iov_len=4}], 1,
[{iov_base=0x7ffd560344f4, iov_len=4}], 1, 0)
= -1 EPERM (Operation not permitted)
To which I responded by running it all as root, solving this last issue.
Edit: As suggested by Mark Tolonen, instead of declaring two arrays of size one in read_process_memory, both structures could be passed to the wrapped function using ctypes.byref as follows:
def read_process_memory(pid: int, base: int, size: int) -> typing.Tuple[int, bytes]:
buffer = (ctypes.c_char * size)()
local = IOBuffer(ctypes.addressof(buffer), size)
remote = IOBuffer(base, size)
return _read_process_memory(pid, ctypes.byref(local), 1, ctypes.byref(remote), 1, 0), buffer.raw

'echo' calls .write function INFINITE times

Context
I wrote a Linux device driver in which the functions read and write are implemented. The problem is with the function write, here the portion of the code:
ssize_t LED_01_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos)
{
int retval = 0;
PDEBUG(" reading from user space -> wrinting in kernel space\n");
//struct hello_dev *dev = filp->private_data;
if (count > COMMAND_MAX_LENGHT){
printk(KERN_WARNING "[LEO] LED_01: trying to write more than possible. Aborting write\n");
retval = -EFBIG;
goto out;
}
if (down_interruptible(&(LED_01_devices->sem_LED_01))){
printk(KERN_WARNING "[LEO] LED_01: Device was busy. Operation aborted\n");
return -ERESTARTSYS;
}
if (copy_from_user((void*)&(LED_01_devices-> LED_value), buf, count)) {
printk(KERN_WARNING "[LEO] LED_01: can't use copy_from_user. \n");
retval = -EPERM;
goto out_and_Vsem;
}
write_status_to_LED();
PDEBUG(" Value instert: %u \n", LED_01_devices-> LED_value);
out_and_Vsem:
write_times++;
up(&(LED_01_devices->sem_LED_01));
out:
return retval;
}
Question
If I use the module in a C compiled program, it works properly, as expected.
When I execute echo -n 1 > /dev/LED_01 (from the Command LINE), it writes INFINITE times and, even with the Ctrl+C it doesn't stop. I need to reboot.
Here the snipped code of the test function that works properly:
// ON
result = write(fd, (void*) ON_VALUE, 1);
if ( result != 0 ){
printf("Oh dear, something went wrong with write()! %s\n", strerror(errno));
}
else{
printf("write operation executed succesfully (%u)\n",ON_VALUE[0]);
}
Is the problem in the driver or in the way I use echo?
If you need to whole source code, all the file used are stored in this git repository folder
Value returned by the kernel's .write function is interpreted as:
error code, if it is less than zero (<0),
number of bytes written, if it is more than or equal to zero (>=0)
So, for tell user that all bytes has been written, .write function should return its count parameter.
In case of .write function, returning zero has a little sense: every "standard" utility like echo will just call write() function again.

Is there a standard format for /sys/devices/system/cpu/cpu0/topology/thread_siblings_list?

Considering the following command.
cat /sys/devices/system/cpu/cpu0/topology/thread_siblings_list
When I run this command on my laptop running Ubuntu 16.04, I get the following output.
0,1
However, when I run it on a server running Debian 8, I get the following output.
0-1
Is the standard format or set of standard formats for this pseudo-file documented somewhere?
I searched in the Documentation directory under the kernel source and did not find a description.
There doesn't seem to be an documented way but turbostat, an internal program and part of linux-tools, expects the format to be:
A number, followed by any character as seperator, ..., the last number.
The current version is here.
/*
* get_cpu_position_in_core(cpu)
* return the position of the CPU among its HT siblings in the core
* return -1 if the sibling is not in list
*/
int get_cpu_position_in_core(int cpu)
{
char path[64];
FILE *filep;
int this_cpu;
char character;
int i;
sprintf(path,
"/sys/devices/system/cpu/cpu%d/topology/thread_siblings_list",
cpu);
filep = fopen(path, "r");
if (filep == NULL) {
perror(path);
exit(1);
}
for (i = 0; i < topo.num_threads_per_core; i++) {
fscanf(filep, "%d", &this_cpu);
if (this_cpu == cpu) {
fclose(filep);
return i;
}
/* Account for no separator after last thread*/
if (i != (topo.num_threads_per_core - 1))
fscanf(filep, "%c", &character);
}
fclose(filep);
return -1;
}

How can I get argv from "struct linux_binprm"?

I want to extract all argv from an existing struct linux_binprm. On kernel 3.4, I tried this piece of code: http://www.mail-archive.com/kernelnewbies#nl.linux.org/msg00278.html in do_excve_common, but it doesn't work. It returns (null). What is the problem and how can I get ALL the arguments in a char * string?
. If you want to get the full command line before the binary loader executing in do_execve_common(), you can try following:
there is one argument *argv in the function do_execve_common() parameter table, why bother to get the argv from "struct linux_binprm"? You can use the *argv directly with following codes. In the do_execve_common(), insert some codes as following:
argc = count(argv, MAX_ARG_STRINGS);
i = 0;
while (i < argc)
{
const char __user *str;
int len;
ret = -EFAULT;
str = get_user_arg_ptr(argv, i);
if (IS_ERR(str))
goto out;
len = strnlen_user(str, MAX_ARG_STRLEN);
if (!len)
goto out;
//copy the str to kernel temporary storage
//NOTE: tmp[] is a string array,
// the memory should have been allocated already for strings storage,
// each string is ended with \0
memcpy(tmp[i], str, len)
}
After executing these codes, I think the argv strings will be all saved in tmp[] array.
. While if you want to get the full command line after binary loader executing, I think at this time the argument page has been setup correctly, then you can try following approach to get the full command line:
There is a function proc_pid_cmdline() in ./fs/proc/base.c file, you can re-use most codes in proc_pid_cmdline() function to get the full command line from the argument page.

How to get the size of a gunzipped file in vim

When viewing (or editing) a .gz file, vim knows to locate gunzip and display the file properly.
In such cases, getfsize(expand("%")) would be the size of the gzipped file.
Is there a way to get the size of the expanded file?
[EDIT]
Another way to solve this might be getting the size of current buffer, but there seems to be no such function in vim. Am I missing something?
There's no easy way to get the uncompressed size of a gzipped file, short of uncompressing it and using the getfsize() function. That might not be what you want. I took at a look at RFC 1952 - GZIP File Format Specification, and the only thing that might be useful is the ISIZE field, which contains "...the size of the original (uncompressed) input data modulo 2^32".
EDIT:
I don't know if this helps, but here's some proof-of-concept C code I threw together that retrieves the value of the ISIZE field in a gzip'd file. It works for me using Linux and gcc, but your mileage may vary. If you compile the code, and then pass in a gzip'd filename as a parameter, it will tell you the uncompressed size of the original file.
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
int main(int argc, char *argv[])
{
FILE *fp = NULL;
int i=0;
if ( argc != 2 ) {
fprintf(stderr, "Must specify file to process.\n" );
return -1;
}
// Open the file for reading
if (( fp = fopen( argv[1], "r" )) == NULL ) {
fprintf( stderr, "Unable to open %s for reading: %s\n", argv[1], strerror(errno));
return -1;
}
// Look at the first two bytes and make sure it's a gzip file
int c1 = fgetc(fp);
int c2 = fgetc(fp);
if ( c1 != 0x1f || c2 != 0x8b ) {
fprintf( stderr, "File is not a gzipped file.\n" );
return -1;
}
// Seek to four bytes from the end of the file
fseek(fp, -4L, SEEK_END);
// Array containing the last four bytes
unsigned char read[4];
for (i=0; i<4; ++i ) {
int charRead = 0;
if ((charRead = fgetc(fp)) == EOF ) {
// This shouldn't happen
fprintf( stderr, "Read end-of-file" );
exit(1);
}
else
read[i] = (unsigned char)charRead;
}
// Copy the last four bytes into an int. This could also be done
// using a union.
int intval = 0;
memcpy( &intval, &read, 4 );
printf( "The uncompressed filesize was %d bytes (0x%02x hex)\n", intval, intval );
fclose(fp);
return 0;
}
This appears to work for getting the byte count of a buffer
(line2byte(line("$")+1)-1)
If you're on Unix/linux, try
:%!wc -c
That's in bytes. (It works on windows, if you have e.g. cygwin installed.) Then hit u to get your content back.
HTH
From within vim editor, try this:
<Esc>:!wc -c my_zip_file.gz
That will display you the number of bytes the file is having.

Resources