162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright (c) 2023 Oracle and/or its affiliates. 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * KUnit test of the handshake upcall mechanism. 662306a36Sopenharmony_ci */ 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci#include <kunit/test.h> 962306a36Sopenharmony_ci#include <kunit/visibility.h> 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_ci#include <linux/kernel.h> 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_ci#include <net/sock.h> 1462306a36Sopenharmony_ci#include <net/genetlink.h> 1562306a36Sopenharmony_ci#include <net/netns/generic.h> 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_ci#include <uapi/linux/handshake.h> 1862306a36Sopenharmony_ci#include "handshake.h" 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_ciMODULE_IMPORT_NS(EXPORTED_FOR_KUNIT_TESTING); 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_cistatic int test_accept_func(struct handshake_req *req, struct genl_info *info, 2362306a36Sopenharmony_ci int fd) 2462306a36Sopenharmony_ci{ 2562306a36Sopenharmony_ci return 0; 2662306a36Sopenharmony_ci} 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_cistatic void test_done_func(struct handshake_req *req, unsigned int status, 2962306a36Sopenharmony_ci struct genl_info *info) 3062306a36Sopenharmony_ci{ 3162306a36Sopenharmony_ci} 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_cistruct handshake_req_alloc_test_param { 3462306a36Sopenharmony_ci const char *desc; 3562306a36Sopenharmony_ci struct handshake_proto *proto; 3662306a36Sopenharmony_ci gfp_t gfp; 3762306a36Sopenharmony_ci bool expect_success; 3862306a36Sopenharmony_ci}; 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_cistatic struct handshake_proto handshake_req_alloc_proto_2 = { 4162306a36Sopenharmony_ci .hp_handler_class = HANDSHAKE_HANDLER_CLASS_NONE, 4262306a36Sopenharmony_ci}; 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_cistatic struct handshake_proto handshake_req_alloc_proto_3 = { 4562306a36Sopenharmony_ci .hp_handler_class = HANDSHAKE_HANDLER_CLASS_MAX, 4662306a36Sopenharmony_ci}; 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_cistatic struct handshake_proto handshake_req_alloc_proto_4 = { 4962306a36Sopenharmony_ci .hp_handler_class = HANDSHAKE_HANDLER_CLASS_TLSHD, 5062306a36Sopenharmony_ci}; 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_cistatic struct handshake_proto handshake_req_alloc_proto_5 = { 5362306a36Sopenharmony_ci .hp_handler_class = HANDSHAKE_HANDLER_CLASS_TLSHD, 5462306a36Sopenharmony_ci .hp_accept = test_accept_func, 5562306a36Sopenharmony_ci}; 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_cistatic struct handshake_proto handshake_req_alloc_proto_6 = { 5862306a36Sopenharmony_ci .hp_handler_class = HANDSHAKE_HANDLER_CLASS_TLSHD, 5962306a36Sopenharmony_ci .hp_privsize = UINT_MAX, 6062306a36Sopenharmony_ci .hp_accept = test_accept_func, 6162306a36Sopenharmony_ci .hp_done = test_done_func, 6262306a36Sopenharmony_ci}; 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_cistatic struct handshake_proto handshake_req_alloc_proto_good = { 6562306a36Sopenharmony_ci .hp_handler_class = HANDSHAKE_HANDLER_CLASS_TLSHD, 6662306a36Sopenharmony_ci .hp_accept = test_accept_func, 6762306a36Sopenharmony_ci .hp_done = test_done_func, 6862306a36Sopenharmony_ci}; 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_cistatic const 7162306a36Sopenharmony_cistruct handshake_req_alloc_test_param handshake_req_alloc_params[] = { 7262306a36Sopenharmony_ci { 7362306a36Sopenharmony_ci .desc = "handshake_req_alloc NULL proto", 7462306a36Sopenharmony_ci .proto = NULL, 7562306a36Sopenharmony_ci .gfp = GFP_KERNEL, 7662306a36Sopenharmony_ci .expect_success = false, 7762306a36Sopenharmony_ci }, 7862306a36Sopenharmony_ci { 7962306a36Sopenharmony_ci .desc = "handshake_req_alloc CLASS_NONE", 8062306a36Sopenharmony_ci .proto = &handshake_req_alloc_proto_2, 8162306a36Sopenharmony_ci .gfp = GFP_KERNEL, 8262306a36Sopenharmony_ci .expect_success = false, 8362306a36Sopenharmony_ci }, 8462306a36Sopenharmony_ci { 8562306a36Sopenharmony_ci .desc = "handshake_req_alloc CLASS_MAX", 8662306a36Sopenharmony_ci .proto = &handshake_req_alloc_proto_3, 8762306a36Sopenharmony_ci .gfp = GFP_KERNEL, 8862306a36Sopenharmony_ci .expect_success = false, 8962306a36Sopenharmony_ci }, 9062306a36Sopenharmony_ci { 9162306a36Sopenharmony_ci .desc = "handshake_req_alloc no callbacks", 9262306a36Sopenharmony_ci .proto = &handshake_req_alloc_proto_4, 9362306a36Sopenharmony_ci .gfp = GFP_KERNEL, 9462306a36Sopenharmony_ci .expect_success = false, 9562306a36Sopenharmony_ci }, 9662306a36Sopenharmony_ci { 9762306a36Sopenharmony_ci .desc = "handshake_req_alloc no done callback", 9862306a36Sopenharmony_ci .proto = &handshake_req_alloc_proto_5, 9962306a36Sopenharmony_ci .gfp = GFP_KERNEL, 10062306a36Sopenharmony_ci .expect_success = false, 10162306a36Sopenharmony_ci }, 10262306a36Sopenharmony_ci { 10362306a36Sopenharmony_ci .desc = "handshake_req_alloc excessive privsize", 10462306a36Sopenharmony_ci .proto = &handshake_req_alloc_proto_6, 10562306a36Sopenharmony_ci .gfp = GFP_KERNEL | __GFP_NOWARN, 10662306a36Sopenharmony_ci .expect_success = false, 10762306a36Sopenharmony_ci }, 10862306a36Sopenharmony_ci { 10962306a36Sopenharmony_ci .desc = "handshake_req_alloc all good", 11062306a36Sopenharmony_ci .proto = &handshake_req_alloc_proto_good, 11162306a36Sopenharmony_ci .gfp = GFP_KERNEL, 11262306a36Sopenharmony_ci .expect_success = true, 11362306a36Sopenharmony_ci }, 11462306a36Sopenharmony_ci}; 11562306a36Sopenharmony_ci 11662306a36Sopenharmony_cistatic void 11762306a36Sopenharmony_cihandshake_req_alloc_get_desc(const struct handshake_req_alloc_test_param *param, 11862306a36Sopenharmony_ci char *desc) 11962306a36Sopenharmony_ci{ 12062306a36Sopenharmony_ci strscpy(desc, param->desc, KUNIT_PARAM_DESC_SIZE); 12162306a36Sopenharmony_ci} 12262306a36Sopenharmony_ci 12362306a36Sopenharmony_ci/* Creates the function handshake_req_alloc_gen_params */ 12462306a36Sopenharmony_ciKUNIT_ARRAY_PARAM(handshake_req_alloc, handshake_req_alloc_params, 12562306a36Sopenharmony_ci handshake_req_alloc_get_desc); 12662306a36Sopenharmony_ci 12762306a36Sopenharmony_cistatic void handshake_req_alloc_case(struct kunit *test) 12862306a36Sopenharmony_ci{ 12962306a36Sopenharmony_ci const struct handshake_req_alloc_test_param *param = test->param_value; 13062306a36Sopenharmony_ci struct handshake_req *result; 13162306a36Sopenharmony_ci 13262306a36Sopenharmony_ci /* Arrange */ 13362306a36Sopenharmony_ci 13462306a36Sopenharmony_ci /* Act */ 13562306a36Sopenharmony_ci result = handshake_req_alloc(param->proto, param->gfp); 13662306a36Sopenharmony_ci 13762306a36Sopenharmony_ci /* Assert */ 13862306a36Sopenharmony_ci if (param->expect_success) 13962306a36Sopenharmony_ci KUNIT_EXPECT_NOT_NULL(test, result); 14062306a36Sopenharmony_ci else 14162306a36Sopenharmony_ci KUNIT_EXPECT_NULL(test, result); 14262306a36Sopenharmony_ci 14362306a36Sopenharmony_ci kfree(result); 14462306a36Sopenharmony_ci} 14562306a36Sopenharmony_ci 14662306a36Sopenharmony_cistatic void handshake_req_submit_test1(struct kunit *test) 14762306a36Sopenharmony_ci{ 14862306a36Sopenharmony_ci struct socket *sock; 14962306a36Sopenharmony_ci int err, result; 15062306a36Sopenharmony_ci 15162306a36Sopenharmony_ci /* Arrange */ 15262306a36Sopenharmony_ci err = __sock_create(&init_net, PF_INET, SOCK_STREAM, IPPROTO_TCP, 15362306a36Sopenharmony_ci &sock, 1); 15462306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, err, 0); 15562306a36Sopenharmony_ci 15662306a36Sopenharmony_ci /* Act */ 15762306a36Sopenharmony_ci result = handshake_req_submit(sock, NULL, GFP_KERNEL); 15862306a36Sopenharmony_ci 15962306a36Sopenharmony_ci /* Assert */ 16062306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, result, -EINVAL); 16162306a36Sopenharmony_ci 16262306a36Sopenharmony_ci sock_release(sock); 16362306a36Sopenharmony_ci} 16462306a36Sopenharmony_ci 16562306a36Sopenharmony_cistatic void handshake_req_submit_test2(struct kunit *test) 16662306a36Sopenharmony_ci{ 16762306a36Sopenharmony_ci struct handshake_req *req; 16862306a36Sopenharmony_ci int result; 16962306a36Sopenharmony_ci 17062306a36Sopenharmony_ci /* Arrange */ 17162306a36Sopenharmony_ci req = handshake_req_alloc(&handshake_req_alloc_proto_good, GFP_KERNEL); 17262306a36Sopenharmony_ci KUNIT_ASSERT_NOT_NULL(test, req); 17362306a36Sopenharmony_ci 17462306a36Sopenharmony_ci /* Act */ 17562306a36Sopenharmony_ci result = handshake_req_submit(NULL, req, GFP_KERNEL); 17662306a36Sopenharmony_ci 17762306a36Sopenharmony_ci /* Assert */ 17862306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, result, -EINVAL); 17962306a36Sopenharmony_ci 18062306a36Sopenharmony_ci /* handshake_req_submit() destroys @req on error */ 18162306a36Sopenharmony_ci} 18262306a36Sopenharmony_ci 18362306a36Sopenharmony_cistatic void handshake_req_submit_test3(struct kunit *test) 18462306a36Sopenharmony_ci{ 18562306a36Sopenharmony_ci struct handshake_req *req; 18662306a36Sopenharmony_ci struct socket *sock; 18762306a36Sopenharmony_ci int err, result; 18862306a36Sopenharmony_ci 18962306a36Sopenharmony_ci /* Arrange */ 19062306a36Sopenharmony_ci req = handshake_req_alloc(&handshake_req_alloc_proto_good, GFP_KERNEL); 19162306a36Sopenharmony_ci KUNIT_ASSERT_NOT_NULL(test, req); 19262306a36Sopenharmony_ci 19362306a36Sopenharmony_ci err = __sock_create(&init_net, PF_INET, SOCK_STREAM, IPPROTO_TCP, 19462306a36Sopenharmony_ci &sock, 1); 19562306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, err, 0); 19662306a36Sopenharmony_ci sock->file = NULL; 19762306a36Sopenharmony_ci 19862306a36Sopenharmony_ci /* Act */ 19962306a36Sopenharmony_ci result = handshake_req_submit(sock, req, GFP_KERNEL); 20062306a36Sopenharmony_ci 20162306a36Sopenharmony_ci /* Assert */ 20262306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, result, -EINVAL); 20362306a36Sopenharmony_ci 20462306a36Sopenharmony_ci /* handshake_req_submit() destroys @req on error */ 20562306a36Sopenharmony_ci sock_release(sock); 20662306a36Sopenharmony_ci} 20762306a36Sopenharmony_ci 20862306a36Sopenharmony_cistatic void handshake_req_submit_test4(struct kunit *test) 20962306a36Sopenharmony_ci{ 21062306a36Sopenharmony_ci struct handshake_req *req, *result; 21162306a36Sopenharmony_ci struct socket *sock; 21262306a36Sopenharmony_ci struct file *filp; 21362306a36Sopenharmony_ci int err; 21462306a36Sopenharmony_ci 21562306a36Sopenharmony_ci /* Arrange */ 21662306a36Sopenharmony_ci req = handshake_req_alloc(&handshake_req_alloc_proto_good, GFP_KERNEL); 21762306a36Sopenharmony_ci KUNIT_ASSERT_NOT_NULL(test, req); 21862306a36Sopenharmony_ci 21962306a36Sopenharmony_ci err = __sock_create(&init_net, PF_INET, SOCK_STREAM, IPPROTO_TCP, 22062306a36Sopenharmony_ci &sock, 1); 22162306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, err, 0); 22262306a36Sopenharmony_ci filp = sock_alloc_file(sock, O_NONBLOCK, NULL); 22362306a36Sopenharmony_ci KUNIT_ASSERT_NOT_ERR_OR_NULL(test, filp); 22462306a36Sopenharmony_ci KUNIT_ASSERT_NOT_NULL(test, sock->sk); 22562306a36Sopenharmony_ci sock->file = filp; 22662306a36Sopenharmony_ci 22762306a36Sopenharmony_ci err = handshake_req_submit(sock, req, GFP_KERNEL); 22862306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, err, 0); 22962306a36Sopenharmony_ci 23062306a36Sopenharmony_ci /* Act */ 23162306a36Sopenharmony_ci result = handshake_req_hash_lookup(sock->sk); 23262306a36Sopenharmony_ci 23362306a36Sopenharmony_ci /* Assert */ 23462306a36Sopenharmony_ci KUNIT_EXPECT_NOT_NULL(test, result); 23562306a36Sopenharmony_ci KUNIT_EXPECT_PTR_EQ(test, req, result); 23662306a36Sopenharmony_ci 23762306a36Sopenharmony_ci handshake_req_cancel(sock->sk); 23862306a36Sopenharmony_ci fput(filp); 23962306a36Sopenharmony_ci} 24062306a36Sopenharmony_ci 24162306a36Sopenharmony_cistatic void handshake_req_submit_test5(struct kunit *test) 24262306a36Sopenharmony_ci{ 24362306a36Sopenharmony_ci struct handshake_req *req; 24462306a36Sopenharmony_ci struct handshake_net *hn; 24562306a36Sopenharmony_ci struct socket *sock; 24662306a36Sopenharmony_ci struct file *filp; 24762306a36Sopenharmony_ci struct net *net; 24862306a36Sopenharmony_ci int saved, err; 24962306a36Sopenharmony_ci 25062306a36Sopenharmony_ci /* Arrange */ 25162306a36Sopenharmony_ci req = handshake_req_alloc(&handshake_req_alloc_proto_good, GFP_KERNEL); 25262306a36Sopenharmony_ci KUNIT_ASSERT_NOT_NULL(test, req); 25362306a36Sopenharmony_ci 25462306a36Sopenharmony_ci err = __sock_create(&init_net, PF_INET, SOCK_STREAM, IPPROTO_TCP, 25562306a36Sopenharmony_ci &sock, 1); 25662306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, err, 0); 25762306a36Sopenharmony_ci filp = sock_alloc_file(sock, O_NONBLOCK, NULL); 25862306a36Sopenharmony_ci KUNIT_ASSERT_NOT_ERR_OR_NULL(test, filp); 25962306a36Sopenharmony_ci KUNIT_ASSERT_NOT_NULL(test, sock->sk); 26062306a36Sopenharmony_ci sock->file = filp; 26162306a36Sopenharmony_ci 26262306a36Sopenharmony_ci net = sock_net(sock->sk); 26362306a36Sopenharmony_ci hn = handshake_pernet(net); 26462306a36Sopenharmony_ci KUNIT_ASSERT_NOT_NULL(test, hn); 26562306a36Sopenharmony_ci 26662306a36Sopenharmony_ci saved = hn->hn_pending; 26762306a36Sopenharmony_ci hn->hn_pending = hn->hn_pending_max + 1; 26862306a36Sopenharmony_ci 26962306a36Sopenharmony_ci /* Act */ 27062306a36Sopenharmony_ci err = handshake_req_submit(sock, req, GFP_KERNEL); 27162306a36Sopenharmony_ci 27262306a36Sopenharmony_ci /* Assert */ 27362306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, err, -EAGAIN); 27462306a36Sopenharmony_ci 27562306a36Sopenharmony_ci fput(filp); 27662306a36Sopenharmony_ci hn->hn_pending = saved; 27762306a36Sopenharmony_ci} 27862306a36Sopenharmony_ci 27962306a36Sopenharmony_cistatic void handshake_req_submit_test6(struct kunit *test) 28062306a36Sopenharmony_ci{ 28162306a36Sopenharmony_ci struct handshake_req *req1, *req2; 28262306a36Sopenharmony_ci struct socket *sock; 28362306a36Sopenharmony_ci struct file *filp; 28462306a36Sopenharmony_ci int err; 28562306a36Sopenharmony_ci 28662306a36Sopenharmony_ci /* Arrange */ 28762306a36Sopenharmony_ci req1 = handshake_req_alloc(&handshake_req_alloc_proto_good, GFP_KERNEL); 28862306a36Sopenharmony_ci KUNIT_ASSERT_NOT_NULL(test, req1); 28962306a36Sopenharmony_ci req2 = handshake_req_alloc(&handshake_req_alloc_proto_good, GFP_KERNEL); 29062306a36Sopenharmony_ci KUNIT_ASSERT_NOT_NULL(test, req2); 29162306a36Sopenharmony_ci 29262306a36Sopenharmony_ci err = __sock_create(&init_net, PF_INET, SOCK_STREAM, IPPROTO_TCP, 29362306a36Sopenharmony_ci &sock, 1); 29462306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, err, 0); 29562306a36Sopenharmony_ci filp = sock_alloc_file(sock, O_NONBLOCK, NULL); 29662306a36Sopenharmony_ci KUNIT_ASSERT_NOT_ERR_OR_NULL(test, filp); 29762306a36Sopenharmony_ci KUNIT_ASSERT_NOT_NULL(test, sock->sk); 29862306a36Sopenharmony_ci sock->file = filp; 29962306a36Sopenharmony_ci 30062306a36Sopenharmony_ci /* Act */ 30162306a36Sopenharmony_ci err = handshake_req_submit(sock, req1, GFP_KERNEL); 30262306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, err, 0); 30362306a36Sopenharmony_ci err = handshake_req_submit(sock, req2, GFP_KERNEL); 30462306a36Sopenharmony_ci 30562306a36Sopenharmony_ci /* Assert */ 30662306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, err, -EBUSY); 30762306a36Sopenharmony_ci 30862306a36Sopenharmony_ci handshake_req_cancel(sock->sk); 30962306a36Sopenharmony_ci fput(filp); 31062306a36Sopenharmony_ci} 31162306a36Sopenharmony_ci 31262306a36Sopenharmony_cistatic void handshake_req_cancel_test1(struct kunit *test) 31362306a36Sopenharmony_ci{ 31462306a36Sopenharmony_ci struct handshake_req *req; 31562306a36Sopenharmony_ci struct socket *sock; 31662306a36Sopenharmony_ci struct file *filp; 31762306a36Sopenharmony_ci bool result; 31862306a36Sopenharmony_ci int err; 31962306a36Sopenharmony_ci 32062306a36Sopenharmony_ci /* Arrange */ 32162306a36Sopenharmony_ci req = handshake_req_alloc(&handshake_req_alloc_proto_good, GFP_KERNEL); 32262306a36Sopenharmony_ci KUNIT_ASSERT_NOT_NULL(test, req); 32362306a36Sopenharmony_ci 32462306a36Sopenharmony_ci err = __sock_create(&init_net, PF_INET, SOCK_STREAM, IPPROTO_TCP, 32562306a36Sopenharmony_ci &sock, 1); 32662306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, err, 0); 32762306a36Sopenharmony_ci 32862306a36Sopenharmony_ci filp = sock_alloc_file(sock, O_NONBLOCK, NULL); 32962306a36Sopenharmony_ci KUNIT_ASSERT_NOT_ERR_OR_NULL(test, filp); 33062306a36Sopenharmony_ci sock->file = filp; 33162306a36Sopenharmony_ci 33262306a36Sopenharmony_ci err = handshake_req_submit(sock, req, GFP_KERNEL); 33362306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, err, 0); 33462306a36Sopenharmony_ci 33562306a36Sopenharmony_ci /* NB: handshake_req hasn't been accepted */ 33662306a36Sopenharmony_ci 33762306a36Sopenharmony_ci /* Act */ 33862306a36Sopenharmony_ci result = handshake_req_cancel(sock->sk); 33962306a36Sopenharmony_ci 34062306a36Sopenharmony_ci /* Assert */ 34162306a36Sopenharmony_ci KUNIT_EXPECT_TRUE(test, result); 34262306a36Sopenharmony_ci 34362306a36Sopenharmony_ci fput(filp); 34462306a36Sopenharmony_ci} 34562306a36Sopenharmony_ci 34662306a36Sopenharmony_cistatic void handshake_req_cancel_test2(struct kunit *test) 34762306a36Sopenharmony_ci{ 34862306a36Sopenharmony_ci struct handshake_req *req, *next; 34962306a36Sopenharmony_ci struct handshake_net *hn; 35062306a36Sopenharmony_ci struct socket *sock; 35162306a36Sopenharmony_ci struct file *filp; 35262306a36Sopenharmony_ci struct net *net; 35362306a36Sopenharmony_ci bool result; 35462306a36Sopenharmony_ci int err; 35562306a36Sopenharmony_ci 35662306a36Sopenharmony_ci /* Arrange */ 35762306a36Sopenharmony_ci req = handshake_req_alloc(&handshake_req_alloc_proto_good, GFP_KERNEL); 35862306a36Sopenharmony_ci KUNIT_ASSERT_NOT_NULL(test, req); 35962306a36Sopenharmony_ci 36062306a36Sopenharmony_ci err = __sock_create(&init_net, PF_INET, SOCK_STREAM, IPPROTO_TCP, 36162306a36Sopenharmony_ci &sock, 1); 36262306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, err, 0); 36362306a36Sopenharmony_ci 36462306a36Sopenharmony_ci filp = sock_alloc_file(sock, O_NONBLOCK, NULL); 36562306a36Sopenharmony_ci KUNIT_ASSERT_NOT_ERR_OR_NULL(test, filp); 36662306a36Sopenharmony_ci sock->file = filp; 36762306a36Sopenharmony_ci 36862306a36Sopenharmony_ci err = handshake_req_submit(sock, req, GFP_KERNEL); 36962306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, err, 0); 37062306a36Sopenharmony_ci 37162306a36Sopenharmony_ci net = sock_net(sock->sk); 37262306a36Sopenharmony_ci hn = handshake_pernet(net); 37362306a36Sopenharmony_ci KUNIT_ASSERT_NOT_NULL(test, hn); 37462306a36Sopenharmony_ci 37562306a36Sopenharmony_ci /* Pretend to accept this request */ 37662306a36Sopenharmony_ci next = handshake_req_next(hn, HANDSHAKE_HANDLER_CLASS_TLSHD); 37762306a36Sopenharmony_ci KUNIT_ASSERT_PTR_EQ(test, req, next); 37862306a36Sopenharmony_ci 37962306a36Sopenharmony_ci /* Act */ 38062306a36Sopenharmony_ci result = handshake_req_cancel(sock->sk); 38162306a36Sopenharmony_ci 38262306a36Sopenharmony_ci /* Assert */ 38362306a36Sopenharmony_ci KUNIT_EXPECT_TRUE(test, result); 38462306a36Sopenharmony_ci 38562306a36Sopenharmony_ci fput(filp); 38662306a36Sopenharmony_ci} 38762306a36Sopenharmony_ci 38862306a36Sopenharmony_cistatic void handshake_req_cancel_test3(struct kunit *test) 38962306a36Sopenharmony_ci{ 39062306a36Sopenharmony_ci struct handshake_req *req, *next; 39162306a36Sopenharmony_ci struct handshake_net *hn; 39262306a36Sopenharmony_ci struct socket *sock; 39362306a36Sopenharmony_ci struct file *filp; 39462306a36Sopenharmony_ci struct net *net; 39562306a36Sopenharmony_ci bool result; 39662306a36Sopenharmony_ci int err; 39762306a36Sopenharmony_ci 39862306a36Sopenharmony_ci /* Arrange */ 39962306a36Sopenharmony_ci req = handshake_req_alloc(&handshake_req_alloc_proto_good, GFP_KERNEL); 40062306a36Sopenharmony_ci KUNIT_ASSERT_NOT_NULL(test, req); 40162306a36Sopenharmony_ci 40262306a36Sopenharmony_ci err = __sock_create(&init_net, PF_INET, SOCK_STREAM, IPPROTO_TCP, 40362306a36Sopenharmony_ci &sock, 1); 40462306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, err, 0); 40562306a36Sopenharmony_ci 40662306a36Sopenharmony_ci filp = sock_alloc_file(sock, O_NONBLOCK, NULL); 40762306a36Sopenharmony_ci KUNIT_ASSERT_NOT_ERR_OR_NULL(test, filp); 40862306a36Sopenharmony_ci sock->file = filp; 40962306a36Sopenharmony_ci 41062306a36Sopenharmony_ci err = handshake_req_submit(sock, req, GFP_KERNEL); 41162306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, err, 0); 41262306a36Sopenharmony_ci 41362306a36Sopenharmony_ci net = sock_net(sock->sk); 41462306a36Sopenharmony_ci hn = handshake_pernet(net); 41562306a36Sopenharmony_ci KUNIT_ASSERT_NOT_NULL(test, hn); 41662306a36Sopenharmony_ci 41762306a36Sopenharmony_ci /* Pretend to accept this request */ 41862306a36Sopenharmony_ci next = handshake_req_next(hn, HANDSHAKE_HANDLER_CLASS_TLSHD); 41962306a36Sopenharmony_ci KUNIT_ASSERT_PTR_EQ(test, req, next); 42062306a36Sopenharmony_ci 42162306a36Sopenharmony_ci /* Pretend to complete this request */ 42262306a36Sopenharmony_ci handshake_complete(next, -ETIMEDOUT, NULL); 42362306a36Sopenharmony_ci 42462306a36Sopenharmony_ci /* Act */ 42562306a36Sopenharmony_ci result = handshake_req_cancel(sock->sk); 42662306a36Sopenharmony_ci 42762306a36Sopenharmony_ci /* Assert */ 42862306a36Sopenharmony_ci KUNIT_EXPECT_FALSE(test, result); 42962306a36Sopenharmony_ci 43062306a36Sopenharmony_ci fput(filp); 43162306a36Sopenharmony_ci} 43262306a36Sopenharmony_ci 43362306a36Sopenharmony_cistatic struct handshake_req *handshake_req_destroy_test; 43462306a36Sopenharmony_ci 43562306a36Sopenharmony_cistatic void test_destroy_func(struct handshake_req *req) 43662306a36Sopenharmony_ci{ 43762306a36Sopenharmony_ci handshake_req_destroy_test = req; 43862306a36Sopenharmony_ci} 43962306a36Sopenharmony_ci 44062306a36Sopenharmony_cistatic struct handshake_proto handshake_req_alloc_proto_destroy = { 44162306a36Sopenharmony_ci .hp_handler_class = HANDSHAKE_HANDLER_CLASS_TLSHD, 44262306a36Sopenharmony_ci .hp_accept = test_accept_func, 44362306a36Sopenharmony_ci .hp_done = test_done_func, 44462306a36Sopenharmony_ci .hp_destroy = test_destroy_func, 44562306a36Sopenharmony_ci}; 44662306a36Sopenharmony_ci 44762306a36Sopenharmony_cistatic void handshake_req_destroy_test1(struct kunit *test) 44862306a36Sopenharmony_ci{ 44962306a36Sopenharmony_ci struct handshake_req *req; 45062306a36Sopenharmony_ci struct socket *sock; 45162306a36Sopenharmony_ci struct file *filp; 45262306a36Sopenharmony_ci int err; 45362306a36Sopenharmony_ci 45462306a36Sopenharmony_ci /* Arrange */ 45562306a36Sopenharmony_ci handshake_req_destroy_test = NULL; 45662306a36Sopenharmony_ci 45762306a36Sopenharmony_ci req = handshake_req_alloc(&handshake_req_alloc_proto_destroy, GFP_KERNEL); 45862306a36Sopenharmony_ci KUNIT_ASSERT_NOT_NULL(test, req); 45962306a36Sopenharmony_ci 46062306a36Sopenharmony_ci err = __sock_create(&init_net, PF_INET, SOCK_STREAM, IPPROTO_TCP, 46162306a36Sopenharmony_ci &sock, 1); 46262306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, err, 0); 46362306a36Sopenharmony_ci 46462306a36Sopenharmony_ci filp = sock_alloc_file(sock, O_NONBLOCK, NULL); 46562306a36Sopenharmony_ci KUNIT_ASSERT_NOT_ERR_OR_NULL(test, filp); 46662306a36Sopenharmony_ci sock->file = filp; 46762306a36Sopenharmony_ci 46862306a36Sopenharmony_ci err = handshake_req_submit(sock, req, GFP_KERNEL); 46962306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, err, 0); 47062306a36Sopenharmony_ci 47162306a36Sopenharmony_ci handshake_req_cancel(sock->sk); 47262306a36Sopenharmony_ci 47362306a36Sopenharmony_ci /* Act */ 47462306a36Sopenharmony_ci /* Ensure the close/release/put process has run to 47562306a36Sopenharmony_ci * completion before checking the result. 47662306a36Sopenharmony_ci */ 47762306a36Sopenharmony_ci __fput_sync(filp); 47862306a36Sopenharmony_ci 47962306a36Sopenharmony_ci /* Assert */ 48062306a36Sopenharmony_ci KUNIT_EXPECT_PTR_EQ(test, handshake_req_destroy_test, req); 48162306a36Sopenharmony_ci} 48262306a36Sopenharmony_ci 48362306a36Sopenharmony_cistatic struct kunit_case handshake_api_test_cases[] = { 48462306a36Sopenharmony_ci { 48562306a36Sopenharmony_ci .name = "req_alloc API fuzzing", 48662306a36Sopenharmony_ci .run_case = handshake_req_alloc_case, 48762306a36Sopenharmony_ci .generate_params = handshake_req_alloc_gen_params, 48862306a36Sopenharmony_ci }, 48962306a36Sopenharmony_ci { 49062306a36Sopenharmony_ci .name = "req_submit NULL req arg", 49162306a36Sopenharmony_ci .run_case = handshake_req_submit_test1, 49262306a36Sopenharmony_ci }, 49362306a36Sopenharmony_ci { 49462306a36Sopenharmony_ci .name = "req_submit NULL sock arg", 49562306a36Sopenharmony_ci .run_case = handshake_req_submit_test2, 49662306a36Sopenharmony_ci }, 49762306a36Sopenharmony_ci { 49862306a36Sopenharmony_ci .name = "req_submit NULL sock->file", 49962306a36Sopenharmony_ci .run_case = handshake_req_submit_test3, 50062306a36Sopenharmony_ci }, 50162306a36Sopenharmony_ci { 50262306a36Sopenharmony_ci .name = "req_lookup works", 50362306a36Sopenharmony_ci .run_case = handshake_req_submit_test4, 50462306a36Sopenharmony_ci }, 50562306a36Sopenharmony_ci { 50662306a36Sopenharmony_ci .name = "req_submit max pending", 50762306a36Sopenharmony_ci .run_case = handshake_req_submit_test5, 50862306a36Sopenharmony_ci }, 50962306a36Sopenharmony_ci { 51062306a36Sopenharmony_ci .name = "req_submit multiple", 51162306a36Sopenharmony_ci .run_case = handshake_req_submit_test6, 51262306a36Sopenharmony_ci }, 51362306a36Sopenharmony_ci { 51462306a36Sopenharmony_ci .name = "req_cancel before accept", 51562306a36Sopenharmony_ci .run_case = handshake_req_cancel_test1, 51662306a36Sopenharmony_ci }, 51762306a36Sopenharmony_ci { 51862306a36Sopenharmony_ci .name = "req_cancel after accept", 51962306a36Sopenharmony_ci .run_case = handshake_req_cancel_test2, 52062306a36Sopenharmony_ci }, 52162306a36Sopenharmony_ci { 52262306a36Sopenharmony_ci .name = "req_cancel after done", 52362306a36Sopenharmony_ci .run_case = handshake_req_cancel_test3, 52462306a36Sopenharmony_ci }, 52562306a36Sopenharmony_ci { 52662306a36Sopenharmony_ci .name = "req_destroy works", 52762306a36Sopenharmony_ci .run_case = handshake_req_destroy_test1, 52862306a36Sopenharmony_ci }, 52962306a36Sopenharmony_ci {} 53062306a36Sopenharmony_ci}; 53162306a36Sopenharmony_ci 53262306a36Sopenharmony_cistatic struct kunit_suite handshake_api_suite = { 53362306a36Sopenharmony_ci .name = "Handshake API tests", 53462306a36Sopenharmony_ci .test_cases = handshake_api_test_cases, 53562306a36Sopenharmony_ci}; 53662306a36Sopenharmony_ci 53762306a36Sopenharmony_cikunit_test_suites(&handshake_api_suite); 53862306a36Sopenharmony_ci 53962306a36Sopenharmony_ciMODULE_DESCRIPTION("Test handshake upcall API functions"); 54062306a36Sopenharmony_ciMODULE_LICENSE("GPL"); 541