From 72217cac0affebf410ff41ac3224f554eea14fa7 Mon Sep 17 00:00:00 2001 From: Sebastien Buisson Date: Sat, 17 Feb 2024 13:27:15 +0100 Subject: [PATCH] LU-17175 gss: background speedtest for Miller-Rabin rounds The number of rounds used for Miller-Rabin testing of the prime provided as input parameter to DH_check() is evaluated when the lsvcgssd daemon starts. This speed test takes between 5 and 10 seconds so it makes sense to run it in the background. Any prime tested before the right number of rounds has been determined would use the default from OpenSSL. This can lead to longer request processing time, but this is only for a temporary and short period of time. Lustre-change: https://review.whamcloud.com/54088 Lustre-commit: d753dc75ad2a919e5fff3bc51c20b4569cd86a86 Test-Parameters: trivial Test-Parameters: testgroup=review-dne-selinux-ssk-part-1 Test-Parameters: testgroup=review-dne-selinux-ssk-part-2 Signed-off-by: Sebastien Buisson Change-Id: If77f4374c5af463fdadd15979a594af1786af1df Reviewed-by: Andreas Dilger Reviewed-on: https://review.whamcloud.com/c/ex/lustre-release/+/54278 Tested-by: jenkins Tested-by: Maloo --- lustre/tests/test-framework.sh | 9 ++++--- lustre/utils/gss/sk_utils.c | 30 ++++++++++++++++++++- lustre/utils/gss/sk_utils.h | 2 +- lustre/utils/gss/svcgssd.h | 2 +- lustre/utils/gss/svcgssd_main_loop.c | 51 ++++++++++++++++++++++++++++-------- lustre/utils/gss/svcgssd_proc.c | 2 +- 6 files changed, 78 insertions(+), 18 deletions(-) diff --git a/lustre/tests/test-framework.sh b/lustre/tests/test-framework.sh index e73d6cc..2e709c8 100755 --- a/lustre/tests/test-framework.sh +++ b/lustre/tests/test-framework.sh @@ -960,10 +960,13 @@ check_gss_daemon_nodes() { local ret dname=$(basename "$dname" | awk '{print $1}') - do_nodesv $list "num=\\\$(ps -o cmd -C $dname | grep $dname | wc -l); + do_nodesv $list "num=0; +for proc in \\\$(pgrep $dname); do +[ \\\$(ps -o ppid= -p \\\$proc) -ne 1 ] || ((num++)) +done; if [ \\\"\\\$num\\\" -ne 1 ]; then - echo \\\$num instance of $dname; - exit 1; + echo \\\$num instance of $dname; + exit 1; fi; " ret=$? (( $ret == 0 )) || return $ret diff --git a/lustre/utils/gss/sk_utils.c b/lustre/utils/gss/sk_utils.c index efcef1ee..29d5e5f 100644 --- a/lustre/utils/gss/sk_utils.c +++ b/lustre/utils/gss/sk_utils.c @@ -44,6 +44,7 @@ #include #include #include +#include #include "sk_utils.h" #include "write_bytes.h" @@ -838,12 +839,39 @@ static unsigned char test_prime[VALUE_LENGTH] = * \retval max number of rounds to keep prime testing under usec_check_max * return 0 if we should use the default DH_check rounds */ -int sk_speedtest_dh_valid(unsigned int usec_check_max) +int sk_speedtest_dh_valid(unsigned int usec_check_max, pid_t *child) { DH *dh; BIGNUM *p, *g; + struct sigaction sa; int num_rounds, prev_rounds = 0; + /* Set SIGCHLD disposition so that child that terminates + * does not become a zombie. + */ + sa.sa_handler = NULL; + sigemptyset(&sa.sa_mask); + sa.sa_flags = SA_NOCLDWAIT; + if (sigaction(SIGCHLD, &sa, NULL) == -1) + printerr(2, "SIGCHLD sigaction failed\n"); + + *child = fork(); + if (*child == -1) { + printerr(0, "cannot fork child for speedtest: %s\n", + strerror(errno)); + /* in this case the speedtest cannot be run, so return 0 + * to use default num rounds for prime testing + */ + return 0; + } else if (*child != 0) { + /* parent returns immediately, + * 0 means num rounds is not determined yet + */ + return 0; + } + + /* now in forked child process, start speed test */ + dh = DH_new(); if (!dh) return 0; diff --git a/lustre/utils/gss/sk_utils.h b/lustre/utils/gss/sk_utils.h index 0fb3af3..4de88e9 100644 --- a/lustre/utils/gss/sk_utils.h +++ b/lustre/utils/gss/sk_utils.h @@ -380,7 +380,7 @@ uint32_t sk_verify_hash(const char *string, const EVP_MD *hash_alg, struct sk_cred *sk_create_cred(const char *fsname, const char *cluster, const uint32_t flags); #ifndef HAVE_OPENSSL_EVP_PKEY -int sk_speedtest_dh_valid(unsigned int usec_check_max); +int sk_speedtest_dh_valid(unsigned int usec_check_max, pid_t *child); #endif uint32_t sk_gen_params(struct sk_cred *skc, int num_rounds); int sk_sign_bufs(gss_buffer_desc *key, gss_buffer_desc *bufs, const int numbufs, diff --git a/lustre/utils/gss/svcgssd.h b/lustre/utils/gss/svcgssd.h index 936267d..dac11ff 100644 --- a/lustre/utils/gss/svcgssd.h +++ b/lustre/utils/gss/svcgssd.h @@ -47,7 +47,7 @@ extern char *oss_local_realm; extern int null_enabled; extern int krb_enabled; extern int sk_enabled; -extern int sk_dh_checks; +extern int *sk_dh_checks; #define GSSD_SERVICE_NAME "lustre" diff --git a/lustre/utils/gss/svcgssd_main_loop.c b/lustre/utils/gss/svcgssd_main_loop.c index b0d9f89..c3a0a4c 100644 --- a/lustre/utils/gss/svcgssd_main_loop.c +++ b/lustre/utils/gss/svcgssd_main_loop.c @@ -45,6 +45,7 @@ #include /* For nanosleep() */ #include +#include #include "cacheio.h" #include "svcgssd.h" @@ -54,25 +55,48 @@ /* max allowed time for prime testing: 400 ms */ #define MAX_ALLOWED_TIME_FOR_PRIME 400000 -int sk_dh_checks; +int *sk_dh_checks; void svcgssd_run(void) { - int local_socket, remote_socket; + int local_socket = -1, remote_socket; struct sockaddr_un addr; bool retried = false; - int ret = 0; +#if !defined(HAVE_OPENSSL_EVP_PKEY) && OPENSSL_VERSION_NUMBER >= 0x1010103fL + pid_t child = 1; +#endif + int ret = EXIT_SUCCESS; if (sk_enabled) { + sk_dh_checks = mmap(NULL, sizeof(int), PROT_READ | PROT_WRITE, + MAP_SHARED | MAP_ANONYMOUS, -1, 0); + if (sk_dh_checks == MAP_FAILED) { + printerr(LL_ERR, + "cannot mmap memory for sk_dh_checks: %s\n", + strerror(errno)); + ret = EXIT_FAILURE; + goto out_close; + } + #if !defined(HAVE_OPENSSL_EVP_PKEY) && OPENSSL_VERSION_NUMBER >= 0x1010103fL - sk_dh_checks = - sk_speedtest_dh_valid(MAX_ALLOWED_TIME_FOR_PRIME); - if (sk_dh_checks) + /* child will run asynchronously, parent will not wait for it */ + *sk_dh_checks = + sk_speedtest_dh_valid(MAX_ALLOWED_TIME_FOR_PRIME, + &child); + if (*sk_dh_checks) printerr(LL_WARN, "will use %d rounds for prime testing\n", - sk_dh_checks); + *sk_dh_checks); + else + printerr(LL_WARN, + "will use default number of rounds for prime testing\n"); + if (child == 0) + /* job done for child */ + exit(EXIT_SUCCESS); #else - sk_dh_checks = 0; + *sk_dh_checks = 0; + printerr(LL_WARN, + "will use default number of rounds for prime testing\n"); #endif } else { /* For krb, preload mapping table if any */ @@ -83,7 +107,7 @@ again: local_socket = socket(AF_UNIX, SOCK_STREAM, 0); if (local_socket == -1) { printerr(LL_ERR, "unable to create socket: %d\n", -errno); - ret = 1; + ret = EXIT_FAILURE; goto out_close; } @@ -99,13 +123,13 @@ again: goto again; } printerr(LL_ERR, "unable to bind socket: %d\n", -errno); - ret = 1; + ret = EXIT_FAILURE; goto out_close; } if (listen(local_socket, 10) == -1) { printerr(LL_ERR, "unable to listen on socket: %d\n", -errno); - ret = 1; + ret = EXIT_FAILURE; goto out; } @@ -126,5 +150,10 @@ out: out_close: if (local_socket >= 0) close(local_socket); + if (munmap(sk_dh_checks, sizeof(int)) == -1) { + printerr(LL_ERR, "cannot munmap memory for sk_dh_checks: %s\n", + strerror(errno)); + ret = EXIT_FAILURE; + } exit(ret); } diff --git a/lustre/utils/gss/svcgssd_proc.c b/lustre/utils/gss/svcgssd_proc.c index 88e061a..f730c16 100644 --- a/lustre/utils/gss/svcgssd_proc.c +++ b/lustre/utils/gss/svcgssd_proc.c @@ -601,7 +601,7 @@ int handle_sk(struct svc_nego_data *snd) } redo: - rc = sk_gen_params(skc, sk_dh_checks); + rc = sk_gen_params(skc, *sk_dh_checks); if (rc != GSS_S_COMPLETE) { printerr(LL_ERR, "Failed to generate DH params for responder\n"); -- 1.8.3.1