static void
install_filter(void)
{
    struct sock_filter filter[] = {
        /* Load architecture */

        BPF_STMT(BPF_LD | BPF_W | BPF_ABS,
                (offsetof(struct seccomp_data, arch))),

        /* Kill process if the architecture is not what we expect */

        BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, AUDIT_ARCH_X86_64, 1, 0),
        BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_KILL),

        /* Load system call number */

        BPF_STMT(BPF_LD | BPF_W | BPF_ABS,
                 (offsetof(struct seccomp_data, nr))),

        /* Allow system calls other than open() */

        BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, __NR_open, 1, 0),
        BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW),

        /* Kill process on open() */

        BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_KILL)
    };

    struct sock_fprog prog = {
        .len = (unsigned short) (sizeof(filter) / sizeof(filter[0])),
        .filter = filter,
    };

    if (seccomp(SECCOMP_SET_MODE_FILTER, 0, &prog) == -1)
        errExit("seccomp");
    /* On Linux 3.16 and earlier, we must instead use:
            if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog))
                errExit("prctl-PR_SET_SECCOMP");
    */
}

int
main(int argc, char **argv)
{
    if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0))
        errExit("prctl");

    install_filter();

    if (open("/tmp/a", O_RDONLY) == -1)
        errExit("open");

    printf("We shouldn't see this message\n");

    exit(EXIT_SUCCESS);
}
示例#2
0
文件: seccomp.c 项目: nbp/rr
int main(int argc, char* argv[]) {
  struct sigaction sa;
  pthread_t thread;
  pthread_t w_thread;
  char ch;

  test_assert(0 == pipe(pipe_fds));

  sa.sa_sigaction = handler;
  sigemptyset(&sa.sa_mask);
  sa.sa_flags = SA_SIGINFO;
  sigaction(SIGSYS, &sa, NULL);

  pthread_create(&w_thread, NULL, waiting_thread, NULL);

  /* Prepare syscallbuf patch path. Need to do this after
     pthread_create since when we have more than one
     thread we take a different syscall path... */
  open("/dev/null", O_RDONLY);

  test_assert(0 == prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0));
  test_assert(1 == prctl(PR_GET_NO_NEW_PRIVS, 0, 0, 0, 0));
  install_filter();
  test_assert(2 == prctl(PR_GET_SECCOMP));

  test_assert(1 == write(pipe_fds[1], "c", 1));
  pthread_join(w_thread, NULL);

  test_assert(-1 == syscall(SYS_pipe, pipe_fds));
  test_assert(ESRCH == errno);

  /* Spawning a thread will execute an rrcall_init_buffers syscall,
     which our filter tries to block but shouldn't be able to. */
  pthread_create(&thread, NULL, run_thread, NULL);
  pthread_join(thread, NULL);

  /* Check that the ioctls used by syscallbuf aren't blocked */
  test_assert(1 == write(pipe_fds[1], "c", 1));
  test_assert(1 == read(pipe_fds[0], &ch, 1));
  test_assert(1 == write(pipe_fds[1], "c", 1));
  test_assert(1 == read(pipe_fds[0], &ch, 1));

  syscall(SYS_geteuid);
  open("/dev/null", O_RDONLY);
  test_assert(count_SIGSYS == 2);

  atomic_puts("SUCCESS");

  return 0;
}
示例#3
0
文件: seccomp_tsync.c 项目: khuey/rr
static void install_filter(void) {
  struct sock_filter filter[] = { /* Allow all system calls */
                                  BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW)
  };
  struct sock_fprog prog = {
    .len = (unsigned short)(sizeof(filter) / sizeof(filter[0])),
    .filter = filter,
  };
  int ret;

  ret = syscall(RR_seccomp, SECCOMP_SET_MODE_FILTER, SECCOMP_FILTER_FLAG_TSYNC,
                &prog);
  if (ret == -1 && errno == ENOSYS) {
    atomic_puts("seccomp syscall not supported");
    atomic_puts("EXIT-SUCCESS");
    exit(0);
  }
  test_assert(ret == 0);
}

static void* waiting_thread(__attribute__((unused)) void* p) {
  char buf;
  test_assert(1 == read(pipe_fds[0], &buf, 1));
  /* Check this thread *was* affected by SECCOMP_FILTER_FLAG_TSYNC */
  test_assert(2 == prctl(PR_GET_SECCOMP));
  return NULL;
}

int main(void) {
  pthread_t w_thread;

  test_assert(0 == pipe(pipe_fds));

  pthread_create(&w_thread, NULL, waiting_thread, NULL);

  /* Prepare syscallbuf patch path. Need to do this after
     pthread_create since when we have more than one
     thread we take a different syscall path... */
  test_assert(0 == prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0));
  install_filter();
  test_assert(2 == prctl(PR_GET_SECCOMP));

  test_assert(1 == write(pipe_fds[1], "c", 1));
  pthread_join(w_thread, NULL);

  atomic_puts("EXIT-SUCCESS");

  return 0;
}
int
main(int argc, char **argv)
{
    int fd;

    if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0))
        errExit("prctl");

    install_filter();

    fd = open("/dev/zero", O_RDWR);
    if (fd == -1)
        errExit("open");

    seek_test(fd, 0);
    seek_test(fd, 10000);
    seek_test(fd, 0x100000001);

    exit(EXIT_SUCCESS);
}
示例#5
0
static int install_filter(int nr, int arch, int error)
{
	struct sock_filter filter[] = {
		BPF_STMT(BPF_LD+BPF_W+BPF_ABS,
			 (offsetof(struct seccomp_data, arch))),
		BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, arch, 0, 3),
		BPF_STMT(BPF_LD+BPF_W+BPF_ABS,
			 (offsetof(struct seccomp_data, nr))),
		BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, nr, 0, 1),
		BPF_STMT(BPF_RET+BPF_K,
			 SECCOMP_RET_ERRNO|(error & SECCOMP_RET_DATA)),
		BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW),
	};
	struct sock_fprog prog = {
		.len = (unsigned short)(sizeof(filter)/sizeof(filter[0])),
		.filter = filter,
	};
	if (prctl(PR_SET_SECCOMP, 2, &prog)) {
		perror("prctl");
		return 1;
	}
	return 0;
}

int main(int argc, char **argv)
{
	if (argc < 5) {
		fprintf(stderr, "Usage:\n"
			"dropper <syscall_nr> <arch> <errno> <prog> [<args>]\n"
			"Hint:	AUDIT_ARCH_I386: 0x%X\n"
			"	AUDIT_ARCH_X86_64: 0x%X\n"
			"\n", AUDIT_ARCH_I386, AUDIT_ARCH_X86_64);
		return 1;
	}
	if (install_filter(strtol(argv[1], NULL, 0), strtol(argv[2], NULL, 0),
			   strtol(argv[3], NULL, 0)))
		return 1;
	execv(argv[4], &argv[4]);
	printf("Failed to execv\n");
	return 255;
}
示例#6
0
文件: seccomp.c 项目: CarterTsai/rr
static void install_filter(void) {
  struct sock_filter filter[] = {
    /* Load system call number from 'seccomp_data' buffer into
       accumulator */
    BPF_STMT(BPF_LD | BPF_W | BPF_ABS, offsetof(struct seccomp_data, nr)),
    /* Jump forward 1 instruction if system call number
       is not SYS_pipe */
    BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, SYS_pipe, 0, 1),
    /* Error out with ESRCH */
    BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ERRNO | (ESRCH & SECCOMP_RET_DATA)),
    /* Jump forward 1 instruction if system call number
       is not SYS_geteuid */
    BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, SYS_geteuid, 0, 1),
    /* Trigger SIGSYS */
    BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_TRAP),
    /* Jump forward 1 instruction if system call number
       is not SYS_open */
    BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, SYS_open, 0, 1),
    /* Trigger SIGSYS */
    BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_TRAP),
    /* Jump forward 1 instruction if system call number
       is not SYS_rrcall_init_buffers */
    BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, SYS_rrcall_init_buffers, 0, 1),
    /* Trigger SIGSYS */
    BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_TRAP),
    /* Jump forward 1 instruction if system call number
       is not SYS_ioctl */
    BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, SYS_ioctl, 0, 1),
    /* Trigger SIGSYS */
    BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_TRAP),
    /* Destination of system call number mismatch: allow other
       system calls */
    BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW)
  };
  struct sock_fprog prog = {
    .len = (unsigned short)(sizeof(filter) / sizeof(filter[0])),
    .filter = filter,
  };
  int ret;

  ret = syscall(RR_seccomp, SECCOMP_SET_MODE_FILTER, 0, &prog);
  if (ret == -1 && errno == ENOSYS) {
    ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog);
  }
  test_assert(ret == 0);
}

static void* waiting_thread(__attribute__((unused)) void* p) {
  char buf;
  test_assert(1 == read(pipe_fds[0], &buf, 1));
  /* Check this thread wasn't affected by the SET_SECCOMP */
  test_assert(0 == prctl(PR_GET_SECCOMP));
  return NULL;
}

static void* run_thread(__attribute__((unused)) void* p) {
  atomic_printf("EXIT-");
  return NULL;
}

int main(void) {
  struct sigaction sa;
  pthread_t thread;
  pthread_t w_thread;
  char ch;

  test_assert(0 == pipe(pipe_fds));

  sa.sa_sigaction = handler;
  sigemptyset(&sa.sa_mask);
  sa.sa_flags = SA_SIGINFO;
  sigaction(SIGSYS, &sa, NULL);

  pthread_create(&w_thread, NULL, waiting_thread, NULL);

  /* Prepare syscallbuf patch path. Need to do this after
     pthread_create since when we have more than one
     thread we take a different syscall path... */
  open("/dev/null", O_RDONLY);

  test_assert(0 == prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0));
  test_assert(1 == prctl(PR_GET_NO_NEW_PRIVS, 0, 0, 0, 0));
  install_filter();
  test_assert(2 == prctl(PR_GET_SECCOMP));

  test_assert(1 == write(pipe_fds[1], "c", 1));
  pthread_join(w_thread, NULL);

  test_assert(-1 == syscall(SYS_pipe, pipe_fds));
  test_assert(ESRCH == errno);

  /* Spawning a thread will execute an rrcall_init_buffers syscall,
     which our filter tries to block but shouldn't be able to. */
  pthread_create(&thread, NULL, run_thread, NULL);
  pthread_join(thread, NULL);

  /* Check that the ioctls used by syscallbuf aren't blocked */
  test_assert(1 == write(pipe_fds[1], "c", 1));
  test_assert(1 == read(pipe_fds[0], &ch, 1));
  test_assert(1 == write(pipe_fds[1], "c", 1));
  test_assert(1 == read(pipe_fds[0], &ch, 1));

  syscall(SYS_geteuid);
  open("/dev/null", O_RDONLY);
  test_assert(count_SIGSYS == 2);

  atomic_puts("SUCCESS");

  return 0;
}
示例#7
0
void main_loop(int icmp_sock, __u8 *packet, int packlen)
{
	char addrbuf[128];
	char ans_data[4096];
	struct iovec iov;
	struct msghdr msg;
	struct cmsghdr *c;
	int cc;
	int next;
	int polling;

	iov.iov_base = (char *)packet;

	for (;;) {
		/* Check exit conditions. */
		if (exiting)
			break;
		if (npackets && nreceived + nerrors >= npackets)
			break;
		if (deadline && nerrors)
			break;
		/* Check for and do special actions. */
		if (status_snapshot)
			status();

		/* Send probes scheduled to this time. */
		do {
			next = pinger();
			next = schedule_exit(next);
		} while (next <= 0);

		/* "next" is time to send next probe, if positive.
		 * If next<=0 send now or as soon as possible. */

		/* Technical part. Looks wicked. Could be dropped,
		 * if everyone used the newest kernel. :-)
		 * Its purpose is:
		 * 1. Provide intervals less than resolution of scheduler.
		 *    Solution: spinning.
		 * 2. Avoid use of poll(), when recvmsg() can provide
		 *    timed waiting (SO_RCVTIMEO). */
		polling = 0;
		if ((options & (F_ADAPTIVE|F_FLOOD_POLL)) || next<SCHINT(interval)) {
			int recv_expected = in_flight();

			/* If we are here, recvmsg() is unable to wait for
			 * required timeout. */
			if (1000 % HZ == 0 ? next <= 1000 / HZ : (next < INT_MAX / HZ && next * HZ <= 1000)) {
				/* Very short timeout... So, if we wait for
				 * something, we sleep for MININTERVAL.
				 * Otherwise, spin! */
				if (recv_expected) {
					next = MININTERVAL;
				} else {
					next = 0;
					/* When spinning, no reasons to poll.
					 * Use nonblocking recvmsg() instead. */
					polling = MSG_DONTWAIT;
					/* But yield yet. */
					sched_yield();
				}
			}

			if (!polling &&
			    ((options & (F_ADAPTIVE|F_FLOOD_POLL)) || interval)) {
				struct pollfd pset;
				pset.fd = icmp_sock;
				pset.events = POLLIN|POLLERR;
				pset.revents = 0;
				if (poll(&pset, 1, next) < 1 ||
				    !(pset.revents&(POLLIN|POLLERR)))
					continue;
				polling = MSG_DONTWAIT;
			}
		}

		for (;;) {
			struct timeval *recv_timep = NULL;
			struct timeval recv_time;
			int not_ours = 0; /* Raw socket can receive messages
					   * destined to other running pings. */

			iov.iov_len = packlen;
			memset(&msg, 0, sizeof(msg));
			msg.msg_name = addrbuf;
			msg.msg_namelen = sizeof(addrbuf);
			msg.msg_iov = &iov;
			msg.msg_iovlen = 1;
			msg.msg_control = ans_data;
			msg.msg_controllen = sizeof(ans_data);

			cc = recvmsg(icmp_sock, &msg, polling);
			polling = MSG_DONTWAIT;

			if (cc < 0) {
				if (errno == EAGAIN || errno == EINTR)
					break;
				if (!receive_error_msg()) {
					if (errno) {
						perror("ping: recvmsg");
						break;
					}
					not_ours = 1;
				}
			} else {

#ifdef SO_TIMESTAMP
				for (c = CMSG_FIRSTHDR(&msg); c; c = CMSG_NXTHDR(&msg, c)) {
					if (c->cmsg_level != SOL_SOCKET ||
					    c->cmsg_type != SO_TIMESTAMP)
						continue;
					if (c->cmsg_len < CMSG_LEN(sizeof(struct timeval)))
						continue;
					recv_timep = (struct timeval*)CMSG_DATA(c);
				}
#endif

				if ((options&F_LATENCY) || recv_timep == NULL) {
					if ((options&F_LATENCY) ||
					    ioctl(icmp_sock, SIOCGSTAMP, &recv_time))
						gettimeofday(&recv_time, NULL);
					recv_timep = &recv_time;
				}

				not_ours = parse_reply(&msg, cc, addrbuf, recv_timep);
			}

			/* See? ... someone runs another ping on this host. */
			if (not_ours && !using_ping_socket)
				install_filter();

			/* If nothing is in flight, "break" returns us to pinger. */
			if (in_flight() == 0)
				break;

			/* Otherwise, try to recvmsg() again. recvmsg()
			 * is nonblocking after the first iteration, so that
			 * if nothing is queued, it will receive EAGAIN
			 * and return to pinger. */
		}
	}
	finish();
}
示例#8
0
static void
install_filter(void)
{
    struct sock_filter filter[] = {
        /* Load architecture */

        BPF_STMT(BPF_LD | BPF_W | BPF_ABS,
                (offsetof(struct seccomp_data, arch))),

        /* Kill process if the architecture is not what we expect */

        BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, AUDIT_ARCH_X86_64, 1, 0),
        BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_KILL),

        /* Load system call number */

        BPF_STMT(BPF_LD | BPF_W | BPF_ABS,
                 (offsetof(struct seccomp_data, nr))),

        /* Allow system calls other than open() */

        BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, __NR_open, 1, 0),
        BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW),

        /* Kill process on open() */

        BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_KILL)
    };

    struct sock_fprog prog = {
        .len = (unsigned short) (sizeof(filter) / sizeof(filter[0])),
        .filter = filter,
    };

    if (seccomp(SECCOMP_SET_MODE_FILTER, 0, &prog) == -1)
        errExit("seccomp");
}

int
main(int argc, char *argv[])
{
    int j, nloops;

    if (argc < 2) {
        fprintf(stderr, "Usage: %s <num-loops> [x]\n", argv[0]);
        fprintf(stderr, "       (use 'x' to run with BPF filter applied)\n");
        exit(EXIT_FAILURE);
    }

    if (argc > 2) {
        printf("Appling BPF filter\n");

        if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0))
            errExit("prctl");

        install_filter();
    }

    nloops = atoi(argv[1]);

    for (j = 0; j < nloops; j++)
        getppid();

    exit(EXIT_SUCCESS);
}
示例#9
0
文件: test.c 项目: minitu/secfall
void install_filter(void) {
	struct sock_filter filter[] = {
		BPF_STMT(BPF_LD | BPF_W | BPF_ABS,
				(offsetof(struct seccomp_data, arch))),
		BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K,
				AUDIT_ARCH_X86_64, 1, 0),
		BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_KILL),
		BPF_STMT(BPF_LD | BPF_W | BPF_ABS,
				(offsetof(struct seccomp_data, nr))),
		BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 1,
				1, 0),
		BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW),
		BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_TRACE)
	};

	struct sock_fprog prog = {
		.len = (unsigned short) (sizeof(filter) / sizeof(filter[0])),
		.filter = filter,
	};

	prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);

	prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog);
}

int main(int argc, char **argv) {
	pid_t child;
	struct user_regs_struct regs;

	// fork into tracee & tracer
	child = fork();

	if (child == 0) { // tracee
		ptrace(PTRACE_TRACEME, 0, NULL);

		install_filter();

		argv++;
		execvp(argv[0], argv); // execute tracee
	}
	else { // tracer
		int status;
		siginfo_t siginfo;

		waitpid(child, &status, 0); // wait for execve

		ptrace(PTRACE_SETOPTIONS, child, NULL, PTRACE_O_TRACESECCOMP);

		ptrace(PTRACE_CONT, child, NULL, NULL);

		while (1) { // trace loop
			waitpid(child, &status, 0);

			if (WIFEXITED(status) || WIFSIGNALED(status))
				break;

			ptrace(PTRACE_GETSIGINFO, child, NULL, &siginfo);
			printf("signal %d ", siginfo.si_signo);

			ptrace(PTRACE_GETREGS, child, NULL, &regs);
			printf("syscall %llu\n", regs.orig_rax);

			ptrace(PTRACE_CONT, child, NULL, NULL);
		}

		printf("\n");
	}

	return 0;
}
示例#10
0
bool net::filter::parse(const char* filter)
{
  if (!init()) {
    return false;
  }

  bool tcp = false;
  bool udp = false;
  bool src = false;
  bool dest = false;
  unsigned first = 0;
  unsigned last = 0;

  int state = 0; // Initial state.
  while (*filter) {
    switch (state) {
      case 0: // Initial state.
        switch (*filter) {
          case 'i':
          case 'I':
            filter++;
            state = 1; // ICMP.
            break;
          case 's':
          case 'S':
            tcp = true;
            udp = true;
            src = true;
            dest = false;

            filter++;
            state = 4; // "port".
            break;
          case 'd':
          case 'D':
            tcp = true;
            udp = true;
            src = false;
            dest = true;

            filter++;
            state = 4; // "port".
            break;
          case 't':
          case 'T':
            tcp = true;
            udp = false;
            src = false;
            dest = false;

            filter++;
            state = 2; // TCP.
            break;
          case 'u':
          case 'U':
            tcp = false;
            udp = true;
            src = false;
            dest = false;

            filter++;
            state = 3; // UDP.
            break;
          case '0':
          case '1':
          case '2':
          case '3':
          case '4':
          case '5':
          case '6':
          case '7':
          case '8':
          case '9':
            tcp = true;
            udp = true;
            src = true;
            dest = true;

            first = *filter - '0';

            filter++;
            state = 5; // Port or range of ports.
            break;
          case ' ':
          case '\t':
            filter++;
            break;
          default:
            return false;
        }

        break;
      case 1: // ICMP.
        if (((filter[0] != 'c') && (filter[0] != 'C')) || \
            ((filter[1] != 'm') && (filter[1] != 'M')) || \
            ((filter[2] != 'p') && (filter[2] != 'P'))) {
          return false;
        }

        if ((filter[3]) && (!IS_WHITE_SPACE(filter[3]))) {
          return false;
        }

        _M_icmp = true;

        filter += 3;
        state = 0; // Initial state.
        break;
      case 2: // TCP.
        if (((filter[0] != 'c') && (filter[0] != 'C')) || \
            ((filter[1] != 'p') && (filter[1] != 'P'))) {
          return false;
        }

        if ((!filter[2]) || (IS_WHITE_SPACE(filter[2]))) {
          set_tcp_ports(0, USHRT_MAX, true);

          filter += 2;
          state = 0; // Initial state.
        } else if (filter[2] == ':') {
          if ((filter[3] == 's') || (filter[3] == 'S')) {
            src = true;

            filter += 4;
            state = 4; // "port".
          } else if ((filter[3] == 'd') || (filter[3] == 'D')) {
            dest = true;

            filter += 4;
            state = 4; // "port".
          } else if (IS_DIGIT(filter[3])) {
            src = true;
            dest = true;

            first = filter[3] - '0';

            filter += 4;
            state = 5; // Port or range of ports.
          } else {
            return false;
          }
        } else {
          return false;
        }

        break;
      case 3: // UDP.
        if (((filter[0] != 'd') && (filter[0] != 'D')) || \
            ((filter[1] != 'p') && (filter[1] != 'P'))) {
          return false;
        }

        if ((!filter[2]) || (IS_WHITE_SPACE(filter[2]))) {
          set_udp_ports(0, USHRT_MAX, true);

          filter += 2;
          state = 0; // Initial state.
        } else if (filter[2] == ':') {
          if ((filter[3] == 's') || (filter[3] == 'S')) {
            src = true;

            filter += 4;
            state = 4; // "port".
          } else if ((filter[3] == 'd') || (filter[3] == 'D')) {
            dest = true;

            filter += 4;
            state = 4; // "port".
          } else if (IS_DIGIT(filter[3])) {
            src = true;
            dest = true;

            first = filter[3] - '0';

            filter += 4;
            state = 5; // Port or range of ports.
          } else {
            return false;
          }
        } else {
          return false;
        }

        break;
      case 4: // "port".
        if (((filter[0] != 'p') && (filter[0] != 'P')) || \
            ((filter[1] != 'o') && (filter[1] != 'O')) || \
            ((filter[2] != 'r') && (filter[2] != 'R')) || \
            ((filter[3] != 't') && (filter[3] != 'T')) || \
             (filter[4] != ':') || \
            (!IS_DIGIT(filter[5]))) {
          return false;
        }

        first = filter[5] - '0';

        filter += 6;
        state = 5; // Port or range of ports.
        break;
      case 5: // Port or range of ports.
        while (IS_DIGIT(*filter)) {
          if ((first = (first * 10) + (*filter - '0')) > USHRT_MAX) {
            return false;
          }

          filter++;
        }

        if (first == 0) {
          return false;
        }

        if (*filter == '-') {
          last = 0;

          filter++;
          state = 6; // Range of ports.
        } else if ((!*filter) || (IS_WHITE_SPACE(*filter))) {
          install_filter(tcp, udp, src, dest, first, first, true);

          state = 0; // Initial state.
        } else {
          return false;
        }

        break;
      case 6: // Range of ports.
        while (IS_DIGIT(*filter)) {
          if ((last = (last * 10) + (*filter - '0')) > USHRT_MAX) {
            return false;
          }

          filter++;
        }

        if (last == 0) {
          return false;
        }

        if ((*filter) && (!IS_WHITE_SPACE(*filter))) {
          return false;
        }

        if (first > last) {
          return false;
        }

        install_filter(tcp, udp, src, dest, first, last, true);

        state = 0; // Initial state.
        break;
    }
  }

  if (state != 0) {
    return false;
  }

  _M_filter = true;
  return true;
}
示例#11
0
static void
install_filter(void)
{
    struct sock_filter filter[] = {
        /* Load architecture */

        BPF_STMT(BPF_LD | BPF_W | BPF_ABS,
                (offsetof(struct seccomp_data, arch))),

        /* Kill the process if the architecture is not what we expect */

        BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, AUDIT_ARCH_X86_64, 1, 0),
        BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_KILL),

        /* Load system call number */

        BPF_STMT(BPF_LD | BPF_W | BPF_ABS,
                 (offsetof(struct seccomp_data, nr))),

        /* Allow syscalls other than open() */

        BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, __NR_open, 1, 0),
        BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW),

        /* Load second argument of open() (flags) into accumulator */

        BPF_STMT(BPF_LD | BPF_W | BPF_ABS,
                 (offsetof(struct seccomp_data, args[1]))),

        /* Kill the process if O_CREAT was specified */

        BPF_JUMP(BPF_JMP | BPF_JSET | BPF_K, O_CREAT, 0, 1),
        BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_KILL),

        /* Give ENOTSUP error on attempt to open for writing.
           Relies on the fact that O_RDWR and O_WRONLY are
           defined as single, nonoverlapping bits  */

        BPF_JUMP(BPF_JMP | BPF_JSET | BPF_K, O_WRONLY | O_RDWR, 0, 1),
        BPF_STMT(BPF_RET | BPF_K,
                 SECCOMP_RET_ERRNO | (ENOTSUP & SECCOMP_RET_DATA)),

        /* Otherwise allow the open() */

        BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW)
    };

    struct sock_fprog prog = {
        .len = (unsigned short) (sizeof(filter) / sizeof(filter[0])),
        .filter = filter,
    };

    if (seccomp(SECCOMP_SET_MODE_FILTER, 0, &prog))
        errExit("seccomp");
    /* On Linux 3.16 and earlier, we must instead use:
            if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog))
                errExit("prctl-PR_SET_SECCOMP");
    */
}

int
main(int argc, char **argv)
{
    if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0))
        errExit("prctl");

    install_filter();

    if (open("/tmp/a", O_RDONLY) == -1)
        perror("open1");
    if (open("/tmp/a", O_WRONLY) == -1)
        perror("open2");
    if (open("/tmp/a", O_RDWR) == -1)
        perror("open3");
    if (open("/tmp/a", O_CREAT | O_RDWR, 0600) == -1)
        perror("open4");

    exit(EXIT_SUCCESS);
}
示例#12
0
int main() {
  char intf[] = "mon0";		//any interface name so that tcpdump doesn't complain
  char filter_text[] = "type data or subtype ack";
  //do_ls_etc();
  install_filter(intf, filter_text);
}
示例#13
0
文件: bpf-direct.c 项目: 020gzh/linux
static int install_filter(void)
{
	struct sock_filter filter[] = {
		/* Grab the system call number */
		BPF_STMT(BPF_LD+BPF_W+BPF_ABS, syscall_nr),
		/* Jump table for the allowed syscalls */
		BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, __NR_rt_sigreturn, 0, 1),
		BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW),
#ifdef __NR_sigreturn
		BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, __NR_sigreturn, 0, 1),
		BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW),
#endif
		BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, __NR_exit_group, 0, 1),
		BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW),
		BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, __NR_exit, 0, 1),
		BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW),
		BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, __NR_read, 1, 0),
		BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, __NR_write, 3, 2),

		/* Check that read is only using stdin. */
		BPF_STMT(BPF_LD+BPF_W+BPF_ABS, syscall_arg(0)),
		BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, STDIN_FILENO, 4, 0),
		BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_KILL),

		/* Check that write is only using stdout */
		BPF_STMT(BPF_LD+BPF_W+BPF_ABS, syscall_arg(0)),
		BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, STDOUT_FILENO, 1, 0),
		/* Trap attempts to write to stderr */
		BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, STDERR_FILENO, 1, 2),

		BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW),
		BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_TRAP),
		BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_KILL),
	};
	struct sock_fprog prog = {
		.len = (unsigned short)(sizeof(filter)/sizeof(filter[0])),
		.filter = filter,
	};

	if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) {
		perror("prctl(NO_NEW_PRIVS)");
		return 1;
	}


	if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog)) {
		perror("prctl");
		return 1;
	}
	return 0;
}

#define payload(_c) (_c), sizeof((_c))
int main(int argc, char **argv)
{
	char buf[4096];
	ssize_t bytes = 0;
	if (install_emulator())
		return 1;
	if (install_filter())
		return 1;
	syscall(__NR_write, STDOUT_FILENO,
		payload("OHAI! WHAT IS YOUR NAME? "));
	bytes = syscall(__NR_read, STDIN_FILENO, buf, sizeof(buf));
	syscall(__NR_write, STDOUT_FILENO, payload("HELLO, "));
	syscall(__NR_write, STDOUT_FILENO, buf, bytes);
	syscall(__NR_write, STDERR_FILENO,
		payload("Error message going to STDERR\n"));
	return 0;
}