msg_name структуры msghdr не указывает на структуру sockaddr_in в socket_recvmsg модуля безопасности linux

Я использую операцию безопасности socket_recvmsg в модуле безопасности Linux.

int (*socket_recvmsg) (struct socket *sock,struct msghdr *msg, int size, int flags) 

Предполагается, что Msg->msg_name указывает на структуру sockaddr_in, которая содержит sin_family, исходный порт и исходный IP-адрес. msg->msg_namelen указывает размер данных, на которые указывает msg->msg_name. Однако msg->msg->namelen в моей функции socket_recvmsg всегда равно 112, что намного больше, чем sizeof(struct sockaddr_in). Поэтому я предполагаю, что msg->msg_name должно указывать на какую-то другую структуру данных, а не на struct sockaddr_in. Кто-нибудь знает, на какой тип данных указывает msg->msg_name в socket_recvmsg?

Кроме того, msg->msg_name в моей функции sendmsg всегда равно sizeof(struct sockaddr_in), и я могу получить порт и IP-адрес из msg->msg_name в функции sendmsg.


person ruofan    schedule 16.07.2015    source источник


Ответы (2)


Поле msg_name в struct msghdr не обязательно должно указывать на struct sockaddr_in: оно указывает на общий адрес сокета; точная структура зависит от семейства сокетов: если это сокет AF_UNIX, он указывает на struct sockaddr_un, если это AF_INET, он указывает на struct sockaddr_in, а если это AF_INET6, он указывает на struct sockaddr_in6. Все они имеют общее поле sa_family, которое также является первым полем, поэтому вы можете преобразовать msg_name в struct sockaddr *, прочитать поле sa_family и решить, куда двигаться дальше.

Имейте в виду, что могут быть реализованы другие семейства сокетов; В линуксе, например, есть AF_APPLETALK, AF_X25 и еще какие-то, я сейчас не вспомню.

Кроме того, msg->msg_name в моей функции sendmsg всегда равно sizeof(struct sockaddr_in)

Это верно, пока вы используете сокеты AF_INET, потому что IP-адреса и номера портов имеют фиксированную длину. Но аргумент размера не всегда является статически известным значением. В сокетах UNIX (локальных сокетах) размер, который вы передаете, равен не sizeof(struct sockaddr_un), а offsetof(struct sockaddr_un, sa_data)+strlen(pathname), где pathname — это размер строки пути в файловой системе, где находится дескриптор сокета.

person Filipe Gonçalves    schedule 16.07.2015
comment
Привет Филипе, спасибо за ваш ответ. Ваше объяснение имеет смысл для меня. Я занимался udp и tcp, поэтому все пакеты должны быть AF_INET. Однако в моей функции socket_recvmsg первые 2 байта, на которые указывает msg_name, всегда равны 0 (AF_UNSPEC), а msg_namelen — 112. Итак, знаете ли вы, на какой тип данных на самом деле указывает msg_name? - person ruofan; 17.07.2015
comment
@ruofan Я действительно не уверен, что это за функция socket_recvmsg(). Где вы его нашли? Из того, что я мог видеть, это функция PHP, я прав? Может случиться так, что он используется внутренне библиотекой PHP и оборачивает вещи в другую внутреннюю структуру. - person Filipe Gonçalves; 17.07.2015
comment
Итак, socket_recvmsg() — это функция, определенная в linux/security.h. Это часть модуля безопасности Linux. socket_recvmsg() будет вызываться перед фактическим системным вызовом recvmsg. Разработчик может зарегистрировать модуль ядра linux и переопределить socket_recvmsg(), чтобы выполнить некоторую проверку безопасности или разрешений до того, как пакет поступит на системный вызов recvmsg. - person ruofan; 17.07.2015
comment
Кажется, я нашел, почему размер 112, когда он получает пакет udp. На этапе вызова моей функции-ловушки socket_recvmsg() структура msghdr еще не настроена. Таким образом, msg-›msg_name указывает на структуру sockaddr_un и имеет размер 112. - person ruofan; 17.07.2015
comment
@ruofan Приятно знать. На самом деле я думал, что возможно msghdr не был настроен к моменту вызова вашей функции, и поэтому может быть так, что он указывал на максимально возможную адресную структуру (для размещения любого типа сокета ). В этом есть смысл, но это было только подозрение. Если вы нашли решение своей проблемы, вы должны опубликовать ответ и принять его. Я с удовольствием проголосую за это! - person Filipe Gonçalves; 18.07.2015

socket_recvmsg — это функция ловушки в security.h. Он обеспечивает проверку разрешений для вызова recvmsg. Однако ловушка является предварительной операцией, что означает, что функция ловушки выполняется до фактической операции recvmsg. На этапе socket_recvmsg struct msg не был настроен ни для какого конкретного sockaddr.

Я тестировал на Centos 6.6. msg->msg_len равно 112 для сокета udp и 128 для пакета tcp на socket_recvmsg.

person ruofan    schedule 23.07.2015