1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ 28 /* All Rights Reserved */ 29 30 /* 31 * Portions of this source code were derived from Berkeley 4.3 BSD 32 * under license from the Regents of the University of California. 33 */ 34 35 #pragma ident "%Z%%M% %I% %E% SMI" 36 37 /* 38 * fsirand installs random inode generation numbers on all the inodes on 39 * device <special>, and also installs a file system ID in the superblock. 40 * This helps increase the security of file systems exported by NFS. 41 */ 42 43 #include <fcntl.h> 44 #include <stdio.h> 45 #include <errno.h> 46 #include <strings.h> 47 #include <unistd.h> 48 #include <stdlib.h> 49 #include <sys/param.h> 50 #include <sys/types.h> 51 #include <sys/time.h> 52 #include <sys/fs/ufs_fs.h> 53 #include <sys/vnode.h> 54 #include <sys/fs/ufs_inode.h> 55 56 long fsbuf[(SBSIZE / sizeof (long))]; 57 struct dinode dibuf[8192/sizeof (struct dinode)]; 58 59 int 60 main(int argc, char *argv[]) 61 { 62 struct fs *fs; 63 int fd; 64 char *dev; 65 int bno; 66 struct dinode *dip; 67 int inum, imax; 68 int i, n; 69 offset_t seekaddr; 70 int bsize; 71 int pflag = 0; 72 struct timeval timeval; 73 74 argv++; 75 argc--; 76 if (argc > 0 && strcmp(*argv, "-p") == 0) { 77 pflag++; 78 argv++; 79 argc--; 80 } 81 if (argc <= 0) { 82 (void) fprintf(stderr, "Usage: fsirand [-p] special\n"); 83 exit(1); 84 } 85 dev = *argv; 86 fd = open64(dev, pflag ? O_RDONLY : O_RDWR); 87 if (fd == -1) { 88 (void) fprintf(stderr, "fsirand: Cannot open %s: %s\n", dev, 89 strerror(errno)); 90 exit(1); 91 } 92 if (llseek(fd, (offset_t)SBLOCK * DEV_BSIZE, 0) == -1) { 93 (void) fprintf(stderr, 94 "fsirand: Seek to superblock failed: %s\n", 95 strerror(errno)); 96 exit(1); 97 } 98 fs = (struct fs *)fsbuf; 99 if ((n = read(fd, (char *)fs, SBSIZE)) != SBSIZE) { 100 (void) fprintf(stderr, 101 "fsirand: Read of superblock failed: %s\n", 102 n == -1 ? strerror(errno) : "Short read"); 103 exit(1); 104 } 105 if ((fs->fs_magic != FS_MAGIC) && 106 (fs->fs_magic != MTB_UFS_MAGIC)) { 107 (void) fprintf(stderr, 108 "fsirand: Not a file system (bad magic number in superblock)\n"); 109 exit(1); 110 } 111 if (fs->fs_magic == MTB_UFS_MAGIC && 112 (fs->fs_version > MTB_UFS_VERSION_1 || 113 fs->fs_version < MTB_UFS_VERSION_MIN)) { 114 (void) fprintf(stderr, 115 "fsirand: Unrecognized UFS format version number %d (in superblock)\n", 116 fs->fs_version); 117 exit(1); 118 } 119 if (pflag) { 120 (void) printf("fsid: %x %x\n", fs->fs_id[0], fs->fs_id[1]); 121 } else { 122 n = getpid(); 123 (void) gettimeofday(&timeval, (struct timezone *)NULL); 124 srand48((long)(timeval.tv_sec + timeval.tv_usec + n)); 125 } 126 bsize = INOPB(fs) * sizeof (struct dinode); 127 inum = 0; 128 imax = fs->fs_ipg * fs->fs_ncg; 129 while (inum < imax) { 130 bno = itod(fs, inum); 131 seekaddr = (offset_t)fsbtodb(fs, bno) * DEV_BSIZE; 132 if (llseek(fd, seekaddr, 0) == -1) { 133 (void) fprintf(stderr, 134 "fsirand: Seek to %ld %ld failed: %s\n", 135 ((off_t *)&seekaddr)[0], ((off_t *)&seekaddr)[1], 136 strerror(errno)); 137 exit(1); 138 } 139 n = read(fd, (char *)dibuf, bsize); 140 if (n != bsize) { 141 (void) fprintf(stderr, 142 "fsirand: Read of ilist block failed: %s\n", 143 n == -1 ? strerror(errno) : "Short read"); 144 exit(1); 145 } 146 for (dip = dibuf; dip < &dibuf[INOPB(fs)]; dip++) { 147 if (pflag) { 148 (void) printf("ino %d gen %x\n", inum, 149 dip->di_gen); 150 } else { 151 dip->di_gen = lrand48(); 152 } 153 inum++; 154 } 155 if (!pflag) { 156 if (llseek(fd, seekaddr, 0) == -1) { 157 (void) fprintf(stderr, 158 "fsirand: Seek to %ld %ld failed: %s\n", 159 ((off_t *)&seekaddr)[0], 160 ((off_t *)&seekaddr)[1], 161 strerror(errno)); 162 exit(1); 163 } 164 n = write(fd, (char *)dibuf, bsize); 165 if (n != bsize) { 166 (void) fprintf(stderr, 167 "fsirand: Write of ilist block failed: %s\n", 168 n == -1 ? strerror(errno) : "Short write"); 169 exit(1); 170 } 171 } 172 } 173 if (!pflag) { 174 (void) gettimeofday(&timeval, (struct timezone *)NULL); 175 fs->fs_id[0] = timeval.tv_sec; 176 fs->fs_id[1] = timeval.tv_usec + getpid(); 177 if (llseek(fd, (offset_t)SBLOCK * DEV_BSIZE, 0) == -1) { 178 (void) fprintf(stderr, 179 "fsirand: Seek to superblock failed: %s\n", 180 strerror(errno)); 181 exit(1); 182 } 183 if ((n = write(fd, (char *)fs, SBSIZE)) != SBSIZE) { 184 (void) fprintf(stderr, 185 "fsirand: Write of superblock failed: %s\n", 186 n == -1 ? strerror(errno) : "Short write"); 187 exit(1); 188 } 189 } 190 for (i = 0; i < fs->fs_ncg; i++) { 191 seekaddr = (offset_t)fsbtodb(fs, cgsblock(fs, i)) * DEV_BSIZE; 192 if (llseek(fd, seekaddr, 0) == -1) { 193 (void) fprintf(stderr, 194 "fsirand: Seek to alternate superblock failed: %s\n", 195 strerror(errno)); 196 exit(1); 197 } 198 if (pflag) { 199 if ((n = read(fd, (char *)fs, SBSIZE)) != SBSIZE) { 200 (void) fprintf(stderr, 201 "fsirand: Read of alternate superblock failed: %s\n", 202 n == -1 ? strerror(errno) : "Short read"); 203 exit(1); 204 } 205 if ((fs->fs_magic != FS_MAGIC) && 206 (fs->fs_magic != MTB_UFS_MAGIC)) { 207 (void) fprintf(stderr, 208 "fsirand: Not a valid file system (bad " 209 "magic number in alternate superblock)\n"); 210 exit(1); 211 } 212 } else { 213 if ((n = write(fd, (char *)fs, SBSIZE)) != SBSIZE) { 214 (void) fprintf(stderr, 215 "fsirand: Write of alternate superblock failed: %s\n", 216 n == -1 ? strerror(errno) : "Short write"); 217 exit(1); 218 } 219 } 220 } 221 return (0); 222 } 223