Commit 663f4dec authored by Al Viro's avatar Al Viro
Browse files

[readdir] convert qnx4



... and use strnlen() instead of strlen() - it's done on untrusted data,
after all.

Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent 9fd4d059
Loading
Loading
Loading
Loading
+31 −35
Original line number Diff line number Diff line
@@ -14,9 +14,9 @@
#include <linux/buffer_head.h>
#include "qnx4.h"

static int qnx4_readdir(struct file *filp, void *dirent, filldir_t filldir)
static int qnx4_readdir(struct file *file, struct dir_context *ctx)
{
	struct inode *inode = file_inode(filp);
	struct inode *inode = file_inode(file);
	unsigned int offset;
	struct buffer_head *bh;
	struct qnx4_inode_entry *de;
@@ -26,29 +26,30 @@ static int qnx4_readdir(struct file *filp, void *dirent, filldir_t filldir)
	int size;

	QNX4DEBUG((KERN_INFO "qnx4_readdir:i_size = %ld\n", (long) inode->i_size));
	QNX4DEBUG((KERN_INFO "filp->f_pos         = %ld\n", (long) filp->f_pos));
	QNX4DEBUG((KERN_INFO "pos                 = %ld\n", (long) ctx->pos));

	while (filp->f_pos < inode->i_size) {
		blknum = qnx4_block_map( inode, filp->f_pos >> QNX4_BLOCK_SIZE_BITS );
	while (ctx->pos < inode->i_size) {
		blknum = qnx4_block_map(inode, ctx->pos >> QNX4_BLOCK_SIZE_BITS);
		bh = sb_bread(inode->i_sb, blknum);
		if (bh == NULL) {
			printk(KERN_ERR "qnx4_readdir: bread failed (%ld)\n", blknum);
			break;
			return 0;
		}
		ix = (int)(filp->f_pos >> QNX4_DIR_ENTRY_SIZE_BITS) % QNX4_INODES_PER_BLOCK;
		while (ix < QNX4_INODES_PER_BLOCK) {
		ix = (ctx->pos >> QNX4_DIR_ENTRY_SIZE_BITS) % QNX4_INODES_PER_BLOCK;
		for (; ix < QNX4_INODES_PER_BLOCK; ix++, ctx->pos += QNX4_DIR_ENTRY_SIZE) {
			offset = ix * QNX4_DIR_ENTRY_SIZE;
			de = (struct qnx4_inode_entry *) (bh->b_data + offset);
			size = strlen(de->di_fname);
			if (size) {
				if ( !( de->di_status & QNX4_FILE_LINK ) && size > QNX4_SHORT_NAME_MAX )
			if (!de->di_fname[0])
				continue;
			if (!(de->di_status & (QNX4_FILE_USED|QNX4_FILE_LINK)))
				continue;
			if (!(de->di_status & QNX4_FILE_LINK))
				size = QNX4_SHORT_NAME_MAX;
				else if ( size > QNX4_NAME_MAX )
			else
				size = QNX4_NAME_MAX;

				if ( ( de->di_status & (QNX4_FILE_USED|QNX4_FILE_LINK) ) != 0 ) {
			size = strnlen(de->di_fname, size);
			QNX4DEBUG((KERN_INFO "qnx4_readdir:%.*s\n", size, de->di_fname));
					if ( ( de->di_status & QNX4_FILE_LINK ) == 0 )
			if (!(de->di_status & QNX4_FILE_LINK))
				ino = blknum * QNX4_INODES_PER_BLOCK + ix - 1;
			else {
				le  = (struct qnx4_link_info*)de;
@@ -56,18 +57,13 @@ static int qnx4_readdir(struct file *filp, void *dirent, filldir_t filldir)
					QNX4_INODES_PER_BLOCK +
					le->dl_inode_ndx;
			}
					if (filldir(dirent, de->di_fname, size, filp->f_pos, ino, DT_UNKNOWN) < 0) {
			if (!dir_emit(ctx, de->di_fname, size, ino, DT_UNKNOWN)) {
				brelse(bh);
						goto out;
					}
				}
				return 0;
			}
			ix++;
			filp->f_pos += QNX4_DIR_ENTRY_SIZE;
		}
		brelse(bh);
	}
out:
	return 0;
}

@@ -75,7 +71,7 @@ const struct file_operations qnx4_dir_operations =
{
	.llseek		= generic_file_llseek,
	.read		= generic_read_dir,
	.readdir	= qnx4_readdir,
	.iterate	= qnx4_readdir,
	.fsync		= generic_file_fsync,
};