0
votes

I have to reserve a large amount of kernel memory (1.5 MB) and share it with the user space. For the short story, I load my kernel module which allocates a large memory buffer in init function using kmalloc, then the user program call ioctl to retrieve the kernel memory address and remaps it using mmap because I need to share this memory between the two parts.

I would like to know if it's possible to cast this memory block as a structure and use the remaining memory as a data buffer and both parts would see the same structure. It's hard to explain exactly what I want so here is an example.

Here is the structure I want to share between the driver and the user space program :

typedef struct _MemoryBlock {
    int param1;
    int param2;
    short* vm_array1;
    short* km_array1;
    long* vm_array2;
    long* km_array2;
} MemoryBlock;

Structure used to retrieve memory addresses when calling ioctl :

typedef struct _MemStruct {
    void *address;    // Kernel memory address
    void *vmAddress;  // Virtual memory address
    size_t size;     // Size of the memory block
} MemStruct;

As I said, the kernel has allocated 1.5 MB of memory using kmalloc, user part then call ioctl and retrieve the kernel address of this memory block using MemStruct (which is updated by the driver and returned). The address field is the kernel address returned by kmalloc and vmAddress is set to NULL and will be updated after the call to mmap :

MemStruct *memStruct = malloc(sizeof(MemStruct));
ioctl(_This.fd, IOCTL_GET_MEM, (unsigned long) memStruct);

Then I have to remap this memory :

unsigned long mask = getpagesize() - 1;
off_t offset = ((unsigned long) memStruct->address) & ~mask;
memStruct->vmAddress = mmap(0, memStruct->size, PROT_READ | PROT_WRITE, MAP_SHARED, _This.fd, offset);

And in the user part I would like to do this :

MemoryBlock *memBlock = (MemoryBlock*) memStruct->vmAddress;
memBlock->param1 = 42;
memBlock->param2 = 0;
vm_array1 = (short*) (memStruct->vmAddress + sizeof(MemoryBlock));
km_array1 = (short*) (memStruct->address + sizeof(MemoryBlock));

int i; 
for (i = 0; i < 1000; i++) {
    vm_array1[i] = 42;
}

As you can see I use the remaining space of the memory (after the memory used by the structure) to declare a short array.

After that the driver could also access the same memory using the km_array1.

Is this possible ?

1

1 Answers

1
votes

I suppose that the field 'address' of your struct _Menstruct contains the value returned by kmalloc. In this case, this value does'nt have any visibility outside of the kernel space. In the user part, you creates a pointer to short type (km_array1) which points to the kernel address. You will probably have segfault or memory violation. You need to do the assignement in your kernel (km_array1 = (short*)(memstruct->address +sizeof(MemoryBlock)) try writing some random values in the kernel space with the km_array1 variable, and read them in the user part using vm_array1.