The branch stable/13 has been updated by markj:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=c4aae5668c69df4205ab3df382056a71a0e23bb7

commit c4aae5668c69df4205ab3df382056a71a0e23bb7
Author:     Mark Johnston <ma...@freebsd.org>
AuthorDate: 2023-06-12 16:11:20 +0000
Commit:     Mark Johnston <ma...@freebsd.org>
CommitDate: 2023-06-19 12:57:17 +0000

    geli tests: Add a regression test for PR 271766
    
    This test case catches both of the bugs reported there.
    
    PR:             271766
    Reviewed by:    imp
    MFC after:      1 week
    Sponsored by:   The FreeBSD Foundation
    Differential Revision:  https://reviews.freebsd.org/D40469
    
    (cherry picked from commit 9c0467929abaab97f45fc07507b6f30c80211239)
---
 tests/sys/geom/class/eli/Makefile       |   3 +
 tests/sys/geom/class/eli/misc_test.sh   |  38 ++++++++-
 tests/sys/geom/class/eli/unaligned_io.c | 131 ++++++++++++++++++++++++++++++++
 3 files changed, 170 insertions(+), 2 deletions(-)

diff --git a/tests/sys/geom/class/eli/Makefile 
b/tests/sys/geom/class/eli/Makefile
index c7f1342f45ae..bdb1101ef059 100644
--- a/tests/sys/geom/class/eli/Makefile
+++ b/tests/sys/geom/class/eli/Makefile
@@ -37,6 +37,9 @@ SRCS.pbkdf2_test=     \
 
 LIBADD.pbkdf2_test= crypto
 
+PROGS+= unaligned_io
+BINDIR?= ${TESTSDIR}
+
 testvect.h:
        python gentestvect.py > ${.TARGET}
 
diff --git a/tests/sys/geom/class/eli/misc_test.sh 
b/tests/sys/geom/class/eli/misc_test.sh
index 4dc7cb9bf367..420f47f786e6 100644
--- a/tests/sys/geom/class/eli/misc_test.sh
+++ b/tests/sys/geom/class/eli/misc_test.sh
@@ -135,17 +135,51 @@ physpath_cleanup()
        true
 }
 
+unaligned_io_test()
+{
+       cipher=$1
+       secsize=$2
+       ealgo=${cipher%%:*}
+       keylen=${cipher##*:}
+
+       atf_check -s exit:0 -e ignore \
+               geli init -B none -e $ealgo -l $keylen -P -K keyfile \
+               -s $secsize ${md}
+       atf_check geli attach -p -k keyfile ${md}
+
+       atf_check $(atf_get_srcdir)/unaligned_io /dev/${md}.eli
+}
+
+atf_test_case unaligned_io cleanup
+unaligned_io_head()
+{
+       atf_set "descr" "regression test for PR 271766"
+       atf_set "require.user" "root"
+}
+unaligned_io_body()
+{
+       geli_test_setup
+
+       sectors=4
+
+       atf_check dd if=/dev/random of=keyfile bs=512 count=16 status=none
+       for_each_geli_config_nointegrity unaligned_io_test
+}
+unaligned_io_cleanup()
+{
+       geli_test_cleanup
+}
+
 atf_init_test_cases()
 {
        atf_add_test_case physpath
        atf_add_test_case preserve_props
        atf_add_test_case preserve_disk_props
+       atf_add_test_case unaligned_io
 }
 
-
 common_cleanup()
 {
-
        if [ -f "$MD_DEVS" ]; then
                while read test_md; do
                        gnop destroy -f ${test_md}.nop 2>/dev/null
diff --git a/tests/sys/geom/class/eli/unaligned_io.c 
b/tests/sys/geom/class/eli/unaligned_io.c
new file mode 100644
index 000000000000..707d15f40be4
--- /dev/null
+++ b/tests/sys/geom/class/eli/unaligned_io.c
@@ -0,0 +1,131 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2023 The FreeBSD Foundation
+ *
+ * This software was developed by Mark Johnston under sponsorship from
+ * the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 THE AUTHOR 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.
+ */
+
+/*
+ * Idea from a test case by Andrew "RhodiumToad" Gierth in Bugzilla PR 271766.
+ */
+
+#include <sys/param.h>
+#include <sys/disk.h>
+#include <sys/mman.h>
+
+#include <crypto/cryptodev.h>
+
+#include <err.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+int
+main(int argc, char **argv)
+{
+       const char *disk;
+       char *buf1, *buf2;
+       off_t disksz;
+       size_t bufsz, iosz;
+       ssize_t n;
+       unsigned int offsets, secsz;
+       int fd;
+
+       if (argc != 2)
+               errx(1, "Usage: %s <disk>", argv[0]);
+       disk = argv[1];
+
+       fd = open(disk, O_RDWR);
+       if (fd < 0)
+               err(1, "open(%s)", disk);
+
+       if (ioctl(fd, DIOCGSECTORSIZE, &secsz) != 0)
+               err(1, "ioctl(DIOCGSECTORSIZE)");
+       if (secsz == 0)
+               errx(1, "ioctl(DIOCGSECTORSIZE) returned 0");
+       if (ioctl(fd, DIOCGMEDIASIZE, &disksz) != 0)
+               err(1, "ioctl(DIOCGMEDIASIZE)");
+       if (disksz / secsz < 2)
+               errx(1, "disk needs to be at least 2 sectors in size");
+       iosz = 2 * secsz;
+
+       bufsz = iosz + secsz;
+       buf1 = mmap(NULL, bufsz, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE,
+           -1, 0);
+       if (buf1 == MAP_FAILED)
+               err(1, "mmap");
+       buf2 = mmap(NULL, bufsz, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE,
+           -1, 0);
+       if (buf2 == MAP_FAILED)
+               err(1, "mmap");
+
+       arc4random_buf(buf1, bufsz);
+       n = pwrite(fd, buf1, bufsz, 0);
+       if (n < 0 || (size_t)n != bufsz)
+               err(1, "pwrite");
+
+       /*
+        * Limit the number of offsets we test with, to avoid spending too much
+        * time when the sector size is large.
+        */
+       offsets = MAX(EALG_MAX_BLOCK_LEN, HMAC_MAX_BLOCK_LEN) + 1;
+
+       /*
+        * Read test: read the first 2 sectors into buf1, then do the same with
+        * buf2, except at varying offsets into buf2.  After each read, compare
+        * the buffers and make sure they're identical.  This exercises corner
+        * cases in the crypto layer's buffer handling.
+        */
+       n = pread(fd, buf1, iosz, 0);
+       if (n < 0 || (size_t)n != iosz)
+               err(1, "pread");
+       for (unsigned int i = 0; i < offsets; i++) {
+               n = pread(fd, buf2 + i, iosz, 0);
+               if (n < 0 || (size_t)n != iosz)
+                       err(1, "pread");
+               if (memcmp(buf1, buf2 + i, iosz) != 0)
+                       errx(1, "read mismatch at offset %u/%u", i, secsz);
+       }
+
+       /*
+        * Write test.  Try writing buffers at various alignments, and verify
+        * that we read back what we wrote.
+        */
+       arc4random_buf(buf1, bufsz);
+       for (unsigned int i = 0; i < offsets; i++) {
+               n = pwrite(fd, buf1 + i, iosz, 0);
+               if (n < 0 || (size_t)n != iosz)
+                       err(1, "pwrite");
+               n = pread(fd, buf2, iosz, 0);
+               if (n < 0 || (size_t)n != iosz)
+                       err(1, "pread");
+               if (memcmp(buf1 + i, buf2, iosz) != 0)
+                       errx(1, "write mismatch at offset %u/%u", i, secsz);
+       }
+
+       return (0);
+}

Reply via email to