Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 26 Jan 1997 02:04:59 +1100
From:      Giles Lean <giles@nemeton.com.au>
Cc:        Joshua Pincus <pinc_cif@uhura.cc.rochester.edu>, freebsd-scsi@freebsd.org
Subject:   Re: DISASTER! 
Message-ID:  <199701251505.CAA08199@nemeton.com.au>
In-Reply-To: <199701251407.BAA06874@nemeton.com.au> 

next in thread | previous in thread | raw e-mail | index | archive | help
------- =_aaaaaaaaaa0
Content-Type: text/plain; charset="us-ascii"
Content-ID: <8192.854204687.1@nemeton.com.au>

On Sun, 26 Jan 1997 01:07:52 +1100  Giles Lean wrote:

> #text/plain; name=findsb.c src/findsb.c
> #text/plain; name=icat.c src/icat/icat.c
> #text/plain; name=icat.man src/icat/icat.man

Dammit!  How embarassing.  Here they are.

Giles


------- =_aaaaaaaaaa0
Content-Type: text/plain; name="findsb.c"; charset="us-ascii"
Content-ID: <8192.854204687.2@nemeton.com.au>

/*
 * Find superblocks on a BSD FFS filesystem.
 *
 * On NetBSD, need only to check for FS_MAGIC.  HP-UX has about three
 * flavours of FS_MAGIC. You'll need something else for a Veritas
 * file system.
 */

#include <sys/param.h>
#include <sys/types.h>
#include <ufs/ffs/fs.h>

#include <fcntl.h>
#include <stdio.h>

/*
 * Usually larger on HP-UX -- too small will only result in the odd
 * false match.
 */
#define BLOCKSIZE (4 * 1024)

int
main(int argc, char *argv[])
{
	char            block[BLOCKSIZE];
	int             fd;
	struct fs      *filesys;
	int             n;
	int             blockno;

	blockno = 0;
	filesys = (struct fs *) block;

	if (argc != 2) {
		fprintf(stderr, "usage: findsb raw_device\n");
		exit(1);
	}

	if ((fd = open(argv[1], O_RDONLY)) < 0) {
		perror(argv[1]);
		exit(1);
	}

	while ((n = read(fd, block, BLOCKSIZE)) == BLOCKSIZE) {
		if (filesys->fs_magic == FS_MAGIC)
			printf("%d\n", blockno * (BLOCKSIZE / 512));
		blockno++;
	}
}

------- =_aaaaaaaaaa0
Content-Type: text/plain; name="icat.c"; charset="us-ascii"
Content-ID: <8192.854204687.3@nemeton.com.au>

/*
 * icat -- "cat" some inodes on a given device to standard out.
 * WARNING: this program is the biggest security hole in the
 * world, it allows you to completely bypass the file System.
 * Keep this code under your hat.
 */

#include <sys/param.h>
#include <sys/types.h>
#include <sys/file.h>
#include <sys/time.h>
#include <sys/vnode.h>
#include <ufs/ufs/quota.h>
#include <ufs/ufs/inode.h>
#include <ufs/ffs/fs.h>
#include <errno.h>
#include <stdio.h>

/* 4.4BSD changes */
#ifndef itod
#define itod ino_to_fsba
#define itoo ino_to_fsbo
#endif
	
#define	ISIZ		(sizeof(struct dinode))
#define	MAXINOPB	(MAXBSIZE / ISIZ)
#define	MAXNINDIR	(MAXBSIZE / sizeof(daddr_t))

union {
	char		dummy[SBSIZE];
	struct fs	sblk;
} sb_un;
#define sblock sb_un.sblk

struct dinode *iget();
void	bread();
void	indir();

char	*progname;
int	status;
long	dev_bsize = 1;
struct	dinode *ip;
char	bbuf[MAXBSIZE];

main(argc, argv)
	int argc;
	char *argv[];
{
	register int i;
	int fd;
	
	progname = argv[0];
	if (argc < 3) {
		fprintf(stderr, "Usage: %s filsys inumber ...\n", progname);
		exit(1);
	}
	fd = open(argv[1], O_RDONLY);
	if (fd < 0) {
		fprintf(stderr, "%s: cannot open ", progname);
		perror(argv[1]);
		exit(1);
	}
#ifndef tahoe
	bread(fd, SBSIZE, (char *)&sblock, SBSIZE);
#else
	bread(fd, SBOFF, (char *)&sblock, SBSIZE);
#endif
	if (sblock.fs_magic != FS_MAGIC) {
		fprintf(stderr, "%s: bad super-block magic number 0x%x\n",
			progname, sblock.fs_magic);
		exit(1);
	}
	dev_bsize = sblock.fs_fsize / fsbtodb(&sblock, 1);
	for (i = 2; i < argc; i++) {
		if (icatit(fd, argv[i]) == 0)
			status++;
	}
	exit(status);
}

icatit(fd, inumber)
	int fd;
	char *inumber;
{
	register int i;
	unsigned int n;
	int rsize;
	long size;
	
	if (!isnumber(inumber)) {
		fprintf(stderr, "%s: %s is not a number\n",
			progname, inumber);
		return (0);
	}
	n = atoi(inumber);
	if (n == 0) {
		fprintf(stderr, "%s: 0 is an invalid inode number\n",
			progname);
		return (0);
	}
	ip = iget(fd, n);
	if (ip == (struct dinode *)0) {
		fprintf(stderr, "%s: cannot read inode number %u\n",
			progname, n);
		return (0);
	}
	if ((ip->di_mode & IFMT) != IFREG) {
		fprintf(stderr,
			"%s: inode %u has mode 0%o; not a regular file\n",
			progname, n, ip->di_mode);
		return (0);
	}
	/* direct blocks */
	for (i = 0, size = ip->di_size; i < NDADDR && size > 0; i++) {
		rsize = MIN(size, sblock.fs_bsize);
		if (ip->di_db[i]) {
			bread(fd, fsbtodb(&sblock, ip->di_db[i]),
			      bbuf, (int) sblock.fs_bsize);
		} else {
			bzero((char *) bbuf, rsize);
		}
		if (write(1, bbuf, rsize) != rsize) {
			fprintf(stderr, "%s: failed write to ", progname);
			perror("stdout");
			return (0);
		}
		size -= rsize;
	}
	/* indirect blocks */
	for (i = 0; i < NIADDR && size > 0; i++) {
		if (ip->di_ib[i])
			indir(fd, ip->di_ib[i], i, &size);
	}
	return (1);
}

isnumber(s)
	char *s;
{
	register c;
	
	while(c = *s++)
		if (c < '0' || c > '9')
			return(0);
	return(1);
}

struct dinode *
iget(fd, inum)
	int fd;
	unsigned int inum;
{
	struct ino {
		char junk[ISIZ];
	};
	static struct ino buf[MAXINOPB];
	struct dinode *ip;
	
	bread(fd, fsbtodb(&sblock, itod(&sblock, inum)),
	      (char *)buf, (int) sblock.fs_bsize);
	ip = (struct dinode *) &buf[itoo(&sblock, inum)];
	return (ip);
}

void
bread(fd, bno, buf, cnt)
	int fd;
	daddr_t bno;
	char *buf;
	int cnt;
{
	off_t lseek();
	register int n;
	off_t off;
	
	off = bno * dev_bsize;
	if (lseek(fd, off, L_SET) != off) {
		fprintf(stderr, "%s: cannot read block 0x%x\n", progname, bno);
		exit(1);
	}
	if ((n = read(fd, buf, cnt)) < 0) {
		fprintf(stderr, "%s: premature EOF; ", progname);
		fprintf(stderr, "bno = %ld expected = %d count = %d\n",
			bno, cnt, n);
		exit(1);
	}
}

void
indir(fd, blk, lvl, size)
	int fd;
	daddr_t blk;
	int lvl;
	long *size;
{
	int i, rsize;
	daddr_t idblk[MAXNINDIR];
	
	if (blk != 0)
		bread(fd, fsbtodb(&sblock, blk),
		      (char *)idblk, (int)sblock.fs_bsize);
	else
		bzero((char *)idblk, (int)sblock.fs_bsize);
	if (lvl <= 0) {
		for (i = 0; i < NINDIR(&sblock) && *size > 0; i++) {
			rsize = MIN(*size, sblock.fs_bsize);
			if (idblk[i]) {
				bread(fd, fsbtodb(&sblock, idblk[i]),
				      bbuf, (int) sblock.fs_bsize);
			} else {
				bzero((char *) bbuf, rsize);
			}
			if (write(1, bbuf, rsize) != rsize) {
				fprintf(stderr, "%s: failed write to ",
					progname);
				perror("stdout");
				return;
			}
			*size -= rsize;
		}
		return;
	}
	lvl--;
	for (i = 0; i < NINDIR(&sblock); i++) {
		indir(fd, idblk[i], lvl, size);
		if (*size <= 0)
			return;
	}
}

------- =_aaaaaaaaaa0
Content-Type: text/plain; name="icat.man"; charset="us-ascii"
Content-ID: <8192.854204687.4@nemeton.com.au>

ICAT(8)                                                   ICAT(8)

NAME
       icat - cat contents of inode

SYNOPSIS
       icat filesys inumber ...

DESCRIPTION
       Icat  works  like cat except that rather than working with
       file names, it works with (device, inumber)  pairs.   This
       is  particularly useful in looking at files that have been
       unlinked  from  the  file  system  but  are  still   open.
       fstat(8) and lsof(8L) can be used to identify such files.

SEE ALSO
       cat(1), fstat(8), lsof(8L)

WARNING
       Icat  should  only be runnable by the superuser.  Under no
       circumstances should this program be installed  SUID  root
       or  SGID the group that owns the raw disks, because if so,
       file system security can be easily circumvented.


------- =_aaaaaaaaaa0--




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199701251505.CAA08199>