Здравствуйте. В целях самообразования пишу модуль к netfilter. В целом ничего полезного модуль не делает, просто перехватывает пакет и посылает в ответ сформированный пакет. Все это безобразие работает в PREROUTING хуке таблицы raw, дабы не трогать лишний раз conntrack. Так же решил формировать фрейм полностью и отправлять с помощью dev_queue_xmit(), вместо использования ip_local_out().
#include <linux/module.h>
#include <linux/skbuff.h>
#include <linux/netfilter.h>
#include <net/tcp.h>
#include <linux/ip.h>
#include <linux/if_ether.h>
#include <linux/netfilter/x_tables.h>
MODULE_ALIAS("ipt_TEST");
MODULE_LICENSE("GPL");
static int send(struct sk_buff *oldskb)
{
struct sk_buff *newskb;
struct ethhdr *neweth;
struct ethhdr *oldeth;
struct iphdr *newiph;
struct iphdr *oldiph;
struct tcphdr *newth;
struct tcphdr *oldth;
oldeth = eth_hdr(oldskb);
oldiph = ip_hdr(oldskb);
oldth = (struct tcphdr *)(oldskb->data + oldiph->ihl * 4);
newskb = alloc_skb(sizeof(*neweth) + sizeof(*newiph) + sizeof(*newth), GFP_ATOMIC);
if (!newskb) {
goto out;
}
skb_reserve(newskb, sizeof(*neweth)+sizeof(*newiph)+sizeof(*newth));
newth = (struct tcphdr *)skb_push(newskb, sizeof(*newth));
newth->source = oldth->dest;
newth->dest = oldth->source;
newth->seq = htonl(1234567);
newth->ack_seq = htonl(ntohl(oldth->seq)+1);
tcp_flag_byte(newth) = (TCPHDR_RST);
newth->doff = sizeof(*newth) / 4;
newth->window = htons(32767);
newth->urg_ptr = 0;
newskb->ip_summed = CHECKSUM_UNNECESSARY;
newth->check = 0;
newiph =(struct iphdr *) skb_push(newskb, sizeof(*newiph));
newiph->version = 4;
newiph->ihl = sizeof(*newiph) / 4;
newiph->tos = oldiph->tos;
newiph->tot_len = oldiph->tot_len;
newiph->id = 0;
newiph->frag_off = htons(IP_DF);
newiph->ttl = 64;
newiph->protocol = IPPROTO_TCP;
newiph->check = 0;
newiph->saddr = oldiph->daddr;
newiph->daddr = oldiph->saddr;
newth->check = csum_tcpudp_magic(newiph->saddr, newiph->daddr,
sizeof(*newth), IPPROTO_TCP,
csum_partial(newth, sizeof(*newth), 0));
neweth = (struct ethhdr *)skb_push(newskb, sizeof(*neweth));
memcpy(neweth->h_dest, oldeth->h_source, ETH_ALEN);
memcpy(neweth->h_source, oldeth->h_dest, ETH_ALEN);
neweth->h_proto = oldeth->h_proto;
newskb->priority = oldskb->priority;
newskb->dev = oldskb->dev;
newskb->protocol = htons(ETH_P_IP);
newskb->len = sizeof(*neweth)+sizeof(*newiph)+sizeof(*newth);
printk(KERN_CRIT "Begin dev_queue_xmit.\n");
dev_queue_xmit(newskb);
goto out;
out:
if (oldskb);
kfree_skb(oldskb);
if (newskb)
kfree_skb(newskb);
}
unsigned int test_tg(struct sk_buff *skb) {
const struct iphdr *iph = ip_hdr(skb);
const struct tcphdr *th;
th = (const struct tcphdr *)(skb->data + iph->ihl * 4);
if ((tcp_flag_byte(th) & (TCPHDR_FIN | TCPHDR_RST | TCPHDR_ACK | TCPHDR_SYN)) == TCPHDR_SYN)
{
send(skb);
return NF_STOLEN;
}
return NF_DROP;
}
static struct xt_target test_tg_reg __read_mostly = {
.name = "TEST",
.revision = 0,
.family = NFPROTO_IPV4,
.target = test_tg,
.table = "raw",
.hooks = 1 << NF_INET_PRE_ROUTING,
.proto = IPPROTO_TCP,
.me = THIS_MODULE,
};
static int __init test_tg_init(void) {
return xt_register_target(&test_tg_reg);
}
static void __exit test_tg_exit(void) {
xt_unregister_target(&test_tg_reg);
}
module_init(test_tg_init);
module_exit(test_tg_exit);
Загружается модуль без проблем, правда когда пакет попадает ему на обработку ядро ловит oops. Ниже привожу call trace:
[ 506.836187] Begin dev_queue_xmit. [ 506.838360] protocol 0800 is buggy, dev eth0 [ 512.018091] BUG: unable to handle kernel paging request at 0002807c [ 512.020217] IP: [<f810c79a>] scsi_dispatch_cmd+0x74/0x1d0 [scsi_mod] [ 512.020217] *pde = 00000000 [ 512.020217] Oops: 0000 [#1] SMP [ 512.020217] last sysfs file: /sys/module/x_tables/initstate [ 512.020217] Modules linked in: xt_TEST xt_tcpudp iptable_raw ip_tables x_tables loop snd_intel8x0 tpm_tis tpm tpm_bios snd_ac97_codec ac97_bus snd_pcm joydev parport_pc pcspkr psmouse evdev parport snd_timer serio_raw battery ac button snd i2c_piix4 i2c_core soundcore snd_page_alloc ext3 jbd mbcache usbhid hid sd_mod ide_cd_mod cdrom crc_t10dif ata_generic ata_piix ahci libahci libata ohci_hcd ehci_hcd usbcore scsi_mod piix e1000 ide_core [last unloaded: scsi_wait_scan] [ 512.020217] [ 512.020217] Pid: 144, comm: kjournald Not tainted 2.6.39.4 #1 innotek GmbH VirtualBox [ 512.020217] EIP: 0060:[<f810c79a>] EFLAGS: 00010206 CPU: 0 [ 512.020217] EIP is at scsi_dispatch_cmd+0x74/0x1d0 [scsi_mod] [ 512.020217] EAX: 34800000 EBX: efcf3240 ECX: efc6a08c EDX: 34800000 [ 512.020217] ESI: 00028000 EDI: f6704860 EBP: efcf3240 ESP: f6725e58 [ 512.020217] DS: 007b ES: 007b FS: 00d8 GS: 00e0 SS: 0069 [ 512.020217] Process kjournald (pid: 144, ti=f6724000 task=efc10820 task.ti=f6724000) [ 512.020217] Stack: [ 512.020217] efc1b400 efc1ac00 f6704860 f81112b2 efc1c408 efc1b428 efc6a000 efc1b4b8 [ 512.020217] efc1c5f4 f6725ec0 efc1c408 00000000 00000001 c112b14a c112f6a1 00000002 [ 512.020217] f6725ec0 efc1c408 00000002 00000000 c112f81b f6725ec0 00000246 00000000 [ 512.020217] Call Trace: [ 512.020217] [<f81112b2>] ? scsi_request_fn+0x31a/0x44e [scsi_mod] [ 512.020217] [<c112b14a>] ? __blk_run_queue+0x11/0x12 [ 512.020217] [<c112f6a1>] ? queue_unplugged+0x64/0x72 [ 512.020217] [<c112f81b>] ? blk_flush_plug_list+0x16c/0x17e [ 512.020217] [<c112f837>] ? blk_finish_plug+0xa/0x24 [ 512.020217] [<f8334c45>] ? journal_commit_transaction+0x412/0xc21 [jbd] [ 512.020217] [<c10394f7>] ? try_to_del_timer_sync+0x5c/0x63 [ 512.020217] [<c10394f7>] ? try_to_del_timer_sync+0x5c/0x63 [ 512.020217] [<f8337104>] ? kjournald+0xb5/0x1cc [jbd] [ 512.020217] [<c1044692>] ? wake_up_bit+0x56/0x56 [ 512.020217] [<f833704f>] ? commit_timeout+0x5/0x5 [jbd] [ 512.020217] [<c104433c>] ? kthread+0x63/0x68 [ 512.020217] [<c10442d9>] ? kthread_worker_fn+0x114/0x114 [ 512.020217] [<c126517e>] ? kernel_thread_helper+0x6/0xd [ 512.020217] Code: 00 00 68 37 cd 11 f8 e9 54 01 00 00 8a 42 61 84 c0 74 18 3c 03 7f 14 8b 4b 30 8b 52 4c 8a 41 01 c1 e2 05 83 e0 1f 09 d0 88 41 01 [ 512.020217] 7e 7c 00 8b be 80 00 00 00 74 2c a1 40 5a 34 c1 81 c7 f4 01 [ 512.020217] EIP: [<f810c79a>] scsi_dispatch_cmd+0x74/0x1d0 [scsi_mod] SS:ESP 0069:f6725e58 [ 512.020217] CR2: 000000000002807c [ 512.277079] ---[ end trace 51f1ebb813964968 ]--- [ 512.280000] BUG: unable to handle kernel NULL pointer dereference at (null) [ 512.280979] IP: [<f810ce27>] scsi_get_command+0x53/0x78 [scsi_mod] [ 512.280979] *pde = 00000000 [ 512.280979] Oops: 0002 [#2] SMP [ 512.280979] last sysfs file: /sys/module/x_tables/initstate [ 512.280979] Modules linked in: xt_TEST xt_tcpudp iptable_raw ip_tables x_tables loop snd_intel8x0 tpm_tis tpm tpm_bios snd_ac97_codec ac97_bus snd_pcm joydev parport_pc pcspkr psmouse evdev parport snd_timer serio_raw battery ac button snd i2c_piix4 i2c_core soundcore snd_page_alloc ext3 jbd mbcache usbhid hid sd_mod ide_cd_mod cdrom crc_t10dif ata_generic ata_piix ahci libahci libata ohci_hcd ehci_hcd usbcore scsi_mod piix e1000 ide_core [last unloaded: scsi_wait_scan] [ 512.280979] [ 512.280979] Pid: 1301, comm: kworker/0:0 Tainted: G D 2.6.39.4 #1 innotek GmbH VirtualBox [ 512.280979] EIP: 0060:[<f810ce27>] EFLAGS: 00010082 CPU: 0 [ 512.280979] EIP is at scsi_get_command+0x53/0x78 [scsi_mod] [ 512.280979] EAX: 000000d6 EBX: efc1b400 ECX: 00000000 EDX: 00009955 [ 512.280979] ESI: efc1b420 EDI: efc1b41c EBP: efc1b404 ESP: f644beb8 [ 512.280979] DS: 007b ES: 007b FS: 00d8 GS: 00e0 SS: 0068 [ 512.280979] Process kworker/0:0 (pid: 1301, ti=f644a000 task=f652dc70 task.ti=f644a000) [ 512.280979] Stack: [ 512.280979] 00000020 00000000 efc6a948 efc1b400 00001000 f81118c2 015b19e8 00000000 [ 512.280979] f6756800 f828b0b7 efc6a948 efc6a948 efc6a948 feb28187 feb281a4 00000008 [ 512.280979] 00000202 feb130ec efc1b400 f828ae19 f6803040 efc6a948 efc1c408 efc1c408 [ 512.280979] Call Trace: [ 512.280979] [<f81118c2>] ? scsi_setup_fs_cmnd+0x53/0x9b [scsi_mod] [ 512.280979] [<f828b0b7>] ? sd_prep_fn+0x29e/0xb5a [sd_mod] [ 512.280979] [<f828ae19>] ? sd_unprep_fn+0x22/0x22 [sd_mod] [ 512.280979] [<c112e86a>] ? blk_peek_request+0xb6/0x182 [ 512.280979] [<f8111004>] ? scsi_request_fn+0x6c/0x44e [scsi_mod] [ 512.280979] [<c112b14a>] ? __blk_run_queue+0x11/0x12 [ 512.280979] [<c113829b>] ? cfq_kick_queue+0x20/0x31 [ 512.280979] [<c10401dc>] ? process_one_work+0x181/0x25e [ 512.280979] [<c113827b>] ? cfq_init_queue+0x28b/0x28b [ 512.280979] [<c1041b68>] ? worker_thread+0xf3/0x1f4 [ 512.280979] [<c1041a75>] ? manage_workers+0x15a/0x15a [ 512.280979] [<c104433c>] ? kthread+0x63/0x68 [ 512.280979] [<c10442d9>] ? kthread_worker_fn+0x114/0x114 [ 512.280979] [<c126517e>] ? kernel_thread_helper+0x6/0xd [ 512.280979] Code: ff 85 c0 89 c3 74 39 8d 68 04 8d 7e 1c 89 30 89 68 04 89 68 08 89 f8 e8 98 26 15 c9 8b 4e 24 89 6e 24 83 c6 20 89 73 04 89 4b 08 [ 512.280979] 29 89 c2 89 f8 e8 c4 26 15 c9 a1 40 5a 34 c1 89 43 1c eb 07 [ 512.280979] EIP: [<f810ce27>] scsi_get_command+0x53/0x78 [scsi_mod] SS:ESP 0068:f644beb8 [ 512.280979] CR2: 0000000000000000 [ 512.280979] ---[ end trace 51f1ebb813964969 ]--- [ 512.955684] BUG: unable to handle kernel paging request at fffffffc [ 512.957861] IP: [<c1044062>] kthread_data+0x6/0xa [ 512.957861] *pde = 01401067 *pte = 00000000 [ 512.957861] Oops: 0000 [#3] SMP [ 512.957861] last sysfs file: /sys/module/x_tables/initstate [ 512.957861] Modules linked in: xt_TEST xt_tcpudp iptable_raw ip_tables x_tables loop snd_intel8x0 tpm_tis tpm tpm_bios snd_ac97_codec ac97_bus snd_pcm joydev parport_pc pcspkr psmouse evdev parport snd_timer serio_raw battery ac button snd i2c_piix4 i2c_core soundcore snd_page_alloc ext3 jbd mbcache usbhid hid sd_mod ide_cd_mod cdrom crc_t10dif ata_generic ata_piix ahci libahci libata ohci_hcd ehci_hcd usbcore scsi_mod piix e1000 ide_core [last unloaded: scsi_wait_scan] [ 512.957861] [ 512.957861] Pid: 1301, comm: kworker/0:0 Tainted: G D 2.6.39.4 #1 innotek GmbH VirtualBox [ 512.957861] EIP: 0060:[<c1044062>] EFLAGS: 00010096 CPU: 0 [ 512.957861] EIP is at kthread_data+0x6/0xa [ 512.957861] EAX: 00000000 EBX: 00000000 ECX: f652de14 EDX: 00000000 [ 512.957861] ESI: 00000000 EDI: 00000000 EBP: f652dc70 ESP: f644bcfc [ 512.957861] DS: 007b ES: 007b FS: 00d8 GS: 00e0 SS: 0068 [ 512.957861] Process kworker/0:0 (pid: 1301, ti=f644a000 task=f652dc70 task.ti=f644a000) [ 512.957861] Stack: [ 512.957861] c1041716 f6806180 00000000 c125df8f f641c240 c10c6bab f644bd57 00000000 [ 512.957861] f6732700 c13f9180 f652de14 0000000d c13f9180 f652dc70 c13f9180 c13f9180 [ 512.957861] 0000000d f6732710 00000001 00000001 00000086 c1345a80 00000ae0 00000000 [ 512.957861] Call Trace: [ 512.957861] [<c1041716>] ? wq_worker_sleeping+0x9/0x6d [ 512.957861] [<c125df8f>] ? schedule+0x105/0x5be [ 512.957861] [<c10c6bab>] ? d_lookup+0x1f/0x2f [ 512.957861] [<c1031178>] ? release_task+0x375/0x384 [ 512.957861] [<c10326ba>] ? do_exit+0x655/0x663 [ 512.957861] [<c1260c9d>] ? oops_end+0x95/0x99 [ 512.957861] [<c101c6ad>] ? no_context+0x10d/0x116 [ 512.957861] [<c101c7ba>] ? bad_area_nosemaphore+0xa/0xc [ 512.957861] [<c126239c>] ? do_page_fault+0x1b0/0x35d [ 512.957861] [<f810cc87>] ? scsi_pool_alloc_command+0x29/0x41 [scsi_mod] [ 512.957861] [<c12621ec>] ? spurious_fault+0xae/0xae [ 512.957861] [<c12603af>] ? error_code+0x67/0x6c [ 512.957861] [<f810ce27>] ? scsi_get_command+0x53/0x78 [scsi_mod] [ 512.957861] [<f81118c2>] ? scsi_setup_fs_cmnd+0x53/0x9b [scsi_mod] [ 512.957861] [<f828b0b7>] ? sd_prep_fn+0x29e/0xb5a [sd_mod] [ 512.957861] [<f828ae19>] ? sd_unprep_fn+0x22/0x22 [sd_mod] [ 512.957861] [<c112e86a>] ? blk_peek_request+0xb6/0x182 [ 512.957861] [<f8111004>] ? scsi_request_fn+0x6c/0x44e [scsi_mod] [ 512.957861] [<c112b14a>] ? __blk_run_queue+0x11/0x12 [ 512.957861] [<c113829b>] ? cfq_kick_queue+0x20/0x31 [ 512.957861] [<c10401dc>] ? process_one_work+0x181/0x25e [ 512.957861] [<c113827b>] ? cfq_init_queue+0x28b/0x28b [ 512.957861] [<c1041b68>] ? worker_thread+0xf3/0x1f4 [ 512.957861] [<c1041a75>] ? manage_workers+0x15a/0x15a [ 512.957861] [<c104433c>] ? kthread+0x63/0x68 [ 512.957861] [<c10442d9>] ? kthread_worker_fn+0x114/0x114 [ 512.957861] [<c126517e>] ? kernel_thread_helper+0x6/0xd [ 512.957861] Code: 01 46 10 8b 14 24 8d 43 08 e8 b1 b4 21 00 59 5b 5e 5f 5d c3 90 64 a1 c4 44 3f c1 8b 80 78 01 00 00 8b 40 f8 c3 8b 80 78 01 00 00 <8b> 40 fc c3 31 c0 c3 8d 50 04 c7 00 00 00 00 00 89 50 04 89 50 [ 512.957861] EIP: [<c1044062>] kthread_data+0x6/0xa SS:ESP 0068:f644bcfc [ 512.957861] CR2: 00000000fffffffc [ 512.957861] ---[ end trace 51f1ebb81396496a ]--- [ 512.957861] Fixing recursive fault but reboot is needed!
Подскажите пожалуйста в чем проблема, куда копать?