diff options
Diffstat (limited to 'arch/mips/kernel/sysirix.c')
-rw-r--r-- | arch/mips/kernel/sysirix.c | 287 |
1 files changed, 184 insertions, 103 deletions
diff --git a/arch/mips/kernel/sysirix.c b/arch/mips/kernel/sysirix.c index 95a0dc1c6..e87e5084b 100644 --- a/arch/mips/kernel/sysirix.c +++ b/arch/mips/kernel/sysirix.c @@ -1,4 +1,4 @@ -/* $Id: sysirix.c,v 1.14 1996/07/14 01:59:51 dm Exp $ +/* $Id: sysirix.c,v 1.4 1997/07/19 19:03:18 root Exp $ * sysirix.c: IRIX system call emulation. * * Copyright (C) 1996 David S. Miller @@ -652,6 +652,7 @@ struct irix_statfs { asmlinkage int irix_statfs(const char *path, struct irix_statfs *buf, int len, int fs_type) { + struct dentry *dentry; struct inode *inode; struct statfs kbuf; int error, old_fs, i; @@ -664,20 +665,19 @@ asmlinkage int irix_statfs(const char *path, struct irix_statfs *buf, error = verify_area(VERIFY_WRITE, buf, sizeof(struct irix_statfs)); if (error) goto out; - error = namei(NAM_FOLLOW_LINK, path, &inode); - if (error) - goto out; - if (!inode->i_sb->s_op->statfs) { - iput(inode); - error = -ENOSYS; + dentry = namei(path); + error = PTR_ERR(dentry); + if (IS_ERR(dentry)) goto out; - } + inode = dentry->d_inode; old_fs = get_fs(); set_fs(get_ds()); - inode->i_sb->s_op->statfs(inode->i_sb, &kbuf, sizeof(struct statfs)); + error = inode->i_sb->s_op->statfs(inode->i_sb, &kbuf, + sizeof(struct statfs)); set_fs(old_fs); + if (error) + goto dput_and_out; - iput(inode); __put_user(kbuf.f_type, &buf->f_type); __put_user(kbuf.f_bsize, &buf->f_bsize); __put_user(kbuf.f_frsize, &buf->f_frsize); @@ -691,6 +691,8 @@ asmlinkage int irix_statfs(const char *path, struct irix_statfs *buf, } error = 0; +dput_and_out: + dput(dentry); out: unlock_kernel(); return error; @@ -698,7 +700,8 @@ out: asmlinkage int irix_fstatfs(unsigned int fd, struct irix_statfs *buf) { - struct inode * inode; + struct dentry *dentry; + struct inode *inode; struct statfs kbuf; struct file *file; int error, old_fs, i; @@ -711,18 +714,29 @@ asmlinkage int irix_fstatfs(unsigned int fd, struct irix_statfs *buf) error = -EBADF; goto out; } - if (!(inode = file->f_inode)) { + if (!(dentry = file->f_dentry)) { + error = -ENOENT; + goto out; + } + if (!(inode = dentry->d_inode)) { error = -ENOENT; goto out; } + if (!inode->i_sb) { + error = -ENODEV; + goto out; + } if (!inode->i_sb->s_op->statfs) { error = -ENOSYS; goto out; } old_fs = get_fs(); set_fs(get_ds()); - inode->i_sb->s_op->statfs(inode->i_sb, &kbuf, sizeof(struct statfs)); + error = inode->i_sb->s_op->statfs(inode->i_sb, &kbuf, + sizeof(struct statfs)); set_fs(old_fs); + if (error) + goto out; __put_user(kbuf.f_type, &buf->f_type); __put_user(kbuf.f_bsize, &buf->f_bsize); @@ -789,13 +803,14 @@ out: asmlinkage int irix_exec(struct pt_regs *regs) { int error, base = 0; - char * filename; + char *filename; lock_kernel(); if(regs->regs[2] == 1000) base = 1; - error = getname((char *) (long)regs->regs[base + 4], &filename); - if (error) + filename = getname((char *) (long)regs->regs[base + 4]); + error = PTR_ERR(filename); + if (IS_ERR(filename)) goto out; error = do_execve(filename, (char **) (long)regs->regs[base + 5], (char **) 0, regs); @@ -809,13 +824,14 @@ out: asmlinkage int irix_exece(struct pt_regs *regs) { int error, base = 0; - char * filename; + char *filename; lock_kernel(); if(regs->regs[2] == 1000) base = 1; - error = getname((char *) (long)regs->regs[base + 4], &filename); - if (error) + filename = getname((char *) (long)regs->regs[base + 4]); + error = PTR_ERR(filename); + if (IS_ERR(filename)) goto out; error = do_execve(filename, (char **) (long)regs->regs[base + 5], (char **) (long)regs->regs[base + 6], regs); @@ -1380,6 +1396,7 @@ struct irix_statvfs { asmlinkage int irix_statvfs(char *fname, struct irix_statvfs *buf) { + struct dentry *dentry; struct inode *inode; struct statfs kbuf; int error, old_fs, i; @@ -1390,20 +1407,23 @@ asmlinkage int irix_statvfs(char *fname, struct irix_statvfs *buf) error = verify_area(VERIFY_WRITE, buf, sizeof(struct irix_statvfs)); if(error) goto out; - error = namei(NAM_FOLLOW_LINK, fname, &inode); - if(error) - goto out; - if(!inode->i_sb->s_op->statfs) { - iput(inode); - error = -ENOSYS; + dentry = namei(fname); + error = PTR_ERR(dentry); + if(!IS_ERR(dentry)) goto out; - } + inode = dentry->d_inode; + + error = -ENOSYS; + if(!inode->i_sb->s_op->statfs) + goto dput_and_out; old_fs = get_fs(); set_fs(get_ds()); - inode->i_sb->s_op->statfs(inode->i_sb, &kbuf, sizeof(struct statfs)); + error = inode->i_sb->s_op->statfs(inode->i_sb, &kbuf, + sizeof(struct statfs)); set_fs(old_fs); + if (error) + goto dput_and_out; - iput(inode); __put_user(kbuf.f_bsize, &buf->f_bsize); __put_user(kbuf.f_frsize, &buf->f_frsize); __put_user(kbuf.f_blocks, &buf->f_blocks); @@ -1426,6 +1446,8 @@ asmlinkage int irix_statvfs(char *fname, struct irix_statvfs *buf) error = 0; +dput_and_out: + dput(dentry); out: unlock_kernel(); return error; @@ -1433,7 +1455,8 @@ out: asmlinkage int irix_fstatvfs(int fd, struct irix_statvfs *buf) { - struct inode * inode; + struct dentry *dentry; + struct inode *inode; struct statfs kbuf; struct file *file; int error, old_fs, i; @@ -1449,7 +1472,11 @@ asmlinkage int irix_fstatvfs(int fd, struct irix_statvfs *buf) error = -EBADF; goto out; } - if (!(inode = file->f_inode)) { + if (!(dentry = file->f_dentry)) { + error = -ENOENT; + goto out; + } + if (!(inode = dentry->d_inode)) { error = -ENOENT; goto out; } @@ -1459,8 +1486,11 @@ asmlinkage int irix_fstatvfs(int fd, struct irix_statvfs *buf) } old_fs = get_fs(); set_fs(get_ds()); - inode->i_sb->s_op->statfs(inode->i_sb, &kbuf, sizeof(struct statfs)); + error = inode->i_sb->s_op->statfs(inode->i_sb, &kbuf, + sizeof(struct statfs)); set_fs(old_fs); + if (error) + goto out; __put_user(kbuf.f_bsize, &buf->f_bsize); __put_user(kbuf.f_frsize, &buf->f_frsize); @@ -1489,26 +1519,28 @@ out: return error; } -#define NOFOLLOW_LINKS NAM_FOLLOW_TRAILSLASH -#define FOLLOW_LINKS NAM_FOLLOW_LINK +#define NOFOLLOW_LINKS 0 +#define FOLLOW_LINKS 1 -static inline int chown_common(char *filename, uid_t user, gid_t group, int follow) +static inline int chown_common(uid_t user, gid_t group, struct dentry *dentry) { struct inode * inode; int error; struct iattr newattrs; - error = namei(follow, filename,&inode); - if (error) - return error; - if (IS_RDONLY(inode)) { - iput(inode); - return -EROFS; - } - if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) { - iput(inode); - return -EPERM; - } + error = PTR_ERR(dentry); + if (IS_ERR(dentry)) + goto out; + inode = dentry->d_inode; + + error = -EROFS; + if (IS_RDONLY(inode)) + goto dput_and_out; + + error = -EPERM; + if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) + goto dput_and_out; + if (user == (uid_t) -1) user = inode->i_uid; if (group == (gid_t) -1) @@ -1534,38 +1566,45 @@ static inline int chown_common(char *filename, uid_t user, gid_t group, int foll newattrs.ia_mode &= ~S_ISGID; newattrs.ia_valid |= ATTR_MODE; } - inode->i_dirt = 1; if (inode->i_sb->dq_op) { inode->i_sb->dq_op->initialize(inode, -1); + error = -EDQUOT; if (inode->i_sb->dq_op->transfer(inode, &newattrs, 0)) - return -EDQUOT; + goto dput_and_out; error = notify_change(inode, &newattrs); if (error) inode->i_sb->dq_op->transfer(inode, &newattrs, 1); } else error = notify_change(inode, &newattrs); - iput(inode); - return(error); + +dput_and_out: + dput(dentry); +out: + return error; } -asmlinkage int irix_chown(char *fname, int uid, int gid) +asmlinkage int irix_chown(const char *filename, int uid, int gid) { int retval; + struct dentry *dentry; lock_kernel(); /* Do follow any and all links... */ - retval = chown_common(fname, uid, gid, FOLLOW_LINKS); + dentry = namei(filename); + retval = chown_common(uid, gid, dentry); unlock_kernel(); return retval; } -asmlinkage int irix_lchown(char *fname, int uid, int gid) +asmlinkage int irix_lchown(const char *filename, int uid, int gid) { int retval; + struct dentry *dentry; lock_kernel(); /* Do _not_ follow any links... */ - retval = chown_common(fname, uid, gid, NOFOLLOW_LINKS); + dentry = lnamei(filename); + retval = chown_common(uid, gid, dentry); unlock_kernel(); return retval; } @@ -1722,6 +1761,7 @@ struct irix_statvfs64 { asmlinkage int irix_statvfs64(char *fname, struct irix_statvfs64 *buf) { + struct dentry *dentry; struct inode *inode; struct statfs kbuf; int error, old_fs, i; @@ -1731,20 +1771,22 @@ asmlinkage int irix_statvfs64(char *fname, struct irix_statvfs64 *buf) error = verify_area(VERIFY_WRITE, buf, sizeof(struct irix_statvfs)); if(error) goto out; - error = namei(NAM_FOLLOW_LINK, fname, &inode); - if(error) - goto out; - if(!inode->i_sb->s_op->statfs) { - iput(inode); - error = -ENOSYS; + dentry = namei(fname); + error = PTR_ERR(dentry); + if(IS_ERR(dentry)) goto out; - } + error = -ENOSYS; + inode = dentry->d_inode; + if(!inode->i_sb->s_op->statfs) + goto dput_and_out; old_fs = get_fs(); set_fs(get_ds()); - inode->i_sb->s_op->statfs(inode->i_sb, &kbuf, sizeof(struct statfs)); + error = inode->i_sb->s_op->statfs(inode->i_sb, &kbuf, + sizeof(struct statfs)); set_fs(old_fs); + if (error) + goto dput_and_out; - iput(inode); __put_user(kbuf.f_bsize, &buf->f_bsize); __put_user(kbuf.f_frsize, &buf->f_frsize); __put_user(kbuf.f_blocks, &buf->f_blocks); @@ -1767,6 +1809,8 @@ asmlinkage int irix_statvfs64(char *fname, struct irix_statvfs64 *buf) error = 0; +dput_and_out: + dput(dentry); out: unlock_kernel(); return error; @@ -1774,7 +1818,8 @@ out: asmlinkage int irix_fstatvfs64(int fd, struct irix_statvfs *buf) { - struct inode * inode; + struct dentry *dentry; + struct inode *inode; struct statfs kbuf; struct file *file; int error, old_fs, i; @@ -1790,7 +1835,11 @@ asmlinkage int irix_fstatvfs64(int fd, struct irix_statvfs *buf) error = -EBADF; goto out; } - if (!(inode = file->f_inode)) { + if (!(dentry = file->f_dentry)) { + error = -ENOENT; + goto out; + } + if (!(inode = dentry->d_inode)) { error = -ENOENT; goto out; } @@ -1800,8 +1849,11 @@ asmlinkage int irix_fstatvfs64(int fd, struct irix_statvfs *buf) } old_fs = get_fs(); set_fs(get_ds()); - inode->i_sb->s_op->statfs(inode->i_sb, &kbuf, sizeof(struct statfs)); + error = inode->i_sb->s_op->statfs(inode->i_sb, &kbuf, + sizeof(struct statfs)); set_fs(old_fs); + if (error) + goto out; __put_user(kbuf.f_bsize, &buf->f_bsize); __put_user(kbuf.f_frsize, &buf->f_frsize); @@ -1927,6 +1979,8 @@ out: asmlinkage int irix_ngetdents(unsigned int fd, void * dirent, unsigned int count, int *eob) { struct file *file; + struct dentry *dentry; + struct inode *inode; struct irix_dirent32 *lastdirent; struct irix_dirent32_callback buf; int error; @@ -1936,25 +1990,34 @@ asmlinkage int irix_ngetdents(unsigned int fd, void * dirent, unsigned int count printk("[%s:%d] ngetdents(%d, %p, %d, %p) ", current->comm, current->pid, fd, dirent, count, eob); #endif - if (fd >= NR_OPEN || !(file = current->files->fd[fd])) { - error = -EBADF; + error = -EBADF; + if (fd >= NR_OPEN || !(file = current->files->fd[fd])) goto out; - } - if (!file->f_op || !file->f_op->readdir) { - error = -ENOTDIR; + + dentry = file->f_dentry; + if (!dentry) goto out; - } - if(verify_area(VERIFY_WRITE, dirent, count) || - verify_area(VERIFY_WRITE, eob, sizeof(*eob))) { - error = -EFAULT; + + inode = dentry->d_inode; + if (!inode) goto out; - } + + error = -ENOTDIR; + if (!file->f_op || !file->f_op->readdir) + goto out; + + error = -EFAULT; + if(!access_ok(VERIFY_WRITE, dirent, count) || + !access_ok(VERIFY_WRITE, eob, sizeof(*eob))) + goto out; + __put_user(0, eob); buf.current_dir = (struct irix_dirent32 *) dirent; buf.previous = NULL; buf.count = count; buf.error = 0; - error = file->f_op->readdir(file->f_inode, file, &buf, irix_filldir32); + + error = file->f_op->readdir(inode, file, &buf, irix_filldir32); if (error < 0) goto out; lastdirent = buf.previous; @@ -2027,6 +2090,8 @@ out: asmlinkage int irix_getdents64(int fd, void *dirent, int cnt) { struct file *file; + struct dentry *dentry; + struct inode *inode; struct irix_dirent64 *lastdirent; struct irix_dirent64_callback buf; int error; @@ -2036,28 +2101,35 @@ asmlinkage int irix_getdents64(int fd, void *dirent, int cnt) printk("[%s:%d] getdents64(%d, %p, %d) ", current->comm, current->pid, fd, dirent, cnt); #endif - if (fd >= NR_OPEN || !(file = current->files->fd[fd])) { - error = -EBADF; + error = -EBADF; + if (fd >= NR_OPEN || !(file = current->files->fd[fd])) goto out; - } - if (!file->f_op || !file->f_op->readdir) { - error = -ENOTDIR; + + dentry = file->f_dentry; + if (!dentry) goto out; - } - if(verify_area(VERIFY_WRITE, dirent, cnt)) { - error = -EFAULT; + + inode = dentry->d_inode; + if (!inode) goto out; - } - if(cnt < (sizeof(struct irix_dirent64) + 255)) { - error = -EINVAL; + + error = -ENOTDIR; + if (!file->f_op || !file->f_op->readdir) + goto out; + + error = -EFAULT; + if(!access_ok(VERIFY_WRITE, dirent, cnt)) + goto out; + + error = -EINVAL; + if(cnt < (sizeof(struct irix_dirent64) + 255)) goto out; - } buf.curr = (struct irix_dirent64 *) dirent; buf.previous = NULL; buf.count = cnt; buf.error = 0; - error = file->f_op->readdir(file->f_inode, file, &buf, irix_filldir64); + error = file->f_op->readdir(inode, file, &buf, irix_filldir64); if (error < 0) goto out; lastdirent = buf.previous; @@ -2079,6 +2151,8 @@ out: asmlinkage int irix_ngetdents64(int fd, void *dirent, int cnt, int *eob) { struct file *file; + struct dentry *dentry; + struct inode *inode; struct irix_dirent64 *lastdirent; struct irix_dirent64_callback buf; int error; @@ -2088,30 +2162,37 @@ asmlinkage int irix_ngetdents64(int fd, void *dirent, int cnt, int *eob) printk("[%s:%d] ngetdents64(%d, %p, %d) ", current->comm, current->pid, fd, dirent, cnt); #endif - if (fd >= NR_OPEN || !(file = current->files->fd[fd])) { - error = -EBADF; + error = -EBADF; + if (fd >= NR_OPEN || !(file = current->files->fd[fd])) goto out; - } - if (!file->f_op || !file->f_op->readdir) { - error = -ENOTDIR; + + dentry = file->f_dentry; + if (!dentry) goto out; - } - if(verify_area(VERIFY_WRITE, dirent, cnt) || - verify_area(VERIFY_WRITE, eob, sizeof(*eob))) { - error = -EFAULT; + + inode = dentry->d_inode; + if (!inode) goto out; - } - if(cnt < (sizeof(struct irix_dirent64) + 255)) { - error = -EINVAL; + + error = -ENOTDIR; + if (!file->f_op || !file->f_op->readdir) + goto out; + + error = -EFAULT; + if(!access_ok(VERIFY_WRITE, dirent, cnt) || + !access_ok(VERIFY_WRITE, eob, sizeof(*eob))) + goto out; + + error = -EINVAL; + if(cnt < (sizeof(struct irix_dirent64) + 255)) goto out; - } *eob = 0; buf.curr = (struct irix_dirent64 *) dirent; buf.previous = NULL; buf.count = cnt; buf.error = 0; - error = file->f_op->readdir(file->f_inode, file, &buf, irix_filldir64); + error = file->f_op->readdir(inode, file, &buf, irix_filldir64); if (error < 0) goto out; lastdirent = buf.previous; |