1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (c) 2023 Oracle and/or its affiliates. 4 * 5 * KUnit test of the handshake upcall mechanism. 6 */ 7 8 #include <kunit/test.h> 9 #include <kunit/visibility.h> 10 11 #include <linux/kernel.h> 12 13 #include <net/sock.h> 14 #include <net/genetlink.h> 15 #include <net/netns/generic.h> 16 17 #include <uapi/linux/handshake.h> 18 #include "handshake.h" 19 20 MODULE_IMPORT_NS("EXPORTED_FOR_KUNIT_TESTING"); 21 22 static int test_accept_func(struct handshake_req *req, struct genl_info *info, 23 int fd) 24 { 25 return 0; 26 } 27 28 static void test_done_func(struct handshake_req *req, int status, 29 struct genl_info *info) 30 { 31 } 32 33 struct handshake_req_alloc_test_param { 34 const char *desc; 35 struct handshake_proto *proto; 36 gfp_t gfp; 37 bool expect_success; 38 }; 39 40 static struct handshake_proto handshake_req_alloc_proto_2 = { 41 .hp_handler_class = HANDSHAKE_HANDLER_CLASS_NONE, 42 }; 43 44 static struct handshake_proto handshake_req_alloc_proto_3 = { 45 .hp_handler_class = HANDSHAKE_HANDLER_CLASS_MAX, 46 }; 47 48 static struct handshake_proto handshake_req_alloc_proto_4 = { 49 .hp_handler_class = HANDSHAKE_HANDLER_CLASS_TLSHD, 50 }; 51 52 static struct handshake_proto handshake_req_alloc_proto_5 = { 53 .hp_handler_class = HANDSHAKE_HANDLER_CLASS_TLSHD, 54 .hp_accept = test_accept_func, 55 }; 56 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, 62 }; 63 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, 68 }; 69 70 static const 71 struct handshake_req_alloc_test_param handshake_req_alloc_params[] = { 72 { 73 .desc = "handshake_req_alloc NULL proto", 74 .proto = NULL, 75 .gfp = GFP_KERNEL, 76 .expect_success = false, 77 }, 78 { 79 .desc = "handshake_req_alloc CLASS_NONE", 80 .proto = &handshake_req_alloc_proto_2, 81 .gfp = GFP_KERNEL, 82 .expect_success = false, 83 }, 84 { 85 .desc = "handshake_req_alloc CLASS_MAX", 86 .proto = &handshake_req_alloc_proto_3, 87 .gfp = GFP_KERNEL, 88 .expect_success = false, 89 }, 90 { 91 .desc = "handshake_req_alloc no callbacks", 92 .proto = &handshake_req_alloc_proto_4, 93 .gfp = GFP_KERNEL, 94 .expect_success = false, 95 }, 96 { 97 .desc = "handshake_req_alloc no done callback", 98 .proto = &handshake_req_alloc_proto_5, 99 .gfp = GFP_KERNEL, 100 .expect_success = false, 101 }, 102 { 103 .desc = "handshake_req_alloc excessive privsize", 104 .proto = &handshake_req_alloc_proto_6, 105 .gfp = GFP_KERNEL | __GFP_NOWARN, 106 .expect_success = false, 107 }, 108 { 109 .desc = "handshake_req_alloc all good", 110 .proto = &handshake_req_alloc_proto_good, 111 .gfp = GFP_KERNEL, 112 .expect_success = true, 113 }, 114 }; 115 116 static void 117 handshake_req_alloc_get_desc(const struct handshake_req_alloc_test_param *param, 118 char *desc) 119 { 120 strscpy(desc, param->desc, KUNIT_PARAM_DESC_SIZE); 121 } 122 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); 126 127 static void handshake_req_alloc_case(struct kunit *test) 128 { 129 const struct handshake_req_alloc_test_param *param = test->param_value; 130 struct handshake_req *result; 131 132 /* Arrange */ 133 134 /* Act */ 135 result = handshake_req_alloc(param->proto, param->gfp); 136 137 /* Assert */ 138 if (param->expect_success) 139 KUNIT_EXPECT_NOT_NULL(test, result); 140 else 141 KUNIT_EXPECT_NULL(test, result); 142 143 kfree(result); 144 } 145 146 static void handshake_req_submit_test1(struct kunit *test) 147 { 148 struct socket *sock; 149 int err, result; 150 151 /* Arrange */ 152 err = __sock_create(&init_net, PF_INET, SOCK_STREAM, IPPROTO_TCP, 153 &sock, 1); 154 KUNIT_ASSERT_EQ(test, err, 0); 155 156 /* Act */ 157 result = handshake_req_submit(sock, NULL, GFP_KERNEL); 158 159 /* Assert */ 160 KUNIT_EXPECT_EQ(test, result, -EINVAL); 161 162 sock_release(sock); 163 } 164 165 static void handshake_req_submit_test2(struct kunit *test) 166 { 167 struct handshake_req *req; 168 int result; 169 170 /* Arrange */ 171 req = handshake_req_alloc(&handshake_req_alloc_proto_good, GFP_KERNEL); 172 KUNIT_ASSERT_NOT_NULL(test, req); 173 174 /* Act */ 175 result = handshake_req_submit(NULL, req, GFP_KERNEL); 176 177 /* Assert */ 178 KUNIT_EXPECT_EQ(test, result, -EINVAL); 179 180 /* handshake_req_submit() destroys @req on error */ 181 } 182 183 static void handshake_req_submit_test3(struct kunit *test) 184 { 185 struct handshake_req *req; 186 struct socket *sock; 187 int err, result; 188 189 /* Arrange */ 190 req = handshake_req_alloc(&handshake_req_alloc_proto_good, GFP_KERNEL); 191 KUNIT_ASSERT_NOT_NULL(test, req); 192 193 err = __sock_create(&init_net, PF_INET, SOCK_STREAM, IPPROTO_TCP, 194 &sock, 1); 195 KUNIT_ASSERT_EQ(test, err, 0); 196 sock->file = NULL; 197 198 /* Act */ 199 result = handshake_req_submit(sock, req, GFP_KERNEL); 200 201 /* Assert */ 202 KUNIT_EXPECT_EQ(test, result, -EINVAL); 203 204 /* handshake_req_submit() destroys @req on error */ 205 sock_release(sock); 206 } 207 208 static void handshake_req_submit_test4(struct kunit *test) 209 { 210 struct handshake_req *req, *result; 211 unsigned long fcount_before; 212 struct socket *sock; 213 struct file *filp; 214 int err; 215 216 /* Arrange */ 217 req = handshake_req_alloc(&handshake_req_alloc_proto_good, GFP_KERNEL); 218 KUNIT_ASSERT_NOT_NULL(test, req); 219 220 err = __sock_create(&init_net, PF_INET, SOCK_STREAM, IPPROTO_TCP, 221 &sock, 1); 222 KUNIT_ASSERT_EQ(test, err, 0); 223 filp = sock_alloc_file(sock, O_NONBLOCK, NULL); 224 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, filp); 225 KUNIT_ASSERT_NOT_NULL(test, sock->sk); 226 sock->file = filp; 227 228 fcount_before = file_count(filp); 229 err = handshake_req_submit(sock, req, GFP_KERNEL); 230 KUNIT_ASSERT_EQ(test, err, 0); 231 KUNIT_EXPECT_EQ(test, file_count(filp), fcount_before + 1); 232 233 /* Act */ 234 result = handshake_req_hash_lookup(sock->sk); 235 236 /* Assert */ 237 KUNIT_EXPECT_NOT_NULL(test, result); 238 KUNIT_EXPECT_PTR_EQ(test, req, result); 239 240 handshake_req_cancel(sock->sk); 241 KUNIT_EXPECT_EQ(test, file_count(filp), fcount_before); 242 fput(filp); 243 } 244 245 static void handshake_req_submit_test5(struct kunit *test) 246 { 247 unsigned long fcount_before; 248 struct handshake_req *req; 249 struct handshake_net *hn; 250 struct socket *sock; 251 struct file *filp; 252 struct net *net; 253 int saved, err; 254 255 /* Arrange */ 256 req = handshake_req_alloc(&handshake_req_alloc_proto_good, GFP_KERNEL); 257 KUNIT_ASSERT_NOT_NULL(test, req); 258 259 err = __sock_create(&init_net, PF_INET, SOCK_STREAM, IPPROTO_TCP, 260 &sock, 1); 261 KUNIT_ASSERT_EQ(test, err, 0); 262 filp = sock_alloc_file(sock, O_NONBLOCK, NULL); 263 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, filp); 264 KUNIT_ASSERT_NOT_NULL(test, sock->sk); 265 sock->file = filp; 266 267 net = sock_net(sock->sk); 268 hn = handshake_pernet(net); 269 KUNIT_ASSERT_NOT_NULL(test, hn); 270 271 saved = hn->hn_pending; 272 hn->hn_pending = hn->hn_pending_max + 1; 273 fcount_before = file_count(filp); 274 275 /* Act */ 276 err = handshake_req_submit(sock, req, GFP_KERNEL); 277 278 /* Assert */ 279 KUNIT_EXPECT_EQ(test, err, -EAGAIN); 280 KUNIT_EXPECT_EQ(test, file_count(filp), fcount_before); 281 282 fput(filp); 283 hn->hn_pending = saved; 284 } 285 286 static void handshake_req_submit_test6(struct kunit *test) 287 { 288 struct handshake_req *req1, *req2; 289 unsigned long fcount_before; 290 struct socket *sock; 291 struct file *filp; 292 int err; 293 294 /* Arrange */ 295 req1 = handshake_req_alloc(&handshake_req_alloc_proto_good, GFP_KERNEL); 296 KUNIT_ASSERT_NOT_NULL(test, req1); 297 req2 = handshake_req_alloc(&handshake_req_alloc_proto_good, GFP_KERNEL); 298 KUNIT_ASSERT_NOT_NULL(test, req2); 299 300 err = __sock_create(&init_net, PF_INET, SOCK_STREAM, IPPROTO_TCP, 301 &sock, 1); 302 KUNIT_ASSERT_EQ(test, err, 0); 303 filp = sock_alloc_file(sock, O_NONBLOCK, NULL); 304 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, filp); 305 KUNIT_ASSERT_NOT_NULL(test, sock->sk); 306 sock->file = filp; 307 fcount_before = file_count(filp); 308 309 /* Act */ 310 err = handshake_req_submit(sock, req1, GFP_KERNEL); 311 KUNIT_ASSERT_EQ(test, err, 0); 312 KUNIT_EXPECT_EQ(test, file_count(filp), fcount_before + 1); 313 err = handshake_req_submit(sock, req2, GFP_KERNEL); 314 315 /* Assert */ 316 KUNIT_EXPECT_EQ(test, err, -EBUSY); 317 KUNIT_EXPECT_EQ(test, file_count(filp), fcount_before + 1); 318 319 handshake_req_cancel(sock->sk); 320 KUNIT_EXPECT_EQ(test, file_count(filp), fcount_before); 321 fput(filp); 322 } 323 324 static void handshake_req_cancel_test1(struct kunit *test) 325 { 326 unsigned long fcount_before; 327 struct handshake_req *req; 328 struct socket *sock; 329 struct file *filp; 330 bool result; 331 int err; 332 333 /* Arrange */ 334 req = handshake_req_alloc(&handshake_req_alloc_proto_good, GFP_KERNEL); 335 KUNIT_ASSERT_NOT_NULL(test, req); 336 337 err = __sock_create(&init_net, PF_INET, SOCK_STREAM, IPPROTO_TCP, 338 &sock, 1); 339 KUNIT_ASSERT_EQ(test, err, 0); 340 341 filp = sock_alloc_file(sock, O_NONBLOCK, NULL); 342 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, filp); 343 sock->file = filp; 344 345 fcount_before = file_count(filp); 346 err = handshake_req_submit(sock, req, GFP_KERNEL); 347 KUNIT_ASSERT_EQ(test, err, 0); 348 KUNIT_EXPECT_EQ(test, file_count(filp), fcount_before + 1); 349 350 /* NB: handshake_req hasn't been accepted */ 351 352 /* Act */ 353 result = handshake_req_cancel(sock->sk); 354 355 /* Assert */ 356 KUNIT_EXPECT_TRUE(test, result); 357 KUNIT_EXPECT_EQ(test, file_count(filp), fcount_before); 358 359 fput(filp); 360 } 361 362 static void handshake_req_cancel_test2(struct kunit *test) 363 { 364 unsigned long fcount_before; 365 struct handshake_req *req, *next; 366 struct handshake_net *hn; 367 struct socket *sock; 368 struct file *filp; 369 struct net *net; 370 bool result; 371 int err; 372 373 /* Arrange */ 374 req = handshake_req_alloc(&handshake_req_alloc_proto_good, GFP_KERNEL); 375 KUNIT_ASSERT_NOT_NULL(test, req); 376 377 err = __sock_create(&init_net, PF_INET, SOCK_STREAM, IPPROTO_TCP, 378 &sock, 1); 379 KUNIT_ASSERT_EQ(test, err, 0); 380 381 filp = sock_alloc_file(sock, O_NONBLOCK, NULL); 382 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, filp); 383 sock->file = filp; 384 385 fcount_before = file_count(filp); 386 err = handshake_req_submit(sock, req, GFP_KERNEL); 387 KUNIT_ASSERT_EQ(test, err, 0); 388 KUNIT_EXPECT_EQ(test, file_count(filp), fcount_before + 1); 389 390 net = sock_net(sock->sk); 391 hn = handshake_pernet(net); 392 KUNIT_ASSERT_NOT_NULL(test, hn); 393 394 /* Pretend to accept this request */ 395 next = handshake_req_next(hn, HANDSHAKE_HANDLER_CLASS_TLSHD); 396 KUNIT_ASSERT_PTR_EQ(test, req, next); 397 /* Simulate FD_PREPARE() consuming the file reference handed 398 * off by handshake_req_next(); see handshake_nl_accept_doit(). 399 */ 400 fput(filp); 401 402 /* Act */ 403 result = handshake_req_cancel(sock->sk); 404 405 /* Assert */ 406 KUNIT_EXPECT_TRUE(test, result); 407 KUNIT_EXPECT_EQ(test, file_count(filp), fcount_before); 408 409 fput(filp); 410 } 411 412 static void handshake_req_cancel_test3(struct kunit *test) 413 { 414 unsigned long fcount_before; 415 struct handshake_req *req, *next; 416 struct handshake_net *hn; 417 struct socket *sock; 418 struct file *filp; 419 struct net *net; 420 bool result; 421 int err; 422 423 /* Arrange */ 424 req = handshake_req_alloc(&handshake_req_alloc_proto_good, GFP_KERNEL); 425 KUNIT_ASSERT_NOT_NULL(test, req); 426 427 err = __sock_create(&init_net, PF_INET, SOCK_STREAM, IPPROTO_TCP, 428 &sock, 1); 429 KUNIT_ASSERT_EQ(test, err, 0); 430 431 filp = sock_alloc_file(sock, O_NONBLOCK, NULL); 432 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, filp); 433 sock->file = filp; 434 435 fcount_before = file_count(filp); 436 err = handshake_req_submit(sock, req, GFP_KERNEL); 437 KUNIT_ASSERT_EQ(test, err, 0); 438 KUNIT_EXPECT_EQ(test, file_count(filp), fcount_before + 1); 439 440 net = sock_net(sock->sk); 441 hn = handshake_pernet(net); 442 KUNIT_ASSERT_NOT_NULL(test, hn); 443 444 /* Pretend to accept this request */ 445 next = handshake_req_next(hn, HANDSHAKE_HANDLER_CLASS_TLSHD); 446 KUNIT_ASSERT_PTR_EQ(test, req, next); 447 /* Simulate FD_PREPARE() consuming the file reference handed 448 * off by handshake_req_next(); see handshake_nl_accept_doit(). 449 */ 450 fput(filp); 451 452 /* Pretend to complete this request */ 453 handshake_complete(next, -ETIMEDOUT, NULL); 454 KUNIT_EXPECT_EQ(test, file_count(filp), fcount_before); 455 456 /* Act */ 457 result = handshake_req_cancel(sock->sk); 458 459 /* Assert */ 460 KUNIT_EXPECT_FALSE(test, result); 461 KUNIT_EXPECT_EQ(test, file_count(filp), fcount_before); 462 463 fput(filp); 464 } 465 466 static struct handshake_req *handshake_req_destroy_test; 467 468 static void test_destroy_func(struct handshake_req *req) 469 { 470 handshake_req_destroy_test = req; 471 } 472 473 static struct handshake_proto handshake_req_alloc_proto_destroy = { 474 .hp_handler_class = HANDSHAKE_HANDLER_CLASS_TLSHD, 475 .hp_accept = test_accept_func, 476 .hp_done = test_done_func, 477 .hp_destroy = test_destroy_func, 478 }; 479 480 static void handshake_req_destroy_test1(struct kunit *test) 481 { 482 unsigned long fcount_before; 483 struct handshake_req *req; 484 struct socket *sock; 485 struct file *filp; 486 int err; 487 488 /* Arrange */ 489 handshake_req_destroy_test = NULL; 490 491 req = handshake_req_alloc(&handshake_req_alloc_proto_destroy, GFP_KERNEL); 492 KUNIT_ASSERT_NOT_NULL(test, req); 493 494 err = __sock_create(&init_net, PF_INET, SOCK_STREAM, IPPROTO_TCP, 495 &sock, 1); 496 KUNIT_ASSERT_EQ(test, err, 0); 497 498 filp = sock_alloc_file(sock, O_NONBLOCK, NULL); 499 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, filp); 500 sock->file = filp; 501 502 fcount_before = file_count(filp); 503 err = handshake_req_submit(sock, req, GFP_KERNEL); 504 KUNIT_ASSERT_EQ(test, err, 0); 505 506 handshake_req_cancel(sock->sk); 507 KUNIT_EXPECT_EQ(test, file_count(filp), fcount_before); 508 509 /* Act */ 510 /* Ensure the close/release/put process has run to 511 * completion before checking the result. 512 */ 513 __fput_sync(filp); 514 515 /* Assert */ 516 KUNIT_EXPECT_PTR_EQ(test, handshake_req_destroy_test, req); 517 } 518 519 static struct kunit_case handshake_api_test_cases[] = { 520 { 521 .name = "req_alloc API fuzzing", 522 .run_case = handshake_req_alloc_case, 523 .generate_params = handshake_req_alloc_gen_params, 524 }, 525 { 526 .name = "req_submit NULL req arg", 527 .run_case = handshake_req_submit_test1, 528 }, 529 { 530 .name = "req_submit NULL sock arg", 531 .run_case = handshake_req_submit_test2, 532 }, 533 { 534 .name = "req_submit NULL sock->file", 535 .run_case = handshake_req_submit_test3, 536 }, 537 { 538 .name = "req_lookup works", 539 .run_case = handshake_req_submit_test4, 540 }, 541 { 542 .name = "req_submit max pending", 543 .run_case = handshake_req_submit_test5, 544 }, 545 { 546 .name = "req_submit multiple", 547 .run_case = handshake_req_submit_test6, 548 }, 549 { 550 .name = "req_cancel before accept", 551 .run_case = handshake_req_cancel_test1, 552 }, 553 { 554 .name = "req_cancel after accept", 555 .run_case = handshake_req_cancel_test2, 556 }, 557 { 558 .name = "req_cancel after done", 559 .run_case = handshake_req_cancel_test3, 560 }, 561 { 562 .name = "req_destroy works", 563 .run_case = handshake_req_destroy_test1, 564 }, 565 {} 566 }; 567 568 static struct kunit_suite handshake_api_suite = { 569 .name = "Handshake API tests", 570 .test_cases = handshake_api_test_cases, 571 }; 572 573 kunit_test_suites(&handshake_api_suite); 574 575 MODULE_DESCRIPTION("Test handshake upcall API functions"); 576 MODULE_LICENSE("GPL"); 577