Describe the bug File: src/cluster.c

In function clusterCron, node->link is freed by freeClusterLink(node->link) at line 3,674. But the freed node->link could be used by clusterSendPing(node->link, CLUSTERMSG_TYPE_PING) at line 3,696.

        if (node->link && /* is connected */
            now - node->link->ctime >
            server.cluster_node_timeout && /* was not already reconnected */
            node->ping_sent && /* we already sent a ping */
            /* and we are waiting for the pong more than timeout/2 */
            ping_delay > server.cluster_node_timeout/2 &&
            /* and in such interval we are not seeing any traffic at all. */
            data_delay > server.cluster_node_timeout/2)
        {
            /* Disconnect the link, it will be reconnected automatically. */
 3674:       freeClusterLink(node->link);  // --> node->link is freed here !!
        }
       ......
      if (server.cluster->mf_end &&
            nodeIsMaster(myself) &&
            server.cluster->mf_slave == node &&
            node->link)
        {
3696:       clusterSendPing(node->link, CLUSTERMSG_TYPE_PING); // freed node->link could be used here !!.
            continue;
        }

Expected behavior

If this path is feasible, it could cause crash when the uaf is triggered.

Maybe it is better to add some checks to make this path unfeasible.

Comment From: huangzhw

freeClusterLink(node->link); will set node->link to NULL. So this code path will not happen.

Comment From: Yunlongs

freeClusterLink(node->link); will set node->link to NULL. So this code path will not happen.

Ok, by inspecting the implementation of freeClusterLink() carefully, i found that it sets node->link to NULL because node->link->node = node.

Thanks.