1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (c) 2023 Oracle and/or its affiliates.
5 * KUnit test of the handshake upcall mechanism.
8 #include <kunit/test.h>
9 #include <kunit/visibility.h>
11 #include <linux/kernel.h>
14 #include <net/genetlink.h>
15 #include <net/netns/generic.h>
17 #include <uapi/linux/handshake.h>
18 #include "handshake.h"
20 MODULE_IMPORT_NS(EXPORTED_FOR_KUNIT_TESTING
);
22 static int test_accept_func(struct handshake_req
*req
, struct genl_info
*info
,
28 static void test_done_func(struct handshake_req
*req
, unsigned int status
,
29 struct genl_info
*info
)
33 struct handshake_req_alloc_test_param
{
35 struct handshake_proto
*proto
;
40 static struct handshake_proto handshake_req_alloc_proto_2
= {
41 .hp_handler_class
= HANDSHAKE_HANDLER_CLASS_NONE
,
44 static struct handshake_proto handshake_req_alloc_proto_3
= {
45 .hp_handler_class
= HANDSHAKE_HANDLER_CLASS_MAX
,
48 static struct handshake_proto handshake_req_alloc_proto_4
= {
49 .hp_handler_class
= HANDSHAKE_HANDLER_CLASS_TLSHD
,
52 static struct handshake_proto handshake_req_alloc_proto_5
= {
53 .hp_handler_class
= HANDSHAKE_HANDLER_CLASS_TLSHD
,
54 .hp_accept
= test_accept_func
,
57 static struct handshake_proto handshake_req_alloc_proto_6
= {
58 .hp_handler_class
= HANDSHAKE_HANDLER_CLASS_TLSHD
,
59 .hp_privsize
= UINT_MAX
,
60 .hp_accept
= test_accept_func
,
61 .hp_done
= test_done_func
,
64 static struct handshake_proto handshake_req_alloc_proto_good
= {
65 .hp_handler_class
= HANDSHAKE_HANDLER_CLASS_TLSHD
,
66 .hp_accept
= test_accept_func
,
67 .hp_done
= test_done_func
,
71 struct handshake_req_alloc_test_param handshake_req_alloc_params
[] = {
73 .desc
= "handshake_req_alloc NULL proto",
76 .expect_success
= false,
79 .desc
= "handshake_req_alloc CLASS_NONE",
80 .proto
= &handshake_req_alloc_proto_2
,
82 .expect_success
= false,
85 .desc
= "handshake_req_alloc CLASS_MAX",
86 .proto
= &handshake_req_alloc_proto_3
,
88 .expect_success
= false,
91 .desc
= "handshake_req_alloc no callbacks",
92 .proto
= &handshake_req_alloc_proto_4
,
94 .expect_success
= false,
97 .desc
= "handshake_req_alloc no done callback",
98 .proto
= &handshake_req_alloc_proto_5
,
100 .expect_success
= false,
103 .desc
= "handshake_req_alloc excessive privsize",
104 .proto
= &handshake_req_alloc_proto_6
,
105 .gfp
= GFP_KERNEL
| __GFP_NOWARN
,
106 .expect_success
= false,
109 .desc
= "handshake_req_alloc all good",
110 .proto
= &handshake_req_alloc_proto_good
,
112 .expect_success
= true,
117 handshake_req_alloc_get_desc(const struct handshake_req_alloc_test_param
*param
,
120 strscpy(desc
, param
->desc
, KUNIT_PARAM_DESC_SIZE
);
123 /* Creates the function handshake_req_alloc_gen_params */
124 KUNIT_ARRAY_PARAM(handshake_req_alloc
, handshake_req_alloc_params
,
125 handshake_req_alloc_get_desc
);
127 static void handshake_req_alloc_case(struct kunit
*test
)
129 const struct handshake_req_alloc_test_param
*param
= test
->param_value
;
130 struct handshake_req
*result
;
135 result
= handshake_req_alloc(param
->proto
, param
->gfp
);
138 if (param
->expect_success
)
139 KUNIT_EXPECT_NOT_NULL(test
, result
);
141 KUNIT_EXPECT_NULL(test
, result
);
146 static void handshake_req_submit_test1(struct kunit
*test
)
152 err
= __sock_create(&init_net
, PF_INET
, SOCK_STREAM
, IPPROTO_TCP
,
154 KUNIT_ASSERT_EQ(test
, err
, 0);
157 result
= handshake_req_submit(sock
, NULL
, GFP_KERNEL
);
160 KUNIT_EXPECT_EQ(test
, result
, -EINVAL
);
165 static void handshake_req_submit_test2(struct kunit
*test
)
167 struct handshake_req
*req
;
171 req
= handshake_req_alloc(&handshake_req_alloc_proto_good
, GFP_KERNEL
);
172 KUNIT_ASSERT_NOT_NULL(test
, req
);
175 result
= handshake_req_submit(NULL
, req
, GFP_KERNEL
);
178 KUNIT_EXPECT_EQ(test
, result
, -EINVAL
);
180 /* handshake_req_submit() destroys @req on error */
183 static void handshake_req_submit_test3(struct kunit
*test
)
185 struct handshake_req
*req
;
190 req
= handshake_req_alloc(&handshake_req_alloc_proto_good
, GFP_KERNEL
);
191 KUNIT_ASSERT_NOT_NULL(test
, req
);
193 err
= __sock_create(&init_net
, PF_INET
, SOCK_STREAM
, IPPROTO_TCP
,
195 KUNIT_ASSERT_EQ(test
, err
, 0);
199 result
= handshake_req_submit(sock
, req
, GFP_KERNEL
);
202 KUNIT_EXPECT_EQ(test
, result
, -EINVAL
);
204 /* handshake_req_submit() destroys @req on error */
208 static void handshake_req_submit_test4(struct kunit
*test
)
210 struct handshake_req
*req
, *result
;
216 req
= handshake_req_alloc(&handshake_req_alloc_proto_good
, GFP_KERNEL
);
217 KUNIT_ASSERT_NOT_NULL(test
, req
);
219 err
= __sock_create(&init_net
, PF_INET
, SOCK_STREAM
, IPPROTO_TCP
,
221 KUNIT_ASSERT_EQ(test
, err
, 0);
222 filp
= sock_alloc_file(sock
, O_NONBLOCK
, NULL
);
223 KUNIT_ASSERT_NOT_ERR_OR_NULL(test
, filp
);
224 KUNIT_ASSERT_NOT_NULL(test
, sock
->sk
);
227 err
= handshake_req_submit(sock
, req
, GFP_KERNEL
);
228 KUNIT_ASSERT_EQ(test
, err
, 0);
231 result
= handshake_req_hash_lookup(sock
->sk
);
234 KUNIT_EXPECT_NOT_NULL(test
, result
);
235 KUNIT_EXPECT_PTR_EQ(test
, req
, result
);
237 handshake_req_cancel(sock
->sk
);
241 static void handshake_req_submit_test5(struct kunit
*test
)
243 struct handshake_req
*req
;
244 struct handshake_net
*hn
;
251 req
= handshake_req_alloc(&handshake_req_alloc_proto_good
, GFP_KERNEL
);
252 KUNIT_ASSERT_NOT_NULL(test
, req
);
254 err
= __sock_create(&init_net
, PF_INET
, SOCK_STREAM
, IPPROTO_TCP
,
256 KUNIT_ASSERT_EQ(test
, err
, 0);
257 filp
= sock_alloc_file(sock
, O_NONBLOCK
, NULL
);
258 KUNIT_ASSERT_NOT_ERR_OR_NULL(test
, filp
);
259 KUNIT_ASSERT_NOT_NULL(test
, sock
->sk
);
262 net
= sock_net(sock
->sk
);
263 hn
= handshake_pernet(net
);
264 KUNIT_ASSERT_NOT_NULL(test
, hn
);
266 saved
= hn
->hn_pending
;
267 hn
->hn_pending
= hn
->hn_pending_max
+ 1;
270 err
= handshake_req_submit(sock
, req
, GFP_KERNEL
);
273 KUNIT_EXPECT_EQ(test
, err
, -EAGAIN
);
276 hn
->hn_pending
= saved
;
279 static void handshake_req_submit_test6(struct kunit
*test
)
281 struct handshake_req
*req1
, *req2
;
287 req1
= handshake_req_alloc(&handshake_req_alloc_proto_good
, GFP_KERNEL
);
288 KUNIT_ASSERT_NOT_NULL(test
, req1
);
289 req2
= handshake_req_alloc(&handshake_req_alloc_proto_good
, GFP_KERNEL
);
290 KUNIT_ASSERT_NOT_NULL(test
, req2
);
292 err
= __sock_create(&init_net
, PF_INET
, SOCK_STREAM
, IPPROTO_TCP
,
294 KUNIT_ASSERT_EQ(test
, err
, 0);
295 filp
= sock_alloc_file(sock
, O_NONBLOCK
, NULL
);
296 KUNIT_ASSERT_NOT_ERR_OR_NULL(test
, filp
);
297 KUNIT_ASSERT_NOT_NULL(test
, sock
->sk
);
301 err
= handshake_req_submit(sock
, req1
, GFP_KERNEL
);
302 KUNIT_ASSERT_EQ(test
, err
, 0);
303 err
= handshake_req_submit(sock
, req2
, GFP_KERNEL
);
306 KUNIT_EXPECT_EQ(test
, err
, -EBUSY
);
308 handshake_req_cancel(sock
->sk
);
312 static void handshake_req_cancel_test1(struct kunit
*test
)
314 struct handshake_req
*req
;
321 req
= handshake_req_alloc(&handshake_req_alloc_proto_good
, GFP_KERNEL
);
322 KUNIT_ASSERT_NOT_NULL(test
, req
);
324 err
= __sock_create(&init_net
, PF_INET
, SOCK_STREAM
, IPPROTO_TCP
,
326 KUNIT_ASSERT_EQ(test
, err
, 0);
328 filp
= sock_alloc_file(sock
, O_NONBLOCK
, NULL
);
329 KUNIT_ASSERT_NOT_ERR_OR_NULL(test
, filp
);
332 err
= handshake_req_submit(sock
, req
, GFP_KERNEL
);
333 KUNIT_ASSERT_EQ(test
, err
, 0);
335 /* NB: handshake_req hasn't been accepted */
338 result
= handshake_req_cancel(sock
->sk
);
341 KUNIT_EXPECT_TRUE(test
, result
);
346 static void handshake_req_cancel_test2(struct kunit
*test
)
348 struct handshake_req
*req
, *next
;
349 struct handshake_net
*hn
;
357 req
= handshake_req_alloc(&handshake_req_alloc_proto_good
, GFP_KERNEL
);
358 KUNIT_ASSERT_NOT_NULL(test
, req
);
360 err
= __sock_create(&init_net
, PF_INET
, SOCK_STREAM
, IPPROTO_TCP
,
362 KUNIT_ASSERT_EQ(test
, err
, 0);
364 filp
= sock_alloc_file(sock
, O_NONBLOCK
, NULL
);
365 KUNIT_ASSERT_NOT_ERR_OR_NULL(test
, filp
);
368 err
= handshake_req_submit(sock
, req
, GFP_KERNEL
);
369 KUNIT_ASSERT_EQ(test
, err
, 0);
371 net
= sock_net(sock
->sk
);
372 hn
= handshake_pernet(net
);
373 KUNIT_ASSERT_NOT_NULL(test
, hn
);
375 /* Pretend to accept this request */
376 next
= handshake_req_next(hn
, HANDSHAKE_HANDLER_CLASS_TLSHD
);
377 KUNIT_ASSERT_PTR_EQ(test
, req
, next
);
380 result
= handshake_req_cancel(sock
->sk
);
383 KUNIT_EXPECT_TRUE(test
, result
);
388 static void handshake_req_cancel_test3(struct kunit
*test
)
390 struct handshake_req
*req
, *next
;
391 struct handshake_net
*hn
;
399 req
= handshake_req_alloc(&handshake_req_alloc_proto_good
, GFP_KERNEL
);
400 KUNIT_ASSERT_NOT_NULL(test
, req
);
402 err
= __sock_create(&init_net
, PF_INET
, SOCK_STREAM
, IPPROTO_TCP
,
404 KUNIT_ASSERT_EQ(test
, err
, 0);
406 filp
= sock_alloc_file(sock
, O_NONBLOCK
, NULL
);
407 KUNIT_ASSERT_NOT_ERR_OR_NULL(test
, filp
);
410 err
= handshake_req_submit(sock
, req
, GFP_KERNEL
);
411 KUNIT_ASSERT_EQ(test
, err
, 0);
413 net
= sock_net(sock
->sk
);
414 hn
= handshake_pernet(net
);
415 KUNIT_ASSERT_NOT_NULL(test
, hn
);
417 /* Pretend to accept this request */
418 next
= handshake_req_next(hn
, HANDSHAKE_HANDLER_CLASS_TLSHD
);
419 KUNIT_ASSERT_PTR_EQ(test
, req
, next
);
421 /* Pretend to complete this request */
422 handshake_complete(next
, -ETIMEDOUT
, NULL
);
425 result
= handshake_req_cancel(sock
->sk
);
428 KUNIT_EXPECT_FALSE(test
, result
);
433 static struct handshake_req
*handshake_req_destroy_test
;
435 static void test_destroy_func(struct handshake_req
*req
)
437 handshake_req_destroy_test
= req
;
440 static struct handshake_proto handshake_req_alloc_proto_destroy
= {
441 .hp_handler_class
= HANDSHAKE_HANDLER_CLASS_TLSHD
,
442 .hp_accept
= test_accept_func
,
443 .hp_done
= test_done_func
,
444 .hp_destroy
= test_destroy_func
,
447 static void handshake_req_destroy_test1(struct kunit
*test
)
449 struct handshake_req
*req
;
455 handshake_req_destroy_test
= NULL
;
457 req
= handshake_req_alloc(&handshake_req_alloc_proto_destroy
, GFP_KERNEL
);
458 KUNIT_ASSERT_NOT_NULL(test
, req
);
460 err
= __sock_create(&init_net
, PF_INET
, SOCK_STREAM
, IPPROTO_TCP
,
462 KUNIT_ASSERT_EQ(test
, err
, 0);
464 filp
= sock_alloc_file(sock
, O_NONBLOCK
, NULL
);
465 KUNIT_ASSERT_NOT_ERR_OR_NULL(test
, filp
);
468 err
= handshake_req_submit(sock
, req
, GFP_KERNEL
);
469 KUNIT_ASSERT_EQ(test
, err
, 0);
471 handshake_req_cancel(sock
->sk
);
474 /* Ensure the close/release/put process has run to
475 * completion before checking the result.
480 KUNIT_EXPECT_PTR_EQ(test
, handshake_req_destroy_test
, req
);
483 static struct kunit_case handshake_api_test_cases
[] = {
485 .name
= "req_alloc API fuzzing",
486 .run_case
= handshake_req_alloc_case
,
487 .generate_params
= handshake_req_alloc_gen_params
,
490 .name
= "req_submit NULL req arg",
491 .run_case
= handshake_req_submit_test1
,
494 .name
= "req_submit NULL sock arg",
495 .run_case
= handshake_req_submit_test2
,
498 .name
= "req_submit NULL sock->file",
499 .run_case
= handshake_req_submit_test3
,
502 .name
= "req_lookup works",
503 .run_case
= handshake_req_submit_test4
,
506 .name
= "req_submit max pending",
507 .run_case
= handshake_req_submit_test5
,
510 .name
= "req_submit multiple",
511 .run_case
= handshake_req_submit_test6
,
514 .name
= "req_cancel before accept",
515 .run_case
= handshake_req_cancel_test1
,
518 .name
= "req_cancel after accept",
519 .run_case
= handshake_req_cancel_test2
,
522 .name
= "req_cancel after done",
523 .run_case
= handshake_req_cancel_test3
,
526 .name
= "req_destroy works",
527 .run_case
= handshake_req_destroy_test1
,
532 static struct kunit_suite handshake_api_suite
= {
533 .name
= "Handshake API tests",
534 .test_cases
= handshake_api_test_cases
,
537 kunit_test_suites(&handshake_api_suite
);
539 MODULE_DESCRIPTION("Test handshake upcall API functions");
540 MODULE_LICENSE("GPL");