1#!/bin/sh 2 3# 4# Copyright (c) 2016 Dell EMC 5# All rights reserved. 6# 7# Redistribution and use in source and binary forms, with or without 8# modification, are permitted provided that the following conditions 9# are met: 10# 1. Redistributions of source code must retain the above copyright 11# notice, this list of conditions and the following disclaimer. 12# 2. Redistributions in binary form must reproduce the above copyright 13# notice, this list of conditions and the following disclaimer in the 14# documentation and/or other materials provided with the distribution. 15# 16# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26# SUCH DAMAGE. 27# 28 29# Demonstrate that vfs_export() leaks M_CRED when mountd(8) is started: 30# "M_CRED leaked 160". 31 32[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 33 34. ../default.cfg 35 36pgrep -q mountd || echo "Note: mountd(8) must run for this test to fail" 37here=`pwd` 38cd /tmp 39sed '1,/^EOF/d' < $here/$0 > credleak.c 40mycc -o credleak -Wall -Wextra -O2 -g credleak.c || exit 1 41rm -f credleak.c 42 43mount | grep -q "on $mntpoint " && umount -f $mntpoint 44mount -t tmpfs tmpfs $mntpoint 45chmod 777 $mntpoint 46 47old=`vmstat -m | grep -w cred | awk '{print $2}'` 48su $testuser -c "/tmp/credleak $mntpoint" & 49 50while kill -0 $! 2>/dev/null; do 51 umount -f $mntpoint && 52 mount -t tmpfs tmpfs $mntpoint 53 chmod 777 $mntpoint 54 sleep .1 55done 56pkill -9 swap 57wait 58 59while pkill -9 swap; do 60 : 61done > /dev/null 2>&1 62while mount | grep $mntpoint | grep -q tmpfs; do 63 umount $mntpoint || sleep 1 64done 65[ -d "$mntpoint" ] && (cd $mntpoint && find . -delete) 66rm -f /tmp/credleak 67 68s=0 69leak=$((`vmstat -m | grep -w cred | awk '{print $2}'` - old)) 70[ $leak -gt 10 ] && { echo "M_CRED leaked $leak"; s=1; } 71exit $s 72EOF 73#include <sys/param.h> 74#include <sys/stat.h> 75#include <sys/wait.h> 76 77#include <err.h> 78#include <errno.h> 79#include <fcntl.h> 80#include <stdio.h> 81#include <stdlib.h> 82#include <string.h> 83#include <unistd.h> 84 85#define LOOPS 160 86#define PARALLEL 16 87 88int nbc, nbd; 89char *dir; 90 91void 92tmkdir(void) 93{ 94 int i, j; 95 char d[MAXPATHLEN + 1], name[MAXPATHLEN + 1]; 96 97 setproctitle(__func__); 98 99 i = 0; 100 snprintf(name, sizeof(name), "%s/d1.%05d", dir, getpid()); 101 if (mkdir(name, 0755) == -1) { 102 if (errno != ENAMETOOLONG && errno != ENOENT && 103 errno != EBUSY && errno != EACCES && errno != EPERM) 104 warn("mkdir(%s)", name); 105 _exit(0); 106 } 107 for (;;) { 108 snprintf(d, sizeof(d), "/%d", i++); 109 strncat(name, d, sizeof(name) - 1); 110 if (mkdir(name, 0755) == -1) { 111 if (errno != ENAMETOOLONG && errno != ENOENT && 112 errno != EBUSY && errno != EACCES && errno != EPERM) 113 warn("mkdir(%s)", name); 114 i--; 115 break; 116 } 117 nbc++; 118 } 119 120 while (i >= 0) { 121 snprintf(name, sizeof(name), "%s/d1.%05d", dir, getpid()); 122 for (j = 0; j < i; j++) { 123 snprintf(d, sizeof(d), "/%d", j); 124 strncat(name, d, sizeof(name) - 1); 125 } 126 if (rmdir(name) == -1) { 127 if (errno != ENOTEMPTY && errno != ENOENT && errno != 128 EBUSY) 129 warn("rmdir(%s)", name); 130 } else 131 nbd++; 132 i--; 133 } 134#if defined(TEST) 135 if (nbc == 0) 136 fprintf(stderr, "FAIL nbc = %d, nbd = %d\n", nbc, nbd); 137#endif 138 _exit(0); 139} 140 141int 142main(int argc, char **argv) 143{ 144 int i, j; 145 146 if (argc != 2) { 147 fprintf(stderr, "Usage: %s <full path to dir>", argv[0]); 148 exit(1); 149 } 150 dir = argv[1]; 151 152 for (j = 0; j < LOOPS; j++) { 153 for (i = 0; i < PARALLEL; i++) { 154 if (fork() == 0) 155 tmkdir(); 156 } 157 for (i = 0; i < PARALLEL; i++) 158 wait(NULL); 159 } 160 161 return(0); 162} 163