Example #1
0
int main(int argc, char *argv[])
{
	char *name = NULL;

	if (seccomp_syscall_resolve_name("open") != __NR_open)
		goto fail;
	if (seccomp_syscall_resolve_name("socket") != __NR_socket)
		goto fail;
	if (seccomp_syscall_resolve_name("INVALID") != __NR_SCMP_ERROR)
		goto fail;

	if (seccomp_syscall_resolve_name_arch(SCMP_ARCH_NATIVE,
					      "open") != __NR_open)
		goto fail;
	if (seccomp_syscall_resolve_name_arch(SCMP_ARCH_NATIVE,
					      "socket") != __NR_socket)
		goto fail;
	if (seccomp_syscall_resolve_name_arch(SCMP_ARCH_NATIVE,
					      "INVALID") != __NR_SCMP_ERROR)
		goto fail;

	name = seccomp_syscall_resolve_num_arch(SCMP_ARCH_NATIVE, __NR_open);
	if (name == NULL || strcmp(name, "open") != 0)
		goto fail;
	free(name);

	name = seccomp_syscall_resolve_num_arch(SCMP_ARCH_NATIVE, __NR_socket);
	if (name == NULL || strcmp(name, "socket") != 0)
		goto fail;
	free(name);

	name = seccomp_syscall_resolve_num_arch(SCMP_ARCH_NATIVE,
						__NR_SCMP_ERROR);
	if (name != NULL)
		goto fail;
	free(name);

	return 0;

fail:
	if (name != NULL)
		free(name);
	return 1;
}
Example #2
0
/*
 * v2 consists of
 * [x86]
 * open
 * read
 * write
 * close
 * # a comment
 * [x86_64]
 * open
 * read
 * write
 * close
 */
static int parse_config_v2(FILE *f, char *line, struct lxc_conf *conf)
{
	char *p;
	int ret;
	scmp_filter_ctx compat_ctx = NULL;
	bool blacklist = false;
	uint32_t default_policy_action = -1, default_rule_action = -1, action;
	enum lxc_hostarch_t native_arch = get_hostarch(),
			    cur_rule_arch = native_arch;

	if (strncmp(line, "blacklist", 9) == 0)
		blacklist = true;
	else if (strncmp(line, "whitelist", 9) != 0) {
		ERROR("Bad seccomp policy style: %s", line);
		return -1;
	}

	if ((p = strchr(line, ' '))) {
		default_policy_action = get_v2_default_action(p+1);
		if (default_policy_action == -2)
			return -1;
	}

	/* for blacklist, allow any syscall which has no rule */
	if (blacklist) {
		if (default_policy_action == -1)
			default_policy_action = SCMP_ACT_ALLOW;
		if (default_rule_action == -1)
			default_rule_action = SCMP_ACT_KILL;
	} else {
		if (default_policy_action == -1)
			default_policy_action = SCMP_ACT_KILL;
		if (default_rule_action == -1)
			default_rule_action = SCMP_ACT_ALLOW;
	}

	if (native_arch == lxc_seccomp_arch_amd64) {
		cur_rule_arch = lxc_seccomp_arch_all;
		compat_ctx = get_new_ctx(lxc_seccomp_arch_i386,
				default_policy_action);
		if (!compat_ctx)
			goto bad;
	}

	if (default_policy_action != SCMP_ACT_KILL) {
		ret = seccomp_reset(conf->seccomp_ctx, default_policy_action);
		if (ret != 0) {
			ERROR("Error re-initializing seccomp");
			return -1;
		}
		if (seccomp_attr_set(conf->seccomp_ctx, SCMP_FLTATR_CTL_NNP, 0)) {
			ERROR("failed to turn off n-new-privs");
			return -1;
		}
	}

	while (fgets(line, 1024, f)) {

		if (line[0] == '#')
			continue;
		if (strlen(line) == 0)
			continue;
		remove_trailing_newlines(line);
		INFO("processing: .%s.", line);
		if (line[0] == '[') {
			// read the architecture for next set of rules
			if (strcmp(line, "[x86]") == 0 ||
					strcmp(line, "[X86]") == 0) {
				if (native_arch != lxc_seccomp_arch_i386 &&
					native_arch != lxc_seccomp_arch_amd64) {
					cur_rule_arch = lxc_seccomp_arch_unknown;
					continue;
				}
				cur_rule_arch = lxc_seccomp_arch_i386;
				if (native_arch == lxc_seccomp_arch_amd64) {
					if (compat_ctx)
						continue;
					compat_ctx = get_new_ctx(lxc_seccomp_arch_i386,
							default_policy_action);
					if (!compat_ctx)
						goto bad;
				}
			} else if (strcmp(line, "[X86_64]") == 0 ||
					strcmp(line, "[x86_64]") == 0) {
				if (native_arch != lxc_seccomp_arch_amd64) {
					cur_rule_arch = lxc_seccomp_arch_unknown;
					continue;
				}
				cur_rule_arch = lxc_seccomp_arch_amd64;
			} else if (strcmp(line, "[all]") == 0 ||
					strcmp(line, "[ALL]") == 0) {
				cur_rule_arch = lxc_seccomp_arch_all;
				if (native_arch == lxc_seccomp_arch_amd64 && !compat_ctx) {
					if (compat_ctx)
						continue;
					compat_ctx = get_new_ctx(lxc_seccomp_arch_i386,
							default_policy_action);
					if (!compat_ctx)
						goto bad;
				}
			}
#ifdef SCMP_ARCH_ARM
			else if (strcmp(line, "[arm]") == 0 ||
					strcmp(line, "[ARM]") == 0) {
				if (native_arch != lxc_seccomp_arch_arm) {
					cur_rule_arch = lxc_seccomp_arch_unknown;
					continue;
				}
				cur_rule_arch = lxc_seccomp_arch_arm;
			}
#endif
#ifdef SCMP_ARCH_PPC64LE
			else if (strcmp(line, "[ppc64le]") == 0 ||
					strcmp(line, "[PPC64LE]") == 0) {
				if (native_arch != lxc_seccomp_arch_ppc64le) {
					cur_rule_arch = lxc_seccomp_arch_unknown;
					continue;
				}
				cur_rule_arch = lxc_seccomp_arch_ppc64le;
			}
#endif
#ifdef SCMP_ARCH_PPC64
			else if (strcmp(line, "[ppc64]") == 0 ||
					strcmp(line, "[PPC64]") == 0) {
				if (native_arch != lxc_seccomp_arch_ppc64) {
					cur_rule_arch = lxc_seccomp_arch_unknown;
					continue;
				}
				cur_rule_arch = lxc_seccomp_arch_ppc64;
			}
#endif
#ifdef SCMP_ARCH_PPC
			else if (strcmp(line, "[ppc]") == 0 ||
					strcmp(line, "[PPC]") == 0) {
				if (native_arch != lxc_seccomp_arch_ppc) {
					cur_rule_arch = lxc_seccomp_arch_unknown;
					continue;
				}
				cur_rule_arch = lxc_seccomp_arch_ppc;
			}
#endif
			else
				goto bad_arch;

			continue;
		}

		/* irrelevant arch - i.e. arm on i386 */
		if (cur_rule_arch == lxc_seccomp_arch_unknown)
			continue;

		/* read optional action which follows the syscall */
		action = get_and_clear_v2_action(line, default_rule_action);
		if (action == -1) {
			ERROR("Failed to interpret action");
			goto bad_rule;
		}

		/*
		 * TODO generalize - if !is_compat_only(native_arch, cur_rule_arch)
		 *
		 * in other words, the rule is 32-bit only, on 64-bit host;  don't run
		 * the rule against the native arch.
		 */
		if (!(cur_rule_arch == lxc_seccomp_arch_i386 &&
			native_arch == lxc_seccomp_arch_amd64)) {
			INFO("Adding non-compat rule for %s action %d", line, action);
			if (!do_resolve_add_rule(SCMP_ARCH_NATIVE, line, conf->seccomp_ctx, action))
				goto bad_rule;
		}

		/*
		 * TODO generalize - if need_compat(native_arch, cur_rule_arch)
		 */
		if (native_arch == lxc_seccomp_arch_amd64 &&
			cur_rule_arch != lxc_seccomp_arch_amd64) {
			int nr1, nr2;
			INFO("Adding compat rule for %s action %d", line, action);
			nr1 = seccomp_syscall_resolve_name_arch(SCMP_ARCH_X86, line);
			nr2 = seccomp_syscall_resolve_name_arch(SCMP_ARCH_NATIVE, line);
			if (nr1 == nr2) {
				/* If the syscall # is the same for 32- and 64-bit, then we cannot
				 * apply it to the compat_ctx.  So apply it to the noncompat ctx.
				 * We may already have done so, but that's ok
				 */
				INFO("Adding non-compat rule bc nr1 == nr2 (%d, %d)", nr1, nr2);
				if (!do_resolve_add_rule(SCMP_ARCH_NATIVE, line, conf->seccomp_ctx, action))
					goto bad_rule;
				continue;
			}
			INFO("Really adding compat rule bc nr1 == nr2 (%d, %d)", nr1, nr2);
			if (!do_resolve_add_rule(SCMP_ARCH_X86, line,
						compat_ctx, action))
				goto bad_rule;
		}
	}

	if (compat_ctx) {
		INFO("Merging in the compat seccomp ctx into the main one");
		if (seccomp_merge(conf->seccomp_ctx, compat_ctx) != 0) {
			ERROR("Error merging i386 seccomp contexts");
			goto bad;
		}
	}

	return 0;

bad_arch:
	ERROR("Unsupported arch: %s", line);
bad_rule:
bad:
	if (compat_ctx)
		seccomp_release(compat_ctx);
	return -1;
}
Example #3
0
File: seccomp.c Project: C24IO/lxc
/*
 * v2 consists of
 * [x86]
 * open
 * read
 * write
 * close
 * # a comment
 * [x86_64]
 * open
 * read
 * write
 * close
 */
static int parse_config_v2(FILE *f, char *line, struct lxc_conf *conf)
{
#if HAVE_DECL_SECCOMP_SYSCALL_RESOLVE_NAME_ARCH
	char *p;
	int ret;
	scmp_filter_ctx *ctx = NULL;
	bool blacklist = false;
	uint32_t default_policy_action = -1, default_rule_action = -1, action;
	uint32_t arch = SCMP_ARCH_NATIVE;

	if (strncmp(line, "blacklist", 9) == 0)
		blacklist = true;
	else if (strncmp(line, "whitelist", 9) != 0) {
		ERROR("Bad seccomp policy style: %s", line);
		return -1;
	}

	if ((p = strchr(line, ' '))) {
		default_policy_action = get_v2_default_action(p+1);
		if (default_policy_action == -2)
			return -1;
	}

	/* for blacklist, allow any syscall which has no rule */
	if (blacklist) {
		if (default_policy_action == -1)
			default_policy_action = SCMP_ACT_ALLOW;
		if (default_rule_action == -1)
			default_rule_action = SCMP_ACT_KILL;
	} else {
		if (default_policy_action == -1)
			default_policy_action = SCMP_ACT_KILL;
		if (default_rule_action == -1)
			default_rule_action = SCMP_ACT_ALLOW;
	}

	if (default_policy_action != SCMP_ACT_KILL) {
		ret = seccomp_reset(conf->seccomp_ctx, default_policy_action);
		if (ret != 0) {
			ERROR("Error re-initializing seccomp");
			return -1;
		}
		if (seccomp_attr_set(conf->seccomp_ctx, SCMP_FLTATR_CTL_NNP, 0)) {
			ERROR("failed to turn off n-new-privs");
			return -1;
		}
	}

	while (fgets(line, 1024, f)) {
		int nr;

		if (line[0] == '#')
			continue;
		if (strlen(line) == 0)
			continue;
		remove_trailing_newlines(line);
		INFO("processing: .%s.", line);
		if (line[0] == '[') {
			// read the architecture for next set of rules
			if (strcmp(line, "[x86]") == 0 ||
					strcmp(line, "[X86]") == 0)
				arch = SCMP_ARCH_X86;
			else if (strcmp(line, "[X86_64]") == 0 ||
					strcmp(line, "[x86_64]") == 0)
				arch = SCMP_ARCH_X86_64;
#ifdef SCMP_ARCH_ARM
			else if (strcmp(line, "[arm]") == 0 ||
					strcmp(line, "[ARM]") == 0)
				arch = SCMP_ARCH_ARM;
#endif
			else
				goto bad_arch;
			if (ctx) {
				ERROR("Only two arch sections per policy supported");
				goto bad_arch;
			}
			if ((ctx = seccomp_init(default_policy_action)) == NULL) {
				ERROR("Error initializing seccomp context");
				return -1;
			}
			if (seccomp_attr_set(ctx, SCMP_FLTATR_CTL_NNP, 0)) {
				ERROR("failed to turn off n-new-privs");
				seccomp_release(ctx);
				return -1;
			}
			ret = seccomp_arch_add(ctx, arch);
			if (ret == -EEXIST) {
				seccomp_release(ctx);
				ctx = NULL;
				continue;
			}
			if (ret != 0) {
				ERROR("Error %d adding arch: %s", ret, line);
				goto bad_arch;
			}
			if (seccomp_arch_remove(ctx, SCMP_ARCH_NATIVE) != 0) {
				ERROR("Error removing native arch from %s", line);
				goto bad_arch;
			}
			continue;
		}

		action = get_and_clear_v2_action(line, default_rule_action);
		if (action == -1) {
			ERROR("Failed to interpret action");
			goto bad_rule;
		}
		nr = seccomp_syscall_resolve_name_arch(arch, line);
		if (nr < 0) {
			ERROR("Failed to resolve syscall: %s", line);
			goto bad_rule;
		}
		ret = seccomp_rule_add(ctx ? ctx : conf->seccomp_ctx,
				action, nr, 0);
		if (ret < 0) {
			ERROR("failed (%d) loading rule for %s", ret, line);
			goto bad_rule;
		}
	}
	if (ctx) {
		if (seccomp_merge(conf->seccomp_ctx, ctx) != 0) {
			seccomp_release(ctx);
			ERROR("Error merging seccomp contexts");
			return -1;
		}
	}
	return 0;

bad_arch:
	ERROR("Unsupported arch: %s", line);
bad_rule:
	if (ctx)
		seccomp_release(ctx);
	return -1;
#else
	return -1;
#endif
}