From patchwork Mon May 4 17:34:27 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stanislav Fomichev X-Patchwork-Id: 1282919 X-Patchwork-Delegate: bpf@iogearbox.net Return-Path: X-Original-To: incoming-bpf@patchwork.ozlabs.org Delivered-To: patchwork-incoming-bpf@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=23.128.96.18; helo=vger.kernel.org; envelope-from=bpf-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=google.com header.i=@google.com header.a=rsa-sha256 header.s=20161025 header.b=WwLQiw0x; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by ozlabs.org (Postfix) with ESMTP id 49G930536pz9sSm for ; Tue, 5 May 2020 03:34:36 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730396AbgEDReg (ORCPT ); Mon, 4 May 2020 13:34:36 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:52894 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-FAIL-OK-FAIL) by vger.kernel.org with ESMTP id S1730378AbgEDRef (ORCPT ); Mon, 4 May 2020 13:34:35 -0400 Received: from mail-qv1-xf49.google.com (mail-qv1-xf49.google.com [IPv6:2607:f8b0:4864:20::f49]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id D1D7CC061A0F for ; Mon, 4 May 2020 10:34:34 -0700 (PDT) Received: by mail-qv1-xf49.google.com with SMTP id ev8so226772qvb.7 for ; Mon, 04 May 2020 10:34:34 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=BDtpxMOHMu29VlDCmhk8Jml8cnhXkmsBBTxOcB7wsx8=; b=WwLQiw0xH7zc6Vjn+vdpz5+ChyW2zcVg8uEBZwX8mpm5wzQSB4ZrWh3zrCgEIeqEzz FbQV639dGmTzgmyipQLgurTjayr0uD/3tDdi+XYXcDvkdnl+0wx+DE9LQLk+F3M9iRAF SGWgexWtI9hPIVBhZlDwmNLo6wz9zVGg+gLBE1HKiBiZ6zCg6NnZR2aIz6NMqw411JTa Spg26LZgLJlfMVTQveJcMn7FtA7AE7M9Ja41qYkrDKNbOjCb3cBLAHkgYs/wJkdFmTBQ /rQf+r+jVLwK/T0pN2QIEkFLkW19wd6wCShCLYPfRWi4DFUqykEBSmYyi3Fkp4VKKDkg WnlA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=BDtpxMOHMu29VlDCmhk8Jml8cnhXkmsBBTxOcB7wsx8=; b=kGiQqb1btsrJMw7c6JRcDcXhaNLzjQ4KRS3l4Wyd3HGg6jXq+pkiNXLT8VFyWoaihh K+C1DOtlB7mFh86q/SgUvOrE6fRz1tqdjaaz7daJ4T3S1EGv1xBFs10wBFGrlYW8p9Ie pWX6tGB1rwXc8L7M8C05JCJ7PjohTMdORQl23noXzJ9qr7ZmU4GKCFmuU6mzoOhPAe0N qnFFgV3z2aH51nMVqsmA0h8JHYhutV4gVQCy9S1yPPTwQtwE+nzbsAqG+zTDv2ciSaGG KHBniLYZ9+iZ8Og5OqxF6wEko9feuRfNIFWgVOLnhnU/2CygutSJNciSceJ5YpPdsfB2 gtiw== X-Gm-Message-State: AGi0PuaUqY2vQuWPIEyu6L7ed8Jw4kvyiJ+s4Es+bbHrKG3viXH1lnbz rqJj4IwP9SOIhhvc3lnJH6ZPCBE= X-Google-Smtp-Source: APiQypKF5GaqCDIgzfBDsKDpSR2CJqMZ4bfXMEV1UQXqFgbfcp3afwSnU58XTGKUY5p1poUrR+lRsbU= X-Received: by 2002:a05:6214:a0e:: with SMTP id dw14mr169886qvb.185.1588613673835; Mon, 04 May 2020 10:34:33 -0700 (PDT) Date: Mon, 4 May 2020 10:34:27 -0700 In-Reply-To: <20200504173430.6629-1-sdf@google.com> Message-Id: <20200504173430.6629-2-sdf@google.com> Mime-Version: 1.0 References: <20200504173430.6629-1-sdf@google.com> X-Mailer: git-send-email 2.26.2.526.g744177e7f7-goog Subject: [PATCH bpf-next 1/4] selftests/bpf: generalize helpers to control backround listener From: Stanislav Fomichev To: netdev@vger.kernel.org, bpf@vger.kernel.org Cc: davem@davemloft.net, ast@kernel.org, daniel@iogearbox.net, Stanislav Fomichev , Andrey Ignatov Sender: bpf-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: bpf@vger.kernel.org Move the following routines that let us start a background listener thread and connect to a server by fd to the test_prog: * start_server_thread - start background INADDR_ANY thread * stop_server_thread - stop the thread * connect_to_fd - connect to the server identified by fd These will be used in the next commit. Also, extend these helpers to support AF_INET6 and accept the family as an argument. Cc: Andrey Ignatov Signed-off-by: Stanislav Fomichev --- .../selftests/bpf/prog_tests/tcp_rtt.c | 115 +-------------- tools/testing/selftests/bpf/test_progs.c | 138 ++++++++++++++++++ tools/testing/selftests/bpf/test_progs.h | 3 + 3 files changed, 144 insertions(+), 112 deletions(-) diff --git a/tools/testing/selftests/bpf/prog_tests/tcp_rtt.c b/tools/testing/selftests/bpf/prog_tests/tcp_rtt.c index e56b52ab41da..7d2b3b269b5f 100644 --- a/tools/testing/selftests/bpf/prog_tests/tcp_rtt.c +++ b/tools/testing/selftests/bpf/prog_tests/tcp_rtt.c @@ -87,34 +87,6 @@ static int verify_sk(int map_fd, int client_fd, const char *msg, __u32 invoked, return err; } -static int connect_to_server(int server_fd) -{ - struct sockaddr_storage addr; - socklen_t len = sizeof(addr); - int fd; - - fd = socket(AF_INET, SOCK_STREAM, 0); - if (fd < 0) { - log_err("Failed to create client socket"); - return -1; - } - - if (getsockname(server_fd, (struct sockaddr *)&addr, &len)) { - log_err("Failed to get server addr"); - goto out; - } - - if (connect(fd, (const struct sockaddr *)&addr, len) < 0) { - log_err("Fail to connect to server"); - goto out; - } - - return fd; - -out: - close(fd); - return -1; -} static int run_test(int cgroup_fd, int server_fd) { @@ -145,7 +117,7 @@ static int run_test(int cgroup_fd, int server_fd) goto close_bpf_object; } - client_fd = connect_to_server(server_fd); + client_fd = connect_to_fd(AF_INET, server_fd); if (client_fd < 0) { err = -1; goto close_bpf_object; @@ -180,103 +152,22 @@ static int run_test(int cgroup_fd, int server_fd) return err; } -static int start_server(void) -{ - struct sockaddr_in addr = { - .sin_family = AF_INET, - .sin_addr.s_addr = htonl(INADDR_LOOPBACK), - }; - int fd; - - fd = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0); - if (fd < 0) { - log_err("Failed to create server socket"); - return -1; - } - - if (bind(fd, (const struct sockaddr *)&addr, sizeof(addr)) < 0) { - log_err("Failed to bind socket"); - close(fd); - return -1; - } - - return fd; -} - -static pthread_mutex_t server_started_mtx = PTHREAD_MUTEX_INITIALIZER; -static pthread_cond_t server_started = PTHREAD_COND_INITIALIZER; -static volatile bool server_done = false; - -static void *server_thread(void *arg) -{ - struct sockaddr_storage addr; - socklen_t len = sizeof(addr); - int fd = *(int *)arg; - int client_fd; - int err; - - err = listen(fd, 1); - - pthread_mutex_lock(&server_started_mtx); - pthread_cond_signal(&server_started); - pthread_mutex_unlock(&server_started_mtx); - - if (CHECK_FAIL(err < 0)) { - perror("Failed to listed on socket"); - return ERR_PTR(err); - } - - while (true) { - client_fd = accept(fd, (struct sockaddr *)&addr, &len); - if (client_fd == -1 && errno == EAGAIN) { - usleep(50); - continue; - } - break; - } - if (CHECK_FAIL(client_fd < 0)) { - perror("Failed to accept client"); - return ERR_PTR(err); - } - - while (!server_done) - usleep(50); - - close(client_fd); - - return NULL; -} - void test_tcp_rtt(void) { int server_fd, cgroup_fd; - pthread_t tid; - void *server_res; cgroup_fd = test__join_cgroup("/tcp_rtt"); if (CHECK_FAIL(cgroup_fd < 0)) return; - server_fd = start_server(); + server_fd = start_server_thread(AF_INET); if (CHECK_FAIL(server_fd < 0)) goto close_cgroup_fd; - if (CHECK_FAIL(pthread_create(&tid, NULL, server_thread, - (void *)&server_fd))) - goto close_server_fd; - - pthread_mutex_lock(&server_started_mtx); - pthread_cond_wait(&server_started, &server_started_mtx); - pthread_mutex_unlock(&server_started_mtx); - CHECK_FAIL(run_test(cgroup_fd, server_fd)); - server_done = true; - CHECK_FAIL(pthread_join(tid, &server_res)); - CHECK_FAIL(IS_ERR(server_res)); + stop_server_thread(server_fd); -close_server_fd: - close(server_fd); close_cgroup_fd: close(cgroup_fd); } diff --git a/tools/testing/selftests/bpf/test_progs.c b/tools/testing/selftests/bpf/test_progs.c index 93970ec1c9e9..ebf1b3272848 100644 --- a/tools/testing/selftests/bpf/test_progs.c +++ b/tools/testing/selftests/bpf/test_progs.c @@ -371,6 +371,144 @@ void *spin_lock_thread(void *arg) pthread_exit(arg); } +static int start_server(int family) +{ + struct sockaddr_storage addr = {}; + socklen_t len; + int fd; + + if (family == AF_INET) { + struct sockaddr_in *sin = (void *)&addr; + + sin->sin_family = AF_INET; + len = sizeof(*sin); + } else { + struct sockaddr_in6 *sin6 = (void *)&addr; + + sin6->sin6_family = AF_INET6; + len = sizeof(*sin6); + } + + fd = socket(family, SOCK_STREAM | SOCK_NONBLOCK, 0); + if (fd < 0) { + log_err("Failed to create server socket"); + return -1; + } + + if (bind(fd, (const struct sockaddr *)&addr, len) < 0) { + log_err("Failed to bind socket"); + close(fd); + return -1; + } + + return fd; +} + +static pthread_mutex_t server_started_mtx = PTHREAD_MUTEX_INITIALIZER; +static pthread_cond_t server_started = PTHREAD_COND_INITIALIZER; +static volatile bool server_done; +pthread_t server_tid; + +static void *server_thread(void *arg) +{ + struct sockaddr_storage addr; + socklen_t len = sizeof(addr); + int fd = *(int *)arg; + int client_fd; + int err; + + err = listen(fd, 1); + + pthread_mutex_lock(&server_started_mtx); + pthread_cond_signal(&server_started); + pthread_mutex_unlock(&server_started_mtx); + + if (CHECK_FAIL(err < 0)) { + perror("Failed to listed on socket"); + return ERR_PTR(err); + } + + while (true) { + client_fd = accept(fd, (struct sockaddr *)&addr, &len); + if (client_fd == -1 && errno == EAGAIN) { + usleep(50); + continue; + } + break; + } + if (CHECK_FAIL(client_fd < 0)) { + perror("Failed to accept client"); + return ERR_PTR(err); + } + + while (!server_done) + usleep(50); + + close(client_fd); + + return NULL; +} + +int start_server_thread(int family) +{ + int fd = start_server(family); + + if (fd < 0) + return -1; + + if (CHECK_FAIL(pthread_create(&server_tid, NULL, server_thread, + (void *)&fd))) + goto err; + + pthread_mutex_lock(&server_started_mtx); + pthread_cond_wait(&server_started, &server_started_mtx); + pthread_mutex_unlock(&server_started_mtx); + + return fd; +err: + close(fd); + return -1; +} + +void stop_server_thread(int fd) +{ + void *server_res; + + server_done = true; + CHECK_FAIL(pthread_join(server_tid, &server_res)); + CHECK_FAIL(IS_ERR(server_res)); + close(fd); +} + +int connect_to_fd(int family, int server_fd) +{ + struct sockaddr_storage addr; + socklen_t len = sizeof(addr); + int fd; + + fd = socket(family, SOCK_STREAM, 0); + if (fd < 0) { + log_err("Failed to create client socket"); + return -1; + } + + if (getsockname(server_fd, (struct sockaddr *)&addr, &len)) { + log_err("Failed to get server addr"); + goto out; + } + + if (connect(fd, (const struct sockaddr *)&addr, len) < 0) { + log_err("Fail to connect to server with family %d", family); + goto out; + } + + return fd; + +out: + close(fd); + return -1; +} + /* extern declarations for test funcs */ #define DEFINE_TEST(name) extern void test_##name(void); #include diff --git a/tools/testing/selftests/bpf/test_progs.h b/tools/testing/selftests/bpf/test_progs.h index 10188cc8e9e0..363a3f2273a4 100644 --- a/tools/testing/selftests/bpf/test_progs.h +++ b/tools/testing/selftests/bpf/test_progs.h @@ -157,6 +157,9 @@ int compare_map_keys(int map1_fd, int map2_fd); int compare_stack_ips(int smap_fd, int amap_fd, int stack_trace_len); int extract_build_id(char *build_id, size_t size); void *spin_lock_thread(void *arg); +int start_server_thread(int family); +void stop_server_thread(int fd); +int connect_to_fd(int family, int server_fd); #ifdef __x86_64__ #define SYS_NANOSLEEP_KPROBE_NAME "__x64_sys_nanosleep" From patchwork Mon May 4 17:34:28 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stanislav Fomichev X-Patchwork-Id: 1282921 X-Patchwork-Delegate: bpf@iogearbox.net Return-Path: X-Original-To: incoming-bpf@patchwork.ozlabs.org Delivered-To: patchwork-incoming-bpf@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=23.128.96.18; helo=vger.kernel.org; envelope-from=bpf-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=google.com header.i=@google.com header.a=rsa-sha256 header.s=20161025 header.b=roHoMtDs; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by ozlabs.org (Postfix) with ESMTP id 49G9324DyTz9sSW for ; Tue, 5 May 2020 03:34:38 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730407AbgEDReh (ORCPT ); Mon, 4 May 2020 13:34:37 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:52900 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-FAIL-OK-FAIL) by vger.kernel.org with ESMTP id S1729549AbgEDReg (ORCPT ); Mon, 4 May 2020 13:34:36 -0400 Received: from mail-yb1-xb4a.google.com (mail-yb1-xb4a.google.com [IPv6:2607:f8b0:4864:20::b4a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 9299CC061A0E for ; Mon, 4 May 2020 10:34:36 -0700 (PDT) Received: by mail-yb1-xb4a.google.com with SMTP id 186so304102ybq.1 for ; Mon, 04 May 2020 10:34:36 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=2g+oJRYLOrsKuFpc0J3Xz3fus20nXPDKH8t2GbFobk8=; b=roHoMtDszcN/CD2Rh5Zmr2bJhoexhrTpL1LSMEHsEl8SYjCVTjFxAPUQ9W/Q2jlMHb fGLLpiShA5fdYM8cWN4UXLguCsmS9aS14JG954F4KF9eb51EyJAemCBEAuNRf4DWl2Ba qp9l7gI5tQfpuqduGGBnRZKM/5i59UQzq7IWDBIpmePWnFJ1PCyKXua4srz+ShkxuJjh s48JFbLIpMIZuB4AR+Zhj03/pAuqVAjd6a4Vqlje+1hm86V95SLu3KBnPWAK5Ww+7DMa XoJYpJ042uTT0IwOZEHYb9kI+nw3ypEvgYcmuqhNMqEbh6WBHxzJ07GZOnDHzNqkNbUF 4s7w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=2g+oJRYLOrsKuFpc0J3Xz3fus20nXPDKH8t2GbFobk8=; b=o/4WzoqP33GY9oVwhaDm3AM5RSc0iHcTZXnwFFukQ/+hsZ4GDyDJyIKWVa589Fhech R5wF1GiZGTP1CvdIfNd531OZ6QwfQz2FovaoniitAtrCeMj+2QinAs8UlQGXeyYmFfwc lUzhDSEsAofXXLeynecFdTLW11X1rr1JDClISgGmDAdxpO3R4EZ8KSEtWJk2W38RjHAl /BszwEn3TBwn9d3RcCJ4ThCBTEpa5UWeJbwikB7ZQqOOazAjyB6tEgTg3u0DV7GT0WMb 1qJWnd6hTEf738OiGYg4THP2KU1IKI4xzRTfdM9awFRJTBAZFIC3y3jZ4W7xXBj85FKg 1NvQ== X-Gm-Message-State: AGi0PubRvP32jqkwNi9UnvIR8RvIA0srI0n1uKMDXfwKuQoj6Qr1M59Z vI84XPX4tZvmirwymypTHDqEtQc= X-Google-Smtp-Source: APiQypLl2kREBLwI6IEEjPx7r4WPenyVSShCTrUfFujoE2snG5hgA2hrmd8uSHP8+C6cNulfjtnGYYI= X-Received: by 2002:a25:c648:: with SMTP id k69mr480372ybf.340.1588613675655; Mon, 04 May 2020 10:34:35 -0700 (PDT) Date: Mon, 4 May 2020 10:34:28 -0700 In-Reply-To: <20200504173430.6629-1-sdf@google.com> Message-Id: <20200504173430.6629-3-sdf@google.com> Mime-Version: 1.0 References: <20200504173430.6629-1-sdf@google.com> X-Mailer: git-send-email 2.26.2.526.g744177e7f7-goog Subject: [PATCH bpf-next 2/4] selftests/bpf: adopt accept_timeout from sockmap_listen From: Stanislav Fomichev To: netdev@vger.kernel.org, bpf@vger.kernel.org Cc: davem@davemloft.net, ast@kernel.org, daniel@iogearbox.net, Stanislav Fomichev , Andrey Ignatov Sender: bpf-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: bpf@vger.kernel.org Move accept_timeout and recv_timeout to the common place so they can be reused by the other tests. Switch to accept_timeout() in test_progs instead of doing while loop around accept(). This prevents the tests that use start_server_thread/stop_server_thread from being stuck when the error occurs. Cc: Andrey Ignatov Signed-off-by: Stanislav Fomichev --- .../selftests/bpf/prog_tests/sockmap_listen.c | 34 --------------- tools/testing/selftests/bpf/test_progs.c | 43 +++++++++++++++---- tools/testing/selftests/bpf/test_progs.h | 4 ++ 3 files changed, 39 insertions(+), 42 deletions(-) diff --git a/tools/testing/selftests/bpf/prog_tests/sockmap_listen.c b/tools/testing/selftests/bpf/prog_tests/sockmap_listen.c index d7d65a700799..a91c31e64274 100644 --- a/tools/testing/selftests/bpf/prog_tests/sockmap_listen.c +++ b/tools/testing/selftests/bpf/prog_tests/sockmap_listen.c @@ -195,40 +195,6 @@ __ret; \ }) -static int poll_read(int fd, unsigned int timeout_sec) -{ - struct timeval timeout = { .tv_sec = timeout_sec }; - fd_set rfds; - int r; - - FD_ZERO(&rfds); - FD_SET(fd, &rfds); - - r = select(fd + 1, &rfds, NULL, NULL, &timeout); - if (r == 0) - errno = ETIME; - - return r == 1 ? 0 : -1; -} - -static int accept_timeout(int fd, struct sockaddr *addr, socklen_t *len, - unsigned int timeout_sec) -{ - if (poll_read(fd, timeout_sec)) - return -1; - - return accept(fd, addr, len); -} - -static int recv_timeout(int fd, void *buf, size_t len, int flags, - unsigned int timeout_sec) -{ - if (poll_read(fd, timeout_sec)) - return -1; - - return recv(fd, buf, len, flags); -} - static void init_addr_loopback4(struct sockaddr_storage *ss, socklen_t *len) { struct sockaddr_in *addr4 = memset(ss, 0, sizeof(*ss)); diff --git a/tools/testing/selftests/bpf/test_progs.c b/tools/testing/selftests/bpf/test_progs.c index ebf1b3272848..306056bc63ae 100644 --- a/tools/testing/selftests/bpf/test_progs.c +++ b/tools/testing/selftests/bpf/test_progs.c @@ -428,14 +428,7 @@ static void *server_thread(void *arg) return ERR_PTR(err); } - while (true) { - client_fd = accept(fd, (struct sockaddr *)&addr, &len); - if (client_fd == -1 && errno == EAGAIN) { - usleep(50); - continue; - } - break; - } + client_fd = accept_timeout(fd, (struct sockaddr *)&addr, &len, 3); if (CHECK_FAIL(client_fd < 0)) { perror("Failed to accept client"); return ERR_PTR(err); @@ -509,6 +502,40 @@ int connect_to_fd(int family, int server_fd) return -1; } +static int poll_read(int fd, unsigned int timeout_sec) +{ + struct timeval timeout = { .tv_sec = timeout_sec }; + fd_set rfds; + int r; + + FD_ZERO(&rfds); + FD_SET(fd, &rfds); + + r = select(fd + 1, &rfds, NULL, NULL, &timeout); + if (r == 0) + errno = ETIME; + + return r == 1 ? 0 : -1; +} + +int accept_timeout(int fd, struct sockaddr *addr, socklen_t *len, + unsigned int timeout_sec) +{ + if (poll_read(fd, timeout_sec)) + return -1; + + return accept(fd, addr, len); +} + +int recv_timeout(int fd, void *buf, size_t len, int flags, + unsigned int timeout_sec) +{ + if (poll_read(fd, timeout_sec)) + return -1; + + return recv(fd, buf, len, flags); +} + /* extern declarations for test funcs */ #define DEFINE_TEST(name) extern void test_##name(void); #include diff --git a/tools/testing/selftests/bpf/test_progs.h b/tools/testing/selftests/bpf/test_progs.h index 363a3f2273a4..4a48654a4f08 100644 --- a/tools/testing/selftests/bpf/test_progs.h +++ b/tools/testing/selftests/bpf/test_progs.h @@ -160,6 +160,10 @@ void *spin_lock_thread(void *arg); int start_server_thread(int family); void stop_server_thread(int fd); int connect_to_fd(int family, int server_fd); +int accept_timeout(int fd, struct sockaddr *addr, socklen_t *len, + unsigned int timeout_sec); +int recv_timeout(int fd, void *buf, size_t len, int flags, + unsigned int timeout_sec); #ifdef __x86_64__ #define SYS_NANOSLEEP_KPROBE_NAME "__x64_sys_nanosleep" From patchwork Mon May 4 17:34:29 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stanislav Fomichev X-Patchwork-Id: 1282923 X-Patchwork-Delegate: bpf@iogearbox.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=23.128.96.18; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=google.com header.i=@google.com header.a=rsa-sha256 header.s=20161025 header.b=WJKKaDHk; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by ozlabs.org (Postfix) with ESMTP id 49G9344WKFz9sRf for ; Tue, 5 May 2020 03:34:40 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730424AbgEDRej (ORCPT ); Mon, 4 May 2020 13:34:39 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:52912 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-FAIL-OK-FAIL) by vger.kernel.org with ESMTP id S1730404AbgEDRei (ORCPT ); Mon, 4 May 2020 13:34:38 -0400 Received: from mail-yb1-xb4a.google.com (mail-yb1-xb4a.google.com [IPv6:2607:f8b0:4864:20::b4a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id ACA2DC061A0F for ; Mon, 4 May 2020 10:34:38 -0700 (PDT) Received: by mail-yb1-xb4a.google.com with SMTP id r14so234109ybk.21 for ; Mon, 04 May 2020 10:34:38 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=wBE7hm6quI+iooNO3qC1XtqSbOT/H5iFWRQbKwBhMTE=; b=WJKKaDHk/vf/c0Nn0BqzzyJw35wjWGq8OjecyKB9q3mUeYtX/Fo6qSG3eMwhYXjRq/ 09RVKI/+GqGvJgLO+H1q3CKt89P6O0MvASqs25MxVSajaydCv1khR3+Hjyuo41Pxfgzw Pjhm5AWV78S79bCPo8JBpkRKyohJOGEPk0kQv3w5AXA52c2+mV5Xk5OweaB1ueRonkjp aOwsWoJ2U0pRF+AbLCoaO+8/2U/83oDti3foeEaF7OyWCbMlt+PnihKDJ5rRZVMIP9dS wj9hMKsIR1PFEqVmS1XfYi64laC6vBdWqJFYwbNgVxXUDTbW1+e6LTk1d0IhtNJBhz8q F6Fw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=wBE7hm6quI+iooNO3qC1XtqSbOT/H5iFWRQbKwBhMTE=; b=rRDmBxdlE51NB8WZuOpr054imSQZomjPySTsHaXRX3rzI1z1Ud4KngvC81kqc1HkSb lIUQ82c6GuKfptJq1Le2SF7Vac8AdVHvfsaY0tgX9G8Uc4kDR9P53wu8n4AEdWUfQBdw fP7fi6bOxvrIHXc/PbC+D0PCdkYrHLqdxAXtPffOG5G6NNM2rYiXm4Q+/+w0cckXIjBq gCv9Mg31EzHSyTaluodU8B/yIM45MrVCAkz0PKwOknT3NGdDn4xjtTeJyVS/r90ynwQs K0Xz3pScyAoI20zc2Ymq1lcTpEt94HrzCeejeyRb/M0TTBzyJ53uOX0Odb/G8bc6ndi7 HP3g== X-Gm-Message-State: AGi0Pua+ObHA0njq4IUwl1AedhTkjb5jyMtHMvJTrvJ0qQ1K9lX692xF IOVEsVauxkLH3YgR+l6GHzRfsdRiQj8Ujw0ZkqpGACLL+1GjrX7iK0lBa+QBvgA3VE+5huaqSET pdd6Z5IO7CcJ636GkQ9qgoA6hf5lblTwVlUu5lB0aoigL3ooopS/zjw== X-Google-Smtp-Source: APiQypJBba7RWDeEUwV7G604qNN68azWZFCTnB8mAjPgXRWt6PeWtghxoIOZvkxlNI33L4j9WRjSlRs= X-Received: by 2002:a25:3295:: with SMTP id y143mr513997yby.390.1588613677791; Mon, 04 May 2020 10:34:37 -0700 (PDT) Date: Mon, 4 May 2020 10:34:29 -0700 In-Reply-To: <20200504173430.6629-1-sdf@google.com> Message-Id: <20200504173430.6629-4-sdf@google.com> Mime-Version: 1.0 References: <20200504173430.6629-1-sdf@google.com> X-Mailer: git-send-email 2.26.2.526.g744177e7f7-goog Subject: [PATCH bpf-next 3/4] net: refactor arguments of inet{,6}_bind From: Stanislav Fomichev To: netdev@vger.kernel.org, bpf@vger.kernel.org Cc: davem@davemloft.net, ast@kernel.org, daniel@iogearbox.net, Stanislav Fomichev , Andrey Ignatov Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org The intent is to add an additional bind parameter in the next commit. Instead of adding another argument, let's convert all existing flag arguments into an extendable bit field. No functional changes. Cc: Andrey Ignatov Signed-off-by: Stanislav Fomichev --- include/net/inet_common.h | 6 +++++- include/net/ipv6_stubs.h | 2 +- net/core/filter.c | 6 ++++-- net/ipv4/af_inet.c | 10 +++++----- net/ipv6/af_inet6.c | 10 +++++----- 5 files changed, 20 insertions(+), 14 deletions(-) diff --git a/include/net/inet_common.h b/include/net/inet_common.h index ae2ba897675c..a0fb68f5bf59 100644 --- a/include/net/inet_common.h +++ b/include/net/inet_common.h @@ -35,8 +35,12 @@ int inet_shutdown(struct socket *sock, int how); int inet_listen(struct socket *sock, int backlog); void inet_sock_destruct(struct sock *sk); int inet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len); +// Don't allocate port at this moment, defer to connect. +#define BIND_FORCE_ADDRESS_NO_PORT (1 << 0) +// Grab and release socket lock. +#define BIND_WITH_LOCK (1 << 1) int __inet_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len, - bool force_bind_address_no_port, bool with_lock); + u32 flags); int inet_getname(struct socket *sock, struct sockaddr *uaddr, int peer); int inet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg); diff --git a/include/net/ipv6_stubs.h b/include/net/ipv6_stubs.h index a5f7c12c326a..6e622dd3122e 100644 --- a/include/net/ipv6_stubs.h +++ b/include/net/ipv6_stubs.h @@ -63,7 +63,7 @@ extern const struct ipv6_stub *ipv6_stub __read_mostly; /* A stub used by bpf helpers. Similarly ugly as ipv6_stub */ struct ipv6_bpf_stub { int (*inet6_bind)(struct sock *sk, struct sockaddr *uaddr, int addr_len, - bool force_bind_address_no_port, bool with_lock); + u32 flags); struct sock *(*udp6_lib_lookup)(struct net *net, const struct in6_addr *saddr, __be16 sport, const struct in6_addr *daddr, __be16 dport, diff --git a/net/core/filter.c b/net/core/filter.c index dfaf5df13722..fa9ddab5dd1f 100644 --- a/net/core/filter.c +++ b/net/core/filter.c @@ -4538,7 +4538,8 @@ BPF_CALL_3(bpf_bind, struct bpf_sock_addr_kern *, ctx, struct sockaddr *, addr, return err; if (((struct sockaddr_in *)addr)->sin_port != htons(0)) return err; - return __inet_bind(sk, addr, addr_len, true, false); + return __inet_bind(sk, addr, addr_len, + BIND_FORCE_ADDRESS_NO_PORT); #if IS_ENABLED(CONFIG_IPV6) } else if (addr->sa_family == AF_INET6) { if (addr_len < SIN6_LEN_RFC2133) @@ -4548,7 +4549,8 @@ BPF_CALL_3(bpf_bind, struct bpf_sock_addr_kern *, ctx, struct sockaddr *, addr, /* ipv6_bpf_stub cannot be NULL, since it's called from * bpf_cgroup_inet6_connect hook and ipv6 is already loaded */ - return ipv6_bpf_stub->inet6_bind(sk, addr, addr_len, true, false); + return ipv6_bpf_stub->inet6_bind(sk, addr, addr_len, + BIND_FORCE_ADDRESS_NO_PORT); #endif /* CONFIG_IPV6 */ } #endif /* CONFIG_INET */ diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index 6177c4ba0037..68e74b1b0f26 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c @@ -450,12 +450,12 @@ int inet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) if (err) return err; - return __inet_bind(sk, uaddr, addr_len, false, true); + return __inet_bind(sk, uaddr, addr_len, BIND_WITH_LOCK); } EXPORT_SYMBOL(inet_bind); int __inet_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len, - bool force_bind_address_no_port, bool with_lock) + u32 flags) { struct sockaddr_in *addr = (struct sockaddr_in *)uaddr; struct inet_sock *inet = inet_sk(sk); @@ -506,7 +506,7 @@ int __inet_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len, * would be illegal to use them (multicast/broadcast) in * which case the sending device address is used. */ - if (with_lock) + if (flags & BIND_WITH_LOCK) lock_sock(sk); /* Check these errors (active socket, double bind). */ @@ -520,7 +520,7 @@ int __inet_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len, /* Make sure we are allowed to bind here. */ if (snum || !(inet->bind_address_no_port || - force_bind_address_no_port)) { + (flags & BIND_FORCE_ADDRESS_NO_PORT))) { if (sk->sk_prot->get_port(sk, snum)) { inet->inet_saddr = inet->inet_rcv_saddr = 0; err = -EADDRINUSE; @@ -543,7 +543,7 @@ int __inet_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len, sk_dst_reset(sk); err = 0; out_release_sock: - if (with_lock) + if (flags & BIND_WITH_LOCK) release_sock(sk); out: return err; diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c index 345baa0a754f..552c2592b81c 100644 --- a/net/ipv6/af_inet6.c +++ b/net/ipv6/af_inet6.c @@ -273,7 +273,7 @@ static int inet6_create(struct net *net, struct socket *sock, int protocol, } static int __inet6_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len, - bool force_bind_address_no_port, bool with_lock) + u32 flags) { struct sockaddr_in6 *addr = (struct sockaddr_in6 *)uaddr; struct inet_sock *inet = inet_sk(sk); @@ -297,7 +297,7 @@ static int __inet6_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len, !ns_capable(net->user_ns, CAP_NET_BIND_SERVICE)) return -EACCES; - if (with_lock) + if (flags & BIND_WITH_LOCK) lock_sock(sk); /* Check these errors (active socket, double bind). */ @@ -400,7 +400,7 @@ static int __inet6_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len, /* Make sure we are allowed to bind here. */ if (snum || !(inet->bind_address_no_port || - force_bind_address_no_port)) { + (flags & BIND_FORCE_ADDRESS_NO_PORT))) { if (sk->sk_prot->get_port(sk, snum)) { sk->sk_ipv6only = saved_ipv6only; inet_reset_saddr(sk); @@ -423,7 +423,7 @@ static int __inet6_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len, inet->inet_dport = 0; inet->inet_daddr = 0; out: - if (with_lock) + if (flags & BIND_WITH_LOCK) release_sock(sk); return err; out_unlock: @@ -451,7 +451,7 @@ int inet6_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) if (err) return err; - return __inet6_bind(sk, uaddr, addr_len, false, true); + return __inet6_bind(sk, uaddr, addr_len, BIND_WITH_LOCK); } EXPORT_SYMBOL(inet6_bind); From patchwork Mon May 4 17:34:30 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stanislav Fomichev X-Patchwork-Id: 1282925 X-Patchwork-Delegate: bpf@iogearbox.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=23.128.96.18; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=google.com header.i=@google.com header.a=rsa-sha256 header.s=20161025 header.b=ccpCKJDC; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by ozlabs.org (Postfix) with ESMTP id 49G9391ggGz9sSW for ; Tue, 5 May 2020 03:34:45 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730435AbgEDReo (ORCPT ); Mon, 4 May 2020 13:34:44 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:52920 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-FAIL-OK-FAIL) by vger.kernel.org with ESMTP id S1730404AbgEDRek (ORCPT ); Mon, 4 May 2020 13:34:40 -0400 Received: from mail-yb1-xb4a.google.com (mail-yb1-xb4a.google.com [IPv6:2607:f8b0:4864:20::b4a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 64A24C061A0E for ; Mon, 4 May 2020 10:34:40 -0700 (PDT) Received: by mail-yb1-xb4a.google.com with SMTP id b6so279863ybo.8 for ; Mon, 04 May 2020 10:34:40 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=3k3YQgaCXUzr8efzBK8XPW2UxNas7ylH3H0b7KZtn7o=; b=ccpCKJDCQgzBnCk0PxMZk40Z8LEQu1umcFwFh46I+die/9RbrKYNnoGCrqRTedNyDy IPcARYjvdvfZVfGtxIaHPOcRKBSZg9en6Rzy/6JN3OPEo7x51PSFETN4I+6wppZTXUSI gqlKSk67Pf6jFb8KJVNmNjLNZU+xFCZGSndrgCrP53xLjwxJ7Fb35iXj3pEOrvhOnnT9 9se6Iu/TrBsf7ZJgyB+ikEISNGH4oh1xwNT9CFNDY8WKK2xg2fVtfOdrka1g2GZgvex4 uFTRt4dmbfRM9i3okybtOBboQbUEcyD688QSS5o8UKbAvWi6APvob2UC0TASMDF/7RFh RaCQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=3k3YQgaCXUzr8efzBK8XPW2UxNas7ylH3H0b7KZtn7o=; b=gmT8JNMDaf1Iq9vP7P5Yt85HY1SRLuxo26XIUYe5Hk3zNlNe8Avc43Lo2v9eI0L8Mr 6DrhYoF5Qreilb+nGLHRuUjyKkXrj6CDQe8rzk/zVjPp7MbkwgOxNhttuUMUOft7khws JFOjYjU7ENDj3mqezAfwbJC5OFzBVZ/gX4EVEaYVhcecNQp7+MZvWwsINZywxhV+YWeV 0EdbAjPzA1+9Zpuzis4de0xON2ph7bAzL40C9KoM9VsITc+9byYRVkDZib+lVW+A/rYt EKWD6lRw70OtKdd1JPiu90t/XiqGPz2p1oWz23PWoxiNoFgFT0FZhKxIa/URTRLREoQ3 b14g== X-Gm-Message-State: AGi0PuZQARhCvyIX5iHb0dq8LV/VH8bZOdKq637LFMQzKs3Wwilp9bV5 iusA3t+2lv1WNN/0zj9tLM5CNger+smDj3Tk3LKKDlEq4HILWEGg5jNA5lLccNMDWlZwxPNz6wC BqQdF9q1jmq5hrNyjSCNOd7ashBR0M4GtzWwqlneVcXGKmAtuE+ivkg== X-Google-Smtp-Source: APiQypKMqVoIrLhLtY6tcymyJ7/Tgz42lgtux+7311IG2AxgxvaD8bi8g8vfSy/VX4Yx+09QK/genGM= X-Received: by 2002:a25:2:: with SMTP id 2mr537540yba.466.1588613679505; Mon, 04 May 2020 10:34:39 -0700 (PDT) Date: Mon, 4 May 2020 10:34:30 -0700 In-Reply-To: <20200504173430.6629-1-sdf@google.com> Message-Id: <20200504173430.6629-5-sdf@google.com> Mime-Version: 1.0 References: <20200504173430.6629-1-sdf@google.com> X-Mailer: git-send-email 2.26.2.526.g744177e7f7-goog Subject: [PATCH bpf-next 4/4] bpf: allow any port in bpf_bind helper From: Stanislav Fomichev To: netdev@vger.kernel.org, bpf@vger.kernel.org Cc: davem@davemloft.net, ast@kernel.org, daniel@iogearbox.net, Stanislav Fomichev , Andrey Ignatov Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org We want to have a tighter control on what ports we bind to in the BPF_CGROUP_INET{4,6}_CONNECT hooks even if it means connect() becomes slightly more expensive. The expensive part comes from the fact that we now need to call inet_csk_get_port() that verifies that the port is not used and allocates an entry in the hash table for it. Since we can't rely on "snum || !bind_address_no_port" to prevent us from calling POST_BIND hook anymore, let's add another bind flag to indicate that the call site is BPF program. Cc: Andrey Ignatov Signed-off-by: Stanislav Fomichev --- include/net/inet_common.h | 2 + net/core/filter.c | 9 +- net/ipv4/af_inet.c | 10 +- net/ipv6/af_inet6.c | 12 +- .../bpf/prog_tests/connect_force_port.c | 104 ++++++++++++++++++ .../selftests/bpf/progs/connect_force_port4.c | 28 +++++ .../selftests/bpf/progs/connect_force_port6.c | 28 +++++ 7 files changed, 177 insertions(+), 16 deletions(-) create mode 100644 tools/testing/selftests/bpf/prog_tests/connect_force_port.c create mode 100644 tools/testing/selftests/bpf/progs/connect_force_port4.c create mode 100644 tools/testing/selftests/bpf/progs/connect_force_port6.c diff --git a/include/net/inet_common.h b/include/net/inet_common.h index a0fb68f5bf59..4288fd052266 100644 --- a/include/net/inet_common.h +++ b/include/net/inet_common.h @@ -39,6 +39,8 @@ int inet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len); #define BIND_FORCE_ADDRESS_NO_PORT (1 << 0) // Grab and release socket lock. #define BIND_WITH_LOCK (1 << 1) +// Called from BPF program. +#define BIND_FROM_BPF (1 << 2) int __inet_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len, u32 flags); int inet_getname(struct socket *sock, struct sockaddr *uaddr, diff --git a/net/core/filter.c b/net/core/filter.c index fa9ddab5dd1f..fc5161b9ff6a 100644 --- a/net/core/filter.c +++ b/net/core/filter.c @@ -4527,29 +4527,24 @@ BPF_CALL_3(bpf_bind, struct bpf_sock_addr_kern *, ctx, struct sockaddr *, addr, struct sock *sk = ctx->sk; int err; - /* Binding to port can be expensive so it's prohibited in the helper. - * Only binding to IP is supported. - */ err = -EINVAL; if (addr_len < offsetofend(struct sockaddr, sa_family)) return err; if (addr->sa_family == AF_INET) { if (addr_len < sizeof(struct sockaddr_in)) return err; - if (((struct sockaddr_in *)addr)->sin_port != htons(0)) - return err; return __inet_bind(sk, addr, addr_len, + BIND_FROM_BPF | BIND_FORCE_ADDRESS_NO_PORT); #if IS_ENABLED(CONFIG_IPV6) } else if (addr->sa_family == AF_INET6) { if (addr_len < SIN6_LEN_RFC2133) return err; - if (((struct sockaddr_in6 *)addr)->sin6_port != htons(0)) - return err; /* ipv6_bpf_stub cannot be NULL, since it's called from * bpf_cgroup_inet6_connect hook and ipv6 is already loaded */ return ipv6_bpf_stub->inet6_bind(sk, addr, addr_len, + BIND_FROM_BPF | BIND_FORCE_ADDRESS_NO_PORT); #endif /* CONFIG_IPV6 */ } diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index 68e74b1b0f26..fcf0d12a407a 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c @@ -526,10 +526,12 @@ int __inet_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len, err = -EADDRINUSE; goto out_release_sock; } - err = BPF_CGROUP_RUN_PROG_INET4_POST_BIND(sk); - if (err) { - inet->inet_saddr = inet->inet_rcv_saddr = 0; - goto out_release_sock; + if (!(flags & BIND_FROM_BPF)) { + err = BPF_CGROUP_RUN_PROG_INET4_POST_BIND(sk); + if (err) { + inet->inet_saddr = inet->inet_rcv_saddr = 0; + goto out_release_sock; + } } } diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c index 552c2592b81c..771a462a8322 100644 --- a/net/ipv6/af_inet6.c +++ b/net/ipv6/af_inet6.c @@ -407,11 +407,13 @@ static int __inet6_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len, err = -EADDRINUSE; goto out; } - err = BPF_CGROUP_RUN_PROG_INET6_POST_BIND(sk); - if (err) { - sk->sk_ipv6only = saved_ipv6only; - inet_reset_saddr(sk); - goto out; + if (!(flags & BIND_FROM_BPF)) { + err = BPF_CGROUP_RUN_PROG_INET6_POST_BIND(sk); + if (err) { + sk->sk_ipv6only = saved_ipv6only; + inet_reset_saddr(sk); + goto out; + } } } diff --git a/tools/testing/selftests/bpf/prog_tests/connect_force_port.c b/tools/testing/selftests/bpf/prog_tests/connect_force_port.c new file mode 100644 index 000000000000..ef2e5d02f4ad --- /dev/null +++ b/tools/testing/selftests/bpf/prog_tests/connect_force_port.c @@ -0,0 +1,104 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include + +#include "cgroup_helpers.h" + +static int verify_port(int family, int fd, int expected) +{ + struct sockaddr_storage addr; + socklen_t len = sizeof(addr); + __u16 port; + + + if (getsockname(fd, (struct sockaddr *)&addr, &len)) { + log_err("Failed to get server addr"); + return -1; + } + + if (family == AF_INET) + port = ((struct sockaddr_in *)&addr)->sin_port; + else + port = ((struct sockaddr_in6 *)&addr)->sin6_port; + + if (ntohs(port) != expected) { + log_err("Unexpected port %d, expected %d", ntohs(port), + expected); + return -1; + } + + return 0; +} + +static int run_test(int cgroup_fd, int server_fd, int family) +{ + struct bpf_prog_load_attr attr = { + .prog_type = BPF_PROG_TYPE_CGROUP_SOCK_ADDR, + }; + struct bpf_object *obj; + int expected_port; + int prog_fd; + int err; + int fd; + + if (family == AF_INET) { + attr.file = "./connect_force_port4.o"; + attr.expected_attach_type = BPF_CGROUP_INET4_CONNECT; + expected_port = 22222; + } else { + attr.file = "./connect_force_port6.o"; + attr.expected_attach_type = BPF_CGROUP_INET6_CONNECT; + expected_port = 22223; + } + + err = bpf_prog_load_xattr(&attr, &obj, &prog_fd); + if (err) { + log_err("Failed to load BPF object"); + return -1; + } + + err = bpf_prog_attach(prog_fd, cgroup_fd, attr.expected_attach_type, + 0); + if (err) { + log_err("Failed to attach BPF program"); + goto close_bpf_object; + } + + fd = connect_to_fd(family, server_fd); + if (fd < 0) { + err = -1; + goto close_bpf_object; + } + + err = verify_port(family, fd, expected_port); + + close(fd); + +close_bpf_object: + bpf_object__close(obj); + return err; +} + +void test_connect_force_port(void) +{ + int server_fd, cgroup_fd; + + cgroup_fd = test__join_cgroup("/connect_force_port"); + if (CHECK_FAIL(cgroup_fd < 0)) + return; + + server_fd = start_server_thread(AF_INET); + if (CHECK_FAIL(server_fd < 0)) + goto close_cgroup_fd; + CHECK_FAIL(run_test(cgroup_fd, server_fd, AF_INET)); + stop_server_thread(server_fd); + + server_fd = start_server_thread(AF_INET6); + if (CHECK_FAIL(server_fd < 0)) + goto close_cgroup_fd; + CHECK_FAIL(run_test(cgroup_fd, server_fd, AF_INET6)); + stop_server_thread(server_fd); + +close_cgroup_fd: + close(cgroup_fd); +} diff --git a/tools/testing/selftests/bpf/progs/connect_force_port4.c b/tools/testing/selftests/bpf/progs/connect_force_port4.c new file mode 100644 index 000000000000..1b8eb34b2db0 --- /dev/null +++ b/tools/testing/selftests/bpf/progs/connect_force_port4.c @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: GPL-2.0 +#include + +#include +#include +#include +#include + +#include +#include + +char _license[] SEC("license") = "GPL"; +int _version SEC("version") = 1; + +SEC("cgroup/connect4") +int _connect4(struct bpf_sock_addr *ctx) +{ + struct sockaddr_in sa = {}; + + sa.sin_family = AF_INET; + sa.sin_port = bpf_htons(22222); + sa.sin_addr.s_addr = bpf_htonl(0x7f000001); /* 127.0.0.1 */ + + if (bpf_bind(ctx, (struct sockaddr *)&sa, sizeof(sa)) != 0) + return 0; + + return 1; +} diff --git a/tools/testing/selftests/bpf/progs/connect_force_port6.c b/tools/testing/selftests/bpf/progs/connect_force_port6.c new file mode 100644 index 000000000000..8cd1a9e81f64 --- /dev/null +++ b/tools/testing/selftests/bpf/progs/connect_force_port6.c @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: GPL-2.0 +#include + +#include +#include +#include +#include + +#include +#include + +char _license[] SEC("license") = "GPL"; +int _version SEC("version") = 1; + +SEC("cgroup/connect6") +int _connect6(struct bpf_sock_addr *ctx) +{ + struct sockaddr_in6 sa = {}; + + sa.sin6_family = AF_INET; + sa.sin6_port = bpf_htons(22223); + sa.sin6_addr.s6_addr32[3] = bpf_htonl(1); /* ::1 */ + + if (bpf_bind(ctx, (struct sockaddr *)&sa, sizeof(sa)) != 0) + return 0; + + return 1; +}