Quantcast
Channel: Linux.org.ru: Форум (тех. форум)
Viewing all articles
Browse latest Browse all 73888

куда пойдём мы с recvfrom?

$
0
0

Ну вот, recvfrom это системный вызов.

  ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,
                struct sockaddr *src_addr, socklen_t *addrlen);
находится он в net/socket.c.
Если (struct sockaddr *) есть в переданных параметрах,
то она сохраняется в структуру (struct msghdr). Я пытаюсь отследить где эта структура получает значения.
msghdr передаётся в качестве аргумента в sock_recvmsg.
sock_recvmsg есть в этом же файле. Эта функция вызывает другую функцию security_socket_recvmsg, которая находится в security/security.c, которая в свою очередь возвращает определение call_int_hook.
int security_socket_recvmsg(struct socket *sock, struct msghdr *msg,
                            int size, int flags)
{
        return call_int_hook(socket_recvmsg, 0, sock, msg, size, flags);
}
Как понять это определение?
#define call_int_hook(FUNC, IRC, ...) ({                        \
        int RC = IRC;                                           \
        do {                                                    \
                struct security_hook_list *P;                   \
                                                                \
                list_for_each_entry(P, &security_hook_heads.FUNC, list) { \
                        RC = P->hook.FUNC(__VA_ARGS__);         \
                        if (RC != 0)                            \
                                break;                          \
                }                                               \
        } while (0);                                            \
        RC;                                                     \
})
struct security_hook_list находится в include/linux/lsm_hooks.h.
struct security_hook_list {
        struct list_head                list;
        struct list_head                *head;
        union security_list_options     hook;
};
Также struct security_hook_heads.
struct security_hook_heads {
  ...
#ifdef CONFIG_SECURITY_NETWORK
  ...
        struct list_head socket_recvmsg;
  ...
};
Я так и не понел, заполняется здесь структура msghdr?
Дальше в net/socket.c.
int sock_recvmsg(struct socket *sock, struct msghdr *msg, int flags)
{
        int err = security_socket_recvmsg(sock, msg, msg_data_left(msg), flags);

        return err ?: sock_recvmsg_nosec(sock, msg, flags);
}
Так как security_socket_recvmsg уже вызывался, следует функция sock_recvmsg_nosec, если нет ошибки(я правильно понимаю?).
Но функция sock_recvmsg_nosec
static inline int sock_recvmsg_nosec(struct socket *sock, struct msghdr *msg,
                                     int flags)
{
        return sock->ops->recvmsg(sock, msg, msg_data_left(msg), flags);
}
вызывает sock->ops->recvmsg
Вот struct socket из include/linux/net.h.
struct socket {
        socket_state            state;

        kmemcheck_bitfield_begin(type);
        short                   type;
        kmemcheck_bitfield_end(type);

        unsigned long           flags;

        struct socket_wq __rcu  *wq;

        struct file             *file;
        struct sock             *sk;
        const struct proto_ops  *ops;
};
Вот ops из const struct proto_ops.
struct proto_ops {
  ...
         * ===============================
         * msg->msg_namelen should get updated by the recvmsg handlers
         * iff msg_name != NULL. It is by default 0 to prevent
         * returning uninitialized memory to user space.  The recvfrom
         * handlers can assume that msg.msg_name is either NULL or has
         * a minimum size of sizeof(struct sockaddr_storage).
         */
        int             (*recvmsg)   (struct socket *sock, struct msghdr *m,
                                      size_t total_len, int flags);
  ...
Вот на всякий случай функция recvfrom.
SYSCALL_DEFINE6(recvfrom, int, fd, void __user *, ubuf, size_t, size,
                unsigned int, flags, struct sockaddr __user *, addr,
                int __user *, addr_len)
{
        struct socket *sock;
        struct iovec iov;
        struct msghdr msg;
        struct sockaddr_storage address;
        int err, err2;
        int fput_needed;

        err = import_single_range(READ, ubuf, size, &iov, &msg.msg_iter);
        if (unlikely(err))
                return err;
        sock = sockfd_lookup_light(fd, &err, &fput_needed);
        if (!sock)
                goto out;

        msg.msg_control = NULL;
        msg.msg_controllen = 0;
        /* Save some cycles and don't copy the address if not needed */
        msg.msg_name = addr ? (struct sockaddr *)&address : NULL;
        /* We assume all kernel code knows the size of sockaddr_storage */
        msg.msg_namelen = 0;
        msg.msg_iocb = NULL;
        if (sock->file->f_flags & O_NONBLOCK)
                flags |= MSG_DONTWAIT;
        err = sock_recvmsg(sock, &msg, flags);

        if (err >= 0 && addr != NULL) {
                err2 = move_addr_to_user(&address,
                                         msg.msg_namelen, addr, addr_len);
                if (err2 < 0)
                        err = err2;
        }

        fput_light(sock->file, fput_needed);
out:
        return err;
}
Как мне найти код, где заполняются struct sockaddr * данные?

 


Viewing all articles
Browse latest Browse all 73888

Trending Articles