diff --git a/client/client_state.cpp b/client/client_state.cpp index e1c356a57ce..9d9904792cd 100644 --- a/client/client_state.cpp +++ b/client/client_state.cpp @@ -262,6 +262,11 @@ void CLIENT_STATE::show_host_info() { "- OS: %s (%s)", wsl.os_name.c_str(), wsl.os_version.c_str() ); + if (!wsl.libc_version.empty()) { + msg_printf(NULL, MSG_INFO, + "- libc version: %s", wsl.libc_version.c_str() + ); + } if (!wsl.docker_version.empty()) { msg_printf(NULL, MSG_INFO, "- Docker version %s (%s)", wsl.docker_version.c_str(), diff --git a/client/hostinfo_win.cpp b/client/hostinfo_win.cpp index e17f8b9ed80..7f49b863066 100644 --- a/client/hostinfo_win.cpp +++ b/client/hostinfo_win.cpp @@ -1666,23 +1666,19 @@ int HOST_INFO::get_host_info(bool init) { os_name, sizeof(os_name), os_version, sizeof(os_version) ); #ifdef _WIN64 - if (!cc_config.dont_use_wsl) { - OSVERSIONINFOEX osvi; - if (get_OSVERSIONINFO(osvi) && osvi.dwMajorVersion >= 10) { - retval = get_wsl_information( - cc_config.allowed_wsls, wsl_distros, !cc_config.dont_use_docker + OSVERSIONINFOEX osvi; + if (get_OSVERSIONINFO(osvi) && osvi.dwMajorVersion >= 10) { + retval = get_wsl_information(wsl_distros); + if (retval) { + msg_printf(0, MSG_INTERNAL_ERROR, + "get_wsl_information(): %s", boincerror(retval) ); - if (retval) { - msg_printf(0, MSG_INTERNAL_ERROR, - "get_wsl_information(): %s", boincerror(retval) - ); - } } } #endif - if (!cc_config.dont_use_vbox) { - get_virtualbox_version(); - } + + get_virtualbox_version(); + get_processor_info( p_vendor, sizeof(p_vendor), p_model, sizeof(p_model), diff --git a/client/hostinfo_wsl.cpp b/client/hostinfo_wsl.cpp index 133d0ebaeea..cb852c4ab79 100644 --- a/client/hostinfo_wsl.cpp +++ b/client/hostinfo_wsl.cpp @@ -24,6 +24,7 @@ using std::string; #include "str_replace.h" #include "client_msgs.h" #include "hostinfo.h" +#include "util.h" // timeout for commands run in WSL container // If something goes wrong we don't want client to hang @@ -169,17 +170,12 @@ static bool got_both(WSL_DISTRO &wd) { } // Get list of WSL distros usable by BOINC -// (docker_desktop and those allowed by config) // For each of them: // try to find the OS name and version // see if Docker and docker compose are present, get versions // Return nonzero on error // -int get_wsl_information( - vector &allowed_wsls, - WSL_DISTROS &usable_distros, - bool detect_docker // whether to check for Docker -) { +int get_wsl_information(WSL_DISTROS &distros) { WSL_DISTROS all_distros; int retval = get_all_distros(all_distros); if (retval) return retval; @@ -199,14 +195,6 @@ int get_wsl_information( if (wd.distro_name == "docker-desktop-data"){ continue; } - // skip distros that are not allowed except for 'docker-desktop' - // - if (wd.distro_name != "docker-desktop" - && std::find(allowed_wsls.begin(), allowed_wsls.end(), wd.distro_name) == allowed_wsls.end() - ) { - msg_printf(0, MSG_INFO, "WSL distro '%s' detected but is not allowed", wd.distro_name.c_str()); - continue; - } char os_name[256]; char os_version[256]; @@ -314,20 +302,35 @@ int get_wsl_information( // in case nothing worked update_os(wd, "unknown", "unknown"); + // get the libc version + if (!rs.run_program_in_wsl( + wd.distro_name, "ldd --version" + )) { + string buf; + read_from_pipe(rs.out_read, rs.proc_handle, buf, CMD_TIMEOUT); + wd.libc_version = parse_ldd_libc(buf.c_str()); + } + // see if Docker is installed in the distro // - if (detect_docker) { - get_docker_version(rs, wd); - get_docker_compose_version(rs, wd); - } + get_docker_version(rs, wd); + get_docker_compose_version(rs, wd); - usable_distros.distros.push_back(wd); + // see if distro is disallowed + // + vector &dw = cc_config.disallowed_wsls; + if (std::find(dw.begin(), dw.end(), wd.distro_name) != dw.end()) { + wd.disallowed = true; + } + distros.distros.push_back(wd); } return 0; } -static bool get_docker_version_aux(WSL_CMD &rs, WSL_DISTRO &wd, DOCKER_TYPE type) { +static bool get_docker_version_aux( + WSL_CMD &rs, WSL_DISTRO &wd, DOCKER_TYPE type +) { bool ret = false; string reply; string cmd = string(docker_cli_prog(type)) + " --version"; @@ -349,7 +352,9 @@ static void get_docker_version(WSL_CMD &rs, WSL_DISTRO &wd) { get_docker_version_aux(rs, wd, DOCKER); } -static bool get_docker_compose_version_aux(WSL_CMD &rs, WSL_DISTRO &wd, DOCKER_TYPE type) { +static bool get_docker_compose_version_aux( + WSL_CMD &rs, WSL_DISTRO &wd, DOCKER_TYPE type +) { bool ret = false; string reply; string cmd = string(docker_cli_prog(type)) + " compose version"; diff --git a/client/log_flags.cpp b/client/log_flags.cpp index 86d2db0920d..74c11ca5253 100644 --- a/client/log_flags.cpp +++ b/client/log_flags.cpp @@ -195,17 +195,17 @@ void CC_CONFIG::show() { if (dont_use_vbox) { msg_printf(NULL, MSG_INFO, "Config: don't use VirtualBox"); } + if (dont_use_docker) { + msg_printf(NULL, MSG_INFO, "Config: don't use Docker"); + } if (dont_use_wsl) { - msg_printf(NULL, MSG_INFO, "Config: don't use the Windows Subsystem for Linux"); + msg_printf(NULL, MSG_INFO, "Config: don't use Windows Subsystem for Linux"); } - for (string s: allowed_wsls) { + for (string s: disallowed_wsls) { msg_printf(NULL, MSG_INFO, - "Config: allowed WSL distro: %s", s.c_str() + "Config: disallowed WSL distro: %s", s.c_str() ); } - if (dont_use_docker) { - msg_printf(NULL, MSG_INFO, "Config: don't use the Docker"); - } for (i=0; i%s\n", - allowed_wsls[i].c_str() + " %s\n", + disallowed_wsls[i].c_str() ); } diff --git a/lib/cc_config.h b/lib/cc_config.h index 620850df5a4..a2c0ba5bb90 100644 --- a/lib/cc_config.h +++ b/lib/cc_config.h @@ -167,7 +167,7 @@ struct CC_CONFIG { bool dont_suspend_nci; bool dont_use_vbox; bool dont_use_wsl; - std::vector allowed_wsls; + std::vector disallowed_wsls; bool dont_use_docker; std::vector exclude_gpus; std::vector exclusive_apps; diff --git a/lib/hostinfo.h b/lib/hostinfo.h index bf58cb9fbba..c365379c090 100644 --- a/lib/hostinfo.h +++ b/lib/hostinfo.h @@ -173,11 +173,7 @@ class HOST_INFO { extern void make_secure_random_string(char*); #ifdef _WIN64 -extern int get_wsl_information( - std::vector &allowed_wsls, - WSL_DISTROS &usable_distros, - bool detect_docker -); +extern int get_wsl_information(WSL_DISTROS &distros); extern int get_processor_group(HANDLE); #endif diff --git a/lib/util.cpp b/lib/util.cpp index f7b5854096f..2f938a6734f 100644 --- a/lib/util.cpp +++ b/lib/util.cpp @@ -686,3 +686,15 @@ bool process_exists(int pid) { } #endif + +string parse_ldd_libc(const char* input) { + char *q = (char*)strchr(input, '\n'); + if (q) *q = 0; + const char *p = strrchr(input, ' '); + if (!p) return ""; + int maj, min; + if (sscanf(p, "%d.%d", &maj, &min) != 2) return ""; + string s = (string)p; + strip_whitespace(s); + return s; +} diff --git a/lib/util.h b/lib/util.h index 50edb8a680e..663856a2b71 100644 --- a/lib/util.h +++ b/lib/util.h @@ -130,6 +130,13 @@ extern int run_command(char *cmd, std::vector &out); // extern int get_real_executable_path(char* path, size_t max_len); +// given a string of the form +// ldd (Ubuntu GLIBC 2.27-3ubuntu1.6) 2.27 +// return "2.27" (or empty string if can't parse) +// + +extern std::string parse_ldd_libc(const char* input); + #ifdef GCL_SIMULATOR extern double simtime; #define time(x) ((int)simtime) diff --git a/lib/wslinfo.cpp b/lib/wslinfo.cpp index bcb1474b705..86805ebd48a 100644 --- a/lib/wslinfo.cpp +++ b/lib/wslinfo.cpp @@ -27,8 +27,10 @@ void WSL_DISTRO::clear() { distro_name = ""; os_name = ""; os_version = ""; + libc_version = ""; + disallowed = false; is_default = false; - wsl_version = 1; + wsl_version = 0; docker_version = ""; docker_compose_version = ""; } @@ -43,14 +45,28 @@ void WSL_DISTRO::write_xml(MIOFILE& f) { " %s\n" " %s\n" " %s\n" - " %d\n" " %d\n", dn, n, v, - is_default ? 1 : 0, wsl_version ); + if (is_default) { + f.printf( + " \n" + ); + } + if (disallowed) { + f.printf( + " \n" + ); + } + if (!libc_version.empty()) { + f.printf( + " %s\n", + libc_version.c_str() + ); + } if (!docker_version.empty()) { f.printf( " %s\n" @@ -82,7 +98,9 @@ int WSL_DISTRO::parse(XML_PARSER& xp) { if (xp.parse_string("distro_name", distro_name)) continue; if (xp.parse_string("os_name", os_name)) continue; if (xp.parse_string("os_version", os_version)) continue; + if (xp.parse_string("libc_version", libc_version)) continue; if (xp.parse_bool("is_default", is_default)) continue; + if (xp.parse_bool("disallowed", disallowed)) continue; if (xp.parse_int("wsl_version", wsl_version)) continue; if (xp.parse_string("docker_version", docker_version)) continue; if (xp.parse_int("docker_type", i)) { @@ -98,6 +116,13 @@ int WSL_DISTRO::parse(XML_PARSER& xp) { return ERR_XML_PARSE; } +int WSL_DISTRO::libc_version_int() { + int maj, min; + int n = sscanf(libc_version.c_str(), "%d.%d", &maj, &min); + if (n==2) return maj*100+min; + return 0; +} + WSL_DISTROS::WSL_DISTROS() { clear(); } @@ -131,7 +156,8 @@ int WSL_DISTROS::parse(XML_PARSER& xp) { } WSL_DISTRO* WSL_DISTROS::find_match( - const char *os_name_regexp, const char *os_version_regexp + const char *os_name_regexp, const char *os_version_regexp, + int min_libc_version ) { std::regex name_regex(os_name_regexp), version_regex(os_version_regexp); for (WSL_DISTRO &wd: distros) { @@ -141,6 +167,9 @@ WSL_DISTRO* WSL_DISTROS::find_match( if (!std::regex_match(wd.os_version.c_str(), version_regex)) { continue; } + if (wd.libc_version_int() < min_libc_version) { + continue; + } return &wd; } return NULL; diff --git a/lib/wslinfo.h b/lib/wslinfo.h index 4677aa5be1c..4b6e239d821 100644 --- a/lib/wslinfo.h +++ b/lib/wslinfo.h @@ -37,10 +37,14 @@ struct WSL_DISTRO { // name of the operating system std::string os_version; // version of the operating system + std::string libc_version; + // version of libc, as reported by ldd --version int wsl_version; // version of WSL (currently 1 or 2) bool is_default; // this is the default distro + bool disallowed; + // disallowed in cc_config.xml std::string docker_version; // version of Docker (or podman) // empty if not present @@ -55,6 +59,7 @@ struct WSL_DISTRO { void clear(); void write_xml(MIOFILE&); int parse(XML_PARSER&); + int libc_version_int(); }; // a set of WSL distros @@ -67,7 +72,8 @@ struct WSL_DISTROS { void write_xml(MIOFILE&); int parse(XML_PARSER&); WSL_DISTRO *find_match( - const char *os_name_regexp, const char *os_version_regexp + const char *os_name_regexp, const char *os_version_regexp, + int min_libc_version ); WSL_DISTRO *find_docker(); // find a distro containing Docker diff --git a/samples/wsl_wrapper/wsl_wrapper.cpp b/samples/wsl_wrapper/wsl_wrapper.cpp index 09dc795849c..0272024441a 100644 --- a/samples/wsl_wrapper/wsl_wrapper.cpp +++ b/samples/wsl_wrapper/wsl_wrapper.cpp @@ -214,6 +214,7 @@ void poll_client_msgs() { int main(int argc, char** argv) { const char *os_name_regexp=".*", *os_version_regexp=".*", *pass_thru=""; + int min_libc_version = 0; for (int i=1; i\n"); char buf[BLOB_SIZE]; diff --git a/sched/sched_types.h b/sched/sched_types.h index cac8aa3f7a3..71795bb98f2 100644 --- a/sched/sched_types.h +++ b/sched/sched_types.h @@ -267,6 +267,9 @@ struct PLATFORM_LIST { std::vector list; }; +// if you add anything: +// - add it to clear() +// - add it to parse() struct SCHEDULER_REQUEST { char authenticator[256]; CLIENT_PLATFORM platform; @@ -339,6 +342,7 @@ struct SCHEDULER_REQUEST { // whether client uses account-based sandbox. -1 = don't know int allow_multiple_clients; // whether client allows multiple clients per host, -1 don't know + bool dont_use_wsl; bool dont_use_docker; bool using_weak_auth; // Request uses weak authenticator.