diff --git a/MAINTAINERS b/MAINTAINERS index 8c3c798c256c..ea9bb4195aa1 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1,130 +1,130 @@ Please note that the content of this file is strictly advisory. No locks listed here are valid. The only strict review requirements are granted by core. These are documented in LOCKS and enforced by gitadm@. The source tree is a community effort. However, some folks go to the trouble of looking after particular areas of the tree. In return for their active caretaking of the code it is polite to coordinate changes with them. This is a list of people who have expressed an interest in part of the code or listed their active caretaking role so that other committers can easily find somebody who is familiar with it. The notes should specify if there is a 3rd party source tree involved or other things that should be kept in mind. However, this is not a 'big stick', it is an offer to help and a source of guidance. It does not override the communal nature of the tree. It is not a registry of 'turf' or private property. *** This list is prone to becoming stale quickly. The best way to find the recent maintainer of a sub-system is to check recent logs for that directory or sub-system. *** *** Maintainers are encouraged to visit: https://reviews.freebsd.org/herald and configure notifications for parts of the tree which they maintain. Notifications can automatically be sent when someone proposes a revision or makes a commit to the specified subtree. *** subsystem login notes ----------------------------- aio(4) asomers Pre-commit review requested. ath(4) adrian Pre-commit review requested, send to freebsd-wireless@freebsd.org contrib/atf ngie,#test Pre-commit review requested. contrib/capsicum-test ngie,#capsicum,#test Pre-commit review requested. contrib/googletest ngie,#test Pre-commit review requested. sbin/ipf cy Pre-commit review requested. contrib/libcxxrt dim,emaste Pre-commit review preferred. contrib/llvm-project/compiler-rt dim Pre-commit review preferred. contrib/llvm-project/libcxx dim Pre-commit review preferred. contrib/llvm-project/libunwind dim,emaste,jhb Pre-commit review preferred. contrib/llvm-project/lldb dim,emaste Pre-commit review preferred. contrib/llvm-project/llvm dim Pre-commit review preferred. contrib/llvm-project/openmp dim,emaste Pre-commit review preferred. contrib/netbsd-tests ngie,#test Pre-commit review requested. contrib/pjdfstest asomers,ngie,pjd,#test Pre-commit review requested. *env(3) secteam Due to the problematic security history of this code, please have patches reviewed by secteam. etc/mail gshapiro Pre-commit review requested. Keep in sync with -STABLE. etc/sendmail gshapiro Pre-commit review requested. Keep in sync with -STABLE. fetch des Pre-commit review requested, email only. -fusefs(5) asomers Pre-commit review requested. +fusefs(4) asomers Pre-commit review requested. geli pjd Pre-commit review requested (both sys/geom/eli/ and sbin/geom/class/eli/). iwm(4) adrian Pre-commit review requested, send to freebsd-wireless@freebsd.org iwn(4) adrian Pre-commit review requested, send to freebsd-wireless@freebsd.org kqueue jmg Pre-commit review requested. Documentation Required. libdpv dteske Pre-commit review requested. Keep in sync with dpv(1). libfetch des Pre-commit review requested, email only. libfigpar dteske Pre-commit review requested. libm freebsd-numerics Send email with patches to freebsd-numerics@ libpam des Pre-commit review requested, email only. linprocfs des Pre-commit review requested, email only. lpr gad Pre-commit review requested, particularly for lpd/recvjob.c and lpd/printjob.c. nanobsd imp Pre-commit phabricator review requested. net80211 adrian Pre-commit review requested, send to freebsd-wireless@freebsd.org nfs freebsd-fs@FreeBSD.org, rmacklem is best for reviews. nvd(4) imp Pre-commit review requested. nvme(4) imp Pre-commit review requested. nvmecontrol(8) imp Pre-commit review requested. opencrypto jmg Pre-commit review requested. Documentation Required. openssh des Pre-commit review requested, email only. openssl benl Pre-commit review requested. otus(4) adrian Pre-commit review requested, send to freebsd-wireless@freebsd.org pci bus imp,jhb Pre-commit review requested. pmcstudy(8) rrs Pre-commit review requested. procfs des Pre-commit review requested, email only. pseudofs des Pre-commit review requested, email only. random(4), random(9) csprng Pre-commit discussion and review required, release/release.sh gjb,re Pre-commit review and regression tests requested. sctp rrs,tuexen Pre-commit review requested (changes need to be backported to github). sendmail gshapiro Pre-commit review requested. sh(1) jilles Pre-commit review requested. This also applies to kill(1), printf(1) and test(1) which are compiled in as builtins. share/mk imp, bapt, bdrewery, emaste, sjg Make is hard. share/mk/*.test.mk imp,bapt,bdrewery, Pre-commit review requested. emaste,ngie,sjg,#test stand/forth dteske Pre-commit review requested. stand/lua kevans Pre-commit review requested stand imp Pre-commit review strongly requested. sys/compat/linuxkpi pre-commit review requested via #linuxkpi phabricator group. sys/contrib/dev/ice erj Pre-commit phabricator review requested. sys/netpfil/ipfilter cy Pre-commit review requested. sys/dev/e1000 erj Pre-commit phabricator review requested. sys/dev/ixgbe erj Pre-commit phabricator review requested. sys/dev/ixl erj Pre-commit phabricator review requested. sys/dev/ice erj Pre-commit phabricator review requested. sys/dev/xen royger Pre-commit review recommended. sys/netinet/ip_carp.c glebius Pre-commit review recommended. sys/netpfil/pf kp,glebius Pre-commit review recommended. sys/x86/xen royger Pre-commit review recommended. sys/xen royger Pre-commit review recommended. tests ngie,#test Pre-commit review requested. tools/build imp Pre-commit review requested, especially to fix bootstrap issues. top(1) eadler Pre-commit review requested. usr.sbin/bsdconfig dteske Pre-commit phabricator review requested. usr.sbin/dpv dteske Pre-commit review requested. Keep in sync with libdpv. usr.sbin/pkg pkg@ Please coordinate behavior or flag changes with pkg team. usr.sbin/sysrc dteske Pre-commit phabricator review requested. Keep in sync with bsdconfig(8) sysrc.subr. vmm(4) jhb Pre-commit review requested via #bhyve phabricator group. libvmmapi jhb Pre-commit review requested via #bhyve phabricator group. usr.sbin/bhyve* jhb Pre-commit review requested via #bhyve phabricator group. -autofs(5) trasz Pre-commit review recommended. +autofs(4) trasz Pre-commit review recommended. iscsi(4) trasz Pre-commit review recommended. rctl(8) trasz Pre-commit review recommended. sys/dev/ofw nwhitehorn Pre-commit review recommended. sys/dev/usb/wlan adrian Pre-commit review requested, send to freebsd-wireless@freebsd.org sys/arm/allwinner manu Pre-commit review requested sys/arm64/rockchip manu Pre-commit review requested diff --git a/contrib/netbsd-tests/lib/libc/sys/t_revoke.c b/contrib/netbsd-tests/lib/libc/sys/t_revoke.c index ec225b9be491..73cb9144f680 100644 --- a/contrib/netbsd-tests/lib/libc/sys/t_revoke.c +++ b/contrib/netbsd-tests/lib/libc/sys/t_revoke.c @@ -1,196 +1,196 @@ /* $NetBSD: t_revoke.c,v 1.2 2017/01/13 21:15:57 christos Exp $ */ /*- * Copyright (c) 2011 The NetBSD Foundation, Inc. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation * by Jukka Ruohonen. * * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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. */ #include __RCSID("$NetBSD: t_revoke.c,v 1.2 2017/01/13 21:15:57 christos Exp $"); #include #include #include #include #include #include #include #include #include #include static const char path[] = "revoke"; ATF_TC_WITH_CLEANUP(revoke_basic); ATF_TC_HEAD(revoke_basic, tc) { atf_tc_set_md_var(tc, "descr", "A basic test of revoke(2)"); } ATF_TC_BODY(revoke_basic, tc) { struct rlimit res; char tmp[10]; size_t i, n; int *buf; #ifdef __FreeBSD__ - atf_tc_skip("revoke(2) is only implemented for devfs(5)."); + atf_tc_skip("revoke(2) is only implemented for devfs(4)."); #endif (void)memset(&res, 0, sizeof(struct rlimit)); (void)getrlimit(RLIMIT_NOFILE, &res); if ((n = res.rlim_cur / 10) == 0) n = 10; buf = calloc(n, sizeof(int)); ATF_REQUIRE(buf != NULL); buf[0] = open(path, O_RDWR | O_CREAT, 0600); ATF_REQUIRE(buf[0] >= 0); for (i = 1; i < n; i++) { buf[i] = open(path, O_RDWR); ATF_REQUIRE(buf[i] >= 0); } ATF_REQUIRE(revoke(path) == 0); for (i = 0; i < n; i++) { ATF_REQUIRE(read(buf[i], tmp, sizeof(tmp)) == -1); (void)close(buf[i]); } free(buf); (void)unlink(path); } ATF_TC_CLEANUP(revoke_basic, tc) { (void)unlink(path); } ATF_TC(revoke_err); ATF_TC_HEAD(revoke_err, tc) { atf_tc_set_md_var(tc, "descr", "Test errors from revoke(2)"); atf_tc_set_md_var(tc, "require.user", "unprivileged"); } ATF_TC_BODY(revoke_err, tc) { char buf[1024 + 1]; /* XXX: From the manual page... */ (void)memset(buf, 'x', sizeof(buf)); errno = 0; ATF_REQUIRE_ERRNO(EFAULT, revoke((char *)-1) == -1); errno = 0; ATF_REQUIRE_ERRNO(ENAMETOOLONG, revoke(buf) == -1); #ifdef __FreeBSD__ - atf_tc_skip("revoke(2) is only implemented for devfs(5)."); + atf_tc_skip("revoke(2) is only implemented for devfs(4)."); #endif errno = 0; ATF_REQUIRE_ERRNO(EPERM, revoke("/etc/passwd") == -1); errno = 0; ATF_REQUIRE_ERRNO(ENOENT, revoke("/etc/xxx/yyy") == -1); } ATF_TC_WITH_CLEANUP(revoke_perm); ATF_TC_HEAD(revoke_perm, tc) { atf_tc_set_md_var(tc, "descr", "Test permissions revoke(2)"); atf_tc_set_md_var(tc, "require.user", "root"); } ATF_TC_BODY(revoke_perm, tc) { struct passwd *pw; int fd, sta; pid_t pid; #ifdef __FreeBSD__ - atf_tc_skip("revoke(2) is only implemented for devfs(5)."); + atf_tc_skip("revoke(2) is only implemented for devfs(4)."); #endif pw = getpwnam("nobody"); fd = open(path, O_RDWR | O_CREAT, 0600); ATF_REQUIRE(fd >= 0); ATF_REQUIRE(pw != NULL); ATF_REQUIRE(revoke(path) == 0); pid = fork(); ATF_REQUIRE(pid >= 0); if (pid == 0) { if (setuid(pw->pw_uid) != 0) _exit(EXIT_FAILURE); errno = 0; if (revoke(path) == 0) _exit(EXIT_FAILURE); if (errno != EACCES) _exit(EXIT_FAILURE); if (close(fd) != 0) _exit(EXIT_FAILURE); _exit(EXIT_SUCCESS); } (void)wait(&sta); if (WIFEXITED(sta) == 0 || WEXITSTATUS(sta) != EXIT_SUCCESS) atf_tc_fail("revoke(2) did not obey permissions"); (void)close(fd); ATF_REQUIRE(unlink(path) == 0); } ATF_TC_CLEANUP(revoke_perm, tc) { (void)unlink(path); } ATF_TP_ADD_TCS(tp) { ATF_TP_ADD_TC(tp, revoke_basic); ATF_TP_ADD_TC(tp, revoke_err); ATF_TP_ADD_TC(tp, revoke_perm); return atf_no_error(); } diff --git a/lib/libc/gen/getvfsbyname.c b/lib/libc/gen/getvfsbyname.c index b782e5793334..18cbf64b9f4a 100644 --- a/lib/libc/gen/getvfsbyname.c +++ b/lib/libc/gen/getvfsbyname.c @@ -1,87 +1,87 @@ /*- * SPDX-License-Identifier: BSD-3-Clause * * Copyright (c) 1995 * The Regents of the University of California. All rights reserved. * * 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. * 3. Neither the name of the University 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 THE REGENTS 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 REGENTS 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. */ #include #include #include #include #include #include #include /* - * fusefs(5) file systems may have a "subtype" which gets appended to + * fusefs(4) file systems may have a "subtype" which gets appended to * statfs(2)'s f_fstypename field on a per-mount basis. Allow getvfsbyname to * match either the full "fusefs.foobar" or the more general "fusefs". */ static bool are_fusefs(const char *fsname, const char *vfc_name) { const static char fusefs[] = "fusefs"; const static char fusefs_dot[] = "fusefs."; return (strncmp(fsname, fusefs_dot, sizeof(fusefs_dot) - 1) == 0 && strcmp(fusefs, vfc_name) == 0); } /* * Given a filesystem name, determine if it is resident in the kernel, * and if it is resident, return its xvfsconf structure. */ int getvfsbyname(const char *fsname, struct xvfsconf *vfcp) { struct xvfsconf *xvfsp; size_t buflen; int cnt, i; if (sysctlbyname("vfs.conflist", NULL, &buflen, NULL, 0) < 0) return (-1); xvfsp = malloc(buflen); if (xvfsp == NULL) return (-1); if (sysctlbyname("vfs.conflist", xvfsp, &buflen, NULL, 0) < 0) { free(xvfsp); return (-1); } cnt = buflen / sizeof(struct xvfsconf); for (i = 0; i < cnt; i++) { if (strcmp(fsname, xvfsp[i].vfc_name) == 0 || are_fusefs(fsname, xvfsp[i].vfc_name)) { memcpy(vfcp, xvfsp + i, sizeof(struct xvfsconf)); free(xvfsp); return (0); } } free(xvfsp); errno = ENOENT; return (-1); } diff --git a/libexec/rc/rc.initdiskless b/libexec/rc/rc.initdiskless index a6820a546e55..a4c6c613b85a 100644 --- a/libexec/rc/rc.initdiskless +++ b/libexec/rc/rc.initdiskless @@ -1,405 +1,405 @@ #!/bin/sh # # Copyright (c) 1999 Matt Dillon # All rights reserved. # # 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. # # On entry to this script the entire system consists of a read-only root # mounted via NFS. The kernel has run BOOTP and configured an interface # (otherwise it would not have been able to mount the NFS root!) # # We use the contents of /conf to create and populate memory filesystems # that are mounted on top of this root to implement the writable # (and host-specific) parts of the root filesystem, and other volatile # filesystems. # # The hierarchy in /conf has the form /conf/T/M/ where M are directories # for which memory filesystems will be created and filled, # and T is one of the "template" directories below: # # base universal base, typically a replica of the original root; # default secondary universal base, typically overriding some # of the files in the original root; # ${ipba} where ${ipba} is the assigned broadcast IP address # bcast/${ipba} same as above # ${class} where ${class} is a list of directories supplied by # bootp/dhcp through the T134 option. # ${ipba} and ${class} are typically used to configure features # for group of diskless clients, or even individual features; # ${ip} where ${ip} is the machine's assigned IP address, typically # used to set host-specific features; # ip/${ip} same as above # # Template directories are scanned in the order they are listed above, # with each successive directory overriding (merged into) the previous one; # non-existing directories are ignored. The subdirectory forms exist to # help keep the top level /conf manageable in large installations. # # The existence of a directory /conf/T/M causes this script to create a # memory filesystem mounted as /M on the client. # # Some files in /conf have special meaning, namely: # # Filename Action # ---------------------------------------------------------------- # /conf/T/M/remount # The contents of the file is a mount command. E.g. if # /conf/1.2.3.4/foo/remount contains "mount -o ro /dev/ad0s3", # then /dev/ad0s3 will be mounted on /conf/1.2.3.4/foo/ # # /conf/T/M/remount_optional # If this file exists, then failure to execute the mount # command contained in /conf/T/M/remount is non-fatal. # # /conf/T/M/remount_subdir # If this file exists, then the behaviour of /conf/T/M/remount # changes as follows: # 1. /conf/T/M/remount is invoked to mount the root of the # filesystem where the configuration data exists on a # temporary mountpoint. # 2. /conf/T/M/remount_subdir is then invoked to mount a # *subdirectory* of the filesystem mounted by # /conf/T/M/remount on /conf/T/M/. # # /conf/T/M/diskless_remount # The contents of the file points to an NFS filesystem, # possibly followed by mount_nfs options. If the server name # is omitted, the script will prepend the root path used when # booting. E.g. if you booted from foo.com:/path/to/root, # an entry for /conf/base/etc/diskless_remount could be any of # foo.com:/path/to/root/etc # /etc -o ro # Because mount_nfs understands ".." in paths, it is # possible to mount from locations above the NFS root with # paths such as "/../../etc". # # /conf/T/M/md_size # The contents of the file specifies the size of the memory # filesystem to be created, in 512 byte blocks. # The default size is 10240 blocks (5MB). E.g. if # /conf/base/etc/md_size contains "30000" then a 15MB MFS # will be created. In case of multiple entries for the same # directory M, the last one in the scanning order is used. # NOTE: If you only need to create a memory filesystem but not # initialize it from a template, it is preferable to specify # it in fstab e.g. as "md /tmp mfs -s=30m,rw 0 0" # # /conf/T/SUBDIR.cpio.gz # The file is cpio'd into /SUBDIR (and a memory filesystem is # created for /SUBDIR if necessary). The presence of this file # prevents the copy from /conf/T/SUBDIR/ # # /conf/T/M/extract # This is alternative to SUBDIR.cpio.gz and remount. # Similar to remount case, a memory filesystem is created # for /M and initialized from a template but no mounting # performed. Instead, this file is run passing /M as single # argument. It is expected to extract template override to /M # using auxiliary storage found in some embedded systems # having NVRAM too small to hold mountable file system. # # /conf/T/SUBDIR.remove # The list of paths contained in the file are rm -rf'd # relative to /SUBDIR. # # /conf/diskless_remount # Similar to /conf/T/M/diskless_remount above, but allows # all of /conf to be remounted. This can be used to allow # multiple roots to share the same /conf. # # # You will almost universally want to create the following files under /conf # # File Content # ---------------------------- ---------------------------------- # /conf/base/etc/md_size size of /etc filesystem # /conf/base/etc/diskless_remount "/etc" # /conf/default/etc/rc.conf generic diskless config parameters # /conf/default/etc/fstab generic diskless fstab e.g. like this # # foo:/root_part / nfs ro 0 0 # foo:/usr_part /usr nfs ro 0 0 # foo:/home_part /home nfs rw 0 0 # md /tmp mfs -s=30m,rw 0 0 # md /var mfs -s=30m,rw 0 0 # proc /proc procfs rw 0 0 # # plus, possibly, overrides for password files etc. # # NOTE! /var, /tmp, and /dev will be typically created elsewhere, e.g. # as entries in the fstab as above. # Those filesystems should not be specified in /conf. # # (end of documentation, now get to the real code) dlv=`/sbin/sysctl -n vfs.nfs.diskless_valid 2> /dev/null` # DEBUGGING # log something on stdout if verbose. o_verbose=0 # set to 1 or 2 if you want more debugging log() { [ ${o_verbose} -gt 0 ] && echo "*** $* ***" [ ${o_verbose} -gt 1 ] && read -p "=== Press enter to continue" foo } # chkerr: # # Routine to check for error # # checks error code and drops into shell on failure. # if shell exits, terminates script as well as /etc/rc. # if remount_optional exists under the mountpoint, skip this check. # chkerr() { lastitem () ( n=$(($# - 1)) ; shift $n ; echo $1 ) mountpoint="$(lastitem $2)" [ -r $mountpoint/remount_optional ] && ( echo "$2 failed: ignoring due to remount_optional" ; return ) case $1 in 0) ;; *) echo "$2 failed: dropping into /bin/sh" /bin/sh # RESUME ;; esac } # The list of filesystems to umount after the copy to_umount="" handle_remount() { # $1 = mount point local nfspt mountopts b b=$1 log handle_remount $1 [ -d $b -a -f $b/diskless_remount ] || return read nfspt mountopts < $b/diskless_remount log "nfspt ${nfspt} mountopts ${mountopts}" # prepend the nfs root if not present [ `expr "$nfspt" : '\(.\)'` = "/" ] && nfspt="${nfsroot}${nfspt}" mount_nfs $mountopts $nfspt $b chkerr $? "mount_nfs $nfspt $b" to_umount="$b ${to_umount}" } # Create a generic memory disk. -# The 'auto' parameter will attempt to use tmpfs(5), falls back to md(4). +# The 'auto' parameter will attempt to use tmpfs(4), falls back to md(4). # $1 is size in 512-byte sectors, $2 is the mount point. mount_md() { if [ ${o_verbose} -gt 0 ] ; then /sbin/mdmfs -XL -S -s $1 auto $2 else /sbin/mdmfs -S -s $1 auto $2 fi } # Create the memory filesystem if it has not already been created # create_md() { [ "x`eval echo \\$md_created_$1`" = "x" ] || return # only once if [ "x`eval echo \\$md_size_$1`" = "x" ]; then md_size=10240 else md_size=`eval echo \\$md_size_$1` fi log create_md $1 with size $md_size mount_md $md_size /$1 /bin/chmod 755 /$1 eval md_created_$1=created } # DEBUGGING # # set -v # Figure out our interface and IP. # bootp_ifc="" bootp_ipa="" bootp_ipbca="" class="" if [ ${dlv:=0} -ne 0 ] ; then iflist=`ifconfig -l` for i in ${iflist} ; do set -- `ifconfig ${i}` while [ $# -ge 1 ] ; do if [ "${bootp_ifc}" = "" -a "$1" = "inet" ] ; then bootp_ifc=${i} ; bootp_ipa=${2} ; shift fi if [ "${bootp_ipbca}" = "" -a "$1" = "broadcast" ] ; then bootp_ipbca=$2; shift fi shift done if [ "${bootp_ifc}" != "" ] ; then break fi done # Get the values passed with the T134 bootp cookie. class="`/sbin/sysctl -qn kern.bootp_cookie`" echo "Interface ${bootp_ifc} IP-Address ${bootp_ipa} Broadcast ${bootp_ipbca} ${class}" fi log Figure out our NFS root path # set -- `mount -t nfs` while [ $# -ge 1 ] ; do if [ "$2" = "on" -a "$3" = "/" ]; then nfsroot="$1" break fi shift done # The list of directories with template files templates="base default" if [ -n "${bootp_ipbca}" ]; then templates="${templates} ${bootp_ipbca} bcast/${bootp_ipbca}" fi if [ -n "${class}" ]; then templates="${templates} ${class}" fi if [ -n "${bootp_ipa}" ]; then templates="${templates} ${bootp_ipa} ip/${bootp_ipa}" fi # If /conf/diskless_remount exists, remount all of /conf. handle_remount /conf # Resolve templates in /conf/base, /conf/default, /conf/${bootp_ipbca}, # and /conf/${bootp_ipa}. For each subdirectory found within these # directories: # # - calculate memory filesystem sizes. If the subdirectory (prior to # NFS remounting) contains the file 'md_size', the contents specified # in 512 byte sectors will be used to size the memory filesystem. Otherwise # 8192 sectors (4MB) is used. # # - handle NFS remounts. If the subdirectory contains the file # diskless_remount, the contents of the file is NFS mounted over # the directory. For example /conf/base/etc/diskless_remount # might contain 'myserver:/etc'. NFS remounts allow you to avoid # having to dup your system directories in /conf. Your server must # be sure to export those filesystems -alldirs, however. # If the diskless_remount file contains a string beginning with a # '/' it is assumed that the local nfsroot should be prepended to # it before attempting to the remount. This allows the root to be # relocated without needing to change the remount files. # log "templates are ${templates}" for i in ${templates} ; do for j in /conf/$i/* ; do [ -d $j ] || continue # memory filesystem size specification subdir=${j##*/} [ -f $j/md_size ] && eval md_size_$subdir=`cat $j/md_size` # remount. Beware, the command is in the file itself! if [ -f $j/remount ]; then if [ -f $j/remount_subdir ]; then k="/conf.tmp/$i/$subdir" [ -d $k ] || continue # Mount the filesystem root where the config data is # on the temporary mount point. nfspt=`/bin/cat $j/remount` $nfspt $k chkerr $? "$nfspt $k" # Now use a nullfs mount to get the data where we # really want to see it. remount_subdir=`/bin/cat $j/remount_subdir` remount_subdir_cmd="mount -t nullfs $k/$remount_subdir" $remount_subdir_cmd $j chkerr $? "$remount_subdir_cmd $j" # XXX check order -- we must force $k to be unmounted # after j, as j depends on k. to_umount="$j $k ${to_umount}" else nfspt=`/bin/cat $j/remount` $nfspt $j chkerr $? "$nfspt $j" to_umount="$j ${to_umount}" # XXX hope it is really a mount! fi fi # NFS remount handle_remount $j done done # - Create all required MFS filesystems and populate them from # our templates. Support both a direct template and a dir.cpio.gz # archive. Support for auxiliary NVRAM. Support dir.remove files containing # a list of relative paths to remove. # # The dir.cpio.gz form is there to make the copy process more efficient, # so if the cpio archive is present, it prevents the files from dir/ # from being copied. PATH=${PATH}:/rescue for i in ${templates} ; do for j in /conf/$i/* ; do subdir=${j##*/} if [ -d $j -a ! -f $j.cpio.gz ]; then create_md $subdir cp -Rp $j/ /$subdir fi done for j in /conf/$i/*.cpio.gz ; do subdir=${j%*.cpio.gz} subdir=${subdir##*/} if [ -f $j ]; then create_md $subdir echo "Loading /$subdir from cpio archive $j" (cd / ; tar -xpf $j) fi done for j in /conf/$i/*/extract ; do if [ -x $j ]; then subdir=${j%*/extract} subdir=${subdir##*/} create_md $subdir echo "Loading /$subdir using auxiliary command $j" $j /$subdir fi done for j in /conf/$i/*.remove ; do subdir=${j%*.remove} subdir=${subdir##*/} if [ -f $j ]; then # doubly sure it is a memory disk before rm -rf'ing create_md $subdir (cd /$subdir; rm -rf `/bin/cat $j`) fi done done # umount partitions used to fill the memory filesystems [ -n "${to_umount}" ] && umount $to_umount diff --git a/sbin/devd/autofs.conf b/sbin/devd/autofs.conf index a06ca7295d38..2671687ecd83 100644 --- a/sbin/devd/autofs.conf +++ b/sbin/devd/autofs.conf @@ -1,9 +1,9 @@ # -# autofs(5) specific devd events +# autofs(4) specific devd events # Discard autofs caches, useful for the -media special map. notify 100 { match "system" "GEOM"; match "subsystem" "DEV"; action "/usr/sbin/automount -c"; }; diff --git a/sbin/devfs/devfs.rules b/sbin/devfs/devfs.rules index f85940aaa7dd..c51672815e64 100644 --- a/sbin/devfs/devfs.rules +++ b/sbin/devfs/devfs.rules @@ -1,93 +1,93 @@ # -# The following are some default rules for devfs(5) mounts. +# The following are some default rules for devfs(4) mounts. # The format is very simple. Empty lines and lines beginning # with a hash '#' are ignored. If the hash mark occurs anywhere # other than the beginning of a line, it and any subsequent # characters will be ignored. A line in between brackets '[]' # denotes the beginning of a ruleset. In the brackets should # be a name for the rule and its ruleset number. Any other lines # will be considered to be the 'action' part of a rule # passed to the devfs(8) command. These will be passed # "as-is" to the devfs(8) command with the exception that # any references to other rulesets will be expanded first. These # references must include a dollar sign '$' in front of the # name to be expanded properly. # # # Very basic and secure ruleset: Hide everything. # Used as a basis for other rules. # [devfsrules_hide_all=1] add hide # Basic devices typically necessary. # Requires: devfsrules_hide_all # [devfsrules_unhide_basic=2] add path null unhide add path zero unhide add path crypto unhide add path random unhide add path urandom unhide # Devices typically needed to support logged-in users. # Requires: devfsrules_hide_all # [devfsrules_unhide_login=3] add path 'ptyp*' unhide add path 'ptyq*' unhide add path 'ptyr*' unhide add path 'ptys*' unhide add path 'ptyP*' unhide add path 'ptyQ*' unhide add path 'ptyR*' unhide add path 'ptyS*' unhide add path 'ptyl*' unhide add path 'ptym*' unhide add path 'ptyn*' unhide add path 'ptyo*' unhide add path 'ptyL*' unhide add path 'ptyM*' unhide add path 'ptyN*' unhide add path 'ptyO*' unhide add path 'ttyp*' unhide add path 'ttyq*' unhide add path 'ttyr*' unhide add path 'ttys*' unhide add path 'ttyP*' unhide add path 'ttyQ*' unhide add path 'ttyR*' unhide add path 'ttyS*' unhide add path 'ttyl*' unhide add path 'ttym*' unhide add path 'ttyn*' unhide add path 'ttyo*' unhide add path 'ttyL*' unhide add path 'ttyM*' unhide add path 'ttyN*' unhide add path 'ttyO*' unhide add path ptmx unhide add path pts unhide add path 'pts/*' unhide add path fd unhide add path 'fd/*' unhide add path stdin unhide add path stdout unhide add path stderr unhide # Devices usually found in a jail. # [devfsrules_jail=4] add include $devfsrules_hide_all add include $devfsrules_unhide_basic add include $devfsrules_unhide_login add path fuse unhide add path zfs unhide [devfsrules_jail_vnet=5] add include $devfsrules_hide_all add include $devfsrules_unhide_basic add include $devfsrules_unhide_login add include $devfsrules_jail add path pf unhide diff --git a/sys/README.md b/sys/README.md index 10c9f183f7e1..c36686e979f5 100644 --- a/sys/README.md +++ b/sys/README.md @@ -1,60 +1,60 @@ FreeBSD Kernel Source: ---------------------- This directory contains the source files and build glue that make up the FreeBSD kernel and its modules, including both original and contributed software. Kernel configuration files are located in the `conf/` subdirectory of each architecture. `GENERIC` is the configuration used in release builds. `NOTES` contains documentation of all possible entries. `LINT` is a compile-only configuration used to maximize build coverage and detect regressions. Documentation: -------------- Source code documentation is maintained in a set of man pages, under section 9. These pages are located in [`share/man/man9`](../share/man/man9), from the top-level of the src tree. Consult [`intro(9)`](https://man.freebsd.org/intro/9) for an overview of existing pages. Some additional high-level documentation of the kernel is maintained in the [Architecture Handbook](https://docs.freebsd.org/en/books/arch-handbook/). Source Roadmap: --------------- | Directory | Description | | --------- | ----------- | | amd64 | AMD64 (64-bit x86) architecture support | | arm | 32-bit ARM architecture support | | arm64 | 64-bit ARM (AArch64) architecture support | | cam | Common Access Method storage subsystem - `cam(4)` and `ctl(4)` | | cddl | CDDL-licensed optional sources such as DTrace | | conf | kernel build glue | | compat | Linux compatibility layer, FreeBSD 32-bit compatibility | | contrib | 3rd-party imported software such as OpenZFS | | crypto | crypto drivers | | ddb | interactive kernel debugger - `ddb(4)` | | fs | most filesystems, excluding UFS, NFS, and ZFS | | dev | device drivers and other arch independent code | | gdb | kernel remote GDB stub - `gdb(4)` | | geom | GEOM framework - `geom(4)` | | i386 | i386 (32-bit x86) architecture support | | kern | main part of the kernel | | libkern | libc-like and other support functions for kernel use | | modules | kernel module infrastructure | | net | core networking code | | net80211 | wireless networking (IEEE 802.11) - `net80211(4)` | | netgraph | graph-based networking subsystem - `netgraph(4)` | | netinet | IPv4 protocol implementation - `inet(4)` | | netinet6 | IPv6 protocol implementation - `inet6(4)` | | netipsec | IPsec protocol implementation - `ipsec(4)` | | netpfil | packet filters - `ipfw(4)`, `pf(4)`, and `ipfilter(4)` | | opencrypto | OpenCrypto framework - `crypto(7)` | | powerpc | PowerPC/POWER (32 and 64-bit) architecture support | | riscv | 64-bit RISC-V architecture support | | security | security facilities - `audit(4)` and `mac(4)` | | sys | kernel headers | | tests | kernel unit tests | -| ufs | Unix File System - `ffs(7)` | +| ufs | Unix File System - `ffs(4)` | | vm | virtual memory system | | x86 | code shared by AMD64 and i386 architectures | diff --git a/sys/kern/imgact_binmisc.c b/sys/kern/imgact_binmisc.c index aa037bb6046a..ed7a314ec475 100644 --- a/sys/kern/imgact_binmisc.c +++ b/sys/kern/imgact_binmisc.c @@ -1,781 +1,781 @@ /*- * Copyright (c) 2013-16, Stacey D. Son * All rights reserved. * * 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. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /** * Miscellaneous binary interpreter image activator. * * If the given target executable's header matches 'xbe_magic' field in the * 'interpreter_list' then it will use the user-level interpreter specified in * the 'xbe_interpreter' field to execute the binary. The 'xbe_magic' field may * be adjusted to a given offset using the value in the 'xbe_moffset' field * and bits of the header may be masked using the 'xbe_mask' field. The * 'interpreter_list' entries are managed using sysctl(3) as described in the * file. */ /* * Node of the interpreter list. */ typedef struct imgact_binmisc_entry { SLIST_ENTRY(imgact_binmisc_entry) link; char *ibe_name; uint8_t *ibe_magic; uint8_t *ibe_mask; uint8_t *ibe_interpreter; struct vnode *ibe_interpreter_vnode; ssize_t ibe_interp_offset; uint32_t ibe_interp_argcnt; uint32_t ibe_interp_length; uint32_t ibe_argv0_cnt; uint32_t ibe_flags; uint32_t ibe_moffset; uint32_t ibe_msize; } imgact_binmisc_entry_t; /* * sysctl() commands. */ #define IBC_ADD 1 /* Add given entry. */ #define IBC_REMOVE 2 /* Remove entry for a given name. */ #define IBC_DISABLE 3 /* Disable entry for a given name. */ #define IBC_ENABLE 4 /* Enable entry for a given name. */ #define IBC_LOOKUP 5 /* Lookup and return entry for given name. */ #define IBC_LIST 6 /* Get a snapshot of the interpretor list. */ /* * Interpreter string macros. * * They all start with '#' followed by a single letter: */ #define ISM_POUND '#' /* "##" is the escape sequence for single #. */ #define ISM_OLD_ARGV0 'a' /* "#a" is replaced with the old argv0. */ MALLOC_DEFINE(M_BINMISC, KMOD_NAME, "misc binary image activator"); /* The interpreter list. */ static SLIST_HEAD(, imgact_binmisc_entry) interpreter_list = SLIST_HEAD_INITIALIZER(interpreter_list); static int interp_list_entry_count; static struct sx interp_list_sx; #define INTERP_LIST_WLOCK() sx_xlock(&interp_list_sx) #define INTERP_LIST_RLOCK() sx_slock(&interp_list_sx) #define INTERP_LIST_WUNLOCK() sx_xunlock(&interp_list_sx) #define INTERP_LIST_RUNLOCK() sx_sunlock(&interp_list_sx) #define INTERP_LIST_LOCK_INIT() sx_init(&interp_list_sx, KMOD_NAME) #define INTERP_LIST_LOCK_DESTROY() sx_destroy(&interp_list_sx) #define INTERP_LIST_ASSERT_LOCKED() sx_assert(&interp_list_sx, SA_LOCKED) /* * Populate the entry with the information about the interpreter. */ static void imgact_binmisc_populate_interp(char *str, imgact_binmisc_entry_t *ibe, int flags) { uint32_t len = 0, argc = 1; char t[IBE_INTERP_LEN_MAX]; char *sp, *tp; memset(t, 0, sizeof(t)); /* * Normalize interpreter string. Replace white space between args with * single space. */ sp = str; tp = t; while (*sp != '\0') { if (*sp == ' ' || *sp == '\t') { if (++len >= IBE_INTERP_LEN_MAX) break; *tp++ = ' '; argc++; while (*sp == ' ' || *sp == '\t') sp++; continue; } else { *tp++ = *sp++; len++; } } *tp = '\0'; len++; ibe->ibe_interpreter = malloc(len, M_BINMISC, M_WAITOK|M_ZERO); /* Populate all the ibe fields for the interpreter. */ memcpy(ibe->ibe_interpreter, t, len); ibe->ibe_interp_argcnt = argc; ibe->ibe_interp_length = len; ibe->ibe_interpreter_vnode = NULL; if (flags & IBF_PRE_OPEN) { struct nameidata nd; int error; tp = t; while (*tp != '\0' && *tp != ' ') { tp++; } *tp = '\0'; NDINIT(&nd, LOOKUP, FOLLOW | ISOPEN, UIO_SYSSPACE, t); /* * If there is an error, just stop now and fall back * to the non pre-open case where we lookup during * exec. */ error = namei(&nd); if (error) return; ibe->ibe_interpreter_vnode = nd.ni_vp; } } /* * Allocate memory and populate a new entry for the interpreter table. */ static imgact_binmisc_entry_t * imgact_binmisc_new_entry(ximgact_binmisc_entry_t *xbe, ssize_t interp_offset, int argv0_cnt) { imgact_binmisc_entry_t *ibe = NULL; size_t namesz = min(strlen(xbe->xbe_name) + 1, IBE_NAME_MAX); ibe = malloc(sizeof(*ibe), M_BINMISC, M_WAITOK|M_ZERO); ibe->ibe_name = malloc(namesz, M_BINMISC, M_WAITOK|M_ZERO); strlcpy(ibe->ibe_name, xbe->xbe_name, namesz); imgact_binmisc_populate_interp(xbe->xbe_interpreter, ibe, xbe->xbe_flags); ibe->ibe_magic = malloc(xbe->xbe_msize, M_BINMISC, M_WAITOK|M_ZERO); memcpy(ibe->ibe_magic, xbe->xbe_magic, xbe->xbe_msize); ibe->ibe_mask = malloc(xbe->xbe_msize, M_BINMISC, M_WAITOK|M_ZERO); memcpy(ibe->ibe_mask, xbe->xbe_mask, xbe->xbe_msize); ibe->ibe_moffset = xbe->xbe_moffset; ibe->ibe_msize = xbe->xbe_msize; ibe->ibe_flags = xbe->xbe_flags; ibe->ibe_interp_offset = interp_offset; ibe->ibe_argv0_cnt = argv0_cnt; return (ibe); } /* * Free the allocated memory for a given list item. */ static void imgact_binmisc_destroy_entry(imgact_binmisc_entry_t *ibe) { if (!ibe) return; if (ibe->ibe_magic) free(ibe->ibe_magic, M_BINMISC); if (ibe->ibe_mask) free(ibe->ibe_mask, M_BINMISC); if (ibe->ibe_interpreter) free(ibe->ibe_interpreter, M_BINMISC); if (ibe->ibe_name) free(ibe->ibe_name, M_BINMISC); if (ibe->ibe_interpreter_vnode) vrele(ibe->ibe_interpreter_vnode); if (ibe) free(ibe, M_BINMISC); } /* * Find the interpreter in the list by the given name. Return NULL if not * found. */ static imgact_binmisc_entry_t * imgact_binmisc_find_entry(char *name) { imgact_binmisc_entry_t *ibe; INTERP_LIST_ASSERT_LOCKED(); SLIST_FOREACH(ibe, &interpreter_list, link) { if (strncmp(name, ibe->ibe_name, IBE_NAME_MAX) == 0) return (ibe); } return (NULL); } /* * Add the given interpreter if it doesn't already exist. Return EEXIST * if the name already exist in the interpreter list. */ static int imgact_binmisc_add_entry(ximgact_binmisc_entry_t *xbe) { imgact_binmisc_entry_t *ibe; char *p; ssize_t interp_offset; int argv0_cnt, cnt; if (xbe->xbe_msize > IBE_MAGIC_MAX) return (EINVAL); if (xbe->xbe_moffset + xbe->xbe_msize > IBE_MATCH_MAX) return (EINVAL); for(cnt = 0, p = xbe->xbe_name; *p != 0; cnt++, p++) if (cnt >= IBE_NAME_MAX || !isascii((int)*p)) return (EINVAL); for(cnt = 0, p = xbe->xbe_interpreter; *p != 0; cnt++, p++) if (cnt >= IBE_INTERP_LEN_MAX || !isascii((int)*p)) return (EINVAL); /* Make sure we don't have any invalid #'s. */ p = xbe->xbe_interpreter; interp_offset = 0; argv0_cnt = 0; while ((p = strchr(p, '#')) != NULL) { p++; switch(*p) { case ISM_POUND: /* "##" */ p++; interp_offset--; break; case ISM_OLD_ARGV0: /* "#a" */ p++; argv0_cnt++; break; case 0: default: /* Anything besides the above is invalid. */ return (EINVAL); } } /* * Preallocate a new entry. We do this without holding the * lock to avoid lock-order problems if IBF_PRE_OPEN is * set. */ ibe = imgact_binmisc_new_entry(xbe, interp_offset, argv0_cnt); INTERP_LIST_WLOCK(); if (imgact_binmisc_find_entry(xbe->xbe_name) != NULL) { INTERP_LIST_WUNLOCK(); imgact_binmisc_destroy_entry(ibe); return (EEXIST); } SLIST_INSERT_HEAD(&interpreter_list, ibe, link); interp_list_entry_count++; INTERP_LIST_WUNLOCK(); return (0); } /* * Remove the interpreter in the list with the given name. Return ENOENT * if not found. */ static int imgact_binmisc_remove_entry(char *name) { imgact_binmisc_entry_t *ibe; INTERP_LIST_WLOCK(); if ((ibe = imgact_binmisc_find_entry(name)) == NULL) { INTERP_LIST_WUNLOCK(); return (ENOENT); } SLIST_REMOVE(&interpreter_list, ibe, imgact_binmisc_entry, link); interp_list_entry_count--; INTERP_LIST_WUNLOCK(); imgact_binmisc_destroy_entry(ibe); return (0); } /* * Disable the interpreter in the list with the given name. Return ENOENT * if not found. */ static int imgact_binmisc_disable_entry(char *name) { imgact_binmisc_entry_t *ibe; INTERP_LIST_WLOCK(); if ((ibe = imgact_binmisc_find_entry(name)) == NULL) { INTERP_LIST_WUNLOCK(); return (ENOENT); } ibe->ibe_flags &= ~IBF_ENABLED; INTERP_LIST_WUNLOCK(); return (0); } /* * Enable the interpreter in the list with the given name. Return ENOENT * if not found. */ static int imgact_binmisc_enable_entry(char *name) { imgact_binmisc_entry_t *ibe; INTERP_LIST_WLOCK(); if ((ibe = imgact_binmisc_find_entry(name)) == NULL) { INTERP_LIST_WUNLOCK(); return (ENOENT); } ibe->ibe_flags |= IBF_ENABLED; INTERP_LIST_WUNLOCK(); return (0); } static int imgact_binmisc_populate_xbe(ximgact_binmisc_entry_t *xbe, imgact_binmisc_entry_t *ibe) { uint32_t i; INTERP_LIST_ASSERT_LOCKED(); memset(xbe, 0, sizeof(*xbe)); strlcpy(xbe->xbe_name, ibe->ibe_name, IBE_NAME_MAX); /* Copy interpreter string. Replace NULL breaks with space. */ memcpy(xbe->xbe_interpreter, ibe->ibe_interpreter, ibe->ibe_interp_length); for(i = 0; i < (ibe->ibe_interp_length - 1); i++) if (xbe->xbe_interpreter[i] == '\0') xbe->xbe_interpreter[i] = ' '; memcpy(xbe->xbe_magic, ibe->ibe_magic, ibe->ibe_msize); memcpy(xbe->xbe_mask, ibe->ibe_mask, ibe->ibe_msize); xbe->xbe_version = IBE_VERSION; xbe->xbe_flags = ibe->ibe_flags; xbe->xbe_moffset = ibe->ibe_moffset; xbe->xbe_msize = ibe->ibe_msize; return (0); } /* * Retrieve the interpreter with the give name and populate the * ximgact_binmisc_entry structure. Return ENOENT if not found. */ static int imgact_binmisc_lookup_entry(char *name, ximgact_binmisc_entry_t *xbe) { imgact_binmisc_entry_t *ibe; int error = 0; INTERP_LIST_RLOCK(); if ((ibe = imgact_binmisc_find_entry(name)) == NULL) { INTERP_LIST_RUNLOCK(); return (ENOENT); } error = imgact_binmisc_populate_xbe(xbe, ibe); INTERP_LIST_RUNLOCK(); return (error); } /* * Get a snapshot of all the interpreter entries in the list. */ static int imgact_binmisc_get_all_entries(struct sysctl_req *req) { ximgact_binmisc_entry_t *xbe, *xbep; imgact_binmisc_entry_t *ibe; int error = 0, count; INTERP_LIST_RLOCK(); count = interp_list_entry_count; xbe = malloc(sizeof(*xbe) * count, M_BINMISC, M_WAITOK|M_ZERO); xbep = xbe; SLIST_FOREACH(ibe, &interpreter_list, link) { error = imgact_binmisc_populate_xbe(xbep++, ibe); if (error) break; } INTERP_LIST_RUNLOCK(); if (!error) error = SYSCTL_OUT(req, xbe, sizeof(*xbe) * count); free(xbe, M_BINMISC); return (error); } /* * sysctl() handler for munipulating interpretor table. * Not MP safe (locked by sysctl). */ static int sysctl_kern_binmisc(SYSCTL_HANDLER_ARGS) { ximgact_binmisc_entry_t xbe; int error = 0; switch(arg2) { case IBC_ADD: /* Add an entry. Limited to IBE_MAX_ENTRIES. */ error = SYSCTL_IN(req, &xbe, sizeof(xbe)); if (error) return (error); if (IBE_VERSION != xbe.xbe_version) return (EINVAL); if ((xbe.xbe_flags & ~IBF_VALID_UFLAGS) != 0) return (EINVAL); if (interp_list_entry_count == IBE_MAX_ENTRIES) return (ENOSPC); error = imgact_binmisc_add_entry(&xbe); break; case IBC_REMOVE: /* Remove an entry. */ error = SYSCTL_IN(req, &xbe, sizeof(xbe)); if (error) return (error); if (IBE_VERSION != xbe.xbe_version) return (EINVAL); error = imgact_binmisc_remove_entry(xbe.xbe_name); break; case IBC_DISABLE: /* Disable an entry. */ error = SYSCTL_IN(req, &xbe, sizeof(xbe)); if (error) return (error); if (IBE_VERSION != xbe.xbe_version) return (EINVAL); error = imgact_binmisc_disable_entry(xbe.xbe_name); break; case IBC_ENABLE: /* Enable an entry. */ error = SYSCTL_IN(req, &xbe, sizeof(xbe)); if (error) return (error); if (IBE_VERSION != xbe.xbe_version) return (EINVAL); error = imgact_binmisc_enable_entry(xbe.xbe_name); break; case IBC_LOOKUP: /* Lookup an entry. */ error = SYSCTL_IN(req, &xbe, sizeof(xbe)); if (error) return (error); if (IBE_VERSION != xbe.xbe_version) return (EINVAL); error = imgact_binmisc_lookup_entry(xbe.xbe_name, &xbe); if (!error) error = SYSCTL_OUT(req, &xbe, sizeof(xbe)); break; case IBC_LIST: /* Return a snapshot of the interpretor list. */ if (!req->oldptr) { /* No pointer then just return the list size. */ error = SYSCTL_OUT(req, 0, interp_list_entry_count * sizeof(ximgact_binmisc_entry_t)); return (error); } else if (!req->oldlen) return (EINVAL); error = imgact_binmisc_get_all_entries(req); break; default: return (EINVAL); } return (error); } SYSCTL_NODE(_kern, OID_AUTO, binmisc, CTLFLAG_RW | CTLFLAG_MPSAFE, 0, "Image activator for miscellaneous binaries"); SYSCTL_PROC(_kern_binmisc, OID_AUTO, add, CTLFLAG_MPSAFE|CTLTYPE_STRUCT|CTLFLAG_WR, NULL, IBC_ADD, sysctl_kern_binmisc, "S,ximgact_binmisc_entry", "Add an activator entry"); SYSCTL_PROC(_kern_binmisc, OID_AUTO, remove, CTLFLAG_MPSAFE|CTLTYPE_STRUCT|CTLFLAG_WR, NULL, IBC_REMOVE, sysctl_kern_binmisc, "S,ximgact_binmisc_entry", "Remove an activator entry"); SYSCTL_PROC(_kern_binmisc, OID_AUTO, disable, CTLFLAG_MPSAFE|CTLTYPE_STRUCT|CTLFLAG_WR, NULL, IBC_DISABLE, sysctl_kern_binmisc, "S,ximgact_binmisc_entry", "Disable an activator entry"); SYSCTL_PROC(_kern_binmisc, OID_AUTO, enable, CTLFLAG_MPSAFE|CTLTYPE_STRUCT|CTLFLAG_WR, NULL, IBC_ENABLE, sysctl_kern_binmisc, "S,ximgact_binmisc_entry", "Enable an activator entry"); SYSCTL_PROC(_kern_binmisc, OID_AUTO, lookup, CTLFLAG_MPSAFE|CTLTYPE_STRUCT|CTLFLAG_RW|CTLFLAG_ANYBODY, NULL, IBC_LOOKUP, sysctl_kern_binmisc, "S,ximgact_binmisc_entry", "Lookup an activator entry"); SYSCTL_PROC(_kern_binmisc, OID_AUTO, list, CTLFLAG_MPSAFE|CTLTYPE_STRUCT|CTLFLAG_RD|CTLFLAG_ANYBODY, NULL, IBC_LIST, sysctl_kern_binmisc, "S,ximgact_binmisc_entry", "Get snapshot of all the activator entries"); static imgact_binmisc_entry_t * imgact_binmisc_find_interpreter(const char *image_header) { imgact_binmisc_entry_t *ibe; const char *p; int i; size_t sz; INTERP_LIST_ASSERT_LOCKED(); SLIST_FOREACH(ibe, &interpreter_list, link) { if (!(IBF_ENABLED & ibe->ibe_flags)) continue; p = image_header + ibe->ibe_moffset; sz = ibe->ibe_msize; if (IBF_USE_MASK & ibe->ibe_flags) { /* Compare using mask. */ for (i = 0; i < sz; i++) if ((*p++ ^ ibe->ibe_magic[i]) & ibe->ibe_mask[i]) break; } else { for (i = 0; i < sz; i++) if (*p++ ^ ibe->ibe_magic[i]) break; } if (i == ibe->ibe_msize) return (ibe); } return (NULL); } static int imgact_binmisc_exec(struct image_params *imgp) { const char *image_header = imgp->image_header; const char *fname = NULL; int error = 0; #ifdef INVARIANTS int argv0_cnt = 0; #endif size_t namelen, offset; imgact_binmisc_entry_t *ibe; struct sbuf *sname; char *s, *d; sname = NULL; namelen = 0; /* Do we have an interpreter for the given image header? */ INTERP_LIST_RLOCK(); if ((ibe = imgact_binmisc_find_interpreter(image_header)) == NULL) { error = -1; goto done; } /* No interpreter nesting allowed. */ if (imgp->interpreted & IMGACT_BINMISC) { error = ENOEXEC; goto done; } imgp->interpreted |= IMGACT_BINMISC; /* * Don't bother with the overhead of putting fname together if we're not * using #a. */ if (ibe->ibe_argv0_cnt != 0) { if (imgp->args->fname != NULL) { fname = imgp->args->fname; } else { - /* Use the fdescfs(5) path for fexecve(2). */ + /* Use the fdescfs(4) path for fexecve(2). */ sname = sbuf_new_auto(); sbuf_printf(sname, "/dev/fd/%d", imgp->args->fd); sbuf_finish(sname); fname = sbuf_data(sname); } namelen = strlen(fname); } /* * We need to "push" the interpreter in the arg[] list. To do this, * we first shift all the other values in the `begin_argv' area to * provide the exact amount of room for the values added. Set up * `offset' as the number of bytes to be added to the `begin_argv' * area. ibe_interp_offset is the fixed offset from macros present in * the interpreter string. */ offset = ibe->ibe_interp_length + ibe->ibe_interp_offset; /* Variable offset to be added from macros to the interpreter string. */ MPASS(ibe->ibe_argv0_cnt == 0 || namelen > 0); offset += ibe->ibe_argv0_cnt * (namelen - 2); /* Make room for the interpreter */ error = exec_args_adjust_args(imgp->args, 0, offset); if (error != 0) { goto done; } /* Add the new argument(s) in the count. */ imgp->args->argc += ibe->ibe_interp_argcnt; /* * The original arg[] list has been shifted appropriately. Copy in * the interpreter path. */ s = ibe->ibe_interpreter; d = imgp->args->begin_argv; while(*s != '\0') { switch (*s) { case '#': /* Handle "#" in interpreter string. */ s++; switch(*s) { case ISM_POUND: /* "##": Replace with a single '#' */ *d++ = '#'; break; case ISM_OLD_ARGV0: /* "#a": Replace with old arg0 (fname). */ MPASS(ibe->ibe_argv0_cnt >= ++argv0_cnt); memcpy(d, fname, namelen); d += namelen; break; default: __assert_unreachable(); } break; case ' ': /* Replace space with NUL to separate arguments. */ *d++ = '\0'; break; default: *d++ = *s; break; } s++; } *d = '\0'; /* Catch ibe->ibe_argv0_cnt counting more #a than we did. */ MPASS(ibe->ibe_argv0_cnt == argv0_cnt); imgp->interpreter_name = imgp->args->begin_argv; if (ibe->ibe_interpreter_vnode) { imgp->interpreter_vp = ibe->ibe_interpreter_vnode; vref(imgp->interpreter_vp); } done: INTERP_LIST_RUNLOCK(); if (sname) sbuf_delete(sname); return (error); } static void imgact_binmisc_init(void *arg) { INTERP_LIST_LOCK_INIT(); } static void imgact_binmisc_fini(void *arg) { imgact_binmisc_entry_t *ibe, *ibe_tmp; /* Free all the interpreters. */ INTERP_LIST_WLOCK(); SLIST_FOREACH_SAFE(ibe, &interpreter_list, link, ibe_tmp) { SLIST_REMOVE(&interpreter_list, ibe, imgact_binmisc_entry, link); imgact_binmisc_destroy_entry(ibe); } INTERP_LIST_WUNLOCK(); INTERP_LIST_LOCK_DESTROY(); } SYSINIT(imgact_binmisc, SI_SUB_EXEC, SI_ORDER_MIDDLE, imgact_binmisc_init, NULL); SYSUNINIT(imgact_binmisc, SI_SUB_EXEC, SI_ORDER_MIDDLE, imgact_binmisc_fini, NULL); /* * Tell kern_execve.c about it, with a little help from the linker. */ static struct execsw imgact_binmisc_execsw = { .ex_imgact = imgact_binmisc_exec, .ex_name = KMOD_NAME }; EXEC_SET(imgact_binmisc, imgact_binmisc_execsw); diff --git a/tests/sys/fs/fusefs/mknod.cc b/tests/sys/fs/fusefs/mknod.cc index 1fb855f44f29..eb745f19acd5 100644 --- a/tests/sys/fs/fusefs/mknod.cc +++ b/tests/sys/fs/fusefs/mknod.cc @@ -1,318 +1,318 @@ /*- * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2019 The FreeBSD Foundation * * This software was developed by BFF Storage Systems, LLC 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. */ extern "C" { #include #include #include #include } #include "mockfs.hh" #include "utils.hh" using namespace testing; #ifndef VNOVAL #define VNOVAL (-1) /* Defined in sys/vnode.h */ #endif class Mknod: public FuseTest { mode_t m_oldmask; const static mode_t c_umask = 022; public: Mknod() { m_oldmask = umask(c_umask); } virtual void SetUp() { if (geteuid() != 0) { GTEST_SKIP() << "Only root may use most mknod(2) variations"; } FuseTest::SetUp(); } virtual void TearDown() { FuseTest::TearDown(); (void)umask(m_oldmask); } /* Test an OK creation of a file with the given mode and device number */ void expect_mknod(uint64_t parent_ino, const char* relpath, uint64_t ino, mode_t mode, dev_t dev) { EXPECT_CALL(*m_mock, process( ResultOf([=](auto in) { const char *name = (const char*)in.body.bytes + sizeof(fuse_mknod_in); return (in.header.nodeid == parent_ino && in.header.opcode == FUSE_MKNOD && in.body.mknod.mode == mode && in.body.mknod.rdev == (uint32_t)dev && in.body.mknod.umask == c_umask && (0 == strcmp(relpath, name))); }, Eq(true)), _) ).WillOnce(Invoke(ReturnImmediate([=](auto in __unused, auto& out) { SET_OUT_HEADER_LEN(out, entry); out.body.entry.attr.mode = mode; out.body.entry.nodeid = ino; out.body.entry.entry_valid = UINT64_MAX; out.body.entry.attr_valid = UINT64_MAX; out.body.entry.attr.rdev = dev; }))); } }; class Mknod_7_11: public FuseTest { public: virtual void SetUp() { m_kernel_minor_version = 11; if (geteuid() != 0) { GTEST_SKIP() << "Only root may use most mknod(2) variations"; } FuseTest::SetUp(); } void expect_lookup(const char *relpath, uint64_t ino, uint64_t size) { FuseTest::expect_lookup_7_8(relpath, ino, S_IFREG | 0644, size, 1); } /* Test an OK creation of a file with the given mode and device number */ void expect_mknod(uint64_t parent_ino, const char* relpath, uint64_t ino, mode_t mode, dev_t dev) { EXPECT_CALL(*m_mock, process( ResultOf([=](auto in) { const char *name = (const char*)in.body.bytes + FUSE_COMPAT_MKNOD_IN_SIZE; return (in.header.nodeid == parent_ino && in.header.opcode == FUSE_MKNOD && in.body.mknod.mode == mode && in.body.mknod.rdev == (uint32_t)dev && (0 == strcmp(relpath, name))); }, Eq(true)), _) ).WillOnce(Invoke(ReturnImmediate([=](auto in __unused, auto& out) { SET_OUT_HEADER_LEN(out, entry); out.body.entry.attr.mode = mode; out.body.entry.nodeid = ino; out.body.entry.entry_valid = UINT64_MAX; out.body.entry.attr_valid = UINT64_MAX; out.body.entry.attr.rdev = dev; }))); } }; /* * mknod(2) should be able to create block devices on a FUSE filesystem. Even * though FreeBSD doesn't use block devices, this is useful when copying media * from or preparing media for other operating systems. */ TEST_F(Mknod, blk) { const char FULLPATH[] = "mountpoint/some_node"; const char RELPATH[] = "some_node"; mode_t mode = S_IFBLK | 0755; dev_t rdev = 0xfe00; /* /dev/vda's device number on Linux */ uint64_t ino = 42; EXPECT_LOOKUP(FUSE_ROOT_ID, RELPATH) .WillOnce(Invoke(ReturnErrno(ENOENT))); expect_mknod(FUSE_ROOT_ID, RELPATH, ino, mode, rdev); EXPECT_EQ(0, mknod(FULLPATH, mode, rdev)) << strerror(errno); } TEST_F(Mknod, chr) { const char FULLPATH[] = "mountpoint/some_node"; const char RELPATH[] = "some_node"; mode_t mode = S_IFCHR | 0755; dev_t rdev = 54; /* /dev/fuse's device number */ uint64_t ino = 42; EXPECT_LOOKUP(FUSE_ROOT_ID, RELPATH) .WillOnce(Invoke(ReturnErrno(ENOENT))); expect_mknod(FUSE_ROOT_ID, RELPATH, ino, mode, rdev); EXPECT_EQ(0, mknod(FULLPATH, mode, rdev)) << strerror(errno); } /* * The daemon is responsible for checking file permissions (unless the * default_permissions mount option was used) */ TEST_F(Mknod, eperm) { const char FULLPATH[] = "mountpoint/some_node"; const char RELPATH[] = "some_node"; mode_t mode = S_IFIFO | 0755; EXPECT_LOOKUP(FUSE_ROOT_ID, RELPATH) .WillOnce(Invoke(ReturnErrno(ENOENT))); EXPECT_CALL(*m_mock, process( ResultOf([=](auto in) { const char *name = (const char*)in.body.bytes + sizeof(fuse_mknod_in); return (in.header.opcode == FUSE_MKNOD && in.body.mknod.mode == mode && (0 == strcmp(RELPATH, name))); }, Eq(true)), _) ).WillOnce(Invoke(ReturnErrno(EPERM))); EXPECT_NE(0, mkfifo(FULLPATH, mode)); EXPECT_EQ(EPERM, errno); } TEST_F(Mknod, fifo) { const char FULLPATH[] = "mountpoint/some_node"; const char RELPATH[] = "some_node"; mode_t mode = S_IFIFO | 0755; dev_t rdev = VNOVAL; /* Fifos don't have device numbers */ uint64_t ino = 42; EXPECT_LOOKUP(FUSE_ROOT_ID, RELPATH) .WillOnce(Invoke(ReturnErrno(ENOENT))); expect_mknod(FUSE_ROOT_ID, RELPATH, ino, mode, rdev); EXPECT_EQ(0, mkfifo(FULLPATH, mode)) << strerror(errno); } /* * Create a unix-domain socket. * * This test case doesn't actually need root privileges. */ TEST_F(Mknod, socket) { const char FULLPATH[] = "mountpoint/some_node"; const char RELPATH[] = "some_node"; mode_t mode = S_IFSOCK | 0755; struct sockaddr_un sa; int fd; dev_t rdev = -1; /* Really it's a don't care */ uint64_t ino = 42; EXPECT_LOOKUP(FUSE_ROOT_ID, RELPATH) .WillOnce(Invoke(ReturnErrno(ENOENT))); expect_mknod(FUSE_ROOT_ID, RELPATH, ino, mode, rdev); fd = socket(AF_UNIX, SOCK_STREAM, 0); ASSERT_LE(0, fd) << strerror(errno); sa.sun_family = AF_UNIX; strlcpy(sa.sun_path, FULLPATH, sizeof(sa.sun_path)); sa.sun_len = sizeof(FULLPATH); ASSERT_EQ(0, bind(fd, (struct sockaddr*)&sa, sizeof(sa))) << strerror(errno); leak(fd); } /* * Nothing bad should happen if the server returns the parent's inode number * for the newly created file. Regression test for bug 263662. * https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=263662 */ TEST_F(Mknod, parent_inode) { const char FULLPATH[] = "mountpoint/parent/some_node"; const char PPATH[] = "parent"; const char RELPATH[] = "some_node"; mode_t mode = S_IFSOCK | 0755; struct sockaddr_un sa; sem_t sem; int fd; dev_t rdev = -1; /* Really it's a don't care */ uint64_t ino = 42; ASSERT_EQ(0, sem_init(&sem, 0, 0)) << strerror(errno); expect_lookup(PPATH, ino, S_IFDIR | 0755, 0, 1); EXPECT_LOOKUP(ino, RELPATH) .WillOnce(Invoke(ReturnErrno(ENOENT))); expect_mknod(ino, RELPATH, ino, mode, rdev); expect_forget(ino, 1, &sem); fd = socket(AF_UNIX, SOCK_STREAM, 0); ASSERT_LE(0, fd) << strerror(errno); sa.sun_family = AF_UNIX; strlcpy(sa.sun_path, FULLPATH, sizeof(sa.sun_path)); sa.sun_len = sizeof(FULLPATH); ASSERT_EQ(-1, bind(fd, (struct sockaddr*)&sa, sizeof(sa))); ASSERT_EQ(EIO, errno); leak(fd); sem_wait(&sem); sem_destroy(&sem); } /* - * fusefs(5) lacks VOP_WHITEOUT support. No bugzilla entry, because that's a + * fusefs(4) lacks VOP_WHITEOUT support. No bugzilla entry, because that's a * feature, not a bug */ TEST_F(Mknod, DISABLED_whiteout) { const char FULLPATH[] = "mountpoint/some_node"; const char RELPATH[] = "some_node"; mode_t mode = S_IFWHT | 0755; dev_t rdev = VNOVAL; /* whiteouts don't have device numbers */ uint64_t ino = 42; EXPECT_LOOKUP(FUSE_ROOT_ID, RELPATH) .WillOnce(Invoke(ReturnErrno(ENOENT))); expect_mknod(FUSE_ROOT_ID, RELPATH, ino, mode, rdev); EXPECT_EQ(0, mknod(FULLPATH, mode, 0)) << strerror(errno); } /* A server built at protocol version 7.11 or earlier can still use mknod */ TEST_F(Mknod_7_11, fifo) { const char FULLPATH[] = "mountpoint/some_node"; const char RELPATH[] = "some_node"; mode_t mode = S_IFIFO | 0755; dev_t rdev = VNOVAL; uint64_t ino = 42; EXPECT_LOOKUP(FUSE_ROOT_ID, RELPATH) .WillOnce(Invoke(ReturnErrno(ENOENT))); expect_mknod(FUSE_ROOT_ID, RELPATH, ino, mode, rdev); EXPECT_EQ(0, mkfifo(FULLPATH, mode)) << strerror(errno); } diff --git a/tests/sys/fs/fusefs/open.cc b/tests/sys/fs/fusefs/open.cc index 7ab3aeb6ba2a..ff736e6c3a94 100644 --- a/tests/sys/fs/fusefs/open.cc +++ b/tests/sys/fs/fusefs/open.cc @@ -1,341 +1,341 @@ /*- * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2019 The FreeBSD Foundation * * This software was developed by BFF Storage Systems, LLC 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. */ extern "C" { #include #include #include } #include "mockfs.hh" #include "utils.hh" using namespace testing; class Open: public FuseTest { public: /* Test an OK open of a file with the given flags */ void test_ok(int os_flags, int fuse_flags) { const char FULLPATH[] = "mountpoint/some_file.txt"; const char RELPATH[] = "some_file.txt"; uint64_t ino = 42; int fd; FuseTest::expect_lookup(RELPATH, ino, S_IFREG | 0644, 0, 1); EXPECT_CALL(*m_mock, process( ResultOf([=](auto in) { return (in.header.opcode == FUSE_OPEN && in.body.open.flags == (uint32_t)fuse_flags && in.header.nodeid == ino); }, Eq(true)), _) ).WillOnce(Invoke(ReturnImmediate([](auto in __unused, auto& out) { out.header.len = sizeof(out.header); SET_OUT_HEADER_LEN(out, open); }))); fd = open(FULLPATH, os_flags); ASSERT_LE(0, fd) << strerror(errno); leak(fd); } }; class OpenNoOpenSupport: public FuseTest { virtual void SetUp() { m_init_flags = FUSE_NO_OPEN_SUPPORT; FuseTest::SetUp(); } }; /* - * fusefs(5) does not support I/O on device nodes (neither does UFS). But it + * fusefs(4) does not support I/O on device nodes (neither does UFS). But it * shouldn't crash */ TEST_F(Open, chr) { const char FULLPATH[] = "mountpoint/zero"; const char RELPATH[] = "zero"; uint64_t ino = 42; EXPECT_LOOKUP(FUSE_ROOT_ID, RELPATH) .WillRepeatedly(Invoke(ReturnImmediate([=](auto in __unused, auto& out) { SET_OUT_HEADER_LEN(out, entry); out.body.entry.attr.mode = S_IFCHR | 0644; out.body.entry.nodeid = ino; out.body.entry.attr.nlink = 1; out.body.entry.attr_valid = UINT64_MAX; out.body.entry.attr.rdev = 44; /* /dev/zero's rdev */ }))); ASSERT_EQ(-1, open(FULLPATH, O_RDONLY)); EXPECT_EQ(EOPNOTSUPP, errno); } /* * The fuse daemon fails the request with enoent. This usually indicates a * race condition: some other FUSE client removed the file in between when the * kernel checked for it with lookup and tried to open it */ TEST_F(Open, enoent) { const char FULLPATH[] = "mountpoint/some_file.txt"; const char RELPATH[] = "some_file.txt"; uint64_t ino = 42; sem_t sem; ASSERT_EQ(0, sem_init(&sem, 0, 0)) << strerror(errno); expect_lookup(RELPATH, ino, S_IFREG | 0644, 0, 1); EXPECT_CALL(*m_mock, process( ResultOf([=](auto in) { return (in.header.opcode == FUSE_OPEN && in.header.nodeid == ino); }, Eq(true)), _) ).WillOnce(Invoke(ReturnErrno(ENOENT))); // Since FUSE_OPEN returns ENOENT, the kernel will reclaim the vnode // and send a FUSE_FORGET expect_forget(ino, 1, &sem); ASSERT_EQ(-1, open(FULLPATH, O_RDONLY)); EXPECT_EQ(ENOENT, errno); sem_wait(&sem); sem_destroy(&sem); } /* * The daemon is responsible for checking file permissions (unless the * default_permissions mount option was used) */ TEST_F(Open, eperm) { const char FULLPATH[] = "mountpoint/some_file.txt"; const char RELPATH[] = "some_file.txt"; uint64_t ino = 42; expect_lookup(RELPATH, ino, S_IFREG | 0644, 0, 1); EXPECT_CALL(*m_mock, process( ResultOf([=](auto in) { return (in.header.opcode == FUSE_OPEN && in.header.nodeid == ino); }, Eq(true)), _) ).WillOnce(Invoke(ReturnErrno(EPERM))); ASSERT_EQ(-1, open(FULLPATH, O_RDONLY)); EXPECT_EQ(EPERM, errno); } /* * fusefs must issue multiple FUSE_OPEN operations if clients with different * credentials open the same file, even if they use the same mode. This is * necessary so that the daemon can validate each set of credentials. */ TEST_F(Open, multiple_creds) { const static char FULLPATH[] = "mountpoint/some_file.txt"; const static char RELPATH[] = "some_file.txt"; int fd1, status; const static uint64_t ino = 42; const static uint64_t fh0 = 100, fh1 = 200; /* Fork a child to open the file with different credentials */ fork(false, &status, [&] { expect_lookup(RELPATH, ino, S_IFREG | 0644, 0, 2); EXPECT_CALL(*m_mock, process( ResultOf([=](auto in) { return (in.header.opcode == FUSE_OPEN && in.header.pid == (uint32_t)getpid() && in.header.nodeid == ino); }, Eq(true)), _) ).WillOnce(Invoke( ReturnImmediate([](auto in __unused, auto& out) { out.body.open.fh = fh0; out.header.len = sizeof(out.header); SET_OUT_HEADER_LEN(out, open); }))); EXPECT_CALL(*m_mock, process( ResultOf([=](auto in) { return (in.header.opcode == FUSE_OPEN && in.header.pid != (uint32_t)getpid() && in.header.nodeid == ino); }, Eq(true)), _) ).WillOnce(Invoke( ReturnImmediate([](auto in __unused, auto& out) { out.body.open.fh = fh1; out.header.len = sizeof(out.header); SET_OUT_HEADER_LEN(out, open); }))); expect_flush(ino, 2, ReturnErrno(0)); expect_release(ino, fh0); expect_release(ino, fh1); fd1 = open(FULLPATH, O_RDONLY); ASSERT_LE(0, fd1) << strerror(errno); }, [] { int fd0; fd0 = open(FULLPATH, O_RDONLY); if (fd0 < 0) { perror("open"); return(1); } leak(fd0); return 0; } ); ASSERT_EQ(0, WEXITSTATUS(status)); close(fd1); } /* https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=236340 */ TEST_F(Open, DISABLED_o_append) { test_ok(O_WRONLY | O_APPEND, O_WRONLY | O_APPEND); } /* The kernel is supposed to filter out this flag */ TEST_F(Open, o_creat) { test_ok(O_WRONLY | O_CREAT, O_WRONLY); } /* https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=236340 */ TEST_F(Open, DISABLED_o_direct) { test_ok(O_WRONLY | O_DIRECT, O_WRONLY | O_DIRECT); } /* The kernel is supposed to filter out this flag */ TEST_F(Open, o_excl) { test_ok(O_WRONLY | O_EXCL, O_WRONLY); } TEST_F(Open, o_exec) { test_ok(O_EXEC, O_EXEC); } /* The kernel is supposed to filter out this flag */ TEST_F(Open, o_noctty) { test_ok(O_WRONLY | O_NOCTTY, O_WRONLY); } TEST_F(Open, o_rdonly) { test_ok(O_RDONLY, O_RDONLY); } /* https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=236340 */ TEST_F(Open, DISABLED_o_trunc) { test_ok(O_WRONLY | O_TRUNC, O_WRONLY | O_TRUNC); } TEST_F(Open, o_wronly) { test_ok(O_WRONLY, O_WRONLY); } TEST_F(Open, o_rdwr) { test_ok(O_RDWR, O_RDWR); } /* * Without FUSE_NO_OPEN_SUPPORT, returning ENOSYS is an error */ TEST_F(Open, enosys) { const char FULLPATH[] = "mountpoint/some_file.txt"; const char RELPATH[] = "some_file.txt"; uint64_t ino = 42; int fd; FuseTest::expect_lookup(RELPATH, ino, S_IFREG | 0644, 0, 1); EXPECT_CALL(*m_mock, process( ResultOf([=](auto in) { return (in.header.opcode == FUSE_OPEN && in.body.open.flags == (uint32_t)O_RDONLY && in.header.nodeid == ino); }, Eq(true)), _) ).Times(1) .WillOnce(Invoke(ReturnErrno(ENOSYS))); fd = open(FULLPATH, O_RDONLY); ASSERT_EQ(-1, fd) << strerror(errno); EXPECT_EQ(ENOSYS, errno); } /* * If a fuse server sets FUSE_NO_OPEN_SUPPORT and returns ENOSYS to a * FUSE_OPEN, then it and subsequent FUSE_OPEN and FUSE_RELEASE operations will * also succeed automatically without being sent to the server. */ TEST_F(OpenNoOpenSupport, enosys) { const char FULLPATH[] = "mountpoint/some_file.txt"; const char RELPATH[] = "some_file.txt"; uint64_t ino = 42; int fd; FuseTest::expect_lookup(RELPATH, ino, S_IFREG | 0644, 0, 2); EXPECT_CALL(*m_mock, process( ResultOf([=](auto in) { return (in.header.opcode == FUSE_OPEN && in.body.open.flags == (uint32_t)O_RDONLY && in.header.nodeid == ino); }, Eq(true)), _) ).Times(1) .WillOnce(Invoke(ReturnErrno(ENOSYS))); expect_flush(ino, 1, ReturnErrno(ENOSYS)); fd = open(FULLPATH, O_RDONLY); ASSERT_LE(0, fd) << strerror(errno); close(fd); fd = open(FULLPATH, O_RDONLY); ASSERT_LE(0, fd) << strerror(errno); leak(fd); } diff --git a/tests/sys/fs/fusefs/xattr.cc b/tests/sys/fs/fusefs/xattr.cc index 7fa2a741e074..b1cbb9ffa768 100644 --- a/tests/sys/fs/fusefs/xattr.cc +++ b/tests/sys/fs/fusefs/xattr.cc @@ -1,843 +1,843 @@ /*- * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2019 The FreeBSD Foundation * * This software was developed by BFF Storage Systems, LLC 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. */ /* Tests for all things relating to extended attributes and FUSE */ extern "C" { #include #include #include #include #include #include } #include "mockfs.hh" #include "utils.hh" using namespace testing; const char FULLPATH[] = "mountpoint/some_file.txt"; const char RELPATH[] = "some_file.txt"; static sem_t killer_semaphore; void* killer(void* target) { pid_t pid = *(pid_t*)target; sem_wait(&killer_semaphore); if (verbosity > 1) printf("Killing! pid %d\n", pid); kill(pid, SIGINT); return(NULL); } class Xattr: public FuseTest { public: void expect_listxattr(uint64_t ino, uint32_t size, ProcessMockerT r, Sequence *seq = NULL) { if (seq == NULL) { EXPECT_CALL(*m_mock, process( ResultOf([=](auto in) { return (in.header.opcode == FUSE_LISTXATTR && in.header.nodeid == ino && in.body.listxattr.size == size); }, Eq(true)), _) ).WillOnce(Invoke(r)) .RetiresOnSaturation(); } else { EXPECT_CALL(*m_mock, process( ResultOf([=](auto in) { return (in.header.opcode == FUSE_LISTXATTR && in.header.nodeid == ino && in.body.listxattr.size == size); }, Eq(true)), _) ).InSequence(*seq) .WillOnce(Invoke(r)) .RetiresOnSaturation(); } } void expect_removexattr(uint64_t ino, const char *attr, int error) { EXPECT_CALL(*m_mock, process( ResultOf([=](auto in) { const char *a = (const char*)in.body.bytes; return (in.header.opcode == FUSE_REMOVEXATTR && in.header.nodeid == ino && 0 == strcmp(attr, a)); }, Eq(true)), _) ).WillOnce(Invoke(ReturnErrno(error))); } void expect_setxattr(uint64_t ino, const char *attr, const char *value, ProcessMockerT r) { EXPECT_CALL(*m_mock, process( ResultOf([=](auto in) { const char *a = (const char*)in.body.bytes + sizeof(fuse_setxattr_in); const char *v = a + strlen(a) + 1; return (in.header.opcode == FUSE_SETXATTR && in.header.nodeid == ino && 0 == strcmp(attr, a) && 0 == strcmp(value, v)); }, Eq(true)), _) ).WillOnce(Invoke(r)); } }; class Getxattr: public Xattr {}; class Listxattr: public Xattr {}; /* Listxattr tests that need to use a signal */ class ListxattrSig: public Listxattr { public: pthread_t m_killer_th; pid_t m_child; void SetUp() { /* * Mount with -o nointr so the mount can't get interrupted while * waiting for a response from the server */ m_nointr = true; FuseTest::SetUp(); ASSERT_EQ(0, sem_init(&killer_semaphore, 0, 0)) << strerror(errno); } void TearDown() { if (m_killer_th != NULL) { pthread_join(m_killer_th, NULL); } sem_destroy(&killer_semaphore); FuseTest::TearDown(); } }; class Removexattr: public Xattr {}; class Setxattr: public Xattr {}; class RofsXattr: public Xattr { public: virtual void SetUp() { m_ro = true; Xattr::SetUp(); } }; /* * If the extended attribute does not exist on this file, the daemon should * return ENOATTR (ENODATA on Linux, but it's up to the daemon to choose the * correct errror code) */ TEST_F(Getxattr, enoattr) { char data[80]; uint64_t ino = 42; int ns = EXTATTR_NAMESPACE_USER; ssize_t r; expect_lookup(RELPATH, ino, S_IFREG | 0644, 0, 1); expect_getxattr(ino, "user.foo", ReturnErrno(ENOATTR)); r = extattr_get_file(FULLPATH, ns, "foo", data, sizeof(data)); ASSERT_EQ(-1, r); ASSERT_EQ(ENOATTR, errno); } /* * If the filesystem returns ENOSYS, then it will be treated as a permanent * failure and all future VOP_GETEXTATTR calls will fail with EOPNOTSUPP * without querying the filesystem daemon */ TEST_F(Getxattr, enosys) { char data[80]; uint64_t ino = 42; int ns = EXTATTR_NAMESPACE_USER; ssize_t r; expect_lookup(RELPATH, ino, S_IFREG | 0644, 0, 2); expect_getxattr(ino, "user.foo", ReturnErrno(ENOSYS)); r = extattr_get_file(FULLPATH, ns, "foo", data, sizeof(data)); ASSERT_EQ(-1, r); EXPECT_EQ(EOPNOTSUPP, errno); /* Subsequent attempts should not query the filesystem at all */ r = extattr_get_file(FULLPATH, ns, "foo", data, sizeof(data)); ASSERT_EQ(-1, r); EXPECT_EQ(EOPNOTSUPP, errno); } /* * On FreeBSD, if the user passes an insufficiently large buffer then the * filesystem is supposed to copy as much of the attribute's value as will fit. * * On Linux, however, the filesystem is supposed to return ERANGE. * * libfuse specifies the Linux behavior. However, that's probably an error. * It would probably be correct for the filesystem to use platform-dependent * behavior. * * This test case covers a filesystem that uses the Linux behavior * TODO: require FreeBSD Behavior. */ TEST_F(Getxattr, erange) { char data[10]; uint64_t ino = 42; int ns = EXTATTR_NAMESPACE_USER; ssize_t r; expect_lookup(RELPATH, ino, S_IFREG | 0644, 0, 1); expect_getxattr(ino, "user.foo", ReturnErrno(ERANGE)); r = extattr_get_file(FULLPATH, ns, "foo", data, sizeof(data)); ASSERT_EQ(-1, r); ASSERT_EQ(ERANGE, errno); } /* * If the user passes a 0-length buffer, then the daemon should just return the * size of the attribute */ TEST_F(Getxattr, size_only) { uint64_t ino = 42; int ns = EXTATTR_NAMESPACE_USER; expect_lookup(RELPATH, ino, S_IFREG | 0644, 0, 1); expect_getxattr(ino, "user.foo", ReturnImmediate([](auto in __unused, auto& out) { SET_OUT_HEADER_LEN(out, getxattr); out.body.getxattr.size = 99; }) ); ASSERT_EQ(99, extattr_get_file(FULLPATH, ns, "foo", NULL, 0)) << strerror(errno);; } /* * Successfully get an attribute from the system namespace */ TEST_F(Getxattr, system) { uint64_t ino = 42; char data[80]; const char value[] = "whatever"; ssize_t value_len = strlen(value) + 1; int ns = EXTATTR_NAMESPACE_SYSTEM; ssize_t r; expect_lookup(RELPATH, ino, S_IFREG | 0644, 0, 1); expect_getxattr(ino, "system.foo", ReturnImmediate([&](auto in __unused, auto& out) { memcpy((void*)out.body.bytes, value, value_len); out.header.len = sizeof(out.header) + value_len; }) ); r = extattr_get_file(FULLPATH, ns, "foo", data, sizeof(data)); ASSERT_EQ(value_len, r) << strerror(errno); EXPECT_STREQ(value, data); } /* * Successfully get an attribute from the user namespace */ TEST_F(Getxattr, user) { uint64_t ino = 42; char data[80]; const char value[] = "whatever"; ssize_t value_len = strlen(value) + 1; int ns = EXTATTR_NAMESPACE_USER; ssize_t r; expect_lookup(RELPATH, ino, S_IFREG | 0644, 0, 1); expect_getxattr(ino, "user.foo", ReturnImmediate([&](auto in __unused, auto& out) { memcpy((void*)out.body.bytes, value, value_len); out.header.len = sizeof(out.header) + value_len; }) ); r = extattr_get_file(FULLPATH, ns, "foo", data, sizeof(data)); ASSERT_EQ(value_len, r) << strerror(errno); EXPECT_STREQ(value, data); } /* * If the filesystem returns ENOSYS, then it will be treated as a permanent * failure and all future VOP_LISTEXTATTR calls will fail with EOPNOTSUPP * without querying the filesystem daemon */ TEST_F(Listxattr, enosys) { uint64_t ino = 42; int ns = EXTATTR_NAMESPACE_USER; expect_lookup(RELPATH, ino, S_IFREG | 0644, 0, 2); expect_listxattr(ino, 0, ReturnErrno(ENOSYS)); ASSERT_EQ(-1, extattr_list_file(FULLPATH, ns, NULL, 0)); EXPECT_EQ(EOPNOTSUPP, errno); /* Subsequent attempts should not query the filesystem at all */ ASSERT_EQ(-1, extattr_list_file(FULLPATH, ns, NULL, 0)); EXPECT_EQ(EOPNOTSUPP, errno); } /* * Listing extended attributes failed because they aren't configured on this * filesystem */ TEST_F(Listxattr, enotsup) { uint64_t ino = 42; int ns = EXTATTR_NAMESPACE_USER; expect_lookup(RELPATH, ino, S_IFREG | 0644, 0, 1); expect_listxattr(ino, 0, ReturnErrno(ENOTSUP)); ASSERT_EQ(-1, extattr_list_file(FULLPATH, ns, NULL, 0)); ASSERT_EQ(ENOTSUP, errno); } /* * On FreeBSD, if the user passes an insufficiently large buffer to * extattr_list_file(2) or VOP_LISTEXTATTR(9), then the file system is supposed * to copy as much of the attribute's value as will fit. * * On Linux, however, the file system is supposed to return ERANGE if an * insufficiently large buffer is passed to listxattr(2). * - * fusefs(5) must guarantee the usual FreeBSD behavior. + * fusefs(4) must guarantee the usual FreeBSD behavior. */ TEST_F(Listxattr, erange) { uint64_t ino = 42; int ns = EXTATTR_NAMESPACE_USER; char attrs[9] = "user.foo"; char expected[3] = {3, 'f', 'o'}; char buf[3]; expect_lookup(RELPATH, ino, S_IFREG | 0644, 0, 1); expect_listxattr(ino, 0, ReturnImmediate([](auto i __unused, auto& out) { out.body.listxattr.size = sizeof(attrs); SET_OUT_HEADER_LEN(out, listxattr); })); expect_listxattr(ino, sizeof(attrs), ReturnImmediate([&](auto in __unused, auto& out) { memcpy((void*)out.body.bytes, attrs, sizeof(attrs)); out.header.len = sizeof(fuse_out_header) + sizeof(attrs); })); ASSERT_EQ(static_cast(sizeof(buf)), extattr_list_file(FULLPATH, ns, buf, sizeof(buf))); ASSERT_EQ(0, memcmp(expected, buf, sizeof(buf))); } /* * A buggy or malicious file system always returns ERANGE, even if we pass an * appropriately sized buffer. That will send the kernel into an infinite * loop. This test will ensure that the loop is interruptible by killing the * blocked process with SIGINT. */ TEST_F(ListxattrSig, erange_forever) { uint64_t ino = 42; uint32_t lie_size = 10; int status; fork(false, &status, [&] { EXPECT_LOOKUP(FUSE_ROOT_ID, RELPATH) .WillRepeatedly(Invoke( ReturnImmediate([=](auto in __unused, auto& out) { SET_OUT_HEADER_LEN(out, entry); out.body.entry.attr.mode = S_IFREG | 0644; out.body.entry.nodeid = ino; out.body.entry.attr.nlink = 1; out.body.entry.attr_valid = UINT64_MAX; out.body.entry.entry_valid = UINT64_MAX; }))); EXPECT_CALL(*m_mock, process( ResultOf([=](auto in) { return (in.header.opcode == FUSE_LISTXATTR && in.header.nodeid == ino && in.body.listxattr.size == 0); }, Eq(true)), _) ).WillRepeatedly(ReturnImmediate([=](auto i __unused, auto& out) { /* The file system requests 10 bytes, but it's a lie */ out.body.listxattr.size = lie_size; SET_OUT_HEADER_LEN(out, listxattr); /* * We can send the signal any time after fusefs enters * VOP_LISTEXTATTR */ sem_post(&killer_semaphore); })); /* * Even though the kernel faithfully respects our size request, * we'll return ERANGE anyway. */ EXPECT_CALL(*m_mock, process( ResultOf([=](auto in) { return (in.header.opcode == FUSE_LISTXATTR && in.header.nodeid == ino && in.body.listxattr.size == lie_size); }, Eq(true)), _) ).WillRepeatedly(ReturnErrno(ERANGE)); ASSERT_EQ(0, pthread_create(&m_killer_th, NULL, killer, &m_mock->m_child_pid)) << strerror(errno); }, [] { /* Child process will block until it gets signaled */ int ns = EXTATTR_NAMESPACE_USER; char buf[3]; extattr_list_file(FULLPATH, ns, buf, sizeof(buf)); return 0; } ); ASSERT_TRUE(WIFSIGNALED(status)); } /* * Get the size of the list that it would take to list no extended attributes */ TEST_F(Listxattr, size_only_empty) { uint64_t ino = 42; int ns = EXTATTR_NAMESPACE_USER; expect_lookup(RELPATH, ino, S_IFREG | 0644, 0, 1); expect_listxattr(ino, 0, ReturnImmediate([](auto i __unused, auto& out) { out.body.listxattr.size = 0; SET_OUT_HEADER_LEN(out, listxattr); })); ASSERT_EQ(0, extattr_list_file(FULLPATH, ns, NULL, 0)) << strerror(errno); } /* * Get the size of the list that it would take to list some extended * attributes. Due to the format differences between a FreeBSD and a * Linux/FUSE extended attribute list, fuse(4) will actually allocate a buffer * and get the whole list, then convert it, just to figure out its size. */ TEST_F(Listxattr, size_only_nonempty) { uint64_t ino = 42; int ns = EXTATTR_NAMESPACE_USER; char attrs[9] = "user.foo"; expect_lookup(RELPATH, ino, S_IFREG | 0644, 0, 1); expect_listxattr(ino, 0, ReturnImmediate([](auto i __unused, auto& out) { out.body.listxattr.size = sizeof(attrs); SET_OUT_HEADER_LEN(out, listxattr); })); expect_listxattr(ino, sizeof(attrs), ReturnImmediate([=](auto in __unused, auto& out) { size_t l = sizeof(attrs); strlcpy((char*)out.body.bytes, attrs, l); out.header.len = sizeof(fuse_out_header) + l; }) ); ASSERT_EQ(4, extattr_list_file(FULLPATH, ns, NULL, 0)) << strerror(errno); } /* * The list of extended attributes grows in between the server's two calls to * FUSE_LISTXATTR. */ TEST_F(Listxattr, size_only_race_bigger) { uint64_t ino = 42; int ns = EXTATTR_NAMESPACE_USER; char attrs0[9] = "user.foo"; char attrs1[18] = "user.foo\0user.bar"; Sequence seq; EXPECT_LOOKUP(FUSE_ROOT_ID, RELPATH) .WillRepeatedly(Invoke( ReturnImmediate([=](auto in __unused, auto& out) { SET_OUT_HEADER_LEN(out, entry); out.body.entry.attr.mode = S_IFREG | 0644; out.body.entry.nodeid = ino; out.body.entry.attr.nlink = 1; out.body.entry.attr_valid = UINT64_MAX; out.body.entry.entry_valid = UINT64_MAX; }))); expect_listxattr(ino, 0, ReturnImmediate([](auto i __unused, auto& out) { out.body.listxattr.size = sizeof(attrs0); SET_OUT_HEADER_LEN(out, listxattr); }), &seq); /* * After the first FUSE_LISTXATTR the list grew, so the second * operation returns ERANGE. */ expect_listxattr(ino, sizeof(attrs0), ReturnErrno(ERANGE), &seq); /* And now the kernel retries */ expect_listxattr(ino, 0, ReturnImmediate([](auto i __unused, auto& out) { out.body.listxattr.size = sizeof(attrs1); SET_OUT_HEADER_LEN(out, listxattr); }), &seq); expect_listxattr(ino, sizeof(attrs1), ReturnImmediate([&](auto in __unused, auto& out) { memcpy((char*)out.body.bytes, attrs1, sizeof(attrs1)); out.header.len = sizeof(fuse_out_header) + sizeof(attrs1); }), &seq ); /* Userspace should never know about the retry */ ASSERT_EQ(8, extattr_list_file(FULLPATH, ns, NULL, 0)) << strerror(errno); } /* * The list of extended attributes shrinks in between the server's two calls to * FUSE_LISTXATTR */ TEST_F(Listxattr, size_only_race_smaller) { uint64_t ino = 42; int ns = EXTATTR_NAMESPACE_USER; char attrs0[18] = "user.foo\0user.bar"; char attrs1[9] = "user.foo"; expect_lookup(RELPATH, ino, S_IFREG | 0644, 0, 1); expect_listxattr(ino, 0, ReturnImmediate([](auto i __unused, auto& out) { out.body.listxattr.size = sizeof(attrs0); SET_OUT_HEADER_LEN(out, listxattr); })); expect_listxattr(ino, sizeof(attrs0), ReturnImmediate([&](auto in __unused, auto& out) { strlcpy((char*)out.body.bytes, attrs1, sizeof(attrs1)); out.header.len = sizeof(fuse_out_header) + sizeof(attrs1); }) ); ASSERT_EQ(4, extattr_list_file(FULLPATH, ns, NULL, 0)) << strerror(errno); } TEST_F(Listxattr, size_only_really_big) { uint64_t ino = 42; int ns = EXTATTR_NAMESPACE_USER; expect_lookup(RELPATH, ino, S_IFREG | 0644, 0, 1); expect_listxattr(ino, 0, ReturnImmediate([](auto i __unused, auto& out) { out.body.listxattr.size = 16000; SET_OUT_HEADER_LEN(out, listxattr); })); expect_listxattr(ino, 16000, ReturnImmediate([](auto in __unused, auto& out) { const char l[16] = "user.foobarbang"; for (int i=0; i < 1000; i++) { memcpy(&out.body.bytes[16 * i], l, 16); } out.header.len = sizeof(fuse_out_header) + 16000; }) ); ASSERT_EQ(11000, extattr_list_file(FULLPATH, ns, NULL, 0)) << strerror(errno); } /* * List all of the user attributes of a file which has both user and system * attributes */ TEST_F(Listxattr, user) { uint64_t ino = 42; int ns = EXTATTR_NAMESPACE_USER; char data[80]; char expected[9] = {3, 'f', 'o', 'o', 4, 'b', 'a', 'n', 'g'}; char attrs[28] = "user.foo\0system.x\0user.bang"; expect_lookup(RELPATH, ino, S_IFREG | 0644, 0, 1); expect_listxattr(ino, 0, ReturnImmediate([&](auto in __unused, auto& out) { out.body.listxattr.size = sizeof(attrs); SET_OUT_HEADER_LEN(out, listxattr); }) ); expect_listxattr(ino, sizeof(attrs), ReturnImmediate([&](auto in __unused, auto& out) { memcpy((void*)out.body.bytes, attrs, sizeof(attrs)); out.header.len = sizeof(fuse_out_header) + sizeof(attrs); })); ASSERT_EQ(static_cast(sizeof(expected)), extattr_list_file(FULLPATH, ns, data, sizeof(data))) << strerror(errno); ASSERT_EQ(0, memcmp(expected, data, sizeof(expected))); } /* * List all of the system attributes of a file which has both user and system * attributes */ TEST_F(Listxattr, system) { uint64_t ino = 42; int ns = EXTATTR_NAMESPACE_SYSTEM; char data[80]; char expected[2] = {1, 'x'}; char attrs[28] = "user.foo\0system.x\0user.bang"; expect_lookup(RELPATH, ino, S_IFREG | 0644, 0, 1); expect_listxattr(ino, 0, ReturnImmediate([&](auto in __unused, auto& out) { out.body.listxattr.size = sizeof(attrs); SET_OUT_HEADER_LEN(out, listxattr); }) ); expect_listxattr(ino, sizeof(attrs), ReturnImmediate([&](auto in __unused, auto& out) { memcpy((void*)out.body.bytes, attrs, sizeof(attrs)); out.header.len = sizeof(fuse_out_header) + sizeof(attrs); })); ASSERT_EQ(static_cast(sizeof(expected)), extattr_list_file(FULLPATH, ns, data, sizeof(data))) << strerror(errno); ASSERT_EQ(0, memcmp(expected, data, sizeof(expected))); } /* Fail to remove a nonexistent attribute */ TEST_F(Removexattr, enoattr) { uint64_t ino = 42; int ns = EXTATTR_NAMESPACE_USER; expect_lookup(RELPATH, ino, S_IFREG | 0644, 0, 1); expect_removexattr(ino, "user.foo", ENOATTR); ASSERT_EQ(-1, extattr_delete_file(FULLPATH, ns, "foo")); ASSERT_EQ(ENOATTR, errno); } /* * If the filesystem returns ENOSYS, then it will be treated as a permanent * failure and all future VOP_DELETEEXTATTR calls will fail with EOPNOTSUPP * without querying the filesystem daemon */ TEST_F(Removexattr, enosys) { uint64_t ino = 42; int ns = EXTATTR_NAMESPACE_USER; expect_lookup(RELPATH, ino, S_IFREG | 0644, 0, 2); expect_removexattr(ino, "user.foo", ENOSYS); ASSERT_EQ(-1, extattr_delete_file(FULLPATH, ns, "foo")); EXPECT_EQ(EOPNOTSUPP, errno); /* Subsequent attempts should not query the filesystem at all */ ASSERT_EQ(-1, extattr_delete_file(FULLPATH, ns, "foo")); EXPECT_EQ(EOPNOTSUPP, errno); } /* Successfully remove a user xattr */ TEST_F(Removexattr, user) { uint64_t ino = 42; int ns = EXTATTR_NAMESPACE_USER; expect_lookup(RELPATH, ino, S_IFREG | 0644, 0, 1); expect_removexattr(ino, "user.foo", 0); ASSERT_EQ(0, extattr_delete_file(FULLPATH, ns, "foo")) << strerror(errno); } /* Successfully remove a system xattr */ TEST_F(Removexattr, system) { uint64_t ino = 42; int ns = EXTATTR_NAMESPACE_SYSTEM; expect_lookup(RELPATH, ino, S_IFREG | 0644, 0, 1); expect_removexattr(ino, "system.foo", 0); ASSERT_EQ(0, extattr_delete_file(FULLPATH, ns, "foo")) << strerror(errno); } /* * If the filesystem returns ENOSYS, then it will be treated as a permanent * failure and all future VOP_SETEXTATTR calls will fail with EOPNOTSUPP * without querying the filesystem daemon */ TEST_F(Setxattr, enosys) { uint64_t ino = 42; const char value[] = "whatever"; ssize_t value_len = strlen(value) + 1; int ns = EXTATTR_NAMESPACE_USER; ssize_t r; expect_lookup(RELPATH, ino, S_IFREG | 0644, 0, 2); expect_setxattr(ino, "user.foo", value, ReturnErrno(ENOSYS)); r = extattr_set_file(FULLPATH, ns, "foo", (const void*)value, value_len); ASSERT_EQ(-1, r); EXPECT_EQ(EOPNOTSUPP, errno); /* Subsequent attempts should not query the filesystem at all */ r = extattr_set_file(FULLPATH, ns, "foo", (const void*)value, value_len); ASSERT_EQ(-1, r); EXPECT_EQ(EOPNOTSUPP, errno); } /* * SETXATTR will return ENOTSUP if the namespace is invalid or the filesystem * as currently configured doesn't support extended attributes. */ TEST_F(Setxattr, enotsup) { uint64_t ino = 42; const char value[] = "whatever"; ssize_t value_len = strlen(value) + 1; int ns = EXTATTR_NAMESPACE_USER; ssize_t r; expect_lookup(RELPATH, ino, S_IFREG | 0644, 0, 1); expect_setxattr(ino, "user.foo", value, ReturnErrno(ENOTSUP)); r = extattr_set_file(FULLPATH, ns, "foo", (const void*)value, value_len); ASSERT_EQ(-1, r); EXPECT_EQ(ENOTSUP, errno); } /* * Successfully set a user attribute. */ TEST_F(Setxattr, user) { uint64_t ino = 42; const char value[] = "whatever"; ssize_t value_len = strlen(value) + 1; int ns = EXTATTR_NAMESPACE_USER; ssize_t r; expect_lookup(RELPATH, ino, S_IFREG | 0644, 0, 1); expect_setxattr(ino, "user.foo", value, ReturnErrno(0)); r = extattr_set_file(FULLPATH, ns, "foo", (const void*)value, value_len); ASSERT_EQ(value_len, r) << strerror(errno); } /* * Successfully set a system attribute. */ TEST_F(Setxattr, system) { uint64_t ino = 42; const char value[] = "whatever"; ssize_t value_len = strlen(value) + 1; int ns = EXTATTR_NAMESPACE_SYSTEM; ssize_t r; expect_lookup(RELPATH, ino, S_IFREG | 0644, 0, 1); expect_setxattr(ino, "system.foo", value, ReturnErrno(0)); r = extattr_set_file(FULLPATH, ns, "foo", (const void*)value, value_len); ASSERT_EQ(value_len, r) << strerror(errno); } TEST_F(RofsXattr, deleteextattr_erofs) { uint64_t ino = 42; int ns = EXTATTR_NAMESPACE_USER; expect_lookup(RELPATH, ino, S_IFREG | 0644, 0, 1); ASSERT_EQ(-1, extattr_delete_file(FULLPATH, ns, "foo")); ASSERT_EQ(EROFS, errno); } TEST_F(RofsXattr, setextattr_erofs) { uint64_t ino = 42; const char value[] = "whatever"; ssize_t value_len = strlen(value) + 1; int ns = EXTATTR_NAMESPACE_USER; ssize_t r; expect_lookup(RELPATH, ino, S_IFREG | 0644, 0, 1); r = extattr_set_file(FULLPATH, ns, "foo", (const void*)value, value_len); ASSERT_EQ(-1, r); EXPECT_EQ(EROFS, errno); } diff --git a/tools/test/stress2/misc/devfs5.sh b/tools/test/stress2/misc/devfs5.sh index ab96b37bfa2b..5a72d7db9efb 100755 --- a/tools/test/stress2/misc/devfs5.sh +++ b/tools/test/stress2/misc/devfs5.sh @@ -1,68 +1,68 @@ #!/bin/sh # # SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2019 Dell EMC Isilon # # 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. # [ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 # Test scenario for https://reviews.freebsd.org/D20411 -# Add devfs(5) support for VOP_MKDIR(9) and VOP_RMDIR(9) +# Add devfs(4) support for VOP_MKDIR(9) and VOP_RMDIR(9) . ../default.cfg mkdir /dev/devfs5 2>/dev/null || exit 0 rmdir /dev/devfs5 mount | grep -q "on $mntpoint " && umount -f $mntpoint mount -t devfs null $mntpoint || exit 1 (cd ../testcases/swap; ./swap -t 30m -i 20 -h -l 100) & spid=$! cd $mntpoint N=3000 for i in `jot 25`; do ( mkdir s$i; cd s$i for k in `jot 5`; do for j in `jot $N`; do mkdir d$i.$j; done for j in `jot $N`; do rmdir d$i.$j; done done cd ..; rmdir s$i ) & pids="$pids $!" done for i in $pids; do wait $i done while pkill swap; do :; done wait spid cd / while mount | grep -q "on $mntpoint "; do umount $mntpoint && break sleep 1 done exit 0 diff --git a/tools/test/stress2/misc/ext2fs3.sh b/tools/test/stress2/misc/ext2fs3.sh index f33b4cc73547..fd129a235102 100755 --- a/tools/test/stress2/misc/ext2fs3.sh +++ b/tools/test/stress2/misc/ext2fs3.sh @@ -1,68 +1,68 @@ #!/bin/sh # # Copyright (c) 2017 Dell EMC Isilon # All rights reserved. # # 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. # -# ext2fs(5) test scenario with a 1k block size +# ext2fs(4) test scenario with a 1k block size # "panic: ext2_reallocblks: alloc mismatch" seen. # "Fatal trap 12: page fault while in kernel mode" seen. [ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 [ -r /usr/src/tools/regression/fsx/fsx.c ] || exit 0 . ../default.cfg # Uses mke2fs from sysutils/e2fsprogs [ -z "`type mke2fs 2>/dev/null`" ] && echo "Skipping test as mke2fs not installed" && exit 0 dir=/tmp odir=`pwd` cd $dir cc -o fsx -Wall -Wextra -O2 -g /usr/src/tools/regression/fsx/fsx.c || exit 1 rm -f fsx.c cd $odir mount | grep "$mntpoint" | grep -q md$mdstart && umount $mntpoint mdconfig -l | grep -q md$mdstart && mdconfig -d -u $mdstart mdconfig -a -t swap -s 1g -u $mdstart mke2fs -m 0 -b 1024 /dev/md$mdstart > /dev/null mount -t ext2fs /dev/md$mdstart $mntpoint chmod 777 $mntpoint cp /tmp/fsx $mntpoint cd $mntpoint ./fsx -S 2016 -N 2000 ./TEST_FILE cd $here while mount | grep $mntpoint | grep -q /dev/md; do umount $mntpoint || sleep 1 done mdconfig -d -u $mdstart exit 0 diff --git a/tools/test/stress2/misc/fifo4.sh b/tools/test/stress2/misc/fifo4.sh index 2a8a149e3105..1578b8786d43 100755 --- a/tools/test/stress2/misc/fifo4.sh +++ b/tools/test/stress2/misc/fifo4.sh @@ -1,80 +1,80 @@ #!/bin/sh # # SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2018 Dell EMC Isilon # # 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. # -# tmpfs(5) version of fifo2.sh +# tmpfs(4) version of fifo2.sh # No problems seen on HEAD. [ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 . ../default.cfg odir=`pwd` cd /tmp sed '1,/^EOF/d' < $odir/fifo2.sh > fifo2.c rm -f /tmp/fifo2 mycc -o fifo2 -Wall -Wextra -O2 -g fifo2.c -lpthread || exit 1 rm -f fifo2.c mount | grep $mntpoint | grep -q /dev/md && umount -f $mntpoint mount -o size=1g -t tmpfs tmpfs $mntpoint chmod 777 $mntpoint for i in `jot 5`; do mkfifo $mntpoint/f$i chmod 777 $mntpoint/f$i done daemon sh -c "(cd $odir/../testcases/swap; ./swap -t 10m -i 20 -l 100)" > \ /dev/null sleeptime=12 st=`date '+%s'` while [ $((`date '+%s'` - st)) -lt $((10 * sleeptime)) ]; do (cd $mntpoint; /tmp/fifo2) & while ! pgrep -q fifo2; do :; done start=`date '+%s'` while [ $((`date '+%s'` - start)) -lt $sleeptime ]; do pgrep -q fifo2 || break sleep .5 done while pgrep -q fifo2; do pkill -9 fifo2; done wait done pkill -9 swap fifo2 while pgrep -q "swap|fifo2"; do pkill -9 swap fifo2; done for i in `jot 10`; do mount | grep -q "on $mntpoint " && \ umount $mntpoint > /dev/null 2>&1 && break sleep 10 done s=0 mount | grep -q "on $mntpoint " && { echo "umount $mntpoint failed"; s=1; } rm -f /tmp/fifo2 exit $s diff --git a/tools/test/stress2/misc/mkfifo5.sh b/tools/test/stress2/misc/mkfifo5.sh index c0355cef2db0..96d30e5fe024 100755 --- a/tools/test/stress2/misc/mkfifo5.sh +++ b/tools/test/stress2/misc/mkfifo5.sh @@ -1,214 +1,214 @@ #!/bin/sh # # Copyright (c) 2017 Dell EMC Isilon # All rights reserved. # # 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. # -# mkfifo(2), select(2) with tmpfs(5) scenario. +# mkfifo(2), select(2) with tmpfs(4) scenario. . ../default.cfg [ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 dir=/tmp odir=`pwd` cd $dir sed '1,/^EOF/d' < $odir/$0 > $dir/mkfifo5.c mycc -o mkfifo5 -Wall -Wextra -O0 -g mkfifo5.c || exit 1 rm -f mkfifo5.c cd $odir mount | grep -q "on $mntpoint " && umount -f $mntpoint mount -o size=1g -t tmpfs tmpfs $mntpoint fifo=$mntpoint/fifo.file cd $mntpoint /tmp/mkfifo5 $fifo s=$? cd $odir while mount | grep "on $mntpoint " | grep -q tmpfs; do umount $mntpoint || sleep 1 done rm -rf /tmp/mkfifo5 exit $s EOF #include #include #include #include #include #include #include #include #include #include #include #include static char *path; #define PARALLEL 1 static void reader(void) { fd_set rset; struct timeval timeout; int fd, n, r; char ch; do { if((fd = open(path, O_RDONLY)) == -1) if (errno != EINTR) err(1, "open(%s, O_RDONLY)", path); if (fd == -1) warn("open(%s) ro", path); } while (fd == -1); /* Read one character */ FD_ZERO(&rset); FD_SET(fd, &rset); if ((n = select(fd + 1, &rset, NULL, NULL, NULL)) < 0) if (errno != EINTR) err(1, "select()"); if (n == 1 && FD_ISSET(fd, &rset)) { r = read(fd, &ch, 1); if (r == -1) err(1, "read"); if (r == 0) fprintf(stderr, "read(1): EOF\n"); } /* timeout */ ch = 'z'; FD_ZERO(&rset); FD_SET(fd, &rset); timeout.tv_sec = 1; timeout.tv_usec = 0; if ((n = select(fd + 1, &rset, NULL, NULL, &timeout)) < 0) if (errno != EINTR) err(1, "select()"); if (n != 1) fprintf(stderr, "FAIL Expected n == 0, got %d\n", n); if (n == 1 && FD_ISSET(fd, &rset)) { r = read(fd, &ch, 1); if (r == -1) err(1, "read"); if (r == 0) fprintf(stderr, "read(2): EOF\n"); } /* timeout */ ch = 'z'; FD_ZERO(&rset); FD_SET(fd, &rset); timeout.tv_sec = 1; timeout.tv_usec = 0; if ((n = select(fd + 1, &rset, NULL, NULL, &timeout)) < 0) if (errno != EINTR) err(1, "select()"); if (n != 1) fprintf(stderr, "FAIL Expected n == 0, got %d\n", n); if (n == 1 && FD_ISSET(fd, &rset)) { r = read(fd, &ch, 1); if (r == -1) err(1, "read"); if (r != 0) fprintf(stderr, "read(3): %c\n", ch); } if (close(fd) == -1) err(1, "close() in child"); _exit(n == 1 ? 0 : 1); } static void writer(void) { int fd; do { if ((fd = open(path, O_WRONLY)) == -1) if (errno != EINTR) err(1, "open(%s, O_WRONLY)", path); if (fd == -1) warn("open(%s) wr", path); } while (fd == -1); if (write(fd, "a", 1) != 1) err(1, "write one"); if (write(fd, "b", 1) != 1) err(1, "write one"); if (close(fd) == -1) warn("close() in parent"); } static void test(void) { pid_t pid; int status; if ((pid = fork()) == 0) reader(); writer(); if (waitpid(pid, &status, 0) != pid) err(1, "waitpid(%d)", pid); _exit(status != 0); } int main(int argc __unused, char *argv[]) { int e, i, pids[PARALLEL], status; if (argc != 2) { fprintf(stderr, "Usage: %s \n", argv[0]); exit(1); } path = argv[1]; e = 0; unlink(path); if (mkfifo(path, 0640) == -1) err(1, "mkfifo(%s)", path); for (i = 0; i < PARALLEL; i++) { if ((pids[i] = fork()) == 0) test(); } for (i = 0; i < PARALLEL; i++) { if (waitpid(pids[i], &status, 0) == -1) err(1, "waitpid(%d)", pids[i]); e += status == 0 ? 0 : 1; } return (e); } diff --git a/tools/test/stress2/misc/mkfifo6.sh b/tools/test/stress2/misc/mkfifo6.sh index 5647bf9493d6..13a62b5e0286 100755 --- a/tools/test/stress2/misc/mkfifo6.sh +++ b/tools/test/stress2/misc/mkfifo6.sh @@ -1,183 +1,183 @@ #!/bin/sh # # Copyright (c) 2017 Dell EMC Isilon # All rights reserved. # # 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. # -# mkfifo(2), select(2) with tmpfs(5) scenario. +# mkfifo(2), select(2) with tmpfs(4) scenario. . ../default.cfg [ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 dir=/tmp odir=`pwd` cd $dir sed '1,/^EOF/d' < $odir/$0 > $dir/mkfifo6.c mycc -o mkfifo6 -Wall -Wextra -O0 -g mkfifo6.c || exit 1 rm -f mkfifo6.c cd $odir mount | grep -q "on $mntpoint " && umount -f $mntpoint mount -o size=1g -t tmpfs tmpfs $mntpoint fifo=$mntpoint/fifo.file cd $mntpoint /tmp/mkfifo6 $fifo s=$? cd $odir while mount | grep "on $mntpoint " | grep -q tmpfs; do umount $mntpoint || sleep 1 done rm -rf /tmp/mkfifo6 exit $s EOF #include #include #include #include #include #include #include #include #include #include #include #include static char *path; #define PARALLEL 1 static void reader(void) { fd_set rset; struct timeval timeout; int fd, n, r; char ch; do { if((fd = open(path, O_RDONLY)) == -1) if (errno != EINTR) err(1, "open(%s, O_RDONLY)", path); if (fd == -1) warn("open(%s) ro", path); } while (fd == -1); /* timeout */ ch = 'z'; FD_ZERO(&rset); FD_SET(fd, &rset); timeout.tv_sec = 0; timeout.tv_usec = 100000; if ((n = select(fd + 1, &rset, NULL, NULL, &timeout)) < 0) if (errno != EINTR) err(1, "select()"); if (n != 0) fprintf(stderr, "FAIL Expected n == 0, got %d\n", n); if (n == 1 && FD_ISSET(fd, &rset)) { r = read(fd, &ch, 1); if (r == -1) err(1, "read"); if (r != 0) fprintf(stderr, "read(2): %c\n", ch); else fprintf(stderr, "read(2): EOF\n"); } sleep(3); if (close(fd) == -1) err(1, "close() in child"); _exit(n); } static void writer(void) { int fd; do { if ((fd = open(path, O_WRONLY)) == -1) if (errno != EINTR) err(1, "open(%s, O_WRONLY)", path); if (fd == -1) warn("open(%s) wr", path); } while (fd == -1); sleep(2); if (write(fd, "a", 1) != 1) err(1, "write one"); if (close(fd) == -1) warn("close() in parent"); } static void test(void) { pid_t pid; int status; if ((pid = fork()) == 0) reader(); writer(); if (waitpid(pid, &status, 0) != pid) err(1, "waitpid(%d)", pid); _exit(status != 0); } int main(int argc __unused, char *argv[]) { int e, i, pids[PARALLEL], status; if (argc != 2) { fprintf(stderr, "Usage: %s \n", argv[0]); exit(1); } path = argv[1]; e = 0; unlink(path); if (mkfifo(path, 0640) == -1) err(1, "mkfifo(%s)", path); for (i = 0; i < PARALLEL; i++) { if ((pids[i] = fork()) == 0) test(); } for (i = 0; i < PARALLEL; i++) { if (waitpid(pids[i], &status, 0) == -1) err(1, "waitpid(%d)", pids[i]); e += status == 0 ? 0 : 1; } return (e); } diff --git a/tools/test/stress2/misc/mkfifo7.sh b/tools/test/stress2/misc/mkfifo7.sh index b17e84536bed..c1af3374526e 100755 --- a/tools/test/stress2/misc/mkfifo7.sh +++ b/tools/test/stress2/misc/mkfifo7.sh @@ -1,203 +1,203 @@ #!/bin/sh # # Copyright (c) 2017 Dell EMC Isilon # All rights reserved. # # 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. # -# mkfifo(2), poll(2) with tmpfs(5) scenario. +# mkfifo(2), poll(2) with tmpfs(4) scenario. . ../default.cfg [ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 dir=/tmp odir=`pwd` cd $dir sed '1,/^EOF/d' < $odir/$0 > $dir/mkfifo7.c mycc -o mkfifo7 -Wall -Wextra -O0 -g mkfifo7.c || exit 1 rm -f mkfifo7.c cd $odir mount | grep -q "on $mntpoint " && umount -f $mntpoint mount -o size=1g -t tmpfs tmpfs $mntpoint fifo=$mntpoint/fifo.file cd $mntpoint /tmp/mkfifo7 $fifo s=$? cd $odir while mount | grep "on $mntpoint " | grep -q tmpfs; do umount $mntpoint || sleep 1 done rm -rf /tmp/mkfifo7 exit $s EOF #include #include #include #include #include #include #include #include #include #include #include #include #include static char *path; #define PARALLEL 1 static void reader(void) { struct pollfd pfd; int fd, n, r; char ch; do { if((fd = open(path, O_RDONLY)) == -1) if (errno != EINTR) err(1, "open(%s, O_RDONLY)", path); if (fd == -1) warn("open(%s) ro", path); } while (fd == -1); /* Read one character */ pfd.fd = fd; pfd.events = POLLIN; if ((n = poll(&pfd, 1, 0)) == -1) err(1, "poll()"); if (n == 1) { r = read(fd, &ch, 1); if (r == -1) err(1, "read"); if (r != 0) fprintf(stderr, "read(1): %c\n", ch); else fprintf(stderr, "read(1): EOF\n"); } /* timeout */ ch = 'z'; if ((n = poll(&pfd, 1, 7000)) == -1) err(1, "poll()"); if (n != 1) fprintf(stderr, "FAIL Expected n == 1, got %d\n", n); if (n == 1) { r = read(fd, &ch, 1); if (r == -1) err(1, "read"); if (r == 0) fprintf(stderr, "read(2): EOF\n"); } /* timeout */ ch = 'z'; if ((n = poll(&pfd, 1, 7000)) == -1) err(1, "poll()"); if (n != 1) fprintf(stderr, "FAIL Expected n == 1, got %d\n", n); if (n == 1) { r = read(fd, &ch, 1); if (r == -1) err(1, "read"); if (r != 0) fprintf(stderr, "read(3): %c\n", ch); } if (close(fd) == -1) err(1, "close() in child"); _exit(n == 1 ? 0 : 1); } static void writer(void) { int fd; do { if ((fd = open(path, O_WRONLY)) == -1) if (errno != EINTR) err(1, "open(%s, O_WRONLY)", path); if (fd == -1) warn("open(%s) wr", path); } while (fd == -1); if (write(fd, "a", 1) != 1) err(1, "write one"); if (close(fd) == -1) warn("close() in parent"); } static void test(void) { pid_t pid; int status; if ((pid = fork()) == 0) reader(); writer(); if (waitpid(pid, &status, 0) != pid) err(1, "waitpid(%d)", pid); _exit(status != 0); } int main(int argc __unused, char *argv[]) { int e, i, pids[PARALLEL], status; if (argc != 2) { fprintf(stderr, "Usage: %s \n", argv[0]); exit(1); } path = argv[1]; e = 0; unlink(path); if (mkfifo(path, 0640) == -1) err(1, "mkfifo(%s)", path); for (i = 0; i < PARALLEL; i++) { if ((pids[i] = fork()) == 0) test(); } for (i = 0; i < PARALLEL; i++) { if (waitpid(pids[i], &status, 0) == -1) err(1, "waitpid(%d)", pids[i]); e += status == 0 ? 0 : 1; } return (e); } diff --git a/tools/test/stress2/misc/mlockall4.sh b/tools/test/stress2/misc/mlockall4.sh index 778256fa8976..66ae05fa4ae1 100755 --- a/tools/test/stress2/misc/mlockall4.sh +++ b/tools/test/stress2/misc/mlockall4.sh @@ -1,66 +1,66 @@ #!/bin/sh # # Copyright (c) 2013 EMC Corp. # All rights reserved. # # 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. # -# mlockall(2) / nullfs(5) scenario causes: +# mlockall(2) / nullfs(4) scenario causes: # http://people.freebsd.org/~pho/stress/log/kostik619.txt # kern/182661, fixed in r256211. . ../default.cfg [ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 odir=`pwd` cd /tmp sed '1,/^EOF/d' < $odir/$0 > mlockall4.c mycc -o mlockall4 -Wall -Wextra mlockall4.c || exit 1 rm -f mlockall4.c mount | grep -q "on $mntpoint " && umount -f $mntpoint mount -t nullfs /tmp $mntpoint $mntpoint/mlockall4 & sleep 2 umount -f $mntpoint wait rm -f /tmp/mlockall4 exit EOF #include #include #include #include int main(void) { if (mlockall(MCL_CURRENT | MCL_FUTURE) == -1) err(1, "mlockall(MCL_CURRENT | MCL_FUTURE)"); sleep(5); return (0); } diff --git a/tools/test/stress2/misc/msdos14.sh b/tools/test/stress2/misc/msdos14.sh index 9c7a636f5f59..aaa95144c14e 100755 --- a/tools/test/stress2/misc/msdos14.sh +++ b/tools/test/stress2/misc/msdos14.sh @@ -1,121 +1,121 @@ #!/bin/sh # # SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2021 Peter Holm # # 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. # -# Rename(2) test with msdosfs(5) +# Rename(2) test with msdosfs(4) # Test scenario by kib@ . ../default.cfg [ `id -u` -ne 0 ] && echo "Must be root!" && exit 1 [ -x /sbin/mount_msdosfs ] || exit 0 dir=/tmp odir=`pwd` cd $dir cat > /tmp/msdos14.c < #include #include #include #include #include #include int main(void) { struct stat sb; uint64_t x; int error, fd; char from[64], to[64]; for (x = 0;; x++) { snprintf(from, sizeof(from), "x.%" PRIu64 ".from", x); snprintf(to, sizeof(to), "x.%" PRIu64 ".to", x); fd = open(from, O_CREAT | O_TRUNC | O_EXCL, 0666); if (fd == -1) err(1, "open %s", from); close(fd); error = rename(from, to); if (error == -1) err(1, "rename %s %s", from, to); error = stat(to, &sb); if (error == -1) err(1, "stat %s", to); error = unlink(to); if (error == -1) err(1, "unlink %s", to); } } EOF cc -o msdos14 -Wall -Wextra -O2 msdos14.c || exit 1 rm -f msdos14.c cd $odir log=/tmp/msdos14sh..log mount | grep "$mntpoint" | grep -q md$mdstart && umount -f $mntpoint mdconfig -l | grep -q $mdstart && mdconfig -d -u $mdstart set -e mdconfig -a -t swap -s 4g -u $mdstart gpart create -s bsd md$mdstart > /dev/null gpart add -t freebsd-ufs md$mdstart > /dev/null part=a newfs_msdos -b 1024 /dev/md${mdstart}$part > /dev/null mount -t msdosfs /dev/md${mdstart}$part $mntpoint set +e cp /tmp/msdos14 $mntpoint cd $mntpoint (cd $odir/../testcases/swap; ./swap -t 5m -i 20 -l 100) > /dev/null & sleep 2 timeout 5m ./msdos14 while pkill swap; do :; done wait cd $odir while mount | grep "$mntpoint" | grep -q md$mdstart; do umount $mntpoint || sleep 1 done fsck -t msdosfs -y /dev/md${mdstart}$part > $log 2>&1 if egrep -q "BAD|INCONSISTENCY|MODIFIED" $log; then echo "fsck issues:" cat $log s=1 mount -t msdosfs /dev/md${mdstart}$part $mntpoint || exit 1 ls -lR $mntpoint umount $mntpoint fi mdconfig -d -u $mdstart rm /tmp/msdos14 $log exit $s diff --git a/tools/test/stress2/misc/nullfs18.sh b/tools/test/stress2/misc/nullfs18.sh index 0ee0a1c2ef6b..b4414cbc3e3e 100755 --- a/tools/test/stress2/misc/nullfs18.sh +++ b/tools/test/stress2/misc/nullfs18.sh @@ -1,132 +1,132 @@ #!/bin/sh # # Copyright (c) 2016 EMC Corp. # All rights reserved. # # 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. # [ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 -# Demonstate nullfs(5) inode leak. +# Demonstate nullfs(4) inode leak. # Fixed by r295717. . ../default.cfg N=3 mount | grep $mntpoint | grep -q /dev/md && umount -f $mntpoint mdconfig -l | grep -q md$mdstart && mdconfig -d -u $mdstart mdconfig -a -t swap -s 2g -u $mdstart || exit 1 newfs -n md$mdstart > /dev/null mount /dev/md$mdstart $mntpoint chmod 777 $mntpoint set `df -ik $mntpoint | tail -1 | awk '{print $4,$7}'` export KBLOCKS=$(($1 / N)) export INODES=$(($2 / N)) export runRUNTIME=2m export LOAD=80 export symlinkLOAD=80 export rwLOAD=80 export TESTPROGS=" testcases/rw/rw testcases/creat/creat testcases/mkdir/mkdir " for i in `jot $N 1`; do eval mp$i=${mntpoint}$i done for i in `jot $N 1`; do eval mp=\$mp$i [ -d $mp ] || mkdir -p $mp mount | grep $mp | grep -q nullfs && umount -f $mp msrc=$mntpoint/d$i mkdir -p $msrc chmod 777 $msrc mount -t nullfs $msrc $mp chmod 777 $mp export RUNDIR=$mp/stressX export CTRLDIR=$mp/stressX.control mkdir $RUNDIR $CTRLDIR chmod 777 $RUNDIR $CTRLDIR su $testuser -c 'cd ..; ./testcases/run/run $TESTPROGS' > \ /dev/null 2>&1 & mps="$mps $mp" done (cd ../testcases/swap; ./swap -t 10m -i 20 > /dev/null 2>&1) & sleep 1 while pgrep -q run; do find $mps -ls > /dev/null 2>&1 done while pgrep -q swap; do pkill -9 swap done wait (cd $mntpoint; find . -delete) sync; sleep 1; sync; sleep 1; sync inodes=`df -i $mntpoint | tail -1 | awk '{print $6}'` if [ $inodes -ne 4 ]; then echo "FAIL 1" e=1 mount | sed -n "1p;/${mntpoint#/}/p" echo df -ik | sed -n "1p;/${mntpoint#/}/p" printf "\nfind ${mntpoint}* -ls\n" find ${mntpoint}* -ls for i in `jot $N 1`; do eval mp=\$mp$i echo "umount $mp" mount | grep $mp | grep -q nullfs && umount $mp done echo df -ik | sed -n "1p;/${mntpoint#/}/p" else for i in `jot $N 1`; do eval mp=\$mp$i mount | grep $mp | grep -q nullfs && umount $mp done inodes=`df -i $mntpoint | tail -1 | awk '{print $6}'` if [ $inodes -ne 1 ]; then echo "FAIL 2" e=2 mount | sed -n "1p;/${mntpoint#/}/p" echo df -ik | sed -n "1p;/${mntpoint#/}/p" fi fi while mount | grep $mntpoint | grep -q /dev/md; do umount $mntpoint || sleep 1 done mdconfig -d -u $mdstart exit $e diff --git a/tools/test/stress2/misc/pread.sh b/tools/test/stress2/misc/pread.sh index 1bf3b874e6af..24ee2efb696a 100755 --- a/tools/test/stress2/misc/pread.sh +++ b/tools/test/stress2/misc/pread.sh @@ -1,189 +1,189 @@ #!/bin/sh # # Copyright (c) 2011 Peter Holm # All rights reserved. # # 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. # # pread(2) fuzzing inspired by the iknowthis test suite # by Tavis Ormandy # Fixed in r227527. [ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 . ../default.cfg here=`pwd` cd /tmp sed '1,/^EOF/d' < $here/$0 > pread.c mycc -o pread -Wall -Wextra pread.c rm -f pread.c mount | grep $mntpoint | grep -q /dev/md && umount -f $mntpoint mdconfig -l | grep -q md$mdstart && mdconfig -d -u $mdstart mount -t tmpfs tmpfs $mntpoint cp -a /usr/include $mntpoint -echo "Testing tmpfs(5)" +echo "Testing tmpfs(4)" /tmp/pread $mntpoint while mount | grep -q "on $mntpoint "; do umount $mntpoint || sleep 1 done -echo "Testing fdescfs(5)" +echo "Testing fdescfs(4)" mount -t fdescfs null /dev/fd for i in `jot 100`; do /tmp/pread /dev/fd done while mount | grep -q "on /dev/fd "; do umount /dev/fd || sleep 1 done -echo "Testing procfs(5)" +echo "Testing procfs(4)" mount -t procfs procfs $mntpoint /tmp/pread $mntpoint while mount | grep -q "on $mntpoint "; do umount $mntpoint || sleep 1 done mdconfig -a -t swap -s 1g -u $mdstart || exit 1 newfs $newfs_flags md$mdstart > /dev/null mount /dev/md$mdstart $mntpoint cp -a /usr/include $mntpoint echo "Testing FFS" /tmp/pread $mntpoint while mount | grep -q "on $mntpoint "; do umount $mntpoint || sleep 1 done mdconfig -d -u $mdstart mount -t nullfs /bin $mntpoint -echo "Testing nullfs(5)" +echo "Testing nullfs(4)" /tmp/pread $mntpoint while mount | grep -q "on $mntpoint "; do umount $mntpoint || sleep 1 done -echo "Testing procfs(5)" +echo "Testing procfs(4)" mount -t procfs procfs $mntpoint /tmp/pread $mntpoint while mount | grep -q "on $mntpoint "; do umount $mntpoint || sleep 1 done echo "Testing devfs(8)" mount -t devfs devfs $mntpoint /tmp/pread $mntpoint while mount | grep -q "on $mntpoint "; do umount $mntpoint || sleep 1 done rm -f /tmp/pread exit 0 EOF #include #include #include #include #include #include #include #include #include #include #include #include #include #include static void hand(int i __unused) { /* handler */ _exit(1); } int test(char *path) { FTS *fts; FTSENT *p; int ftsoptions; char *args[2]; int buf[64], fd; signal(SIGSEGV, hand); signal(SIGABRT, hand); ftsoptions = FTS_PHYSICAL; args[0] = path; args[1] = 0; if ((fts = fts_open(args, ftsoptions, NULL)) == NULL) err(1, "fts_open"); while ((p = fts_read(fts)) != NULL) { if ((fd = open(p->fts_path, O_RDONLY)) == -1) { if (errno != EACCES && errno != ENXIO) warn("open(%s)", p->fts_path); continue; } alarm(1); pread(fd, (void *)0xdeadc0de, 0x7ffffff, 0xffffffff); pread(fd, buf, 0x7ffffff, 0xffffffff); pread(fd, buf, sizeof(buf), 0xffffffff); pread(fd, buf, sizeof(buf), 0); close(fd); } fts_close(fts); exit(0); } int main(int argc __unused, char **argv) { int i; struct passwd *pw; if ((pw = getpwnam("nobody")) == NULL) err(1, "no such user: nobody"); if (setgroups(1, &pw->pw_gid) || setegid(pw->pw_gid) || setgid(pw->pw_gid) || seteuid(pw->pw_uid) || setuid(pw->pw_uid)) err(1, "Can't drop privileges to \"nobody\""); endpwent(); if (daemon(0, 0) == -1) err(1, "daemon()"); for (i = 0; i < 10; i++) { if (fork() == 0) test(argv[1]); wait(NULL); } return (0); } diff --git a/tools/test/stress2/misc/procfs3.sh b/tools/test/stress2/misc/procfs3.sh index c9c4820adbff..30bcc8b3cd62 100755 --- a/tools/test/stress2/misc/procfs3.sh +++ b/tools/test/stress2/misc/procfs3.sh @@ -1,154 +1,154 @@ #!/bin/sh # # Copyright (c) 2012 Peter Holm # All rights reserved. # # 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. # -# procfs(5) test scenario. +# procfs(4) test scenario. # "panic: wchan 0xc10a4f68 has no wmesg" seen [ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 . ../default.cfg mount | grep -q "/proc " || { mount -t procfs procfs /proc || exit 1; } here=`pwd` cd /tmp sed '1,/^EOF/d' < $here/$0 > procfs3.c mycc -o procfs3 -Wall -Wextra -O2 procfs3.c || exit 1 rm -f procfs3.c cd $here su $testuser -c /tmp/procfs3 rm -f /tmp/procfs3 exit 0 EOF #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define PARALLEL 10 void handler(int i __unused) { } int test(void) { FTS *fts; FTSENT *p; int ftsoptions; char *args[2]; int fd, i; char buf[1629]; ftsoptions = FTS_PHYSICAL; args[0] = "/proc"; args[1] = 0; if ((fts = fts_open(args, ftsoptions, NULL)) == NULL) err(1, "fts_open"); while ((p = fts_read(fts)) != NULL) { switch (p->fts_info) { case FTS_F: /* Ignore. */ break; case FTS_D: /* Ignore. */ continue; case FTS_DP: continue; case FTS_DC: /* Ignore. */ continue; case FTS_SL: /* Ignore. */ continue; case FTS_DNR: continue; case FTS_NS: continue; case FTS_ERR: case FTS_DEFAULT: warnx("%s: %s. fts_info = %d", p->fts_path, strerror(p->fts_errno), p->fts_info); continue; default: printf("%s: default, %d\n", getprogname(), p->fts_info); break; } if ((fd = open(p->fts_path, O_RDONLY)) == -1) continue; signal(SIGALRM, handler); alarm(1); for (i = 0; i < 2; i++) { read(fd, buf, 1629); } close(fd); } if (errno != 0 && errno != ENOENT) err(1, "fts_read"); if (fts_close(fts) == -1) err(1, "fts_close()"); return (0); } int main(void) { int i, j; for (i = 0; i < PARALLEL; i++) { if (fork() == 0) { for (j = 0; j < 50; j++) { test(); } _exit(0); } } for (i = 0; i < PARALLEL; i++) wait(NULL); return (0); } diff --git a/tools/test/stress2/misc/readdir.sh b/tools/test/stress2/misc/readdir.sh index 8616a8a40206..425295631181 100755 --- a/tools/test/stress2/misc/readdir.sh +++ b/tools/test/stress2/misc/readdir.sh @@ -1,177 +1,177 @@ #!/bin/sh # # Copyright (c) 2011 Peter Holm # All rights reserved. # # 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. # # readdir(3) fuzzing inspired by the iknowthis test suite # by Tavis Ormandy # "panic: kmem_malloc(1328054272): kmem_map too small" seen [ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 . ../default.cfg here=`pwd` cd /tmp sed '1,/^EOF/d' < $here/$0 > readdir.c mycc -o readdir -Wall -Wextra readdir.c || exit 1 rm -f readdir.c mount | grep $mntpoint | grep -q /dev/md && umount -f $mntpoint mdconfig -l | grep -q md$mdstart && mdconfig -d -u $mdstart mount -t tmpfs tmpfs $mntpoint -echo "Testing tmpfs(5)" +echo "Testing tmpfs(4)" cp -a /usr/include $mntpoint /tmp/readdir $mntpoint umount $mntpoint -echo "Testing fdescfs(5)" +echo "Testing fdescfs(4)" kldstat -v | grep -q fdescfs || { kldload fdescfs.ko; loaded=1; } mount -t fdescfs null /dev/fd /tmp/readdir /dev/fd umount /dev/fd [ $unload ] && kldunload fdescfs.ko -echo "Testing procfs(5)" +echo "Testing procfs(4)" mount -t procfs procfs $mntpoint /tmp/readdir $mntpoint umount $mntpoint if ping -c 2 `echo $nfs_export | sed 's/:.*//'` > /dev/null 2>&1; then echo "Testing nfs" mount -t nfs -o nfsv3,tcp,nolockd,retrycnt=3,soft,timeout=1 \ $nfs_export $mntpoint /tmp/readdir $mntpoint umount $mntpoint fi mdconfig -a -t swap -s 1g -u $mdstart || exit 1 newfs md$mdstart > /dev/null mount /dev/md$mdstart $mntpoint cp -a /usr/include $mntpoint echo "Testing UFS" /tmp/readdir $mntpoint umount $mntpoint mdconfig -d -u $mdstart mdconfig -a -t swap -s 1g -u $mdstart || exit 1 newfs $newfs_flags md$mdstart > /dev/null mount /dev/md$mdstart $mntpoint cp -a /usr/include $mntpoint echo "Testing FFS" /tmp/readdir $mntpoint umount $mntpoint mdconfig -d -u $mdstart mount -t nullfs /bin $mntpoint -echo "Testing nullfs(5)" +echo "Testing nullfs(4)" /tmp/readdir $mntpoint umount $mntpoint rm -f /tmp/readdir exit 0 EOF #include #include #include #include #include #include #include #include #include #include #include #include #define RUNTIME 120 /* copy from /usr/src/lib/libc/gen/gen-private.h */ struct _telldir; /* see telldir.h */ struct pthread_mutex; /* * Structure describing an open directory. * * NOTE. Change structure layout with care, at least dd_fd field has to * remain unchanged to guarantee backward compatibility. */ struct _dirdesc { int dd_fd; /* file descriptor associated with directory */ long dd_loc; /* offset in current buffer */ long dd_size; /* amount of data returned by getdirentries */ char *dd_buf; /* data buffer */ int dd_len; /* size of data buffer */ long dd_seek; /* magic cookie returned by getdirentries */ long dd_rewind; /* magic cookie for rewinding */ int dd_flags; /* flags for readdir */ struct pthread_mutex *dd_lock; /* lock */ struct _telldir *dd_td; /* telldir position recording */ }; /* End copy */ static void hand(int i __unused) { /* handler */ _exit(1); } static void test(char *path) { DIR *dirp, fuzz; int i; signal(SIGSEGV, hand); alarm(300); for (i = 0; i < 2000; i++) { if ((dirp = opendir(path)) == NULL) break; bcopy(dirp, &fuzz, sizeof(fuzz)); fuzz.dd_len = arc4random(); readdir(&fuzz); closedir(dirp); } _exit(0); } int main(int argc __unused, char **argv) { time_t start; start = time(NULL); while (time(NULL) - start < RUNTIME) { if (fork() == 0) test(argv[1]); wait(NULL); } return (0); } diff --git a/tools/test/stress2/misc/sendfile5.sh b/tools/test/stress2/misc/sendfile5.sh index c81515003a13..933e4f94a73c 100755 --- a/tools/test/stress2/misc/sendfile5.sh +++ b/tools/test/stress2/misc/sendfile5.sh @@ -1,164 +1,164 @@ #!/bin/sh # # Copyright (c) 2011 Peter Holm # All rights reserved. # # 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. # # sendfile(2) test by kib@ # Deadlock seen. [ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 . ../default.cfg here=`pwd` file=`basename $diskimage` dir=`dirname $diskimage` cd /tmp sed '1,/^EOF/d' < $here/$0 > sendfile5.c mycc -o sendfile5 -Wall -Wextra -O2 sendfile5.c rm -f sendfile5.c need=1024 [ `df -k $(dirname $diskimage) | tail -1 | awk '{print int($4 / 1024)}'` \ -lt $need ] && printf "Need %d MB on %s.\n" $need `dirname $diskimage` && exit 0 dd if=/dev/zero of=$diskimage bs=1m count=$need status=none cd $here mount | grep $mntpoint | grep -q /dev/md && umount -f $mntpoint mdconfig -l | grep -q md$mdstart && mdconfig -d -u $mdstart kldstat | grep -q tmpfs.ko || loaded=1 mount -t tmpfs tmpfs $mntpoint -echo "Testing tmpfs(5)" +echo "Testing tmpfs(4)" cp $diskimage $mntpoint /tmp/sendfile5 $mntpoint/$file umount $mntpoint [ $loaded ] && kldunload tmpfs.ko mdconfig -a -t swap -s 2g -u $mdstart || exit 1 newfs $newfs_flags md$mdstart > /dev/null mount /dev/md$mdstart $mntpoint echo "Testing FFS" cp $diskimage $mntpoint /tmp/sendfile5 $mntpoint/$file umount $mntpoint mdconfig -d -u $mdstart mount -t nullfs $dir $mntpoint -echo "Testing nullfs(5)" +echo "Testing nullfs(4)" /tmp/sendfile5 $mntpoint/$file umount $mntpoint rm -f /tmp/sendfile5 $diskimage exit EOF #include #include #include #include #include #include #include #include #include #include int main(int argc, char *argv[]) { const char *from_name; char *buf; int sv[2]; struct stat st; off_t written, pos; int child, error, from, status; if (argc != 2) errx(1, "Usage: %s from", argv[0]); from_name = argv[1]; from = open(from_name, O_RDONLY); if (from == -1) err(1, "open read %s", from_name); error = fstat(from, &st); if (error == -1) err(1, "stat %s", from_name); error = socketpair(AF_UNIX, SOCK_STREAM, 0, sv); if (error == -1) err(1, "socketpair"); child = fork(); if (child == -1) err(1, "fork"); else if (child != 0) { close(sv[1]); pos = 0; for (;;) { error = sendfile(from, sv[0], pos, st.st_size - pos, NULL, &written, 0); if (error == -1) { if (errno != EAGAIN) err(1, "sendfile"); } pos += written; if (pos == st.st_size) break; } close(sv[0]); waitpid(child, &status, 0); } else { close(sv[0]); buf = malloc(st.st_size); if (buf == NULL) err(1, "malloc %jd", st.st_size); pos = 0; for (;;) { written = 413; if (written > st.st_size - pos) written = st.st_size - pos; #if 0 written = st.st_size - pos; if (written > 1000) written = 1000; written = arc4random_uniform(written) + 1; #endif error = read(sv[1], buf + pos, written); if (error == -1) err(1, "read"); else if (error == 0) errx(1, "short read"); pos += error; if (pos == st.st_size) break; } close(sv[1]); _exit(0); } return (0); } diff --git a/tools/test/stress2/misc/tmpfs10.sh b/tools/test/stress2/misc/tmpfs10.sh index 870530c57ea7..6388f59959a4 100755 --- a/tools/test/stress2/misc/tmpfs10.sh +++ b/tools/test/stress2/misc/tmpfs10.sh @@ -1,155 +1,155 @@ #!/bin/sh # # Copyright (c) 2013 EMC Corp. # All rights reserved. # # 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. # -# tmpfs(5) name lookup problem seen: +# tmpfs(4) name lookup problem seen: # $ ./tmpfs10.sh # tmpfs10: unlink(p01193.14729) at loop #2: No such file or directory # unlink(p01193.14729) succeeded at call #2. # tmpfs10: unlink(p01186.14409) at loop #2: No such file or directory # unlink(p01186.14409) succeeded at call #2. # FAIL # $ # Fixed in r253967. [ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 . ../default.cfg odir=`pwd` cd /tmp sed '1,/^EOF/d' < $odir/$0 > tmpfs10.c mycc -o tmpfs10 -Wall -Wextra -O2 -g tmpfs10.c || exit 1 rm -f tmpfs10.c cd $odir mount | grep -q "on $mntpoint " && umount $mntpoint mount -t tmpfs tmpfs $mntpoint cd $mntpoint /tmp/tmpfs10 || { find $mntpoint ! -type d | xargs ls -il; echo FAIL; } cd $odir umount $mntpoint rm -f /tmp/tmpfs10 exit 0 EOF #include #include #include #include #include #include #include #include #include static int loop; int error; #define PARALLEL 20 #define SIZE 16000 void test2(void) { int i, j, k; pid_t pid; char file[128], dir[128]; loop++; pid = getpid(); sprintf(dir,"%s.%05d", getprogname(), pid); if (mkdir(dir, 0770) < 0) err(1, "mkdir(%s), %s:%d", dir, __FILE__, __LINE__); if (chdir(dir) == -1) err(1, "chdir(%s), %s:%d", dir, __FILE__, __LINE__); for (j = 0; j < SIZE; j++) { sprintf(file,"p%05d.%05d", pid, j); if (symlink("/tmp/not/there", file) == -1) { if (errno != EINTR) { warn("symlink(%s). %s.%d", file, __FILE__, __LINE__); break; } } } for (i = --j; i >= 0; i--) { sprintf(file,"p%05d.%05d", pid, i); if (unlink(file) == -1) { warn("unlink(%s) at loop #%d", file, loop); error++; for (k = 0; k < 10; k++) { usleep(10000); if (unlink(file) == 0) { fprintf(stderr, "unlink(%s) succeeded at call #%d.\n", file, k + 2); break; } } } } (void)chdir(".."); if (rmdir(dir) == -1) warn("rmdir(%s), %s:%d", dir, __FILE__, __LINE__); } void test(void) { sleep(arc4random() % 3 + 1); test2(); if (error == 0) test2(); _exit(error); } int main(void) { int e, i, status; for (i = 0; i < PARALLEL; i++) if (fork() == 0) test(); e = 0; for (i = 0; i < PARALLEL; i++) { wait(&status); e += WEXITSTATUS(status); } return (e); } diff --git a/tools/test/stress2/misc/tmpfs11.sh b/tools/test/stress2/misc/tmpfs11.sh index efb535b8ea94..629ca8ae3d31 100755 --- a/tools/test/stress2/misc/tmpfs11.sh +++ b/tools/test/stress2/misc/tmpfs11.sh @@ -1,81 +1,81 @@ #!/bin/sh # # Copyright (c) 2014 EMC Corp. # All rights reserved. # # 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. # [ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 -# Test with two tmpfs(5) file systems mounted. +# Test with two tmpfs(4) file systems mounted. . ../default.cfg mp1=$mntpoint mp2=${mntpoint}2 [ -d $mp2 ] || mkdir -p $mp2 md1=$mdstart md2=$((mdstart + 1)) mount | grep $mp1 | grep -q tmpfs && umount -f $mp1 mount -o size=1g -t tmpfs tmpfs $mp1 chmod 777 $mp1 mount | grep $mp2 | grep -q tmpfs && umount -f $mp2 mount -o size=1g -t tmpfs tmpfs $mp2 chmod 777 $mp2 export runRUNTIME=15m export RUNDIR=$mp1/stressX export CTRLDIR=$mp1/stressX.control export LOAD=80 export symlinkLOAD=80 export rwLOAD=80 export TESTPROGS=" testcases/lockf2/lockf2 testcases/symlink/symlink testcases/openat/openat testcases/rw/rw testcases/fts/fts testcases/link/link testcases/lockf/lockf testcases/creat/creat testcases/mkdir/mkdir testcases/rename/rename testcases/mkfifo/mkfifo " su $testuser -c 'cd ..; ./testcases/run/run $TESTPROGS' > /dev/null 2>&1 & export TESTPROGS="$TESTPROGS testcases/swap/swap" export RUNDIR=$mp2/stressX export CTRLDIR=$mp2/stressX.control su $testuser -c 'cd ..; ./testcases/run/run $TESTPROGS' > /dev/null 2>&1 & wait while mount | grep "$mp2 " | grep -q tmpfs; do umount $mp2 || sleep 1 done while mount | grep "$mp1 " | grep -q tmpfs; do umount $mp1 || sleep 1 done diff --git a/tools/test/stress2/misc/tmpfs17.sh b/tools/test/stress2/misc/tmpfs17.sh index 878fcf6c95d1..d5f6c50d2e48 100755 --- a/tools/test/stress2/misc/tmpfs17.sh +++ b/tools/test/stress2/misc/tmpfs17.sh @@ -1,144 +1,144 @@ #!/bin/sh # # Copyright (c) 2017 Dell EMC Isilon # All rights reserved. # # 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. # -# tmpfs(5) option nonc test scenario +# tmpfs(4) option nonc test scenario . ../default.cfg [ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 dir=/tmp odir=`pwd` cd $dir sed '1,/^EOF/d' < $odir/$0 > $dir/tmpfs17.c mycc -o tmpfs17 -Wall -Wextra -O0 -g tmpfs17.c || exit 1 rm -f tmpfs17.c cd $odir mount | grep "on $mntpoint " | grep -q /dev/md && umount -f $mntpoint mount -o nonc -t tmpfs tmpfs $mntpoint || { rm /tmp/tmpfs17; exit 0; } cd $mntpoint /tmp/tmpfs17 & pid=$! sleep .2 pid2=`pgrep tmpfs17` for i in `jot 5`; do for p in $pid2; do while true; do procstat -f $p > /dev/null 2>&1; done & pids="$pids $!" done done while kill -0 $pid 2>/dev/null; do sleep 2 done kill $pids 2>/dev/null wait cd $odir for i in `jot 10`; do umount $mntpoint && break sleep 1 done s=0 mount | grep -q "on $mntpoint " && { s=1; umount -f $mntpoint; } rm -rf /tmp/tmpfs17 exit $s EOF #include #include #include #include #include #include #include #include #include #include #include #include static volatile u_int *share; #define PARALLEL 4 #define RUNTIME (5 * 60) #define SYNC 0 static void test(void) { pid_t pid; time_t start; int fd, i; char file[80]; atomic_add_int(&share[SYNC], 1); while (share[SYNC] != PARALLEL) ; i= 0; pid = getpid(); start = time(NULL); while ((time(NULL) - start) < RUNTIME) { snprintf(file, sizeof(file), "file.%06d.%03d", pid, i++); if ((fd = open(file, O_RDWR|O_CREAT, DEFFILEMODE)) == -1) err(1, "open(%s)", file); close(fd); if (unlink(file) == -1) err(1, "unlink(%s)", file); } _exit(0); } int main(void) { size_t len; int e, i, pids[PARALLEL], status; e = 0; len = PAGE_SIZE; if ((share = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_ANON | MAP_SHARED, -1, 0)) == MAP_FAILED) err(1, "mmap"); for (i = 0; i < PARALLEL; i++) { if ((pids[i] = fork()) == 0) test(); } for (i = 0; i < PARALLEL; i++) { if (waitpid(pids[i], &status, 0) == -1) err(1, "waitpid(%d)", pids[i]); e += status == 0 ? 0 : 1; } return (e); } diff --git a/tools/test/stress2/misc/tmpfs8.sh b/tools/test/stress2/misc/tmpfs8.sh index b17a329f69e7..b78f0e74562b 100755 --- a/tools/test/stress2/misc/tmpfs8.sh +++ b/tools/test/stress2/misc/tmpfs8.sh @@ -1,178 +1,178 @@ #!/bin/sh # # Copyright (c) 2011 Peter Holm # All rights reserved. # # 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. # [ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 -# Demonstrate rename(2) cache problem for tmpfs(5). Fixed in r226987. +# Demonstrate rename(2) cache problem for tmpfs(4). Fixed in r226987. # Variation of rename6.sh . ../default.cfg here=`pwd` cd /tmp sed '1,/^EOF/d' < $here/$0 > tmpfs8.c mycc -o tmpfs8 -Wall -Wextra -O2 tmpfs8.c rm -f tmpfs8.c cd $here mount | grep $mntpoint | grep -q tmpfs && umount -f $mntpoint mount -t tmpfs tmpfs $mntpoint chmod 777 $mntpoint su $testuser -c "cd $mntpoint; /tmp/tmpfs8" while mount | grep $mntpoint | grep -q tmpfs; do umount $mntpoint || sleep 1 done rm -f /tmp/tmpfs8 exit EOF #include #include #include #include #include #include #include #include #include #include #include #include #include #include pid_t spid; const char *logfile = "test.log"; char new[128]; void cleanup() { kill(spid, SIGINT); } static void Stat() { struct stat sb; int i; setproctitle("Stat"); for (;;) { for (i = 0; i < 1000; i++) { stat(logfile, &sb); stat(new, &sb); } // usleep(1000); usleep(100); } } int main(void) { struct stat sb1, sb2, sb3; int fd, i, r1, r2, r3; if ((spid = fork()) == 0) Stat(); setproctitle("main"); atexit(cleanup); for (i = 0; i < 200000; i++) { bzero(&sb1, sizeof(sb1)); bzero(&sb2, sizeof(sb2)); if ((fd = open(logfile, O_RDWR | O_CREAT | O_TRUNC, 0644)) == -1) err(1, "creat(%s)", logfile); close(fd); sprintf(new, "test.log.%05d", i); if ((fd = open(new, O_RDWR | O_CREAT | O_TRUNC, 0644)) == -1) err(1, "creat(%s)", new); write(fd, "xxx", 3); close(fd); if ((r3 = stat(new, &sb3)) == -1) err(1, "stat(%s)", new); #if 1 if (rename(logfile, new) == -1) warn("rename(%s, %s)", logfile, new); #else /* No cache problem is seen */ if (link(logfile, new) == -1) err(1, "link(%s, %s)", logfile, new); if (unlink(logfile) == -1) err(1, "unlink(%s)", logfile); #endif /* * stat() for logfile and new will be identical sometimes, * but only when Stat() is running. */ r1 = stat(logfile, &sb1); r2 = stat(new, &sb2); if (r1 == 0 && r2 == 0 && bcmp(&sb1, &sb2, sizeof(sb1)) == 0) { fprintf(stderr, "FAIL 1\n"); fprintf(stderr, "%-15s: ino = %4ju, nlink = %ju, " "size = %jd\n", logfile, (uintmax_t)sb1.st_ino, (uintmax_t)sb1.st_nlink, sb1.st_blocks); fprintf(stderr, "%-15s: ino = %4ju, nlink = %ju, " "size = %jd\n", new , (uintmax_t)sb2.st_ino, (uintmax_t)sb2.st_nlink, sb2.st_blocks); } if (bcmp(&sb2, &sb3, sizeof(sb2)) == 0) { fprintf(stderr, "Old to file is lingering\n"); } if (sb2.st_ino == sb3.st_ino) { fprintf(stderr, "FAIL 2\n"); if (r1 == 0) fprintf(stderr, "sb1: %-15s: ino = %4ju, nlink = %ju, " "size = %jd\n", logfile, (uintmax_t)sb1.st_ino, (uintmax_t)sb1.st_nlink, sb1.st_blocks); if (r2 == 0) fprintf(stderr, "sb2: %-15s: ino = %4ju, nlink = %ju, " "size = %jd\n", new, (uintmax_t)sb2.st_ino, (uintmax_t)sb2.st_nlink, sb2.st_blocks); if (r3 == 0) fprintf(stderr, "sb3: %-15s: ino = %4ju, nlink = %ju, " "size = %jd\n", new, (uintmax_t)sb3.st_ino, (uintmax_t)sb3.st_nlink, sb3.st_blocks); exit(1); } unlink(new); } kill(spid, SIGINT); wait(NULL); return (0); } diff --git a/tools/test/stress2/misc/unionfs17.sh b/tools/test/stress2/misc/unionfs17.sh index bcb6d242187b..9ddbd1cab8cb 100755 --- a/tools/test/stress2/misc/unionfs17.sh +++ b/tools/test/stress2/misc/unionfs17.sh @@ -1,73 +1,73 @@ #!/bin/sh # # Copyright (c) 2024 Peter Holm # # SPDX-License-Identifier: BSD-2-Clause # -# unionfs(8) test +# unionfs(4) test # Variation of unionfs7.sh, but with tmpfs # "mkdir: rmdir(d17) Directory not empty" seen. [ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 . ../default.cfg mp1=/mnt$mdstart mp2=/mnt$((mdstart + 1)) mkdir -p $mp1 $mp2 set -e for i in $mp1 $mp2; do mount | grep -q "on $i " && umount -f $i done mount -o size=4g -t tmpfs dummy $mp1 mount -o size=4g -t tmpfs dummy $mp2 mount -t unionfs -o noatime $mp1 $mp2 set +e export 'INODES=100000' export CTRLDIR=$mp2/stressX.control export INCARNATIONS=10 export LOAD=80 export RUNDIR=$mp2/stressX export runRUNTIME=5m export rwLOAD=80 export symlinkLOAD=80 export TESTPROGS=" testcases/lockf2/lockf2 testcases/symlink/symlink testcases/openat/openat testcases/rw/rw testcases/fts/fts testcases/link/link testcases/lockf/lockf testcases/creat/creat testcases/mkdir/mkdir testcases/rename/rename testcases/mkfifo/mkfifo testcases/dirnprename/dirnprename testcases/dirrename/dirrename testcases/swap/swap " cp -r ../../stress2 $mp2 export TESTPROGS=`echo $TESTPROGS | sed 's/\n/ /g'` set +e chmod 777 $mp2 su $testuser -c \ "(cd $mp2/stress2; ./testcases/run/run $TESTPROGS)" while mount | grep -Eq "on $mp2 .*unionfs"; do umount $mp2 && break sleep 5 done umount $mp2 n=`find $mp1/stressX | wc -l` [ $n -eq 1 ] && s=0 || { find $mp1/stressX -ls | head -12; s=1; } umount $mp1 exit $s diff --git a/tools/test/stress2/misc/unionfs18.sh b/tools/test/stress2/misc/unionfs18.sh index e772a67a07fb..a7840db263e1 100755 --- a/tools/test/stress2/misc/unionfs18.sh +++ b/tools/test/stress2/misc/unionfs18.sh @@ -1,73 +1,73 @@ #!/bin/sh # # Copyright (c) 2024 Peter Holm # # SPDX-License-Identifier: BSD-2-Clause # -# Simple unionfs(8) + tmpfs test +# Simple unionfs(4) + tmpfs(4) test # "rmdir: d2: Directory not empty" seen. [ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 . ../default.cfg mp1=/mnt$mdstart mp2=/mnt$((mdstart + 1)) mkdir -p $mp1 $mp2 set -e for i in $mp1 $mp2; do mount | grep -q "on $i " && umount -f $i done md1=$mdstart md2=$((md1 + 1)) mp1=/mnt$md1 mp2=/mnt$md2 mkdir -p $mp1 $mp2 for i in $mp1 $mp2; do mount | grep -q "on $i " && umount -f $i done if [ $# -eq 0 ]; then echo "tmpfs version" mount -o size=4g -t tmpfs dummy $mp1 mount -o size=4g -t tmpfs dummy $mp2 else echo "UFS version" for i in $md1 $md2; do mdconfig -l | grep -q md$i && mdconfig -d -u $i done mdconfig -a -t swap -s 4g -u $md1 mdconfig -a -t swap -s 4g -u $md2 newfs $newfs_flags -n md$md1 > /dev/null newfs $newfs_flags -n md$md2 > /dev/null mount /dev/md$md1 $mp1 mount /dev/md$md2 $mp2 fi mount -t unionfs -o noatime $mp1 $mp2 set +e N=3 # Tree depth here=`pwd` cd $mp2 mkdir dir; cd dir for j in `seq 1 $N`; do mkdir d$j && cd d$j done for j in `seq $N 1`; do cd .. && rmdir d$j done cd .. rmdir dir || { s=1; find dir -ls; } cd $here while mount | grep -Eq "on $mp2 .*unionfs"; do umount $mp2 && break sleep 5 done umount $mp2 umount $mp1 exit $s diff --git a/tools/test/stress2/misc/unionfs6.sh b/tools/test/stress2/misc/unionfs6.sh index 54e688b0a111..cae1995a2e0d 100755 --- a/tools/test/stress2/misc/unionfs6.sh +++ b/tools/test/stress2/misc/unionfs6.sh @@ -1,104 +1,104 @@ #!/bin/sh # # SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2021 Peter Holm # # 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. # -# unionfs(8) test +# unionfs(4) test # "panic: ufs dir vp 0xfffffe0157351068 ip 0xfffffe016a63d488 flags 0x3c06" seen [ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 . ../default.cfg md1=$mdstart md2=$((md1 + 1)) mp1=/mnt$md1 mp2=/mnt$md2 mkdir -p $mp1 $mp2 set -e for i in $mp1 $mp2; do mount | grep -q "on $i " && umount -f $i done for i in $md1 $md2; do mdconfig -l | grep -q md$i && mdconfig -d -u $i done mdconfig -a -t swap -s 4g -u $md1 mdconfig -a -t swap -s 4g -u $md2 newfs $newfs_flags -n md$md1 > /dev/null newfs $newfs_flags -n md$md2 > /dev/null mount /dev/md$md1 $mp1 mount /dev/md$md2 $mp2 mount -t unionfs -o noatime $mp1 $mp2 set +e mount | grep -E "$mp1|$mp2" set `df -ik $mp2 | tail -1 | awk '{print $4,$7}'` export KBLOCKS=$(($1 / 4)) export INODES=$(($2 / 4)) export CTRLDIR=$mp2/stressX.control export INCARNATIONS=10 export LOAD=80 export RUNDIR=$mp2/stressX export runRUNTIME=5m export rwLOAD=80 export symlinkLOAD=80 export TESTPROGS=" testcases/lockf2/lockf2 testcases/symlink/symlink testcases/openat/openat testcases/rw/rw testcases/fts/fts testcases/link/link testcases/lockf/lockf testcases/creat/creat testcases/mkdir/mkdir testcases/rename/rename testcases/mkfifo/mkfifo testcases/dirnprename/dirnprename testcases/dirrename/dirrename testcases/swap/swap " set +e chmod 777 $mp2 su $testuser -c \ '(cd ..; ./testcases/run/run $TESTPROGS)' while mount | grep -Eq "on $mp2 .*unionfs"; do umount $mp2 && break sleep 5 done umount $mp2 n=`find $mp1/stressX | wc -l` [ $n -eq 1 ] && s=0 || { find $mp1/stressX -ls | head -12; s=1; } umount $mp1 mdconfig -d -u $md2 mdconfig -d -u $md1 exit $s diff --git a/tools/test/stress2/misc/unionfs7.sh b/tools/test/stress2/misc/unionfs7.sh index 1684a960d142..6adcd01a5f83 100755 --- a/tools/test/stress2/misc/unionfs7.sh +++ b/tools/test/stress2/misc/unionfs7.sh @@ -1,110 +1,110 @@ #!/bin/sh # # SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2021 Peter Holm # # 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. # -# unionfs(8) test +# unionfs(4) test # "unionfs_get_node_status: 0xfffffe018f356770 is not exclusive locked but # should be" seen. # https://people.freebsd.org/~pho/stress/log/log0202.txt [ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 . ../default.cfg md1=$mdstart md2=$((md1 + 1)) mp1=/mnt$md1 mp2=/mnt$md2 mkdir -p $mp1 $mp2 set -e for i in $mp1 $mp2; do mount | grep -q "on $i " && umount -f $i done for i in $md1 $md2; do mdconfig -l | grep -q md$i && mdconfig -d -u $i done mdconfig -a -t swap -s 4g -u $md1 mdconfig -a -t swap -s 4g -u $md2 newfs $newfs_flags -n md$md1 > /dev/null newfs $newfs_flags -n md$md2 > /dev/null mount /dev/md$md1 $mp1 mount /dev/md$md2 $mp2 mount -t unionfs -o noatime $mp1 $mp2 set +e mount | grep -E "$mp1|$mp2" set `df -ik $mp2 | tail -1 | awk '{print $4,$7}'` export KBLOCKS=$(($1 / 4)) export INODES=$(($2 / 4)) export CTRLDIR=$mp2/stressX.control export INCARNATIONS=10 export LOAD=80 export RUNDIR=$mp2/stressX export runRUNTIME=5m export rwLOAD=80 export symlinkLOAD=80 export TESTPROGS=" testcases/lockf2/lockf2 testcases/symlink/symlink testcases/openat/openat testcases/rw/rw testcases/fts/fts testcases/link/link testcases/lockf/lockf testcases/creat/creat testcases/mkdir/mkdir testcases/rename/rename testcases/mkfifo/mkfifo testcases/dirnprename/dirnprename testcases/dirrename/dirrename testcases/swap/swap " cp -r ../../stress2 $mp2 export TESTPROGS=`echo $TESTPROGS | sed 's/\n/ /g'` set +e chmod 777 $mp2 su $testuser -c \ "(cd $mp2/stress2; ./testcases/run/run $TESTPROGS)" while mount | grep -Eq "on $mp2 .*unionfs"; do umount $mp2 && break sleep 5 done umount $mp2 n=`find $mp1/stressX | wc -l` [ $n -eq 1 ] && s=0 || { find $mp1/stressX -ls | head -12; s=1; } umount $mp1 mdconfig -d -u $md2 mdconfig -d -u $md1 exit $s diff --git a/tools/test/stress2/misc/unionfs8.sh b/tools/test/stress2/misc/unionfs8.sh index 9ddf5a990b82..fdc37b16ff03 100755 --- a/tools/test/stress2/misc/unionfs8.sh +++ b/tools/test/stress2/misc/unionfs8.sh @@ -1,124 +1,124 @@ #!/bin/sh # # SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2021 Peter Holm # # 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. # -# unionfs(8) test with a cd9660 file system +# unionfs(4) test with a cd9660(4) file system # "panic: unionfs_noderem: vnode 0xfffffe014f9259c8 locked recursively" seen # https://people.freebsd.org/~pho/stress/log/log0233.txt [ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 [ -z "`type mkisofs 2>/dev/null`" ] && { echo "cdrtools not installed"; exit 0; } . ../default.cfg I=`dirname $diskimage`/unionfs8.iso md1=$mdstart md2=$((md1 + 1)) mp1=/mnt$md1 mp2=/mnt$md2 mkdir -p $mp1 $mp2 set -e for i in $mp1 $mp2; do mount | grep -q "on $i " && umount -f $i done for i in $md1 $md2; do mdconfig -l | grep -q md$i && mdconfig -d -u $i done mdconfig -a -t swap -s 5g -u $md1 mdconfig -a -t swap -s 5g -u $md2 newfs $newfs_flags -n md$md1 > /dev/null newfs $newfs_flags -n md$md2 > /dev/null mount /dev/md$md1 $mp1 cp -r ../../stress2 $mp1 mkisofs -o $I -r $mp1 > /dev/null 2>&1 umount $mp1 mdconfig -d -u $md1 mdconfig -a -t vnode -f $I -u $md1 mount -t cd9660 /dev/md$mdstart $mp1 mount /dev/md$md2 $mp2 chmod 777 $mp2 mount -t unionfs -o below $mp1 $mp2 set +e mount | grep -E "$mp1|$mp2" set `df -ik $mp2 | tail -1 | awk '{print $4,$7}'` export KBLOCKS=$(($1 / 6)) export INODES=$(($2 / 6)) export CTRLDIR=$mp2/stressX.control export INCARNATIONS=10 export LOAD=80 export RUNDIR=$mp2/stressX export runRUNTIME=5m export rwLOAD=80 export symlinkLOAD=80 export TESTPROGS=" testcases/lockf2/lockf2 testcases/symlink/symlink testcases/openat/openat testcases/rw/rw testcases/fts/fts testcases/link/link testcases/lockf/lockf testcases/creat/creat testcases/mkdir/mkdir testcases/rename/rename testcases/mkfifo/mkfifo testcases/dirnprename/dirnprename testcases/dirrename/dirrename testcases/swap/swap " export TESTPROGS=`echo $TESTPROGS | sed 's/\n/ /g'` set +e su $testuser -c \ "(cd $mp2/stress2; ./testcases/run/run $TESTPROGS)" n=`find $mp2/stressX 2>/dev/null | wc -l` [ $n -eq 1 ] && s=0 || { find $mp2/stressX -ls 2>/dev/null | head -12; s=1; } while mount | grep "on $mp2" | grep -q unionfs; do umount $mp2 && break done for i in `jot 5`; do umount $mp2 && break sleep .5 done for i in `jot 5`; do umount $mp1 && break sleep .5 done mdconfig -d -u $md2 mdconfig -d -u $md1 rm -f $I exit $s