示例#1
0
int lxc_read_seccomp_config(struct lxc_conf *conf)
{
	FILE *f;
	int ret;
	int check_seccomp_attr_set;

	if (!conf->seccomp)
		return 0;

	if (!use_seccomp())
		return 0;
#if HAVE_SCMP_FILTER_CTX
	/* XXX for debug, pass in SCMP_ACT_TRAP */
	conf->seccomp_ctx = seccomp_init(SCMP_ACT_KILL);
	ret = !conf->seccomp_ctx;
#else
	ret = seccomp_init(SCMP_ACT_KILL) < 0;
#endif
	if (ret) {
		ERROR("Failed initializing seccomp.");
		return -1;
	}

/* turn off no-new-privs.  We don't want it in lxc, and it breaks
 * with apparmor */
#if HAVE_SCMP_FILTER_CTX
	check_seccomp_attr_set = seccomp_attr_set(conf->seccomp_ctx, SCMP_FLTATR_CTL_NNP, 0);
#else
	check_seccomp_attr_set = seccomp_attr_set(SCMP_FLTATR_CTL_NNP, 0);
#endif
	if (check_seccomp_attr_set) {
		ERROR("Failed to turn off n-new-privs.");
		return -1;
	}
#ifdef SCMP_FLTATR_ATL_TSKIP
	if (seccomp_attr_set(conf->seccomp_ctx, SCMP_FLTATR_ATL_TSKIP, 1)) {
		WARN("Failed to turn on seccomp nop-skip, continuing");
	}
#endif

	f = fopen(conf->seccomp, "r");
	if (!f) {
		SYSERROR("Failed to open seccomp policy file %s.", conf->seccomp);
		return -1;
	}
	ret = parse_config(f, conf);
	fclose(f);
	return ret;
}
int seccomp_start(void)
{
    int rc = 0;
    unsigned int i = 0;
    scmp_filter_ctx ctx;

    ctx = seccomp_init(SCMP_ACT_KILL);
    if (ctx == NULL) {
        rc = -1;
        goto seccomp_return;
    }

    for (i = 0; i < ARRAY_SIZE(seccomp_whitelist); i++) {
        rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, seccomp_whitelist[i].num, 0);
        if (rc < 0) {
            goto seccomp_return;
        }
        rc = seccomp_syscall_priority(ctx, seccomp_whitelist[i].num,
                                      seccomp_whitelist[i].priority);
        if (rc < 0) {
            goto seccomp_return;
        }
    }

    rc = seccomp_load(ctx);

  seccomp_return:
    seccomp_release(ctx);
    return rc;
}
示例#3
0
void setup_seccomp() {
	scmp_filter_ctx ctx = seccomp_init(SCMP_ACT_KILL);
	if(!ctx) exit(-1);
	if(seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(open), 0)) exit(-1);
	if(seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socket), 0)) exit(-1);
#if (SCMP_SYS(setsockopt))
#warning System does not have sys_setsockopt, the expected way to do SO_REUSEADDR.
	if(seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(setsockopt), 0)) exit(-1);
#endif
#ifdef NEEDS_SOCKETCALL
#warning NEEDS_SOCKETCALL=1 has been set, I wish it was not needed on some systems.
	if(seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socketcall), 0)) exit(-1);
#endif
	if(seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(bind), 0)) exit(-1);
	if(seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(listen), 0)) exit(-1);
	if(seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(rt_sigaction), 0)) exit(-1);
	if(seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(accept), 0)) exit(-1);
	if(seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(clone), 0)) exit(-1);
	if(seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(setresuid32), 0)) exit(-1);
	if(seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(setresgid32), 0)) exit(-1);
	if(seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(alarm), 0)) exit(-1);
	if(seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(dup2), 0)) exit(-1);
	if(seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(close), 0)) exit(-1);
	if(seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(write), 0)) exit(-1);
	if(seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(read), 0)) exit(-1);
	if(seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(exit_group), 0)) exit(-1);
	
	// Allow further restrictions.
	if(seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(prctl), 1, SCMP_A0(SCMP_CMP_EQ, PR_SET_NO_NEW_PRIVS))) exit(-1);
	if(seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(prctl), 1, SCMP_A0(SCMP_CMP_EQ, PR_SET_SECCOMP))) exit(-1);
	
	if(seccomp_load(ctx)) exit(-1);
	seccomp_release(ctx);
}
示例#4
0
int main(int argc, char *argv[]) {

    if (argc < 6 || strcmp(argv[1], "--error") || (strcmp(argv[3], "--allow") && strcmp(argv[3], "--deny"))) {
        usage(argv[0]);
        return 1;
    }

    const int err = parse_positive(argv[2]);
    if (err < 0) {
        return 2;
    }
    const bool default_block = !strcmp(argv[3], "--allow");

    if (-1 == prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) {
        perror("prctl");
        return 10;
    }

    uint32_t rule_action = !default_block ? SCMP_ACT_ERRNO(err) : SCMP_ACT_ALLOW;
    scmp_filter_ctx ctx = seccomp_init(default_block ? SCMP_ACT_ERRNO(err) : SCMP_ACT_ALLOW);

    int arg = 4;
    for (; arg < argc; ++arg) {
        if (!strcmp(argv[arg], "--")) {
            ++arg;
            break;
        }

        const int syscall_no = parse_positive(argv[arg]);

        if (syscall_no < 0) {
            seccomp_release(ctx);
            return 5;
        }

        if (seccomp_rule_add(ctx, rule_action, syscall_no, 0)) {
            perror("rule add");
            fprintf(stderr, "not a valid syscall number for a rule: '%s'\n", argv[arg]);
            seccomp_release(ctx);
            return 20;
        }
    }

    if (arg == argc) {
        usage(argv[0]);
        return 3;
    }

    if (seccomp_load(ctx)) {
        perror("load");
        seccomp_release(ctx);
        return 4;
    }

    seccomp_release(ctx);
    execvp(argv[arg], &argv[arg]);
    perror("execve");
    return 5;
}
示例#5
0
void drop_privileges(void) {
    scmp_filter_ctx ctx = seccomp_init(DENY_ACTION);
    if (ctx == NULL) {
        return;
    }

    int rc = 0;
    rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(sigreturn), 0);
    rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(rt_sigprocmask), 0);
    rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(futex), 0);
    rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(epoll_wait), 0);
    rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(epoll_pwait), 0);
    rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(accept4), 0);
    rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(accept), 0);
    rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(write), 0);
    rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(writev), 0);
    rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(fstat), 0);
    rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mmap), 0);
    rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(munmap), 0);
    rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(shmctl), 0);
    rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(exit_group), 0);
    rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(brk), 0);
    rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(ioctl), 1, SCMP_A1(SCMP_CMP_EQ, TIOCGWINSZ));
    rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(ioctl), 1, SCMP_A1(SCMP_CMP_EQ, TCGETS));

#ifdef MEMCACHED_DEBUG
    rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(open), 0);
    rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(fcntl), 0);
    rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(read), 0);
    rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(readv), 0);
    rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(lseek), 0);
    rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(close), 0);
    rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(getpid), 0);

    if (settings.relaxed_privileges) {
        rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(openat), 0);
        rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mkdir), 0);
        rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(access), 0);
    }
#endif

    if (rc != 0) {
        goto fail;
    }

    rc = seccomp_load(ctx);
    if (rc < 0) {
        goto fail;
    }

    seccomp_release(ctx);
    return;

fail:
    seccomp_release(ctx);
    fprintf(stderr, "Failed to set a seccomp profile on the main thread\n");
    exit(EXIT_FAILURE);
}
int main(int argc, char *argv[])
{
	int rc;
	struct util_options opts;
	scmp_filter_ctx ctx = NULL;

	rc = util_getopt(argc, argv, &opts);
	if (rc < 0)
		goto out;

	ctx = seccomp_init(SCMP_ACT_KILL);
	if (ctx == NULL)
		return ENOMEM;

	rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(open), 0);
	if (rc != 0)
		goto out;

	rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(close), 0);
	if (rc != 0)
		goto out;

	rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(read), 3,
			      SCMP_A0(SCMP_CMP_EQ, STDIN_FILENO),
			      SCMP_A1(SCMP_CMP_NE, 0x0),
			      SCMP_A2(SCMP_CMP_LT, SSIZE_MAX));
	if (rc != 0)
		goto out;

	rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(write), 3,
			      SCMP_A0(SCMP_CMP_EQ, STDOUT_FILENO),
			      SCMP_A1(SCMP_CMP_NE, 0x0),
			      SCMP_A2(SCMP_CMP_LT, SSIZE_MAX));
	if (rc != 0)
		goto out;
	rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(write), 3,
			      SCMP_A0(SCMP_CMP_EQ, STDERR_FILENO),
			      SCMP_A1(SCMP_CMP_NE, 0x0),
			      SCMP_A2(SCMP_CMP_LT, SSIZE_MAX));
	if (rc != 0)
		goto out;

	rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(close), 0);
	if (rc != 0)
		goto out;

	rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(rt_sigreturn), 0);
	if (rc != 0)
		goto out;

	rc = util_filter_output(&opts, ctx);
	if (rc)
		goto out;

out:
	seccomp_release(ctx);
	return (rc < 0 ? -rc : rc);
}
示例#7
0
文件: seccomp.c 项目: ArikaChen/lxc
int lxc_read_seccomp_config(struct lxc_conf *conf)
{
	FILE *f;
	int ret;

	if (!conf->seccomp)
		return 0;

#if HAVE_SCMP_FILTER_CTX
	/* XXX for debug, pass in SCMP_ACT_TRAP */
	conf->seccomp_ctx = seccomp_init(SCMP_ACT_ERRNO(31));
	ret = !conf->seccomp_ctx;
#else
	ret = seccomp_init(SCMP_ACT_ERRNO(31)) < 0;
#endif
	if (ret) {
		ERROR("failed initializing seccomp");
		return -1;
	}

	/* turn of no-new-privs.  We don't want it in lxc, and it breaks
	 * with apparmor */
	if (seccomp_attr_set(
#if HAVE_SCMP_FILTER_CTX
			conf->seccomp_ctx,
#endif
			SCMP_FLTATR_CTL_NNP, 0)) {
		ERROR("failed to turn off n-new-privs\n");
		return -1;
	}

	process_lock();
	f = fopen(conf->seccomp, "r");
	process_unlock();
	if (!f) {
		SYSERROR("failed to open seccomp policy file %s\n", conf->seccomp);
		return -1;
	}
	ret = parse_config(f, conf);
	process_lock();
	fclose(f);
	process_unlock();
	return ret;
}
示例#8
0
文件: misc3.c 项目: 0x36/MCSC2014
int main()
{
	char *addr;
	int fd,ret;
	char buf[20]={0};
	char sc[128]={0};
	scmp_filter_ctx ctx;

	
	ctx  = seccomp_init(SCMP_ACT_KILL);
	if (!ctx) {
		perror("seccomp_init");
		return -1;
	}
	ret = seccomp_rule_add(ctx,SCMP_ACT_ALLOW,SCMP_SYS(write),0);
	if(ret) {
		perror("add rule");
		return -1;
	}

	ret = seccomp_rule_add(ctx,SCMP_ACT_ALLOW,SCMP_SYS(access),0);
	if(ret) {
		perror("add rule");
		return -1;
	}
	
	fd = open("./.passwd",O_RDONLY);
	if(fd == -1) {
		perror("open");
		return -1;
	}
	read(fd,buf,20);
	
	addr = mmap(0,4096,PROT_READ|PROT_WRITE,MAP_SHARED |MAP_ANONYMOUS,-1,0);
	if (addr == (char*)-1) {
		perror("mmap");
		return -1;
	}
	
	memset(addr,0,4096);
	memcpy(addr,"MCSC",4);
	memcpy(addr+4,"2014",4);
	memcpy(&addr[8],buf,20);
	
	printf("put you shellcode here : ");
	fflush(stdout);
	
	ssize_t rc = read(0,sc,128);
	sc[rc-1]=0;
	seccomp_load(ctx);
	
	((void (*)(void))sc)();
	
	
	return 0;
}
int main(int argc, char *argv[])
{
	int rc;
	struct util_options opts;
	scmp_filter_ctx ctx = NULL;

	rc = util_getopt(argc, argv, &opts);
	if (rc < 0)
		goto out;

	ctx = seccomp_init(SCMP_ACT_KILL);
	if (ctx == NULL)
		return ENOMEM;

	rc = seccomp_arch_remove(ctx, SCMP_ARCH_NATIVE);
	if (rc != 0)
		goto out;

	rc = seccomp_arch_add(ctx, SCMP_ARCH_X86);
	if (rc != 0)
		goto out;
	rc = seccomp_arch_add(ctx, SCMP_ARCH_X86_64);
	if (rc != 0)
		goto out;
	rc = seccomp_arch_add(ctx, SCMP_ARCH_X32);
	if (rc != 0)
		goto out;

	rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socket), 0);
	if (rc != 0)
		goto out;

	rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(connect), 0);
	if (rc != 0)
		goto out;

	rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(accept), 0);
	if (rc != 0)
		goto out;

	rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(accept4), 0);
	if (rc != 0)
		goto out;

	rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(shutdown), 0);
	if (rc != 0)
		goto out;

	rc = util_filter_output(&opts, ctx);
	if (rc)
		goto out;

out:
	seccomp_release(ctx);
	return (rc < 0 ? -rc : rc);
}
int main(int argc, char *argv[])
{
	int rc;
	scmp_filter_ctx ctx = NULL;

	rc = util_action_parse(argv[1]);
	if (rc != SCMP_ACT_ALLOW) {
		rc = 1;
		goto out;
	}

	rc = util_trap_install();
	if (rc != 0)
		goto out;

	ctx = seccomp_init(SCMP_ACT_TRAP);
	if (ctx == NULL)
		return ENOMEM;

	rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(open), 0);
	if (rc != 0)
		goto out;
	rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(openat), 0);
	if (rc != 0)
		goto out;
	rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(write), 0);
	if (rc != 0)
		goto out;
	rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(close), 0);
	if (rc != 0)
		goto out;
	rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(rt_sigreturn), 0);
	if (rc != 0)
		goto out;
	rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(exit_group), 0);
	if (rc != 0)
		goto out;

	rc = seccomp_load(ctx);
	if (rc != 0)
		goto out;

	rc = util_file_write("/dev/null");
	if (rc != 0)
		goto out;

	rc = 160;

out:
	seccomp_release(ctx);
	return (rc < 0 ? -rc : rc);
}
示例#11
0
static void
setup_seccomp() {
	scmp_filter_ctx ctx;
	unsigned int i;
	int ret;

	/* Make sure the lists are in sync */
	INSIST((sizeof(scmp_syscalls) / sizeof(int)) ==
	       (sizeof(scmp_syscall_names) / sizeof(const char *)));

	ctx = seccomp_init(SCMP_ACT_KILL);
	if (ctx == NULL) {
		isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
			      NS_LOGMODULE_MAIN, ISC_LOG_WARNING,
			      "libseccomp activation failed");
		return;
	}

	for (i = 0 ; i < sizeof(scmp_syscalls)/sizeof(*(scmp_syscalls)); i++) {
		ret = seccomp_rule_add(ctx, SCMP_ACT_ALLOW,
				       scmp_syscalls[i], 0);
		if (ret < 0)
			isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
				      NS_LOGMODULE_MAIN, ISC_LOG_WARNING,
				      "libseccomp rule failed: %s",
				      scmp_syscall_names[i]);

		else
			isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
				      NS_LOGMODULE_MAIN, ISC_LOG_DEBUG(9),
				      "added libseccomp rule: %s",
				      scmp_syscall_names[i]);
	}

	ret = seccomp_load(ctx);
	if (ret < 0) {
		isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
			      NS_LOGMODULE_MAIN, ISC_LOG_WARNING,
			      "libseccomp unable to load filter");
	} else {
		isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
			      NS_LOGMODULE_MAIN, ISC_LOG_NOTICE,
			      "libseccomp sandboxing active");
	}

	/*
	 * Release filter in ctx. Filters already loaded are not
	 * affected.
	 */
	seccomp_release(ctx);
}
示例#12
0
static
void init_seccomp_addconn(uint32_t def_action)
{
	scmp_filter_ctx ctx = seccomp_init(def_action);
	int rc = 0;

	if (ctx == NULL) {
			printf("seccomp_init_addconn() failed!");
			exit(EXIT_SECCOMP_FAIL);
	}

	rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(access), 0);
	rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(arch_prctl), 0);
	rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(brk), 0);
	rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(close), 0);
	rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(connect), 0);
	rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(exit_group), 0);
	rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(fcntl), 0);
	rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(fstat), 0);
	rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(getrlimit), 0);
	rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(ioctl), 0);
	rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mmap), 0);
	rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mprotect), 0);
	rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(open), 0);
	rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(prctl), 0);
	rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(read), 0);
	rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(readlink), 0);
	rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(rt_sigaction), 0);
	rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(rt_sigprocmask), 0);
	rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(set_robust_list), 0);
	rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(set_tid_address), 0);
	rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socket), 0);
	rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socketpair), 0);
	rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(statfs), 0);
	rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(write), 0);

	if (rc != 0) {
		printf("seccomp_rule_add() failed!");
		seccomp_release(ctx);
		exit(EXIT_SECCOMP_FAIL);
	}

	rc = seccomp_load(ctx);
	if (rc < 0) {
		printf("seccomp_load() failed!");
		seccomp_release(ctx);
		exit(EXIT_SECCOMP_FAIL);
	}

}
示例#13
0
文件: mooa.c 项目: seanlynch/mooa
static void install_seccomp_filter(const char *syscalls[]) {
  scmp_filter_ctx ctx = seccomp_init(SCMP_ACT_TRAP);
  if (!ctx) {
    errx(EXIT_FAILURE, "Failed to init seccomp");
  }

  for (int i = 0; ; i++) {
    const char *syscall = syscalls[i];
    if (!syscall) break;
    check(seccomp_rule_add(ctx, SCMP_ACT_ALLOW, get_syscall_nr(syscall), 0));
  }

  check(seccomp_load(ctx));
}
int main(int argc, char *argv[])
{
	int rc;
	struct util_options opts;
	scmp_filter_ctx ctx = NULL;

	rc = util_getopt(argc, argv, &opts);
	if (rc < 0)
		goto out;

	ctx = seccomp_init(SCMP_ACT_KILL);
	if (ctx == NULL)
		return ENOMEM;

	/* the syscall and argument numbers are all fake to make the test
	 * simpler */

	rc = seccomp_syscall_priority(ctx, 1000, 3);
	if (rc != 0)
		goto out;
	rc = seccomp_syscall_priority(ctx, 1001, 2);
	if (rc != 0)
		goto out;
	rc = seccomp_syscall_priority(ctx, 1002, 1);
	if (rc != 0)
		goto out;

	rc = seccomp_rule_add_exact(ctx, SCMP_ACT_ALLOW, 1000, 2,
				    SCMP_A0(SCMP_CMP_EQ, 0),
				    SCMP_A1(SCMP_CMP_EQ, 1));
	if (rc != 0)
		goto out;
	rc = seccomp_rule_add_exact(ctx, SCMP_ACT_ALLOW, 1001, 1,
				    SCMP_A0(SCMP_CMP_EQ, 0));
	if (rc != 0)
		goto out;
	rc = seccomp_rule_add_exact(ctx, SCMP_ACT_ALLOW, 1002, 0);
	if (rc != 0)
		goto out;

	rc = util_filter_output(&opts, ctx);
	if (rc)
		goto out;

out:
	seccomp_release(ctx);
	return (rc < 0 ? -rc : rc);
}
示例#15
0
文件: seccomp.c 项目: alphaKAI/poe
void
poe_init_seccomp(uint32_t act)
{
    scmp_filter_ctx ctx = seccomp_init(act);
    if (!ctx) ERROR("seccomp_init() failed");

    for (int i = 0; i < syscall_rules_count; i++) {
        struct syscall_rule rule = syscall_rules[i];
        if (seccomp_rule_add(ctx, rule.action, rule.syscall, 0) < 0) ERROR("seccomp_rule_add() failed");
    }

    int rc = seccomp_load(ctx);
    if (rc < 0) ERROR("seccomp_load() failed: %s", strerror(-rc));

    seccomp_release(ctx);
}
示例#16
0
void sandboxify() {
	if (seccomp_init(SCMP_ACT_TRAP) < 0)
		ERROR("Cannot go into SECCOMPv2");

	seccomp_rule_add(SCMP_ACT_ALLOW, SCMP_SYS(open), 0);
	seccomp_rule_add(SCMP_ACT_ALLOW, SCMP_SYS(openat), 0); // XXXX

	// seccomp_rule_add(SCMP_ACT_ERRNO(EPERM), SCMP_SYS(open), 0);
	seccomp_rule_add(SCMP_ACT_ERRNO(EPERM), SCMP_SYS(access), 0);
	seccomp_rule_add(SCMP_ACT_ERRNO(EPERM), SCMP_SYS(fcntl), 0); // XXXX
	seccomp_rule_add(SCMP_ACT_ERRNO(EPERM), SCMP_SYS(fstat), 0);
	seccomp_rule_add(SCMP_ACT_ERRNO(EPERM), SCMP_SYS(fstat64), 0);
	seccomp_rule_add(SCMP_ACT_ERRNO(EPERM), SCMP_SYS(stat64), 0);

	seccomp_rule_add(SCMP_ACT_ALLOW, SCMP_SYS(getdents), 0); // XXXX
	seccomp_rule_add(SCMP_ACT_ALLOW, SCMP_SYS(stat), 0); // XXXX
	seccomp_rule_add(SCMP_ACT_ALLOW, SCMP_SYS(dup), 0); // XXXX
	seccomp_rule_add(SCMP_ACT_ALLOW, SCMP_SYS(lseek), 0); // XXXX

	seccomp_rule_add(SCMP_ACT_ALLOW, SCMP_SYS(close), 0);
	seccomp_rule_add(SCMP_ACT_ALLOW, SCMP_SYS(read), 0);
	seccomp_rule_add(SCMP_ACT_ALLOW, SCMP_SYS(getdents64), 0);
	seccomp_rule_add(SCMP_ACT_ALLOW, SCMP_SYS(write), 0);
	// seccomp_rule_add(SCMP_ACT_ALLOW, SCMP_SYS(writev), 0); // XXX
	// seccomp_rule_add(SCMP_ACT_ALLOW, SCMP_SYS(mprotect), 0); // XXX
	// seccomp_rule_add(SCMP_ACT_ALLOW, SCMP_SYS(futex), 0); // XXX

	seccomp_rule_add(SCMP_ACT_ALLOW, SCMP_SYS(mmap2), 0);
	seccomp_rule_add(SCMP_ACT_ALLOW, SCMP_SYS(mmap), 0);
	seccomp_rule_add(SCMP_ACT_ALLOW, SCMP_SYS(munmap), 0);
	seccomp_rule_add(SCMP_ACT_ALLOW, SCMP_SYS(mremap), 0);

	seccomp_rule_add(SCMP_ACT_ALLOW, SCMP_SYS(brk), 0);
	seccomp_rule_add(SCMP_ACT_ALLOW, SCMP_SYS(gettimeofday), 0);
	seccomp_rule_add(SCMP_ACT_ALLOW, SCMP_SYS(time), 0);
	seccomp_rule_add(SCMP_ACT_ALLOW, SCMP_SYS(exit_group), 0);

#ifdef DEBUG_SECCOMP
	if (install_syscall_reporter())
		ERROR("Cannot install syscall reporter");
#endif

	if (seccomp_load() < 0)
		ERROR("Cannot load SECCOMP filters");

	seccomp_release();
}
示例#17
0
文件: seccomp.c 项目: Azendale/lxc
scmp_filter_ctx get_new_ctx(enum lxc_hostarch_t n_arch, uint32_t default_policy_action)
{
	scmp_filter_ctx ctx;
	int ret;
	uint32_t arch;

	switch(n_arch) {
	case lxc_seccomp_arch_i386: arch = SCMP_ARCH_X86; break;
	case lxc_seccomp_arch_amd64: arch = SCMP_ARCH_X86_64; break;
	case lxc_seccomp_arch_arm: arch = SCMP_ARCH_ARM; break;
#ifdef SCMP_ARCH_PPC64LE
	case lxc_seccomp_arch_ppc64le: arch = SCMP_ARCH_PPC64LE; break;
#endif
#ifdef SCMP_ARCH_PPC64
	case lxc_seccomp_arch_ppc64: arch = SCMP_ARCH_PPC64; break;
#endif
#ifdef SCMP_ARCH_PPC
	case lxc_seccomp_arch_ppc: arch = SCMP_ARCH_PPC; break;
#endif
	default: return NULL;
	}

	if ((ctx = seccomp_init(default_policy_action)) == NULL) {
		ERROR("Error initializing seccomp context");
		return NULL;
	}
	if (seccomp_attr_set(ctx, SCMP_FLTATR_CTL_NNP, 0)) {
		ERROR("failed to turn off n-new-privs");
		seccomp_release(ctx);
		return NULL;
	}
	ret = seccomp_arch_add(ctx, arch);
	if (ret != 0) {
		ERROR("Seccomp error %d (%s) adding arch: %d", ret,
				strerror(ret), (int)n_arch);
		seccomp_release(ctx);
		return NULL;
	}
	if (seccomp_arch_remove(ctx, SCMP_ARCH_NATIVE) != 0) {
		ERROR("Seccomp error removing native arch");
		seccomp_release(ctx);
		return NULL;
	}

	return ctx;
}
示例#18
0
文件: seccomp.c 项目: lizh06/ctags
int installSyscallFilter (void)
{
	// Use SCMP_ACT_TRAP to get a core dump.
	scmp_filter_ctx ctx = seccomp_init (SCMP_ACT_KILL);
	if (ctx == NULL)
	{
		return 1;
	}

	// Memory allocation.
	seccomp_rule_add (ctx, SCMP_ACT_ALLOW, SCMP_SYS (mmap), 0);
	seccomp_rule_add (ctx, SCMP_ACT_ALLOW, SCMP_SYS (munmap), 0);
	seccomp_rule_add (ctx, SCMP_ACT_ALLOW, SCMP_SYS (mremap), 0);
	seccomp_rule_add (ctx, SCMP_ACT_ALLOW, SCMP_SYS (brk), 0);

	// I/O
	seccomp_rule_add (ctx, SCMP_ACT_ALLOW, SCMP_SYS (read), 0);
	seccomp_rule_add (ctx, SCMP_ACT_ALLOW, SCMP_SYS (write), 0);

	// Clean exit
	seccomp_rule_add (ctx, SCMP_ACT_ALLOW, SCMP_SYS (exit), 0);
	seccomp_rule_add (ctx, SCMP_ACT_ALLOW, SCMP_SYS (exit_group), 0);

	// The bowels of stdio want to know the size of a file, even for stdout.
	seccomp_rule_add (ctx, SCMP_ACT_ALLOW, SCMP_SYS (fstat), 0);

	// seems unnecessary, but this comes from
	// main/parse.c:2764 : tagFilePosition (&tagfpos);
	seccomp_rule_add (ctx, SCMP_ACT_ALLOW, SCMP_SYS (lseek), 0);

	// libxml2 uses pthread_once, which in turn uses a futex
	seccomp_rule_add (ctx, SCMP_ACT_ALLOW, SCMP_SYS (futex), 0);

	verbose ("Entering sandbox\n");
	int err = seccomp_load (ctx);
	if (err < 0)
	{
		error (WARNING, "Failed to install syscall filter");
		/* Error handling is done in upper layer. */
	}

	seccomp_release (ctx);

	return err;
}
示例#19
0
文件: lockdown.cpp 项目: APTX/geordi
int main(int const argc, char * const * const argv)
{
	try
	{
		alarm(10);

		close(fileno(stdin));
		for (int fd = fileno(stderr); fd != 1024; ++fd) close(fd);
		dup2(fileno(stdout), fileno(stderr));

		limitResource(RLIMIT_CPU, 9, 11);
		limitResource(RLIMIT_AS, 512*1024*1024);
		limitResource(RLIMIT_DATA, 512*1024*1024);
		limitResource(RLIMIT_FSIZE, 10*1024*1024);
		limitResource(RLIMIT_LOCKS, 0);
		limitResource(RLIMIT_MEMLOCK, 0);
		limitResource(RLIMIT_NPROC, 16);

		if (argc < 2) e("params: program args");

		if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) != 0) e("prctl");

		scmp_filter_ctx const ctx = seccomp_init(SCMP_ACT_TRAP);

		if (!ctx) e("seccomp_init");

		if (seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(clone), 1,
			SCMP_CMP(0, SCMP_CMP_MASKED_EQ, CLONE_THREAD, CLONE_THREAD)) != 0)
			e("seccomp_rule_add");

		for (auto && p : rules)
			if (seccomp_rule_add(ctx, p.second, p.first, 0) != 0)
				e("seccomp_rule_add");

		if (seccomp_load(ctx) < 0) e("seccomp_load");

		execv(argv[1], argv + 1);
		e("execv");
	}
	catch (std::exception const & e)
	{
		std::cerr << "exception: " << e.what() << '\n';
		return 1;
	}
}
示例#20
0
文件: sandbox.c 项目: Archer-sys/tor
/**
 * Function responsible for setting up and enabling a global syscall filter.
 * The function is a prototype developed for stage 1 of sandboxing Tor.
 * Returns 0 on success.
 */
static int
install_syscall_filter(sandbox_cfg_t* cfg)
{
  int rc = 0;
  scmp_filter_ctx ctx;

  ctx = seccomp_init(SCMP_ACT_TRAP);
  if (ctx == NULL) {
    log_err(LD_BUG,"(Sandbox) failed to initialise libseccomp context");
    rc = -1;
    goto end;
  }

  // protectign sandbox parameter strings
  if ((rc = prot_strings(ctx, cfg))) {
    goto end;
  }

  // add parameter filters
  if ((rc = add_param_filter(ctx, cfg))) {
    log_err(LD_BUG, "(Sandbox) failed to add param filters!");
    goto end;
  }

  // adding filters with no parameters
  if ((rc = add_noparam_filter(ctx))) {
    log_err(LD_BUG, "(Sandbox) failed to add param filters!");
    goto end;
  }

  // loading the seccomp2 filter
  if ((rc = seccomp_load(ctx))) {
    log_err(LD_BUG, "(Sandbox) failed to load: %d (%s)!", rc,
            strerror(-rc));
    goto end;
  }

  // marking the sandbox as active
  sandbox_active = 1;

 end:
  seccomp_release(ctx);
  return (rc < 0 ? -rc : rc);
}
示例#21
0
int main(int argc, char *argv[])
{
	int rc;
	struct util_options opts;
	scmp_filter_ctx ctx = NULL;

	rc = util_getopt(argc, argv, &opts);
	if (rc < 0)
		goto out;

	ctx = seccomp_init(SCMP_ACT_KILL);
	if (ctx == NULL)
		return ENOMEM;

	rc = seccomp_rule_add_exact(ctx, SCMP_ACT_ALLOW, SCMP_SYS(read), 0);
	if (rc != 0)
		goto out;

	rc = seccomp_rule_add_exact(ctx, SCMP_ACT_ALLOW, SCMP_SYS(write), 0);
	if (rc != 0)
		goto out;

	rc = seccomp_rule_add_exact(ctx, SCMP_ACT_ALLOW, SCMP_SYS(close), 0);
	if (rc != 0)
		goto out;

	rc = seccomp_rule_add_exact(ctx,
				    SCMP_ACT_ALLOW, SCMP_SYS(rt_sigreturn), 0);
	if (rc != 0)
		goto out;

	rc = util_filter_output(&opts, ctx);
	if (rc)
		goto out;

out:
	seccomp_release(ctx);
	return (rc < 0 ? -rc : rc);
}
示例#22
0
int main() {
  printf("step 1: unrestricted\n");

  // ensure none of our children will ever be granted more priv
  // (via setuid, capabilities, ...)
  prctl(PR_SET_NO_NEW_PRIVS, 1);
  // ensure no escape is possible via ptrace
  prctl(PR_SET_DUMPABLE, 0);

  // Init the filter
  scmp_filter_ctx ctx;
  ctx = seccomp_init(SCMP_ACT_KILL); // default action: kill

  // setup basic whitelist
  seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(rt_sigreturn), 0);
  seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(exit), 0);
  seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(read), 0);
  seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(write), 0);
  
  // setup our rule
  seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(dup2), 2, 
                        SCMP_A0(SCMP_CMP_EQ, 1),
                        SCMP_A1(SCMP_CMP_EQ, 2));

  // build and load the filter
  seccomp_load(ctx);
  printf("step 2: only 'write' and dup2(1, 2) syscalls\n");
  
  // Redirect stderr to stdout
  dup2(1, 2);
  printf("step 3: stderr redirected to stdout\n");

  // Duplicate stderr to arbitrary fd
  dup2(2, 42);
  printf("step 4: !! YOU SHOULD NOT SEE ME !!\n");

  // Success (well, not so in this case...)
  return 0;
}
示例#23
0
int main(int argc, char *argv[])
{
	int rc;
	struct util_options opts;
	scmp_filter_ctx ctx = NULL;

	rc = util_getopt(argc, argv, &opts);
	if (rc < 0)
		goto out;

	ctx = seccomp_init(SCMP_ACT_ALLOW);
	if (ctx == NULL)
		return ENOMEM;

	rc = util_filter_output(&opts, ctx);
	if (rc)
		goto out;

out:
	seccomp_release(ctx);
	return (rc < 0 ? -rc : rc);
}
int main(int argc, char *argv[])
{
	int rc;
	struct util_options opts;
	scmp_filter_ctx ctx = NULL;

	rc = util_getopt(argc, argv, &opts);
	if (rc < 0)
		goto out;

	ctx = seccomp_init(SCMP_ACT_KILL);
	if (ctx == NULL)
		return ENOMEM;

	rc = seccomp_arch_remove(ctx, SCMP_ARCH_NATIVE);
	if (rc != 0)
		goto out;

	rc = seccomp_arch_add(ctx, SCMP_ARCH_X86);
	if (rc != 0)
		goto out;

	rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(tuxcall), 0);
	if (rc != 0)
		goto out;
	rc = seccomp_rule_add_exact(ctx, SCMP_ACT_ALLOW, SCMP_SYS(tuxcall), 0);
	if (rc != -EDOM)
		goto out;

	rc = util_filter_output(&opts, ctx);
	if (rc)
		goto out;

out:
	seccomp_release(ctx);
	return (rc < 0 ? -rc : rc);
}
示例#25
0
void drop_sys(int syscall) {
	scmp_filter_ctx ctx = seccomp_init(SCMP_ACT_ALLOW);
	if(seccomp_rule_add(ctx, SCMP_ACT_KILL, syscall, 0)) exit(-1);
	if(seccomp_load(ctx)) exit(-1);
	seccomp_release(ctx);
}
示例#26
0
文件: main.c 项目: skeggsb/envytools
int main(int argc, char *argv[])
{
	char *filename = read_opts(argc, argv);

	/* set up an rnn context */
	rnn_init();
	rnndb = rnn_newdb();
	rnn_parsefile(rnndb, "fifo/nv_objects.xml");
	if (rnndb->estatus)
		demmt_abort();
	rnn_prepdb(rnndb);
	domain = rnn_finddomain(rnndb, "SUBCHAN");
	if (!domain)
		demmt_abort();

	rnndb_g80_texture = rnn_newdb();
	rnn_parsefile(rnndb_g80_texture, "graph/g80_texture.xml");
	if (rnndb_g80_texture->estatus)
		demmt_abort();
	rnn_parsefile(rnndb_g80_texture, "graph/gm107_texture.xml");
	if (rnndb_g80_texture->estatus)
		demmt_abort();
	rnn_prepdb(rnndb_g80_texture);

	rnndb_gf100_shaders = rnn_newdb();
	rnn_parsefile(rnndb_gf100_shaders, "graph/gf100_shaders.xml");
	if (rnndb_gf100_shaders->estatus)
		demmt_abort();
	rnn_prepdb(rnndb_gf100_shaders);

	gf100_shaders_ctx = rnndec_newcontext(rnndb_gf100_shaders);
	gf100_shaders_ctx->colors = colors;
	/* doesn't matter which, just needs to exist to make it
	 * possible to modify later.
	 */
	rnndec_varadd(gf100_shaders_ctx, "GF100_SHADER_KIND", "FP");

	rnndb_nvrm_object = rnn_newdb();
	rnn_parsefile(rnndb_nvrm_object, "../docs/nvrm/rnndb/nvrm_object.xml");
	if (rnndb_nvrm_object->estatus)
		demmt_abort();
	rnn_prepdb(rnndb_nvrm_object);

	tic_domain = rnn_finddomain(rnndb_g80_texture, "TIC");
	tic2_domain = rnn_finddomain(rnndb_g80_texture, "TIC2");
	tsc_domain = rnn_finddomain(rnndb_g80_texture, "TSC");

	gf100_sp_header_domain = rnn_finddomain(rnndb_gf100_shaders, "GF100_SP_HEADER");
	gf100_fp_header_domain = rnn_finddomain(rnndb_gf100_shaders, "GF100_FP_HEADER");
	if (!gf100_sp_header_domain || !gf100_fp_header_domain)
		demmt_abort();

	gk104_cp_header_domain = rnn_finddomain(rnndb, "GK104_COMPUTE_LAUNCH_DESC");
	if (!gk104_cp_header_domain)
		demmt_abort();

	if (filename)
	{
		close(0);
		if (open_input(filename) == NULL)
		{
			perror("open");
			exit(1);
		}
		free(filename);
	}

	if (pager_enabled)
	{
		int pipe_fds[2];
		pid_t pid;

		if (pipe(pipe_fds) < 0)
		{
			perror("pipe");
			demmt_abort();
		}

		pid = fork();
		if (pid < 0)
		{
			perror("fork");
			demmt_abort();
		}

		if (pid > 0)
		{
			char *less_argv[] = { "less", "-ScR", NULL };

			close(pipe_fds[1]);
			dup2(pipe_fds[0], 0);
			close(pipe_fds[0]);
			execvp(less_argv[0], less_argv);

			perror("exec");
			demmt_abort();
		}

		close(pipe_fds[0]);
		dup2(pipe_fds[1], 1);
		dup2(pipe_fds[1], 2);
		close(pipe_fds[1]);
	}

#ifdef LIBSECCOMP_AVAILABLE
	if (seccomp_level)
	{
		int rc;
		scmp_filter_ctx ctx;
		if (seccomp_level == 2)
			ctx = seccomp_init(SCMP_ACT_KILL);
		else
			ctx = seccomp_init(SCMP_ACT_TRACE(1234));
		if (!ctx)
		{
			fprintf(stderr, "seccomp_init failed\n");
			exit(1);
		}

		rc = seccomp_rule_add_exact(ctx, SCMP_ACT_ALLOW, SCMP_SYS(read), 1,
				SCMP_A0(SCMP_CMP_EQ, 0));
		if (rc != 0)
			exit(1);
		seccomp_syscall_priority(ctx, SCMP_SYS(read), 254);

		rc = seccomp_rule_add_exact(ctx, SCMP_ACT_ALLOW, SCMP_SYS(write), 1,
				SCMP_A0(SCMP_CMP_LE, 2));
		if (rc != 0)
			exit(1);
		seccomp_syscall_priority(ctx, SCMP_SYS(write), 255);

		rc = seccomp_rule_add_exact(ctx, SCMP_ACT_ALLOW, SCMP_SYS(rt_sigreturn), 0);
		if (rc != 0)
			exit(1);

		rc = seccomp_rule_add_exact(ctx, SCMP_ACT_ALLOW, SCMP_SYS(fstat), 1,
				SCMP_A0(SCMP_CMP_EQ, 1));
		if (rc != 0)
			exit(1);

		rc = seccomp_rule_add_exact(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mmap), 0);
		if (rc != 0)
			exit(1);

		rc = seccomp_rule_add_exact(ctx, SCMP_ACT_ALLOW, SCMP_SYS(brk), 0);
		if (rc != 0)
			exit(1);

		rc = seccomp_rule_add_exact(ctx, SCMP_ACT_ALLOW, SCMP_SYS(munmap), 0);
		if (rc != 0)
			exit(1);

		rc = seccomp_rule_add_exact(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mremap), 0);
		if (rc != 0)
			exit(1);

		rc = seccomp_rule_add_exact(ctx, SCMP_ACT_ALLOW, SCMP_SYS(exit_group), 0);
		if (rc != 0)
			exit(1);

		rc = seccomp_rule_add_exact(ctx, SCMP_ACT_ALLOW, SCMP_SYS(ioctl), 2,
				SCMP_A0(SCMP_CMP_EQ, 1),
				SCMP_A1(SCMP_CMP_EQ, 0x5401/*TCGETS*/));
		if (rc != 0)
			exit(1);

		rc = seccomp_load(ctx);
		if (rc != 0)
		{
			fprintf(stderr, "seccomp_load failed with error: %d\n", rc);
			exit(1);
		}

		seccomp_release(ctx);
	}
#endif

	mmt_decode(&demmt_funcs.base, NULL);
	fflush(stdout);

	fini_macrodis();
	demmt_cleanup_isas();
	rnndec_freecontext(gf100_shaders_ctx);
	rnn_freedb(rnndb);
	rnn_freedb(rnndb_g80_texture);
	rnn_freedb(rnndb_gf100_shaders);
	rnn_freedb(rnndb_nvrm_object);
	rnn_fini();

	return 0;
}
int main(int argc, char *argv[])
{
  const char *argv0 = argv[0];
  int opt, optidx;

  bool separate_read_write = false;

  bool proxy = false;
  struct sockaddr_in proxy_sin;

  bool join = false;

#ifdef HAVE_SECCOMP
  int nrules = 0;
  uint32_t def_action = SCMP_ACT_ALLOW;
  char *fixed = (char *)mmap((void *)0x800000, 0x1000, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED, -1, 0);
#endif

  struct option longopts[] = {
    {"abstract"    , no_argument       , 0 , 'a'} ,
    {"directory"   , required_argument , 0 , 'd'} ,
    {"environment" , required_argument , 0 , 'e'} ,
    {"join"        , no_argument       , 0 , 'j'} ,
    {"policy"      , required_argument , 0 , 'o'} ,
    {"proxy"       , required_argument , 0 , 'p'} ,
    {"seccomp"     , required_argument , 0 , 'c'} ,
    {"separate"    , no_argument       , 0 , 's'} ,
    {0             , 0                 , 0 , 0}   ,
  };
  while ((opt = getopt_long(argc, argv, "+0ac:d:e:hjo:p:s", longopts, &optidx)) != -1) {
    switch (opt) {
    case 'a':
      af_unix = true;
      break;
    case 'c': {
#ifdef HAVE_SECCOMP
      char *pp = optarg, *p, *qq, *q, *saved0, *saved1;
      for (; ; pp = NULL) {
        p = strtok_r(pp, " \t,", &saved0);
        if (! p) break;

        bool negative = false;
        int num, pos, nfilters = 0;
        enum scmp_compare op;
        if (nrules >= SIZE(scmp_rules))
          errx(BAD_ARG, "too many rules");
        if (*p == '+')
          p++;
        else if (*p == '-')
          p++, negative = true;
        scmp_rules[nrules].action = negative ? SCMP_ACT_TRAP : SCMP_ACT_ALLOW;

        for (qq = p; ; qq = NULL) {
          q = strtok_r(qq, ":", &saved1);
          if (! q) break;
          if (qq) {
            num = seccomp_syscall_resolve_name(q);
            if (num < 0)
              errx(BAD_ARG, "unknown syscall \"%s\"", q);
            scmp_rules[nrules].syscall = num;
          } else {
            if (nfilters >= SIZE(scmp_rules[0].arg_array))
              errx(BAD_ARG, "too many filters");
            if (! ('0' <= *q && *q <= '5'))
              errx(BAD_ARG, "argument position should be 0-5");
            pos = *q-'0';
            REP(i, nfilters)
              if (pos == scmp_rules[nrules].arg_array[i].arg)
                errx(BAD_ARG, "duplicate argument position %d", pos);
            q++;
            if (*q == '=')
              q++, op = SCMP_CMP_EQ;
            else if (*q == '!' && q[1] == '=')
              q += 2, op = SCMP_CMP_NE;
            else if (*q == '<') {
              if (q[1] == '=')
                q += 2, op = SCMP_CMP_LE;
              else
                q++, op = SCMP_CMP_LT;
            } else if (*q == '>') {
              if (q[1] == '=')
                q += 2, op = SCMP_CMP_GE;
              else
                q++, op = SCMP_CMP_GT;
            }
            else
              errx(BAD_ARG, "unknown operator \"%c\"", *q);
            scmp_datum_t val = strtol(q, &q, 0);
            if (*q)
              errx(BAD_ARG, "invalid number");
            scmp_rules[nrules].arg_array[nfilters++] = SCMP_CMP(pos, op, val);
          }
        }
        scmp_rules[nrules].arg_cnt = nfilters;
        nrules++;
      }
#else
      errx(ERR_SYSCALL, "HAVE_SECCOMP not enabled");
#endif
      break;
    }
    case 'd':
      Chdir(optarg);
      break;
    case 'h':
      show_help(STDOUT_FILENO, argv0);
      break;
    case 'j':
      join = true;
      break;
    case 'e':
      putenv(optarg);
      break;
    case 'o':
#ifdef HAVE_SECCOMP
      if (optarg[0] == 'k')
        def_action = SCMP_ACT_KILL;
      else if (optarg[0] == 't')
        def_action = SCMP_ACT_TRAP;
      else if (optarg[0] == 'a')
        def_action = SCMP_ACT_ALLOW;
#else
      errx(ERR_SYSCALL, "HAVE_SECCOMP not enabled");
#endif
      break;
    case 'p': // proxy
      {
        char *p = strchr(optarg, ':');
        if (! p)
          errx(BAD_ARG, "no semicolon");
        *p = '\0';
        proxy_sin.sin_family = AF_INET;
        if (inet_aton(optarg, &proxy_sin.sin_addr) < 0)
          errx(BAD_ARG, "gethostbyname: %s", strerror(errno));
        proxy_sin.sin_port = htons(strtol(p+1, &p, 10));
        if (*p)
          errx(BAD_ARG, "port");
        proxy = true;
      }
      break;
    case 's':
      separate_read_write = true;
      break;
    default:
      show_help(STDERR_FILENO, argv0);
      break;
    }
  }

  argc -= optind;
  argv += optind;

  if (argc < 1) {
    show_help(STDERR_FILENO, argv0);
    return BAD_ARG;
  }

  char buf[4096];
  int pipe_p2c[2], pipe_c2p1[2], pipe_c2p2[2];
  if (af_unix) {
    unix_p2c.sun_family = AF_UNIX; 
    unix_c2p1.sun_family = AF_UNIX;
    unix_c2p2.sun_family = AF_UNIX;
    unix_p2c.sun_path[0] = '\0';
    unix_c2p1.sun_path[0] = '\0';
    unix_c2p2.sun_path[0] = '\0';
    sprintf(unix_p2c.sun_path+1, "/tmp/unix/%d-%d.in", getuid(), getpid());
    sprintf(unix_c2p1.sun_path+1, "/tmp/unix/%d-%d.out", getuid(), getpid());
    sprintf(unix_c2p2.sun_path+1, "/tmp/unix/%d-%d.err", getuid(), getpid());
    pipe_p2c[0] = socket(AF_UNIX, SOCK_STREAM, 0);
    pipe_c2p1[1] = socket(AF_UNIX, SOCK_STREAM, 0);
    if (! join)
      pipe_c2p2[1] = socket(AF_UNIX, SOCK_STREAM, 0);
    atexit(atexit_rm);
    if (bind(pipe_p2c[0], &unix_p2c, sizeof unix_p2c) < 0 ||
        bind(pipe_c2p1[1], &unix_c2p1, sizeof unix_c2p1) < 0)
      return perror(""), 0;
    if (! join && bind(pipe_c2p2[1], &unix_c2p2, sizeof unix_c2p2) < 0)
      return perror(""), 0;
    if (listen(pipe_p2c[0], 1) < 0 ||
        listen(pipe_c2p1[1], 1) < 0)
      return perror(""), 0;
    if (! join && listen(pipe_c2p2[1], 1) < 0)
      return perror(""), 0;
  } else {
    Pipe(pipe_p2c);
    Pipe(pipe_c2p1);
    if (! join)
      Pipe(pipe_c2p2);
  }

  child = Fork();
  if (! child) {
    // child
    if (af_unix) {
      // close bound sockets
      close(pipe_p2c[0]);
      close(pipe_c2p1[1]);
      close(pipe_c2p2[1]);

      // domain sockets for client
      pipe_p2c[1] = socket(AF_UNIX, SOCK_STREAM, 0);
      pipe_c2p1[0] = socket(AF_UNIX, SOCK_STREAM, 0);
      if (! join)
        pipe_c2p2[0] = socket(AF_UNIX, SOCK_STREAM, 0);

      if (connect(pipe_p2c[1], &unix_p2c, sizeof unix_p2c) < 0 ||
          connect(pipe_c2p1[0], &unix_c2p1, sizeof unix_c2p1) < 0)
        return 0;
      dup2(pipe_p2c[1], STDIN_FILENO); close(pipe_p2c[1]);
      dup2(pipe_c2p1[0], STDOUT_FILENO); close(pipe_c2p1[0]);
      if (join)
        dup2(STDOUT_FILENO, STDERR_FILENO);
      else {
        connect(pipe_c2p2[0], &unix_c2p2, sizeof unix_c2p2);
        dup2(pipe_c2p2[0], STDERR_FILENO); close(pipe_c2p2[0]);
      }
    } else {
      close(pipe_p2c[1]); dup2(pipe_p2c[0], STDIN_FILENO); close(pipe_p2c[0]);
      close(pipe_c2p1[0]); dup2(pipe_c2p1[1], STDOUT_FILENO); close(pipe_c2p1[1]);
      if (join)
        dup2(STDOUT_FILENO, STDERR_FILENO);
      else {
        close(pipe_c2p2[0]); dup2(pipe_c2p2[1], STDERR_FILENO); close(pipe_c2p2[1]);
      }
    }

#ifdef HAVE_SECCOMP
    scmp_filter_ctx ctx = seccomp_init(def_action);
    if (ctx == NULL)
      return 1;
    REP(i, nrules) {
      int ret = seccomp_rule_add_array(ctx, scmp_rules[i].action, scmp_rules[i].syscall,
                                       scmp_rules[i].arg_cnt, scmp_rules[i].arg_array);
      if (ret < 0)
        return 1;
    }
    if (seccomp_load(ctx) < 0)
      return 1;
    seccomp_release(ctx);

    strcpy(fixed, *argv);
    execv(fixed, argv); // execve will change the first argument
#else
    execvp(*argv, argv);
#endif
  } else {
示例#28
0
int
ntpdmain(
	int argc,
	char *argv[]
	)
{
	l_fp		now;
	struct recvbuf *rbuf;
	const char *	logfilename;
# ifdef HAVE_UMASK
	mode_t		uv;
# endif
# if defined(HAVE_GETUID) && !defined(MPE) /* MPE lacks the concept of root */
	uid_t		uid;
# endif
# if defined(HAVE_WORKING_FORK)
	long		wait_sync = 0;
	int		pipe_fds[2];
	int		rc;
	int		exit_code;
#  ifdef _AIX
	struct sigaction sa;
#  endif
#  if !defined(HAVE_SETSID) && !defined (HAVE_SETPGID) && defined(TIOCNOTTY)
	int		fid;
#  endif
# endif	/* HAVE_WORKING_FORK*/
# ifdef SCO5_CLOCK
	int		fd;
	int		zero;
# endif

# ifdef NEED_PTHREAD_WARMUP
	my_pthread_warmup();
# endif
	
# ifdef HAVE_UMASK
	uv = umask(0);
	if (uv)
		umask(uv);
	else
		umask(022);
# endif
	saved_argc = argc;
	saved_argv = argv;
	progname = argv[0];
	initializing = TRUE;		/* mark that we are initializing */
	parse_cmdline_opts(&argc, &argv);
# ifdef DEBUG
	debug = OPT_VALUE_SET_DEBUG_LEVEL;
#  ifdef HAVE_SETLINEBUF
	setlinebuf(stdout);
#  endif
# endif

	if (HAVE_OPT(NOFORK) || HAVE_OPT(QUIT)
# ifdef DEBUG
	    || debug
# endif
	    || HAVE_OPT(SAVECONFIGQUIT))
		nofork = TRUE;

	init_logging(progname, NLOG_SYNCMASK, TRUE);
	/* honor -l/--logfile option to log to a file */
	if (HAVE_OPT(LOGFILE)) {
		logfilename = OPT_ARG(LOGFILE);
		syslogit = FALSE;
		change_logfile(logfilename, FALSE);
	} else {
		logfilename = NULL;
		if (nofork)
			msyslog_term = TRUE;
		if (HAVE_OPT(SAVECONFIGQUIT))
			syslogit = FALSE;
	}
	msyslog(LOG_NOTICE, "%s: Starting", Version);

	{
		int i;
		char buf[1024];	/* Secret knowledge of msyslog buf length */
		char *cp = buf;

		/* Note that every arg has an initial space character */
		snprintf(cp, sizeof(buf), "Command line:");
		cp += strlen(cp);

		for (i = 0; i < saved_argc ; ++i) {
			snprintf(cp, sizeof(buf) - (cp - buf),
				" %s", saved_argv[i]);
			cp += strlen(cp);
		}
		msyslog(LOG_INFO, "%s", buf);
	}

	/*
	 * Install trap handlers to log errors and assertion failures.
	 * Default handlers print to stderr which doesn't work if detached.
	 */
	isc_assertion_setcallback(assertion_failed);
	isc_error_setfatal(library_fatal_error);
	isc_error_setunexpected(library_unexpected_error);

	/* MPE lacks the concept of root */
# if defined(HAVE_GETUID) && !defined(MPE)
	uid = getuid();
	if (uid && !HAVE_OPT( SAVECONFIGQUIT )) {
		msyslog_term = TRUE;
		msyslog(LOG_ERR,
			"must be run as root, not uid %ld", (long)uid);
		exit(1);
	}
# endif

/*
 * Enable the Multi-Media Timer for Windows?
 */
# ifdef SYS_WINNT
	if (HAVE_OPT( MODIFYMMTIMER ))
		set_mm_timer(MM_TIMER_HIRES);
# endif

#ifdef HAVE_DNSREGISTRATION
/*
 * Enable mDNS registrations?
 */
	if (HAVE_OPT( MDNS )) {
		mdnsreg = TRUE;
	}
#endif  /* HAVE_DNSREGISTRATION */

	if (HAVE_OPT( NOVIRTUALIPS ))
		listen_to_virtual_ips = 0;

	/*
	 * --interface, listen on specified interfaces
	 */
	if (HAVE_OPT( INTERFACE )) {
		int		ifacect = STACKCT_OPT( INTERFACE );
		const char**	ifaces  = STACKLST_OPT( INTERFACE );
		sockaddr_u	addr;

		while (ifacect-- > 0) {
			add_nic_rule(
				is_ip_address(*ifaces, AF_UNSPEC, &addr)
					? MATCH_IFADDR
					: MATCH_IFNAME,
				*ifaces, -1, ACTION_LISTEN);
			ifaces++;
		}
	}

	if (HAVE_OPT( NICE ))
		priority_done = 0;

# ifdef HAVE_SCHED_SETSCHEDULER
	if (HAVE_OPT( PRIORITY )) {
		config_priority = OPT_VALUE_PRIORITY;
		config_priority_override = 1;
		priority_done = 0;
	}
# endif

# ifdef HAVE_WORKING_FORK
	/* make sure the FDs are initialised */
	pipe_fds[0] = -1;
	pipe_fds[1] = -1;
	do {					/* 'loop' once */
		if (!HAVE_OPT( WAIT_SYNC ))
			break;
		wait_sync = OPT_VALUE_WAIT_SYNC;
		if (wait_sync <= 0) {
			wait_sync = 0;
			break;
		}
		/* -w requires a fork() even with debug > 0 */
		nofork = FALSE;
		if (pipe(pipe_fds)) {
			exit_code = (errno) ? errno : -1;
			msyslog(LOG_ERR,
				"Pipe creation failed for --wait-sync: %m");
			exit(exit_code);
		}
		waitsync_fd_to_close = pipe_fds[1];
	} while (0);				/* 'loop' once */
# endif	/* HAVE_WORKING_FORK */

	init_lib();
# ifdef SYS_WINNT
	/*
	 * Start interpolation thread, must occur before first
	 * get_systime()
	 */
	init_winnt_time();
# endif
	/*
	 * Initialize random generator and public key pair
	 */
	get_systime(&now);

	ntp_srandom((int)(now.l_i * now.l_uf));

	/*
	 * Detach us from the terminal.  May need an #ifndef GIZMO.
	 */
	if (!nofork) {

# ifdef HAVE_WORKING_FORK
		rc = fork();
		if (-1 == rc) {
			exit_code = (errno) ? errno : -1;
			msyslog(LOG_ERR, "fork: %m");
			exit(exit_code);
		}
		if (rc > 0) {	
			/* parent */
			exit_code = wait_child_sync_if(pipe_fds[0],
						       wait_sync);
			exit(exit_code);
		}
		
		/*
		 * child/daemon 
		 * close all open files excepting waitsync_fd_to_close.
		 * msyslog() unreliable until after init_logging().
		 */
		closelog();
		if (syslog_file != NULL) {
			fclose(syslog_file);
			syslog_file = NULL;
			syslogit = TRUE;
		}
		close_all_except(waitsync_fd_to_close);
		INSIST(0 == open("/dev/null", 0) && 1 == dup2(0, 1) \
			&& 2 == dup2(0, 2));

		init_logging(progname, 0, TRUE);
		/* we lost our logfile (if any) daemonizing */
		setup_logfile(logfilename);

#  ifdef SYS_DOMAINOS
		{
			uid_$t puid;
			status_$t st;

			proc2_$who_am_i(&puid);
			proc2_$make_server(&puid, &st);
		}
#  endif	/* SYS_DOMAINOS */
#  ifdef HAVE_SETSID
		if (setsid() == (pid_t)-1)
			msyslog(LOG_ERR, "setsid(): %m");
#  elif defined(HAVE_SETPGID)
		if (setpgid(0, 0) == -1)
			msyslog(LOG_ERR, "setpgid(): %m");
#  else		/* !HAVE_SETSID && !HAVE_SETPGID follows */
#   ifdef TIOCNOTTY
		fid = open("/dev/tty", 2);
		if (fid >= 0) {
			ioctl(fid, (u_long)TIOCNOTTY, NULL);
			close(fid);
		}
#   endif	/* TIOCNOTTY */
		ntp_setpgrp(0, getpid());
#  endif	/* !HAVE_SETSID && !HAVE_SETPGID */
#  ifdef _AIX
		/* Don't get killed by low-on-memory signal. */
		sa.sa_handler = catch_danger;
		sigemptyset(&sa.sa_mask);
		sa.sa_flags = SA_RESTART;
		sigaction(SIGDANGER, &sa, NULL);
#  endif	/* _AIX */
# endif		/* HAVE_WORKING_FORK */
	}

# ifdef SCO5_CLOCK
	/*
	 * SCO OpenServer's system clock offers much more precise timekeeping
	 * on the base CPU than the other CPUs (for multiprocessor systems),
	 * so we must lock to the base CPU.
	 */
	fd = open("/dev/at1", O_RDONLY);		
	if (fd >= 0) {
		zero = 0;
		if (ioctl(fd, ACPU_LOCK, &zero) < 0)
			msyslog(LOG_ERR, "cannot lock to base CPU: %m");
		close(fd);
	}
# endif

	/* Setup stack size in preparation for locking pages in memory. */
# if defined(HAVE_MLOCKALL)
#  ifdef HAVE_SETRLIMIT
	ntp_rlimit(RLIMIT_STACK, DFLT_RLIMIT_STACK * 4096, 4096, "4k");
#   ifdef RLIMIT_MEMLOCK
	/*
	 * The default RLIMIT_MEMLOCK is very low on Linux systems.
	 * Unless we increase this limit malloc calls are likely to
	 * fail if we drop root privilege.  To be useful the value
	 * has to be larger than the largest ntpd resident set size.
	 */
	ntp_rlimit(RLIMIT_MEMLOCK, DFLT_RLIMIT_MEMLOCK * 1024 * 1024, 1024 * 1024, "MB");
#   endif	/* RLIMIT_MEMLOCK */
#  endif	/* HAVE_SETRLIMIT */
# else	/* !HAVE_MLOCKALL follows */
#  ifdef HAVE_PLOCK
#   ifdef PROCLOCK
#    ifdef _AIX
	/*
	 * set the stack limit for AIX for plock().
	 * see get_aix_stack() for more info.
	 */
	if (ulimit(SET_STACKLIM, (get_aix_stack() - 8 * 4096)) < 0)
		msyslog(LOG_ERR,
			"Cannot adjust stack limit for plock: %m");
#    endif	/* _AIX */
#   endif	/* PROCLOCK */
#  endif	/* HAVE_PLOCK */
# endif	/* !HAVE_MLOCKALL */

	/*
	 * Set up signals we pay attention to locally.
	 */
# ifdef SIGDIE1
	signal_no_reset(SIGDIE1, finish);
	signal_no_reset(SIGDIE2, finish);
	signal_no_reset(SIGDIE3, finish);
	signal_no_reset(SIGDIE4, finish);
# endif
# ifdef SIGBUS
	signal_no_reset(SIGBUS, finish);
# endif

# if !defined(SYS_WINNT) && !defined(VMS)
#  ifdef DEBUG
	(void) signal_no_reset(MOREDEBUGSIG, moredebug);
	(void) signal_no_reset(LESSDEBUGSIG, lessdebug);
#  else
	(void) signal_no_reset(MOREDEBUGSIG, no_debug);
	(void) signal_no_reset(LESSDEBUGSIG, no_debug);
#  endif	/* DEBUG */
# endif	/* !SYS_WINNT && !VMS */

	/*
	 * Set up signals we should never pay attention to.
	 */
# ifdef SIGPIPE
	signal_no_reset(SIGPIPE, SIG_IGN);
# endif

	/*
	 * Call the init_ routines to initialize the data structures.
	 *
	 * Exactly what command-line options are we expecting here?
	 */
	INIT_SSL();
	init_auth();
	init_util();
	init_restrict();
	init_mon();
	init_timer();
	init_request();
	init_control();
	init_peer();
# ifdef REFCLOCK
	init_refclock();
# endif
	set_process_priority();
	init_proto();		/* Call at high priority */
	init_io();
	init_loopfilter();
	mon_start(MON_ON);	/* monitor on by default now	  */
				/* turn off in config if unwanted */

	/*
	 * Get the configuration.  This is done in a separate module
	 * since this will definitely be different for the gizmo board.
	 */
	getconfig(argc, argv);

	if (-1 == cur_memlock) {
# if defined(HAVE_MLOCKALL)
		/*
		 * lock the process into memory
		 */
		if (   !HAVE_OPT(SAVECONFIGQUIT)
#  ifdef RLIMIT_MEMLOCK
		    && -1 != DFLT_RLIMIT_MEMLOCK
#  endif
		    && 0 != mlockall(MCL_CURRENT|MCL_FUTURE))
			msyslog(LOG_ERR, "mlockall(): %m");
# else	/* !HAVE_MLOCKALL follows */
#  ifdef HAVE_PLOCK
#   ifdef PROCLOCK
		/*
		 * lock the process into memory
		 */
		if (!HAVE_OPT(SAVECONFIGQUIT) && 0 != plock(PROCLOCK))
			msyslog(LOG_ERR, "plock(PROCLOCK): %m");
#   else	/* !PROCLOCK follows  */
#    ifdef TXTLOCK
		/*
		 * Lock text into ram
		 */
		if (!HAVE_OPT(SAVECONFIGQUIT) && 0 != plock(TXTLOCK))
			msyslog(LOG_ERR, "plock(TXTLOCK) error: %m");
#    else	/* !TXTLOCK follows */
		msyslog(LOG_ERR, "plock() - don't know what to lock!");
#    endif	/* !TXTLOCK */
#   endif	/* !PROCLOCK */
#  endif	/* HAVE_PLOCK */
# endif	/* !HAVE_MLOCKALL */
	}

	loop_config(LOOP_DRIFTINIT, 0);
	report_event(EVNT_SYSRESTART, NULL, NULL);
	initializing = FALSE;

# ifdef HAVE_DROPROOT
	if (droproot) {
		/* Drop super-user privileges and chroot now if the OS supports this */

#  ifdef HAVE_LINUX_CAPABILITIES
		/* set flag: keep privileges accross setuid() call (we only really need cap_sys_time): */
		if (prctl( PR_SET_KEEPCAPS, 1L, 0L, 0L, 0L ) == -1) {
			msyslog( LOG_ERR, "prctl( PR_SET_KEEPCAPS, 1L ) failed: %m" );
			exit(-1);
		}
#  elif HAVE_SOLARIS_PRIVS
		/* Nothing to do here */
#  else
		/* we need a user to switch to */
		if (user == NULL) {
			msyslog(LOG_ERR, "Need user name to drop root privileges (see -u flag!)" );
			exit(-1);
		}
#  endif	/* HAVE_LINUX_CAPABILITIES || HAVE_SOLARIS_PRIVS */

		if (user != NULL) {
			if (isdigit((unsigned char)*user)) {
				sw_uid = (uid_t)strtoul(user, &endp, 0);
				if (*endp != '\0')
					goto getuser;

				if ((pw = getpwuid(sw_uid)) != NULL) {
					free(user);
					user = estrdup(pw->pw_name);
					sw_gid = pw->pw_gid;
				} else {
					errno = 0;
					msyslog(LOG_ERR, "Cannot find user ID %s", user);
					exit (-1);
				}

			} else {
getuser:
				errno = 0;
				if ((pw = getpwnam(user)) != NULL) {
					sw_uid = pw->pw_uid;
					sw_gid = pw->pw_gid;
				} else {
					if (errno)
						msyslog(LOG_ERR, "getpwnam(%s) failed: %m", user);
					else
						msyslog(LOG_ERR, "Cannot find user `%s'", user);
					exit (-1);
				}
			}
		}
		if (group != NULL) {
			if (isdigit((unsigned char)*group)) {
				sw_gid = (gid_t)strtoul(group, &endp, 0);
				if (*endp != '\0')
					goto getgroup;
			} else {
getgroup:
				if ((gr = getgrnam(group)) != NULL) {
					sw_gid = gr->gr_gid;
				} else {
					errno = 0;
					msyslog(LOG_ERR, "Cannot find group `%s'", group);
					exit (-1);
				}
			}
		}

		if (chrootdir ) {
			/* make sure cwd is inside the jail: */
			if (chdir(chrootdir)) {
				msyslog(LOG_ERR, "Cannot chdir() to `%s': %m", chrootdir);
				exit (-1);
			}
			if (chroot(chrootdir)) {
				msyslog(LOG_ERR, "Cannot chroot() to `%s': %m", chrootdir);
				exit (-1);
			}
			if (chdir("/")) {
				msyslog(LOG_ERR, "Cannot chdir() to`root after chroot(): %m");
				exit (-1);
			}
		}
#  ifdef HAVE_SOLARIS_PRIVS
		if ((lowprivs = priv_str_to_set(LOWPRIVS, ",", NULL)) == NULL) {
			msyslog(LOG_ERR, "priv_str_to_set() failed:%m");
			exit(-1);
		}
		if ((highprivs = priv_allocset()) == NULL) {
			msyslog(LOG_ERR, "priv_allocset() failed:%m");
			exit(-1);
		}
		(void) getppriv(PRIV_PERMITTED, highprivs);
		(void) priv_intersect(highprivs, lowprivs);
		if (setppriv(PRIV_SET, PRIV_PERMITTED, lowprivs) == -1) {
			msyslog(LOG_ERR, "setppriv() failed:%m");
			exit(-1);
		}
#  endif /* HAVE_SOLARIS_PRIVS */
		if (user && initgroups(user, sw_gid)) {
			msyslog(LOG_ERR, "Cannot initgroups() to user `%s': %m", user);
			exit (-1);
		}
		if (group && setgid(sw_gid)) {
			msyslog(LOG_ERR, "Cannot setgid() to group `%s': %m", group);
			exit (-1);
		}
		if (group && setegid(sw_gid)) {
			msyslog(LOG_ERR, "Cannot setegid() to group `%s': %m", group);
			exit (-1);
		}
		if (group) {
			if (0 != setgroups(1, &sw_gid)) {
				msyslog(LOG_ERR, "setgroups(1, %d) failed: %m", sw_gid);
				exit (-1);
			}
		}
		else if (pw)
			if (0 != initgroups(pw->pw_name, pw->pw_gid)) {
				msyslog(LOG_ERR, "initgroups(<%s>, %d) filed: %m", pw->pw_name, pw->pw_gid);
				exit (-1);
			}
		if (user && setuid(sw_uid)) {
			msyslog(LOG_ERR, "Cannot setuid() to user `%s': %m", user);
			exit (-1);
		}
		if (user && seteuid(sw_uid)) {
			msyslog(LOG_ERR, "Cannot seteuid() to user `%s': %m", user);
			exit (-1);
		}

#  if !defined(HAVE_LINUX_CAPABILITIES) && !defined(HAVE_SOLARIS_PRIVS)
		/*
		 * for now assume that the privilege to bind to privileged ports
		 * is associated with running with uid 0 - should be refined on
		 * ports that allow binding to NTP_PORT with uid != 0
		 */
		disable_dynamic_updates |= (sw_uid != 0);  /* also notifies routing message listener */
#  endif /* !HAVE_LINUX_CAPABILITIES && !HAVE_SOLARIS_PRIVS */

		if (disable_dynamic_updates && interface_interval) {
			interface_interval = 0;
			msyslog(LOG_INFO, "running as non-root disables dynamic interface tracking");
		}

#  ifdef HAVE_LINUX_CAPABILITIES
		{
			/*
			 *  We may be running under non-root uid now, but we still hold full root privileges!
			 *  We drop all of them, except for the crucial one or two: cap_sys_time and
			 *  cap_net_bind_service if doing dynamic interface tracking.
			 */
			cap_t caps;
			char *captext;
			
			captext = (0 != interface_interval)
				      ? "cap_sys_time,cap_net_bind_service=pe"
				      : "cap_sys_time=pe";
			caps = cap_from_text(captext);
			if (!caps) {
				msyslog(LOG_ERR,
					"cap_from_text(%s) failed: %m",
					captext);
				exit(-1);
			}
			if (-1 == cap_set_proc(caps)) {
				msyslog(LOG_ERR,
					"cap_set_proc() failed to drop root privs: %m");
				exit(-1);
			}
			cap_free(caps);
		}
#  endif	/* HAVE_LINUX_CAPABILITIES */
#  ifdef HAVE_SOLARIS_PRIVS
		if (priv_delset(lowprivs, "proc_setid") == -1) {
			msyslog(LOG_ERR, "priv_delset() failed:%m");
			exit(-1);
		}
		if (setppriv(PRIV_SET, PRIV_PERMITTED, lowprivs) == -1) {
			msyslog(LOG_ERR, "setppriv() failed:%m");
			exit(-1);
		}
		priv_freeset(lowprivs);
		priv_freeset(highprivs);
#  endif /* HAVE_SOLARIS_PRIVS */
		root_dropped = TRUE;
		fork_deferred_worker();
	}	/* if (droproot) */
# endif	/* HAVE_DROPROOT */

/* libssecomp sandboxing */
#if defined (LIBSECCOMP) && (KERN_SECCOMP)
	scmp_filter_ctx ctx;

	if ((ctx = seccomp_init(SCMP_ACT_KILL)) < 0)
		msyslog(LOG_ERR, "%s: seccomp_init(SCMP_ACT_KILL) failed: %m", __func__);
	else {
		msyslog(LOG_DEBUG, "%s: seccomp_init(SCMP_ACT_KILL) succeeded", __func__);
	}

#ifdef __x86_64__
int scmp_sc[] = {
	SCMP_SYS(adjtimex),
	SCMP_SYS(bind),
	SCMP_SYS(brk),
	SCMP_SYS(chdir),
	SCMP_SYS(clock_gettime),
	SCMP_SYS(clock_settime),
	SCMP_SYS(close),
	SCMP_SYS(connect),
	SCMP_SYS(exit_group),
	SCMP_SYS(fstat),
	SCMP_SYS(fsync),
	SCMP_SYS(futex),
	SCMP_SYS(getitimer),
	SCMP_SYS(getsockname),
	SCMP_SYS(ioctl),
	SCMP_SYS(lseek),
	SCMP_SYS(madvise),
	SCMP_SYS(mmap),
	SCMP_SYS(munmap),
	SCMP_SYS(open),
	SCMP_SYS(poll),
	SCMP_SYS(read),
	SCMP_SYS(recvmsg),
	SCMP_SYS(rename),
	SCMP_SYS(rt_sigaction),
	SCMP_SYS(rt_sigprocmask),
	SCMP_SYS(rt_sigreturn),
	SCMP_SYS(select),
	SCMP_SYS(sendto),
	SCMP_SYS(setitimer),
	SCMP_SYS(setsid),
	SCMP_SYS(socket),
	SCMP_SYS(stat),
	SCMP_SYS(time),
	SCMP_SYS(write),
};
#endif
#ifdef __i386__
int scmp_sc[] = {
	SCMP_SYS(_newselect),
	SCMP_SYS(adjtimex),
	SCMP_SYS(brk),
	SCMP_SYS(chdir),
	SCMP_SYS(clock_gettime),
	SCMP_SYS(clock_settime),
	SCMP_SYS(close),
	SCMP_SYS(exit_group),
	SCMP_SYS(fsync),
	SCMP_SYS(futex),
	SCMP_SYS(getitimer),
	SCMP_SYS(madvise),
	SCMP_SYS(mmap),
	SCMP_SYS(mmap2),
	SCMP_SYS(munmap),
	SCMP_SYS(open),
	SCMP_SYS(poll),
	SCMP_SYS(read),
	SCMP_SYS(rename),
	SCMP_SYS(rt_sigaction),
	SCMP_SYS(rt_sigprocmask),
	SCMP_SYS(select),
	SCMP_SYS(setitimer),
	SCMP_SYS(setsid),
	SCMP_SYS(sigprocmask),
	SCMP_SYS(sigreturn),
	SCMP_SYS(socketcall),
	SCMP_SYS(stat64),
	SCMP_SYS(time),
	SCMP_SYS(write),
};
#endif
	{
		int i;

		for (i = 0; i < COUNTOF(scmp_sc); i++) {
			if (seccomp_rule_add(ctx,
			    SCMP_ACT_ALLOW, scmp_sc[i], 0) < 0) {
				msyslog(LOG_ERR,
				    "%s: seccomp_rule_add() failed: %m",
				    __func__);
			}
		}
	}

	if (seccomp_load(ctx) < 0)
		msyslog(LOG_ERR, "%s: seccomp_load() failed: %m",
		    __func__);	
	else {
		msyslog(LOG_DEBUG, "%s: seccomp_load() succeeded", __func__);
	}
#endif /* LIBSECCOMP and KERN_SECCOMP */

# ifdef HAVE_IO_COMPLETION_PORT

	for (;;) {
		GetReceivedBuffers();
# else /* normal I/O */

	BLOCK_IO_AND_ALARM();
	was_alarmed = FALSE;

	for (;;) {
		if (alarm_flag) {	/* alarmed? */
			was_alarmed = TRUE;
			alarm_flag = FALSE;
		}

		if (!was_alarmed && !has_full_recv_buffer()) {
			/*
			 * Nothing to do.  Wait for something.
			 */
			io_handler();
		}

		if (alarm_flag) {	/* alarmed? */
			was_alarmed = TRUE;
			alarm_flag = FALSE;
		}

		if (was_alarmed) {
			UNBLOCK_IO_AND_ALARM();
			/*
			 * Out here, signals are unblocked.  Call timer routine
			 * to process expiry.
			 */
			timer();
			was_alarmed = FALSE;
			BLOCK_IO_AND_ALARM();
		}

# endif		/* !HAVE_IO_COMPLETION_PORT */

# ifdef DEBUG_TIMING
		{
			l_fp pts;
			l_fp tsa, tsb;
			int bufcount = 0;

			get_systime(&pts);
			tsa = pts;
# endif
			rbuf = get_full_recv_buffer();
			while (rbuf != NULL) {
				if (alarm_flag) {
					was_alarmed = TRUE;
					alarm_flag = FALSE;
				}
				UNBLOCK_IO_AND_ALARM();

				if (was_alarmed) {
					/* avoid timer starvation during lengthy I/O handling */
					timer();
					was_alarmed = FALSE;
				}

				/*
				 * Call the data procedure to handle each received
				 * packet.
				 */
				if (rbuf->receiver != NULL) {
# ifdef DEBUG_TIMING
					l_fp dts = pts;

					L_SUB(&dts, &rbuf->recv_time);
					DPRINTF(2, ("processing timestamp delta %s (with prec. fuzz)\n", lfptoa(&dts, 9)));
					collect_timing(rbuf, "buffer processing delay", 1, &dts);
					bufcount++;
# endif
					(*rbuf->receiver)(rbuf);
				} else {
					msyslog(LOG_ERR, "fatal: receive buffer callback NULL");
					abort();
				}

				BLOCK_IO_AND_ALARM();
				freerecvbuf(rbuf);
				rbuf = get_full_recv_buffer();
			}
# ifdef DEBUG_TIMING
			get_systime(&tsb);
			L_SUB(&tsb, &tsa);
			if (bufcount) {
				collect_timing(NULL, "processing", bufcount, &tsb);
				DPRINTF(2, ("processing time for %d buffers %s\n", bufcount, lfptoa(&tsb, 9)));
			}
		}
# endif

		/*
		 * Go around again
		 */

# ifdef HAVE_DNSREGISTRATION
		if (mdnsreg && (current_time - mdnsreg ) > 60 && mdnstries && sys_leap != LEAP_NOTINSYNC) {
			mdnsreg = current_time;
			msyslog(LOG_INFO, "Attempting to register mDNS");
			if ( DNSServiceRegister (&mdns, 0, 0, NULL, "_ntp._udp", NULL, NULL, 
			    htons(NTP_PORT), 0, NULL, NULL, NULL) != kDNSServiceErr_NoError ) {
				if (!--mdnstries) {
					msyslog(LOG_ERR, "Unable to register mDNS, giving up.");
				} else {	
					msyslog(LOG_INFO, "Unable to register mDNS, will try later.");
				}
			} else {
				msyslog(LOG_INFO, "mDNS service registered.");
				mdnsreg = FALSE;
			}
		}
# endif /* HAVE_DNSREGISTRATION */

	}
	UNBLOCK_IO_AND_ALARM();
	return 1;
}
#endif	/* !SIM */


#if !defined(SIM) && defined(SIGDIE1)
/*
 * finish - exit gracefully
 */
static RETSIGTYPE
finish(
	int sig
	)
{
	const char *sig_desc;

	sig_desc = NULL;
#ifdef HAVE_STRSIGNAL
	sig_desc = strsignal(sig);
#endif
	if (sig_desc == NULL)
		sig_desc = "";
	msyslog(LOG_NOTICE, "%s exiting on signal %d (%s)", progname,
		sig, sig_desc);
	/* See Bug 2513 and Bug 2522 re the unlink of PIDFILE */
# ifdef HAVE_DNSREGISTRATION
	if (mdns != NULL)
		DNSServiceRefDeallocate(mdns);
# endif
	peer_cleanup();
	exit(0);
}
#endif	/* !SIM && SIGDIE1 */


#ifndef SIM
/*
 * wait_child_sync_if - implements parent side of -w/--wait-sync
 */
# ifdef HAVE_WORKING_FORK
static int
wait_child_sync_if(
	int	pipe_read_fd,
	long	wait_sync
	)
{
	int	rc;
	int	exit_code;
	time_t	wait_end_time;
	time_t	cur_time;
	time_t	wait_rem;
	fd_set	readset;
	struct timeval wtimeout;

	if (0 == wait_sync) 
		return 0;

	/* waitsync_fd_to_close used solely by child */
	close(waitsync_fd_to_close);
	wait_end_time = time(NULL) + wait_sync;
	do {
		cur_time = time(NULL);
		wait_rem = (wait_end_time > cur_time)
				? (wait_end_time - cur_time)
				: 0;
		wtimeout.tv_sec = wait_rem;
		wtimeout.tv_usec = 0;
		FD_ZERO(&readset);
		FD_SET(pipe_read_fd, &readset);
		rc = select(pipe_read_fd + 1, &readset, NULL, NULL,
			    &wtimeout);
		if (-1 == rc) {
			if (EINTR == errno)
				continue;
			exit_code = (errno) ? errno : -1;
			msyslog(LOG_ERR,
				"--wait-sync select failed: %m");
			return exit_code;
		}
		if (0 == rc) {
			/*
			 * select() indicated a timeout, but in case
			 * its timeouts are affected by a step of the
			 * system clock, select() again with a zero 
			 * timeout to confirm.
			 */
			FD_ZERO(&readset);
			FD_SET(pipe_read_fd, &readset);
			wtimeout.tv_sec = 0;
			wtimeout.tv_usec = 0;
			rc = select(pipe_read_fd + 1, &readset, NULL,
				    NULL, &wtimeout);
			if (0 == rc)	/* select() timeout */
				break;
			else		/* readable */
				return 0;
		} else			/* readable */
			return 0;
	} while (wait_rem > 0);

	fprintf(stderr, "%s: -w/--wait-sync %ld timed out.\n",
		progname, wait_sync);
	return ETIMEDOUT;
}
示例#29
0
int main(int argc, char **argv) {
    prevent_leaked_file_descriptors();

    bool mount_proc = false;
    bool mount_dev = false;
    const char *username = "******";
    const char *hostname = "playpen";
    long timeout = 0;
    long memory_limit = 128;
    struct bind_list *binds = NULL, *binds_tail = NULL;
    char *devices = NULL;
    char *syscalls = NULL;
    const char *syscalls_file = NULL;
    const char *learn_name = NULL;

    static const struct option opts[] = {
        { "help",          no_argument,       0, 'h' },
        { "version",       no_argument,       0, 'v' },
        { "mount-proc",    no_argument,       0, 'p' },
        { "mount-dev",     no_argument,       0, 0x100 },
        { "bind",          required_argument, 0, 'b' },
        { "bind-rw",       required_argument, 0, 'B' },
        { "user",          required_argument, 0, 'u' },
        { "hostname",      required_argument, 0, 'n' },
        { "timeout",       required_argument, 0, 't' },
        { "memory-limit",  required_argument, 0, 'm' },
        { "devices",       required_argument, 0, 'd' },
        { "syscalls",      required_argument, 0, 's' },
        { "syscalls-file", required_argument, 0, 'S' },
        { "learn",         required_argument, 0, 'l' },
        { 0, 0, 0, 0 }
    };

    for (;;) {
        int opt = getopt_long(argc, argv, "hvpb:B:u:n:t:m:d:s:S:l:", opts, NULL);
        if (opt == -1)
            break;

        switch (opt) {
        case 'h':
            usage(stdout);
        case 'v':
            printf("%s %s\n", program_invocation_short_name, VERSION);
            return 0;
        case 'p':
            mount_proc = true;
            break;
        case 0x100:
            mount_dev = true;
            break;
        case 'b':
        case 'B':
            if (binds) {
                binds_tail->next = bind_list_alloc(optarg, opt == 'b');
                binds_tail = binds_tail->next;
            } else {
                binds = binds_tail = bind_list_alloc(optarg, opt == 'b');
            }
            break;
        case 'u':
            username = optarg;
            break;
        case 'n':
            hostname = optarg;
            break;
        case 't':
            timeout = strtolx_positive(optarg, "timeout");
            break;
        case 'm':
            memory_limit = strtolx_positive(optarg, "memory limit");
            break;
        case 'd':
            devices = optarg;
            break;
        case 's':
            syscalls = optarg;
            break;
        case 'S':
            syscalls_file = optarg;
            break;
        case 'l':
            learn_name = optarg;
            break;
        default:
            usage(stderr);
        }
    }

    if (argc - optind < 2) {
        usage(stderr);
    }

    const char *root = argv[optind];
    optind++;

    scmp_filter_ctx ctx = seccomp_init(learn_name ? SCMP_ACT_TRACE(0) : SCMP_ACT_KILL);
    if (!ctx) errx(EXIT_FAILURE, "seccomp_init");

    if (syscalls_file) {
        char name[SYSCALL_NAME_MAX];
        FILE *file = fopen(syscalls_file, "r");
        if (!file) err(EXIT_FAILURE, "failed to open syscalls file: %s", syscalls_file);
        while (fgets(name, sizeof name, file)) {
            char *pos;
            if ((pos = strchr(name, '\n'))) *pos = '\0';
            check(seccomp_rule_add(ctx, SCMP_ACT_ALLOW, get_syscall_nr(name), 0));
        }
        fclose(file);
    }

    check(seccomp_rule_add(ctx, SCMP_ACT_ALLOW, __NR_execve, 0));

    if (syscalls) {
        for (char *s_ptr = syscalls, *saveptr; ; s_ptr = NULL) {
            const char *syscall = strtok_r(s_ptr, ",", &saveptr);
            if (!syscall) break;
            check(seccomp_rule_add(ctx, SCMP_ACT_ALLOW, get_syscall_nr(syscall), 0));
        }
    }

    int epoll_fd = epoll_create1(EPOLL_CLOEXEC);
    check_posix(epoll_fd, "epoll_create1");

    sigset_t mask;
    sigemptyset(&mask);
    sigaddset(&mask, SIGCHLD);
    sigaddset(&mask, SIGHUP);
    sigaddset(&mask, SIGINT);
    sigaddset(&mask, SIGTERM);

    check_posix(sigprocmask(SIG_BLOCK, &mask, NULL), "sigprocmask");

    int sig_fd = signalfd(-1, &mask, SFD_CLOEXEC);
    check_posix(sig_fd, "signalfd");

    epoll_add(epoll_fd, sig_fd, EPOLLIN);

    int pipe_in[2];
    int pipe_out[2];
    int pipe_err[2];
    check_posix(pipe(pipe_in), "pipe");
    check_posix(pipe(pipe_out), "pipe");
    set_non_blocking(pipe_out[0]);
    check_posix(pipe(pipe_err), "pipe");
    set_non_blocking(pipe_err[0]);

    int rc = epoll_ctl(epoll_fd, EPOLL_CTL_ADD, STDIN_FILENO,
                       &(struct epoll_event){ .data.fd = STDIN_FILENO, .events = EPOLLIN });
示例#30
0
文件: runner.c 项目: QingdaoU/Judger
int child_process(void *clone_args){
    FILE *log_fp = ((struct clone_args *)clone_args)->log_fp;
    struct config *config = ((struct clone_args *)clone_args)->config;
    FILE *in_file = NULL, *out_file = NULL, *err_file = NULL;
    struct rlimit memory_limit, cpu_time_rlimit;
    gid_t group_list[] = {config->gid};
#ifndef __APPLE__
    int i;
    int syscalls_whitelist[] = {SCMP_SYS(read), SCMP_SYS(fstat),
                                SCMP_SYS(mmap), SCMP_SYS(mprotect), 
                                SCMP_SYS(munmap), SCMP_SYS(open), 
                                SCMP_SYS(arch_prctl), SCMP_SYS(brk), 
                                SCMP_SYS(access), SCMP_SYS(exit_group), 
                                SCMP_SYS(close)};
    int syscalls_whitelist_length = sizeof(syscalls_whitelist) / sizeof(int);
    scmp_filter_ctx ctx = NULL;
#endif
    // child process
    // On success, these system calls return 0.
    // On error, -1 is returned, and errno is set appropriately.
    if (config->max_memory != MEMORY_UNLIMITED) {
        memory_limit.rlim_cur = memory_limit.rlim_max = (rlim_t) (config->max_memory) * 2;
        if (setrlimit(RLIMIT_AS, &memory_limit) == -1) {
            LOG_FATAL(log_fp, "setrlimit memory failed, errno: %d", errno);
            ERROR(log_fp, SETRLIMIT_FAILED);
        }
    }
    if (config->max_cpu_time != CPU_TIME_UNLIMITED) {
        // cpu time
        if (set_timer(config->max_cpu_time / 1000, config->max_cpu_time % 1000, 1) != SUCCESS) {
            LOG_FATAL(log_fp, "set cpu time timer failed");
            ERROR(log_fp, SETITIMER_FAILED);
        }
        // real time
        if (set_timer(config->max_real_time / 1000, config->max_real_time % 1000, 0) != SUCCESS) {
            LOG_FATAL(log_fp, "set real time timer failed");
            ERROR(log_fp, SETITIMER_FAILED);
        }

        // child process can not inherit timeout rules from parent process defined by setitimer, so we use setrlimit to
        // control child process max running time
        cpu_time_rlimit.rlim_cur = cpu_time_rlimit.rlim_max = (config->max_cpu_time + 1000) / 1000;
        if (setrlimit(RLIMIT_CPU, &cpu_time_rlimit) == -1) {
            LOG_FATAL(log_fp, "setrlimit cpu time failed, errno: %d", errno);
            ERROR(log_fp, SETRLIMIT_FAILED);
        }
    }

    // read stdin from in file
    // On success, these system calls return the new descriptor. 
    // On error, -1 is returned, and errno is set appropriately.
    if (config->in_file != NULL) {
        if ((in_file = fopen(config->in_file, "r")) == NULL) {
            LOG_FATAL(log_fp, "failed to open stdin redirect file");
            ERROR(log_fp, DUP2_FAILED);
        }
        if (dup2(fileno(in_file), fileno(stdin)) == -1) {
            LOG_FATAL(log_fp, "dup2 stdin failed, errno: %d", errno);
            ERROR(log_fp, DUP2_FAILED);
        }
    }
    // write stdout to out file
    if (config->out_file != NULL) {
        if ((out_file = fopen(config->out_file, "w")) == NULL) {
            LOG_FATAL(log_fp, "failed to open stdout redirect file");
            ERROR(log_fp, DUP2_FAILED);
        }
        if (dup2(fileno(out_file), fileno(stdout)) == -1) {
            LOG_FATAL(log_fp, "dup2 stdout failed, errno: %d", errno);
            ERROR(log_fp, DUP2_FAILED);
        }
    }
    // write stderr to err file
    if (config->err_file != NULL) {
        // if err_file and out_file are the same path, we use out_file pointer as err_file pointer, to avoid conflict
        if (strcmp(config->out_file, config->err_file) == 0) {
            err_file = out_file;
        }
        else {
            if ((err_file = fopen(config->err_file, "w")) == NULL) {
                LOG_FATAL(log_fp, "failed to open stderr redirect file");
                ERROR(log_fp, DUP2_FAILED);
            }
        }
        if (dup2(fileno(err_file), fileno(stderr)) == -1) {
            LOG_FATAL(log_fp, "dup2 stdout failed, errno: %d", errno);
            ERROR(log_fp, DUP2_FAILED);
        }
    }
    if (config->gid != -1 && (setgid(config->gid) == -1 || setgroups(sizeof(group_list) / sizeof(gid_t), group_list) == -1)) {
        LOG_FATAL(log_fp, "setgid failed, errno: %d", errno);
        ERROR(log_fp, SET_GID_FAILED);
    }
    if (config->uid != -1 && setuid(config->uid) == -1) {
        LOG_FATAL(log_fp, "setuid failed, errno: %d", errno);
        ERROR(log_fp, SET_UID_FAILED);
    }
#ifndef __APPLE__
    if (config->use_sandbox != 0) {
        // load seccomp rules
        ctx = seccomp_init(SCMP_ACT_KILL);
        if (!ctx) {
            LOG_FATAL(log_fp, "init seccomp failed");
            ERROR(log_fp, LOAD_SECCOMP_FAILED);
        }
        for (i = 0; i < syscalls_whitelist_length; i++) {
            if (seccomp_rule_add(ctx, SCMP_ACT_ALLOW, syscalls_whitelist[i], 0) != 0) {
                LOG_FATAL(log_fp, "load syscall white list failed");
                ERROR(log_fp, LOAD_SECCOMP_FAILED);
            }
        }
        // add extra rule for execve
        if (seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(execve), 1, SCMP_A0(SCMP_CMP_EQ, (scmp_datum_t)(config->path))) != 0) {
            LOG_FATAL(log_fp, "load execve rule failed");
            ERROR(log_fp, LOAD_SECCOMP_FAILED);
        }
        // only fd 0 1 2 are allowed
        if (seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(write), 1, SCMP_A0(SCMP_CMP_LE, 2)) != 0) {
            LOG_FATAL(log_fp, "load dup2 rule failed");
            ERROR(log_fp, LOAD_SECCOMP_FAILED);
        }
        if (seccomp_load(ctx) != 0) {
            LOG_FATAL(log_fp, "seccomp load failed");
            ERROR(log_fp, LOAD_SECCOMP_FAILED);
        }
        seccomp_release(ctx);
    }
#endif
    execve(config->path, config->args, config->env);
    LOG_FATAL(log_fp, "execve failed, errno: %d", errno);
    ERROR(log_fp, EXCEVE_FAILED);
    return 1;
}