2014-02-07 2 views
1

Я попытался сбрасывать все данные, отправленные определенным процессом в Linux, путем подключения обработчика к функции ядра sock_sendmsg(), определенной в linux/socket.c. Я мог бы это сделать, написав обработчик зонда systemtap для probe kernel.function("[email protected]/socket.c"), который сбрасывает все блоки данных, переданные со вторым аргументом struct msghdr *msg.sock_sendmsg(): неявные вызовы функций от Kernel

Вот отрывок из net/socket.c:

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; 
} 

Я проверил мой Systemtap сценарий hook_sendmsg.stp. Сначала я запустил hook_sendmsg.stp в одном терминале. Затем я открыл другой терминал и вызвал команду telnet для подключения к stackoverflow.com и напечатал HEAD/HTTP/1.0<Enter twice> в терминале. Я получил следующий вывод из hook_sendmsg.stp:

[email protected]:~# stap -g hook_sendmsg.stp 
message block [0]; type=3(raw); state=1(unconnected) 
14 00 00 00 16 00 01 03 ec 95 f4 52 00 00 00 00 |...........R....| 
00 00 00 00          |................| 
message block [0]; type=3(raw); state=1(unconnected) 
14 00 00 00 16 00 01 03 ec 95 f4 52 00 00 00 00 |...........R....| 
00 00 00 00          |................| 
message block [0]; type=2(udp); state=1(unconnected) 
4d 0d 01 00 00 01 00 00 00 00 00 00 0d 73 74 61 |M............sta| 
63 6b 6f 76 65 72 66 6c 6f 77 03 63 6f 6d 00 00 |ckoverflow.com..| 
01 00 01          |................| 
message block [0]; type=2(udp); state=1(unconnected) 
0f 1e 01 00 00 01 00 00 00 00 00 00 0d 73 74 61 |.............sta| 
63 6b 6f 76 65 72 66 6c 6f 77 03 63 6f 6d 00 00 |ckoverflow.com..| 
1c 00 01          |................| 
message block [0]; type=1(tcp); state=3(connected) 
48 45 41 44 20 2f 20 48 54 54 50 2f 31 2e 30 0d |HEAD/HTTP/1.0.| 
0a            |................| 
message block [0]; type=1(tcp); state=3(connected) 
0d 0a           |................| 

Это показывает, что полностью sock_sendmsg() были названы 6 раз в контексте telnet. Очевидно, что 3-й и 4-й являются DNS-запросами для общедоступных DNS-серверов Google 8.8.8.8 и 8.8.4.4. 5-я и 6-я - это две строки HTTP-запроса, отправленные с telnet. Но что требовали 1 и 2? Они вызвали внутренне ядро?

Заранее спасибо.

+0

Вы можете добавьте print_backtrace(); print_ubacktrace(); пара для обработчика зонда, чтобы понять, что происходит. Добавьте «-d/usr/bin/telnet -ldd -d kernel» в командную строку stap, чтобы включить более полное обратное трассирование. – fche

+0

Спасибо, fche. Полезные советы для отладки ядра. Я пробовал эти функции, но 'print_ubacktrace()' не работал. По-видимому, Debian не включает опцию 'CONFIG_UTRACE' по умолчанию. Мне нужно перекомпилировать Ядро. –

+0

Хм, я не думаю, что вам нужно CONFIG_UPROBES только для print_ubacktrace(). Если вы уверены, пришлите нам несколько подробностей в списке рассылки. – fche

ответ

1

Они NETLINK сообщения, как вы можете увидеть, если вы контролировать команду телнета из пользовательского пространства с Трассированием (проверьте семейство сокета):

sendto(3, "\24\0\0\0\26\0\1\3?\254\364R\0\0\0\0\0\0\0\0", 20, 0, {sa_family=AF_NETLINK, pid=0, groups=00000000}, 12) = 20 
sendto(3, "\24\0\0\0\26\0\1\3?\254\364R\0\0\0\0\0\0\0\0", 20, 0, {sa_family=AF_NETLINK, pid=0, groups=00000000}, 12) = 20 
send(3, "\212\355\1\0\0\1\0\0\0\0\0\0\rstackoverflow\3com\0\0"..., 35, MSG_NOSIGNAL) = 35 
send(3, "\241\353\1\0\0\1\0\0\0\0\0\0\rstackoverflow\3com\10i"..., 50, MSG_NOSIGNAL) = 50 
send(3, "|\341\1\0\0\1\0\0\0\0\0\0\rstackoverflow\3com\0\0"..., 35, MSG_NOSIGNAL) = 35 
send(3, "HEAD/HTTP/1.0\r\n", 17, 0) = 17 
send(3, "\r\n", 2, 0)     = 2 

Netlink представляет собой интерфейс, используемый в пользовательском пространстве процессов общения с ядром (поэтому они отправляются по telnet), как правило, для маршрутизации, межсетевого экрана ... pourposes [1]. Некоторые обычные функции сети C (т. Е. Getsockname) работают внутри с такими сообщениями NETLINK.

Если вы хотите, чтобы исследовать немного больше, вы должны перевести полезную нагрузку send_message к NETLINK структуре заголовка и проверить, какой тип сообщений являются .:

 struct nlmsghdr { 
      __u32 nlmsg_len; /* Length of message including header. */ 
      __u16 nlmsg_type; /* Type of message content. */ 
      __u16 nlmsg_flags; /* Additional flags. */ 
      __u32 nlmsg_seq; /* Sequence number. */ 
      __u32 nlmsg_pid; /* Sender port ID. */ 
     }; 

[1] http://man7.org/linux/man-pages/man7/netlink.7.html

+1

В частности, getaddrinfo() glibc использует свою внутреннюю функцию __check_pf() для проверки наличия интерфейсов ipv4 и/или ipv6 в системе. – fche

+0

Спасибо, Джон. Я много не знал о NETLINK, но интересно, что NETLINK используется внутренне с помощью некоторых стандартных функций библиотеки. –