/* Curl busyloop PoC written by Harry Sintonen Public Domain My current understanding is that the socket will report as having data to receive and thus curl_multi_poll() will always return immediately. The socket will be added to the pollset by the Curl_ssl_adjust_pollset() since OpenSSL reports SSL_ERROR_WANT_READ. curl_multi_perform() sees the connection paused and does nothing -> Busyloop Largely based on https://curl.se/libcurl/c/multi-app.html */ #include #include #include #define HANDLECOUNT 1 size_t write_callback(char *ptr, size_t size, size_t nmemb, void *userdata) { return CURL_WRITEFUNC_PAUSE; } int sockopt_callback(void *clientp, curl_socket_t curlfd, curlsocktype purpose) { const int newsize = 32768; int rc = 0; rc |= setsockopt(curlfd, SOL_SOCKET, SO_RCVBUF, &newsize, sizeof(newsize)); rc |= setsockopt(curlfd, SOL_SOCKET, SO_SNDBUF, &newsize, sizeof(newsize)); return rc ? CURL_SOCKOPT_ERROR : CURL_SOCKOPT_OK; } int main(void) { CURL *curl[HANDLECOUNT]; CURLM *multi; int i; curl_global_init(CURL_GLOBAL_ALL); for(i = 0; i < HANDLECOUNT; i++) { curl[i] = curl_easy_init(); //curl_easy_setopt(curl[i], CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); curl_easy_setopt(curl[i], CURLOPT_BUFFERSIZE, 32 * 1024); curl_easy_setopt(curl[i], CURLOPT_SOCKOPTFUNCTION, sockopt_callback); curl_easy_setopt(curl[0], CURLOPT_URL, "https://curl.se/download/curl-8.20.0.tar.xz"); curl_easy_setopt(curl[0], CURLOPT_WRITEFUNCTION, write_callback); } multi = curl_multi_init(); if(multi) { int still_running = 1; /* keep number of running handles */ for(i = 0; i < HANDLECOUNT; i++) curl_multi_add_handle(multi, curl[i]); while(still_running) { CURLMcode mresult = curl_multi_perform(multi, &still_running); //printf("mresult %d still_running %d\n", mresult, still_running); if (mresult) break; if(still_running) { mresult = curl_multi_poll(multi, NULL, 0, 1000, NULL); //printf("curl_multi_poll mresult %d\n", mresult); } if(mresult) break; } for(i = 0; i < HANDLECOUNT; i++) curl_multi_remove_handle(multi, curl[i]); curl_multi_cleanup(multi); } for(i = 0; i < HANDLECOUNT; i++) curl_easy_cleanup(curl[i]); curl_global_cleanup(); return 0; }