On 12/2/24 16:07, Antonio Quartulli wrote:
+/**
- ovpn_nl_peer_modify - modify the peer attributes according to the incoming msg
- @peer: the peer to modify
- @info: generic netlink info from the user request
- @attrs: the attributes from the user request
- Return: a negative error code in case of failure, 0 on success or 1 on
success and the VPN IPs have been modified (requires rehashing in MP
mode)- */
+static int ovpn_nl_peer_modify(struct ovpn_peer *peer, struct genl_info *info,
struct nlattr **attrs)+{
- struct sockaddr_storage ss = {};
- u32 sockfd, interv, timeout;
- struct socket *sock = NULL;
- u8 *local_ip = NULL;
- bool rehash = false;
- int ret;
- if (attrs[OVPN_A_PEER_SOCKET]) {
if (peer->sock) {NL_SET_ERR_MSG_FMT_MOD(info->extack,"peer socket can't be modified");return -EINVAL;}/* lookup the fd in the kernel table and extract the socket* object*/sockfd = nla_get_u32(attrs[OVPN_A_PEER_SOCKET]);/* sockfd_lookup() increases sock's refcounter */sock = sockfd_lookup(sockfd, &ret);if (!sock) {NL_SET_ERR_MSG_FMT_MOD(info->extack,"cannot lookup peer socket (fd=%u): %d",sockfd, ret);return -ENOTSOCK;}/* Only when using UDP as transport protocol the remote endpoint* can be configured so that ovpn knows where to send packets* to.** In case of TCP, the socket is connected to the peer and ovpn* will just send bytes over it, without the need to specify a* destination.*/if (sock->sk->sk_protocol != IPPROTO_UDP &&(attrs[OVPN_A_PEER_REMOTE_IPV4] ||attrs[OVPN_A_PEER_REMOTE_IPV6])) {NL_SET_ERR_MSG_FMT_MOD(info->extack,"unexpected remote IP address for non UDP socket");sockfd_put(sock);return -EINVAL;}peer->sock = ovpn_socket_new(sock, peer);if (IS_ERR(peer->sock)) {NL_SET_ERR_MSG_FMT_MOD(info->extack,"cannot encapsulate socket: %ld",PTR_ERR(peer->sock));sockfd_put(sock);peer->sock = NULL;
This looks race-prone. If any other CPU can do concurrent read access to peer->sock it could observe an invalid pointer Even if such race does not exist, it would be cleaner store ovpn_socket_new() return value in a local variable and set peer->sock only on successful creation.
/P