I enabled kmemleak and got a bunch of call traces like:
=====================================================================
unreferenced object 0xffff99144b13f600 (size 232):                              
                                                                                
                        
  comm "cat", pid 1100, jiffies 4294739144                                      
                                                                                
                        
  hex dump (first 32 bytes):                                                    
                                                                                
                        
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................           
                                                                                
                        
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................           
                                                                                
                        
  backtrace (crc 8540ec4f):                                                     
                                                                                
                        
    kmemleak_alloc+0x4a/0x90                                                    
                                                                                
                        
    kmem_cache_alloc_node+0x2ea/0x390                                           
                                                                                
                        
    __alloc_skb+0x174/0x1b0                                                     
                                                                                
                        
    audit_log_start+0x198/0x3d0                                                 
                                                                                
                        
    audit_log_proctitle+0x32/0x160                                              
                                                                                
                        
    audit_log_exit+0x6c6/0x780                                                  
                                                                                
                        
    __audit_syscall_exit+0xee/0x140                                             
                                                                                
                        
    syscall_exit_work+0x12b/0x150                                               
                                                                                
                        
    syscall_exit_to_user_mode_prepare+0x39/0x80                                 
                                                                                
                        
    syscall_exit_to_user_mode+0x11/0x260                                        
                                                                                
                        
    do_syscall_64+0x8c/0x180                                                    
                                                                                
                        
    entry_SYSCALL_64_after_hwframe+0x78/0x80
======================================================================

It indicates the skb allocated in audit_log_start is leaking.
 
Look into audit_log_end, when freeing skb, all skb are dequeued one by one from 
ab->skb_list and call __audit_log_end:
=====================================================
void audit_log_end(struct audit_buffer *ab)
{
        struct sk_buff *skb;

        if (!ab)
                return;

        while ((skb = skb_dequeue(&ab->skb_list)))
                __audit_log_end(skb);

        audit_buffer_free(ab);
}
=====================================================

In __audit_log_end:
=====================================================
static void __audit_log_end(struct sk_buff *skb)
{
        struct nlmsghdr *nlh;

        if (audit_rate_check()) {
                /* setup the netlink header, see the comments in
                 * kauditd_send_multicast_skb() for length quirks */
                nlh = nlmsg_hdr(skb);
                nlh->nlmsg_len = skb->len - NLMSG_HDRLEN;

                /* queue the netlink packet and poke the kauditd thread */
                skb_queue_tail(&audit_queue, skb);
                wake_up_interruptible(&kauditd_wait);
        } else
                audit_log_lost("rate limit exceeded");
}
=====================================================

If it doesn’t exceed the rate limit (audit_rate_check), the skb will be added 
to audit_queue and handled by the worker.
But if it exceeds the rate limit, nothing happens, then the skb is leak, 
because it’s already been dequeued from the list and no one is able to free it.

I checked the upstream lsm stacking, the latest version still has this issue:
https://github.com/cschaufler/lsm-stacking/blob/audit-6.17-rc1/kernel/audit.c#L2631

It should check rate limit first, if it doesn’t exceed the limit, then
dequeue the skb from the list, if it exceeds the limit, it should go to
audit_buffer_free which will free all skb in ab->skb_list

I’ve modified the code to check if it exceeds the rate limit before dequeuing 
the first skb from the skb_list and build a test kernel here:
https://launchpad.net/~gerald-yang-tw/+archive/ubuntu/audit-memleak

This is not ideal, because in audit_rate_check, it only considers adding one 
skb at a time and checks if it exceeds audit_rate_limit.
We should take all skb in skb_list into account instead of just one skb, 
otherwise it could exceed the rate limit a little bit.

But I think this is where the slab leak happens, I can not reproduce the issue 
with the above test kernel.
I'm checking if there is a better way to fix it and send a patch upstream.

If you would like to help run some tests, please use the above test
kernel and see if it fixes the slab leak, thanks!

To install the test kernel, please add the above test PPA and install the 
following test packages:
linux-image-unsigned-6.8.0-81-generic
linux-modules-6.8.0-81-generic
linux-modules-extra-6.8.0-81-generic

Regards,
Gerald

-- 
You received this bug notification because you are a member of Ubuntu
Bugs, which is subscribed to Ubuntu.
https://bugs.launchpad.net/bugs/2098730

Title:
  Kernel 6.8.0 memory leak

To manage notifications about this bug go to:
https://bugs.launchpad.net/ubuntu/+source/linux/+bug/2098730/+subscriptions


-- 
ubuntu-bugs mailing list
[email protected]
https://lists.ubuntu.com/mailman/listinfo/ubuntu-bugs

Reply via email to