(root)/
strace-6.5/
tests/
prctl-seccomp-filter-v.c
       1  /*
       2   * Check verbose decoding of prctl PR_SET_SECCOMP SECCOMP_MODE_FILTER.
       3   *
       4   * Copyright (c) 2015-2016 Dmitry V. Levin <ldv@strace.io>
       5   * Copyright (c) 2016-2021 The strace developers.
       6   * All rights reserved.
       7   *
       8   * SPDX-License-Identifier: GPL-2.0-or-later
       9   */
      10  
      11  #include "tests.h"
      12  #include <stddef.h>
      13  #include <unistd.h>
      14  #include <stdio.h>
      15  #include <errno.h>
      16  #include <sys/prctl.h>
      17  #include <linux/seccomp.h>
      18  #include <linux/filter.h>
      19  #include "scno.h"
      20  
      21  #if defined BPF_JUMP && defined BPF_STMT
      22  
      23  # define SOCK_FILTER_ALLOW_SYSCALL(nr) \
      24  		BPF_JUMP(BPF_JMP|BPF_K|BPF_JEQ, __NR_ ## nr, 0, 1), \
      25  		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW)
      26  
      27  # define SOCK_FILTER_DENY_SYSCALL(nr, err) \
      28  		BPF_JUMP(BPF_JMP|BPF_K|BPF_JEQ, __NR_ ## nr, 0, 1), \
      29  		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ERRNO|(SECCOMP_RET_DATA & (err)))
      30  
      31  # define SOCK_FILTER_KILL_PROCESS \
      32  		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_KILL)
      33  
      34  # define PRINT_ALLOW_SYSCALL(nr) \
      35  	printf("BPF_JUMP(BPF_JMP|BPF_K|BPF_JEQ, %#lx, 0, 0x1), " \
      36  	       "BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW), ", \
      37  	       (long) __NR_ ## nr)
      38  
      39  # define PRINT_DENY_SYSCALL(nr, err) \
      40  	printf("BPF_JUMP(BPF_JMP|BPF_K|BPF_JEQ, %#lx, 0, 0x1), " \
      41  	       "BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ERRNO|%#x), ", \
      42  	       (long) __NR_ ## nr, err)
      43  
      44  static const struct sock_filter filter[] = {
      45  	/* load syscall number */
      46  	BPF_STMT(BPF_LD|BPF_W|BPF_ABS, offsetof(struct seccomp_data, nr)),
      47  
      48  	/* allow syscalls */
      49  	SOCK_FILTER_ALLOW_SYSCALL(close),
      50  	SOCK_FILTER_ALLOW_SYSCALL(exit),
      51  	SOCK_FILTER_ALLOW_SYSCALL(exit_group),
      52  
      53  	/* deny syscalls */
      54  	SOCK_FILTER_DENY_SYSCALL(sync, EBUSY),
      55  	SOCK_FILTER_DENY_SYSCALL(setsid, EPERM),
      56  
      57  	/* kill process */
      58  	SOCK_FILTER_KILL_PROCESS
      59  };
      60  
      61  static const struct sock_fprog prog = {
      62  	.len = ARRAY_SIZE(filter),
      63  	.filter = (struct sock_filter *) filter,
      64  };
      65  
      66  int
      67  main(void)
      68  {
      69  	int fds[2];
      70  
      71  	prctl_marker();
      72  
      73  	puts("prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)  = 0");
      74  
      75  	printf("prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, {len=%u, filter=[",
      76  	       prog.len);
      77  
      78  	printf("BPF_STMT(BPF_LD|BPF_W|BPF_ABS, %#x), ",
      79  	       (unsigned) offsetof(struct seccomp_data, nr));
      80  
      81  	PRINT_ALLOW_SYSCALL(close);
      82  	PRINT_ALLOW_SYSCALL(exit);
      83  	PRINT_ALLOW_SYSCALL(exit_group);
      84  
      85  	PRINT_DENY_SYSCALL(sync, EBUSY),
      86  	PRINT_DENY_SYSCALL(setsid, EPERM),
      87  
      88  	printf("BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_KILL_THREAD)");
      89  
      90  	puts("]}) = 0");
      91  	puts("+++ exited with 0 +++");
      92  
      93  	fflush(stdout);
      94  	close(0);
      95  	close(1);
      96  
      97  	if (pipe(fds))
      98  		perror_msg_and_fail("pipe");
      99  	if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0))
     100  		perror_msg_and_skip("PR_SET_NO_NEW_PRIVS");
     101  	if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog))
     102  		perror_msg_and_skip("PR_SET_SECCOMP");
     103  	if (close(0) || close(1))
     104  		_exit(77);
     105  
     106  	_exit(0);
     107  }
     108  
     109  #else
     110  
     111  SKIP_MAIN_UNDEFINED("BPF_JUMP && BPF_STMT")
     112  
     113  #endif