Changeset View
Changeset View
Standalone View
Standalone View
sys/kern/kern_jail.c
Show First 20 Lines • Show All 771 Lines • ▼ Show 20 Lines | prison_ip_set(struct prison *pr, const pr_family_t af, struct prison_ip *new) | ||||||||||||
old = *mem; | old = *mem; | ||||||||||||
ck_pr_store_ptr(mem, new); | ck_pr_store_ptr(mem, new); | ||||||||||||
prison_ip_free(old); | prison_ip_free(old); | ||||||||||||
} | } | ||||||||||||
/* | /* | ||||||||||||
* Restrict a prison's IP address list with its parent's, possibly replacing | * Restrict a prison's IP address list with its parent's, possibly replacing | ||||||||||||
* it. Return true if the replacement buffer was used (or would have been). | * it. Return true if the replacement buffer was used (or should redo). | ||||||||||||
* kern_jail_set() helper. | * kern_jail_set() helper. | ||||||||||||
*/ | */ | ||||||||||||
static bool | static bool | ||||||||||||
prison_ip_restrict(struct prison *pr, const pr_family_t af, | prison_ip_restrict(struct prison *pr, const pr_family_t af, | ||||||||||||
struct prison_ip *new) | struct prison_ip *new) | ||||||||||||
{ | { | ||||||||||||
const struct prison_ip *ppip = pr->pr_parent->pr_addrs[af]; | const struct prison_ip *ppip = pr->pr_parent->pr_addrs[af]; | ||||||||||||
const struct prison_ip *pip = pr->pr_addrs[af]; | const struct prison_ip *pip = pr->pr_addrs[af]; | ||||||||||||
int (*const cmp)(const void *, const void *) = pr_families[af].cmp; | int (*const cmp)(const void *, const void *) = pr_families[af].cmp; | ||||||||||||
const size_t size = pr_families[af].size; | const size_t size = pr_families[af].size; | ||||||||||||
uint32_t ips; | uint32_t ips; | ||||||||||||
bool alloced; | bool alloced, used; | ||||||||||||
mtx_assert(&pr->pr_mtx, MA_OWNED); | mtx_assert(&pr->pr_mtx, MA_OWNED); | ||||||||||||
/* | /* | ||||||||||||
* Due to epoch-synchronized access to the IP address lists we always | * Due to epoch-synchronized access to the IP address lists we always | ||||||||||||
* allocate a new list even if the old one has enough space. We could | * allocate a new list even if the old one has enough space. We could | ||||||||||||
* atomically update an IPv4 address inside a list, but that would | * atomically update an IPv4 address inside a list, but that would | ||||||||||||
* screw up sorting, and in case of IPv6 we can't even atomically write | * screw up sorting, and in case of IPv6 we can't even atomically write | ||||||||||||
* one. | * one. | ||||||||||||
*/ | */ | ||||||||||||
ips = (pr->pr_flags & pr_families[af].ip_flag) ? pip->ips : ppip->ips; | if (ppip == NULL) { | ||||||||||||
if (ips == 0) { | if (pip != NULL) | ||||||||||||
prison_ip_set(pr, af, NULL); | prison_ip_set(pr, af, NULL); | ||||||||||||
return (false); | return (false); | ||||||||||||
} | } | ||||||||||||
if (!(pr->pr_flags & pr_families[af].ip_flag)) { | |||||||||||||
used = true; | |||||||||||||
glebius: Remove this assignment, and ... | |||||||||||||
if (new == NULL) { | if (new == NULL) { | ||||||||||||
new = prison_ip_alloc(af, ips, M_NOWAIT); | new = prison_ip_alloc(af, ppip->ips, M_NOWAIT); | ||||||||||||
if (new == NULL) | if (new == NULL) | ||||||||||||
return (true); | return (true); /* redo */ | ||||||||||||
alloced = true; | used = false; | ||||||||||||
} else | } | ||||||||||||
Done Inline Actions
glebius: | |||||||||||||
alloced = false; | |||||||||||||
if (!(pr->pr_flags & pr_families[af].ip_flag)) { | |||||||||||||
/* This has no user settings, so just copy the parent's list. */ | /* This has no user settings, so just copy the parent's list. */ | ||||||||||||
bcopy(ppip + 1, new + 1, ips * size); | MPASS(new->ips == ppip->ips); | ||||||||||||
} else { | bcopy(ppip + 1, new + 1, ppip->ips * size); | ||||||||||||
prison_ip_set(pr, af, new); | |||||||||||||
return (used); | |||||||||||||
} else if (pip != NULL) { | |||||||||||||
/* Remove addresses that aren't in the parent. */ | /* Remove addresses that aren't in the parent. */ | ||||||||||||
int i; | int i; | ||||||||||||
i = 0; /* index in pip */ | i = 0; /* index in pip */ | ||||||||||||
ips = 0; /* index in new */ | ips = 0; /* index in new */ | ||||||||||||
used = true; | |||||||||||||
Done Inline ActionsRemove this assignment, and ... glebius: Remove this assignment, and ... | |||||||||||||
if (new == NULL) { | |||||||||||||
new = prison_ip_alloc(af, pip->ips, M_NOWAIT); | |||||||||||||
if (new == NULL) | |||||||||||||
return (true); /* redo */ | |||||||||||||
used = false; | |||||||||||||
alloced = true; | |||||||||||||
} else | |||||||||||||
alloced = false; | |||||||||||||
Done Inline Actions
glebius: | |||||||||||||
for (int pi = 0; pi < ppip->ips; pi++) | for (int pi = 0; pi < ppip->ips; pi++) | ||||||||||||
if (cmp(PR_IP(pip, 0), PR_IP(ppip, pi)) == 0) { | if (cmp(PR_IP(pip, 0), PR_IP(ppip, pi)) == 0) { | ||||||||||||
/* Found our primary address in parent. */ | /* Found our primary address in parent. */ | ||||||||||||
bcopy(PR_IP(pip, i), PR_IPD(new, ips), size); | bcopy(PR_IP(pip, i), PR_IPD(new, ips), size); | ||||||||||||
i++; | i++; | ||||||||||||
ips++; | ips++; | ||||||||||||
break; | break; | ||||||||||||
} | } | ||||||||||||
Show All 22 Lines | for (int pi = 1; i < pip->ips; ) { | ||||||||||||
pi++; | pi++; | ||||||||||||
break; | break; | ||||||||||||
} | } | ||||||||||||
} | } | ||||||||||||
if (ips == 0) { | if (ips == 0) { | ||||||||||||
if (alloced) | if (alloced) | ||||||||||||
prison_ip_free(new); | prison_ip_free(new); | ||||||||||||
new = NULL; | new = NULL; | ||||||||||||
used = false; | |||||||||||||
} else { | |||||||||||||
/* Shrink to real size */ | |||||||||||||
KASSERT((new->ips >= ips), | |||||||||||||
("Out-of-bounds write to prison_ip %p", new)); | |||||||||||||
new->ips = ips; | |||||||||||||
} | } | ||||||||||||
} | |||||||||||||
prison_ip_set(pr, af, new); | prison_ip_set(pr, af, new); | ||||||||||||
return (new != NULL ? true : false); | return (used); | ||||||||||||
} | |||||||||||||
return (false); | |||||||||||||
} | } | ||||||||||||
/* | /* | ||||||||||||
* Fast-path check if an address belongs to a prison. | * Fast-path check if an address belongs to a prison. | ||||||||||||
*/ | */ | ||||||||||||
int | int | ||||||||||||
prison_ip_check(const struct prison *pr, const pr_family_t af, | prison_ip_check(const struct prison *pr, const pr_family_t af, | ||||||||||||
const void *addr) | const void *addr) | ||||||||||||
▲ Show 20 Lines • Show All 4,105 Lines • Show Last 20 Lines |
Remove this assignment, and ...