--- linux-2.4.21/fs/nfs/inode.c.orig 2004-06-09 12:52:29.000000000 -0400 +++ linux-2.4.21/fs/nfs/inode.c 2004-06-16 21:14:37.000000000 -0400 @@ -593,6 +593,7 @@ out_fail: return NULL; } +#define TOOBIG(_arg) ((_arg) > LONG_MAX) static int nfs_statfs(struct super_block *sb, struct statfs *buf) { @@ -605,24 +606,44 @@ nfs_statfs(struct super_block *sb, struc error = server->rpc_ops->statfs(server, NFS_FH(sb->s_root->d_inode), &res); buf->f_type = NFS_SUPER_MAGIC; - if (error < 0) + if (error < 0) { + printk("nfs_statfs: statfs error = %d\n", -error); goto out_err; + } buf->f_bsize = sb->s_blocksize; blockbits = sb->s_blocksize_bits; blockres = (1 << blockbits) - 1; + buf->f_namelen = server->namelen; + + /* + * Make sure things fit + */ + if (TOOBIG(((res.tbytes + blockres) >> blockbits))) + goto too_big; + if (TOOBIG(((res.fbytes + blockres) >> blockbits))) + goto too_big; + if (TOOBIG(((res.abytes + blockres) >> blockbits))) + goto too_big; + if (TOOBIG(res.tfiles) || TOOBIG(res.afiles)) + goto too_big; + buf->f_blocks = (res.tbytes + blockres) >> blockbits; buf->f_bfree = (res.fbytes + blockres) >> blockbits; buf->f_bavail = (res.abytes + blockres) >> blockbits; buf->f_files = res.tfiles; buf->f_ffree = res.afiles; - buf->f_namelen = server->namelen; return 0; + + too_big: + dprintk("nfs_statfs: failed: EOVERFLOW\n"); + buf->f_files = buf->f_ffree = -1; + out_err: - printk("nfs_statfs: statfs error = %d\n", -error); buf->f_bsize = buf->f_blocks = buf->f_bfree = buf->f_bavail = -1; return 0; } +#undef TOOBIG static int nfs_show_options(struct seq_file *m, struct vfsmount *mnt) {