root/tools/testing/selftests/bpf/progs/sockopt_sk.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. SEC
  2. SEC

   1 // SPDX-License-Identifier: GPL-2.0
   2 #include <string.h>
   3 #include <netinet/in.h>
   4 #include <netinet/tcp.h>
   5 #include <linux/bpf.h>
   6 #include "bpf_helpers.h"
   7 
   8 char _license[] SEC("license") = "GPL";
   9 __u32 _version SEC("version") = 1;
  10 
  11 #define SOL_CUSTOM                      0xdeadbeef
  12 
  13 struct sockopt_sk {
  14         __u8 val;
  15 };
  16 
  17 struct bpf_map_def SEC("maps") socket_storage_map = {
  18         .type = BPF_MAP_TYPE_SK_STORAGE,
  19         .key_size = sizeof(int),
  20         .value_size = sizeof(struct sockopt_sk),
  21         .map_flags = BPF_F_NO_PREALLOC,
  22 };
  23 BPF_ANNOTATE_KV_PAIR(socket_storage_map, int, struct sockopt_sk);
  24 
  25 SEC("cgroup/getsockopt")
  26 int _getsockopt(struct bpf_sockopt *ctx)
  27 {
  28         __u8 *optval_end = ctx->optval_end;
  29         __u8 *optval = ctx->optval;
  30         struct sockopt_sk *storage;
  31 
  32         if (ctx->level == SOL_IP && ctx->optname == IP_TOS)
  33                 /* Not interested in SOL_IP:IP_TOS;
  34                  * let next BPF program in the cgroup chain or kernel
  35                  * handle it.
  36                  */
  37                 return 1;
  38 
  39         if (ctx->level == SOL_SOCKET && ctx->optname == SO_SNDBUF) {
  40                 /* Not interested in SOL_SOCKET:SO_SNDBUF;
  41                  * let next BPF program in the cgroup chain or kernel
  42                  * handle it.
  43                  */
  44                 return 1;
  45         }
  46 
  47         if (ctx->level == SOL_TCP && ctx->optname == TCP_CONGESTION) {
  48                 /* Not interested in SOL_TCP:TCP_CONGESTION;
  49                  * let next BPF program in the cgroup chain or kernel
  50                  * handle it.
  51                  */
  52                 return 1;
  53         }
  54 
  55         if (ctx->level != SOL_CUSTOM)
  56                 return 0; /* EPERM, deny everything except custom level */
  57 
  58         if (optval + 1 > optval_end)
  59                 return 0; /* EPERM, bounds check */
  60 
  61         storage = bpf_sk_storage_get(&socket_storage_map, ctx->sk, 0,
  62                                      BPF_SK_STORAGE_GET_F_CREATE);
  63         if (!storage)
  64                 return 0; /* EPERM, couldn't get sk storage */
  65 
  66         if (!ctx->retval)
  67                 return 0; /* EPERM, kernel should not have handled
  68                            * SOL_CUSTOM, something is wrong!
  69                            */
  70         ctx->retval = 0; /* Reset system call return value to zero */
  71 
  72         optval[0] = storage->val;
  73         ctx->optlen = 1;
  74 
  75         return 1;
  76 }
  77 
  78 SEC("cgroup/setsockopt")
  79 int _setsockopt(struct bpf_sockopt *ctx)
  80 {
  81         __u8 *optval_end = ctx->optval_end;
  82         __u8 *optval = ctx->optval;
  83         struct sockopt_sk *storage;
  84 
  85         if (ctx->level == SOL_IP && ctx->optname == IP_TOS)
  86                 /* Not interested in SOL_IP:IP_TOS;
  87                  * let next BPF program in the cgroup chain or kernel
  88                  * handle it.
  89                  */
  90                 return 1;
  91 
  92         if (ctx->level == SOL_SOCKET && ctx->optname == SO_SNDBUF) {
  93                 /* Overwrite SO_SNDBUF value */
  94 
  95                 if (optval + sizeof(__u32) > optval_end)
  96                         return 0; /* EPERM, bounds check */
  97 
  98                 *(__u32 *)optval = 0x55AA;
  99                 ctx->optlen = 4;
 100 
 101                 return 1;
 102         }
 103 
 104         if (ctx->level == SOL_TCP && ctx->optname == TCP_CONGESTION) {
 105                 /* Always use cubic */
 106 
 107                 if (optval + 5 > optval_end)
 108                         return 0; /* EPERM, bounds check */
 109 
 110                 memcpy(optval, "cubic", 5);
 111                 ctx->optlen = 5;
 112 
 113                 return 1;
 114         }
 115 
 116         if (ctx->level != SOL_CUSTOM)
 117                 return 0; /* EPERM, deny everything except custom level */
 118 
 119         if (optval + 1 > optval_end)
 120                 return 0; /* EPERM, bounds check */
 121 
 122         storage = bpf_sk_storage_get(&socket_storage_map, ctx->sk, 0,
 123                                      BPF_SK_STORAGE_GET_F_CREATE);
 124         if (!storage)
 125                 return 0; /* EPERM, couldn't get sk storage */
 126 
 127         storage->val = optval[0];
 128         ctx->optlen = -1; /* BPF has consumed this option, don't call kernel
 129                            * setsockopt handler.
 130                            */
 131 
 132         return 1;
 133 }

/* [<][>][^][v][top][bottom][index][help] */