1#!/bin/sh 2 3# 4# Copyright (c) 2017 Dell EMC Isilon 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# Test nfsv4 delegations. Scenario suggestion by kib. 30# "(nfsdelegation), uid 0, was killed: text file modification" seen. 31# Fixed by r316745 32 33[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 34 35. ../default.cfg 36 37[ -z "$nfs_export" ] && exit 0 38ping -c 2 `echo $nfs_export | sed 's/:.*//'` > /dev/null 2>&1 || 39 exit 0 40 41here=`pwd` 42cd /tmp 43sed '1,/^EOF/d' < $here/$0 > nfsdelegation.c 44mycc -o nfsdelegation -Wall -Wextra -O0 nfsdelegation.c || exit 1 45rm -f nfsdelegation.c 46 47[ `sysctl -n sysctl vfs.timestamp_precision` -ne 3 ] && 48 echo "vfs.timestamp_precision must be set to 3" 49[ "`sysctl -ni vfs.nfsd.issue_delegations`" != "1" ] && 50 { echo "vfs.nfsd.issue_delegations is not enabled"; exit 0; } 51pgrep -q nfscbd || { echo "nfscbd is not running"; exit 0; } 52 53mount | grep "$mntpoint" | grep -q nfs && umount $mntpoint 54opt="-o nocto" 55opt="$opt -o nolockd -o nfsv4" 56mount $opt $nfs_export $mntpoint || exit 1 57sleep .2 58 59wdir=$mntpoint/nfsdelegation.`jot -rc 8 a z | tr -d '\n'`/nfsdelegation 60mkdir -p $wdir || exit 1 61 62delegs=0 63s=0 64(cd $wdir; /tmp/nfsdelegation) & 65while kill -0 $! 2>/dev/null; do 66 r=`nfsstat -ec | grep -A1 Delegs | tail -1 | awk '{print $5}'` 67 [ $r -gt $delegs ] && { delegs=$r; break; } 68done 69wait 70[ $delegs -eq 0 ] && { echo "No delegations detected"; s=2; } 71 72rm -rf $wdir 73umount $mntpoint 74while mount | grep "$mntpoint " | grep -q nfs; do 75 umount -f $mntpoint 76done 77tail -3 /var/log/messages | grep -m1 nfsdelegation: && s=2 78rm -f /tmp/nfsdelegation 79exit $s 80EOF 81#include <sys/param.h> 82#include <sys/mman.h> 83#include <sys/stat.h> 84#include <sys/wait.h> 85 86#include <err.h> 87#include <errno.h> 88#include <fcntl.h> 89#include <stdio.h> 90#include <stdlib.h> 91#include <string.h> 92#include <unistd.h> 93 94#define LOOPS 100 95#define INPUTFILE "/bin/sleep" 96#define PARALLEL 3 97 98static volatile u_int *share; 99 100static int 101tmmap(int idx) 102{ 103 struct stat statbuf; 104 pid_t epid, pid; 105 int i; 106 int fdout; 107 char *cmdline[3], *dst, file[128], help[80]; 108 109 pid = getpid(); 110 cmdline[1] = ".01"; 111 cmdline[2] = 0; 112 for (i = 0; i < LOOPS; i++) { 113 sprintf(file,"nfsdelegation.p%05d.%05d", pid, i); 114 cmdline[0] = file; 115 116 snprintf(help, sizeof(help), "cp %s %s; chmod 777 %s", INPUTFILE, file, file); 117 system(help); 118 share[idx] = 0; 119 if ((epid = fork()) == 0) { 120 alarm(60); 121 while (share[idx] == 0) 122 usleep(100); 123 if (execve(cmdline[0], cmdline, NULL) == -1) 124 err(1, "execve"); 125 } 126 127 if ((fdout = open(file, O_RDWR)) < 0) 128 err(1, "open(%s)", file); 129 if (fstat(fdout, &statbuf) < 0) 130 err(1, "fstat error"); 131 132 if ((dst = mmap(0, statbuf.st_size, PROT_READ | PROT_WRITE | 133 MAP_PRIVATE, MAP_SHARED, fdout, 0)) == (caddr_t) - 1) 134 err(1, "mmap error for output"); 135 136 dst[statbuf.st_size] = 1; 137 138 close(fdout); 139 if (munmap(dst, statbuf.st_size) == -1) 140 err(1, "munmap"); 141 share[idx] = 1; 142 if (waitpid(epid, NULL, 0) != epid) 143 err(1, "waitpid(%d)", epid); 144 } 145 146 _exit(0); 147} 148 149int 150main(void) 151{ 152 size_t len; 153 int i; 154 155 len = PAGE_SIZE; 156 if ((share = mmap(NULL, len, PROT_READ | PROT_WRITE, 157 MAP_ANON | MAP_SHARED, -1, 0)) == MAP_FAILED) 158 err(1, "mmap"); 159 for (i = 0; i < PARALLEL; i++) { 160 if (fork() == 0) 161 tmmap(i); 162 } 163 164 for (i = 0; i < PARALLEL; i++) { 165 wait(NULL); 166 } 167 168 return (0); 169} 170