segfault
segfault

Reputation: 109

msg_name of a struct msghdr doesn't point to a struct sockaddr_in in socket_recvmsg of linux security module

I use a security operation 'socket_recvmsg' in the Linux security module.

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

Msg->msg_name is supposed to point to a struct sockaddr_in, which contains the sin_family, source port and source ip address. msg->msg_namelen indicates the size of data pointed by msg->msg_name. However, the msg->msg->namelen in my socket_recvmsg function is always 112, which is far larger than sizeof(struct sockaddr_in). So I guess msg->msg_name must point to some other data structure, rather than struct sockaddr_in. Does anyone know what data type the msg->msg_name in socket_recvmsg point to?

Also, the msg->msg_name in my sendmsg function always equals to sizeof(struct sockaddr_in), and I can get port and ip address from msg->msg_name in sendmsg function.

Upvotes: 1

Views: 3516

Answers (2)

segfault
segfault

Reputation: 109

socket_recvmsg is a hook function in security.h. It provides permission checking for recvmsg call. However, the hook is a pre-op, which means the hook function occurs before the actual operation recvmsg. At the stage of socket_recvmsg, the struct msg has not been set up for any specific sockaddr.

I tested on centos 6.6. The msg->msg_len is 112 for udp socket, and is 128 for tcp packet at socket_recvmsg.

Upvotes: 0

Filipe Gonçalves
Filipe Gonçalves

Reputation: 21213

The msg_name field of struct msghdr does not necessarily have to point to a struct sockaddr_in: it points to a generic socket address; the exact structure depends on the socket family: if it's an AF_UNIX socket, it points to a struct sockaddr_un, if it's AF_INET, it points to struct sockaddr_in, and if it's AF_INET6 it points to struct sockaddr_in6. All of them share the sa_family field, which is also the first field, so you can cast msg_name to struct sockaddr *, read the sa_family field, and decide where to go from there.

Keep in mind that there may be other socket families implemented; Linux, for example, has AF_APPLETALK, AF_X25, and some others I don't remember right now.

Also, the msg->msg_name in my sendmsg function always equals to sizeof(struct sockaddr_in)

This is true as long as you're using AF_INET sockets, because ip addresses and port numbers have a fixed length. But the size argument is not always a statically known value. In UNIX sockets (local sockets), the size you pass is not sizeof(struct sockaddr_un), but instead it is offsetof(struct sockaddr_un, sa_data)+strlen(pathname), where pathname is the size of the path string in the filesystem where the socket handle lives.

Upvotes: 3

Related Questions