tests: deterministic runner (per-gate VM reset), hardened unload path
This commit is contained in:
1 parent
a0941b77fe
commit
2690d6145c
12 files changed
+138
-60
No files matched your search
@@ -313,12 +313,12 @@ struct pfk_rwlock {
|
||||
#undef _IOWR
|
||||
#define PFKXIOC_NRBITS 8
|
||||
#define PFKXIOC_TYPEBITS 8
|
||||
#define PFKXIOC_SIZEBITS 13
|
||||
#define PFKXIOC_SIZEBITS 14
|
||||
#define PFKXIOC_DIRBITS 2
|
||||
#define PFKXIOC_NRSHIFT 0
|
||||
#define PFKXIOC_TYPESHIFT (PFKXIOC_NRSHIFT + PFKXIOC_NRBITS)
|
||||
#define PFKXIOC_SIZESHIFT (PFKXIOC_TYPESHIFT + PFKXIOC_TYPEBITS)
|
||||
#define PFKXIOC_DIRSHIFT (PFKXIOC_SIZESHIFT + PFKXIOC_SIZEBITS + 1)
|
||||
#define PFKXIOC_DIRSHIFT (PFKXIOC_SIZESHIFT + PFKXIOC_SIZEBITS)
|
||||
#define PFKXIOC_NONE 0U
|
||||
#define PFKXIOC_WRITE 1U /* OpenBSD IOC_IN (copyin) */
|
||||
#define PFKXIOC_READ 2U /* OpenBSD IOC_OUT (copyout) */
|
||||
|
||||
@@ -5020,6 +5020,8 @@ pf_test_rule(struct pf_pdesc *pd, struct pf_rule **rm, struct pf_state **sm,
|
||||
|
||||
if (pd->virtual_proto != PF_VPROTO_FRAGMENT
|
||||
&& !ctx.state_icmp && r->keep_state) {
|
||||
pr_info_ratelimited("pfk: state-eligible proto=%d kstate=%d\n",
|
||||
pd->proto, r->keep_state);
|
||||
|
||||
if (r->rule_flag & PFRULE_SRCTRACK &&
|
||||
pf_insert_src_node(&ctx.sns[PF_SN_NONE], r, PF_SN_NONE,
|
||||
|
||||
@@ -2266,35 +2266,40 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
|
||||
sizeof(pr->anchor) ||
|
||||
strnlen(pr->anchor_call, sizeof(pr->anchor_call)) >=
|
||||
sizeof(pr->anchor_call)) {
|
||||
error = ENAMETOOLONG;
|
||||
error = ENAMETOOLONG; pr_info("pfkE: addrule1\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
rule = pool_get(&pf_rule_pl, PR_WAITOK|PR_LIMITFAIL|PR_ZERO);
|
||||
if (rule == NULL) {
|
||||
error = ENOMEM;
|
||||
error = ENOMEM; pr_info("pfkE: addrule-pool\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if ((error = pf_rule_copyin(&pr->rule, rule))) {
|
||||
pr_info("pfkE: addrule copyin=%d\n", error);
|
||||
pf_rule_free(rule);
|
||||
rule = NULL;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (pr->rule.return_icmp >> 8 > ICMP_MAXTYPE) {
|
||||
pr_info("pfkE: addrule icmp %x\n", pr->rule.return_icmp);
|
||||
error = EINVAL;
|
||||
pf_rule_free(rule);
|
||||
rule = NULL;
|
||||
goto fail;
|
||||
}
|
||||
if ((error = pf_rule_checkaf(rule))) {
|
||||
pr_info("pfkE: addrule checkaf=%d\n", error);
|
||||
pf_rule_free(rule);
|
||||
rule = NULL;
|
||||
goto fail;
|
||||
}
|
||||
if (rule->src.addr.type == PF_ADDR_NONE ||
|
||||
rule->dst.addr.type == PF_ADDR_NONE) {
|
||||
pr_info("pfkE: addrule none src=%d dst=%d\n",
|
||||
rule->src.addr.type, rule->dst.addr.type);
|
||||
error = EINVAL;
|
||||
pf_rule_free(rule);
|
||||
rule = NULL;
|
||||
|
||||
@@ -33,18 +33,25 @@ struct pfk_pkt {
|
||||
int dir;
|
||||
};
|
||||
|
||||
#define PFK_MARK_PASSED 0x50460001u /* skb->mark: survived pf_test already */
|
||||
#define PFK_DONE_IN 0x50460010u /* skb->mark bit: PF_IN pass completed */
|
||||
#define PFK_DONE_OUT 0x50460020u /* skb->mark bit: PF_OUT pass completed */
|
||||
|
||||
static void
|
||||
pfk_pkt_reinject(struct pfk_pkt *pk)
|
||||
{
|
||||
struct sk_buff *skb = pk->skb;
|
||||
|
||||
skb->mark = PFK_MARK_PASSED;
|
||||
pk->skb->mark |= (pk->dir == PF_IN) ? PFK_DONE_IN : PFK_DONE_OUT;
|
||||
if (pk->dir == PF_IN) {
|
||||
if (skb->dev)
|
||||
/* netif_rx expects data at the network header (eth_type_trans
|
||||
* already done by the driver) — exactly the state the PRE
|
||||
* hook sees. protocol/mac_header are preserved. */
|
||||
if (skb->dev) {
|
||||
skb_reset_network_header(skb);
|
||||
skb->protocol = htons(pk->af == AF_INET ?
|
||||
ETH_P_IP : ETH_P_IPV6);
|
||||
netif_rx(skb);
|
||||
else {
|
||||
} else {
|
||||
kfree_skb(skb);
|
||||
}
|
||||
} else {
|
||||
@@ -123,11 +130,9 @@ pfk_enqueue_verdict(int af, struct sk_buff *skb,
|
||||
{
|
||||
struct pfk_pkt *pk;
|
||||
struct pfk_ifnet *ifp;
|
||||
unsigned int pk_dir_done __maybe_unused;
|
||||
int dir;
|
||||
|
||||
if (skb->mark == PFK_MARK_PASSED)
|
||||
return NF_ACCEPT;
|
||||
|
||||
switch (st->hook) {
|
||||
case NF_INET_PRE_ROUTING:
|
||||
dir = PF_IN;
|
||||
@@ -139,6 +144,8 @@ pfk_enqueue_verdict(int af, struct sk_buff *skb,
|
||||
default:
|
||||
return NF_ACCEPT; /* LOCAL_IN/FORWARD */
|
||||
}
|
||||
if (skb->mark & (dir == PF_IN ? PFK_DONE_IN : PFK_DONE_OUT))
|
||||
return NF_ACCEPT;
|
||||
|
||||
if (af == AF_INET && !pskb_may_pull(skb, sizeof(struct pf_ip)))
|
||||
return NF_ACCEPT;
|
||||
|
||||
@@ -54,6 +54,9 @@ pfk_ioctl_io(struct file *filp, unsigned int cmd, unsigned long arg)
|
||||
p.p_ucred = &cred;
|
||||
p.p_p = &pp;
|
||||
|
||||
if (cmd == DIOCADDRULE)
|
||||
pr_info("pfkE: ioctl sz=%d kern_size=%d rule=%d\n", (int)sz,
|
||||
(int)sizeof(struct pfioc_rule), (int)sizeof(struct pf_rule));
|
||||
kdata = kzalloc(sz ? sz : sizeof(long), GFP_KERNEL);
|
||||
if (!kdata)
|
||||
return -ENOMEM;
|
||||
@@ -127,6 +130,7 @@ static int __init pfk_init(void)
|
||||
* No NET_LOCK here: pfattach/pfi take what locks they need (PF_LOCK),
|
||||
* and control ioctls serialize with NET_LOCK themselves. */
|
||||
pf_status_init();
|
||||
stoeplitz_init(); /* pf.c flow-id hashing cache (was never called) */
|
||||
pfattach(0);
|
||||
pfk_if_set_event_cb(pfk_pfi_event);
|
||||
pfk_if_iterate(pfk_pfi_attach_one);
|
||||
@@ -149,9 +153,21 @@ err_mbuf:
|
||||
return err;
|
||||
}
|
||||
|
||||
extern struct timeout pf_purge_to, pf_purge_states_to;
|
||||
|
||||
static void __exit pfk_exit(void)
|
||||
{
|
||||
/* stop sources before flushing workqueues: the purge timer
|
||||
* self-rearms (pf_purge re-arms on every run) and would keep the
|
||||
* workqueues non-empty forever (observed rmmod hang). */
|
||||
misc_deregister(&pfk_dev);
|
||||
pfk_net_lock();
|
||||
pf_status.running = 0;
|
||||
pfk_net_unlock();
|
||||
timeout_del(&pf_purge_to);
|
||||
timeout_del(&pf_purge_states_to);
|
||||
timeout_del_sync(&pf_purge_to);
|
||||
timeout_del_sync(&pf_purge_states_to);
|
||||
pfk_hooks_unregister();
|
||||
pfk_if_exit();
|
||||
pfk_pcb_exit();
|
||||
|
||||
Reference in new issue
Block a user