The branch stable/14 has been updated by ronald:

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

commit 9d80d681ee9ddfb7a403924c877eac26d12e9077
Author:     Ronald Klop <ron...@freebsd.org>
AuthorDate: 2025-02-06 21:50:46 +0000
Commit:     Ronald Klop <ron...@freebsd.org>
CommitDate: 2025-07-13 11:44:35 +0000

    swapon: parse md.eli device for encrypted swapfile from fstab
    
    Summary:
    Although fstab(5) suggests usage of md(4) and an .eli suffix in the same
    paragraph, the combination did not work.
    This patch adds a bit of parsing, creates the md device and then passes
    that device to the *_geli function.
    
    Add unit tests.
    
    PR:     186252
    Approved by:    delphij
    MFC after:      2 weeks
    Relnotes:       yes
    Differential Revision:  https://reviews.freebsd.org/D48874
    
    (cherry picked from commit 1ee33e3a578c35ff0e8ef5db87a8005f1f99546a)
---
 etc/mtree/BSD.tests.dist         |   2 +
 sbin/swapon/Makefile             |   5 ++
 sbin/swapon/swapon.c             |  50 ++++++++---
 sbin/swapon/tests/Makefile       |   5 ++
 sbin/swapon/tests/swapon_test.sh | 181 +++++++++++++++++++++++++++++++++++++++
 5 files changed, 233 insertions(+), 10 deletions(-)

diff --git a/etc/mtree/BSD.tests.dist b/etc/mtree/BSD.tests.dist
index 4e014025f623..f29fad1395f8 100644
--- a/etc/mtree/BSD.tests.dist
+++ b/etc/mtree/BSD.tests.dist
@@ -481,6 +481,8 @@
         ..
         savecore
         ..
+        swapon
+        ..
         sysctl
         ..
     ..
diff --git a/sbin/swapon/Makefile b/sbin/swapon/Makefile
index 4cca18367c1e..7696fc51b463 100644
--- a/sbin/swapon/Makefile
+++ b/sbin/swapon/Makefile
@@ -10,4 +10,9 @@ MLINKS+=swapon.8 swapctl.8
 
 LIBADD=        util
 
+.include <src.opts.mk>
+
+HAS_TESTS=
+SUBDIR.${MK_TESTS}+= tests
+
 .include <bsd.prog.mk>
diff --git a/sbin/swapon/swapon.c b/sbin/swapon/swapon.c
index b9b865c0fc09..f7ec26decb1d 100644
--- a/sbin/swapon/swapon.c
+++ b/sbin/swapon/swapon.c
@@ -66,6 +66,8 @@ static char sccsid[] = "@(#)swapon.c  8.1 (Berkeley) 6/5/93";
 #include <string.h>
 #include <unistd.h>
 
+#define DOT_ELI ".eli"
+
 static void usage(void) __dead2;
 static const char *swap_on_off(const char *, int, char *);
 static const char *swap_on_off_gbde(const char *, int);
@@ -243,8 +245,11 @@ swap_on_off(const char *name, int doingall, char *mntops)
            (fnmatch(_PATH_DEV MD_NAME "[0-9]*", name, 0) == 0 ||
             fnmatch(MD_NAME "[0-9]*", name, 0) == 0 ||
             strncmp(_PATH_DEV MD_NAME, name,
-               sizeof(_PATH_DEV) + sizeof(MD_NAME)) == 0 ||
-            strncmp(MD_NAME, name, sizeof(MD_NAME)) == 0))
+               sizeof(_PATH_DEV MD_NAME)) == 0 ||
+            strncmp(MD_NAME, name, sizeof(MD_NAME)) == 0 ||
+            strncmp(_PATH_DEV MD_NAME DOT_ELI, name,
+               sizeof(_PATH_DEV MD_NAME DOT_ELI)) == 0 ||
+            strncmp(MD_NAME DOT_ELI, name, sizeof(MD_NAME DOT_ELI)) == 0))
                return (swap_on_off_md(name, mntops, doingall));
 
        basebuf = strdup(name);
@@ -257,7 +262,7 @@ swap_on_off(const char *name, int doingall, char *mntops)
        }
 
        /* Swap on encrypted device by GEOM_ELI. */
-       if (fnmatch("*.eli", base, 0) == 0) {
+       if (fnmatch("*" DOT_ELI, base, 0) == 0) {
                free(basebuf);
                return (swap_on_off_geli(name, mntops, doingall));
        }
@@ -399,6 +404,8 @@ swap_on_geli_args(const char *mntops)
                                        return (NULL);
                                }
                                Tflag = " -T ";
+                       } else if ((p = strstr(token, "file=")) == token) {
+                               /* ignore known option */
                        } else if (strcmp(token, "late") == 0) {
                                /* ignore known option */
                        } else if (strcmp(token, "noauto") == 0) {
@@ -488,24 +495,38 @@ swap_on_off_md(const char *name, char *mntops, int 
doingall)
        char *p, *vnodefile;
        size_t linelen;
        u_long ul;
+       const char *suffix;
+       char *devbuf, *dname;
+       int name_len;
 
        fd = -1;
        sfd = NULL;
-       if (strlen(name) == (sizeof(MD_NAME) - 1))
+       devbuf = strdup(name);
+       name_len = strlen(name) - strlen(DOT_ELI);
+       if (name_len > 0 && strcmp(suffix = &name[name_len], DOT_ELI) == 0) {
+               suffix++;
+               devbuf[name_len] = '\0';
+       } else
+               suffix = NULL;
+       /* dname will be name without /dev/ prefix and .eli suffix */
+       dname = basename(devbuf);
+       if (strlen(dname) == (sizeof(MD_NAME) - 1))
                mdunit = -1;
        else {
                errno = 0;
-               ul = strtoul(name + 2, &p, 10);
+               ul = strtoul(dname + 2, &p, 10);
                if (errno == 0) {
                        if (*p != '\0' || ul > INT_MAX)
                                errno = EINVAL;
                }
                if (errno) {
-                       warn("Bad device unit: %s", name);
+                       warn("Bad device unit: %s", dname);
+                       free(devbuf);
                        return (NULL);
                }
                mdunit = (int)ul;
        }
+       free(devbuf);
 
        vnodefile = NULL;
        if ((p = strstr(mntops, "file=")) != NULL) {
@@ -645,10 +666,19 @@ swap_on_off_md(const char *name, char *mntops, int 
doingall)
                        }
                }
        }
-       snprintf(mdpath, sizeof(mdpath), "%s%s%d", _PATH_DEV,
-           MD_NAME, mdunit);
-       mdpath[sizeof(mdpath) - 1] = '\0';
-       ret = swap_on_off_sfile(mdpath, doingall);
+
+       if (suffix != NULL && strcmp("eli", suffix) == 0) {
+               /* Swap on encrypted device by GEOM_ELI. */
+               snprintf(mdpath, sizeof(mdpath), "%s%s%d" DOT_ELI, _PATH_DEV,
+                   MD_NAME, mdunit);
+               mdpath[sizeof(mdpath) - 1] = '\0';
+               ret = swap_on_off_geli(mdpath, mntops, doingall);
+       } else {
+               snprintf(mdpath, sizeof(mdpath), "%s%s%d", _PATH_DEV,
+                   MD_NAME, mdunit);
+               mdpath[sizeof(mdpath) - 1] = '\0';
+               ret = swap_on_off_sfile(mdpath, doingall);
+       }
 
        if (which_prog == SWAPOFF) {
                if (ret != NULL) {
diff --git a/sbin/swapon/tests/Makefile b/sbin/swapon/tests/Makefile
new file mode 100644
index 000000000000..aa0c9cf202d6
--- /dev/null
+++ b/sbin/swapon/tests/Makefile
@@ -0,0 +1,5 @@
+ATF_TESTS_SH=  swapon_test
+
+TEST_METADATA.swapon_test+=    required_user="root"
+
+.include <bsd.test.mk>
diff --git a/sbin/swapon/tests/swapon_test.sh b/sbin/swapon/tests/swapon_test.sh
new file mode 100755
index 000000000000..3c4286cd6815
--- /dev/null
+++ b/sbin/swapon/tests/swapon_test.sh
@@ -0,0 +1,181 @@
+# Copyright (c) 2025 Ronald Klop <ron...@freebsd.org>
+#
+# 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.
+#
+#
+
+atf_test_case attach_mdX cleanup
+attach_mdX_head()
+{
+       atf_set "descr" "mdX device should attach"
+}
+attach_mdX_body()
+{
+       # if the swapfile is too small (like 1k) then mdconfig hangs looking up 
the md
+       atf_check -s exit:0 -x "truncate -s 10k swapfile"
+       atf_check -s exit:0 -o save:fstab.out -x "echo 'md3    none    swap    
sw,file=swapfile  0       0'"
+       atf_check -s exit:0 -o match:"swapon: adding /dev/md3 as swap device" 
-x "swapon -F fstab.out -a"
+}
+attach_mdX_cleanup()
+{
+       swapoff -F fstab.out -a
+}
+
+###
+atf_test_case attach_dev_mdX cleanup
+attach_dev_mdX_head()
+{
+       atf_set "descr" "/dev/mdX device should attach"
+}
+attach_dev_mdX_body()
+{
+       # if the swapfile is too small (like 1k) then mdconfig hangs looking up 
the md
+       atf_check -s exit:0 -x "truncate -s 10k swapfile"
+       atf_check -s exit:0 -o save:fstab.out -x "echo '/dev/md3    none    
swap    sw,file=swapfile  0       0'"
+       atf_check -s exit:0 -o match:"swapon: adding /dev/md3 as swap device" 
-x "swapon -F fstab.out -a"
+}
+attach_dev_mdX_cleanup()
+{
+       swapoff -F fstab.out -a
+}
+
+###
+atf_test_case attach_md cleanup
+attach_md_head()
+{
+       atf_set "descr" "mdX device should attach"
+}
+attach_md_body()
+{
+       # if the swapfile is too small (like 1k) then mdconfig hangs looking up 
the md
+       atf_check -s exit:0 -x "truncate -s 10k swapfile"
+       atf_check -s exit:0 -o save:fstab.out -x "echo 'md    none    swap    
sw,file=swapfile  0       0'"
+       atf_check -s exit:0 -o match:"swapon: adding /dev/md0 as swap device" 
-x "swapon -F fstab.out -a"
+}
+attach_md_cleanup()
+{
+       swapoff -F fstab.out -a
+}
+
+###
+atf_test_case attach_dev_md cleanup
+attach_dev_md_head()
+{
+       atf_set "descr" "/dev/md device should attach"
+}
+attach_dev_md_body()
+{
+       # if the swapfile is too small (like 1k) then mdconfig hangs looking up 
the md
+       atf_check -s exit:0 -x "truncate -s 10k swapfile"
+       atf_check -s exit:0 -o save:fstab.out -x "echo '/dev/md    none    swap 
   sw,file=swapfile  0       0'"
+       atf_check -s exit:0 -o match:"swapon: adding /dev/md0 as swap device" 
-x "swapon -F fstab.out -a"
+}
+attach_dev_md_cleanup()
+{
+       swapoff -F fstab.out -a
+}
+
+###
+atf_test_case attach_mdX_eli cleanup
+attach_mdX_eli_head()
+{
+       atf_set "descr" "mdX.eli device should attach"
+}
+attach_mdX_eli_body()
+{
+       # if the swapfile is too small (like 1k) then mdconfig hangs looking up 
the md
+       atf_check -s exit:0 -x "truncate -s 10k swapfile"
+       atf_check -s exit:0 -o save:fstab.out -x "echo 'md3.eli    none    swap 
   sw,file=swapfile  0       0'"
+       atf_check -s exit:0 -o match:"swapon: adding /dev/md3.eli as swap 
device" -x "swapon -F fstab.out -a"
+}
+attach_mdX_eli_cleanup()
+{
+       swapoff -F fstab.out -a
+}
+
+###
+atf_test_case attach_dev_mdX_eli cleanup
+attach_dev_mdX_eli_head()
+{
+       atf_set "descr" "/dev/mdX.eli device should attach"
+}
+attach_dev_mdX_eli_body()
+{
+       # if the swapfile is too small (like 1k) then mdconfig hangs looking up 
the md
+       atf_check -s exit:0 -x "truncate -s 10k swapfile"
+       atf_check -s exit:0 -o save:fstab.out -x "echo '/dev/md3.eli    none    
swap    sw,file=swapfile  0       0'"
+       atf_check -s exit:0 -o match:"swapon: adding /dev/md3.eli as swap 
device" -x "swapon -F fstab.out -a"
+}
+attach_dev_mdX_eli_cleanup()
+{
+       swapoff -F fstab.out -a
+}
+
+###
+atf_test_case attach_md_eli cleanup
+attach_md_eli_head()
+{
+       atf_set "descr" "md.eli device should attach"
+}
+attach_md_eli_body()
+{
+       # if the swapfile is too small (like 1k) then mdconfig hangs looking up 
the md
+       atf_check -s exit:0 -x "truncate -s 10k swapfile"
+       atf_check -s exit:0 -o save:fstab.out -x "echo 'md.eli    none    swap  
  sw,file=swapfile  0       0'"
+       atf_check -s exit:0 -o match:"swapon: adding /dev/md0.eli as swap 
device" -x "swapon -F fstab.out -a"
+}
+attach_md_eli_cleanup()
+{
+       swapoff -F fstab.out -a
+}
+
+###
+atf_test_case attach_dev_md_eli cleanup
+attach_dev_md_eli_head()
+{
+       atf_set "descr" "/dev/md.eli device should attach"
+}
+attach_dev_md_eli_body()
+{
+       # if the swapfile is too small (like 1k) then mdconfig hangs looking up 
the md
+       atf_check -s exit:0 -x "truncate -s 10k swapfile"
+       atf_check -s exit:0 -o save:fstab.out -x "echo '/dev/md.eli    none    
swap    sw,file=swapfile  0       0'"
+       atf_check -s exit:0 -o match:"swapon: adding /dev/md0.eli as swap 
device" -x "swapon -F fstab.out -a"
+}
+attach_dev_md_eli_cleanup()
+{
+       swapoff -F fstab.out -a
+}
+
+###
+atf_init_test_cases()
+{
+       atf_add_test_case attach_mdX
+       atf_add_test_case attach_dev_mdX
+       atf_add_test_case attach_md
+       atf_add_test_case attach_dev_md
+
+       atf_add_test_case attach_mdX_eli
+       atf_add_test_case attach_dev_mdX_eli
+       atf_add_test_case attach_md_eli
+       atf_add_test_case attach_dev_md_eli
+}

Reply via email to