From bd1da0a002e9a43cfb5220835c7a42804d90dc56 Mon Sep 17 00:00:00 2001 From: Mariusz Zaborski Date: Sat, 2 May 2015 17:45:52 +0000 Subject: [PATCH] =?UTF-8?q?Approved,=20opr=C3=B3cz=20u=C5=BCycie=20RESTORE?= =?UTF-8?q?=5FERRNO()=20do=20ustawiania=20errno.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change the nvlist_recv() function to take additional argument that specifies flags expected on the received nvlist. Receiving a nvlist with different set of flags than the ones we expect might lead to undefined behaviour, which might be potentially dangerous. Update consumers of this and related functions and update the tests. Approved by: pjd (mentor) Update man page for nvlist_unpack, nvlist_recv, nvlist_xfer, cap_recv_nvlist and cap_xfer_nvlist. Reviewed by: AllanJude Approved by: pjd (mentor) --- lib/libcapsicum/libcapsicum.3 | 18 +++++++-- lib/libcapsicum/libcapsicum.c | 14 +++---- lib/libcapsicum/libcapsicum.h | 4 +- lib/libcapsicum/libcapsicum_dns.c | 8 ++-- lib/libcapsicum/libcapsicum_grp.c | 8 ++-- lib/libcapsicum/libcapsicum_pwd.c | 6 +-- lib/libcapsicum/libcapsicum_random.c | 2 +- lib/libcapsicum/libcapsicum_service.c | 2 +- lib/libcapsicum/libcapsicum_sysctl.c | 2 +- lib/libcasper/libcasper.c | 4 +- lib/libnv/nv.3 | 50 +++++++++++++++++++++---- lib/libnv/tests/nv_tests.cc | 6 +-- lib/libnv/tests/nvlist_send_recv_test.c | 2 +- sbin/casperd/casperd.c | 2 +- sbin/casperd/zygote.c | 4 +- sys/dev/pci/pci_iov.c | 2 +- sys/kern/subr_nvlist.c | 21 +++++++---- sys/sys/nv.h | 6 +-- usr.sbin/iovctl/iovctl.c | 2 +- 19 files changed, 109 insertions(+), 54 deletions(-) diff --git a/lib/libcapsicum/libcapsicum.3 b/lib/libcapsicum/libcapsicum.3 index 9df565a4077d..cbfd214a3bc5 100644 --- a/lib/libcapsicum/libcapsicum.3 +++ b/lib/libcapsicum/libcapsicum.3 @@ -27,7 +27,7 @@ .\" .\" $FreeBSD$ .\" -.Dd April 14, 2014 +.Dd May 2, 2015 .Dt LIBCAPSICUM 3 .Os .Sh NAME @@ -68,9 +68,9 @@ .Ft "int" .Fn cap_send_nvlist "const cap_channel_t *chan" "const nvlist_t *nvl" .Ft "nvlist_t *" -.Fn cap_recv_nvlist "const cap_channel_t *chan" +.Fn cap_recv_nvlist "const cap_channel_t *chan" "int flags" .Ft "nvlist_t *" -.Fn cap_xfer_nvlist "const cap_channel_t *chan" "nvlist_t *nvl" +.Fn cap_xfer_nvlist "const cap_channel_t *chan" "nvlist_t *nvl" "int flags" .In libcapsicum_service.h .Ft "cap_channel_t *" .Fn cap_service_open "const cap_channel_t *chan" "const char *name" @@ -171,11 +171,23 @@ Most services should provide higher level API. The .Fn cap_recv_nvlist function receives the given nvlist over the given capability. +The +.Fa flags +argument defines what type the top nvlist is expected to be. +If the nvlist flags do not match the flags passed to +.Fn cap_recv_nvlist , +the nvlist will not be returned. .Pp The .Fn cap_xfer_nvlist function sends the given nvlist, destroys it and receives new nvlist in response over the given capability. +The +.Fa flags +argument defines what type the top nvlist is expected to be. +If the nvlist flags do not match the flags passed to +.Fn cap_xfer_nvlist , +the nvlist will not be returned. It does not matter if the function succeeds or fails, the nvlist given for sending will always be destroyed once the function returns. .Pp diff --git a/lib/libcapsicum/libcapsicum.c b/lib/libcapsicum/libcapsicum.c index 79ca8716261a..79c570f60e44 100644 --- a/lib/libcapsicum/libcapsicum.c +++ b/lib/libcapsicum/libcapsicum.c @@ -142,7 +142,7 @@ cap_clone(const cap_channel_t *chan) nvl = nvlist_create(0); nvlist_add_string(nvl, "cmd", "clone"); - nvl = cap_xfer_nvlist(chan, nvl); + nvl = cap_xfer_nvlist(chan, nvl, 0); if (nvl == NULL) return (NULL); if (nvlist_get_number(nvl, "error") != 0) { @@ -195,7 +195,7 @@ cap_limit_set(const cap_channel_t *chan, nvlist_t *limits) nvlmsg = nvlist_create(0); nvlist_add_string(nvlmsg, "cmd", "limit_set"); nvlist_add_nvlist(nvlmsg, "limits", limits); - nvlmsg = cap_xfer_nvlist(chan, nvlmsg); + nvlmsg = cap_xfer_nvlist(chan, nvlmsg, 0); if (nvlmsg == NULL) { nvlist_destroy(limits); return (-1); @@ -218,7 +218,7 @@ cap_limit_get(const cap_channel_t *chan, nvlist_t **limitsp) nvlmsg = nvlist_create(0); nvlist_add_string(nvlmsg, "cmd", "limit_get"); - nvlmsg = cap_xfer_nvlist(chan, nvlmsg); + nvlmsg = cap_xfer_nvlist(chan, nvlmsg, 0); if (nvlmsg == NULL) return (-1); error = (int)nvlist_get_number(nvlmsg, "error"); @@ -246,21 +246,21 @@ cap_send_nvlist(const cap_channel_t *chan, const nvlist_t *nvl) } nvlist_t * -cap_recv_nvlist(const cap_channel_t *chan) +cap_recv_nvlist(const cap_channel_t *chan, int flags) { assert(chan != NULL); assert(chan->cch_magic == CAP_CHANNEL_MAGIC); - return (nvlist_recv(chan->cch_sock)); + return (nvlist_recv(chan->cch_sock, flags)); } nvlist_t * -cap_xfer_nvlist(const cap_channel_t *chan, nvlist_t *nvl) +cap_xfer_nvlist(const cap_channel_t *chan, nvlist_t *nvl, int flags) { assert(chan != NULL); assert(chan->cch_magic == CAP_CHANNEL_MAGIC); - return (nvlist_xfer(chan->cch_sock, nvl)); + return (nvlist_xfer(chan->cch_sock, nvl, flags)); } diff --git a/lib/libcapsicum/libcapsicum.h b/lib/libcapsicum/libcapsicum.h index 4f8c59752ad8..c7110d86c9ed 100644 --- a/lib/libcapsicum/libcapsicum.h +++ b/lib/libcapsicum/libcapsicum.h @@ -105,11 +105,11 @@ int cap_send_nvlist(const cap_channel_t *chan, const nvlist_t *nvl); /* * Function receives nvlist over the given capability. */ -nvlist_t *cap_recv_nvlist(const cap_channel_t *chan); +nvlist_t *cap_recv_nvlist(const cap_channel_t *chan, int flags); /* * Function sends the given nvlist, destroys it and receives new nvlist in * response over the given capability. */ -nvlist_t *cap_xfer_nvlist(const cap_channel_t *chan, nvlist_t *nvl); +nvlist_t *cap_xfer_nvlist(const cap_channel_t *chan, nvlist_t *nvl, int flags); #endif /* !_LIBCAPSICUM_H_ */ diff --git a/lib/libcapsicum/libcapsicum_dns.c b/lib/libcapsicum/libcapsicum_dns.c index 6f240bd65009..a180b6b3b0ae 100644 --- a/lib/libcapsicum/libcapsicum_dns.c +++ b/lib/libcapsicum/libcapsicum_dns.c @@ -132,7 +132,7 @@ cap_gethostbyname2(cap_channel_t *chan, const char *name, int type) nvlist_add_string(nvl, "cmd", "gethostbyname"); nvlist_add_number(nvl, "family", (uint64_t)type); nvlist_add_string(nvl, "name", name); - nvl = cap_xfer_nvlist(chan, nvl); + nvl = cap_xfer_nvlist(chan, nvl, 0); if (nvl == NULL) { h_errno = NO_RECOVERY; return (NULL); @@ -159,7 +159,7 @@ cap_gethostbyaddr(cap_channel_t *chan, const void *addr, socklen_t len, nvlist_add_string(nvl, "cmd", "gethostbyaddr"); nvlist_add_binary(nvl, "addr", addr, (size_t)len); nvlist_add_number(nvl, "family", (uint64_t)type); - nvl = cap_xfer_nvlist(chan, nvl); + nvl = cap_xfer_nvlist(chan, nvl, 0); if (nvl == NULL) { h_errno = NO_RECOVERY; return (NULL); @@ -233,7 +233,7 @@ cap_getaddrinfo(cap_channel_t *chan, const char *hostname, const char *servname, nvlist_add_number(nvl, "hints.ai_protocol", (uint64_t)hints->ai_protocol); } - nvl = cap_xfer_nvlist(chan, nvl); + nvl = cap_xfer_nvlist(chan, nvl, 0); if (nvl == NULL) return (EAI_MEMORY); if (nvlist_get_number(nvl, "error") != 0) { @@ -283,7 +283,7 @@ cap_getnameinfo(cap_channel_t *chan, const struct sockaddr *sa, socklen_t salen, nvlist_add_number(nvl, "servlen", (uint64_t)servlen); nvlist_add_binary(nvl, "sa", sa, (size_t)salen); nvlist_add_number(nvl, "flags", (uint64_t)flags); - nvl = cap_xfer_nvlist(chan, nvl); + nvl = cap_xfer_nvlist(chan, nvl, 0); if (nvl == NULL) return (EAI_MEMORY); if (nvlist_get_number(nvl, "error") != 0) { diff --git a/lib/libcapsicum/libcapsicum_grp.c b/lib/libcapsicum/libcapsicum_grp.c index adfbc95a4bd6..267ac68c28f2 100644 --- a/lib/libcapsicum/libcapsicum_grp.c +++ b/lib/libcapsicum/libcapsicum_grp.c @@ -195,7 +195,7 @@ cap_getgrcommon_r(cap_channel_t *chan, const char *cmd, const char *name, } else { abort(); } - nvl = cap_xfer_nvlist(chan, nvl); + nvl = cap_xfer_nvlist(chan, nvl, 0); if (nvl == NULL) { assert(errno != 0); *result = NULL; @@ -319,7 +319,7 @@ cap_setgroupent(cap_channel_t *chan, int stayopen) nvl = nvlist_create(0); nvlist_add_string(nvl, "cmd", "setgroupent"); nvlist_add_bool(nvl, "stayopen", stayopen != 0); - nvl = cap_xfer_nvlist(chan, nvl); + nvl = cap_xfer_nvlist(chan, nvl, 0); if (nvl == NULL) return (0); if (nvlist_get_number(nvl, "error") != 0) { @@ -339,7 +339,7 @@ cap_setgrent(cap_channel_t *chan) nvl = nvlist_create(0); nvlist_add_string(nvl, "cmd", "setgrent"); - nvl = cap_xfer_nvlist(chan, nvl); + nvl = cap_xfer_nvlist(chan, nvl, 0); if (nvl == NULL) return (0); if (nvlist_get_number(nvl, "error") != 0) { @@ -360,7 +360,7 @@ cap_endgrent(cap_channel_t *chan) nvl = nvlist_create(0); nvlist_add_string(nvl, "cmd", "endgrent"); /* Ignore any errors, we have no way to report them. */ - nvlist_destroy(cap_xfer_nvlist(chan, nvl)); + nvlist_destroy(cap_xfer_nvlist(chan, nvl, 0)); } int diff --git a/lib/libcapsicum/libcapsicum_pwd.c b/lib/libcapsicum/libcapsicum_pwd.c index 4c1570337519..32eeeb022462 100644 --- a/lib/libcapsicum/libcapsicum_pwd.c +++ b/lib/libcapsicum/libcapsicum_pwd.c @@ -154,7 +154,7 @@ cap_getpwcommon_r(cap_channel_t *chan, const char *cmd, const char *login, } else { abort(); } - nvl = cap_xfer_nvlist(chan, nvl); + nvl = cap_xfer_nvlist(chan, nvl, 0); if (nvl == NULL) { assert(errno != 0); *result = NULL; @@ -278,7 +278,7 @@ cap_setpassent(cap_channel_t *chan, int stayopen) nvl = nvlist_create(0); nvlist_add_string(nvl, "cmd", "setpassent"); nvlist_add_bool(nvl, "stayopen", stayopen != 0); - nvl = cap_xfer_nvlist(chan, nvl); + nvl = cap_xfer_nvlist(chan, nvl, 0); if (nvl == NULL) return (0); if (nvlist_get_number(nvl, "error") != 0) { @@ -299,7 +299,7 @@ cap_set_end_pwent(cap_channel_t *chan, const char *cmd) nvl = nvlist_create(0); nvlist_add_string(nvl, "cmd", cmd); /* Ignore any errors, we have no way to report them. */ - nvlist_destroy(cap_xfer_nvlist(chan, nvl)); + nvlist_destroy(cap_xfer_nvlist(chan, nvl, 0)); } void diff --git a/lib/libcapsicum/libcapsicum_random.c b/lib/libcapsicum/libcapsicum_random.c index eed97e287ac6..2c3eb3635767 100644 --- a/lib/libcapsicum/libcapsicum_random.c +++ b/lib/libcapsicum/libcapsicum_random.c @@ -57,7 +57,7 @@ cap_random_buf(cap_channel_t *chan, void *buf, size_t nbytes) nvlist_add_string(nvl, "cmd", "generate"); nvlist_add_number(nvl, "size", (uint64_t)(left > MAXSIZE ? MAXSIZE : left)); - nvl = cap_xfer_nvlist(chan, nvl); + nvl = cap_xfer_nvlist(chan, nvl, 0); if (nvl == NULL) return (-1); if (nvlist_get_number(nvl, "error") != 0) { diff --git a/lib/libcapsicum/libcapsicum_service.c b/lib/libcapsicum/libcapsicum_service.c index 412766864d25..edfde8cc0a43 100644 --- a/lib/libcapsicum/libcapsicum_service.c +++ b/lib/libcapsicum/libcapsicum_service.c @@ -56,7 +56,7 @@ cap_service_open(const cap_channel_t *chan, const char *name) nvlist_add_string(nvl, "service", name); if (fd_is_valid(STDERR_FILENO)) nvlist_add_descriptor(nvl, "stderrfd", STDERR_FILENO); - nvl = cap_xfer_nvlist(chan, nvl); + nvl = cap_xfer_nvlist(chan, nvl, 0); if (nvl == NULL) return (NULL); error = (int)nvlist_get_number(nvl, "error"); diff --git a/lib/libcapsicum/libcapsicum_sysctl.c b/lib/libcapsicum/libcapsicum_sysctl.c index 6ea951bc27ea..fc691136cd0b 100644 --- a/lib/libcapsicum/libcapsicum_sysctl.c +++ b/lib/libcapsicum/libcapsicum_sysctl.c @@ -63,7 +63,7 @@ cap_sysctlbyname(cap_channel_t *chan, const char *name, void *oldp, nvlist_add_number(nvl, "oldlen", (uint64_t)*oldlenp); if (newp != NULL) nvlist_add_binary(nvl, "newp", newp, newlen); - nvl = cap_xfer_nvlist(chan, nvl); + nvl = cap_xfer_nvlist(chan, nvl, 0); if (nvl == NULL) return (-1); if (nvlist_get_number(nvl, "error") != 0) { diff --git a/lib/libcasper/libcasper.c b/lib/libcasper/libcasper.c index 7545baa47f6d..cb95346ec161 100644 --- a/lib/libcasper/libcasper.c +++ b/lib/libcasper/libcasper.c @@ -279,7 +279,7 @@ casper_message(const cap_channel_t *capcas, struct service *service) const char *cmd; nvlist_t *nvl; - nvl = cap_recv_nvlist(capcas); + nvl = cap_recv_nvlist(capcas, 0); if (nvl == NULL) pjdlog_exit(1, "Unable to receive message from Casper"); cmd = nvlist_get_string(nvl, "cmd"); @@ -297,7 +297,7 @@ service_message(struct service *service, struct service_connection *sconn) const char *cmd; int error; - nvlin = cap_recv_nvlist(service_connection_get_chan(sconn)); + nvlin = cap_recv_nvlist(service_connection_get_chan(sconn), 0); if (nvlin == NULL) { if (errno == ENOTCONN) { pjdlog_debug(1, "Connection closed by the client."); diff --git a/lib/libnv/nv.3 b/lib/libnv/nv.3 index bbb7b031107c..4c0e236b090a 100644 --- a/lib/libnv/nv.3 +++ b/lib/libnv/nv.3 @@ -28,7 +28,7 @@ .\" .\" $FreeBSD$ .\" -.Dd May 1, 2015 +.Dd May 2, 2015 .Dt NV 3 .Os .Sh NAME @@ -85,14 +85,14 @@ .Ft "void *" .Fn nvlist_pack "const nvlist_t *nvl" "size_t *sizep" .Ft "nvlist_t *" -.Fn nvlist_unpack "const void *buf" "size_t size" +.Fn nvlist_unpack "const void *buf" "size_t size" "int flags" .\" .Ft int .Fn nvlist_send "int sock" "const nvlist_t *nvl" .Ft "nvlist_t *" -.Fn nvlist_recv "int sock" +.Fn nvlist_recv "int sock" "int flags" .Ft "nvlist_t *" -.Fn nvlist_xfer "int sock" "nvlist_t *nvl" +.Fn nvlist_xfer "int sock" "nvlist_t *nvl" "int flags" .\" .Ft "const char *" .Fn nvlist_next "const nvlist_t *nvl" "int *typep" "void **cookiep" @@ -325,6 +325,18 @@ The nvlist must not be in error state. The .Fn nvlist_unpack function converts the given buffer to the nvlist. +The +.Fa flags +argument defines what type of the top level nvlist is expected to be. +Flags are set up using the +.Fn nvlist_create +function. +If the nvlist flags do not match the flags passed to +.Fn nvlist_unpack , +the nvlist will not be returned. +Every nested nvlist list should be checked using +.Fn nvlist_flags +function. The function returns .Dv NULL in case of an error. @@ -343,12 +355,36 @@ The function receives nvlist over the socket given by the .Fa sock argument. +The +.Fa flags +argument defines what type of the top level nvlist is expected to be. +Flags are set up using the +.Fn nvlist_create +function. +If the nvlist flags do not match the flags passed to +.Fn nvlist_recv , +the nvlist will not be returned. +Every nested nvlist list should be checked using +.Fn nvlist_flags +function. .Pp The .Fn nvlist_xfer function sends the given nvlist over the socket given by the .Fa sock argument and receives nvlist over the same socket. +The +.Fa flags +argument defines what type of the top level nvlist is expected to be. +Flags are set up using the +.Fn nvlist_create +function. +If the nvlist flags do not match the flags passed to +.Fn nvlist_xfer , +the nvlist will not be returned. +Every nested nvlist list should be checked using +.Fn nvlist_flags +function. The given nvlist is always destroyed. .Pp The @@ -559,7 +595,7 @@ const char *command; char *filename; int fd; -nvl = nvlist_recv(sock); +nvl = nvlist_recv(sock, 0); if (nvl == NULL) err(1, "nvlist_recv() failed"); @@ -588,7 +624,7 @@ const char *name; void *cookie; int type; -nvl = nvlist_recv(sock); +nvl = nvlist_recv(sock, 0); if (nvl == NULL) err(1, "nvlist_recv() failed"); @@ -617,7 +653,7 @@ const char *name; void *cookie; int type; -nvl = nvlist_recv(sock); +nvl = nvlist_recv(sock, 0); if (nvl == NULL) err(1, "nvlist_recv() failed"); diff --git a/lib/libnv/tests/nv_tests.cc b/lib/libnv/tests/nv_tests.cc index 2d9fd97914d1..1fee182acea0 100644 --- a/lib/libnv/tests/nv_tests.cc +++ b/lib/libnv/tests/nv_tests.cc @@ -440,7 +440,7 @@ ATF_TEST_CASE_BODY(nvlist_pack__empty_nvlist) packed = nvlist_pack(nvl, &packed_size); ATF_REQUIRE(packed != NULL); - unpacked = nvlist_unpack(packed, packed_size); + unpacked = nvlist_unpack(packed, packed_size, 0); ATF_REQUIRE(unpacked != NULL); ATF_REQUIRE(unpacked != nvl); ATF_REQUIRE(nvlist_empty(unpacked)); @@ -534,7 +534,7 @@ ATF_TEST_CASE_BODY(nvlist_pack__multiple_values) packed = nvlist_pack(nvl, &packed_size); ATF_REQUIRE(packed != NULL); - unpacked = nvlist_unpack(packed, packed_size); + unpacked = nvlist_unpack(packed, packed_size, 0); ATF_REQUIRE(unpacked != 0); it = NULL; @@ -614,7 +614,7 @@ ATF_TEST_CASE_BODY(nvlist_unpack__duplicate_key) ATF_REQUIRE(keypos != NULL); memcpy(keypos, key2, keylen); - unpacked = nvlist_unpack(packed, size); + unpacked = nvlist_unpack(packed, size, 0); ATF_REQUIRE(nvlist_error(unpacked) != 0); free(packed); diff --git a/lib/libnv/tests/nvlist_send_recv_test.c b/lib/libnv/tests/nvlist_send_recv_test.c index 1b083c35d339..50222fbb8e39 100644 --- a/lib/libnv/tests/nvlist_send_recv_test.c +++ b/lib/libnv/tests/nvlist_send_recv_test.c @@ -95,7 +95,7 @@ parent(int sock) int type, ctype; size_t size; - nvl = nvlist_recv(sock); + nvl = nvlist_recv(sock, 0); CHECK(nvlist_error(nvl) == 0); if (nvlist_error(nvl) != 0) err(1, "nvlist_recv() failed"); diff --git a/sbin/casperd/casperd.c b/sbin/casperd/casperd.c index 4b9037b40e38..f83881107de7 100644 --- a/sbin/casperd/casperd.c +++ b/sbin/casperd/casperd.c @@ -357,7 +357,7 @@ service_external_execute(int chanfd) int stderrfd, execfd, procfd; nvlist_t *nvl; - nvl = nvlist_recv(chanfd); + nvl = nvlist_recv(chanfd, 0); if (nvl == NULL) pjdlog_exit(1, "Unable to receive nvlist"); service = nvlist_take_string(nvl, "service"); diff --git a/sbin/casperd/zygote.c b/sbin/casperd/zygote.c index be3d9e5eee4c..c460bd322b92 100644 --- a/sbin/casperd/zygote.c +++ b/sbin/casperd/zygote.c @@ -91,7 +91,7 @@ zygote_clone(zygote_func_t *func, int flags, int *chanfdp, int *procfdp) nvl = nvlist_create(0); nvlist_add_number(nvl, "func", (uint64_t)(uintptr_t)func); nvlist_add_number(nvl, "flags", (uint64_t)flags); - nvl = nvlist_xfer(zygote_sock, nvl); + nvl = nvlist_xfer(zygote_sock, nvl, 0); if (nvl == NULL) return (-1); if (nvlist_exists_number(nvl, "error")) { @@ -134,7 +134,7 @@ zygote_main(int sock) closefrom(sock + 1); for (;;) { - nvlin = nvlist_recv(sock); + nvlin = nvlist_recv(sock, 0); if (nvlin == NULL) { if (errno == ENOTCONN) { /* Casperd exited. */ diff --git a/sys/dev/pci/pci_iov.c b/sys/dev/pci/pci_iov.c index e256a5d126f1..4672e55e5996 100644 --- a/sys/dev/pci/pci_iov.c +++ b/sys/dev/pci/pci_iov.c @@ -386,7 +386,7 @@ pci_iov_parse_config(struct pcicfg_iov *iov, struct pci_iov_arg *arg, if (error != 0) goto out; - config = nvlist_unpack(packed_config, arg->len); + config = nvlist_unpack(packed_config, arg->len, NV_FLAG_IGNORE_CASE); if (config == NULL) { error = EINVAL; goto out; diff --git a/sys/kern/subr_nvlist.c b/sys/kern/subr_nvlist.c index f96b8905d869..ec4471866226 100644 --- a/sys/kern/subr_nvlist.c +++ b/sys/kern/subr_nvlist.c @@ -774,7 +774,8 @@ nvlist_unpack_header(nvlist_t *nvl, const unsigned char *ptr, size_t nfds, } static nvlist_t * -nvlist_xunpack(const void *buf, size_t size, const int *fds, size_t nfds) +nvlist_xunpack(const void *buf, size_t size, const int *fds, size_t nfds, + int flags) { const unsigned char *ptr; nvlist_t *nvl, *retnvl, *tmpnvl; @@ -782,6 +783,8 @@ nvlist_xunpack(const void *buf, size_t size, const int *fds, size_t nfds) size_t left; bool isbe; + PJDLOG_ASSERT((flags & ~(NV_FLAG_PUBLIC_MASK)) == 0); + left = size; ptr = buf; @@ -793,6 +796,10 @@ nvlist_xunpack(const void *buf, size_t size, const int *fds, size_t nfds) ptr = nvlist_unpack_header(nvl, ptr, nfds, &isbe, &left); if (ptr == NULL) goto failed; + if (nvl->nvl_flags != flags) { + ERRNO_SET(EILSEQ); + goto failed; + } while (left > 0) { ptr = nvpair_unpack(isbe, ptr, &left, &nvp); @@ -849,10 +856,10 @@ nvlist_xunpack(const void *buf, size_t size, const int *fds, size_t nfds) } nvlist_t * -nvlist_unpack(const void *buf, size_t size) +nvlist_unpack(const void *buf, size_t size, int flags) { - return (nvlist_xunpack(buf, size, NULL, 0)); + return (nvlist_xunpack(buf, size, NULL, 0, flags)); } #ifndef _KERNEL @@ -900,7 +907,7 @@ nvlist_send(int sock, const nvlist_t *nvl) } nvlist_t * -nvlist_recv(int sock) +nvlist_recv(int sock, int flags) { struct nvlist_header nvlhdr; nvlist_t *nvl, *ret; @@ -937,7 +944,7 @@ nvlist_recv(int sock) goto out; } - nvl = nvlist_xunpack(buf, size, fds, nfds); + nvl = nvlist_xunpack(buf, size, fds, nfds, flags); if (nvl == NULL) { ERRNO_SAVE(); for (i = 0; i < nfds; i++) @@ -957,7 +964,7 @@ nvlist_recv(int sock) } nvlist_t * -nvlist_xfer(int sock, nvlist_t *nvl) +nvlist_xfer(int sock, nvlist_t *nvl, int flags) { if (nvlist_send(sock, nvl) < 0) { @@ -965,7 +972,7 @@ nvlist_xfer(int sock, nvlist_t *nvl) return (NULL); } nvlist_destroy(nvl); - return (nvlist_recv(sock)); + return (nvlist_recv(sock, flags)); } #endif diff --git a/sys/sys/nv.h b/sys/sys/nv.h index 5c342dced820..4a339ecbfa49 100644 --- a/sys/sys/nv.h +++ b/sys/sys/nv.h @@ -87,11 +87,11 @@ void nvlist_fdump(const nvlist_t *nvl, FILE *fp); size_t nvlist_size(const nvlist_t *nvl); void *nvlist_pack(const nvlist_t *nvl, size_t *sizep); -nvlist_t *nvlist_unpack(const void *buf, size_t size); +nvlist_t *nvlist_unpack(const void *buf, size_t size, int flags); int nvlist_send(int sock, const nvlist_t *nvl); -nvlist_t *nvlist_recv(int sock); -nvlist_t *nvlist_xfer(int sock, nvlist_t *nvl); +nvlist_t *nvlist_recv(int sock, int flags); +nvlist_t *nvlist_xfer(int sock, nvlist_t *nvl, int flags); const char *nvlist_next(const nvlist_t *nvl, int *typep, void **cookiep); diff --git a/usr.sbin/iovctl/iovctl.c b/usr.sbin/iovctl/iovctl.c index faa9586511a0..dbf29d81c732 100644 --- a/usr.sbin/iovctl/iovctl.c +++ b/usr.sbin/iovctl/iovctl.c @@ -80,7 +80,7 @@ get_schema(int fd) err(1, "Could not fetch config schema"); } - schema = nvlist_unpack(arg.schema, arg.len); + schema = nvlist_unpack(arg.schema, arg.len, NV_FLAG_IGNORE_CASE); if (schema == NULL) err(1, "Could not unpack schema");