1#!/bin/sh 2 3# 4# SPDX-License-Identifier: BSD-2-Clause 5# 6# Copyright (c) 2022 Peter Holm <pho@FreeBSD.org> 7# 8# Redistribution and use in source and binary forms, with or without 9# modification, are permitted provided that the following conditions 10# are met: 11# 1. Redistributions of source code must retain the above copyright 12# notice, this list of conditions and the following disclaimer. 13# 2. Redistributions in binary form must reproduce the above copyright 14# notice, this list of conditions and the following disclaimer in the 15# documentation and/or other materials provided with the distribution. 16# 17# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27# SUCH DAMAGE. 28# 29 30[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 31 32# Test setrlimit() max file size and ftruncate() 33 34# Problem seen: 35# Testing UFS -O1 36# setrlimit: ftruncate(5413) did not fail. limit = 2791 37# Testing FFS -U 38# setrlimit: ftruncate(9956) did not fail. limit = 7880 39# Testing msdosfs 40# setrlimit: ftruncate(9033) did not fail. limit = 5884 41# Testing tmpfs 42# setrlimit: ftruncate(123) did not fail. limit = 86 43 44. ../default.cfg 45 46cat > /tmp/setrlimit.c <<EOF 47#include <sys/types.h> 48#include <sys/resource.h> 49#include <sys/stat.h> 50 51#include <err.h> 52#include <errno.h> 53#include <fcntl.h> 54#include <signal.h> 55#include <stdio.h> 56#include <stdlib.h> 57#include <unistd.h> 58 59static int signals; 60 61static void 62handler(int sig __unused) 63{ 64#if defined(DEBUG) 65 fprintf(stderr, "Got signal SIGXFSZ\n"); 66#endif 67 signals++; 68} 69 70void 71test(int argc, char *argv[]) 72{ 73 struct rlimit rlim; 74 rlim_t limit, sz; 75 struct sigaction act; 76 long pos; 77 int e, expected, fd; 78 char file[] = "setrlimit.file"; 79 80 if (argc != 2) { 81 fprintf(stderr, "Usage: %s <FS size>\n", argv[0]); 82 exit(1); 83 } 84 expected = signals = 0; 85 sz = atol(argv[1]); 86 arc4random_buf(&limit, sizeof(limit)); 87 if (limit < 0) 88 limit = -limit; 89 limit = limit % sz + 1; 90 rlim.rlim_cur = rlim.rlim_max = limit; 91 if (setrlimit(RLIMIT_FSIZE, &rlim) == -1) 92 err(1, "setrlimit(%ld)", limit); 93 94 act.sa_handler = handler; 95 act.sa_flags = 0; 96 sigemptyset(&act.sa_mask); 97 if (sigaction(SIGXFSZ, &act, NULL) != 0) 98 err(1, "sigaction"); 99 100 if ((fd = open(file, O_WRONLY | O_CREAT | O_TRUNC, DEFFILEMODE)) == -1) 101 err(1, "open(%s)", file); 102 103 e = 0; 104 arc4random_buf(&pos, sizeof(pos)); 105 if (pos < 0) 106 pos = -pos; 107 pos = pos % (limit * 2); 108 if (pos > limit) 109 expected = 1; 110 if (ftruncate(fd, pos) == -1) { 111 e = errno; 112 if (pos <= limit) 113 errc(1, e, "ftruncate(%ld), limit = %ld", pos, limit); 114 } else { 115 if (pos > limit) 116 errx(1, "ftruncate(%ld) did not fail. limit = %ld", pos, limit); 117 } 118 119 if (lseek(fd, limit - 1, SEEK_SET) == -1) 120 err(1, "lseek(limit - 1)"); 121 if (write(fd, "a", 1) != 1) 122 err(1, "write() at limit - 1. limit = %ld", limit); 123 124 if (write(fd, "b", 1) != -1) 125 err(1, "write() at limit. limit = %ld", limit); 126 expected++; 127 128 /* Partial write test. No signal is expected */ 129 if (lseek(fd, limit - 1, SEEK_SET) == -1) 130 err(1, "lseek(limit - 1)"); 131 if (write(fd, "12", 2) != 1) 132 err(1, "write() at limit - 1. limit = %ld", limit); 133 134 if (signals != expected) 135 errx(1, "Expected %d signals, got %d", expected, signals); 136 137 close(fd); 138 unlink(file); 139} 140 141int 142main(int argc, char *argv[]) 143{ 144 int i; 145 146 for (i = 0; i < 100; i++) 147 test(argc, argv); 148 149} 150EOF 151 152here=`pwd` 153s=0 154cc -o /tmp/setrlimit -Wall -Wextra -O0 -g /tmp/setrlimit.c || exit 1 155 156mount | grep "on $mntpoint " | grep -q /dev/md && umount -f $mntpoint 157[ -c /dev/md$mdstart ] && mdconfig -d -u $mdstart 158 159echo "Testing UFS -O1" 160mdconfig -t swap -s 1g -u $mdstart 161newfs -O1 /dev/md$mdstart > /dev/null 162mount /dev/md$mdstart $mntpoint 163cd $mntpoint; /tmp/setrlimit 10000 || s=1 164cd $here 165umount $mntpoint 166mdconfig -d -u $mdstart 167 168echo "Testing FFS -U" 169mdconfig -t swap -s 1g -u $mdstart 170newfs -U /dev/md$mdstart > /dev/null 171mount /dev/md$mdstart $mntpoint 172cd $mntpoint; /tmp/setrlimit 10000 || s=$((s + 2)) 173cd $here 174umount $mntpoint 175mdconfig -d -u $mdstart 176 177echo "Testing msdosfs" 178mdconfig -t swap -s 1g -u $mdstart 179newfs_msdos -F 32 -b 8192 /dev/md$mdstart > /dev/null 2>&1 180mount -t msdosfs /dev/md$mdstart $mntpoint 181cd $mntpoint; /tmp/setrlimit 10000 || s=$((s + 4)) 182cd $here 183umount $mntpoint 184mdconfig -d -u $mdstart 185 186echo "Testing tmpfs" 187mount -o size=20000 -t tmpfs dummy $mntpoint 188cd $mntpoint; /tmp/setrlimit 10000 || s=$((s + 8)) 189cd $here 190umount $mntpoint 191 192rm -f /tmp/setrlimit /tmp/setrlimit.c 193exit $s 194