diff options
Diffstat (limited to 'sbin/swapon')
-rw-r--r-- | sbin/swapon/Makefile | 7 | ||||
-rw-r--r-- | sbin/swapon/swapon.8 | 2 | ||||
-rw-r--r-- | sbin/swapon/swapon.c | 122 | ||||
-rw-r--r-- | sbin/swapon/tests/Makefile | 5 | ||||
-rwxr-xr-x | sbin/swapon/tests/swapon_test.sh | 225 |
5 files changed, 275 insertions, 86 deletions
diff --git a/sbin/swapon/Makefile b/sbin/swapon/Makefile index 4cca18367c1e..0c034338a533 100644 --- a/sbin/swapon/Makefile +++ b/sbin/swapon/Makefile @@ -1,5 +1,3 @@ -# @(#)Makefile 8.1 (Berkeley) 6/5/93 - PACKAGE=runtime PROG= swapon MAN= swapon.8 @@ -10,4 +8,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.8 b/sbin/swapon/swapon.8 index 64ad9edca776..f5534c06eb9f 100644 --- a/sbin/swapon/swapon.8 +++ b/sbin/swapon/swapon.8 @@ -25,8 +25,6 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.\" @(#)swapon.8 8.1 (Berkeley) 6/5/93 -.\" .Dd November 29, 2021 .Dt SWAPON 8 .Os diff --git a/sbin/swapon/swapon.c b/sbin/swapon/swapon.c index b9b865c0fc09..3dff4df5e63f 100644 --- a/sbin/swapon/swapon.c +++ b/sbin/swapon/swapon.c @@ -29,18 +29,6 @@ * SUCH DAMAGE. */ -#if 0 -#ifndef lint -static const char copyright[] = -"@(#) Copyright (c) 1980, 1993\n\ - The Regents of the University of California. All rights reserved.\n"; -#endif /* not lint */ - -#ifndef lint -static char sccsid[] = "@(#)swapon.c 8.1 (Berkeley) 6/5/93"; -#endif /* not lint */ -#endif -#include <sys/cdefs.h> #include <sys/param.h> #include <sys/disk.h> #include <sys/disklabel.h> @@ -66,9 +54,10 @@ 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); static const char *swap_on_off_geli(const char *, char *, int); static const char *swap_on_off_md(const char *, char *, int); static const char *swap_on_off_sfile(const char *, int); @@ -243,21 +232,18 @@ 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); base = basename(basebuf); - /* Swap on encrypted device by GEOM_BDE. */ - if (fnmatch("*.bde", base, 0) == 0) { - free(basebuf); - return (swap_on_off_gbde(name, doingall)); - } - /* 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)); } @@ -281,59 +267,6 @@ swap_basename(const char *name) return (dname); } -static const char * -swap_on_off_gbde(const char *name, int doingall) -{ - const char *ret; - char pass[64 * 2 + 1]; - unsigned char bpass[64]; - char *dname; - int i, error; - - dname = swap_basename(name); - if (dname == NULL) - return (NULL); - - if (which_prog == SWAPON) { - arc4random_buf(bpass, sizeof(bpass)); - for (i = 0; i < (int)sizeof(bpass); i++) - sprintf(&pass[2 * i], "%02x", bpass[i]); - pass[sizeof(pass) - 1] = '\0'; - - error = run_cmd(NULL, "%s init %s -P %s", _PATH_GBDE, - dname, pass); - if (error) { - /* bde device found. Ignore it. */ - free(dname); - if (qflag == 0) - warnx("%s: Device already in use", name); - return (NULL); - } - error = run_cmd(NULL, "%s attach %s -p %s", _PATH_GBDE, - dname, pass); - free(dname); - if (error) { - warnx("gbde (attach) error: %s", name); - return (NULL); - } - } - - ret = swap_on_off_sfile(name, doingall); - - if (which_prog == SWAPOFF) { - error = run_cmd(NULL, "%s detach %s", _PATH_GBDE, dname); - free(dname); - if (error) { - /* bde device not found. Ignore it. */ - if (qflag == 0) - warnx("%s: Device not found", name); - return (NULL); - } - } - - return (ret); -} - /* Build geli(8) arguments from mntops */ static char * swap_on_geli_args(const char *mntops) @@ -399,6 +332,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 +423,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 +594,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..a04bb36cc49e --- /dev/null +++ b/sbin/swapon/tests/swapon_test.sh @@ -0,0 +1,225 @@ +# Copyright (c) 2025 Ronald Klop <ronald@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 + # but need a swapfile bigger than one page kernel page size + pagesize=$(sysctl -n hw.pagesize) + minsize=$(( pagesize * 2 )) + atf_check -s exit:0 -x "truncate -s $minsize swapfile" + atf_check -s exit:0 -o save:fstab.out -x "echo 'md31 none swap sw,file=swapfile 0 0'" + atf_check -s exit:0 -o match:"swapon: adding /dev/md31 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 + # but need a swapfile bigger than one page kernel page size + pagesize=$(sysctl -n hw.pagesize) + minsize=$(( pagesize * 2 )) + atf_check -s exit:0 -x "truncate -s $minsize swapfile" + atf_check -s exit:0 -o save:fstab.out -x "echo '/dev/md32 none swap sw,file=swapfile 0 0'" + atf_check -s exit:0 -o match:"swapon: adding /dev/md32 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" "md device should attach" +} +attach_md_body() +{ + # if the swapfile is too small (like 1k) then mdconfig hangs looking up the md + # but need a swapfile bigger than one page kernel page size + pagesize=$(sysctl -n hw.pagesize) + minsize=$(( pagesize * 2 )) + atf_check -s exit:0 -x "truncate -s $minsize 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/md[0-9][0-9]* 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 + # but need a swapfile bigger than one page kernel page size + pagesize=$(sysctl -n hw.pagesize) + minsize=$(( pagesize * 2 )) + atf_check -s exit:0 -x "truncate -s $minsize 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/md[0-9][0-9]* 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 + # but need a swapfile bigger than one page kernel page size + pagesize=$(sysctl -n hw.pagesize) + minsize=$(( pagesize * 2 )) + atf_check -s exit:0 -x "truncate -s $minsize swapfile" + atf_check -s exit:0 -o save:fstab.out -x "echo 'md33.eli none swap sw,file=swapfile 0 0'" + atf_check -s exit:0 -o match:"swapon: adding /dev/md33.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 + # but need a swapfile bigger than one page kernel page size + pagesize=$(sysctl -n hw.pagesize) + minsize=$(( pagesize * 2 )) + atf_check -s exit:0 -x "truncate -s $minsize swapfile" + atf_check -s exit:0 -o save:fstab.out -x "echo '/dev/md34.eli none swap sw,file=swapfile 0 0'" + atf_check -s exit:0 -o match:"swapon: adding /dev/md34.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 + # but need a swapfile bigger than one page kernel page size + pagesize=$(sysctl -n hw.pagesize) + minsize=$(( pagesize * 2 )) + atf_check -s exit:0 -x "truncate -s $minsize 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/md[0-9][0-9]*.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 + # but need a swapfile bigger than one page kernel page size + pagesize=$(sysctl -n hw.pagesize) + minsize=$(( pagesize * 2 )) + atf_check -s exit:0 -x "truncate -s $minsize 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/md[0-9][0-9]*.eli as swap device" -x "swapon -F fstab.out -a" +} +attach_dev_md_eli_cleanup() +{ + swapoff -F fstab.out -a +} + +### + +atf_test_case attach_too_small +attach_too_small_head() +{ + atf_set "descr" "should refuse to attach if smaller than one kernel page size" +} +attach_too_small_body() +{ + # Need to use smaller than kernel page size + pagesize=$(sysctl -n hw.pagesize) + minsize=$(( pagesize / 2 )) + atf_check -s exit:0 -x "truncate -s $minsize swapfile" + atf_check -s exit:0 -o save:fstab.out -x "echo 'md35 none swap sw,file=swapfile 0 0'" + atf_check -s exit:1 -e match:"swapon: /dev/md35: NSWAPDEV limit reached" -x "swapon -F fstab.out -a" + atf_check -s exit:0 -x "mdconfig -d -u 35" +} + +### +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 + + atf_add_test_case attach_too_small +} |