Добрый день.
Хочу узнать, из-за чего происходит подобное.
Я ставлю перехватчик на какую-то функцию ядра. (через обыкновенный jmp).
При этом, перехватываемая и функция перехватчик абсолютно идентичны.
Получается следующее.
«Работа модуля»
Функция ядра
Функция ядра
Функция ядра
Функция перехватчик (заместили собой другую ф-ю)
Функция ядра
Функция ядра
Замечу такой способ перехвата, всегда работал на ура, и никогда никаких проблем не было замечено.
Однако произошло исключение из правила, поставил перехватчик на функцию tcp_sendpage и должно было быть всё, как обычно, - работать без сбоев - идеально.
int tcp_sendpage(struct sock *sk, struct page *page, int offset,
size_t size, int flags)
{
ssize_t res;
if (!(sk->sk_route_caps & NETIF_F_SG) ||
!(sk->sk_route_caps & NETIF_F_ALL_CSUM))
return sock_no_sendpage(sk->sk_socket, page, offset, size,
flags);
lock_sock(sk);
TCP_CHECK_TIMER(sk);
res = do_tcp_sendpages(sk, &page, offset, size, flags);
TCP_CHECK_TIMER(sk);
release_sock(sk);
return res;
}
Но при передачи данных (при работе перехватчика) вылетает следующая ошибка.
BUG: unable to handle kernel NULL pointer dereference at 00000044
Dec 4 11:45:59 localhost kernel: IP: [<c0387d1a>] sock_sendmsg+0xca/0x100
Dec 4 11:45:59 localhost kernel: *pde = 00000000
Dec 4 11:45:59 localhost kernel: Oops: 0000 [#8] SMP
Dec 4 11:45:59 localhost kernel: last sysfs file: /sys/devices/pci0000:00/0000:00:01.1/host0/target0:0:0/0:0:0:0/block/sda/sda1/uevent
G D 2.6.33.7-desktop-2mnb #1 /VirtualBox
Dec 4 11:45:59 localhost kernel: EIP: 0060:[<c0387d1a>] EFLAGS: 00010246 CPU: 0
Dec 4 11:45:59 localhost kernel: EIP is at sock_sendmsg+0xca/0x100
Dec 4 11:45:59 localhost kernel: EAX: cc179c70 EBX: 00000000 ECX: cc179d54 EDX: d88bd84c
Dec 4 11:45:59 localhost kernel: ESI: 00001000 EDI: cc179d54 EBP: cc179d2c ESP: cc179c68
Dec 4 11:45:59 localhost kernel: DS: 007b ES: 007b FS: 00d8 GS: 00e0 SS: 0068
Dec 4 11:45:59 localhost kernel: Stack:
Dec 4 11:45:59 localhost kernel: 00001000 00000000 00000082 00000082 00000000 00000001 ffffffff 00000000
Dec 4 11:45:59 localhost kernel: <0> 00000000 00000000 00000000 00000000 f3738c80 00000000 00000000 c07141b3
Dec 4 11:45:59 localhost kernel: <0> 00000016 cc179ce0 cc179d2c 00000246 cc179d48 00000082 00000034 fa30063c
Dec 4 11:45:59 localhost kernel: Call Trace:
Dec 4 11:45:59 localhost kernel: [<c01d2a2f>] ? page_address+0xbf/0xe0
Dec 4 11:45:59 localhost kernel: [<c01d2a2f>] ? page_address+0xbf/0xe0
Dec 4 11:45:59 localhost kernel: [<c04292ab>] ? printk+0x1d/0x22
Dec 4 11:45:59 localhost kernel: [<c0387d85>] ? kernel_sendmsg+0x35/0x50
Dec 4 11:45:59 localhost kernel: [<fa2f873f>] ? my_sock_no_sendpage+0xbf/0xf0 [мой модуль]
Dec 4 11:45:59 localhost kernel: [<fa2f87f6>] ? my_tcp_sendpage+0x86/0xb0 [мой модуль]
Dec 4 11:45:59 localhost kernel: [<c03cbac0>] ? tcp_sendpage+0x0/0x470
Dec 4 11:45:59 localhost kernel: [<c0386afd>] ? kernel_sendpage+0x2d/0x50
Dec 4 11:45:59 localhost kernel: [<c0386b62>] ? sock_sendpage+0x42/0x50
Dec 4 11:45:59 localhost kernel: [<c0212487>] ? pipe_to_sendpage+0x87/0x90
Dec 4 11:45:59 localhost kernel: [<c0386b20>] ? sock_sendpage+0x0/0x50
Dec 4 11:45:59 localhost kernel: [<c02124ec>] ? splice_from_pipe_feed+0x5c/0x100
Dec 4 11:45:59 localhost kernel: [<c0212400>] ? pipe_to_sendpage+0x0/0x90
Dec 4 11:45:59 localhost kernel: [<c0389903>] ? sock_aio_write+0x113/0x130
Dec 4 11:45:59 localhost kernel: [<c021289c>] ? __splice_from_pipe+0x5c/0x70
Dec 4 11:45:59 localhost kernel: [<c0212400>] ? pipe_to_sendpage+0x0/0x90
Dec 4 11:45:59 localhost kernel: [<c0212913>] ? splice_from_pipe+0x63/0x80
Dec 4 11:45:59 localhost kernel: [<c0212970>] ? generic_splice_sendpage+0x0/0x30
Dec 4 11:45:59 localhost kernel: [<c0212996>] ? generic_splice_sendpage+0x26/0x30
Dec 4 11:45:59 localhost kernel: [<c0212400>] ? pipe_to_sendpage+0x0/0x90
Dec 4 11:45:59 localhost kernel: [<c0212e1f>] ? vfs_splice_from+0x5f/0x90
Dec 4 11:45:59 localhost kernel: [<c0212e7b>] ? direct_splice_actor+0x2b/0x40
Dec 4 11:45:59 localhost kernel: [<c0212c3f>] ? splice_direct_to_actor+0xcf/0x1d0
Dec 4 11:45:59 localhost kernel: [<c0212e50>] ? direct_splice_actor+0x0/0x40
Dec 4 11:45:59 localhost kernel: [<c0212d9d>] ? do_splice_direct+0x5d/0x80
Dec 4 11:45:59 localhost kernel: [<c01f47f7>] ? do_sendfile+0x1a7/0x230
Dec 4 11:45:59 localhost kernel: [<c01f513b>] ? sys_sendfile64+0x8b/0xb0
Dec 4 11:45:59 localhost kernel: [<c042c2a4>] ? syscall_call+0x7/0xb
Dec 4 11:45:59 localhost kernel: Code: 89 55 d0 89 4d c0 e8 56 2b ee ff 85 c0 75 1f 8b 43 24 89 da 89 f9 89 34 24 89 85 40 ff ff ff 8b 9d 40 ff ff ff 8d 85 44 ff ff ff <ff> 53 44 3d ef fd ff ff 74 14 8b 5d f4 8b 75 f8 8b 7d fc 89 ec
Dec 4 11:45:59 localhost kernel: EIP: [<c0387d1a>] sock_sendmsg+0xca/0x100 SS:ESP 0068:cc179c68
Dec 4 11:45:59 localhost kernel: CR2: 0000000000000044
Вот список вызываемых функций.
1) my_tcp_sendpage - функция перехватчик.
2) my_sock_no_sendpage - тоже моя функция (копия оригинала из кода ядра) вот ошибка sock->ops = (null) sock->ops должен указывать на функции сокета, а после моего перехвата, по каким-то причинам он равен нулю!!!
3) kernel_sendmsg
4) sock_sendmsg
5) __sock_sendmsg (в этой функции oops происходит, как полагаю на
этом return sock->ops->sendmsg(iocb, sock, msg, size) ) ведь sock->ops = (null) проверено в функции my_sock_no_sendpage
Вот код этих функций из ядра.
int tcp_sendpage(struct sock *sk, struct page *page, int offset,
size_t size, int flags)
{
ssize_t res;
if (!(sk->sk_route_caps & NETIF_F_SG) ||
!(sk->sk_route_caps & NETIF_F_ALL_CSUM))
return sock_no_sendpage(sk->sk_socket, page, offset, size,
flags);
lock_sock(sk);
TCP_CHECK_TIMER(sk);
res = do_tcp_sendpages(sk, &page, offset, size, flags);
TCP_CHECK_TIMER(sk);
release_sock(sk);
return res;
}
ssize_t sock_no_sendpage(struct socket *sock, struct page *page, int offset, size_t size, int flags)
{
ssize_t res;
struct msghdr msg = {.msg_flags = flags};
struct kvec iov;
char *kaddr = kmap(page);
iov.iov_base = kaddr + offset;
iov.iov_len = size;
res = kernel_sendmsg(sock, &msg, &iov, 1, size);
kunmap(page);
return res;
}
int kernel_sendmsg(struct socket *sock, struct msghdr *msg,
struct kvec *vec, size_t num, size_t size)
{
mm_segment_t oldfs = get_fs();
int result;
set_fs(KERNEL_DS);
/*
* the following is safe, since for compiler definitions of kvec and
* iovec are identical, yielding the same in-core layout and alignment
*/
msg->msg_iov = (struct iovec *)vec;
msg->msg_iovlen = num;
result = sock_sendmsg(sock, msg, size);
set_fs(oldfs);
return result;
}
int sock_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
{
struct kiocb iocb;
struct sock_iocb siocb;
int ret;
init_sync_kiocb(&iocb, NULL);
iocb.private = &siocb;
ret = __sock_sendmsg(&iocb, sock, msg, size);
if (-EIOCBQUEUED == ret)
ret = wait_on_sync_kiocb(&iocb);
return ret;
}
static inline int __sock_sendmsg(struct kiocb *iocb, struct socket *sock,
struct msghdr *msg, size_t size)
{
struct sock_iocb *si = kiocb_to_siocb(iocb);
int err;
sock_update_classid(sock->sk);
si->sock = sock;
si->scm = NULL;
si->msg = msg;
si->size = size;
err = security_socket_sendmsg(sock, msg, size);
if (err)
return err;
return sock->ops->sendmsg(iocb, sock, msg, size);
}
Ктонибудь может мне объяснит в чём может быть заключена проблема???