[object][job] Fix bug where process creation bypasses ZX_POL_NEW_ANY This change fixes a bug where process creation would succeed even when the job policy prohibited it via ZX_POL_NEW_ANY. See ZX-3364 for details. Add test and static_asserts to reduce the likelihood of regression. Bug: ZX-3364 #done Test: "k ut job_policy" Change-Id: Ifcb22d3c341d1ebc1c8e37c264e5833305dacf59
diff --git a/kernel/object/job_policy.cpp b/kernel/object/job_policy.cpp index cc9d393..0c81d45 100644 --- a/kernel/object/job_policy.cpp +++ b/kernel/object/job_policy.cpp
@@ -6,6 +6,7 @@ #include <assert.h> #include <err.h> +#include <fbl/algorithm.h> #include <kernel/deadline.h> #include <zircon/syscalls/policy.h> @@ -63,8 +64,22 @@ // space of a single uint64_t so the 'union' trick works. static_assert(sizeof(Encoding) == sizeof(pol_cookie_t), "bitfield issue"); -// Make sure that adding new policies forces updating this file. -static_assert(ZX_POL_MAX == 13u, "please update PolicyManager AddPolicy and QueryBasicPolicy"); +// It is critical that this array contain all "new object" policies because it's used to implement +// ZX_NEW_ANY. +const uint32_t kNewObjectPolicies[]{ + ZX_POL_NEW_VMO, + ZX_POL_NEW_CHANNEL, + ZX_POL_NEW_EVENT, + ZX_POL_NEW_EVENTPAIR, + ZX_POL_NEW_PORT, + ZX_POL_NEW_SOCKET, + ZX_POL_NEW_FIFO, + ZX_POL_NEW_TIMER, + ZX_POL_NEW_PROCESS, +}; +static_assert( + fbl::count_of(kNewObjectPolicies) + 4 == ZX_POL_MAX, + "please update JobPolicy::AddPartial, JobPolicy::QueryBasicPolicy, and kNewObjectPolicies"); bool CanSetEntry(uint64_t existing, uint32_t new_action) { if (Encoding::is_default(existing)) @@ -184,8 +199,8 @@ if (in.condition == ZX_POL_NEW_ANY) { // loop over all ZX_POL_NEW_xxxx conditions. - for (uint32_t it = ZX_POL_NEW_VMO; it <= ZX_POL_NEW_TIMER; ++it) { - if ((res = AddPartial(mode, new_cookie, it, in.policy, &partials[it])) < 0) { + for (auto pol : kNewObjectPolicies) { + if ((res = AddPartial(mode, new_cookie, pol, in.policy, &partials[pol])) < 0) { return res; } }
diff --git a/kernel/object/job_policy_tests.cpp b/kernel/object/job_policy_tests.cpp index f2adfd7..896240e 100644 --- a/kernel/object/job_policy_tests.cpp +++ b/kernel/object/job_policy_tests.cpp
@@ -85,6 +85,25 @@ END_TEST; } +static bool add_basic_policy_deny_any() { + BEGIN_TEST; + + JobPolicy p; + zx_policy_basic_t policy{ZX_POL_NEW_ANY, ZX_POL_ACTION_DENY}; + ASSERT_EQ(ZX_OK, p.AddBasicPolicy(ZX_JOB_POL_ABSOLUTE, &policy, 1), ""); + ASSERT_EQ(ZX_POL_ACTION_DENY, p.QueryBasicPolicy(ZX_POL_NEW_VMO), ""); + ASSERT_EQ(ZX_POL_ACTION_DENY, p.QueryBasicPolicy(ZX_POL_NEW_CHANNEL), ""); + ASSERT_EQ(ZX_POL_ACTION_DENY, p.QueryBasicPolicy(ZX_POL_NEW_EVENT), ""); + ASSERT_EQ(ZX_POL_ACTION_DENY, p.QueryBasicPolicy(ZX_POL_NEW_EVENTPAIR), ""); + ASSERT_EQ(ZX_POL_ACTION_DENY, p.QueryBasicPolicy(ZX_POL_NEW_PORT), ""); + ASSERT_EQ(ZX_POL_ACTION_DENY, p.QueryBasicPolicy(ZX_POL_NEW_SOCKET), ""); + ASSERT_EQ(ZX_POL_ACTION_DENY, p.QueryBasicPolicy(ZX_POL_NEW_FIFO), ""); + ASSERT_EQ(ZX_POL_ACTION_DENY, p.QueryBasicPolicy(ZX_POL_NEW_TIMER), ""); + ASSERT_EQ(ZX_POL_ACTION_DENY, p.QueryBasicPolicy(ZX_POL_NEW_PROCESS), ""); + + END_TEST; +} + static bool set_get_timer_slack() { BEGIN_TEST; @@ -103,5 +122,6 @@ UNITTEST("add_basic_policy_absolute", add_basic_policy_absolute) UNITTEST("add_basic_policy_relative", add_basic_policy_relative) UNITTEST("add_basic_policy_unmodified_on_error", add_basic_policy_unmodified_on_error) +UNITTEST("add_basic_policy_deny_any", add_basic_policy_deny_any) UNITTEST("set_get_timer_slack", set_get_timer_slack) UNITTEST_END_TESTCASE(job_policy_tests, "job_policy", "JobPolicy tests");