git: 89ddfbbac84c - main - jail: Fix regression panic from eb8dcdeac22d
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Fri, 13 Jan 2023 10:46:09 UTC
The branch main has been updated by zlei:
URL: https://cgit.FreeBSD.org/src/commit/?id=89ddfbbac84cb923e41782c014dc581352e498a9
commit 89ddfbbac84cb923e41782c014dc581352e498a9
Author: Zhenlei Huang <zlei@FreeBSD.org>
AuthorDate: 2023-01-13 10:15:06 +0000
Commit: Zhenlei Huang <zlei@FreeBSD.org>
CommitDate: 2023-01-13 10:45:14 +0000
jail: Fix regression panic from eb8dcdeac22d
And possibly infinite loop calling prison_ip_restrict() in
kern_jail_set() [2].
[1] It is possible that prisons do not have any IPv4 or IPv6 addresses.
[2] If prison_ip_restrict() is not provided with prison_ip, when it
allocates prison_ip successfully, then it should return false to
indicate not redo prison_ip_restrict() later.
Reviewed by: glebius
Approved by: kp (mentor)
Fixes: eb8dcdeac22d jail: network epoch protection for IP address lists
Differential Revision: https://reviews.freebsd.org/D37906
---
sys/kern/kern_jail.c | 55 +++++++++++++++++++++++++++++++++++++---------------
1 file changed, 39 insertions(+), 16 deletions(-)
diff --git a/sys/kern/kern_jail.c b/sys/kern/kern_jail.c
index c8ae362c652c..e9fc8ddae144 100644
--- a/sys/kern/kern_jail.c
+++ b/sys/kern/kern_jail.c
@@ -777,7 +777,7 @@ prison_ip_set(struct prison *pr, const pr_family_t af, struct prison_ip *new)
/*
* 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.
*/
static bool
@@ -789,7 +789,7 @@ prison_ip_restrict(struct prison *pr, const pr_family_t af,
int (*const cmp)(const void *, const void *) = pr_families[af].cmp;
const size_t size = pr_families[af].size;
uint32_t ips;
- bool alloced;
+ bool alloced, used;
mtx_assert(&pr->pr_mtx, MA_OWNED);
@@ -800,28 +800,44 @@ prison_ip_restrict(struct prison *pr, const pr_family_t af,
* screw up sorting, and in case of IPv6 we can't even atomically write
* one.
*/
- ips = (pr->pr_flags & pr_families[af].ip_flag) ? pip->ips : ppip->ips;
- if (ips == 0) {
- prison_ip_set(pr, af, NULL);
+ if (ppip == NULL) {
+ if (pip != NULL)
+ prison_ip_set(pr, af, NULL);
return (false);
}
- if (new == NULL) {
- new = prison_ip_alloc(af, ips, M_NOWAIT);
- if (new == NULL)
- return (true);
- alloced = true;
- } else
- alloced = false;
+
if (!(pr->pr_flags & pr_families[af].ip_flag)) {
+ if (new == NULL) {
+ new = prison_ip_alloc(af, ppip->ips, M_NOWAIT);
+ if (new == NULL)
+ return (true); /* redo */
+ used = false;
+ } else
+ used = true;
/* This has no user settings, so just copy the parent's list. */
- bcopy(ppip + 1, new + 1, ips * size);
- } else {
+ MPASS(new->ips == ppip->ips);
+ 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. */
int i;
i = 0; /* index in pip */
ips = 0; /* index in new */
+ used = true;
+ if (new == NULL) {
+ new = prison_ip_alloc(af, pip->ips, M_NOWAIT);
+ if (new == NULL)
+ return (true); /* redo */
+ used = false;
+ alloced = true;
+ } else {
+ used = true;
+ alloced = false;
+ }
+
for (int pi = 0; pi < ppip->ips; pi++)
if (cmp(PR_IP(pip, 0), PR_IP(ppip, pi)) == 0) {
/* Found our primary address in parent. */
@@ -860,10 +876,17 @@ prison_ip_restrict(struct prison *pr, const pr_family_t af,
if (alloced)
prison_ip_free(new);
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);
+ return (used);
}
- prison_ip_set(pr, af, new);
- return (new != NULL ? true : false);
+ return (false);
}
/*