From nobody Wed Apr 20 09:43:17 2022 X-Original-To: dev-commits-src-all@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 48B5513A32D8; Wed, 20 Apr 2022 09:43:18 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4Kjwhk1JnZz3vkb; Wed, 20 Apr 2022 09:43:18 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1650447798; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=w3xOWjeyKen4jX2SoRM2MY0hQMaoQiarEC0qWIjx2Zo=; b=XVf9QJSqlM19rrXvJPBX2XzFpxI/4YZ6L2XimzzoEw3niG+Oo7dgpiHdgd1pCJXejRnvK3 SQaNj/5+cz1Xy8d/sRQQtV9pLzqwyvUIFexBuV8lMz1XVPSGbyGOfjnYYywYEpx9QPPsgS IVJO9QYUs6xeWIJS8sdCQNoPQ8u1LkEcKqkmwHnwlUikVGIYsY0FqoVG/oGS3t3xTDR/j7 tB8n444S5tn82KWh9VsprOHwRYL+iCOWaAauteZJSym7ptrRUt4r4nITbHuWHBNhPCzSCE H/lVLJ09icH3SkHxTwA9a0pwDv6sOaVr48qjxekmoypVHTkUiybQSfEsXT+KDA== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 0E189118E1; Wed, 20 Apr 2022 09:43:18 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.16.1/8.16.1) with ESMTP id 23K9hHuS033405; Wed, 20 Apr 2022 09:43:17 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 23K9hHcf033404; Wed, 20 Apr 2022 09:43:17 GMT (envelope-from git) Date: Wed, 20 Apr 2022 09:43:17 GMT Message-Id: <202204200943.23K9hHcf033404@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Kristof Provost Subject: git: 7ed19f5c7780 - main - libpfctl: grow request buffer on ENOSPC List-Id: Commit messages for all branches of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-all List-Help: List-Post: List-Subscribe: List-Unsubscribe: Sender: owner-dev-commits-src-all@freebsd.org X-BeenThere: dev-commits-src-all@freebsd.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: kp X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: 7ed19f5c7780ebe9ec67121f0c5aa19fbc80bf1a Auto-Submitted: auto-generated ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1650447798; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=w3xOWjeyKen4jX2SoRM2MY0hQMaoQiarEC0qWIjx2Zo=; b=ybelJ5oztNn60bo5A98tzPY6FN7HxwYoaPfpzf//xv09CguH4w2CAq9MDUxgoNiPL42Li3 1WhQqnMdOFjN2PHxmW1V7AT8gYyAHSj1pi7DH8Bt2W6DME+gv3eWqnHHBxEbs82pR49bNv 3oOAAVvtfEJYTOC3KcUXvabKHyABztKWUQM028v+ORc2Vl9NysHTgeo1eWya4CmyHq461N F743ooASdXRwKtBtmfEHZ8iYwf4wM0TY9ZEWh0yF0YCJagdKyXNnnAo2DAVwQf33riKJ86 0GqEhIWQkhM3ufYnWl/lQmkaZS8wOoPH/LutoNINLUSeV4r+AnkN9KmwIhiK8A== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1650447798; a=rsa-sha256; cv=none; b=ouVi4/6zI8fmfQovfLdjrfep5qtl9hYz0YfEE/EG8dzMgUIWoDgXasApPxkc8lCH3yaVsf m8P3eNN0vqlnhm5jLsYJsplVsTNEH2vzW8BVfhqJflGM3dos4hN1T8nQhXQ3U0o6avKW/g dOHjXIP7sQJRMykBDuTEj42Bx1noKqd1FZ6Ga1JNq1ml3EuTzSKN+CN2ts+76/ia3/dmlo VexSXlQA1WvtAaFUQRryYos5t+C/b96uU2CbqutVYgC7/xkrL8MI2ja4U/1+aCC9KyCWYD +hUqq9WrdLiRS+jD6sYaVhMZxgATBIjn7qTxO0uK9I4/kJMU7PUocSdJ9cOtlA== ARC-Authentication-Results: i=1; mx1.freebsd.org; none X-ThisMailContainsUnwantedMimeParts: N The branch main has been updated by kp: URL: https://cgit.FreeBSD.org/src/commit/?id=7ed19f5c7780ebe9ec67121f0c5aa19fbc80bf1a commit 7ed19f5c7780ebe9ec67121f0c5aa19fbc80bf1a Author: Kristof Provost AuthorDate: 2022-04-14 12:08:53 +0000 Commit: Kristof Provost CommitDate: 2022-04-20 08:51:39 +0000 libpfctl: grow request buffer on ENOSPC When we issue a request to pf and expect a serialised nvlist as a reply we have to supply a suitable buffer to the kernel. The required size for this buffer is difficult to predict, and may be (slightly) different from request to request. If it's insufficient the kernel will return ENOSPC. Teach libpfctl to catch this and send the request again with a larger buffer. MFC after: 2 weeks Sponsored by: Rubicon Communications, LLC ("Netgate") Differential Revision: https://reviews.freebsd.org/D34908 --- lib/libpfctl/libpfctl.c | 200 +++++++++++++++--------------------------------- 1 file changed, 61 insertions(+), 139 deletions(-) diff --git a/lib/libpfctl/libpfctl.c b/lib/libpfctl/libpfctl.c index f3a22106d51b..89123bd80ad5 100644 --- a/lib/libpfctl/libpfctl.c +++ b/lib/libpfctl/libpfctl.c @@ -59,6 +59,49 @@ const char* PFCTL_SYNCOOKIES_MODE_NAMES[] = { static int _pfctl_clear_states(int , const struct pfctl_kill *, unsigned int *, uint64_t); +static int +pfctl_do_ioctl(int dev, uint cmd, size_t size, nvlist_t **nvl) +{ + struct pfioc_nv nv; + void *data; + size_t nvlen; + int ret; + + data = nvlist_pack(*nvl, &nvlen); + +retry: + nv.data = malloc(size); + memcpy(nv.data, data, nvlen); + free(data); + + nv.len = nvlen; + nv.size = size; + + ret = ioctl(dev, cmd, &nv); + if (ret == -1 && errno == ENOSPC) { + size *= 2; + free(nv.data); + goto retry; + } + + nvlist_destroy(*nvl); + *nvl = NULL; + + if (ret == 0) { + *nvl = nvlist_unpack(nv.data, nv.len, 0); + if (*nvl == NULL) { + free(nv.data); + return (EIO); + } + } else { + ret = errno; + } + + free(nv.data); + + return (ret); +} + static void pf_nvuint_8_array(const nvlist_t *nvl, const char *name, size_t maxelems, uint8_t *numbers, size_t *nelems) @@ -159,7 +202,6 @@ _pfctl_get_status_counters(const nvlist_t *nvl, struct pfctl_status * pfctl_get_status(int dev) { - struct pfioc_nv nv; struct pfctl_status *status; nvlist_t *nvl; size_t len; @@ -169,18 +211,9 @@ pfctl_get_status(int dev) if (status == NULL) return (NULL); - nv.data = malloc(4096); - nv.len = nv.size = 4096; - - if (ioctl(dev, DIOCGETSTATUSNV, &nv)) { - free(nv.data); - free(status); - return (NULL); - } + nvl = nvlist_create(0); - nvl = nvlist_unpack(nv.data, nv.len, 0); - free(nv.data); - if (nvl == NULL) { + if (pfctl_do_ioctl(dev, DIOCGETSTATUSNV, 4096, &nvl)) { free(status); return (NULL); } @@ -626,31 +659,16 @@ int pfctl_get_eth_rulesets_info(int dev, struct pfctl_eth_rulesets_info *ri, const char *path) { - uint8_t buf[1024]; - struct pfioc_nv nv; nvlist_t *nvl; - void *packed; - size_t len; + int ret; bzero(ri, sizeof(*ri)); nvl = nvlist_create(0); nvlist_add_string(nvl, "path", path); - packed = nvlist_pack(nvl, &len); - memcpy(buf, packed, len); - free(packed); - nvlist_destroy(nvl); - - nv.data = buf; - nv.len = len; - nv.size = sizeof(buf); - if (ioctl(dev, DIOCGETETHRULESETS, &nv) != 0) - return (errno); - - nvl = nvlist_unpack(buf, nv.len, 0); - if (nvl == NULL) - return (EIO); + if ((ret = pfctl_do_ioctl(dev, DIOCGETETHRULESETS, 256, &nvl)) != 0) + return (ret); ri->nr = nvlist_get_number(nvl, "nr"); @@ -662,32 +680,17 @@ int pfctl_get_eth_ruleset(int dev, const char *path, int nr, struct pfctl_eth_ruleset_info *ri) { - uint8_t buf[1024]; - struct pfioc_nv nv; nvlist_t *nvl; - void *packed; - size_t len; + int ret; bzero(ri, sizeof(*ri)); nvl = nvlist_create(0); nvlist_add_string(nvl, "path", path); nvlist_add_number(nvl, "nr", nr); - packed = nvlist_pack(nvl, &len); - memcpy(buf, packed, len); - free(packed); - nvlist_destroy(nvl); - - nv.data = buf; - nv.len = len; - nv.size = sizeof(buf); - if (ioctl(dev, DIOCGETETHRULESET, &nv) != 0) - return (errno); - - nvl = nvlist_unpack(buf, nv.len, 0); - if (nvl == NULL) - return (EIO); + if ((ret = pfctl_do_ioctl(dev, DIOCGETETHRULESET, 1024, &nvl)) != 0) + return (ret); ri->nr = nvlist_get_number(nvl, "nr"); strlcpy(ri->path, nvlist_get_string(nvl, "path"), MAXPATHLEN); @@ -701,31 +704,16 @@ int pfctl_get_eth_rules_info(int dev, struct pfctl_eth_rules_info *rules, const char *path) { - uint8_t buf[1024]; - struct pfioc_nv nv; nvlist_t *nvl; - void *packed; - size_t len; + int ret; bzero(rules, sizeof(*rules)); nvl = nvlist_create(0); nvlist_add_string(nvl, "anchor", path); - packed = nvlist_pack(nvl, &len); - memcpy(buf, packed, len); - free(packed); - nvlist_destroy(nvl); - nv.data = buf; - nv.len = len; - nv.size = sizeof(buf); - - if (ioctl(dev, DIOCGETETHRULES, &nv) != 0) - return (errno); - - nvl = nvlist_unpack(buf, nv.len, 0); - if (nvl == NULL) - return (EIO); + if ((ret = pfctl_do_ioctl(dev, DIOCGETETHRULES, 1024, &nvl)) != 0) + return (ret); rules->nr = nvlist_get_number(nvl, "nr"); rules->ticket = nvlist_get_number(nvl, "ticket"); @@ -739,11 +727,8 @@ pfctl_get_eth_rule(int dev, uint32_t nr, uint32_t ticket, const char *path, struct pfctl_eth_rule *rule, bool clear, char *anchor_call) { - uint8_t buf[2048]; - struct pfioc_nv nv; nvlist_t *nvl; - void *data; - size_t len; + int ret; nvl = nvlist_create(0); @@ -752,22 +737,8 @@ pfctl_get_eth_rule(int dev, uint32_t nr, uint32_t ticket, nvlist_add_number(nvl, "nr", nr); nvlist_add_bool(nvl, "clear", clear); - data = nvlist_pack(nvl, &len); - nv.data = buf; - memcpy(buf, data, len); - free(data); - nv.len = len; - nv.size = sizeof(buf); - if (ioctl(dev, DIOCGETETHRULE, &nv)) { - nvlist_destroy(nvl); - return (errno); - } - nvlist_destroy(nvl); - - nvl = nvlist_unpack(buf, nv.len, 0); - if (nvl == NULL) { - return (EIO); - } + if ((ret = pfctl_do_ioctl(dev, DIOCGETETHRULE, 2048, &nvl)) != 0) + return (ret); pfctl_nveth_rule_to_eth_rule(nvl, rule); @@ -1004,9 +975,7 @@ int pfctl_get_clear_rule(int dev, uint32_t nr, uint32_t ticket, const char *anchor, uint32_t ruleset, struct pfctl_rule *rule, char *anchor_call, bool clear) { - struct pfioc_nv nv; nvlist_t *nvl; - void *nvlpacked; int ret; nvl = nvlist_create(0); @@ -1021,30 +990,8 @@ int pfctl_get_clear_rule(int dev, uint32_t nr, uint32_t ticket, if (clear) nvlist_add_bool(nvl, "clear_counter", true); - nvlpacked = nvlist_pack(nvl, &nv.len); - if (nvlpacked == NULL) { - nvlist_destroy(nvl); - return (ENOMEM); - } - nv.data = malloc(8182); - nv.size = 8192; - assert(nv.len <= nv.size); - memcpy(nv.data, nvlpacked, nv.len); - nvlist_destroy(nvl); - nvl = NULL; - free(nvlpacked); - - ret = ioctl(dev, DIOCGETRULENV, &nv); - if (ret != 0) { - free(nv.data); + if ((ret = pfctl_do_ioctl(dev, DIOCGETRULENV, 8192, &nvl)) != 0) return (ret); - } - - nvl = nvlist_unpack(nv.data, nv.len, 0); - if (nvl == NULL) { - free(nv.data); - return (EIO); - } pf_nvrule_to_rule(nvlist_get_nvlist(nvl, "rule"), rule); @@ -1052,7 +999,6 @@ int pfctl_get_clear_rule(int dev, uint32_t nr, uint32_t ticket, strlcpy(anchor_call, nvlist_get_string(nvl, "anchor_call"), MAXPATHLEN); - free(nv.data); nvlist_destroy(nvl); return (0); @@ -1238,22 +1184,8 @@ _pfctl_clear_states(int dev, const struct pfctl_kill *kill, nvlist_add_string(nvl, "label", kill->label); nvlist_add_bool(nvl, "kill_match", kill->kill_match); - nv.data = nvlist_pack(nvl, &nv.len); - nv.size = nv.len; - nvlist_destroy(nvl); - nvl = NULL; - - ret = ioctl(dev, ioctlval, &nv); - if (ret != 0) { - free(nv.data); + if ((ret = pfctl_do_ioctl(dev, ioctlval, 1024, &nvl)) != 0) return (ret); - } - - nvl = nvlist_unpack(nv.data, nv.len, 0); - if (nvl == NULL) { - free(nv.data); - return (EIO); - } if (killed) *killed = nvlist_get_number(nvl, "killed"); @@ -1415,7 +1347,6 @@ pfctl_set_syncookies(int dev, const struct pfctl_syncookies *s) int pfctl_get_syncookies(int dev, struct pfctl_syncookies *s) { - struct pfioc_nv nv; nvlist_t *nvl; int ret; uint state_limit; @@ -1427,19 +1358,10 @@ pfctl_get_syncookies(int dev, struct pfctl_syncookies *s) bzero(s, sizeof(*s)); - nv.data = malloc(256); - nv.len = nv.size = 256; + nvl = nvlist_create(0); - if (ioctl(dev, DIOCGETSYNCOOKIES, &nv)) { - free(nv.data); + if ((ret = pfctl_do_ioctl(dev, DIOCGETSYNCOOKIES, 256, &nvl)) != 0) return (errno); - } - - nvl = nvlist_unpack(nv.data, nv.len, 0); - free(nv.data); - if (nvl == NULL) { - return (EIO); - } enabled = nvlist_get_bool(nvl, "enabled"); adaptive = nvlist_get_bool(nvl, "adaptive");