On Sun, Jan 8, 2023 at 2:24 PM chrishell <chris@xxxxxxxxxxxx> wrote: > > To shorten my probblem description: I created a linked list within a > function, which is called in the module _init function. Right after > leaving this function I tested this list within the _init function, > which worked. But within the kprobe function, the access to that linked > list leads to kernel oops or even kernel panics > > Hope there is someone who can give me a hint. > Hint. Inside the kernel always address the issue of concurrency. Adding and removing from lists commonly needs a protective mutual exclusive lock. Look for like data structures and use the macro/standard tools to get it ALL correct including cache coherency. There are two strategies -- a data lock or a code monitor. https://www.geeksforgeeks.org/deadlock-starvation-and-livelock/ > > > > the p_page pointer is the pointer to the alloacted page. Therefore each > > element of that linked list holds a pointer to allocated memory segment. > > > > in the __init function I do, among other things, allocate some memory > > for that structure, thought a static struct would be also sufficient. > > > > /* create the head storage record */ > > pHead = (struct kprobe_head*) kzalloc(sizeof(struct kprobe_head), > > GFP_KERNEL); > > if(pHead == NULL) > > return -ENOMEM; > > > > then I create the linked list with this function: > > > > static __u8 _kprobe_setup_cache_elements( struct kprobe_head *pHead, > > __u16 elements, __u32 size) > > { > > unsigned int count = 0; > > __u8 rc = 0; > > struct list_head local_head; > > > > INIT_LIST_HEAD(&local_head); > > > > if(pHead != NULL) { > > > > pr_err("create list with %p\n", pHead); > > //INIT_LIST_HEAD(pHead->p_mem_cache); > > > > for(count=0; count<elements; count++) { > > struct kprobe_mem_cache *new = kzalloc(sizeof(struct > > kprobe_mem_cache), GFP_KERNEL); > > if(NULL == new) { > > pr_err("error: kzalloc issue"); > > return -ENOMEM; > > } > > > > /* allocate memory for one page */ > > new->p_page = vmalloc(size); > > if(NULL == new->p_page) { > > pr_err("error: vmalloc issue"); > > return -ENOMEM; > > } > > else { > > pr_err("List Element %d added Size: %u addr: %p \n", > > count, size, new->p_page); > > } > > > > new->size = size; > > new->dirty = 0; > > > > list_add_tail(&new->list_element, &local_head); > > } > > > > pHead->p_mem_cache = &local_head; > > } > > return rc; > > } > > > > right after that, still in the __init function I traverse trough this > > linked list, just to see if its work. > > > > if(pHead->p_mem_cache != NULL) > > { > > pr_err("within loop %p %p\n", pHead, pHead->p_mem_cache); > > list_for_each(local_head, pHead->p_mem_cache) { > > local_page = list_entry(local_head, struct > > kprobe_mem_cache, list_element); > > if(local_page->size) > > pr_err("address: %u \n", local_page->size ); > > } > > } > > > > > > And here it works. > > > > The problem now is that this is a kprobe kernel module and I defined a > > kprobe function as pre_handler function called submit_bio_pre which is > > evoked whenever the block layer function submit_bio is called by the > > kernel. Within that function however the access to that linked list failed > > > > int submit_bio_pre(struct kprobe *p_submit_bio, struct pt_regs *regs) > > { > > int rc = 0; > > struct bio *bio = NULL; > > static unsigned int len = 0; > > static unsigned int counter; > > struct kprobe_mem_cache *tmp = NULL; > > struct kprobe_mem_cache *local_page = NULL; > > struct list_head *local_head = NULL; > > > > bio = (struct bio*) regs_get_kernel_argument(regs, 0); > > > > if(pHead != NULL) > > pr_err("#### pHead is initialized %p #####\n", pHead); > > > > if(pHead->p_mem_cache != NULL) > > pr_err("#### pHead->p_mem_cache is initialized %p #######\n", > > pHead->p_mem_cache); > > > > if(pHead->p_mem_cache != NULL && counter == 0) > > { > > spin_lock(&sl); > > pr_err("within loop submit_bio_pre \n"); > > list_for_each(local_head, pHead->p_mem_cache) { > > local_page = list_entry(local_head, struct > > kprobe_mem_cache, list_element); > > if(local_page->size) > > pr_err("address bio: %u \n", local_page->size ); > > } > > spin_unlock(&sl); > > counter++; > > } > > > > As it seems is the head pointer valid and has the same address as in the > > init function. Also the head pointer to the linked list is a valid one. > > But traversing through the linked list is not possible any more. As you > > can see I added a spin_lock to that kprobe function, albeit I only read > > from the linked list. This function does something completely different > > normally anyway. > > > > When I load this module, the initialisation of the linked list works, > > also the following walk through the list, but within the kprobe function > > sometimes I can see the first and second pr_err. But after that the > > kernel breaks: > > > > [ 191.460196] Unable to handle kernel paging request at virtual address > > 000323bfa8c17bf5 > > > > [ 191.669571] Call trace: > > [ 191.672021] submit_bio_pre+0xcc/0x150 > > [ 191.676641] kprobe_breakpoint_handler+0x100/0x190 > > [ 191.681445] call_break_hook+0x68/0x80 > > [ 191.685201] brk_handler+0x1c/0x60 > > > > So can anybody tell me, what is the reason that the linked list doesn't > > work within the kprobe? > > > > Thank you in advance > > > > BR Christian > > > > > > _______________________________________________ > > Kernelnewbies mailing list > > Kernelnewbies@xxxxxxxxxxxxxxxxx > > https://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies > > > > > _______________________________________________ > Kernelnewbies mailing list > Kernelnewbies@xxxxxxxxxxxxxxxxx > https://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies _______________________________________________ Kernelnewbies mailing list Kernelnewbies@xxxxxxxxxxxxxxxxx https://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies