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 /* 36 * fsirand installs random inode generation numbers on all the inodes on 37 * device <special>, and also installs a file system ID in the superblock. 38 * This helps increase the security of file systems exported by NFS. 39 */ 40 41 #include <fcntl.h> 42 #include <stdio.h> 43 #include <errno.h> 44 #include <strings.h> 45 #include <unistd.h> 46 #include <stdlib.h> 47 #include <sys/param.h> 48 #include <sys/types.h> 49 #include <sys/time.h> 50 #include <sys/fs/ufs_fs.h> 51 #include <sys/vnode.h> 52 #include <sys/fs/ufs_inode.h> 53 54 long fsbuf[(SBSIZE / sizeof (long))]; 55 struct dinode dibuf[8192/sizeof (struct dinode)]; 56 57 int 58 main(int argc, char *argv[]) 59 { 60 struct fs *fs; 61 int fd; 62 char *dev; 63 int bno; 64 struct dinode *dip; 65 int inum, imax; 66 int i, n; 67 offset_t seekaddr; 68 int bsize; 69 int pflag = 0; 70 struct timeval timeval; 71 72 argv++; 73 argc--; 74 if (argc > 0 && strcmp(*argv, "-p") == 0) { 75 pflag++; 76 argv++; 77 argc--; 78 } 79 if (argc <= 0) { 80 (void) fprintf(stderr, "Usage: fsirand [-p] special\n"); 81 exit(1); 82 } 83 dev = *argv; 84 fd = open64(dev, pflag ? O_RDONLY : O_RDWR); 85 if (fd == -1) { 86 (void) fprintf(stderr, "fsirand: Cannot open %s: %s\n", dev, 87 strerror(errno)); 88 exit(1); 89 } 90 if (llseek(fd, (offset_t)SBLOCK * DEV_BSIZE, 0) == -1) { 91 (void) fprintf(stderr, 92 "fsirand: Seek to superblock failed: %s\n", 93 strerror(errno)); 94 exit(1); 95 } 96 fs = (struct fs *)fsbuf; 97 if ((n = read(fd, (char *)fs, SBSIZE)) != SBSIZE) { 98 (void) fprintf(stderr, 99 "fsirand: Read of superblock failed: %s\n", 100 n == -1 ? strerror(errno) : "Short read"); 101 exit(1); 102 } 103 if ((fs->fs_magic != FS_MAGIC) && 104 (fs->fs_magic != MTB_UFS_MAGIC)) { 105 (void) fprintf(stderr, 106 "fsirand: Not a file system (bad magic number in superblock)\n"); 107 exit(1); 108 } 109 if (fs->fs_magic == FS_MAGIC && 110 (fs->fs_version != UFS_EFISTYLE4NONEFI_VERSION_2 && 111 fs->fs_version != UFS_VERSION_MIN)) { 112 (void) fprintf(stderr, 113 "fsirand: Unrecognized UFS format version number %d (in superblock)\n", 114 fs->fs_version); 115 exit(1); 116 } 117 if (fs->fs_magic == MTB_UFS_MAGIC && 118 (fs->fs_version > MTB_UFS_VERSION_1 || 119 fs->fs_version < MTB_UFS_VERSION_MIN)) { 120 (void) fprintf(stderr, 121 "fsirand: Unrecognized UFS format version number %d (in superblock)\n", 122 fs->fs_version); 123 exit(1); 124 } 125 if (pflag) { 126 (void) printf("fsid: %x %x\n", fs->fs_id[0], fs->fs_id[1]); 127 } else { 128 n = getpid(); 129 (void) gettimeofday(&timeval, (struct timezone *)NULL); 130 srand48((long)(timeval.tv_sec + timeval.tv_usec + n)); 131 } 132 bsize = INOPB(fs) * sizeof (struct dinode); 133 inum = 0; 134 imax = fs->fs_ipg * fs->fs_ncg; 135 while (inum < imax) { 136 bno = itod(fs, inum); 137 seekaddr = (offset_t)fsbtodb(fs, bno) * DEV_BSIZE; 138 if (llseek(fd, seekaddr, 0) == -1) { 139 (void) fprintf(stderr, 140 "fsirand: Seek to %ld %ld failed: %s\n", 141 ((off_t *)&seekaddr)[0], ((off_t *)&seekaddr)[1], 142 strerror(errno)); 143 exit(1); 144 } 145 n = read(fd, (char *)dibuf, bsize); 146 if (n != bsize) { 147 (void) fprintf(stderr, 148 "fsirand: Read of ilist block failed: %s\n", 149 n == -1 ? strerror(errno) : "Short read"); 150 exit(1); 151 } 152 for (dip = dibuf; dip < &dibuf[INOPB(fs)]; dip++) { 153 if (pflag) { 154 (void) printf("ino %d gen %x\n", inum, 155 dip->di_gen); 156 } else { 157 dip->di_gen = lrand48(); 158 } 159 inum++; 160 } 161 if (!pflag) { 162 if (llseek(fd, seekaddr, 0) == -1) { 163 (void) fprintf(stderr, 164 "fsirand: Seek to %ld %ld failed: %s\n", 165 ((off_t *)&seekaddr)[0], 166 ((off_t *)&seekaddr)[1], 167 strerror(errno)); 168 exit(1); 169 } 170 n = write(fd, (char *)dibuf, bsize); 171 if (n != bsize) { 172 (void) fprintf(stderr, 173 "fsirand: Write of ilist block failed: %s\n", 174 n == -1 ? strerror(errno) : "Short write"); 175 exit(1); 176 } 177 } 178 } 179 if (!pflag) { 180 (void) gettimeofday(&timeval, (struct timezone *)NULL); 181 fs->fs_id[0] = timeval.tv_sec; 182 fs->fs_id[1] = timeval.tv_usec + getpid(); 183 if (llseek(fd, (offset_t)SBLOCK * DEV_BSIZE, 0) == -1) { 184 (void) fprintf(stderr, 185 "fsirand: Seek to superblock failed: %s\n", 186 strerror(errno)); 187 exit(1); 188 } 189 if ((n = write(fd, (char *)fs, SBSIZE)) != SBSIZE) { 190 (void) fprintf(stderr, 191 "fsirand: Write of superblock failed: %s\n", 192 n == -1 ? strerror(errno) : "Short write"); 193 exit(1); 194 } 195 } 196 for (i = 0; i < fs->fs_ncg; i++) { 197 seekaddr = (offset_t)fsbtodb(fs, cgsblock(fs, i)) * DEV_BSIZE; 198 if (llseek(fd, seekaddr, 0) == -1) { 199 (void) fprintf(stderr, 200 "fsirand: Seek to alternate superblock failed: %s\n", 201 strerror(errno)); 202 exit(1); 203 } 204 if (pflag) { 205 if ((n = read(fd, (char *)fs, SBSIZE)) != SBSIZE) { 206 (void) fprintf(stderr, 207 "fsirand: Read of alternate superblock failed: %s\n", 208 n == -1 ? strerror(errno) : "Short read"); 209 exit(1); 210 } 211 if ((fs->fs_magic != FS_MAGIC) && 212 (fs->fs_magic != MTB_UFS_MAGIC)) { 213 (void) fprintf(stderr, 214 "fsirand: Not a valid file system (bad " 215 "magic number in alternate superblock)\n"); 216 exit(1); 217 } 218 } else { 219 if ((n = write(fd, (char *)fs, SBSIZE)) != SBSIZE) { 220 (void) fprintf(stderr, 221 "fsirand: Write of alternate superblock failed: %s\n", 222 n == -1 ? strerror(errno) : "Short write"); 223 exit(1); 224 } 225 } 226 } 227 return (0); 228 } 229