X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=fs%2Fcompat.c;h=2eb03c49b07ce226cda102c5c25b0dd8884b1afd;hb=9317259ead88fe6c05120ae1e3ace99738e2c698;hp=a912bdf691cfca03e07eba1b5753d58779dabf66;hpb=1da177e4c3f41524e886b7f1b8a0c1fc7321cac2;p=linux-2.6 diff --git a/fs/compat.c b/fs/compat.c index a912bdf691..2eb03c49b0 100644 --- a/fs/compat.c +++ b/fs/compat.c @@ -31,12 +31,13 @@ #include #include #include +#include #include #include #include #include #include -#include +#include #include #include #include @@ -309,96 +310,6 @@ static int __init init_sys32_ioctl(void) __initcall(init_sys32_ioctl); -int register_ioctl32_conversion(unsigned int cmd, - ioctl_trans_handler_t handler) -{ - struct ioctl_trans *t; - struct ioctl_trans *new_t; - unsigned long hash = ioctl32_hash(cmd); - - new_t = kmalloc(sizeof(*new_t), GFP_KERNEL); - if (!new_t) - return -ENOMEM; - - down_write(&ioctl32_sem); - for (t = ioctl32_hash_table[hash]; t; t = t->next) { - if (t->cmd == cmd) { - printk(KERN_ERR "Trying to register duplicated ioctl32 " - "handler %x\n", cmd); - up_write(&ioctl32_sem); - kfree(new_t); - return -EINVAL; - } - } - new_t->next = NULL; - new_t->cmd = cmd; - new_t->handler = handler; - ioctl32_insert_translation(new_t); - - up_write(&ioctl32_sem); - return 0; -} -EXPORT_SYMBOL(register_ioctl32_conversion); - -static inline int builtin_ioctl(struct ioctl_trans *t) -{ - return t >= ioctl_start && t < (ioctl_start + ioctl_table_size); -} - -/* Problem: - This function cannot unregister duplicate ioctls, because they are not - unique. - When they happen we need to extend the prototype to pass the handler too. */ - -int unregister_ioctl32_conversion(unsigned int cmd) -{ - unsigned long hash = ioctl32_hash(cmd); - struct ioctl_trans *t, *t1; - - down_write(&ioctl32_sem); - - t = ioctl32_hash_table[hash]; - if (!t) { - up_write(&ioctl32_sem); - return -EINVAL; - } - - if (t->cmd == cmd) { - if (builtin_ioctl(t)) { - printk("%p tried to unregister builtin ioctl %x\n", - __builtin_return_address(0), cmd); - } else { - ioctl32_hash_table[hash] = t->next; - up_write(&ioctl32_sem); - kfree(t); - return 0; - } - } - while (t->next) { - t1 = t->next; - if (t1->cmd == cmd) { - if (builtin_ioctl(t1)) { - printk("%p tried to unregister builtin " - "ioctl %x\n", - __builtin_return_address(0), cmd); - goto out; - } else { - t->next = t1->next; - up_write(&ioctl32_sem); - kfree(t1); - return 0; - } - } - t = t1; - } - printk(KERN_ERR "Trying to free unknown 32bit ioctl handler %x\n", - cmd); -out: - up_write(&ioctl32_sem); - return -EINVAL; -} -EXPORT_SYMBOL(unregister_ioctl32_conversion); - static void compat_ioctl_error(struct file *filp, unsigned int fd, unsigned int cmd, unsigned long arg) { @@ -719,14 +630,14 @@ compat_sys_io_submit(aio_context_t ctx_id, int nr, u32 __user *iocb) struct compat_ncp_mount_data { compat_int_t version; compat_uint_t ncp_fd; - compat_uid_t mounted_uid; + __compat_uid_t mounted_uid; compat_pid_t wdog_pid; unsigned char mounted_vol[NCP_VOLNAME_LEN + 1]; compat_uint_t time_out; compat_uint_t retry_count; compat_uint_t flags; - compat_uid_t uid; - compat_gid_t gid; + __compat_uid_t uid; + __compat_gid_t gid; compat_mode_t file_mode; compat_mode_t dir_mode; }; @@ -783,9 +694,9 @@ static void *do_ncp_super_data_conv(void *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_uid_t mounted_uid; + __compat_uid_t uid; + __compat_gid_t gid; compat_mode_t file_mode; compat_mode_t dir_mode; }; @@ -806,10 +717,79 @@ static void *do_smb_super_data_conv(void *raw_data) return raw_data; } +struct compat_nfs_string { + compat_uint_t len; + compat_uptr_t data; +}; + +static inline void compat_nfs_string(struct nfs_string *dst, + struct compat_nfs_string *src) +{ + dst->data = compat_ptr(src->data); + dst->len = src->len; +} + +struct compat_nfs4_mount_data_v1 { + compat_int_t version; + compat_int_t flags; + compat_int_t rsize; + compat_int_t wsize; + compat_int_t timeo; + compat_int_t retrans; + compat_int_t acregmin; + compat_int_t acregmax; + compat_int_t acdirmin; + compat_int_t acdirmax; + struct compat_nfs_string client_addr; + struct compat_nfs_string mnt_path; + struct compat_nfs_string hostname; + compat_uint_t host_addrlen; + compat_uptr_t host_addr; + compat_int_t proto; + compat_int_t auth_flavourlen; + compat_uptr_t auth_flavours; +}; + +static int do_nfs4_super_data_conv(void *raw_data) +{ + int version = *(compat_uint_t *) raw_data; + + if (version == 1) { + struct compat_nfs4_mount_data_v1 *raw = raw_data; + struct nfs4_mount_data *real = raw_data; + + /* copy the fields backwards */ + real->auth_flavours = compat_ptr(raw->auth_flavours); + real->auth_flavourlen = raw->auth_flavourlen; + real->proto = raw->proto; + real->host_addr = compat_ptr(raw->host_addr); + real->host_addrlen = raw->host_addrlen; + compat_nfs_string(&real->hostname, &raw->hostname); + compat_nfs_string(&real->mnt_path, &raw->mnt_path); + compat_nfs_string(&real->client_addr, &raw->client_addr); + real->acdirmax = raw->acdirmax; + real->acdirmin = raw->acdirmin; + real->acregmax = raw->acregmax; + real->acregmin = raw->acregmin; + real->retrans = raw->retrans; + real->timeo = raw->timeo; + real->wsize = raw->wsize; + real->rsize = raw->rsize; + real->flags = raw->flags; + real->version = raw->version; + } + else { + return -EINVAL; + } + + return 0; +} + extern int copy_mount_options (const void __user *, unsigned long *); #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, @@ -845,6 +825,9 @@ asmlinkage long compat_sys_mount(char __user * dev_name, char __user * dir_name, do_smb_super_data_conv((void *)data_page); } else if (!strcmp((char *)type_page, NCPFS_NAME)) { do_ncp_super_data_conv((void *)data_page); + } else if (!strcmp((char *)type_page, NFS4_NAME)) { + if (do_nfs4_super_data_conv((void *) data_page)) + goto out4; } } @@ -853,6 +836,7 @@ asmlinkage long compat_sys_mount(char __user * dev_name, char __user * dir_name, flags, (void*)data_page); unlock_kernel(); + out4: free_page(data_page); out3: free_page(dev_page); @@ -1233,9 +1217,13 @@ static ssize_t compat_do_readv_writev(int type, struct file *file, out: if (iov != iovstack) kfree(iov); - if ((ret + (type == READ)) > 0) - dnotify_parent(file->f_dentry, - (type == READ) ? DN_ACCESS : DN_MODIFY); + if ((ret + (type == READ)) > 0) { + struct dentry *dentry = file->f_dentry; + if (type == READ) + fsnotify_access(dentry); + else + fsnotify_modify(dentry); + } return ret; } @@ -1730,8 +1718,8 @@ struct compat_nfsctl_export { compat_dev_t ex32_dev; compat_ino_t ex32_ino; compat_int_t ex32_flags; - compat_uid_t ex32_anon_uid; - compat_gid_t ex32_anon_gid; + __compat_uid_t ex32_anon_uid; + __compat_gid_t ex32_anon_gid; }; struct compat_nfsctl_fdparm {