cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

sockopt_sk.c (4967B)


      1// SPDX-License-Identifier: GPL-2.0
      2#include <test_progs.h>
      3#include "cgroup_helpers.h"
      4
      5#include <linux/tcp.h>
      6#include "sockopt_sk.skel.h"
      7
      8#ifndef SOL_TCP
      9#define SOL_TCP IPPROTO_TCP
     10#endif
     11
     12#define SOL_CUSTOM			0xdeadbeef
     13
     14static int getsetsockopt(void)
     15{
     16	int fd, err;
     17	union {
     18		char u8[4];
     19		__u32 u32;
     20		char cc[16]; /* TCP_CA_NAME_MAX */
     21		struct tcp_zerocopy_receive zc;
     22	} buf = {};
     23	socklen_t optlen;
     24	char *big_buf = NULL;
     25
     26	fd = socket(AF_INET, SOCK_STREAM, 0);
     27	if (fd < 0) {
     28		log_err("Failed to create socket");
     29		return -1;
     30	}
     31
     32	/* IP_TOS - BPF bypass */
     33
     34	optlen = getpagesize() * 2;
     35	big_buf = calloc(1, optlen);
     36	if (!big_buf) {
     37		log_err("Couldn't allocate two pages");
     38		goto err;
     39	}
     40
     41	*(int *)big_buf = 0x08;
     42	err = setsockopt(fd, SOL_IP, IP_TOS, big_buf, optlen);
     43	if (err) {
     44		log_err("Failed to call setsockopt(IP_TOS)");
     45		goto err;
     46	}
     47
     48	memset(big_buf, 0, optlen);
     49	optlen = 1;
     50	err = getsockopt(fd, SOL_IP, IP_TOS, big_buf, &optlen);
     51	if (err) {
     52		log_err("Failed to call getsockopt(IP_TOS)");
     53		goto err;
     54	}
     55
     56	if (*big_buf != 0x08) {
     57		log_err("Unexpected getsockopt(IP_TOS) optval 0x%x != 0x08",
     58			(int)*big_buf);
     59		goto err;
     60	}
     61
     62	/* IP_TTL - EPERM */
     63
     64	buf.u8[0] = 1;
     65	err = setsockopt(fd, SOL_IP, IP_TTL, &buf, 1);
     66	if (!err || errno != EPERM) {
     67		log_err("Unexpected success from setsockopt(IP_TTL)");
     68		goto err;
     69	}
     70
     71	/* SOL_CUSTOM - handled by BPF */
     72
     73	buf.u8[0] = 0x01;
     74	err = setsockopt(fd, SOL_CUSTOM, 0, &buf, 1);
     75	if (err) {
     76		log_err("Failed to call setsockopt");
     77		goto err;
     78	}
     79
     80	buf.u32 = 0x00;
     81	optlen = 4;
     82	err = getsockopt(fd, SOL_CUSTOM, 0, &buf, &optlen);
     83	if (err) {
     84		log_err("Failed to call getsockopt");
     85		goto err;
     86	}
     87
     88	if (optlen != 1) {
     89		log_err("Unexpected optlen %d != 1", optlen);
     90		goto err;
     91	}
     92	if (buf.u8[0] != 0x01) {
     93		log_err("Unexpected buf[0] 0x%02x != 0x01", buf.u8[0]);
     94		goto err;
     95	}
     96
     97	/* IP_FREEBIND - BPF can't access optval past PAGE_SIZE */
     98
     99	optlen = getpagesize() * 2;
    100	memset(big_buf, 0, optlen);
    101
    102	err = setsockopt(fd, SOL_IP, IP_FREEBIND, big_buf, optlen);
    103	if (err != 0) {
    104		log_err("Failed to call setsockopt, ret=%d", err);
    105		goto err;
    106	}
    107
    108	err = getsockopt(fd, SOL_IP, IP_FREEBIND, big_buf, &optlen);
    109	if (err != 0) {
    110		log_err("Failed to call getsockopt, ret=%d", err);
    111		goto err;
    112	}
    113
    114	if (optlen != 1 || *(__u8 *)big_buf != 0x55) {
    115		log_err("Unexpected IP_FREEBIND getsockopt, optlen=%d, optval=0x%x",
    116			optlen, *(__u8 *)big_buf);
    117	}
    118
    119	/* SO_SNDBUF is overwritten */
    120
    121	buf.u32 = 0x01010101;
    122	err = setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &buf, 4);
    123	if (err) {
    124		log_err("Failed to call setsockopt(SO_SNDBUF)");
    125		goto err;
    126	}
    127
    128	buf.u32 = 0x00;
    129	optlen = 4;
    130	err = getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &buf, &optlen);
    131	if (err) {
    132		log_err("Failed to call getsockopt(SO_SNDBUF)");
    133		goto err;
    134	}
    135
    136	if (buf.u32 != 0x55AA*2) {
    137		log_err("Unexpected getsockopt(SO_SNDBUF) 0x%x != 0x55AA*2",
    138			buf.u32);
    139		goto err;
    140	}
    141
    142	/* TCP_CONGESTION can extend the string */
    143
    144	strcpy(buf.cc, "nv");
    145	err = setsockopt(fd, SOL_TCP, TCP_CONGESTION, &buf, strlen("nv"));
    146	if (err) {
    147		log_err("Failed to call setsockopt(TCP_CONGESTION)");
    148		goto err;
    149	}
    150
    151
    152	optlen = sizeof(buf.cc);
    153	err = getsockopt(fd, SOL_TCP, TCP_CONGESTION, &buf, &optlen);
    154	if (err) {
    155		log_err("Failed to call getsockopt(TCP_CONGESTION)");
    156		goto err;
    157	}
    158
    159	if (strcmp(buf.cc, "cubic") != 0) {
    160		log_err("Unexpected getsockopt(TCP_CONGESTION) %s != %s",
    161			buf.cc, "cubic");
    162		goto err;
    163	}
    164
    165	/* TCP_ZEROCOPY_RECEIVE triggers */
    166	memset(&buf, 0, sizeof(buf));
    167	optlen = sizeof(buf.zc);
    168	err = getsockopt(fd, SOL_TCP, TCP_ZEROCOPY_RECEIVE, &buf, &optlen);
    169	if (err) {
    170		log_err("Unexpected getsockopt(TCP_ZEROCOPY_RECEIVE) err=%d errno=%d",
    171			err, errno);
    172		goto err;
    173	}
    174
    175	memset(&buf, 0, sizeof(buf));
    176	buf.zc.address = 12345; /* Not page aligned. Rejected by tcp_zerocopy_receive() */
    177	optlen = sizeof(buf.zc);
    178	errno = 0;
    179	err = getsockopt(fd, SOL_TCP, TCP_ZEROCOPY_RECEIVE, &buf, &optlen);
    180	if (errno != EINVAL) {
    181		log_err("Unexpected getsockopt(TCP_ZEROCOPY_RECEIVE) err=%d errno=%d",
    182			err, errno);
    183		goto err;
    184	}
    185
    186	free(big_buf);
    187	close(fd);
    188	return 0;
    189err:
    190	free(big_buf);
    191	close(fd);
    192	return -1;
    193}
    194
    195static void run_test(int cgroup_fd)
    196{
    197	struct sockopt_sk *skel;
    198
    199	skel = sockopt_sk__open_and_load();
    200	if (!ASSERT_OK_PTR(skel, "skel_load"))
    201		goto cleanup;
    202
    203	skel->bss->page_size = getpagesize();
    204
    205	skel->links._setsockopt =
    206		bpf_program__attach_cgroup(skel->progs._setsockopt, cgroup_fd);
    207	if (!ASSERT_OK_PTR(skel->links._setsockopt, "setsockopt_link"))
    208		goto cleanup;
    209
    210	skel->links._getsockopt =
    211		bpf_program__attach_cgroup(skel->progs._getsockopt, cgroup_fd);
    212	if (!ASSERT_OK_PTR(skel->links._getsockopt, "getsockopt_link"))
    213		goto cleanup;
    214
    215	ASSERT_OK(getsetsockopt(), "getsetsockopt");
    216
    217cleanup:
    218	sockopt_sk__destroy(skel);
    219}
    220
    221void test_sockopt_sk(void)
    222{
    223	int cgroup_fd;
    224
    225	cgroup_fd = test__join_cgroup("/sockopt_sk");
    226	if (CHECK_FAIL(cgroup_fd < 0))
    227		return;
    228
    229	run_test(cgroup_fd);
    230	close(cgroup_fd);
    231}