<div dir="ltr">Thanks for the tip! <br></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Tue, May 2, 2023 at 10:18 PM Alexander Kapshuk <<a href="mailto:alexander.kapshuk@gmail.com">alexander.kapshuk@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">On Tue, May 2, 2023 at 6:35 PM Abdul Matin<br>
<<a href="mailto:abdulmatincuetcse17@gmail.com" target="_blank">abdulmatincuetcse17@gmail.com</a>> wrote:<br>
><br>
> I'm initializing the memory for skbPrev at module init function:<br>
><br>
> static int __init nf_conntrack_my_mod_init(void)<br>
> {<br>
>     saddr_m = (union nf_inet_addr* ) kmalloc(sizeof(union nf_inet_addr), GFP_KERNEL);<br>
>     skbPrev = (struct sk_buff*) kmalloc(sizeof(struct sk_buff), GFP_KERNEL);<br>
>     if (saddr_m == NULL) {<br>
>       printk(KERN_INFO "Can not allocate space for saddr\n");<br>
>       return -ENOMEM;<br>
>     }<br>
>     if(skbPrev == NULL) {<br>
>       printk(KERN_INFO "Can not allocate space for skbPrev\n");<br>
>       return -ENOMEM;<br>
>     }<br>
><br>
> On Tue, May 2, 2023 at 8:23 PM Alexander Kapshuk <<a href="mailto:alexander.kapshuk@gmail.com" target="_blank">alexander.kapshuk@gmail.com</a>> wrote:<br>
>><br>
>> On Tue, May 2, 2023 at 3:26 PM Abdul Matin<br>
>> <<a href="mailto:abdulmatincuetcse17@gmail.com" target="_blank">abdulmatincuetcse17@gmail.com</a>> wrote:<br>
>> ><br>
>> > Hi.<br>
>> > I'm writing a netfilter module where I need to copy a sk_buff in a global variable that I use in another subsequent call. But I crashed the whole kernel. I've tried to add a code snippet to share with you how I'm doing it.<br>
>> ><br>
>> > here case1 is always true before case2 (i.e. 1st call of help -> case1 is true, 2nd call of help -> case2 true).<br>
>> > So, in the 2nd call, case2 is true where we're using exp, ctinfoPrev, saddr_m which have been initialized before in case1.<br>
>> ><br>
>> > union nf_inet_addr *saddr_m;<br>
>> > struct sk_buff* skbPrev;<br>
>><br>
>> This declares a pointer to struct sk_buff which is uninitialised and<br>
>> most probably set to NULL by the compiler.<br>
>> Where do you allocate memory for skbPrev?<br>
>><br>
>> > enum ip_conntrack_info ctinfoPrev;<br>
>> > struct nf_conntrack_expect *exp;<br>
>> ><br>
>> > static int help(struct sk_buff *skb,<br>
>> >     unsigned int protoff,<br>
>> >     struct nf_conn *ct,<br>
>> >     enum ip_conntrack_info ctinfo)<br>
>> > {<br>
>> >      switch (msgType) {<br>
>> >     case case1:<br>
>> ><br>
>> >     ctinfoPrev = ctinfo;<br>
>> >     memcpy((void *)skbPrev, (const void *)skb, sizeof(skb));<br>
>><br>
>> The NULL pointer dereference probably happens here, as memcpy attempts<br>
>>  to copy data from skb to skbPrev, which is likely to be NULL.<br>
>><br>
>> >     skbPrev->next = (struct sk_buff*) kmalloc(sizeof(struct sk_buff), GFP_KERNEL);<br>
>> >     skbPrev->prev = (struct sk_buff*) kmalloc(sizeof(struct sk_buff), GFP_KERNEL);<br>
>> >     skbPrev->sk = (struct sock*) kmalloc(sizeof(struct sock), GFP_KERNEL);<br>
>> >     memcpy((void *)(skbPrev->next), (const void *)skb->next, sizeof(skb->next));<br>
>> >     memcpy((void *)(skbPrev->prev), (const void *)skb->prev, sizeof(skb->prev));<br>
>> >    memcpy((void *)(skbPrev->sk), (const void *)skb->sk, sizeof(skb->sk));<br>
>> ><br>
>> >     unsigned int type = (dptr[0] << 8) | dptr[1]; // little endian<br>
>> >     unsigned int length = (dptr[2] << 8) | dptr[3];<br>
>> >     printk(KERN_INFO "type: %hu length: %hu", type, length);<br>
>> ><br>
>> >     unsigned int ip;<br>
>> >     memcpy(&ip, dptr, 4);<br>
>> >     ip = ntohl(ip) ^ MAGIC_COOKIE_VALUE_HOST;<br>
>> >     exp = nf_ct_expect_alloc(ct);<br>
>> >     if (exp == NULL) {<br>
>> >         printk( KERN_INFO "cannot alloc expectation");<br>
>> >         return NF_DROP;<br>
>> >     }<br>
>> >     tuple = &ct->tuplehash[IP_CT_DIR_REPLY].tuple;<br>
>> >     nf_ct_expect_init(exp, NF_CT_EXPECT_CLASS_DEFAULT,<br>
>> >     nf_ct_l3num(ct),<br>
>> >     saddr_m, &tuple->dst.u3,<br>
>> >     IPPROTO_UDP, NULL, &tuple->dst.u.udp.port);<br>
>> ><br>
>> >     pr_debug("expect: ");<br>
>> >     nf_ct_dump_tuple(&exp->tuple);<br>
>> ><br>
>> ><br>
>> >     break;<br>
>> >    case case2:<br>
>> >     printk(KERN_INFO "createpermission response\n");<br>
>> >     nf_nat_tftp = rcu_dereference(nf_nat_tftp_hook);<br>
>> >     if (nf_nat_tftp && ct->status & IPS_NAT_MASK)<br>
>> >     ret= nf_nat_tftp(skbPrev, ctinfoPrev, exp);<br>
>> >     else if (nf_ct_expect_related(exp, 0) != 0) {<br>
>> >     printk( KERN_INFO "cannot add expectation");<br>
>> >     nf_ct_helper_log(skb, ct, "cannot add expectation");<br>
>> >     ret = NF_DROP;<br>
>> >     }<br>
>> >    nf_ct_expect_put(exp);<br>
>> >    break;<br>
>> >    }<br>
>> >    return ret;<br>
>> >   }<br>
>> > I got this log before crash: 1,589,5743337757,-;BUG: kernel NULL pointer dereference, address: 0000000000000000<br>
>> > 1,590,5743337860,-;#PF: supervisor read access in kernel mode<br>
>> > 1,591,5743337880,-;#PF: error_code(0x0000) - not-present page<br>
>> > 6,592,5743337900,-;PGD 0 P4D 0<br>
>> > 4,593,5743337974,-;Oops: 0000 [#1] SMP PTI<br>
>> ><br>
>> > Is there anything wrong I am doing in copying and initializing?<br>
>> ><br>
>> > _______________________________________________<br>
>> > Kernelnewbies mailing list<br>
>> > <a href="mailto:Kernelnewbies@kernelnewbies.org" target="_blank">Kernelnewbies@kernelnewbies.org</a><br>
>> > <a href="https://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies" rel="noreferrer" target="_blank">https://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies</a><br>
<br>
I see.<br>
Without seeing the code in its entirety it's hard to tell which<br>
pointer is being null-dereferenced.<br>
Examine the OOPS output. The answer may very well be there.<br>
Otherwise, you want to add some pr_info() or printk() calls around the<br>
pointers being dereferenced in your code and see if any of those are<br>
set to NULL.<br>
</blockquote></div>