Memory management 如何将数据安全地附加到IPTables目标的sk_buff中

Memory management 如何将数据安全地附加到IPTables目标的sk_buff中,memory-management,linux-kernel,iptables,Memory Management,Linux Kernel,Iptables,我正在开发一个Linux内核模块,它需要修改网络数据包并附加一个额外的头。我已经实现了修改部分,重新计算了校验和,效果很好。但我不知道如何安全地附加一个额外的头。如果我的输入数据包类似于: ip-header / tcp-header / data if (skb_headroom(skb) < sizeof(struct newheader)) { printk("I got here!\n"); if (pskb_expand_head(skb, sizeof(str

我正在开发一个Linux内核模块,它需要修改网络数据包并附加一个额外的头。我已经实现了修改部分,重新计算了校验和,效果很好。但我不知道如何安全地附加一个额外的头。如果我的输入数据包类似于:

ip-header / tcp-header / data
if (skb_headroom(skb) < sizeof(struct newheader)) {
    printk("I got here!\n");
    if (pskb_expand_head(skb, sizeof(struct newheader) - skb_headroom(skb), 0, GPF_ATOMIC) != 0) {
        printk("And also here\n");
        return NF_DROP;
    }
}
我想要一个输出包,如:

ip-header / tcp-header / my-header / data
就我所读的内容而言,我想我需要以下代码。我在代码上写下了我的具体问题作为注释。我通常关心的是,我在这里写的代码是否是内存安全的,或者我应该如何做才能有一种内存安全的方式来附加新的头。此外,如果我做错了什么,或者有更好的方法来做,我也会感谢你的评论。我试着找一些例子,但到目前为止运气不好。代码如下:

static unsigned int my_iptables_target(struct sk_buff *skb, const struct xt_action_param *par) {
    const struct xt_mytarget_info *info = par->targinfo;
    /* Some code ... */

    if (!skb_make_writable(skb, skb->len)) {
        //Drop the packet
        return NF_DROP;
    }

    struct newheader* myheader;
    // Check if there is enough space and do something about it
    if (skb_headroom(skb) < sizeof(struct newheader)) {
        // So there is no enugh space.
        /* I don't know well what to put here. I read that a function called pskb_expand_head might
         * do the job. I do not understand very well how it works, or why it might fail (return value
         * different from zero). Does this code work:
         */
        if (pskb_expand_head(skb, sizeof(struct newheader) - skb_headroom(skb), 0, GPF_ATOMIC) != 0) {
            // What does it mean if the code reaches this point?
            return NF_DROP;
        }
    }
    // At this point, there should be enough space
    skb_push(skb, sizeof(struct newheader));

    /* I also think that skb_push() creates space at the beggining, to open space between the header and
     * the body I guess I must move the network/transport headers up. Perhaps something like this:
     */
    memcpy(skb->data, skb->data + sizeof(struct newheader), size_of_all_headers - sizeof(struct newheader));

    // Then set myheader address and fill data.
    myheader = skb->data + size_of_all_headers;

    //Then just set the new header, and recompute checksums.

    return XT_CONTINUE;
}
static unsigned int my_iptables_目标(struct sk_buff*skb,const struct xt_action_param*par){
const struct xt_mytarget_info*info=par->targetinfo;
/*一些代码*/
如果(!skb_使_可写(skb,skb->len)){
//丢包
返回NF_滴;
}
结构newheader*myheader;
//检查是否有足够的空间并采取措施
if(skb_净空(skb)data,skb->data+sizeof(struct newheader),size_of_all_headers-sizeof(struct newheader));
//然后设置myheader地址并填充数据。
myheader=skb->数据+所有头的大小;
//然后只需设置新的头,并重新计算校验和。
返回XT_继续;
}

我假设变量
size\u of_all\u headers
包含网络和传输头的大小(以字节为单位)。我还认为
memcpy
以递增的顺序复制字节,所以调用应该不会有问题。那么上面的代码有效吗?这是所有的记忆安全?有更好的方法吗?有没有这样的例子(或者你能提供一个例子)?

我使用了一个与问题中的代码类似的代码,到目前为止,它在我所做的所有测试中都非常有效。为了回答一些具体的问题,我使用了如下方法:

ip-header / tcp-header / data
if (skb_headroom(skb) < sizeof(struct newheader)) {
    printk("I got here!\n");
    if (pskb_expand_head(skb, sizeof(struct newheader) - skb_headroom(skb), 0, GPF_ATOMIC) != 0) {
        printk("And also here\n");
        return NF_DROP;
    }
}
if(skb_净空(skb)
但是没有一个print语句被执行过。我认为这是因为操作系统在内存中保留了足够的空间,这样在IP头的限制下就不会出现问题。但我认为最好留下if语句,以便在必要时增加数据包

我测试和使用的代码的另一个不同之处是,我没有向上移动所有其他头来为我的头创建空间,而是选择向下移动数据包的主体