18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci// Copyright (c) 2018 Facebook 38c2ecf20Sopenharmony_ci 48c2ecf20Sopenharmony_ci#include <string.h> 58c2ecf20Sopenharmony_ci#include <unistd.h> 68c2ecf20Sopenharmony_ci 78c2ecf20Sopenharmony_ci#include <arpa/inet.h> 88c2ecf20Sopenharmony_ci#include <netinet/in.h> 98c2ecf20Sopenharmony_ci#include <sys/types.h> 108c2ecf20Sopenharmony_ci#include <sys/socket.h> 118c2ecf20Sopenharmony_ci 128c2ecf20Sopenharmony_ci#include <bpf/bpf.h> 138c2ecf20Sopenharmony_ci#include <bpf/libbpf.h> 148c2ecf20Sopenharmony_ci 158c2ecf20Sopenharmony_ci#include "bpf_rlimit.h" 168c2ecf20Sopenharmony_ci#include "cgroup_helpers.h" 178c2ecf20Sopenharmony_ci 188c2ecf20Sopenharmony_ci#define CG_PATH "/foo" 198c2ecf20Sopenharmony_ci#define SOCKET_COOKIE_PROG "./socket_cookie_prog.o" 208c2ecf20Sopenharmony_ci 218c2ecf20Sopenharmony_cistruct socket_cookie { 228c2ecf20Sopenharmony_ci __u64 cookie_key; 238c2ecf20Sopenharmony_ci __u32 cookie_value; 248c2ecf20Sopenharmony_ci}; 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_cistatic int start_server(void) 278c2ecf20Sopenharmony_ci{ 288c2ecf20Sopenharmony_ci struct sockaddr_in6 addr; 298c2ecf20Sopenharmony_ci int fd; 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_ci fd = socket(AF_INET6, SOCK_STREAM, 0); 328c2ecf20Sopenharmony_ci if (fd == -1) { 338c2ecf20Sopenharmony_ci log_err("Failed to create server socket"); 348c2ecf20Sopenharmony_ci goto out; 358c2ecf20Sopenharmony_ci } 368c2ecf20Sopenharmony_ci 378c2ecf20Sopenharmony_ci memset(&addr, 0, sizeof(addr)); 388c2ecf20Sopenharmony_ci addr.sin6_family = AF_INET6; 398c2ecf20Sopenharmony_ci addr.sin6_addr = in6addr_loopback; 408c2ecf20Sopenharmony_ci addr.sin6_port = 0; 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_ci if (bind(fd, (const struct sockaddr *)&addr, sizeof(addr)) == -1) { 438c2ecf20Sopenharmony_ci log_err("Failed to bind server socket"); 448c2ecf20Sopenharmony_ci goto close_out; 458c2ecf20Sopenharmony_ci } 468c2ecf20Sopenharmony_ci 478c2ecf20Sopenharmony_ci if (listen(fd, 128) == -1) { 488c2ecf20Sopenharmony_ci log_err("Failed to listen on server socket"); 498c2ecf20Sopenharmony_ci goto close_out; 508c2ecf20Sopenharmony_ci } 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_ci goto out; 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_ciclose_out: 558c2ecf20Sopenharmony_ci close(fd); 568c2ecf20Sopenharmony_ci fd = -1; 578c2ecf20Sopenharmony_ciout: 588c2ecf20Sopenharmony_ci return fd; 598c2ecf20Sopenharmony_ci} 608c2ecf20Sopenharmony_ci 618c2ecf20Sopenharmony_cistatic int connect_to_server(int server_fd) 628c2ecf20Sopenharmony_ci{ 638c2ecf20Sopenharmony_ci struct sockaddr_storage addr; 648c2ecf20Sopenharmony_ci socklen_t len = sizeof(addr); 658c2ecf20Sopenharmony_ci int fd; 668c2ecf20Sopenharmony_ci 678c2ecf20Sopenharmony_ci fd = socket(AF_INET6, SOCK_STREAM, 0); 688c2ecf20Sopenharmony_ci if (fd == -1) { 698c2ecf20Sopenharmony_ci log_err("Failed to create client socket"); 708c2ecf20Sopenharmony_ci goto out; 718c2ecf20Sopenharmony_ci } 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_ci if (getsockname(server_fd, (struct sockaddr *)&addr, &len)) { 748c2ecf20Sopenharmony_ci log_err("Failed to get server addr"); 758c2ecf20Sopenharmony_ci goto close_out; 768c2ecf20Sopenharmony_ci } 778c2ecf20Sopenharmony_ci 788c2ecf20Sopenharmony_ci if (connect(fd, (const struct sockaddr *)&addr, len) == -1) { 798c2ecf20Sopenharmony_ci log_err("Fail to connect to server"); 808c2ecf20Sopenharmony_ci goto close_out; 818c2ecf20Sopenharmony_ci } 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_ci goto out; 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_ciclose_out: 868c2ecf20Sopenharmony_ci close(fd); 878c2ecf20Sopenharmony_ci fd = -1; 888c2ecf20Sopenharmony_ciout: 898c2ecf20Sopenharmony_ci return fd; 908c2ecf20Sopenharmony_ci} 918c2ecf20Sopenharmony_ci 928c2ecf20Sopenharmony_cistatic int validate_map(struct bpf_map *map, int client_fd) 938c2ecf20Sopenharmony_ci{ 948c2ecf20Sopenharmony_ci __u32 cookie_expected_value; 958c2ecf20Sopenharmony_ci struct sockaddr_in6 addr; 968c2ecf20Sopenharmony_ci socklen_t len = sizeof(addr); 978c2ecf20Sopenharmony_ci struct socket_cookie val; 988c2ecf20Sopenharmony_ci int err = 0; 998c2ecf20Sopenharmony_ci int map_fd; 1008c2ecf20Sopenharmony_ci 1018c2ecf20Sopenharmony_ci if (!map) { 1028c2ecf20Sopenharmony_ci log_err("Map not found in BPF object"); 1038c2ecf20Sopenharmony_ci goto err; 1048c2ecf20Sopenharmony_ci } 1058c2ecf20Sopenharmony_ci 1068c2ecf20Sopenharmony_ci map_fd = bpf_map__fd(map); 1078c2ecf20Sopenharmony_ci 1088c2ecf20Sopenharmony_ci err = bpf_map_lookup_elem(map_fd, &client_fd, &val); 1098c2ecf20Sopenharmony_ci 1108c2ecf20Sopenharmony_ci err = getsockname(client_fd, (struct sockaddr *)&addr, &len); 1118c2ecf20Sopenharmony_ci if (err) { 1128c2ecf20Sopenharmony_ci log_err("Can't get client local addr"); 1138c2ecf20Sopenharmony_ci goto out; 1148c2ecf20Sopenharmony_ci } 1158c2ecf20Sopenharmony_ci 1168c2ecf20Sopenharmony_ci cookie_expected_value = (ntohs(addr.sin6_port) << 8) | 0xFF; 1178c2ecf20Sopenharmony_ci if (val.cookie_value != cookie_expected_value) { 1188c2ecf20Sopenharmony_ci log_err("Unexpected value in map: %x != %x", val.cookie_value, 1198c2ecf20Sopenharmony_ci cookie_expected_value); 1208c2ecf20Sopenharmony_ci goto err; 1218c2ecf20Sopenharmony_ci } 1228c2ecf20Sopenharmony_ci 1238c2ecf20Sopenharmony_ci goto out; 1248c2ecf20Sopenharmony_cierr: 1258c2ecf20Sopenharmony_ci err = -1; 1268c2ecf20Sopenharmony_ciout: 1278c2ecf20Sopenharmony_ci return err; 1288c2ecf20Sopenharmony_ci} 1298c2ecf20Sopenharmony_ci 1308c2ecf20Sopenharmony_cistatic int run_test(int cgfd) 1318c2ecf20Sopenharmony_ci{ 1328c2ecf20Sopenharmony_ci enum bpf_attach_type attach_type; 1338c2ecf20Sopenharmony_ci struct bpf_prog_load_attr attr; 1348c2ecf20Sopenharmony_ci struct bpf_program *prog; 1358c2ecf20Sopenharmony_ci struct bpf_object *pobj; 1368c2ecf20Sopenharmony_ci const char *prog_name; 1378c2ecf20Sopenharmony_ci int server_fd = -1; 1388c2ecf20Sopenharmony_ci int client_fd = -1; 1398c2ecf20Sopenharmony_ci int prog_fd = -1; 1408c2ecf20Sopenharmony_ci int err = 0; 1418c2ecf20Sopenharmony_ci 1428c2ecf20Sopenharmony_ci memset(&attr, 0, sizeof(attr)); 1438c2ecf20Sopenharmony_ci attr.file = SOCKET_COOKIE_PROG; 1448c2ecf20Sopenharmony_ci attr.prog_type = BPF_PROG_TYPE_UNSPEC; 1458c2ecf20Sopenharmony_ci attr.prog_flags = BPF_F_TEST_RND_HI32; 1468c2ecf20Sopenharmony_ci 1478c2ecf20Sopenharmony_ci err = bpf_prog_load_xattr(&attr, &pobj, &prog_fd); 1488c2ecf20Sopenharmony_ci if (err) { 1498c2ecf20Sopenharmony_ci log_err("Failed to load %s", attr.file); 1508c2ecf20Sopenharmony_ci goto out; 1518c2ecf20Sopenharmony_ci } 1528c2ecf20Sopenharmony_ci 1538c2ecf20Sopenharmony_ci bpf_object__for_each_program(prog, pobj) { 1548c2ecf20Sopenharmony_ci prog_name = bpf_program__section_name(prog); 1558c2ecf20Sopenharmony_ci 1568c2ecf20Sopenharmony_ci if (libbpf_attach_type_by_name(prog_name, &attach_type)) 1578c2ecf20Sopenharmony_ci goto err; 1588c2ecf20Sopenharmony_ci 1598c2ecf20Sopenharmony_ci err = bpf_prog_attach(bpf_program__fd(prog), cgfd, attach_type, 1608c2ecf20Sopenharmony_ci BPF_F_ALLOW_OVERRIDE); 1618c2ecf20Sopenharmony_ci if (err) { 1628c2ecf20Sopenharmony_ci log_err("Failed to attach prog %s", prog_name); 1638c2ecf20Sopenharmony_ci goto out; 1648c2ecf20Sopenharmony_ci } 1658c2ecf20Sopenharmony_ci } 1668c2ecf20Sopenharmony_ci 1678c2ecf20Sopenharmony_ci server_fd = start_server(); 1688c2ecf20Sopenharmony_ci if (server_fd == -1) 1698c2ecf20Sopenharmony_ci goto err; 1708c2ecf20Sopenharmony_ci 1718c2ecf20Sopenharmony_ci client_fd = connect_to_server(server_fd); 1728c2ecf20Sopenharmony_ci if (client_fd == -1) 1738c2ecf20Sopenharmony_ci goto err; 1748c2ecf20Sopenharmony_ci 1758c2ecf20Sopenharmony_ci if (validate_map(bpf_map__next(NULL, pobj), client_fd)) 1768c2ecf20Sopenharmony_ci goto err; 1778c2ecf20Sopenharmony_ci 1788c2ecf20Sopenharmony_ci goto out; 1798c2ecf20Sopenharmony_cierr: 1808c2ecf20Sopenharmony_ci err = -1; 1818c2ecf20Sopenharmony_ciout: 1828c2ecf20Sopenharmony_ci close(client_fd); 1838c2ecf20Sopenharmony_ci close(server_fd); 1848c2ecf20Sopenharmony_ci bpf_object__close(pobj); 1858c2ecf20Sopenharmony_ci printf("%s\n", err ? "FAILED" : "PASSED"); 1868c2ecf20Sopenharmony_ci return err; 1878c2ecf20Sopenharmony_ci} 1888c2ecf20Sopenharmony_ci 1898c2ecf20Sopenharmony_ciint main(int argc, char **argv) 1908c2ecf20Sopenharmony_ci{ 1918c2ecf20Sopenharmony_ci int cgfd = -1; 1928c2ecf20Sopenharmony_ci int err = 0; 1938c2ecf20Sopenharmony_ci 1948c2ecf20Sopenharmony_ci cgfd = cgroup_setup_and_join(CG_PATH); 1958c2ecf20Sopenharmony_ci if (cgfd < 0) 1968c2ecf20Sopenharmony_ci goto err; 1978c2ecf20Sopenharmony_ci 1988c2ecf20Sopenharmony_ci if (run_test(cgfd)) 1998c2ecf20Sopenharmony_ci goto err; 2008c2ecf20Sopenharmony_ci 2018c2ecf20Sopenharmony_ci goto out; 2028c2ecf20Sopenharmony_cierr: 2038c2ecf20Sopenharmony_ci err = -1; 2048c2ecf20Sopenharmony_ciout: 2058c2ecf20Sopenharmony_ci close(cgfd); 2068c2ecf20Sopenharmony_ci cleanup_cgroup_environment(); 2078c2ecf20Sopenharmony_ci return err; 2088c2ecf20Sopenharmony_ci} 209