Compare commits

..

No commits in common. "c8-stream-rhel" and "c9s" have entirely different histories.

28 changed files with 3731 additions and 2122 deletions

5
.gitignore vendored
View File

@ -1,2 +1,3 @@
SOURCES/libguestfs.keyring
SOURCES/nbdkit-1.24.0.tar.gz
/clog
/nbdkit-*.tar.gz
/nbdkit-*.tar.gz.sig

View File

@ -1,2 +0,0 @@
1bbc40f501a7fef9eef2a39b701a71aee2fea7c4 SOURCES/libguestfs.keyring
069720cc0d1502b007652101d293a57d7b4d7c41 SOURCES/nbdkit-1.24.0.tar.gz

View File

@ -0,0 +1,151 @@
From e97b5ec6e7e7406688f68a5828e66ef46046fd9f Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Tue, 23 Jul 2024 14:46:41 +0100
Subject: [PATCH] server: log: Move preserve errno to log_verror function
This neutral code refactoring just moves the place where we preserve
errno out one layer, but should have no other effect.
(cherry picked from commit f2c644d4495d5e75883ff729936102c90489e8d8)
---
server/internal.h | 8 ++++----
server/log-stderr.c | 9 ++-------
server/log-syslog.c | 13 ++++---------
server/log.c | 12 ++++++++----
4 files changed, 18 insertions(+), 24 deletions(-)
diff --git a/server/internal.h b/server/internal.h
index 7eba3bce..57e777e9 100644
--- a/server/internal.h
+++ b/server/internal.h
@@ -339,10 +339,10 @@ extern void free_debug_flags (void);
extern void log_verror (const char *fs, va_list args);
/* log-*.c */
-extern void log_stderr_verror (const char *fs, va_list args)
- ATTRIBUTE_FORMAT_PRINTF (1, 0);
-extern void log_syslog_verror (const char *fs, va_list args)
- ATTRIBUTE_FORMAT_PRINTF (1, 0);
+extern void log_stderr_verror (int orig_errno, const char *fs, va_list args)
+ ATTRIBUTE_FORMAT_PRINTF (2, 0);
+extern void log_syslog_verror (int orig_errno, const char *fs, va_list args)
+ ATTRIBUTE_FORMAT_PRINTF (2, 0);
/* vfprintf.c */
#if !HAVE_VFPRINTF_PERCENT_M
diff --git a/server/log-stderr.c b/server/log-stderr.c
index 8a55f5df..4d8b09da 100644
--- a/server/log-stderr.c
+++ b/server/log-stderr.c
@@ -43,12 +43,9 @@
#include "internal.h"
-/* Note: preserves the previous value of errno. */
void
-log_stderr_verror (const char *fs, va_list args)
+log_stderr_verror (int orig_errno, const char *fs, va_list args)
{
- int err = errno; /* must be first line of function */
-
const char *name = threadlocal_get_name ();
size_t instance_num = threadlocal_get_instance_num ();
int tty;
@@ -69,7 +66,7 @@ log_stderr_verror (const char *fs, va_list args)
}
fprintf (stderr, "error: ");
- errno = err; /* must restore in case fs contains %m */
+ errno = orig_errno; /* must restore in case fs contains %m */
vfprintf (stderr, fs, args);
fprintf (stderr, "\n");
@@ -78,6 +75,4 @@ log_stderr_verror (const char *fs, va_list args)
#ifdef HAVE_FUNLOCKFILE
funlockfile (stderr);
#endif
-
- errno = err; /* must be last line of function */
}
diff --git a/server/log-syslog.c b/server/log-syslog.c
index 76c5035b..29a7a825 100644
--- a/server/log-syslog.c
+++ b/server/log-syslog.c
@@ -45,11 +45,9 @@
/* Tempted to use LOG_FTP instead of LOG_DAEMON! */
static const int PRIORITY = LOG_DAEMON|LOG_ERR;
-/* Note: preserves the previous value of errno. */
void
-log_syslog_verror (const char *fs, va_list args)
+log_syslog_verror (int orig_errno, const char *fs, va_list args)
{
- int err = errno;
const char *name = threadlocal_get_name ();
size_t instance_num = threadlocal_get_instance_num ();
CLEANUP_FREE char *msg = NULL;
@@ -59,9 +57,9 @@ log_syslog_verror (const char *fs, va_list args)
fp = open_memstream (&msg, &len);
if (fp == NULL) {
/* Fallback to logging using fs, args directly. */
- errno = err; /* Must restore in case fs contains %m */
+ errno = orig_errno; /* must restore in case fs contains %m */
vsyslog (PRIORITY, fs, args);
- goto out;
+ return;
}
if (name) {
@@ -71,12 +69,9 @@ log_syslog_verror (const char *fs, va_list args)
fprintf (fp, ": ");
}
- errno = err; /* Must restore in case fs contains %m */
+ errno = orig_errno; /* must restore in case fs contains %m */
vfprintf (fp, fs, args);
close_memstream (fp);
syslog (PRIORITY, "%s", msg);
-
- out:
- errno = err;
}
diff --git a/server/log.c b/server/log.c
index 464e4f9a..9c1f667a 100644
--- a/server/log.c
+++ b/server/log.c
@@ -46,23 +46,27 @@
void
log_verror (const char *fs, va_list args)
{
+ int orig_errno = errno;
+
switch (log_to) {
case LOG_TO_DEFAULT:
if (forked_into_background)
- log_syslog_verror (fs, args);
+ log_syslog_verror (orig_errno, fs, args);
else
- log_stderr_verror (fs, args);
+ log_stderr_verror (orig_errno, fs, args);
break;
case LOG_TO_SYSLOG:
- log_syslog_verror (fs, args);
+ log_syslog_verror (orig_errno, fs, args);
break;
case LOG_TO_STDERR:
- log_stderr_verror (fs, args);
+ log_stderr_verror (orig_errno, fs, args);
break;
case LOG_TO_NULL:
/* nothing */
break;
}
+
+ errno = orig_errno; /* Restore errno before leaving the function. */
}
/* Note: preserves the previous value of errno. */
--
2.43.0

View File

@ -0,0 +1,177 @@
From ae28c97079cce7792c5954f67a418402a48ed0cf Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Wed, 24 Jul 2024 10:29:13 +0100
Subject: [PATCH] server: Rename threadlocal_{set,get}_error to .._errno
A simple mechanical change, to avoid confusion with
threadlocal_{set,get}_last_error introduced in the following commit.
(cherry picked from commit 1d7f655726ad3483d0e8086741182aada7ae8595)
---
server/internal.h | 4 ++--
server/plugins.c | 27 +++++++++++++--------------
server/protocol.c | 5 +++--
server/threadlocal.c | 4 ++--
4 files changed, 20 insertions(+), 20 deletions(-)
diff --git a/server/internal.h b/server/internal.h
index 57e777e9..6549c87b 100644
--- a/server/internal.h
+++ b/server/internal.h
@@ -568,8 +568,8 @@ extern void threadlocal_set_name (const char *name)
extern const char *threadlocal_get_name (void);
extern void threadlocal_set_instance_num (size_t instance_num);
extern size_t threadlocal_get_instance_num (void);
-extern void threadlocal_set_error (int err);
-extern int threadlocal_get_error (void);
+extern void threadlocal_set_errno (int err);
+extern int threadlocal_get_errno (void);
extern void *threadlocal_buffer (size_t size);
extern void threadlocal_set_conn (struct connection *conn);
extern struct connection *threadlocal_get_conn (void);
diff --git a/server/plugins.c b/server/plugins.c
index ca89ac7a..3c7df0d2 100644
--- a/server/plugins.c
+++ b/server/plugins.c
@@ -633,15 +633,14 @@ plugin_can_cache (struct context *c)
NBDKIT_DLL_PUBLIC void
nbdkit_set_error (int err)
{
- threadlocal_set_error (err);
+ threadlocal_set_errno (err);
}
-/* Grab the appropriate error value.
- */
+/* Grab the appropriate error value. */
static int
-get_error (struct backend_plugin *p)
+get_errno (struct backend_plugin *p)
{
- int ret = threadlocal_get_error ();
+ int ret = threadlocal_get_errno ();
if (!ret && p->plugin.errno_is_preserved != 0)
ret = errno;
@@ -664,7 +663,7 @@ plugin_pread (struct context *c,
else
r = p->plugin._pread_v1 (c->handle, buf, count, offset);
if (r == -1)
- *err = get_error (p);
+ *err = get_errno (p);
return r;
}
@@ -685,7 +684,7 @@ plugin_flush (struct context *c,
return -1;
}
if (r == -1)
- *err = get_error (p);
+ *err = get_errno (p);
return r;
}
@@ -715,7 +714,7 @@ plugin_pwrite (struct context *c,
if (r != -1 && need_flush)
r = plugin_flush (c, 0, err);
if (r == -1 && !*err)
- *err = get_error (p);
+ *err = get_errno (p);
return r;
}
@@ -744,7 +743,7 @@ plugin_trim (struct context *c,
if (r != -1 && need_flush)
r = plugin_flush (c, 0, err);
if (r == -1 && !*err)
- *err = get_error (p);
+ *err = get_errno (p);
return r;
}
@@ -782,7 +781,7 @@ plugin_zero (struct context *c,
else
emulate = true;
if (r == -1)
- *err = emulate ? EOPNOTSUPP : get_error (p);
+ *err = emulate ? EOPNOTSUPP : get_errno (p);
if (r == 0 || (*err != EOPNOTSUPP && *err != ENOTSUP))
goto done;
}
@@ -794,7 +793,7 @@ plugin_zero (struct context *c,
}
flags &= ~NBDKIT_FLAG_MAY_TRIM;
- threadlocal_set_error (0);
+ threadlocal_set_errno (0);
*err = 0;
while (count) {
@@ -814,7 +813,7 @@ plugin_zero (struct context *c,
if (r != -1 && need_flush)
r = plugin_flush (c, 0, err);
if (r == -1 && !*err)
- *err = get_error (p);
+ *err = get_errno (p);
return r;
}
@@ -839,7 +838,7 @@ plugin_extents (struct context *c,
r = -1;
}
if (r == -1)
- *err = get_error (p);
+ *err = get_errno (p);
return r;
}
@@ -859,7 +858,7 @@ plugin_cache (struct context *c,
r = p->plugin.cache (c->handle, count, offset, flags);
if (r == -1)
- *err = get_error (p);
+ *err = get_errno (p);
return r;
}
diff --git a/server/protocol.c b/server/protocol.c
index 9b63f789..677da05c 100644
--- a/server/protocol.c
+++ b/server/protocol.c
@@ -235,8 +235,9 @@ handle_request (uint16_t cmd, uint16_t flags, uint64_t offset, uint32_t count,
int err = 0;
/* Clear the error, so that we know if the plugin calls
- * nbdkit_set_error() or relied on errno. */
- threadlocal_set_error (0);
+ * nbdkit_set_error() or relied on errno.
+ */
+ threadlocal_set_errno (0);
switch (cmd) {
case NBD_CMD_READ:
diff --git a/server/threadlocal.c b/server/threadlocal.c
index 088fe55a..9bb656bc 100644
--- a/server/threadlocal.c
+++ b/server/threadlocal.c
@@ -154,7 +154,7 @@ threadlocal_get_instance_num (void)
}
void
-threadlocal_set_error (int err)
+threadlocal_set_errno (int err)
{
struct threadlocal *threadlocal = pthread_getspecific (threadlocal_key);
@@ -167,7 +167,7 @@ threadlocal_set_error (int err)
/* This preserves errno, for convenience.
*/
int
-threadlocal_get_error (void)
+threadlocal_get_errno (void)
{
int err = errno;
struct threadlocal *threadlocal = pthread_getspecific (threadlocal_key);
--
2.43.0

View File

@ -0,0 +1,95 @@
From 00107f9d36fc6a1b33a1bde25e3239c520b82ab1 Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Wed, 24 Jul 2024 10:37:58 +0100
Subject: [PATCH] server: Introduce threadlocal_{set,get}_last_error
Plus a function to clear the last_error field.
(cherry picked from commit fa5055ae2b9f96af941d697de39198c96ee2580a)
---
server/internal.h | 3 +++
server/threadlocal.c | 40 ++++++++++++++++++++++++++++++++++++++++
2 files changed, 43 insertions(+)
diff --git a/server/internal.h b/server/internal.h
index 6549c87b..da19fb99 100644
--- a/server/internal.h
+++ b/server/internal.h
@@ -570,6 +570,9 @@ extern void threadlocal_set_instance_num (size_t instance_num);
extern size_t threadlocal_get_instance_num (void);
extern void threadlocal_set_errno (int err);
extern int threadlocal_get_errno (void);
+extern void threadlocal_set_last_error (char *msg);
+extern void threadlocal_clear_last_error (void);
+extern const char *threadlocal_get_last_error (void);
extern void *threadlocal_buffer (size_t size);
extern void threadlocal_set_conn (struct connection *conn);
extern struct connection *threadlocal_get_conn (void);
diff --git a/server/threadlocal.c b/server/threadlocal.c
index 9bb656bc..74a3c4e5 100644
--- a/server/threadlocal.c
+++ b/server/threadlocal.c
@@ -56,6 +56,7 @@ struct threadlocal {
char *name; /* Can be NULL. */
size_t instance_num; /* Can be 0. */
int err;
+ char *last_error; /* Can be NULL. */
void *buffer; /* Can be NULL. */
size_t buffer_size;
struct connection *conn; /* Can be NULL. */
@@ -70,6 +71,7 @@ free_threadlocal (void *threadlocalv)
struct threadlocal *threadlocal = threadlocalv;
free (threadlocal->name);
+ free (threadlocal->last_error);
free (threadlocal->buffer);
free (threadlocal);
}
@@ -176,6 +178,44 @@ threadlocal_get_errno (void)
return threadlocal ? threadlocal->err : 0;
}
+/* Set the last_error field. The ownership of the 'msg' string is
+ * passed to the threadlocal and will be freed here.
+ */
+void
+threadlocal_set_last_error (char *msg)
+{
+ struct threadlocal *threadlocal = pthread_getspecific (threadlocal_key);
+
+ if (threadlocal) {
+ free (threadlocal->last_error);
+ threadlocal->last_error = msg;
+ }
+ else {
+ /* ... otherwise throw it away, it's informational. */
+ free (msg);
+ }
+}
+
+void
+threadlocal_clear_last_error (void)
+{
+ threadlocal_set_last_error (NULL);
+}
+
+/* Get the last_error field. If successful, this returns a non-NULL
+ * string. This is valid until something calls nbdkit_error() in the
+ * same thread, so it should be used quickly. Returning NULL is not
+ * necessarily an error. The last_error is informational and may not
+ * be available.
+ */
+const char *
+threadlocal_get_last_error (void)
+{
+ struct threadlocal *threadlocal = pthread_getspecific (threadlocal_key);
+
+ return threadlocal ? threadlocal->last_error : NULL;
+}
+
/* Return the single pread/pwrite buffer for this thread. The buffer
* size is increased to size bytes if required.
*
--
2.43.0

View File

@ -0,0 +1,95 @@
From 4cde9d78c4293e294f80376266cfce420f15a6ff Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Tue, 23 Jul 2024 15:28:06 +0100
Subject: [PATCH] server: Take a thread-local copy of the last call to
nbdkit_error
nbdkit_error has traditionally been a "fancy wrapper around fprintf"
(kind of, don't take that literally). It is encouraged that plugins
and filters do something like:
if (error) {
nbdkit_error ("oops, a bad thing happened");
return -1;
}
but we don't enforce this. Plugins might call nbdkit_error more than
once or not at all.
The point where we get to sending an error back over the wire to the
NBD client is long after the plugin returned above, and after
nbdkit_error was called.
Therefore in order to send errors back to the NBD client, we must keep
the last error message around.
This change simply modifies nbdkit_error to make a best-effort attempt
to save the last error message in thread-local storage.
We also clear the last error when a new request starts, to ensure that
we don't leak errors across different callbacks or connections.
(cherry picked from commit bfa6d4064cb74f429149d14ab4025b258fc95ec4)
---
server/log.c | 21 +++++++++++++++++++++
server/protocol.c | 5 +++++
2 files changed, 26 insertions(+)
diff --git a/server/log.c b/server/log.c
index 9c1f667a..acf14d57 100644
--- a/server/log.c
+++ b/server/log.c
@@ -40,6 +40,25 @@
#include "internal.h"
+/* Copy the error message to threadlocal. This is sent to callers
+ * which are using structured replies, but is for extra information
+ * only so don't fail if we are unable to copy it.
+ */
+static void
+copy_error_to_threadlocal (int orig_errno, const char *fs, va_list args)
+{
+ va_list args_copy;
+ char *msg;
+ int r;
+
+ va_copy (args_copy, args);
+ errno = orig_errno; /* must restore in case fs contains %m */
+ r = vasprintf (&msg, fs, args_copy);
+ va_end (args_copy);
+ if (r != -1 && msg)
+ threadlocal_set_last_error (msg); /* ownership passed to threadlocal */
+}
+
/* Call the right log_*_verror function depending on log_sink.
* Note: preserves the previous value of errno.
*/
@@ -48,6 +67,8 @@ log_verror (const char *fs, va_list args)
{
int orig_errno = errno;
+ copy_error_to_threadlocal (orig_errno, fs, args);
+
switch (log_to) {
case LOG_TO_DEFAULT:
if (forked_into_background)
diff --git a/server/protocol.c b/server/protocol.c
index 677da05c..d428bfc8 100644
--- a/server/protocol.c
+++ b/server/protocol.c
@@ -239,6 +239,11 @@ handle_request (uint16_t cmd, uint16_t flags, uint64_t offset, uint32_t count,
*/
threadlocal_set_errno (0);
+ /* Also clear the last error in this thread so we will only save
+ * nbdkit_error() from this request.
+ */
+ threadlocal_clear_last_error ();
+
switch (cmd) {
case NBD_CMD_READ:
if (backend_pread (c, buf, count, offset, 0, &err) == -1)
--
2.43.0

View File

@ -0,0 +1,177 @@
From e121d8e1d39605043317cbdf28f60056e6681d56 Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Tue, 23 Jul 2024 15:45:04 +0100
Subject: [PATCH] server: Send the last error to the NBD client
This sends the last error saved in the connection handle back to the
NBD client. This is informational and best effort.
qemu reports the error already, for example:
$ nbdkit --log=null \
eval open=' echo EPERM Go Away >&2; exit 1 ' get_size=' echo 100 ' \
--run 'qemu-img info "$uri"'
qemu-img: Could not open 'nbd+unix://?socket=/tmp/nbdkitIDl6iy/socket': Requested export not available
server reported: /tmp/nbdkitRDAfXH/open: Go Away
This goes back to at least qemu 2.12.0 (RHEL 7) and possibly earlier,
so we can just assume that qemu does this for the test.
libnbd requires a patch to display this information.
(cherry picked from commit 46484ca8e6a35c45fe96b6c972ceba8984d401e8)
---
server/protocol-handshake-newstyle.c | 43 ++++++++++++++++------
tests/Makefile.am | 2 +
tests/test-last-error.sh | 55 ++++++++++++++++++++++++++++
3 files changed, 88 insertions(+), 12 deletions(-)
create mode 100755 tests/test-last-error.sh
diff --git a/server/protocol-handshake-newstyle.c b/server/protocol-handshake-newstyle.c
index 6b3bc76f..c18d32e5 100644
--- a/server/protocol-handshake-newstyle.c
+++ b/server/protocol-handshake-newstyle.c
@@ -57,28 +57,47 @@ send_newstyle_option_reply (uint32_t option, uint32_t reply)
{
GET_CONN;
struct nbd_fixed_new_option_reply fixed_new_option_reply;
+ const char *last_error = NULL;
+ uint32_t replylen = 0;
+
+ if (NBD_REP_IS_ERR (reply)) {
+ last_error = threadlocal_get_last_error ();
+ /* Note that calling nbdkit_error will invalidate last_error, so
+ * be careful below.
+ */
+ if (last_error) {
+ size_t len = strlen (last_error);
+ if (len <= NBD_MAX_STRING)
+ replylen = len;
+ }
+ }
fixed_new_option_reply.magic = htobe64 (NBD_REP_MAGIC);
fixed_new_option_reply.option = htobe32 (option);
fixed_new_option_reply.reply = htobe32 (reply);
- fixed_new_option_reply.replylen = htobe32 (0);
+ fixed_new_option_reply.replylen = htobe32 (replylen);
debug ("replying to %s with %s", name_of_nbd_opt (option),
name_of_nbd_rep (reply));
if (conn->send (&fixed_new_option_reply,
- sizeof fixed_new_option_reply, 0) == -1) {
- /* The protocol document says that the client is allowed to simply
- * drop the connection after sending NBD_OPT_ABORT, or may read
- * the reply.
- */
- if (option == NBD_OPT_ABORT)
- debug ("write: %s: %m", name_of_nbd_opt (option));
- else
- nbdkit_error ("write: %s: %m", name_of_nbd_opt (option));
- return -1;
- }
+ sizeof fixed_new_option_reply,
+ replylen > 0 ? SEND_MORE : 0) == -1)
+ goto err;
+ if (replylen > 0 && conn->send (last_error, replylen, 0) == -1)
+ goto err;
return 0;
+
+err:
+ /* The protocol document says that the client is allowed to simply
+ * drop the connection after sending NBD_OPT_ABORT, or may read
+ * the reply.
+ */
+ if (option == NBD_OPT_ABORT)
+ debug ("write: %s: %m", name_of_nbd_opt (option));
+ else
+ nbdkit_error ("write: %s: %m", name_of_nbd_opt (option));
+ return -1;
}
/* Reply to NBD_OPT_LIST with the plugin's list of export names.
diff --git a/tests/Makefile.am b/tests/Makefile.am
index b670fbf9..d510807c 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -276,6 +276,7 @@ TESTS += \
test-read-password-interactive.sh \
test-nbd-client.sh \
test-nbd-client-tls.sh \
+ test-last-error.sh \
$(NULL)
if !IS_WINDOWS
TESTS += \
@@ -301,6 +302,7 @@ EXTRA_DIST += \
test-plugin-docs.sh \
test-ipv4-lo.sh \
test-ipv6-lo.sh \
+ test-last-error.sh \
test-long-name.sh \
test-nbd-client.sh \
test-nbd-client-tls.sh \
diff --git a/tests/test-last-error.sh b/tests/test-last-error.sh
new file mode 100755
index 00000000..fc720606
--- /dev/null
+++ b/tests/test-last-error.sh
@@ -0,0 +1,55 @@
+#!/usr/bin/env bash
+# nbdkit
+# Copyright Red Hat
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# * Neither the name of Red Hat nor the names of its contributors may be
+# used to endorse or promote products derived from this software without
+# specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY RED HAT AND CONTRIBUTORS ''AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RED HAT OR
+# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+# OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+
+source ./functions.sh
+set -e
+set -x
+
+# Test informational error messages sent to the NBD client.
+# qemu-img supports this since at least 2.12.0.
+
+requires_run
+requires_plugin eval
+requires qemu-img --version
+
+out=last-error.out
+rm -f $out
+cleanup_fn rm -f $out
+
+export out
+
+nbdkit eval \
+ open=' echo EPERM Go Away >&2; exit 1 ' get_size=' echo 0 ' \
+ --run ' qemu-img info "$uri" > $out 2>&1 ||: '
+cat $out
+
+grep "Go Away" $out
--
2.43.0

View File

@ -1,82 +0,0 @@
From 99788909d9ec36e3210cf85976fe5b18da690ddd Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Wed, 4 Aug 2021 20:24:59 +0100
Subject: [PATCH] cache, cow: Fix data corruption in zero and trim on unaligned
tail
Commit eb6009b092 ("cache, cow: Reduce use of bounce-buffer") first
introduced in nbdkit 1.14 added an optimization of the
read-modify-write mechanism used for unaligned heads and tails when
zeroing in the cache layer.
Unfortunately the part applied to the tail contained a mistake: It
zeroes the end of the buffer rather than the beginning. This causes
data corruption when you use the zero or trim function with an offset
and count which is not aligned to the block size.
Although the bug has been around for years, a recent change made it
more likely to happen. Commit c1905b0a28 ("cache, cow: Use a 64K
block size by default") increased the default block size from 4K to
64K. Most filesystems use a 4K block size so operations like fstrim
will make 4K-aligned requests, and with a 4K block size also in the
cache or cow filter the unaligned case would never have been hit
before.
We can demonstrate the bug simply by filling a buffer with data
(100000 bytes in the example), and then trimming that data, which
ought to zero it out.
Before this commit there is data visible after the trim:
$ nbdkit --filter=cow data "0x21 * 100000" --run 'nbdsh -u $uri -c "h.trim(100000, 0)" ; nbdcopy $uri - | hexdump -C'
00000000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
00018000 21 21 21 21 21 21 21 21 21 21 21 21 21 21 21 21 |!!!!!!!!!!!!!!!!|
*
000186a0
After this commit the trim completely clears the data:
$ nbdkit --filter=cow data "0x21 * 100000" --run 'nbdsh -u $uri -c "h.trim(100000, 0)" ; nbdcopy $uri - | hexdump -C'
00000000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
000186a0
Thanks: Ming Xie for finding the bug
Fixes: commit eb6009b092ae642ed25f133d487dd40ef7bf70f8
(cherry picked from commit a0ae7b2158598ce48ac31706319007f716d01c87)
(cherry picked from commit c0b15574647672cb5c48178333acdd07424692ef)
---
filters/cache/cache.c | 2 +-
filters/cow/cow.c | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/filters/cache/cache.c b/filters/cache/cache.c
index 91dcc43d..0616cc7b 100644
--- a/filters/cache/cache.c
+++ b/filters/cache/cache.c
@@ -493,7 +493,7 @@ cache_zero (struct nbdkit_next_ops *next_ops, void *nxdata,
ACQUIRE_LOCK_FOR_CURRENT_SCOPE (&lock);
r = blk_read (next_ops, nxdata, blknum, block, err);
if (r != -1) {
- memset (&block[count], 0, blksize - count);
+ memset (block, 0, count);
r = blk_write (next_ops, nxdata, blknum, block, flags, err);
}
if (r == -1)
diff --git a/filters/cow/cow.c b/filters/cow/cow.c
index 51ca64a4..1cfcc4e7 100644
--- a/filters/cow/cow.c
+++ b/filters/cow/cow.c
@@ -419,7 +419,7 @@ cow_zero (struct nbdkit_next_ops *next_ops, void *nxdata,
ACQUIRE_LOCK_FOR_CURRENT_SCOPE (&lock);
r = blk_read (next_ops, nxdata, blknum, block, err);
if (r != -1) {
- memset (&block[count], 0, BLKSIZE - count);
+ memset (block, 0, count);
r = blk_write (blknum, block, err);
}
if (r == -1)
--
2.31.1

View File

@ -1,94 +0,0 @@
From 6b9d4380df9bd0be91f49aad8c4f47b4e672adde Mon Sep 17 00:00:00 2001
From: Eric Blake <eblake@redhat.com>
Date: Mon, 16 Aug 2021 13:43:29 -0500
Subject: [PATCH] server: CVE-2021-3716 reset structured replies on starttls
https://nostarttls.secvuln.info/ pointed out a series of CVEs in
common implementation flaw in various SMTP and IMAP clients and
servers, all with a common thread of improperly caching plaintext
state across the STARTTLS encryption boundary; and recommended that
other protocols with a STARTTLS operation perform a similar audit.
It turns out that nbdkit has the same vulnerability in regards to the
NBD protocol: when nbdkit is run in opportunistic TLS mode, an
attacker is able to inject a plaintext NBD_OPT_STRUCTURED_REPLY before
proxying everything else a client sends to the server; if the server
then acts on that plaintext request (as nbdkit did before this patch),
then the server ends up sending structured replies to at least
NBD_CMD_READ, even though the client was assuming that the transition
to TLS has ruled out a MitM attack.
On the bright side, nbdkit's behavior on a second
NBD_OPT_STRUCTURED_REPLY was to still reply with success, so a client
that always requests structured replies after starting TLS sees no
difference in behavior (that is, qemu 2.12 and later are immune) (had
nbdkit given an error to the second request, that may have caused
confusion to more clients). And there is always the mitigation of
using --tls=require, which lets nbdkit reject the MitM message
pre-encryption. However, nbd-client 3.15 to the present do not
understand structured replies, and I have confirmed that a MitM
attacker can thus cause a denial-of-service attack that does not
trigger until the client does its first encrypted NBD_CMD_READ.
The NBD spec has been recently tightened to declare the nbdkit
behavior to be a security hole:
https://github.com/NetworkBlockDevice/nbd/commit/77e55378096aa
Fixes: eaa4c6e9a2c4bd (server: Minimal implementation of NBD Structured Replies.)
(cherry picked from commit 09a13dafb7bb3a38ab52eb5501cba786365ba7fd)
(cherry picked from commit 6185b15a81e6915734d678f0781e31d45a7941a1)
---
docs/nbdkit-security.pod | 11 +++++++++--
server/protocol-handshake-newstyle.c | 3 ++-
2 files changed, 11 insertions(+), 3 deletions(-)
diff --git a/docs/nbdkit-security.pod b/docs/nbdkit-security.pod
index 3a28e54d..5a4e6da8 100644
--- a/docs/nbdkit-security.pod
+++ b/docs/nbdkit-security.pod
@@ -10,7 +10,7 @@ For how to report new security issues, see the C<SECURITY> file in the
top level source directory, also available online here:
L<https://github.com/libguestfs/nbdkit/blob/master/SECURITY>
-=head2 CVE-2019-14850
+=head2 CVE-2019-14850
denial of service due to premature opening of back-end connection
See the full announcement and links to mitigation, tests and fixes
@@ -26,6 +26,13 @@ See the full announcement and links to mitigation, tests and fixes
here:
https://www.redhat.com/archives/libguestfs/2019-September/msg00272.html
+=head2 CVE-2021-3716
+structured read denial of service attack against starttls
+
+See the full announcement and links to mitigation, tests and fixes
+here:
+https://www.redhat.com/archives/libguestfs/2021-August/msg00083.html
+
=head1 SEE ALSO
L<nbdkit(1)>.
@@ -38,4 +45,4 @@ Richard W.M. Jones
=head1 COPYRIGHT
-Copyright (C) 2013-2020 Red Hat Inc.
+Copyright (C) 2013-2021 Red Hat Inc.
diff --git a/server/protocol-handshake-newstyle.c b/server/protocol-handshake-newstyle.c
index 0a76a814..b94950e2 100644
--- a/server/protocol-handshake-newstyle.c
+++ b/server/protocol-handshake-newstyle.c
@@ -495,7 +495,8 @@ negotiate_handshake_newstyle_options (void)
return -1;
conn->using_tls = true;
debug ("using TLS on this connection");
- /* Wipe out any cached default export name. */
+ /* Wipe out any cached state. */
+ conn->structured_replies = false;
for_each_backend (b) {
struct handle *h = get_handle (conn, b->i);
free (h->default_exportname);
--
2.31.1

View File

@ -1,40 +0,0 @@
From add9b794b9dc697a1b52115c997fcfb6e06bf64c Mon Sep 17 00:00:00 2001
From: Eric Blake <eblake@redhat.com>
Date: Mon, 16 Aug 2021 13:43:29 -0500
Subject: [PATCH] server: reset meta context replies on starttls
Related to CVE-2021-3716, but not as severe. No compliant client will
send NBD_CMD_BLOCK_STATUS unless it first negotiates
NBD_OPT_SET_META_CONTEXT. If an attacker injects a premature
SET_META_CONTEXT, either the client will never notice (because it
never uses BLOCK_STATUS), or the client will overwrite the attacker's
attempt with the client's own SET_META_CONTEXT request after
encryption is enabled. So I don't class this as having the potential
to trigger denial-of-service due to any protocol mismatch between
compliant client and server (I don't care what happens with
non-compliant clients).
Fixes: 26455d45 (server: protocol: Implement Block Status "base:allocation".)
(cherry picked from commit 6c5faac6a37077cf2366388a80862bb00616d0d8)
(cherry picked from commit 814d8103fb4b581dc01dfd25d2cd81596576f211)
---
server/protocol-handshake-newstyle.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/server/protocol-handshake-newstyle.c b/server/protocol-handshake-newstyle.c
index b94950e2..eb0f3961 100644
--- a/server/protocol-handshake-newstyle.c
+++ b/server/protocol-handshake-newstyle.c
@@ -497,6 +497,9 @@ negotiate_handshake_newstyle_options (void)
debug ("using TLS on this connection");
/* Wipe out any cached state. */
conn->structured_replies = false;
+ free (conn->exportname_from_set_meta_context);
+ conn->exportname_from_set_meta_context = NULL;
+ conn->meta_context_base_allocation = false;
for_each_backend (b) {
struct handle *h = get_handle (conn, b->i);
free (h->default_exportname);
--
2.31.1

View File

@ -1,59 +0,0 @@
From 3c2879a38c299b725091cea45329879e3f46fc99 Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Tue, 31 Aug 2021 11:23:27 +0100
Subject: [PATCH] cow: Fix for qemu 6.1 which requires backing format
The diffing example in the manual created a qcow2 file with a backing
file but did not specify the backing format. However qemu 6.1 now
requires this and fails with:
qemu-img: cow-diff.qcow2: Backing file specified without backing format
or:
qemu-img: Could not change the backing file to 'cow-base.img': backing format must be specified
Fix the example by adding the -F option to the command line.
Also there was a test of this rebasing sequence which failed, so this
commit updates the test too.
(cherry picked from commit 618290ef33ce13b75c1a79fea1f1ffb327b5ba07)
---
filters/cow/nbdkit-cow-filter.pod | 4 ++--
tests/test-cow.sh | 4 ++--
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/filters/cow/nbdkit-cow-filter.pod b/filters/cow/nbdkit-cow-filter.pod
index 4d5ae856..510bdd40 100644
--- a/filters/cow/nbdkit-cow-filter.pod
+++ b/filters/cow/nbdkit-cow-filter.pod
@@ -101,8 +101,8 @@ At the end, disconnect the client.
Run these C<qemu-img> commands to construct a qcow2 file containing
the differences:
- qemu-img create -f qcow2 -b nbd:localhost diff.qcow2
- qemu-img rebase -b disk.img diff.qcow2
+ qemu-img create -F raw -b nbd:localhost -f qcow2 diff.qcow2
+ qemu-img rebase -F raw -b disk.img -f qcow2 diff.qcow2
F<diff.qcow2> now contains the differences between the base
(F<disk.img>) and the changes stored in nbdkit-cow-filter. C<nbdkit>
diff --git a/tests/test-cow.sh b/tests/test-cow.sh
index 8772afd7..edc4c223 100755
--- a/tests/test-cow.sh
+++ b/tests/test-cow.sh
@@ -72,8 +72,8 @@ fi
# If we have qemu-img, try the hairy rebase operation documented
# in the nbdkit-cow-filter manual.
if qemu-img --version >/dev/null 2>&1; then
- qemu-img create -f qcow2 -b nbd:unix:$sock cow-diff.qcow2
- time qemu-img rebase -b cow-base.img cow-diff.qcow2
+ qemu-img create -F raw -b nbd:unix:$sock -f qcow2 cow-diff.qcow2
+ time qemu-img rebase -F raw -b cow-base.img -f qcow2 cow-diff.qcow2
qemu-img info cow-diff.qcow2
# This checks the file we created exists.
--
2.31.1

View File

@ -1,141 +0,0 @@
From 9e20e2696fdb68008c9b4f1c36298f813320e381 Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Sat, 23 Oct 2021 16:16:39 +0100
Subject: [PATCH] vddk: Include VDDK major library version in --dump-plugin
output
Although it doesn't seem to be possible to get the precise VDDK
version, With a relatively simple change we can at least return the
VDDK major version. Currently this can be 5, 6 or 7.
(cherry picked from commit 8700649d147948897f3b97810a1dff37924bdd6e)
---
plugins/vddk/nbdkit-vddk-plugin.pod | 4 ++++
plugins/vddk/vddk.c | 29 +++++++++++++++++++----------
tests/test-vddk-real-dump-plugin.sh | 2 ++
3 files changed, 25 insertions(+), 10 deletions(-)
diff --git a/plugins/vddk/nbdkit-vddk-plugin.pod b/plugins/vddk/nbdkit-vddk-plugin.pod
index 8b14eda0..822b96be 100644
--- a/plugins/vddk/nbdkit-vddk-plugin.pod
+++ b/plugins/vddk/nbdkit-vddk-plugin.pod
@@ -417,6 +417,10 @@ at runtime.
If this is printed then the C<nfchostport=PORT> parameter is supported
by this build.
+=item C<vddk_library_version=...>
+
+The VDDK major library version: 5, 6, 7, ...
+
=item C<vddk_dll=...>
Prints the full path to the VDDK shared library. Since this requires
diff --git a/plugins/vddk/vddk.c b/plugins/vddk/vddk.c
index 69193504..291283f4 100644
--- a/plugins/vddk/vddk.c
+++ b/plugins/vddk/vddk.c
@@ -77,6 +77,7 @@ int vddk_debug_datapath = 1;
static void *dl; /* dlopen handle */
static bool init_called; /* was InitEx called */
static __thread int error_suppression; /* threadlocal error suppression */
+static int library_version; /* VDDK major: 5, 6, 7, ... */
static enum { NONE = 0, ZLIB, FASTLZ, SKIPZ } compression; /* compression */
static char *config; /* config */
@@ -297,7 +298,10 @@ vddk_config (const char *key, const char *value)
static void
load_library (bool load_error_is_fatal)
{
- static const char *sonames[] = {
+ static struct {
+ const char *soname;
+ int library_version;
+ } libs[] = {
/* Prefer the newest library in case multiple exist. Check two
* possible directories: the usual VDDK installation puts .so
* files in an arch-specific subdirectory of $libdir (our minimum
@@ -305,12 +309,13 @@ load_library (bool load_error_is_fatal)
* but our testsuite is easier to write if we point libdir
* directly to a stub .so.
*/
- "lib64/libvixDiskLib.so.7",
- "libvixDiskLib.so.7",
- "lib64/libvixDiskLib.so.6",
- "libvixDiskLib.so.6",
- "lib64/libvixDiskLib.so.5",
- "libvixDiskLib.so.5",
+ { "lib64/libvixDiskLib.so.7", 7 },
+ { "libvixDiskLib.so.7", 7 },
+ { "lib64/libvixDiskLib.so.6", 6 },
+ { "libvixDiskLib.so.6", 6 },
+ { "lib64/libvixDiskLib.so.5", 5 },
+ { "libvixDiskLib.so.5", 5 },
+ { NULL }
};
size_t i;
CLEANUP_FREE char *orig_error = NULL;
@@ -323,19 +328,20 @@ load_library (bool load_error_is_fatal)
}
}
- for (i = 0; i < sizeof sonames / sizeof sonames[0]; ++i) {
+ for (i = 0; libs[i].soname != NULL; ++i) {
CLEANUP_FREE char *path;
/* Set the full path so that dlopen will preferentially load the
* system libraries from the same directory.
*/
- if (asprintf (&path, "%s/%s", libdir, sonames[i]) == -1) {
+ if (asprintf (&path, "%s/%s", libdir, libs[i].soname) == -1) {
nbdkit_error ("asprintf: %m");
exit (EXIT_FAILURE);
}
dl = dlopen (path, RTLD_NOW);
if (dl != NULL) {
+ library_version = libs[i].library_version;
/* Now that we found the library, ensure that LD_LIBRARY_PATH
* includes its directory for all future loads. This may modify
* path in-place and/or re-exec nbdkit, but that's okay.
@@ -356,10 +362,12 @@ load_library (bool load_error_is_fatal)
"If '%s' is located on a non-standard path you may need to\n"
"set libdir=/path/to/vmware-vix-disklib-distrib.\n\n"
"See nbdkit-vddk-plugin(1) man page section \"LIBRARY LOCATION\" for details.",
- orig_error ? : "(unknown error)", sonames[0]);
+ orig_error ? : "(unknown error)", libs[0].soname);
exit (EXIT_FAILURE);
}
+ assert (library_version >= 5);
+
/* Load symbols. */
#define STUB(fn,ret,args) \
do { \
@@ -474,6 +482,7 @@ vddk_dump_plugin (void)
printf ("vddk_default_libdir=%s\n", VDDK_LIBDIR);
printf ("vddk_has_nfchostport=1\n");
+ printf ("vddk_library_version=%d\n", library_version);
#if defined(HAVE_DLADDR)
/* It would be nice to print the version of VDDK from the shared
diff --git a/tests/test-vddk-real-dump-plugin.sh b/tests/test-vddk-real-dump-plugin.sh
index 1479e416..59c79693 100755
--- a/tests/test-vddk-real-dump-plugin.sh
+++ b/tests/test-vddk-real-dump-plugin.sh
@@ -51,10 +51,12 @@ rm -f $files
cleanup_fn rm -f $files
nbdkit -f -v vddk libdir="$vddkdir" --dump-plugin > $out
+cat $out
# Check the vddk_* entries are set.
grep ^vddk_default_libdir= $out
grep ^vddk_has_nfchostport= $out
+grep ^vddk_library_version= $out
grep ^vddk_dll= $out
dll="$(grep ^vddk_dll $out | cut -d= -f2)"
--
2.31.1

View File

@ -1,55 +0,0 @@
From b8b376cf39d97c9f523a9867612126088b43c523 Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Sat, 23 Oct 2021 19:50:52 +0100
Subject: [PATCH] vddk: Only print vddk_library_version when we managed to load
the library
Because --dump-plugin calls load_library (false) it won't fail if we
didn't manage to load the library. This results in library_version
being 0, which we printed incorrectly.
Resolve this problem by not printing the vddk_library_version entry in
this case.
Fixes: commit 8700649d147948897f3b97810a1dff37924bdd6e
(cherry picked from commit a3fba12c3e9c2113009f556360ae0bd04c45f6bb)
---
plugins/vddk/nbdkit-vddk-plugin.pod | 1 +
plugins/vddk/vddk.c | 9 ++++++++-
2 files changed, 9 insertions(+), 1 deletion(-)
diff --git a/plugins/vddk/nbdkit-vddk-plugin.pod b/plugins/vddk/nbdkit-vddk-plugin.pod
index 822b96be..c56faddc 100644
--- a/plugins/vddk/nbdkit-vddk-plugin.pod
+++ b/plugins/vddk/nbdkit-vddk-plugin.pod
@@ -420,6 +420,7 @@ by this build.
=item C<vddk_library_version=...>
The VDDK major library version: 5, 6, 7, ...
+If this is omitted it means the library could not be loaded.
=item C<vddk_dll=...>
diff --git a/plugins/vddk/vddk.c b/plugins/vddk/vddk.c
index 291283f4..96615749 100644
--- a/plugins/vddk/vddk.c
+++ b/plugins/vddk/vddk.c
@@ -482,7 +482,14 @@ vddk_dump_plugin (void)
printf ("vddk_default_libdir=%s\n", VDDK_LIBDIR);
printf ("vddk_has_nfchostport=1\n");
- printf ("vddk_library_version=%d\n", library_version);
+
+ /* Because load_library (false) we might not have loaded VDDK, in
+ * which case we didn't set library_version. Note this cannot
+ * happen in the normal (non-debug-plugin) path because there we use
+ * load_library (true).
+ */
+ if (library_version > 0)
+ printf ("vddk_library_version=%d\n", library_version);
#if defined(HAVE_DLADDR)
/* It would be nice to print the version of VDDK from the shared
--
2.31.1

View File

@ -1,53 +0,0 @@
From e850f65053d89ad54c27280f48506da5eb631a68 Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Fri, 18 Nov 2022 09:43:19 +0000
Subject: [PATCH] vddk: Add support for VDDK 8.0.0
There are no changes in any of the structures or enums that we rely on.
Reported-by: Ming Xie
Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=2143889
(cherry picked from commit dbe12ed499baeea94d603db55cad9e971e0ebcf0)
---
plugins/vddk/nbdkit-vddk-plugin.pod | 2 +-
plugins/vddk/vddk.c | 4 +++-
2 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/plugins/vddk/nbdkit-vddk-plugin.pod b/plugins/vddk/nbdkit-vddk-plugin.pod
index c56faddc..c94c41eb 100644
--- a/plugins/vddk/nbdkit-vddk-plugin.pod
+++ b/plugins/vddk/nbdkit-vddk-plugin.pod
@@ -419,7 +419,7 @@ by this build.
=item C<vddk_library_version=...>
-The VDDK major library version: 5, 6, 7, ...
+The VDDK major library version: 5, 6, 7, 8, ...
If this is omitted it means the library could not be loaded.
=item C<vddk_dll=...>
diff --git a/plugins/vddk/vddk.c b/plugins/vddk/vddk.c
index 96615749..2140789a 100644
--- a/plugins/vddk/vddk.c
+++ b/plugins/vddk/vddk.c
@@ -77,7 +77,7 @@ int vddk_debug_datapath = 1;
static void *dl; /* dlopen handle */
static bool init_called; /* was InitEx called */
static __thread int error_suppression; /* threadlocal error suppression */
-static int library_version; /* VDDK major: 5, 6, 7, ... */
+static int library_version; /* VDDK major: 5, 6, 7, 8, ... */
static enum { NONE = 0, ZLIB, FASTLZ, SKIPZ } compression; /* compression */
static char *config; /* config */
@@ -309,6 +309,8 @@ load_library (bool load_error_is_fatal)
* but our testsuite is easier to write if we point libdir
* directly to a stub .so.
*/
+ { "lib64/libvixDiskLib.so.8", 8 },
+ { "libvixDiskLib.so.8", 8 },
{ "lib64/libvixDiskLib.so.7", 7 },
{ "libvixDiskLib.so.7", 7 },
{ "lib64/libvixDiskLib.so.6", 6 },
--
2.31.1

View File

@ -1,17 +0,0 @@
-----BEGIN PGP SIGNATURE-----
iQJFBAABCAAvFiEE93dPsa0HSn6Mh2fqkXOPc+G3aKAFAl/3RBgRHHJpY2hAYW5u
ZXhpYS5vcmcACgkQkXOPc+G3aKBIIRAAmgoGrmJ8aYO7z+kKgNFjd/p0QxRTZhS/
ol59ojG6jIzN2x/C2PFbRmPB6HJTEg4anrDX04WrP6R+lID1RrH9pTFQabv0YDQC
z49oeXAqINYHvAqgFUJCwlymd7BHEYUudLlK3yu7gQKxMM+J/2v0glpxrtLM7KlD
vvSZkVfbvHlCWIbMWLWIaRHeoWZIXNOjsAp3uEWN2YgikDoxbXVKoh07JoQx5tJ5
2U+a/zo4BQuRspjnhmWc252ZF/8d954/L8J+2mKvbRRf2iAmsqPgS+MNi7WKWO4K
w7/urKn0osuOaArs5xYHJnApmJ9U88CzZpoHQkYhcGgnDOipW9ByJRzT41vVQPW5
IluQODpZUuawWtRIwV/Eoi+LaV2gINAL48Afr02UFYj4gmYQ5TeayLP7NKRQO0VL
jwL4Z3a0cDyUX4i1OArn2ll8THfiog38HfLb70AG1l3P1BVoVVBYWCYbs4xgC9IK
LWkjPKuGXvkGVfZi0nCGdPTOoB1CqCXUvKHXm52FCHg12uJMrBQEivodBoCTbtl0
fSjULQcfrovUEb4d/rDAX7EgJbFS+1jDnodaFHsmNToo3CqfkMBdhLkxG3XExwjy
OOR34wZssjTLsLlWH/RPucWD25RDy1vdPBska9QvvO7W0p+aOtFbnttkTh5cqs45
rHg/sDEiaLA=
=OrsS
-----END PGP SIGNATURE-----

File diff suppressed because it is too large Load Diff

View File

@ -6,7 +6,7 @@ set -e
# directory. Use it like this:
# ./copy-patches.sh
rhel_version=8.8
rhel_version=9.6
# Check we're in the right directory.
if [ ! -f nbdkit.spec ]; then

6
gating.yaml Executable file
View File

@ -0,0 +1,6 @@
--- !Policy
product_versions:
- rhel-9
decision_context: osci_compose_gate
rules:
- !PassingTestCaseRule {test_case_name: osci.brew-build.tier0.functional}

BIN
libguestfs.keyring Normal file

Binary file not shown.

23
nbdkit-find-provides Executable file
View File

@ -0,0 +1,23 @@
#!/bin/bash -
# Generate RPM provides automatically for nbdkit packages and filters.
# Copyright (C) 2009-2022 Red Hat Inc.
# To test:
# find /usr/lib64/nbdkit/plugins | ./nbdkit-find-provides VER REL
# find /usr/lib64/nbdkit/filters | ./nbdkit-find-provides VER REL
ver="$1"
rel="$2"
function process_file
{
if [[ $1 =~ /plugins/nbdkit-.*-plugin ]] ||
[[ $1 =~ /filters/nbdkit-.*-filter ]]; then
echo "Provides:" "$(basename $1 .so)" "=" "$ver-$rel"
fi
}
while read line; do
process_file "$line"
done

3
nbdkit.attr Normal file
View File

@ -0,0 +1,3 @@
%__nbdkit_provides %{_rpmconfigdir}/nbdkit-find-provides %{version} %{release}
%__nbdkit_path %{_libdir}/nbdkit/(plugins|filters)/nbdkit-.*-(plugin|filter)(\.so)?$
%__nbdkit_flags exeonly

3
nbdkit.fc Normal file
View File

@ -0,0 +1,3 @@
/usr/sbin/nbdkit -- gen_context(system_u:object_r:nbdkit_exec_t,s0)
/usr/lib/systemd/system/nbdkit.* gen_context(system_u:object_r:nbdkit_unit_file_t,s0)

207
nbdkit.if Normal file
View File

@ -0,0 +1,207 @@
## <summary>policy for nbdkit</summary>
########################################
## <summary>
## Execute nbdkit_exec_t in the nbdkit domain.
## </summary>
## <param name="domain">
## <summary>
## Domain allowed to transition.
## </summary>
## </param>
#
interface(`nbdkit_domtrans',`
gen_require(`
type nbdkit_t, nbdkit_exec_t;
')
corecmd_search_bin($1)
domtrans_pattern($1, nbdkit_exec_t, nbdkit_t)
')
######################################
## <summary>
## Execute nbdkit in the caller domain.
## </summary>
## <param name="domain">
## <summary>
## Domain allowed access.
## </summary>
## </param>
#
interface(`nbdkit_exec',`
gen_require(`
type nbdkit_exec_t;
')
corecmd_search_bin($1)
can_exec($1, nbdkit_exec_t)
')
########################################
## <summary>
## Execute nbdkit in the nbdkit domain, and
## allow the specified role the nbdkit domain.
## </summary>
## <param name="domain">
## <summary>
## Domain allowed to transition
## </summary>
## </param>
## <param name="role">
## <summary>
## The role to be allowed the nbdkit domain.
## </summary>
## </param>
#
interface(`nbdkit_run',`
gen_require(`
type nbdkit_t;
attribute_role nbdkit_roles;
')
nbdkit_domtrans($1)
roleattribute $2 nbdkit_roles;
')
########################################
## <summary>
## Role access for nbdkit
## </summary>
## <param name="role">
## <summary>
## Role allowed access
## </summary>
## </param>
## <param name="domain">
## <summary>
## User domain for the role
## </summary>
## </param>
#
interface(`nbdkit_role',`
gen_require(`
type nbdkit_t;
attribute_role nbdkit_roles;
')
roleattribute $1 nbdkit_roles;
nbdkit_domtrans($2)
ps_process_pattern($2, nbdkit_t)
allow $2 nbdkit_t:process { signull signal sigkill };
')
########################################
## <summary>
## Allow attempts to connect to nbdkit
## with a unix stream socket.
## </summary>
## <param name="domain">
## <summary>
## Domain to not audit.
## </summary>
## </param>
#
interface(`nbdkit_stream_connect',`
gen_require(`
type nbdkit_t;
')
allow $1 nbdkit_t:unix_stream_socket connectto;
')
########################################
## <summary>
## Allow nbdkit_exec_t to be an entrypoint
## of the specified domain
## </summary>
## <param name="domain">
## <summary>
## Domain allowed access.
## </summary>
## </param>
## <rolecap/>
#
interface(`nbdkit_entrypoint',`
gen_require(`
type nbdkit_exec_t;
')
allow $1 nbdkit_exec_t:file entrypoint;
')
# ----------------------------------------------------------------------
# RWMJ: See:
# https://issues.redhat.com/browse/RHEL-5174?focusedId=23387259&page=com.atlassian.jira.plugin.system.issuetabpanels%3Acomment-tabpanel#comment-23387259
# Remove this when virt.if gets updated.
########################################
#
# Interface compatibility blocks
#
# The following definitions ensure compatibility with distribution policy
# versions that do not contain given interfaces (epel, or older Fedora
# releases).
# Each block tests for existence of given interface and defines it if needed.
#
########################################
## <summary>
## Read and write to svirt_image dirs.
## </summary>
## <param name="domain">
## <summary>
## Domain allowed access.
## </summary>
## </param>
#
ifndef(`virt_rw_svirt_image_dirs',`
interface(`virt_rw_svirt_image_dirs',`
gen_require(`
type svirt_image_t;
')
allow $1 svirt_image_t:dir rw_dir_perms;
')
')
########################################
## <summary>
## Create svirt_image sock_files.
## </summary>
## <param name="domain">
## <summary>
## Domain allowed access.
## </summary>
## </param>
#
ifndef(`virt_create_svirt_image_sock_files',`
interface(`virt_create_svirt_image_sock_files',`
gen_require(`
type svirt_image_t;
')
allow $1 svirt_image_t:sock_file create_sock_file_perms;
')
')
########################################
## <summary>
## Read and write virtlogd pipes.
## </summary>
## <param name="domain">
## <summary>
## Domain allowed access.
## </summary>
## </param>
#
ifndef(`virtlogd_rw_pipes',`
interface(`virtlogd_rw_pipes',`
gen_require(`
type virtlogd_t;
')
allow $1 virtlogd_t:fifo_file rw_fifo_file_perms;
')
')

2670
nbdkit.spec Normal file

File diff suppressed because it is too large Load Diff

100
nbdkit.te Normal file
View File

@ -0,0 +1,100 @@
policy_module(nbdkit, 1.0.0)
########################################
#
# Declarations
#
gen_require(`
type unconfined_t;
')
type nbdkit_t;
type nbdkit_exec_t;
application_domain(nbdkit_t, nbdkit_exec_t)
mcs_constrained(nbdkit_t)
role system_r types nbdkit_t;
type nbdkit_home_t;
userdom_user_home_content(nbdkit_home_t)
type nbdkit_tmp_t;
files_tmp_file(nbdkit_tmp_t)
type nbdkit_unit_file_t;
systemd_unit_file(nbdkit_unit_file_t)
permissive nbdkit_t;
########################################
#
# nbdkit local policy
#
allow nbdkit_t self:capability { setgid setuid };
allow nbdkit_t self:fifo_file rw_fifo_file_perms;
allow nbdkit_t self:netlink_route_socket rw_netlink_socket_perms;
allow nbdkit_t self:process { fork setsockcreate signal_perms };
allow nbdkit_t self:tcp_socket create_stream_socket_perms;
allow nbdkit_t self:udp_socket create_socket_perms;
manage_dirs_pattern(nbdkit_t, nbdkit_tmp_t, nbdkit_tmp_t)
manage_files_pattern(nbdkit_t, nbdkit_tmp_t, nbdkit_tmp_t)
userdom_user_tmp_filetrans(nbdkit_t, nbdkit_tmp_t, { dir file })
manage_dirs_pattern(nbdkit_t, nbdkit_home_t, nbdkit_home_t)
manage_files_pattern(nbdkit_t, nbdkit_home_t, nbdkit_home_t)
userdom_user_home_dir_filetrans(nbdkit_t, nbdkit_home_t, { dir file })
corenet_tcp_connect_http_port(nbdkit_t)
corenet_tcp_connect_ssh_port(nbdkit_t)
corenet_tcp_connect_tftp_port(nbdkit_t)
corenet_tcp_bind_generic_port(nbdkit_t)
corenet_tcp_bind_generic_node(nbdkit_t)
domain_use_interactive_fds(nbdkit_t)
files_read_etc_files(nbdkit_t)
init_abstract_socket_activation(nbdkit_t)
init_ioctl_stream_sockets(nbdkit_t)
init_rw_stream_sockets(nbdkit_t)
optional_policy(`
auth_use_nsswitch(nbdkit_t)
')
optional_policy(`
logging_send_syslog_msg(nbdkit_t)
')
optional_policy(`
miscfiles_read_localization(nbdkit_t)
miscfiles_read_generic_certs(nbdkit_t)
')
optional_policy(`
sysnet_dns_name_resolve(nbdkit_t)
sysnet_read_config(nbdkit_t)
')
optional_policy(`
userdom_read_user_home_content_files(nbdkit_t)
userdom_use_inherited_user_ptys(nbdkit_t)
')
optional_policy(`
virt_create_svirt_image_sock_files(nbdkit_t)
virt_read_qemu_pid_files(nbdkit_t)
virtlogd_rw_pipes(nbdkit_t)
virt_rw_svirt_image(nbdkit_t)
virt_rw_svirt_image_dirs(nbdkit_t)
virt_search_lib(nbdkit_t)
virt_stream_connect_svirt(nbdkit_t)
')
# FIXME: It would be nice to allow libvirt to transition nbdkit_exec_t to
# nbdkit_t when libvirtd was started manually from the commandline (i.e. in
# unconfined_t), but we don't want this transition to happen automatically
# when starting directly from the shell. I'm not sure how to achieve this...
#nbdkit_domtrans(unconfined_t, nbdkit_exec_t, nbdkit_t)

2
sources Normal file
View File

@ -0,0 +1,2 @@
SHA512 (nbdkit-1.38.5.tar.gz) = 86e3160e46f8a571e2d18378987066abb3365aea76db4610b478b7d29bf510f1114132a23c149e7a211920be42274606aa05a42e15576a97915582d07077bc4e
SHA512 (nbdkit-1.38.5.tar.gz.sig) = 3be02420dae81472892980ea35087c23838321766cbe3e2b77238fbd9a2be79538c8d92f1ee471c2ee9983b56f19e59385962e6bd79b5c9efc072f7e1c682c49

6
tests/basic-test.sh Executable file
View File

@ -0,0 +1,6 @@
#!/bin/bash -
set -e
set -x
# Run nbdkit and check that nbdinfo can connect back to it.
nbdkit -U - memory 1G --run 'nbdinfo "$uri"'

12
tests/tests.yml Executable file
View File

@ -0,0 +1,12 @@
- hosts: localhost
roles:
- role: standard-test-basic
tags:
- classic
required_packages:
- libnbd
- nbdkit
tests:
- simple:
dir: .
run: ./basic-test.sh