~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/tools/testing/selftests/bpf/prog_tests/sockopt.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0
  2 #include <test_progs.h>
  3 #include <io_uring/mini_liburing.h>
  4 #include "cgroup_helpers.h"
  5 
  6 static char bpf_log_buf[4096];
  7 static bool verbose;
  8 
  9 #ifndef PAGE_SIZE
 10 #define PAGE_SIZE 4096
 11 #endif
 12 
 13 enum sockopt_test_error {
 14         OK = 0,
 15         DENY_LOAD,
 16         DENY_ATTACH,
 17         EOPNOTSUPP_GETSOCKOPT,
 18         EPERM_GETSOCKOPT,
 19         EFAULT_GETSOCKOPT,
 20         EPERM_SETSOCKOPT,
 21         EFAULT_SETSOCKOPT,
 22 };
 23 
 24 static struct sockopt_test {
 25         const char                      *descr;
 26         const struct bpf_insn           insns[64];
 27         enum bpf_prog_type              prog_type;
 28         enum bpf_attach_type            attach_type;
 29         enum bpf_attach_type            expected_attach_type;
 30 
 31         int                             set_optname;
 32         int                             set_level;
 33         const char                      set_optval[64];
 34         socklen_t                       set_optlen;
 35 
 36         int                             get_optname;
 37         int                             get_level;
 38         const char                      get_optval[64];
 39         socklen_t                       get_optlen;
 40         socklen_t                       get_optlen_ret;
 41 
 42         enum sockopt_test_error         error;
 43         bool                            io_uring_support;
 44 } tests[] = {
 45 
 46         /* ==================== getsockopt ====================  */
 47 
 48         {
 49                 .descr = "getsockopt: no expected_attach_type",
 50                 .insns = {
 51                         /* return 1 */
 52                         BPF_MOV64_IMM(BPF_REG_0, 1),
 53                         BPF_EXIT_INSN(),
 54 
 55                 },
 56                 .attach_type = BPF_CGROUP_GETSOCKOPT,
 57                 .expected_attach_type = 0,
 58                 .error = DENY_LOAD,
 59         },
 60         {
 61                 .descr = "getsockopt: wrong expected_attach_type",
 62                 .insns = {
 63                         /* return 1 */
 64                         BPF_MOV64_IMM(BPF_REG_0, 1),
 65                         BPF_EXIT_INSN(),
 66 
 67                 },
 68                 .attach_type = BPF_CGROUP_GETSOCKOPT,
 69                 .expected_attach_type = BPF_CGROUP_SETSOCKOPT,
 70                 .error = DENY_ATTACH,
 71         },
 72         {
 73                 .descr = "getsockopt: bypass bpf hook",
 74                 .insns = {
 75                         /* return 1 */
 76                         BPF_MOV64_IMM(BPF_REG_0, 1),
 77                         BPF_EXIT_INSN(),
 78                 },
 79                 .attach_type = BPF_CGROUP_GETSOCKOPT,
 80                 .expected_attach_type = BPF_CGROUP_GETSOCKOPT,
 81 
 82                 .get_level = SOL_IP,
 83                 .set_level = SOL_IP,
 84 
 85                 .get_optname = IP_TOS,
 86                 .set_optname = IP_TOS,
 87 
 88                 .set_optval = { 1 << 3 },
 89                 .set_optlen = 1,
 90 
 91                 .get_optval = { 1 << 3 },
 92                 .get_optlen = 1,
 93         },
 94         {
 95                 .descr = "getsockopt: return EPERM from bpf hook",
 96                 .insns = {
 97                         BPF_MOV64_IMM(BPF_REG_0, 0),
 98                         BPF_EXIT_INSN(),
 99                 },
100                 .attach_type = BPF_CGROUP_GETSOCKOPT,
101                 .expected_attach_type = BPF_CGROUP_GETSOCKOPT,
102 
103                 .get_level = SOL_IP,
104                 .get_optname = IP_TOS,
105 
106                 .get_optlen = 1,
107                 .error = EPERM_GETSOCKOPT,
108         },
109         {
110                 .descr = "getsockopt: no optval bounds check, deny loading",
111                 .insns = {
112                         /* r6 = ctx->optval */
113                         BPF_LDX_MEM(BPF_DW, BPF_REG_6, BPF_REG_1,
114                                     offsetof(struct bpf_sockopt, optval)),
115 
116                         /* ctx->optval[0] = 0x80 */
117                         BPF_MOV64_IMM(BPF_REG_0, 0x80),
118                         BPF_STX_MEM(BPF_W, BPF_REG_6, BPF_REG_0, 0),
119 
120                         /* return 1 */
121                         BPF_MOV64_IMM(BPF_REG_0, 1),
122                         BPF_EXIT_INSN(),
123                 },
124                 .attach_type = BPF_CGROUP_GETSOCKOPT,
125                 .expected_attach_type = BPF_CGROUP_GETSOCKOPT,
126                 .error = DENY_LOAD,
127         },
128         {
129                 .descr = "getsockopt: read ctx->level",
130                 .insns = {
131                         /* r6 = ctx->level */
132                         BPF_LDX_MEM(BPF_W, BPF_REG_6, BPF_REG_1,
133                                     offsetof(struct bpf_sockopt, level)),
134 
135                         /* if (ctx->level == 123) { */
136                         BPF_JMP_IMM(BPF_JNE, BPF_REG_6, 123, 4),
137                         /* ctx->retval = 0 */
138                         BPF_MOV64_IMM(BPF_REG_0, 0),
139                         BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_0,
140                                     offsetof(struct bpf_sockopt, retval)),
141                         /* return 1 */
142                         BPF_MOV64_IMM(BPF_REG_0, 1),
143                         BPF_JMP_A(1),
144                         /* } else { */
145                         /* return 0 */
146                         BPF_MOV64_IMM(BPF_REG_0, 0),
147                         /* } */
148                         BPF_EXIT_INSN(),
149                 },
150                 .attach_type = BPF_CGROUP_GETSOCKOPT,
151                 .expected_attach_type = BPF_CGROUP_GETSOCKOPT,
152 
153                 .get_level = 123,
154 
155                 .get_optlen = 1,
156         },
157         {
158                 .descr = "getsockopt: deny writing to ctx->level",
159                 .insns = {
160                         /* ctx->level = 1 */
161                         BPF_MOV64_IMM(BPF_REG_0, 1),
162                         BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_0,
163                                     offsetof(struct bpf_sockopt, level)),
164                         BPF_EXIT_INSN(),
165                 },
166                 .attach_type = BPF_CGROUP_GETSOCKOPT,
167                 .expected_attach_type = BPF_CGROUP_GETSOCKOPT,
168 
169                 .error = DENY_LOAD,
170         },
171         {
172                 .descr = "getsockopt: read ctx->optname",
173                 .insns = {
174                         /* r6 = ctx->optname */
175                         BPF_LDX_MEM(BPF_W, BPF_REG_6, BPF_REG_1,
176                                     offsetof(struct bpf_sockopt, optname)),
177 
178                         /* if (ctx->optname == 123) { */
179                         BPF_JMP_IMM(BPF_JNE, BPF_REG_6, 123, 4),
180                         /* ctx->retval = 0 */
181                         BPF_MOV64_IMM(BPF_REG_0, 0),
182                         BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_0,
183                                     offsetof(struct bpf_sockopt, retval)),
184                         /* return 1 */
185                         BPF_MOV64_IMM(BPF_REG_0, 1),
186                         BPF_JMP_A(1),
187                         /* } else { */
188                         /* return 0 */
189                         BPF_MOV64_IMM(BPF_REG_0, 0),
190                         /* } */
191                         BPF_EXIT_INSN(),
192                 },
193                 .attach_type = BPF_CGROUP_GETSOCKOPT,
194                 .expected_attach_type = BPF_CGROUP_GETSOCKOPT,
195 
196                 .get_optname = 123,
197 
198                 .get_optlen = 1,
199         },
200         {
201                 .descr = "getsockopt: read ctx->retval",
202                 .insns = {
203                         /* r6 = ctx->retval */
204                         BPF_LDX_MEM(BPF_W, BPF_REG_6, BPF_REG_1,
205                                     offsetof(struct bpf_sockopt, retval)),
206 
207                         /* return 1 */
208                         BPF_MOV64_IMM(BPF_REG_0, 1),
209                         BPF_EXIT_INSN(),
210                 },
211                 .attach_type = BPF_CGROUP_GETSOCKOPT,
212                 .expected_attach_type = BPF_CGROUP_GETSOCKOPT,
213 
214                 .get_level = SOL_IP,
215                 .get_optname = IP_TOS,
216                 .get_optlen = 1,
217         },
218         {
219                 .descr = "getsockopt: deny writing to ctx->optname",
220                 .insns = {
221                         /* ctx->optname = 1 */
222                         BPF_MOV64_IMM(BPF_REG_0, 1),
223                         BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_0,
224                                     offsetof(struct bpf_sockopt, optname)),
225                         BPF_EXIT_INSN(),
226                 },
227                 .attach_type = BPF_CGROUP_GETSOCKOPT,
228                 .expected_attach_type = BPF_CGROUP_GETSOCKOPT,
229 
230                 .error = DENY_LOAD,
231         },
232         {
233                 .descr = "getsockopt: read ctx->optlen",
234                 .insns = {
235                         /* r6 = ctx->optlen */
236                         BPF_LDX_MEM(BPF_W, BPF_REG_6, BPF_REG_1,
237                                     offsetof(struct bpf_sockopt, optlen)),
238 
239                         /* if (ctx->optlen == 64) { */
240                         BPF_JMP_IMM(BPF_JNE, BPF_REG_6, 64, 4),
241                         /* ctx->retval = 0 */
242                         BPF_MOV64_IMM(BPF_REG_0, 0),
243                         BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_0,
244                                     offsetof(struct bpf_sockopt, retval)),
245                         /* return 1 */
246                         BPF_MOV64_IMM(BPF_REG_0, 1),
247                         BPF_JMP_A(1),
248                         /* } else { */
249                         /* return 0 */
250                         BPF_MOV64_IMM(BPF_REG_0, 0),
251                         /* } */
252                         BPF_EXIT_INSN(),
253                 },
254                 .attach_type = BPF_CGROUP_GETSOCKOPT,
255                 .expected_attach_type = BPF_CGROUP_GETSOCKOPT,
256 
257                 .get_level = SOL_SOCKET,
258                 .get_optlen = 64,
259                 .io_uring_support = true,
260         },
261         {
262                 .descr = "getsockopt: deny bigger ctx->optlen",
263                 .insns = {
264                         /* ctx->optlen = 65 */
265                         BPF_MOV64_IMM(BPF_REG_0, 65),
266                         BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_0,
267                                     offsetof(struct bpf_sockopt, optlen)),
268 
269                         /* ctx->retval = 0 */
270                         BPF_MOV64_IMM(BPF_REG_0, 0),
271                         BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_0,
272                                     offsetof(struct bpf_sockopt, retval)),
273 
274                         /* return 1 */
275                         BPF_MOV64_IMM(BPF_REG_0, 1),
276                         BPF_EXIT_INSN(),
277                 },
278                 .attach_type = BPF_CGROUP_GETSOCKOPT,
279                 .expected_attach_type = BPF_CGROUP_GETSOCKOPT,
280 
281                 .get_optlen = 64,
282 
283                 .error = EFAULT_GETSOCKOPT,
284                 .io_uring_support = true,
285         },
286         {
287                 .descr = "getsockopt: ignore >PAGE_SIZE optlen",
288                 .insns = {
289                         /* write 0xFF to the first optval byte */
290 
291                         /* r6 = ctx->optval */
292                         BPF_LDX_MEM(BPF_DW, BPF_REG_6, BPF_REG_1,
293                                     offsetof(struct bpf_sockopt, optval)),
294                         /* r2 = ctx->optval */
295                         BPF_MOV64_REG(BPF_REG_2, BPF_REG_6),
296                         /* r6 = ctx->optval + 1 */
297                         BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, 1),
298 
299                         /* r7 = ctx->optval_end */
300                         BPF_LDX_MEM(BPF_DW, BPF_REG_7, BPF_REG_1,
301                                     offsetof(struct bpf_sockopt, optval_end)),
302 
303                         /* if (ctx->optval + 1 <= ctx->optval_end) { */
304                         BPF_JMP_REG(BPF_JGT, BPF_REG_6, BPF_REG_7, 1),
305                         /* ctx->optval[0] = 0xF0 */
306                         BPF_ST_MEM(BPF_B, BPF_REG_2, 0, 0xFF),
307                         /* } */
308 
309                         /* retval changes are ignored */
310                         /* ctx->retval = 5 */
311                         BPF_MOV64_IMM(BPF_REG_0, 5),
312                         BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_0,
313                                     offsetof(struct bpf_sockopt, retval)),
314 
315                         /* return 1 */
316                         BPF_MOV64_IMM(BPF_REG_0, 1),
317                         BPF_EXIT_INSN(),
318                 },
319                 .attach_type = BPF_CGROUP_GETSOCKOPT,
320                 .expected_attach_type = BPF_CGROUP_GETSOCKOPT,
321 
322                 .get_level = 1234,
323                 .get_optname = 5678,
324                 .get_optval = {}, /* the changes are ignored */
325                 .get_optlen = PAGE_SIZE + 1,
326                 .error = EOPNOTSUPP_GETSOCKOPT,
327                 .io_uring_support = true,
328         },
329         {
330                 .descr = "getsockopt: support smaller ctx->optlen",
331                 .insns = {
332                         /* ctx->optlen = 32 */
333                         BPF_MOV64_IMM(BPF_REG_0, 32),
334                         BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_0,
335                                     offsetof(struct bpf_sockopt, optlen)),
336                         /* ctx->retval = 0 */
337                         BPF_MOV64_IMM(BPF_REG_0, 0),
338                         BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_0,
339                                     offsetof(struct bpf_sockopt, retval)),
340                         /* return 1 */
341                         BPF_MOV64_IMM(BPF_REG_0, 1),
342                         BPF_EXIT_INSN(),
343                 },
344                 .attach_type = BPF_CGROUP_GETSOCKOPT,
345                 .expected_attach_type = BPF_CGROUP_GETSOCKOPT,
346 
347                 .get_level = SOL_SOCKET,
348                 .get_optlen = 64,
349                 .get_optlen_ret = 32,
350                 .io_uring_support = true,
351         },
352         {
353                 .descr = "getsockopt: deny writing to ctx->optval",
354                 .insns = {
355                         /* ctx->optval = 1 */
356                         BPF_MOV64_IMM(BPF_REG_0, 1),
357                         BPF_STX_MEM(BPF_DW, BPF_REG_1, BPF_REG_0,
358                                     offsetof(struct bpf_sockopt, optval)),
359                         BPF_EXIT_INSN(),
360                 },
361                 .attach_type = BPF_CGROUP_GETSOCKOPT,
362                 .expected_attach_type = BPF_CGROUP_GETSOCKOPT,
363 
364                 .error = DENY_LOAD,
365         },
366         {
367                 .descr = "getsockopt: deny writing to ctx->optval_end",
368                 .insns = {
369                         /* ctx->optval_end = 1 */
370                         BPF_MOV64_IMM(BPF_REG_0, 1),
371                         BPF_STX_MEM(BPF_DW, BPF_REG_1, BPF_REG_0,
372                                     offsetof(struct bpf_sockopt, optval_end)),
373                         BPF_EXIT_INSN(),
374                 },
375                 .attach_type = BPF_CGROUP_GETSOCKOPT,
376                 .expected_attach_type = BPF_CGROUP_GETSOCKOPT,
377 
378                 .error = DENY_LOAD,
379         },
380         {
381                 .descr = "getsockopt: rewrite value",
382                 .insns = {
383                         /* r6 = ctx->optval */
384                         BPF_LDX_MEM(BPF_DW, BPF_REG_6, BPF_REG_1,
385                                     offsetof(struct bpf_sockopt, optval)),
386                         /* r2 = ctx->optval */
387                         BPF_MOV64_REG(BPF_REG_2, BPF_REG_6),
388                         /* r6 = ctx->optval + 1 */
389                         BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, 1),
390 
391                         /* r7 = ctx->optval_end */
392                         BPF_LDX_MEM(BPF_DW, BPF_REG_7, BPF_REG_1,
393                                     offsetof(struct bpf_sockopt, optval_end)),
394 
395                         /* if (ctx->optval + 1 <= ctx->optval_end) { */
396                         BPF_JMP_REG(BPF_JGT, BPF_REG_6, BPF_REG_7, 1),
397                         /* ctx->optval[0] = 0xF0 */
398                         BPF_ST_MEM(BPF_B, BPF_REG_2, 0, 0xF0),
399                         /* } */
400 
401                         /* ctx->retval = 0 */
402                         BPF_MOV64_IMM(BPF_REG_0, 0),
403                         BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_0,
404                                     offsetof(struct bpf_sockopt, retval)),
405 
406                         /* return 1*/
407                         BPF_MOV64_IMM(BPF_REG_0, 1),
408                         BPF_EXIT_INSN(),
409                 },
410                 .attach_type = BPF_CGROUP_GETSOCKOPT,
411                 .expected_attach_type = BPF_CGROUP_GETSOCKOPT,
412 
413                 .get_level = SOL_IP,
414                 .get_optname = IP_TOS,
415 
416                 .get_optval = { 0xF0 },
417                 .get_optlen = 1,
418         },
419 
420         /* ==================== setsockopt ====================  */
421 
422         {
423                 .descr = "setsockopt: no expected_attach_type",
424                 .insns = {
425                         /* return 1 */
426                         BPF_MOV64_IMM(BPF_REG_0, 1),
427                         BPF_EXIT_INSN(),
428 
429                 },
430                 .attach_type = BPF_CGROUP_SETSOCKOPT,
431                 .expected_attach_type = 0,
432                 .error = DENY_LOAD,
433         },
434         {
435                 .descr = "setsockopt: wrong expected_attach_type",
436                 .insns = {
437                         /* return 1 */
438                         BPF_MOV64_IMM(BPF_REG_0, 1),
439                         BPF_EXIT_INSN(),
440 
441                 },
442                 .attach_type = BPF_CGROUP_SETSOCKOPT,
443                 .expected_attach_type = BPF_CGROUP_GETSOCKOPT,
444                 .error = DENY_ATTACH,
445         },
446         {
447                 .descr = "setsockopt: bypass bpf hook",
448                 .insns = {
449                         /* return 1 */
450                         BPF_MOV64_IMM(BPF_REG_0, 1),
451                         BPF_EXIT_INSN(),
452                 },
453                 .attach_type = BPF_CGROUP_SETSOCKOPT,
454                 .expected_attach_type = BPF_CGROUP_SETSOCKOPT,
455 
456                 .get_level = SOL_IP,
457                 .set_level = SOL_IP,
458 
459                 .get_optname = IP_TOS,
460                 .set_optname = IP_TOS,
461 
462                 .set_optval = { 1 << 3 },
463                 .set_optlen = 1,
464 
465                 .get_optval = { 1 << 3 },
466                 .get_optlen = 1,
467         },
468         {
469                 .descr = "setsockopt: return EPERM from bpf hook",
470                 .insns = {
471                         /* return 0 */
472                         BPF_MOV64_IMM(BPF_REG_0, 0),
473                         BPF_EXIT_INSN(),
474                 },
475                 .attach_type = BPF_CGROUP_SETSOCKOPT,
476                 .expected_attach_type = BPF_CGROUP_SETSOCKOPT,
477 
478                 .set_level = SOL_IP,
479                 .set_optname = IP_TOS,
480 
481                 .set_optlen = 1,
482                 .error = EPERM_SETSOCKOPT,
483         },
484         {
485                 .descr = "setsockopt: no optval bounds check, deny loading",
486                 .insns = {
487                         /* r6 = ctx->optval */
488                         BPF_LDX_MEM(BPF_DW, BPF_REG_6, BPF_REG_1,
489                                     offsetof(struct bpf_sockopt, optval)),
490 
491                         /* r0 = ctx->optval[0] */
492                         BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_6, 0),
493 
494                         /* return 1 */
495                         BPF_MOV64_IMM(BPF_REG_0, 1),
496                         BPF_EXIT_INSN(),
497                 },
498                 .attach_type = BPF_CGROUP_SETSOCKOPT,
499                 .expected_attach_type = BPF_CGROUP_SETSOCKOPT,
500                 .error = DENY_LOAD,
501         },
502         {
503                 .descr = "setsockopt: read ctx->level",
504                 .insns = {
505                         /* r6 = ctx->level */
506                         BPF_LDX_MEM(BPF_W, BPF_REG_6, BPF_REG_1,
507                                     offsetof(struct bpf_sockopt, level)),
508 
509                         /* if (ctx->level == 123) { */
510                         BPF_JMP_IMM(BPF_JNE, BPF_REG_6, 123, 4),
511                         /* ctx->optlen = -1 */
512                         BPF_MOV64_IMM(BPF_REG_0, -1),
513                         BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_0,
514                                     offsetof(struct bpf_sockopt, optlen)),
515                         /* return 1 */
516                         BPF_MOV64_IMM(BPF_REG_0, 1),
517                         BPF_JMP_A(1),
518                         /* } else { */
519                         /* return 0 */
520                         BPF_MOV64_IMM(BPF_REG_0, 0),
521                         /* } */
522                         BPF_EXIT_INSN(),
523                 },
524                 .attach_type = BPF_CGROUP_SETSOCKOPT,
525                 .expected_attach_type = BPF_CGROUP_SETSOCKOPT,
526 
527                 .set_level = 123,
528 
529                 .set_optlen = 1,
530                 .io_uring_support = true,
531         },
532         {
533                 .descr = "setsockopt: allow changing ctx->level",
534                 .insns = {
535                         /* ctx->level = SOL_IP */
536                         BPF_MOV64_IMM(BPF_REG_0, SOL_IP),
537                         BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_0,
538                                     offsetof(struct bpf_sockopt, level)),
539                         /* return 1 */
540                         BPF_MOV64_IMM(BPF_REG_0, 1),
541                         BPF_EXIT_INSN(),
542                 },
543                 .attach_type = BPF_CGROUP_SETSOCKOPT,
544                 .expected_attach_type = BPF_CGROUP_SETSOCKOPT,
545 
546                 .get_level = SOL_IP,
547                 .set_level = 234, /* should be rewritten to SOL_IP */
548 
549                 .get_optname = IP_TOS,
550                 .set_optname = IP_TOS,
551 
552                 .set_optval = { 1 << 3 },
553                 .set_optlen = 1,
554                 .get_optval = { 1 << 3 },
555                 .get_optlen = 1,
556         },
557         {
558                 .descr = "setsockopt: read ctx->optname",
559                 .insns = {
560                         /* r6 = ctx->optname */
561                         BPF_LDX_MEM(BPF_W, BPF_REG_6, BPF_REG_1,
562                                     offsetof(struct bpf_sockopt, optname)),
563 
564                         /* if (ctx->optname == 123) { */
565                         BPF_JMP_IMM(BPF_JNE, BPF_REG_6, 123, 4),
566                         /* ctx->optlen = -1 */
567                         BPF_MOV64_IMM(BPF_REG_0, -1),
568                         BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_0,
569                                     offsetof(struct bpf_sockopt, optlen)),
570                         /* return 1 */
571                         BPF_MOV64_IMM(BPF_REG_0, 1),
572                         BPF_JMP_A(1),
573                         /* } else { */
574                         /* return 0 */
575                         BPF_MOV64_IMM(BPF_REG_0, 0),
576                         /* } */
577                         BPF_EXIT_INSN(),
578                 },
579                 .attach_type = BPF_CGROUP_SETSOCKOPT,
580                 .expected_attach_type = BPF_CGROUP_SETSOCKOPT,
581 
582                 .set_optname = 123,
583 
584                 .set_optlen = 1,
585                 .io_uring_support = true,
586         },
587         {
588                 .descr = "setsockopt: allow changing ctx->optname",
589                 .insns = {
590                         /* ctx->optname = IP_TOS */
591                         BPF_MOV64_IMM(BPF_REG_0, IP_TOS),
592                         BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_0,
593                                     offsetof(struct bpf_sockopt, optname)),
594                         /* return 1 */
595                         BPF_MOV64_IMM(BPF_REG_0, 1),
596                         BPF_EXIT_INSN(),
597                 },
598                 .attach_type = BPF_CGROUP_SETSOCKOPT,
599                 .expected_attach_type = BPF_CGROUP_SETSOCKOPT,
600 
601                 .get_level = SOL_IP,
602                 .set_level = SOL_IP,
603 
604                 .get_optname = IP_TOS,
605                 .set_optname = 456, /* should be rewritten to IP_TOS */
606 
607                 .set_optval = { 1 << 3 },
608                 .set_optlen = 1,
609                 .get_optval = { 1 << 3 },
610                 .get_optlen = 1,
611         },
612         {
613                 .descr = "setsockopt: read ctx->optlen",
614                 .insns = {
615                         /* r6 = ctx->optlen */
616                         BPF_LDX_MEM(BPF_W, BPF_REG_6, BPF_REG_1,
617                                     offsetof(struct bpf_sockopt, optlen)),
618 
619                         /* if (ctx->optlen == 64) { */
620                         BPF_JMP_IMM(BPF_JNE, BPF_REG_6, 64, 4),
621                         /* ctx->optlen = -1 */
622                         BPF_MOV64_IMM(BPF_REG_0, -1),
623                         BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_0,
624                                     offsetof(struct bpf_sockopt, optlen)),
625                         /* return 1 */
626                         BPF_MOV64_IMM(BPF_REG_0, 1),
627                         BPF_JMP_A(1),
628                         /* } else { */
629                         /* return 0 */
630                         BPF_MOV64_IMM(BPF_REG_0, 0),
631                         /* } */
632                         BPF_EXIT_INSN(),
633                 },
634                 .attach_type = BPF_CGROUP_SETSOCKOPT,
635                 .expected_attach_type = BPF_CGROUP_SETSOCKOPT,
636 
637                 .set_optlen = 64,
638                 .io_uring_support = true,
639         },
640         {
641                 .descr = "setsockopt: ctx->optlen == -1 is ok",
642                 .insns = {
643                         /* ctx->optlen = -1 */
644                         BPF_MOV64_IMM(BPF_REG_0, -1),
645                         BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_0,
646                                     offsetof(struct bpf_sockopt, optlen)),
647                         /* return 1 */
648                         BPF_MOV64_IMM(BPF_REG_0, 1),
649                         BPF_EXIT_INSN(),
650                 },
651                 .attach_type = BPF_CGROUP_SETSOCKOPT,
652                 .expected_attach_type = BPF_CGROUP_SETSOCKOPT,
653 
654                 .set_optlen = 64,
655                 .io_uring_support = true,
656         },
657         {
658                 .descr = "setsockopt: deny ctx->optlen < 0 (except -1)",
659                 .insns = {
660                         /* ctx->optlen = -2 */
661                         BPF_MOV64_IMM(BPF_REG_0, -2),
662                         BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_0,
663                                     offsetof(struct bpf_sockopt, optlen)),
664                         /* return 1 */
665                         BPF_MOV64_IMM(BPF_REG_0, 1),
666                         BPF_EXIT_INSN(),
667                 },
668                 .attach_type = BPF_CGROUP_SETSOCKOPT,
669                 .expected_attach_type = BPF_CGROUP_SETSOCKOPT,
670 
671                 .set_optlen = 4,
672 
673                 .error = EFAULT_SETSOCKOPT,
674                 .io_uring_support = true,
675         },
676         {
677                 .descr = "setsockopt: deny ctx->optlen > input optlen",
678                 .insns = {
679                         /* ctx->optlen = 65 */
680                         BPF_MOV64_IMM(BPF_REG_0, 65),
681                         BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_0,
682                                     offsetof(struct bpf_sockopt, optlen)),
683                         BPF_MOV64_IMM(BPF_REG_0, 1),
684                         BPF_EXIT_INSN(),
685                 },
686                 .attach_type = BPF_CGROUP_SETSOCKOPT,
687                 .expected_attach_type = BPF_CGROUP_SETSOCKOPT,
688 
689                 .set_optlen = 64,
690 
691                 .error = EFAULT_SETSOCKOPT,
692                 .io_uring_support = true,
693         },
694         {
695                 .descr = "setsockopt: ignore >PAGE_SIZE optlen",
696                 .insns = {
697                         /* write 0xFF to the first optval byte */
698 
699                         /* r6 = ctx->optval */
700                         BPF_LDX_MEM(BPF_DW, BPF_REG_6, BPF_REG_1,
701                                     offsetof(struct bpf_sockopt, optval)),
702                         /* r2 = ctx->optval */
703                         BPF_MOV64_REG(BPF_REG_2, BPF_REG_6),
704                         /* r6 = ctx->optval + 1 */
705                         BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, 1),
706 
707                         /* r7 = ctx->optval_end */
708                         BPF_LDX_MEM(BPF_DW, BPF_REG_7, BPF_REG_1,
709                                     offsetof(struct bpf_sockopt, optval_end)),
710 
711                         /* if (ctx->optval + 1 <= ctx->optval_end) { */
712                         BPF_JMP_REG(BPF_JGT, BPF_REG_6, BPF_REG_7, 1),
713                         /* ctx->optval[0] = 0xF0 */
714                         BPF_ST_MEM(BPF_B, BPF_REG_2, 0, 0xF0),
715                         /* } */
716 
717                         BPF_MOV64_IMM(BPF_REG_0, 1),
718                         BPF_EXIT_INSN(),
719                 },
720                 .attach_type = BPF_CGROUP_SETSOCKOPT,
721                 .expected_attach_type = BPF_CGROUP_SETSOCKOPT,
722 
723                 .set_level = SOL_IP,
724                 .set_optname = IP_TOS,
725                 .set_optval = {},
726                 .set_optlen = PAGE_SIZE + 1,
727 
728                 .get_level = SOL_IP,
729                 .get_optname = IP_TOS,
730                 .get_optval = {}, /* the changes are ignored */
731                 .get_optlen = 4,
732         },
733         {
734                 .descr = "setsockopt: allow changing ctx->optlen within bounds",
735                 .insns = {
736                         /* r6 = ctx->optval */
737                         BPF_LDX_MEM(BPF_DW, BPF_REG_6, BPF_REG_1,
738                                     offsetof(struct bpf_sockopt, optval)),
739                         /* r2 = ctx->optval */
740                         BPF_MOV64_REG(BPF_REG_2, BPF_REG_6),
741                         /* r6 = ctx->optval + 1 */
742                         BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, 1),
743 
744                         /* r7 = ctx->optval_end */
745                         BPF_LDX_MEM(BPF_DW, BPF_REG_7, BPF_REG_1,
746                                     offsetof(struct bpf_sockopt, optval_end)),
747 
748                         /* if (ctx->optval + 1 <= ctx->optval_end) { */
749                         BPF_JMP_REG(BPF_JGT, BPF_REG_6, BPF_REG_7, 1),
750                         /* ctx->optval[0] = 1 << 3 */
751                         BPF_ST_MEM(BPF_B, BPF_REG_2, 0, 1 << 3),
752                         /* } */
753 
754                         /* ctx->optlen = 1 */
755                         BPF_MOV64_IMM(BPF_REG_0, 1),
756                         BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_0,
757                                     offsetof(struct bpf_sockopt, optlen)),
758 
759                         /* return 1*/
760                         BPF_MOV64_IMM(BPF_REG_0, 1),
761                         BPF_EXIT_INSN(),
762                 },
763                 .attach_type = BPF_CGROUP_SETSOCKOPT,
764                 .expected_attach_type = BPF_CGROUP_SETSOCKOPT,
765 
766                 .get_level = SOL_IP,
767                 .set_level = SOL_IP,
768 
769                 .get_optname = IP_TOS,
770                 .set_optname = IP_TOS,
771 
772                 .set_optval = { 1, 1, 1, 1 },
773                 .set_optlen = 4,
774                 .get_optval = { 1 << 3 },
775                 .get_optlen = 1,
776         },
777         {
778                 .descr = "setsockopt: deny write ctx->retval",
779                 .insns = {
780                         /* ctx->retval = 0 */
781                         BPF_MOV64_IMM(BPF_REG_0, 0),
782                         BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_0,
783                                     offsetof(struct bpf_sockopt, retval)),
784 
785                         /* return 1 */
786                         BPF_MOV64_IMM(BPF_REG_0, 1),
787                         BPF_EXIT_INSN(),
788                 },
789                 .attach_type = BPF_CGROUP_SETSOCKOPT,
790                 .expected_attach_type = BPF_CGROUP_SETSOCKOPT,
791 
792                 .error = DENY_LOAD,
793         },
794         {
795                 .descr = "setsockopt: deny read ctx->retval",
796                 .insns = {
797                         /* r6 = ctx->retval */
798                         BPF_LDX_MEM(BPF_W, BPF_REG_6, BPF_REG_1,
799                                     offsetof(struct bpf_sockopt, retval)),
800 
801                         /* return 1 */
802                         BPF_MOV64_IMM(BPF_REG_0, 1),
803                         BPF_EXIT_INSN(),
804                 },
805                 .attach_type = BPF_CGROUP_SETSOCKOPT,
806                 .expected_attach_type = BPF_CGROUP_SETSOCKOPT,
807 
808                 .error = DENY_LOAD,
809         },
810         {
811                 .descr = "setsockopt: deny writing to ctx->optval",
812                 .insns = {
813                         /* ctx->optval = 1 */
814                         BPF_MOV64_IMM(BPF_REG_0, 1),
815                         BPF_STX_MEM(BPF_DW, BPF_REG_1, BPF_REG_0,
816                                     offsetof(struct bpf_sockopt, optval)),
817                         BPF_EXIT_INSN(),
818                 },
819                 .attach_type = BPF_CGROUP_SETSOCKOPT,
820                 .expected_attach_type = BPF_CGROUP_SETSOCKOPT,
821 
822                 .error = DENY_LOAD,
823         },
824         {
825                 .descr = "setsockopt: deny writing to ctx->optval_end",
826                 .insns = {
827                         /* ctx->optval_end = 1 */
828                         BPF_MOV64_IMM(BPF_REG_0, 1),
829                         BPF_STX_MEM(BPF_DW, BPF_REG_1, BPF_REG_0,
830                                     offsetof(struct bpf_sockopt, optval_end)),
831                         BPF_EXIT_INSN(),
832                 },
833                 .attach_type = BPF_CGROUP_SETSOCKOPT,
834                 .expected_attach_type = BPF_CGROUP_SETSOCKOPT,
835 
836                 .error = DENY_LOAD,
837         },
838         {
839                 .descr = "setsockopt: allow IP_TOS <= 128",
840                 .insns = {
841                         /* r6 = ctx->optval */
842                         BPF_LDX_MEM(BPF_DW, BPF_REG_6, BPF_REG_1,
843                                     offsetof(struct bpf_sockopt, optval)),
844                         /* r7 = ctx->optval + 1 */
845                         BPF_MOV64_REG(BPF_REG_7, BPF_REG_6),
846                         BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, 1),
847 
848                         /* r8 = ctx->optval_end */
849                         BPF_LDX_MEM(BPF_DW, BPF_REG_8, BPF_REG_1,
850                                     offsetof(struct bpf_sockopt, optval_end)),
851 
852                         /* if (ctx->optval + 1 <= ctx->optval_end) { */
853                         BPF_JMP_REG(BPF_JGT, BPF_REG_7, BPF_REG_8, 4),
854 
855                         /* r9 = ctx->optval[0] */
856                         BPF_LDX_MEM(BPF_B, BPF_REG_9, BPF_REG_6, 0),
857 
858                         /* if (ctx->optval[0] < 128) */
859                         BPF_JMP_IMM(BPF_JGT, BPF_REG_9, 128, 2),
860                         BPF_MOV64_IMM(BPF_REG_0, 1),
861                         BPF_JMP_A(1),
862                         /* } */
863 
864                         /* } else { */
865                         BPF_MOV64_IMM(BPF_REG_0, 0),
866                         /* } */
867 
868                         BPF_EXIT_INSN(),
869                 },
870                 .attach_type = BPF_CGROUP_SETSOCKOPT,
871                 .expected_attach_type = BPF_CGROUP_SETSOCKOPT,
872 
873                 .get_level = SOL_IP,
874                 .set_level = SOL_IP,
875 
876                 .get_optname = IP_TOS,
877                 .set_optname = IP_TOS,
878 
879                 .set_optval = { 0x80 },
880                 .set_optlen = 1,
881                 .get_optval = { 0x80 },
882                 .get_optlen = 1,
883         },
884         {
885                 .descr = "setsockopt: deny IP_TOS > 128",
886                 .insns = {
887                         /* r6 = ctx->optval */
888                         BPF_LDX_MEM(BPF_DW, BPF_REG_6, BPF_REG_1,
889                                     offsetof(struct bpf_sockopt, optval)),
890                         /* r7 = ctx->optval + 1 */
891                         BPF_MOV64_REG(BPF_REG_7, BPF_REG_6),
892                         BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, 1),
893 
894                         /* r8 = ctx->optval_end */
895                         BPF_LDX_MEM(BPF_DW, BPF_REG_8, BPF_REG_1,
896                                     offsetof(struct bpf_sockopt, optval_end)),
897 
898                         /* if (ctx->optval + 1 <= ctx->optval_end) { */
899                         BPF_JMP_REG(BPF_JGT, BPF_REG_7, BPF_REG_8, 4),
900 
901                         /* r9 = ctx->optval[0] */
902                         BPF_LDX_MEM(BPF_B, BPF_REG_9, BPF_REG_6, 0),
903 
904                         /* if (ctx->optval[0] < 128) */
905                         BPF_JMP_IMM(BPF_JGT, BPF_REG_9, 128, 2),
906                         BPF_MOV64_IMM(BPF_REG_0, 1),
907                         BPF_JMP_A(1),
908                         /* } */
909 
910                         /* } else { */
911                         BPF_MOV64_IMM(BPF_REG_0, 0),
912                         /* } */
913 
914                         BPF_EXIT_INSN(),
915                 },
916                 .attach_type = BPF_CGROUP_SETSOCKOPT,
917                 .expected_attach_type = BPF_CGROUP_SETSOCKOPT,
918 
919                 .get_level = SOL_IP,
920                 .set_level = SOL_IP,
921 
922                 .get_optname = IP_TOS,
923                 .set_optname = IP_TOS,
924 
925                 .set_optval = { 0x81 },
926                 .set_optlen = 1,
927                 .get_optval = { 0x00 },
928                 .get_optlen = 1,
929 
930                 .error = EPERM_SETSOCKOPT,
931         },
932 
933         /* ==================== prog_type ====================  */
934 
935         {
936                 .descr = "can attach only BPF_CGROUP_SETSOCKOP",
937                 .insns = {
938                         /* return 1 */
939                         BPF_MOV64_IMM(BPF_REG_0, 1),
940                         BPF_EXIT_INSN(),
941 
942                 },
943                 .prog_type = BPF_PROG_TYPE_CGROUP_SKB,
944                 .attach_type = BPF_CGROUP_SETSOCKOPT,
945                 .expected_attach_type = 0,
946                 .error = DENY_ATTACH,
947         },
948 
949         {
950                 .descr = "can attach only BPF_CGROUP_GETSOCKOP",
951                 .insns = {
952                         /* return 1 */
953                         BPF_MOV64_IMM(BPF_REG_0, 1),
954                         BPF_EXIT_INSN(),
955 
956                 },
957                 .prog_type = BPF_PROG_TYPE_CGROUP_SKB,
958                 .attach_type = BPF_CGROUP_GETSOCKOPT,
959                 .expected_attach_type = 0,
960                 .error = DENY_ATTACH,
961         },
962 };
963 
964 static int load_prog(const struct bpf_insn *insns,
965                      enum bpf_prog_type prog_type,
966                      enum bpf_attach_type expected_attach_type)
967 {
968         LIBBPF_OPTS(bpf_prog_load_opts, opts,
969                 .expected_attach_type = expected_attach_type,
970                 .log_level = 2,
971                 .log_buf = bpf_log_buf,
972                 .log_size = sizeof(bpf_log_buf),
973         );
974         int fd, insns_cnt = 0;
975 
976         for (;
977              insns[insns_cnt].code != (BPF_JMP | BPF_EXIT);
978              insns_cnt++) {
979         }
980         insns_cnt++;
981 
982         fd = bpf_prog_load(prog_type, NULL, "GPL", insns, insns_cnt, &opts);
983         if (verbose && fd < 0)
984                 fprintf(stderr, "%s\n", bpf_log_buf);
985 
986         return fd;
987 }
988 
989 /* Core function that handles io_uring ring initialization,
990  * sending SQE with sockopt command and waiting for the CQE.
991  */
992 static int uring_sockopt(int op, int fd, int level, int optname,
993                          const void *optval, socklen_t optlen)
994 {
995         struct io_uring_cqe *cqe;
996         struct io_uring_sqe *sqe;
997         struct io_uring ring;
998         int err;
999 
1000         err = io_uring_queue_init(1, &ring, 0);
1001         if (!ASSERT_OK(err, "io_uring initialization"))
1002                 return err;
1003 
1004         sqe = io_uring_get_sqe(&ring);
1005         if (!ASSERT_NEQ(sqe, NULL, "Get an SQE")) {
1006                 err = -1;
1007                 goto fail;
1008         }
1009 
1010         io_uring_prep_cmd(sqe, op, fd, level, optname, optval, optlen);
1011 
1012         err = io_uring_submit(&ring);
1013         if (!ASSERT_EQ(err, 1, "Submit SQE"))
1014                 goto fail;
1015 
1016         err = io_uring_wait_cqe(&ring, &cqe);
1017         if (!ASSERT_OK(err, "Wait for CQE"))
1018                 goto fail;
1019 
1020         err = cqe->res;
1021 
1022 fail:
1023         io_uring_queue_exit(&ring);
1024 
1025         return err;
1026 }
1027 
1028 static int uring_setsockopt(int fd, int level, int optname, const void *optval,
1029                             socklen_t optlen)
1030 {
1031         return uring_sockopt(SOCKET_URING_OP_SETSOCKOPT, fd, level, optname,
1032                              optval, optlen);
1033 }
1034 
1035 static int uring_getsockopt(int fd, int level, int optname, void *optval,
1036                             socklen_t *optlen)
1037 {
1038         int ret = uring_sockopt(SOCKET_URING_OP_GETSOCKOPT, fd, level, optname,
1039                                 optval, *optlen);
1040         if (ret < 0)
1041                 return ret;
1042 
1043         /* Populate optlen back to be compatible with systemcall interface,
1044          * and simplify the test.
1045          */
1046         *optlen = ret;
1047 
1048         return 0;
1049 }
1050 
1051 /* Execute the setsocktopt operation */
1052 static int call_setsockopt(bool use_io_uring, int fd, int level, int optname,
1053                            const void *optval, socklen_t optlen)
1054 {
1055         if (use_io_uring)
1056                 return uring_setsockopt(fd, level, optname, optval, optlen);
1057 
1058         return setsockopt(fd, level, optname, optval, optlen);
1059 }
1060 
1061 /* Execute the getsocktopt operation */
1062 static int call_getsockopt(bool use_io_uring, int fd, int level, int optname,
1063                            void *optval, socklen_t *optlen)
1064 {
1065         if (use_io_uring)
1066                 return uring_getsockopt(fd, level, optname, optval, optlen);
1067 
1068         return getsockopt(fd, level, optname, optval, optlen);
1069 }
1070 
1071 static int run_test(int cgroup_fd, struct sockopt_test *test, bool use_io_uring,
1072                     bool use_link)
1073 {
1074         int prog_type = BPF_PROG_TYPE_CGROUP_SOCKOPT;
1075         int sock_fd, err, prog_fd, link_fd = -1;
1076         void *optval = NULL;
1077         int ret = 0;
1078 
1079         if (test->prog_type)
1080                 prog_type = test->prog_type;
1081 
1082         prog_fd = load_prog(test->insns, prog_type, test->expected_attach_type);
1083         if (prog_fd < 0) {
1084                 if (test->error == DENY_LOAD)
1085                         return 0;
1086 
1087                 log_err("Failed to load BPF program");
1088                 return -1;
1089         }
1090 
1091         if (use_link) {
1092                 err = bpf_link_create(prog_fd, cgroup_fd, test->attach_type, NULL);
1093                 link_fd = err;
1094         } else {
1095                 err = bpf_prog_attach(prog_fd, cgroup_fd, test->attach_type, 0);
1096         }
1097         if (err < 0) {
1098                 if (test->error == DENY_ATTACH)
1099                         goto close_prog_fd;
1100 
1101                 log_err("Failed to attach BPF program");
1102                 ret = -1;
1103                 goto close_prog_fd;
1104         }
1105 
1106         sock_fd = socket(AF_INET, SOCK_STREAM, 0);
1107         if (sock_fd < 0) {
1108                 log_err("Failed to create AF_INET socket");
1109                 ret = -1;
1110                 goto detach_prog;
1111         }
1112 
1113         if (test->set_optlen) {
1114                 if (test->set_optlen >= PAGE_SIZE) {
1115                         int num_pages = test->set_optlen / PAGE_SIZE;
1116                         int remainder = test->set_optlen % PAGE_SIZE;
1117 
1118                         test->set_optlen = num_pages * sysconf(_SC_PAGESIZE) + remainder;
1119                 }
1120 
1121                 err = call_setsockopt(use_io_uring, sock_fd, test->set_level,
1122                                       test->set_optname, test->set_optval,
1123                                       test->set_optlen);
1124                 if (err) {
1125                         if (errno == EPERM && test->error == EPERM_SETSOCKOPT)
1126                                 goto close_sock_fd;
1127                         if (errno == EFAULT && test->error == EFAULT_SETSOCKOPT)
1128                                 goto free_optval;
1129 
1130                         log_err("Failed to call setsockopt");
1131                         ret = -1;
1132                         goto close_sock_fd;
1133                 }
1134         }
1135 
1136         if (test->get_optlen) {
1137                 if (test->get_optlen >= PAGE_SIZE) {
1138                         int num_pages = test->get_optlen / PAGE_SIZE;
1139                         int remainder = test->get_optlen % PAGE_SIZE;
1140 
1141                         test->get_optlen = num_pages * sysconf(_SC_PAGESIZE) + remainder;
1142                 }
1143 
1144                 optval = malloc(test->get_optlen);
1145                 memset(optval, 0, test->get_optlen);
1146                 socklen_t optlen = test->get_optlen;
1147                 socklen_t expected_get_optlen = test->get_optlen_ret ?:
1148                         test->get_optlen;
1149 
1150                 err = call_getsockopt(use_io_uring, sock_fd, test->get_level,
1151                                       test->get_optname, optval, &optlen);
1152                 if (err) {
1153                         if (errno == EOPNOTSUPP && test->error == EOPNOTSUPP_GETSOCKOPT)
1154                                 goto free_optval;
1155                         if (errno == EPERM && test->error == EPERM_GETSOCKOPT)
1156                                 goto free_optval;
1157                         if (errno == EFAULT && test->error == EFAULT_GETSOCKOPT)
1158                                 goto free_optval;
1159 
1160                         log_err("Failed to call getsockopt");
1161                         ret = -1;
1162                         goto free_optval;
1163                 }
1164 
1165                 if (optlen != expected_get_optlen) {
1166                         errno = 0;
1167                         log_err("getsockopt returned unexpected optlen");
1168                         ret = -1;
1169                         goto free_optval;
1170                 }
1171 
1172                 if (memcmp(optval, test->get_optval, optlen) != 0) {
1173                         errno = 0;
1174                         log_err("getsockopt returned unexpected optval");
1175                         ret = -1;
1176                         goto free_optval;
1177                 }
1178         }
1179 
1180         ret = test->error != OK;
1181 
1182 free_optval:
1183         free(optval);
1184 close_sock_fd:
1185         close(sock_fd);
1186 detach_prog:
1187         if (use_link) {
1188                 if (link_fd >= 0)
1189                         close(link_fd);
1190         } else {
1191                 bpf_prog_detach2(prog_fd, cgroup_fd, test->attach_type);
1192         }
1193 close_prog_fd:
1194         close(prog_fd);
1195         return ret;
1196 }
1197 
1198 void test_sockopt(void)
1199 {
1200         int cgroup_fd, i;
1201 
1202         cgroup_fd = test__join_cgroup("/sockopt");
1203         if (!ASSERT_GE(cgroup_fd, 0, "join_cgroup"))
1204                 return;
1205 
1206         for (i = 0; i < ARRAY_SIZE(tests); i++) {
1207                 if (!test__start_subtest(tests[i].descr))
1208                         continue;
1209 
1210                 ASSERT_OK(run_test(cgroup_fd, &tests[i], false, false),
1211                           tests[i].descr);
1212                 ASSERT_OK(run_test(cgroup_fd, &tests[i], false, true),
1213                           tests[i].descr);
1214                 if (tests[i].io_uring_support)
1215                         ASSERT_OK(run_test(cgroup_fd, &tests[i], true, false),
1216                                   tests[i].descr);
1217         }
1218 
1219         close(cgroup_fd);
1220 }
1221 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php