diff options
Diffstat (limited to 'arch/parisc/hpux/fs.c')
| -rw-r--r-- | arch/parisc/hpux/fs.c | 128 |
1 files changed, 60 insertions, 68 deletions
diff --git a/arch/parisc/hpux/fs.c b/arch/parisc/hpux/fs.c index d7c80edf448..2bedafea3d9 100644 --- a/arch/parisc/hpux/fs.c +++ b/arch/parisc/hpux/fs.c @@ -21,37 +21,21 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#include <linux/kernel.h> #include <linux/mm.h> +#include <linux/fs.h> #include <linux/sched.h> #include <linux/file.h> -#include <linux/smp_lock.h> -#include <linux/slab.h> #include <linux/ptrace.h> +#include <linux/slab.h> #include <asm/errno.h> #include <asm/uaccess.h> int hpux_execve(struct pt_regs *regs) { - int error; - char *filename; - - filename = getname((char *) regs->gr[26]); - error = PTR_ERR(filename); - if (IS_ERR(filename)) - goto out; - - error = do_execve(filename, (char **) regs->gr[25], - (char **)regs->gr[24], regs); - - if (error == 0) { - task_lock(current); - current->ptrace &= ~PT_DTRACE; - task_unlock(current); - } - putname(filename); - -out: - return error; + return do_execve(getname((const char __user *) regs->gr[26]), + (const char __user *const __user *) regs->gr[25], + (const char __user *const __user *) regs->gr[24]); } struct hpux_dirent { @@ -63,73 +47,80 @@ struct hpux_dirent { }; struct getdents_callback { - struct hpux_dirent *current_dir; - struct hpux_dirent *previous; + struct dir_context ctx; + struct hpux_dirent __user *current_dir; + struct hpux_dirent __user *previous; int count; int error; }; -#define NAME_OFFSET(de) ((int) ((de)->d_name - (char *) (de))) -#define ROUND_UP(x) (((x)+sizeof(long)-1) & ~(sizeof(long)-1)) +#define NAME_OFFSET(de) ((int) ((de)->d_name - (char __user *) (de))) static int filldir(void * __buf, const char * name, int namlen, loff_t offset, - ino_t ino, unsigned d_type) + u64 ino, unsigned d_type) { - struct hpux_dirent * dirent; + struct hpux_dirent __user * dirent; struct getdents_callback * buf = (struct getdents_callback *) __buf; - int reclen = ROUND_UP(NAME_OFFSET(dirent) + namlen + 1); + ino_t d_ino; + int reclen = ALIGN(NAME_OFFSET(dirent) + namlen + 1, sizeof(long)); buf->error = -EINVAL; /* only used if we fail.. */ if (reclen > buf->count) return -EINVAL; + d_ino = ino; + if (sizeof(d_ino) < sizeof(ino) && d_ino != ino) { + buf->error = -EOVERFLOW; + return -EOVERFLOW; + } dirent = buf->previous; if (dirent) - put_user(offset, &dirent->d_off); + if (put_user(offset, &dirent->d_off)) + goto Efault; dirent = buf->current_dir; + if (put_user(d_ino, &dirent->d_ino) || + put_user(reclen, &dirent->d_reclen) || + put_user(namlen, &dirent->d_namlen) || + copy_to_user(dirent->d_name, name, namlen) || + put_user(0, dirent->d_name + namlen)) + goto Efault; buf->previous = dirent; - put_user(ino, &dirent->d_ino); - put_user(reclen, &dirent->d_reclen); - put_user(namlen, &dirent->d_namlen); - copy_to_user(dirent->d_name, name, namlen); - put_user(0, dirent->d_name + namlen); - ((char *) dirent) += reclen; - buf->current_dir = dirent; + buf->current_dir = (void __user *)dirent + reclen; buf->count -= reclen; return 0; +Efault: + buf->error = -EFAULT; + return -EFAULT; } #undef NAME_OFFSET -#undef ROUND_UP -int hpux_getdents(unsigned int fd, struct hpux_dirent *dirent, unsigned int count) +int hpux_getdents(unsigned int fd, struct hpux_dirent __user *dirent, unsigned int count) { - struct file * file; - struct hpux_dirent * lastdirent; - struct getdents_callback buf; - int error = -EBADF; - - file = fget(fd); - if (!file) - goto out; - - buf.current_dir = dirent; - buf.previous = NULL; - buf.count = count; - buf.error = 0; - - error = vfs_readdir(file, filldir, &buf); - if (error < 0) - goto out_putf; - error = buf.error; + struct fd arg; + struct hpux_dirent __user * lastdirent; + struct getdents_callback buf = { + .ctx.actor = filldir, + .current_dir = dirent, + .count = count + }; + int error; + + arg = fdget(fd); + if (!arg.file) + return -EBADF; + + error = iterate_dir(arg.file, &buf.ctx); + if (error >= 0) + error = buf.error; lastdirent = buf.previous; if (lastdirent) { - put_user(file->f_pos, &lastdirent->d_off); - error = count - buf.count; + if (put_user(buf.ctx.pos, &lastdirent->d_off)) + error = -EFAULT; + else + error = count - buf.count; } -out_putf: - fput(file); -out: + fdput(arg); return error; } @@ -139,7 +130,7 @@ int hpux_mount(const char *fs, const char *path, int mflag, return -ENOSYS; } -static int cp_hpux_stat(struct kstat *stat, struct hpux_stat64 *statbuf) +static int cp_hpux_stat(struct kstat *stat, struct hpux_stat64 __user *statbuf) { struct hpux_stat64 tmp; @@ -153,8 +144,8 @@ static int cp_hpux_stat(struct kstat *stat, struct hpux_stat64 *statbuf) tmp.st_ino = stat->ino; tmp.st_mode = stat->mode; tmp.st_nlink = stat->nlink; - tmp.st_uid = stat->uid; - tmp.st_gid = stat->gid; + tmp.st_uid = from_kuid_munged(current_user_ns(), stat->uid); + tmp.st_gid = from_kgid_munged(current_user_ns(), stat->gid); tmp.st_rdev = new_encode_dev(stat->rdev); tmp.st_size = stat->size; tmp.st_atime = stat->atime.tv_sec; @@ -165,7 +156,7 @@ static int cp_hpux_stat(struct kstat *stat, struct hpux_stat64 *statbuf) return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0; } -long hpux_stat64(char *filename, struct hpux_stat64 *statbuf) +long hpux_stat64(const char __user *filename, struct hpux_stat64 __user *statbuf) { struct kstat stat; int error = vfs_stat(filename, &stat); @@ -176,7 +167,7 @@ long hpux_stat64(char *filename, struct hpux_stat64 *statbuf) return error; } -long hpux_fstat64(unsigned int fd, struct hpux_stat64 *statbuf) +long hpux_fstat64(unsigned int fd, struct hpux_stat64 __user *statbuf) { struct kstat stat; int error = vfs_fstat(fd, &stat); @@ -187,7 +178,8 @@ long hpux_fstat64(unsigned int fd, struct hpux_stat64 *statbuf) return error; } -long hpux_lstat64(char *filename, struct hpux_stat64 *statbuf) +long hpux_lstat64(const char __user *filename, + struct hpux_stat64 __user *statbuf) { struct kstat stat; int error = vfs_lstat(filename, &stat); |
