kernelnewbies.kernelnewbies.org archive mirror
 help / color / mirror / Atom feed
From: chrishell <chris@chrishell.de>
To: kernelnewbies@kernelnewbies.org
Subject: Re: linked list within a kernel probe
Date: Sun, 8 Jan 2023 23:24:41 +0100	[thread overview]
Message-ID: <77ba5293-292c-9163-9a54-a2066e93fe14@chrishell.de> (raw)
In-Reply-To: <75bc2d47-a2f9-187b-8ac8-e0ee2c10226a@chrishell.de>

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.

Thanks in advance

BR /Christian



Am 03.01.23 um 19:52 schrieb chrishell:
> Hello out there, I have an issue with a linked list which holds pointers 
> to memory pages for a kprobe. The linked list get initialised but I 
> cannot use it within the kprobe.
> 
> I use main or head pointer to hold everything in one place:
> 
> struct kprobe_head {
>      struct list_head    *p_mem_cache;
>      struct kprobe_fsops    *pfops;
>      struct kprobe         *pProbe;
> };
> 
> and the pointer to access everything:
> 
> static struct kprobe_head *pHead;
> 
> then I have the structure which this list is made of:
> 
> struct kprobe_mem_cache {
> 
>      void            *p_page;
>      __u32            size;
>      __u8            dirty;
>      struct list_head    list_element;
> };
> 
> 
> the list looks like:
>                      ____________________   _________________
>                      |                  |<-|                 |<-|
> pHead->p_mem_cache->| kprobe_mem_cache |->| krobe_mem_cache |->| ...
>                      --------------------  -------------------
> 
> 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@kernelnewbies.org
> https://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies
> 


_______________________________________________
Kernelnewbies mailing list
Kernelnewbies@kernelnewbies.org
https://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies

  reply	other threads:[~2023-01-08 22:25 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-01-03 18:52 linked list within a kernel probe chrishell
2023-01-08 22:24 ` chrishell [this message]
2023-01-09 16:15   ` Billie Alsup (balsup)
2023-01-12 14:48     ` chrishell
2023-01-09 17:56   ` Tom Mitchell
2023-01-12 15:05     ` chrishell

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=77ba5293-292c-9163-9a54-a2066e93fe14@chrishell.de \
    --to=chris@chrishell.de \
    --cc=kernelnewbies@kernelnewbies.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).