diff options
Diffstat (limited to 'fs/compat.c')
-rw-r--r-- | fs/compat.c | 97 |
1 files changed, 35 insertions, 62 deletions
diff --git a/fs/compat.c b/fs/compat.c index 6490d2134ff3..ff66c0d7583d 100644 --- a/fs/compat.c +++ b/fs/compat.c @@ -8,13 +8,14 @@ * Copyright (C) 1997-2000 Jakub Jelinek (jakub@redhat.com) * Copyright (C) 1998 Eddie C. Dost (ecd@skynet.be) * Copyright (C) 2001,2002 Andi Kleen, SuSE Labs - * Copyright (C) 2003 Pavel Machek (pavel@suse.cz) + * Copyright (C) 2003 Pavel Machek (pavel@ucw.cz) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ +#include <linux/stddef.h> #include <linux/kernel.h> #include <linux/linkage.h> #include <linux/compat.h> @@ -28,8 +29,6 @@ #include <linux/vfs.h> #include <linux/ioctl.h> #include <linux/init.h> -#include <linux/smb.h> -#include <linux/smb_mount.h> #include <linux/ncp_mount.h> #include <linux/nfs4_mount.h> #include <linux/syscalls.h> @@ -76,7 +75,8 @@ int compat_printk(const char *fmt, ...) * Not all architectures have sys_utime, so implement this in terms * of sys_utimes. */ -asmlinkage long compat_sys_utime(char __user *filename, struct compat_utimbuf __user *t) +asmlinkage long compat_sys_utime(const char __user *filename, + struct compat_utimbuf __user *t) { struct timespec tv[2]; @@ -90,7 +90,7 @@ asmlinkage long compat_sys_utime(char __user *filename, struct compat_utimbuf __ return do_utimes(AT_FDCWD, filename, t ? tv : NULL, 0); } -asmlinkage long compat_sys_utimensat(unsigned int dfd, char __user *filename, struct compat_timespec __user *t, int flags) +asmlinkage long compat_sys_utimensat(unsigned int dfd, const char __user *filename, struct compat_timespec __user *t, int flags) { struct timespec tv[2]; @@ -105,7 +105,7 @@ asmlinkage long compat_sys_utimensat(unsigned int dfd, char __user *filename, st return do_utimes(dfd, filename, t ? tv : NULL, flags); } -asmlinkage long compat_sys_futimesat(unsigned int dfd, char __user *filename, struct compat_timeval __user *t) +asmlinkage long compat_sys_futimesat(unsigned int dfd, const char __user *filename, struct compat_timeval __user *t) { struct timespec tv[2]; @@ -124,7 +124,7 @@ asmlinkage long compat_sys_futimesat(unsigned int dfd, char __user *filename, st return do_utimes(dfd, filename, t ? tv : NULL, 0); } -asmlinkage long compat_sys_utimes(char __user *filename, struct compat_timeval __user *t) +asmlinkage long compat_sys_utimes(const char __user *filename, struct compat_timeval __user *t) { return compat_sys_futimesat(AT_FDCWD, filename, t); } @@ -168,7 +168,7 @@ static int cp_compat_stat(struct kstat *stat, struct compat_stat __user *ubuf) return err; } -asmlinkage long compat_sys_newstat(char __user * filename, +asmlinkage long compat_sys_newstat(const char __user * filename, struct compat_stat __user *statbuf) { struct kstat stat; @@ -180,7 +180,7 @@ asmlinkage long compat_sys_newstat(char __user * filename, return cp_compat_stat(&stat, statbuf); } -asmlinkage long compat_sys_newlstat(char __user * filename, +asmlinkage long compat_sys_newlstat(const char __user * filename, struct compat_stat __user *statbuf) { struct kstat stat; @@ -193,7 +193,8 @@ asmlinkage long compat_sys_newlstat(char __user * filename, } #ifndef __ARCH_WANT_STAT64 -asmlinkage long compat_sys_newfstatat(unsigned int dfd, char __user *filename, +asmlinkage long compat_sys_newfstatat(unsigned int dfd, + const char __user *filename, struct compat_stat __user *statbuf, int flag) { struct kstat stat; @@ -266,7 +267,7 @@ asmlinkage long compat_sys_statfs(const char __user *pathname, struct compat_sta error = user_path(pathname, &path); if (!error) { struct kstatfs tmp; - error = vfs_statfs(path.dentry, &tmp); + error = vfs_statfs(&path, &tmp); if (!error) error = put_compat_statfs(buf, &tmp); path_put(&path); @@ -284,7 +285,7 @@ asmlinkage long compat_sys_fstatfs(unsigned int fd, struct compat_statfs __user file = fget(fd); if (!file) goto out; - error = vfs_statfs(file->f_path.dentry, &tmp); + error = vfs_statfs(&file->f_path, &tmp); if (!error) error = put_compat_statfs(buf, &tmp); fput(file); @@ -334,7 +335,7 @@ asmlinkage long compat_sys_statfs64(const char __user *pathname, compat_size_t s error = user_path(pathname, &path); if (!error) { struct kstatfs tmp; - error = vfs_statfs(path.dentry, &tmp); + error = vfs_statfs(&path, &tmp); if (!error) error = put_compat_statfs64(buf, &tmp); path_put(&path); @@ -355,7 +356,7 @@ asmlinkage long compat_sys_fstatfs64(unsigned int fd, compat_size_t sz, struct c file = fget(fd); if (!file) goto out; - error = vfs_statfs(file->f_path.dentry, &tmp); + error = vfs_statfs(&file->f_path, &tmp); if (!error) error = put_compat_statfs64(buf, &tmp); fput(file); @@ -378,7 +379,7 @@ asmlinkage long compat_sys_ustat(unsigned dev, struct compat_ustat __user *u) sb = user_get_super(new_decode_dev(dev)); if (!sb) return -EINVAL; - err = vfs_statfs(sb->s_root, &sbuf); + err = statfs_by_dentry(sb->s_root, &sbuf); drop_super(sb); if (err) return err; @@ -605,14 +606,14 @@ ssize_t compat_rw_copy_check_uvector(int type, /* * Single unix specification: * We should -EINVAL if an element length is not >= 0 and fitting an - * ssize_t. The total length is fitting an ssize_t + * ssize_t. * - * Be careful here because iov_len is a size_t not an ssize_t + * In Linux, the total length is limited to MAX_RW_COUNT, there is + * no overflow possibility. */ tot_len = 0; ret = -EINVAL; for (seg = 0; seg < nr_segs; seg++) { - compat_ssize_t tmp = tot_len; compat_uptr_t buf; compat_ssize_t len; @@ -623,13 +624,13 @@ ssize_t compat_rw_copy_check_uvector(int type, } if (len < 0) /* size_t not fitting in compat_ssize_t .. */ goto out; - tot_len += len; - if (tot_len < tmp) /* maths overflow on the compat_ssize_t */ - goto out; if (!access_ok(vrfy_dir(type), compat_ptr(buf), len)) { ret = -EFAULT; goto out; } + if (len > MAX_RW_COUNT - tot_len) + len = MAX_RW_COUNT - tot_len; + tot_len += len; iov->iov_base = compat_ptr(buf); iov->iov_len = (compat_size_t) len; uvector++; @@ -742,30 +743,6 @@ static void *do_ncp_super_data_conv(void *raw_data) return raw_data; } -struct compat_smb_mount_data { - compat_int_t version; - __compat_uid_t mounted_uid; - __compat_uid_t uid; - __compat_gid_t gid; - compat_mode_t file_mode; - compat_mode_t dir_mode; -}; - -static void *do_smb_super_data_conv(void *raw_data) -{ - struct smb_mount_data *s = raw_data; - struct compat_smb_mount_data *c_s = raw_data; - - if (c_s->version != SMB_MOUNT_OLDVERSION) - goto out; - s->dir_mode = c_s->dir_mode; - s->file_mode = c_s->file_mode; - s->gid = c_s->gid; - s->uid = c_s->uid; - s->mounted_uid = c_s->mounted_uid; - out: - return raw_data; -} struct compat_nfs_string { compat_uint_t len; @@ -832,13 +809,13 @@ static int do_nfs4_super_data_conv(void *raw_data) return 0; } -#define SMBFS_NAME "smbfs" #define NCPFS_NAME "ncpfs" #define NFS4_NAME "nfs4" -asmlinkage long compat_sys_mount(char __user * dev_name, char __user * dir_name, - char __user * type, unsigned long flags, - void __user * data) +asmlinkage long compat_sys_mount(const char __user * dev_name, + const char __user * dir_name, + const char __user * type, unsigned long flags, + const void __user * data) { char *kernel_type; unsigned long data_page; @@ -866,9 +843,7 @@ asmlinkage long compat_sys_mount(char __user * dev_name, char __user * dir_name, retval = -EINVAL; if (kernel_type && data_page) { - if (!strcmp(kernel_type, SMBFS_NAME)) { - do_smb_super_data_conv((void *)data_page); - } else if (!strcmp(kernel_type, NCPFS_NAME)) { + if (!strcmp(kernel_type, NCPFS_NAME)) { do_ncp_super_data_conv((void *)data_page); } else if (!strcmp(kernel_type, NFS4_NAME)) { if (do_nfs4_super_data_conv((void *) data_page)) @@ -891,8 +866,6 @@ asmlinkage long compat_sys_mount(char __user * dev_name, char __user * dir_name, return retval; } -#define NAME_OFFSET(de) ((int) ((de)->d_name - (char __user *) (de))) - struct compat_old_linux_dirent { compat_ulong_t d_ino; compat_ulong_t d_offset; @@ -981,7 +954,8 @@ static int compat_filldir(void *__buf, const char *name, int namlen, struct compat_linux_dirent __user * dirent; struct compat_getdents_callback *buf = __buf; compat_ulong_t d_ino; - int reclen = ALIGN(NAME_OFFSET(dirent) + namlen + 2, sizeof(compat_long_t)); + int reclen = ALIGN(offsetof(struct compat_linux_dirent, d_name) + + namlen + 2, sizeof(compat_long_t)); buf->error = -EINVAL; /* only used if we fail.. */ if (reclen > buf->count) @@ -1068,8 +1042,8 @@ static int compat_filldir64(void * __buf, const char * name, int namlen, loff_t { struct linux_dirent64 __user *dirent; struct compat_getdents_callback64 *buf = __buf; - int jj = NAME_OFFSET(dirent); - int reclen = ALIGN(jj + namlen + 1, sizeof(u64)); + int reclen = ALIGN(offsetof(struct linux_dirent64, d_name) + namlen + 1, + sizeof(u64)); u64 off; buf->error = -EINVAL; /* only used if we fail.. */ @@ -1150,7 +1124,7 @@ static ssize_t compat_do_readv_writev(int type, struct file *file, { compat_ssize_t tot_len; struct iovec iovstack[UIO_FASTIOV]; - struct iovec *iov; + struct iovec *iov = iovstack; ssize_t ret; io_fn_t fn; iov_fn_t fnv; @@ -1193,11 +1167,10 @@ out: if (iov != iovstack) kfree(iov); if ((ret + (type == READ)) > 0) { - struct dentry *dentry = file->f_path.dentry; if (type == READ) - fsnotify_access(dentry); + fsnotify_access(file); else - fsnotify_modify(dentry); + fsnotify_modify(file); } return ret; } @@ -1961,7 +1934,7 @@ asmlinkage long compat_sys_ppoll(struct pollfd __user *ufds, } #endif /* HAVE_SET_RESTORE_SIGMASK */ -#if defined(CONFIG_NFSD) || defined(CONFIG_NFSD_MODULE) +#if (defined(CONFIG_NFSD) || defined(CONFIG_NFSD_MODULE)) && !defined(CONFIG_NFSD_DEPRECATED) /* Stuff for NFS server syscalls... */ struct compat_nfsctl_svc { u16 svc32_port; |