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 == FS_MAGIC && 112 (fs->fs_version != UFS_EFISTYLE4NONEFI_VERSION_2 && 113 fs->fs_version != 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 (fs->fs_magic == MTB_UFS_MAGIC && 120 (fs->fs_version > MTB_UFS_VERSION_1 || 121 fs->fs_version < MTB_UFS_VERSION_MIN)) { 122 (void) fprintf(stderr, 123 "fsirand: Unrecognized UFS format version number %d (in superblock)\n", 124 fs->fs_version); 125 exit(1); 126 } 127 if (pflag) { 128 (void) printf("fsid: %x %x\n", fs->fs_id[0], fs->fs_id[1]); 129 } else { 130 n = getpid(); 131 (void) gettimeofday(&timeval, (struct timezone *)NULL); 132 srand48((long)(timeval.tv_sec + timeval.tv_usec + n)); 133 } 134 bsize = INOPB(fs) * sizeof (struct dinode); 135 inum = 0; 136 imax = fs->fs_ipg * fs->fs_ncg; 137 while (inum < imax) { 138 bno = itod(fs, inum); 139 seekaddr = (offset_t)fsbtodb(fs, bno) * DEV_BSIZE; 140 if (llseek(fd, seekaddr, 0) == -1) { 141 (void) fprintf(stderr, 142 "fsirand: Seek to %ld %ld failed: %s\n", 143 ((off_t *)&seekaddr)[0], ((off_t *)&seekaddr)[1], 144 strerror(errno)); 145 exit(1); 146 } 147 n = read(fd, (char *)dibuf, bsize); 148 if (n != bsize) { 149 (void) fprintf(stderr, 150 "fsirand: Read of ilist block failed: %s\n", 151 n == -1 ? strerror(errno) : "Short read"); 152 exit(1); 153 } 154 for (dip = dibuf; dip < &dibuf[INOPB(fs)]; dip++) { 155 if (pflag) { 156 (void) printf("ino %d gen %x\n", inum, 157 dip->di_gen); 158 } else { 159 dip->di_gen = lrand48(); 160 } 161 inum++; 162 } 163 if (!pflag) { 164 if (llseek(fd, seekaddr, 0) == -1) { 165 (void) fprintf(stderr, 166 "fsirand: Seek to %ld %ld failed: %s\n", 167 ((off_t *)&seekaddr)[0], 168 ((off_t *)&seekaddr)[1], 169 strerror(errno)); 170 exit(1); 171 } 172 n = write(fd, (char *)dibuf, bsize); 173 if (n != bsize) { 174 (void) fprintf(stderr, 175 "fsirand: Write of ilist block failed: %s\n", 176 n == -1 ? strerror(errno) : "Short write"); 177 exit(1); 178 } 179 } 180 } 181 if (!pflag) { 182 (void) gettimeofday(&timeval, (struct timezone *)NULL); 183 fs->fs_id[0] = timeval.tv_sec; 184 fs->fs_id[1] = timeval.tv_usec + getpid(); 185 if (llseek(fd, (offset_t)SBLOCK * DEV_BSIZE, 0) == -1) { 186 (void) fprintf(stderr, 187 "fsirand: Seek to superblock failed: %s\n", 188 strerror(errno)); 189 exit(1); 190 } 191 if ((n = write(fd, (char *)fs, SBSIZE)) != SBSIZE) { 192 (void) fprintf(stderr, 193 "fsirand: Write of superblock failed: %s\n", 194 n == -1 ? strerror(errno) : "Short write"); 195 exit(1); 196 } 197 } 198 for (i = 0; i < fs->fs_ncg; i++) { 199 seekaddr = (offset_t)fsbtodb(fs, cgsblock(fs, i)) * DEV_BSIZE; 200 if (llseek(fd, seekaddr, 0) == -1) { 201 (void) fprintf(stderr, 202 "fsirand: Seek to alternate superblock failed: %s\n", 203 strerror(errno)); 204 exit(1); 205 } 206 if (pflag) { 207 if ((n = read(fd, (char *)fs, SBSIZE)) != SBSIZE) { 208 (void) fprintf(stderr, 209 "fsirand: Read of alternate superblock failed: %s\n", 210 n == -1 ? strerror(errno) : "Short read"); 211 exit(1); 212 } 213 if ((fs->fs_magic != FS_MAGIC) && 214 (fs->fs_magic != MTB_UFS_MAGIC)) { 215 (void) fprintf(stderr, 216 "fsirand: Not a valid file system (bad " 217 "magic number in alternate superblock)\n"); 218 exit(1); 219 } 220 } else { 221 if ((n = write(fd, (char *)fs, SBSIZE)) != SBSIZE) { 222 (void) fprintf(stderr, 223 "fsirand: Write of alternate superblock failed: %s\n", 224 n == -1 ? strerror(errno) : "Short write"); 225 exit(1); 226 } 227 } 228 } 229 return (0); 230 } 231