diff options
author | dwmalone <dwmalone@FreeBSD.org> | 2006-02-25 23:50:15 +0000 |
---|---|---|
committer | dwmalone <dwmalone@FreeBSD.org> | 2006-02-25 23:50:15 +0000 |
commit | 7c9e42abb8ff3f164843c9c192e95f5d75147f63 (patch) | |
tree | 3802358c2cbefb0ef713e431a1ef45dbf8df1298 /usr.sbin | |
parent | 2bc6196058d69652ef5cbb29bfbd67c3314ae887 (diff) | |
download | FreeBSD-src-7c9e42abb8ff3f164843c9c192e95f5d75147f63.zip FreeBSD-src-7c9e42abb8ff3f164843c9c192e95f5d75147f63.tar.gz |
The quot command expected all inodes contents to be valid, however
on UFS2 inodes are initialised as they are needed, rather than at
newfs time. When quot encountered these inodes it could produce
crazy results.
Now, on UFS2 filesystems, quot's get_inode function will bzero
unallicated inodes before passing them back to a caller. This is
how UFS2 initialises new inodes, so this should work OK.
Also, while I'm here, make quot exit with an error if it finds
inodes of an unknown type. This should help catch future problems
of this type.
Reviewed by: iedowse
MFC after: 1 week
Diffstat (limited to 'usr.sbin')
-rw-r--r-- | usr.sbin/quot/quot.c | 34 |
1 files changed, 31 insertions, 3 deletions
diff --git a/usr.sbin/quot/quot.c b/usr.sbin/quot/quot.c index 42e8f48..7ef4ae8 100644 --- a/usr.sbin/quot/quot.c +++ b/usr.sbin/quot/quot.c @@ -112,17 +112,36 @@ get_inode(fd,super,ino) ino_t ino; { static caddr_t ipbuf; + static struct cg *cgp; static ino_t last; + static int cg; + struct ufs2_dinode *di2; if (fd < 0) { /* flush cache */ if (ipbuf) { free(ipbuf); ipbuf = 0; + if (super->fs_magic == FS_UFS2_MAGIC) { + free(cgp); + cgp = 0; + } } return 0; } if (!ipbuf || ino < last || ino >= last + INOCNT(super)) { + if (super->fs_magic == FS_UFS2_MAGIC && + (!cgp || cg != ino_to_cg(super, ino))) { + cg = ino_to_cg(super, ino); + if (!cgp && !(cgp = malloc(super->fs_cgsize))) + errx(1, "allocate cg"); + if (lseek(fd, (off_t)cgtod(super, cg) << super->fs_fshift, 0) < 0) + err(1, "lseek cg"); + if (read(fd, cgp, super->fs_cgsize) != super->fs_cgsize) + err(1, "read cg"); + if (!cg_chkmagic(cgp)) + errx(1, "cg has bad magic"); + } if (!ipbuf && !(ipbuf = malloc(INOSZ(super)))) errx(1, "allocate inodes"); @@ -135,8 +154,11 @@ get_inode(fd,super,ino) if (super->fs_magic == FS_UFS1_MAGIC) return ((union dinode *) &((struct ufs1_dinode *)ipbuf)[ino % INOCNT(super)]); - return ((union dinode *) - &((struct ufs2_dinode *)ipbuf)[ino % INOCNT(super)]); + di2 = &((struct ufs2_dinode *)ipbuf)[ino % INOCNT(super)]; + /* If the inode is unused, it might be unallocated too, so zero it. */ + if (isclr(cg_inosused(cgp), ino % super->fs_ipg)) + bzero(di2, sizeof (*di2)); + return ((union dinode *)di2); } #ifdef COMPAT @@ -194,8 +216,14 @@ isfree(super, dp) case IFDIR: case IFREG: return 0; - default: + case IFCHR: + case IFBLK: + case IFSOCK: + case IFWHT: + case 0: return 1; + default: + errx(1, "unknown IFMT 0%o", DIP(super, dp, di_mode) & IFMT); } #endif } |