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