feat(filter): per-directory merge rules at the receiver; implement e/n/w/- modifiers
This commit is contained in:
@@ -225,6 +225,7 @@ static void send_config_only_frame(int fd, const char* missing_path) {
|
||||
EXPECT_TRUE(send_int(fd, 0)); /* size-skipped */
|
||||
EXPECT_TRUE(send_int(fd, 1)); /* missing args */
|
||||
EXPECT_TRUE(send_wire_str(fd, missing_path));
|
||||
EXPECT_TRUE(send_int(fd, 0)); /* per-directory filter-rule block is empty */
|
||||
EXPECT_TRUE(send_int(fd, 0)); /* apply = false */
|
||||
EXPECT_TRUE(send_wire_str(fd, "."));
|
||||
EXPECT_TRUE(send_int(fd, 0));
|
||||
@@ -265,10 +266,111 @@ static void test_config_only_frame_applies_missing_args(void) {
|
||||
config_delete(config);
|
||||
}
|
||||
|
||||
/* The per-directory filter-rule block (protocol 2.30.0) must be bounded on
|
||||
* receive: every count, the action/sides domain, the owner-directory syntax and
|
||||
* the pattern length are validated so a hostile peer can neither overread nor
|
||||
* allocate unboundedly. It also round-trips a valid group faithfully. */
|
||||
static void test_filter_dir_rules_receive_bounds(void) {
|
||||
int p[2];
|
||||
FilterRuleList* out = NULL;
|
||||
|
||||
/* Group count beyond the cap is rejected. */
|
||||
EXPECT_EQ_INT(socketpair(AF_UNIX, SOCK_STREAM, 0, p), 0);
|
||||
EXPECT_TRUE(send_int(p[1], MAX_FILTER_RULES + 1));
|
||||
EXPECT_FALSE(delete_filter_dir_rules_receive(p[0], &out));
|
||||
EXPECT_NULL(out);
|
||||
close(p[0]);
|
||||
close(p[1]);
|
||||
|
||||
/* A negative group count is rejected. */
|
||||
EXPECT_EQ_INT(socketpair(AF_UNIX, SOCK_STREAM, 0, p), 0);
|
||||
EXPECT_TRUE(send_int(p[1], -1));
|
||||
EXPECT_FALSE(delete_filter_dir_rules_receive(p[0], &out));
|
||||
EXPECT_NULL(out);
|
||||
close(p[0]);
|
||||
close(p[1]);
|
||||
|
||||
/* An empty block is valid and yields NULL. */
|
||||
EXPECT_EQ_INT(socketpair(AF_UNIX, SOCK_STREAM, 0, p), 0);
|
||||
EXPECT_TRUE(send_int(p[1], 0));
|
||||
EXPECT_TRUE(delete_filter_dir_rules_receive(p[0], &out));
|
||||
EXPECT_NULL(out);
|
||||
close(p[0]);
|
||||
close(p[1]);
|
||||
|
||||
/* An unknown action is a protocol error. */
|
||||
EXPECT_EQ_INT(socketpair(AF_UNIX, SOCK_STREAM, 0, p), 0);
|
||||
EXPECT_TRUE(send_int(p[1], 1));
|
||||
EXPECT_TRUE(send_wire_str(p[1], ""));
|
||||
EXPECT_TRUE(send_int(p[1], 1));
|
||||
EXPECT_TRUE(send_int(p[1], 999));
|
||||
EXPECT_FALSE(delete_filter_dir_rules_receive(p[0], &out));
|
||||
EXPECT_NULL(out);
|
||||
close(p[0]);
|
||||
close(p[1]);
|
||||
|
||||
/* An absolute owner directory is rejected (confinement). */
|
||||
EXPECT_EQ_INT(socketpair(AF_UNIX, SOCK_STREAM, 0, p), 0);
|
||||
EXPECT_TRUE(send_int(p[1], 1));
|
||||
EXPECT_TRUE(send_wire_str(p[1], "/etc"));
|
||||
EXPECT_TRUE(send_int(p[1], 0));
|
||||
EXPECT_FALSE(delete_filter_dir_rules_receive(p[0], &out));
|
||||
EXPECT_NULL(out);
|
||||
close(p[0]);
|
||||
close(p[1]);
|
||||
|
||||
/* An over-long pattern is rejected before allocation. */
|
||||
{
|
||||
char* big = malloc(MAX_PROTECT_PATTERN_LEN + 2);
|
||||
EXPECT_NOT_NULL(big);
|
||||
memset(big, 'a', MAX_PROTECT_PATTERN_LEN + 1);
|
||||
big[MAX_PROTECT_PATTERN_LEN + 1] = '\0';
|
||||
EXPECT_EQ_INT(socketpair(AF_UNIX, SOCK_STREAM, 0, p), 0);
|
||||
EXPECT_TRUE(send_int(p[1], 1));
|
||||
EXPECT_TRUE(send_wire_str(p[1], ""));
|
||||
EXPECT_TRUE(send_int(p[1], 1));
|
||||
EXPECT_TRUE(send_int(p[1], (int)FILTER_ACTION_EXCLUDE));
|
||||
EXPECT_TRUE(send_int(p[1], (int)(FILTER_SIDE_SENDER | FILTER_SIDE_RECEIVER)));
|
||||
EXPECT_TRUE(send_int(p[1], 0));
|
||||
EXPECT_TRUE(send_int(p[1], 0));
|
||||
EXPECT_TRUE(send_int(p[1], 0));
|
||||
EXPECT_TRUE(send_int(p[1], 0));
|
||||
EXPECT_TRUE(send_wire_str(p[1], big));
|
||||
EXPECT_FALSE(delete_filter_dir_rules_receive(p[0], &out));
|
||||
EXPECT_NULL(out);
|
||||
close(p[0]);
|
||||
close(p[1]);
|
||||
free(big);
|
||||
}
|
||||
|
||||
/* A valid group round-trips its owner, no-inherit flag and pattern. */
|
||||
EXPECT_EQ_INT(socketpair(AF_UNIX, SOCK_STREAM, 0, p), 0);
|
||||
EXPECT_TRUE(send_int(p[1], 1));
|
||||
EXPECT_TRUE(send_wire_str(p[1], "sub"));
|
||||
EXPECT_TRUE(send_int(p[1], 1));
|
||||
EXPECT_TRUE(send_int(p[1], (int)FILTER_ACTION_EXCLUDE));
|
||||
EXPECT_TRUE(send_int(p[1], (int)(FILTER_SIDE_SENDER | FILTER_SIDE_RECEIVER)));
|
||||
EXPECT_TRUE(send_int(p[1], 0));
|
||||
EXPECT_TRUE(send_int(p[1], 0));
|
||||
EXPECT_TRUE(send_int(p[1], 0));
|
||||
EXPECT_TRUE(send_int(p[1], 1)); /* no_inherit */
|
||||
EXPECT_TRUE(send_wire_str(p[1], "*.log"));
|
||||
EXPECT_TRUE(delete_filter_dir_rules_receive(p[0], &out));
|
||||
EXPECT_NOT_NULL(out);
|
||||
EXPECT_EQ_INT(out->count, 1);
|
||||
EXPECT_EQ_STR(out->items[0]->owner, "sub");
|
||||
EXPECT_EQ_STR(out->items[0]->pattern, "*.log");
|
||||
EXPECT_TRUE(out->items[0]->no_inherit);
|
||||
filter_rule_list_free(out);
|
||||
close(p[0]);
|
||||
close(p[1]);
|
||||
}
|
||||
|
||||
void test_delete_plan(void) {
|
||||
test_delete_delay_refilled_dir_removed_recursively();
|
||||
test_delete_delay_removed_file_counted();
|
||||
test_delete_delay_max_delete_bounds_actual();
|
||||
test_delete_delay_actual_removal_charges_budget();
|
||||
test_config_only_frame_applies_missing_args();
|
||||
test_filter_dir_rules_receive_bounds();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user