Messages in this thread Patch in this message | | | From | Andries.Brouwer@cwi ... | Date | Sat, 19 Apr 2003 00:34:08 +0200 (MEST) | Subject | [PATCH] struct loop_info64 with __u64 |
| |
Below a version with __u64 instead of unsigned long long.
Andries
(i) Replace in struct loop_info the dev_t field by __kernel_old_dev_t, where this type is defined in <asm/posix_types.h>, so that problems with a differently sized dev_t in userspace are avoided. (ii) Introduce a new loop_info64, with __u64 device, inode and offset fields.
--------------------------------------------------------- diff -u --recursive --new-file -X /linux/dontdiff a/include/linux/loop.h b/include/linux/loop.h --- a/include/linux/loop.h Fri Nov 22 22:41:13 2002 +++ b/include/linux/loop.h Sat Apr 19 00:08:13 2003 @@ -1,8 +1,6 @@ #ifndef _LINUX_LOOP_H #define _LINUX_LOOP_H -#include <linux/kdev_t.h> - /* * include/linux/loop.h * @@ -74,34 +72,37 @@ #define LO_FLAGS_READ_ONLY 2 #define LO_FLAGS_BH_REMAP 4 -/* - * Note that this structure gets the wrong offsets when directly used - * from a glibc program, because glibc has a 32bit dev_t. - * Prevent people from shooting in their own foot. - */ -#if __GLIBC__ >= 2 && !defined(dev_t) -#error "Wrong dev_t in loop.h" -#endif - -/* - * This uses kdev_t because glibc currently has no appropiate - * conversion version for the loop ioctls. - * The situation is very unpleasant - */ +#include <asm/posix_types.h> /* for __kernel_old_dev_t */ +#include <asm/types.h> /* for __u64 */ +/* Backwards compatibility version */ struct loop_info { - int lo_number; /* ioctl r/o */ - dev_t lo_device; /* ioctl r/o */ - unsigned long lo_inode; /* ioctl r/o */ - dev_t lo_rdevice; /* ioctl r/o */ - int lo_offset; - int lo_encrypt_type; - int lo_encrypt_key_size; /* ioctl w/o */ - int lo_flags; /* ioctl r/o */ - char lo_name[LO_NAME_SIZE]; - unsigned char lo_encrypt_key[LO_KEY_SIZE]; /* ioctl w/o */ - unsigned long lo_init[2]; - char reserved[4]; + int lo_number; /* ioctl r/o */ + __kernel_old_dev_t lo_device; /* ioctl r/o */ + unsigned long lo_inode; /* ioctl r/o */ + __kernel_old_dev_t lo_rdevice; /* ioctl r/o */ + int lo_offset; + int lo_encrypt_type; + int lo_encrypt_key_size; /* ioctl w/o */ + int lo_flags; /* ioctl r/o */ + char lo_name[LO_NAME_SIZE]; + unsigned char lo_encrypt_key[LO_KEY_SIZE]; /* ioctl w/o */ + unsigned long lo_init[2]; + char reserved[4]; +}; + +struct loop_info64 { + __u64 lo_device; /* ioctl r/o */ + __u64 lo_inode; /* ioctl r/o */ + __u64 lo_rdevice; /* ioctl r/o */ + __u64 lo_offset; + __u32 lo_number; /* ioctl r/o */ + __u32 lo_encrypt_type; + __u32 lo_encrypt_key_size; /* ioctl w/o */ + __u32 lo_flags; /* ioctl r/o */ + __u8 lo_name[LO_NAME_SIZE]; + __u8 lo_encrypt_key[LO_KEY_SIZE]; /* ioctl w/o */ + __u64 lo_init[2]; }; /* @@ -125,7 +126,7 @@ int number; /* filter type */ int (*transfer)(struct loop_device *lo, int cmd, char *raw_buf, char *loop_buf, int size, sector_t real_block); - int (*init)(struct loop_device *, struct loop_info *); + int (*init)(struct loop_device *, const struct loop_info64 *); /* release is called from loop_unregister_transfer or clr_fd */ int (*release)(struct loop_device *); int (*ioctl)(struct loop_device *, int cmd, unsigned long arg); @@ -134,7 +135,7 @@ void (*unlock)(struct loop_device *); }; -int loop_register_transfer(struct loop_func_table *funcs); +int loop_register_transfer(struct loop_func_table *funcs); int loop_unregister_transfer(int number); #endif @@ -142,9 +143,11 @@ * IOCTL commands --- we will commandeer 0x4C ('L') */ -#define LOOP_SET_FD 0x4C00 -#define LOOP_CLR_FD 0x4C01 -#define LOOP_SET_STATUS 0x4C02 -#define LOOP_GET_STATUS 0x4C03 +#define LOOP_SET_FD 0x4C00 +#define LOOP_CLR_FD 0x4C01 +#define LOOP_SET_STATUS 0x4C02 +#define LOOP_GET_STATUS 0x4C03 +#define LOOP_SET_STATUS64 0x4C04 +#define LOOP_GET_STATUS64 0x4C05 #endif diff -u --recursive --new-file -X /linux/dontdiff a/include/asm-alpha/posix_types.h b/include/asm-alpha/posix_types.h --- a/include/asm-alpha/posix_types.h Mon Feb 24 23:02:56 2003 +++ b/include/asm-alpha/posix_types.h Sat Apr 19 00:08:13 2003 @@ -40,6 +40,8 @@ typedef __kernel_uid_t __kernel_uid32_t; typedef __kernel_gid_t __kernel_gid32_t; +typedef unsigned int __kernel_old_dev_t; + #ifdef __KERNEL__ #ifndef __GNUC__ diff -u --recursive --new-file -X /linux/dontdiff a/include/asm-arm/posix_types.h b/include/asm-arm/posix_types.h --- a/include/asm-arm/posix_types.h Tue Mar 18 11:48:22 2003 +++ b/include/asm-arm/posix_types.h Sat Apr 19 00:08:13 2003 @@ -45,6 +45,7 @@ typedef unsigned short __kernel_old_uid_t; typedef unsigned short __kernel_old_gid_t; +typedef unsigned short __kernel_old_dev_t; #ifdef __GNUC__ typedef long long __kernel_loff_t; diff -u --recursive --new-file -X /linux/dontdiff a/include/asm-cris/posix_types.h b/include/asm-cris/posix_types.h --- a/include/asm-cris/posix_types.h Fri Nov 22 22:40:22 2002 +++ b/include/asm-cris/posix_types.h Sat Apr 19 00:08:13 2003 @@ -38,6 +38,7 @@ typedef unsigned short __kernel_old_uid_t; typedef unsigned short __kernel_old_gid_t; +typedef unsigned short __kernel_old_dev_t; #ifdef __GNUC__ typedef long long __kernel_loff_t; diff -u --recursive --new-file -X /linux/dontdiff a/include/asm-i386/posix_types.h b/include/asm-i386/posix_types.h --- a/include/asm-i386/posix_types.h Mon Feb 24 23:02:56 2003 +++ b/include/asm-i386/posix_types.h Sat Apr 19 00:08:13 2003 @@ -33,6 +33,7 @@ typedef unsigned short __kernel_old_uid_t; typedef unsigned short __kernel_old_gid_t; +typedef unsigned short __kernel_old_dev_t; #ifdef __GNUC__ typedef long long __kernel_loff_t; diff -u --recursive --new-file -X /linux/dontdiff a/include/asm-ia64/posix_types.h b/include/asm-ia64/posix_types.h --- a/include/asm-ia64/posix_types.h Tue Mar 18 11:48:23 2003 +++ b/include/asm-ia64/posix_types.h Sat Apr 19 00:08:13 2003 @@ -43,6 +43,8 @@ typedef __kernel_uid_t __kernel_uid32_t; typedef __kernel_gid_t __kernel_gid32_t; +typedef unsigned int __kernel_old_dev_t; + # ifdef __KERNEL__ # ifndef __GNUC__ diff -u --recursive --new-file -X /linux/dontdiff a/include/asm-m68k/posix_types.h b/include/asm-m68k/posix_types.h --- a/include/asm-m68k/posix_types.h Wed Mar 5 10:47:30 2003 +++ b/include/asm-m68k/posix_types.h Sat Apr 19 00:08:13 2003 @@ -33,6 +33,7 @@ typedef unsigned short __kernel_old_uid_t; typedef unsigned short __kernel_old_gid_t; +typedef unsigned short __kernel_old_dev_t; #ifdef __GNUC__ typedef long long __kernel_loff_t; diff -u --recursive --new-file -X /linux/dontdiff a/include/asm-mips/posix_types.h b/include/asm-mips/posix_types.h --- a/include/asm-mips/posix_types.h Fri Nov 22 22:40:50 2002 +++ b/include/asm-mips/posix_types.h Sat Apr 19 00:08:13 2003 @@ -39,6 +39,7 @@ typedef int __kernel_gid32_t; typedef __kernel_uid_t __kernel_old_uid_t; typedef __kernel_gid_t __kernel_old_gid_t; +typedef unsigned int __kernel_old_dev_t; #ifdef __GNUC__ typedef long long __kernel_loff_t; diff -u --recursive --new-file -X /linux/dontdiff a/include/asm-mips64/posix_types.h b/include/asm-mips64/posix_types.h --- a/include/asm-mips64/posix_types.h Wed Dec 18 12:52:06 2002 +++ b/include/asm-mips64/posix_types.h Sat Apr 19 00:08:13 2003 @@ -39,6 +39,7 @@ typedef int __kernel_gid32_t; typedef __kernel_uid_t __kernel_old_uid_t; typedef __kernel_gid_t __kernel_old_gid_t; +typedef unsigned int __kernel_old_dev_t; #ifdef __GNUC__ typedef long long __kernel_loff_t; diff -u --recursive --new-file -X /linux/dontdiff a/include/asm-parisc/posix_types.h b/include/asm-parisc/posix_types.h --- a/include/asm-parisc/posix_types.h Tue Mar 25 04:54:42 2003 +++ b/include/asm-parisc/posix_types.h Sat Apr 19 00:08:13 2003 @@ -45,6 +45,8 @@ typedef unsigned long long __kernel_ino64_t; #endif +typedef unsigned int __kernel_old_dev_t; + typedef struct { #if defined(__KERNEL__) || defined(__USE_ALL) int val[2]; diff -u --recursive --new-file -X /linux/dontdiff a/include/asm-ppc/posix_types.h b/include/asm-ppc/posix_types.h --- a/include/asm-ppc/posix_types.h Mon Feb 24 23:02:56 2003 +++ b/include/asm-ppc/posix_types.h Sat Apr 19 00:08:13 2003 @@ -33,6 +33,7 @@ typedef unsigned int __kernel_old_uid_t; typedef unsigned int __kernel_old_gid_t; +typedef unsigned int __kernel_old_dev_t; #ifdef __GNUC__ typedef long long __kernel_loff_t; diff -u --recursive --new-file -X /linux/dontdiff a/include/asm-ppc64/posix_types.h b/include/asm-ppc64/posix_types.h --- a/include/asm-ppc64/posix_types.h Mon Feb 24 23:02:56 2003 +++ b/include/asm-ppc64/posix_types.h Sat Apr 19 00:08:13 2003 @@ -39,6 +39,7 @@ typedef unsigned int __kernel_old_uid_t; typedef unsigned int __kernel_old_gid_t; +typedef unsigned long __kernel_old_dev_t; typedef struct { int val[2]; diff -u --recursive --new-file -X /linux/dontdiff a/include/asm-s390/posix_types.h b/include/asm-s390/posix_types.h --- a/include/asm-s390/posix_types.h Wed Dec 18 12:52:06 2002 +++ b/include/asm-s390/posix_types.h Sat Apr 19 00:08:13 2003 @@ -39,6 +39,7 @@ typedef unsigned short __kernel_old_uid_t; typedef unsigned short __kernel_old_gid_t; +typedef unsigned short __kernel_old_dev_t; #ifdef __GNUC__ typedef long long __kernel_loff_t; diff -u --recursive --new-file -X /linux/dontdiff a/include/asm-s390x/posix_types.h b/include/asm-s390x/posix_types.h --- a/include/asm-s390x/posix_types.h Wed Dec 18 12:52:06 2002 +++ b/include/asm-s390x/posix_types.h Sat Apr 19 00:08:13 2003 @@ -42,6 +42,8 @@ typedef __kernel_uid_t __kernel_uid32_t; typedef __kernel_gid_t __kernel_gid32_t; +typedef unsigned int __kernel_old_dev_t; + typedef struct { #if defined(__KERNEL__) || defined(__USE_ALL) int val[2]; diff -u --recursive --new-file -X /linux/dontdiff a/include/asm-sh/posix_types.h b/include/asm-sh/posix_types.h --- a/include/asm-sh/posix_types.h Fri Nov 22 22:40:41 2002 +++ b/include/asm-sh/posix_types.h Sat Apr 19 00:08:13 2003 @@ -31,6 +31,7 @@ typedef unsigned short __kernel_old_uid_t; typedef unsigned short __kernel_old_gid_t; +typedef unsigned short __kernel_old_dev_t; #ifdef __GNUC__ typedef long long __kernel_loff_t; diff -u --recursive --new-file -X /linux/dontdiff a/include/asm-sparc/posix_types.h b/include/asm-sparc/posix_types.h --- a/include/asm-sparc/posix_types.h Mon Feb 24 23:02:57 2003 +++ b/include/asm-sparc/posix_types.h Sat Apr 19 00:08:13 2003 @@ -31,6 +31,7 @@ typedef unsigned int __kernel_gid32_t; typedef unsigned short __kernel_old_uid_t; typedef unsigned short __kernel_old_gid_t; +typedef unsigned short __kernel_old_dev_t; typedef int __kernel_clockid_t; typedef int __kernel_timer_t; diff -u --recursive --new-file -X /linux/dontdiff a/include/asm-sparc64/posix_types.h b/include/asm-sparc64/posix_types.h --- a/include/asm-sparc64/posix_types.h Mon Feb 24 23:02:57 2003 +++ b/include/asm-sparc64/posix_types.h Sat Apr 19 00:08:13 2003 @@ -34,6 +34,8 @@ typedef __kernel_uid_t __kernel_uid32_t; typedef __kernel_gid_t __kernel_gid32_t; +typedef unsigned int __kernel_old_dev_t; + /* Note this piece of asymmetry from the v9 ABI. */ typedef int __kernel_suseconds_t; diff -u --recursive --new-file -X /linux/dontdiff a/include/asm-v850/posix_types.h b/include/asm-v850/posix_types.h --- a/include/asm-v850/posix_types.h Fri Nov 22 22:41:13 2002 +++ b/include/asm-v850/posix_types.h Sat Apr 19 00:08:13 2003 @@ -40,7 +40,7 @@ /* Some bogus code depends on this; we don't care. */ typedef __kernel_uid_t __kernel_old_uid_t; - +typedef unsigned int __kernel_old_dev_t; typedef struct { #if defined(__KERNEL__) || defined(__USE_ALL) diff -u --recursive --new-file -X /linux/dontdiff a/include/asm-x86_64/posix_types.h b/include/asm-x86_64/posix_types.h --- a/include/asm-x86_64/posix_types.h Mon Feb 24 23:02:57 2003 +++ b/include/asm-x86_64/posix_types.h Sat Apr 19 00:08:13 2003 @@ -22,8 +22,8 @@ typedef long __kernel_time_t; typedef long __kernel_suseconds_t; typedef long __kernel_clock_t; -typedef int __kernel_timer_t; -typedef int __kernel_clockid_t; +typedef int __kernel_timer_t; +typedef int __kernel_clockid_t; typedef int __kernel_daddr_t; typedef char * __kernel_caddr_t; typedef unsigned short __kernel_uid16_t; @@ -42,6 +42,8 @@ typedef __kernel_uid_t __kernel_uid32_t; typedef __kernel_gid_t __kernel_gid32_t; +typedef unsigned long __kernel_old_dev_t; + #ifdef __KERNEL__ #undef __FD_SET diff -u --recursive --new-file -X /linux/dontdiff a/drivers/block/loop.c b/drivers/block/loop.c --- a/drivers/block/loop.c Tue Mar 25 04:54:31 2003 +++ b/drivers/block/loop.c Sat Apr 19 00:08:13 2003 @@ -120,13 +120,13 @@ return 0; } -static int none_status(struct loop_device *lo, struct loop_info *info) +static int none_status(struct loop_device *lo, const struct loop_info64 *info) { lo->lo_flags |= LO_FLAGS_BH_REMAP; return 0; } -static int xor_status(struct loop_device *lo, struct loop_info *info) +static int xor_status(struct loop_device *lo, const struct loop_info64 *info) { if (info->lo_encrypt_key_size <= 0) return -EINVAL; @@ -215,7 +215,8 @@ * The transfer failed, but we still write the data to * keep prepare/commit calls balanced. */ - printk(KERN_ERR "loop: transfer error block %llu\n", (unsigned long long)index); + printk(KERN_ERR "loop: transfer error block %llu\n", + (unsigned long long)index); memset(kaddr + offset, 0, size); } flush_dcache_page(page); @@ -270,7 +271,9 @@ int bsize; }; -static int lo_read_actor(read_descriptor_t * desc, struct page *page, unsigned long offset, unsigned long size) +static int +lo_read_actor(read_descriptor_t *desc, struct page *page, + unsigned long offset, unsigned long size) { char *kaddr; unsigned long count = desc->count; @@ -284,7 +287,8 @@ kaddr = kmap(page); if (lo_do_transfer(lo, READ, kaddr + offset, p->data, size, IV)) { size = 0; - printk(KERN_ERR "loop: transfer error block %ld\n",page->index); + printk(KERN_ERR "loop: transfer error block %ld\n", + page->index); desc->error = -EINVAL; } kunmap(page); @@ -297,7 +301,7 @@ static int do_lo_receive(struct loop_device *lo, - struct bio_vec *bvec, int bsize, loff_t pos) + struct bio_vec *bvec, int bsize, loff_t pos) { struct lo_read_data cookie; struct file *file; @@ -330,8 +334,8 @@ return ret; } -static inline unsigned long loop_get_iv(struct loop_device *lo, - unsigned long sector) +static inline unsigned long +loop_get_iv(struct loop_device *lo, unsigned long sector) { int bs = lo->lo_blocksize; unsigned long offset, IV; @@ -358,6 +362,7 @@ } static int loop_end_io_transfer(struct bio *, unsigned int, int); + static void loop_put_buffer(struct bio *bio) { /* @@ -764,7 +769,8 @@ return err; } -static int loop_init_xfer(struct loop_device *lo, int type,struct loop_info *i) +static int +loop_init_xfer(struct loop_device *lo, int type, const struct loop_info64 *i) { int err = 0; if (type) { @@ -822,9 +828,9 @@ return 0; } -static int loop_set_status(struct loop_device *lo, struct loop_info *arg) +static int +loop_set_status(struct loop_device *lo, const struct loop_info64 *info) { - struct loop_info info; int err; unsigned int type; loff_t offset; @@ -834,23 +840,21 @@ return -EPERM; if (lo->lo_state != Lo_bound) return -ENXIO; - if (copy_from_user(&info, arg, sizeof (struct loop_info))) - return -EFAULT; - if ((unsigned int) info.lo_encrypt_key_size > LO_KEY_SIZE) + if ((unsigned int) info->lo_encrypt_key_size > LO_KEY_SIZE) return -EINVAL; - type = info.lo_encrypt_type; + type = info->lo_encrypt_type; if (type >= MAX_LO_CRYPT || xfer_funcs[type] == NULL) return -EINVAL; - if (type == LO_CRYPT_XOR && info.lo_encrypt_key_size == 0) + if (type == LO_CRYPT_XOR && info->lo_encrypt_key_size == 0) return -EINVAL; err = loop_release_xfer(lo); if (!err) - err = loop_init_xfer(lo, type, &info); + err = loop_init_xfer(lo, type, info); offset = lo->lo_offset; - if (offset != info.lo_offset) { - lo->lo_offset = info.lo_offset; + if (offset != info->lo_offset) { + lo->lo_offset = info->lo_offset; if (figure_loop_size(lo)){ err = -EFBIG; lo->lo_offset = offset; @@ -860,51 +864,147 @@ if (err) return err; - strncpy(lo->lo_name, info.lo_name, LO_NAME_SIZE); + strncpy(lo->lo_name, info->lo_name, LO_NAME_SIZE); lo->transfer = xfer_funcs[type]->transfer; lo->ioctl = xfer_funcs[type]->ioctl; - lo->lo_encrypt_key_size = info.lo_encrypt_key_size; - lo->lo_init[0] = info.lo_init[0]; - lo->lo_init[1] = info.lo_init[1]; - if (info.lo_encrypt_key_size) { - memcpy(lo->lo_encrypt_key, info.lo_encrypt_key, - info.lo_encrypt_key_size); + lo->lo_encrypt_key_size = info->lo_encrypt_key_size; + lo->lo_init[0] = info->lo_init[0]; + lo->lo_init[1] = info->lo_init[1]; + if (info->lo_encrypt_key_size) { + memcpy(lo->lo_encrypt_key, info->lo_encrypt_key, + info->lo_encrypt_key_size); lo->lo_key_owner = current->uid; } return 0; } -static int loop_get_status(struct loop_device *lo, struct loop_info *arg) +static int +loop_get_status(struct loop_device *lo, struct loop_info64 *info) { struct file *file = lo->lo_backing_file; - struct loop_info info; struct kstat stat; int error; if (lo->lo_state != Lo_bound) return -ENXIO; - if (!arg) - return -EINVAL; error = vfs_getattr(file->f_vfsmnt, file->f_dentry, &stat); if (error) return error; - memset(&info, 0, sizeof(info)); - info.lo_number = lo->lo_number; - info.lo_device = stat.dev; - info.lo_inode = stat.ino; - info.lo_rdevice = lo->lo_device ? stat.rdev : stat.dev; - info.lo_offset = lo->lo_offset; - info.lo_flags = lo->lo_flags; - strncpy(info.lo_name, lo->lo_name, LO_NAME_SIZE); - info.lo_encrypt_type = lo->lo_encrypt_type; + memset(info, 0, sizeof(*info)); + info->lo_number = lo->lo_number; + info->lo_device = stat.dev; + info->lo_inode = stat.ino; + info->lo_rdevice = lo->lo_device ? stat.rdev : stat.dev; + info->lo_offset = lo->lo_offset; + info->lo_flags = lo->lo_flags; + strncpy(info->lo_name, lo->lo_name, LO_NAME_SIZE); + info->lo_encrypt_type = lo->lo_encrypt_type; if (lo->lo_encrypt_key_size && capable(CAP_SYS_ADMIN)) { - info.lo_encrypt_key_size = lo->lo_encrypt_key_size; - memcpy(info.lo_encrypt_key, lo->lo_encrypt_key, + info->lo_encrypt_key_size = lo->lo_encrypt_key_size; + memcpy(info->lo_encrypt_key, lo->lo_encrypt_key, lo->lo_encrypt_key_size); } - return copy_to_user(arg, &info, sizeof(info)) ? -EFAULT : 0; + return 0; +} + +static void +loop_info64_from_old(const struct loop_info *info, struct loop_info64 *info64) +{ + info64->lo_number = info->lo_number; + info64->lo_device = info->lo_device; + info64->lo_inode = info->lo_inode; + info64->lo_rdevice = info->lo_rdevice; + info64->lo_offset = info->lo_offset; + info64->lo_encrypt_type = info->lo_encrypt_type; + info64->lo_encrypt_key_size = info->lo_encrypt_key_size; + info64->lo_flags = info->lo_flags; + info64->lo_init[0] = info->lo_init[0]; + info64->lo_init[1] = info->lo_init[1]; + memcpy(info64->lo_name, info->lo_name, LO_NAME_SIZE); + memcpy(info64->lo_encrypt_key, info->lo_encrypt_key, LO_KEY_SIZE); +} + +static int +loop_info64_to_old(const struct loop_info64 *info64, struct loop_info *info) +{ + info->lo_number = info64->lo_number; + info->lo_device = info64->lo_device; + info->lo_inode = info64->lo_inode; + info->lo_rdevice = info64->lo_rdevice; + info->lo_offset = info64->lo_offset; + info->lo_encrypt_type = info64->lo_encrypt_type; + info->lo_encrypt_key_size = info64->lo_encrypt_key_size; + info->lo_flags = info64->lo_flags; + info->lo_init[0] = info64->lo_init[0]; + info->lo_init[1] = info64->lo_init[1]; + memcpy(info->lo_name, info64->lo_name, LO_NAME_SIZE); + memcpy(info->lo_encrypt_key,info64->lo_encrypt_key,LO_KEY_SIZE); + + /* error in case values were truncated */ + if (info->lo_device != info64->lo_device || + info->lo_rdevice != info64->lo_rdevice || + info->lo_inode != info64->lo_inode || + info->lo_offset != info64->lo_offset) + return -EOVERFLOW; + + return 0; +} + +static int +loop_set_status_old(struct loop_device *lo, const struct loop_info *arg) +{ + struct loop_info info; + struct loop_info64 info64; + + if (copy_from_user(&info, arg, sizeof (struct loop_info))) + return -EFAULT; + loop_info64_from_old(&info, &info64); + return loop_set_status(lo, &info64); +} + +static int +loop_set_status64(struct loop_device *lo, const struct loop_info64 *arg) +{ + struct loop_info64 info64; + + if (copy_from_user(&info64, arg, sizeof (struct loop_info64))) + return -EFAULT; + return loop_set_status(lo, &info64); +} + +static int +loop_get_status_old(struct loop_device *lo, struct loop_info *arg) { + struct loop_info info; + struct loop_info64 info64; + int err = 0; + + if (!arg) + err = -EINVAL; + if (!err) + err = loop_get_status(lo, &info64); + if (!err) + err = loop_info64_to_old(&info64, &info); + if (!err && copy_to_user(arg, &info, sizeof(info))) + err = -EFAULT; + + return err; +} + +static int +loop_get_status64(struct loop_device *lo, struct loop_info64 *arg) { + struct loop_info64 info64; + int err = 0; + + if (!arg) + err = -EINVAL; + if (!err) + err = loop_get_status(lo, &info64); + if (!err && copy_to_user(arg, &info64, sizeof(info64))) + err = -EFAULT; + + return err; } static int lo_ioctl(struct inode * inode, struct file * file, @@ -922,10 +1022,16 @@ err = loop_clr_fd(lo, inode->i_bdev); break; case LOOP_SET_STATUS: - err = loop_set_status(lo, (struct loop_info *) arg); + err = loop_set_status_old(lo, (struct loop_info *) arg); break; case LOOP_GET_STATUS: - err = loop_get_status(lo, (struct loop_info *) arg); + err = loop_get_status_old(lo, (struct loop_info *) arg); + break; + case LOOP_SET_STATUS64: + err = loop_set_status64(lo, (struct loop_info64 *) arg); + break; + case LOOP_GET_STATUS64: + err = loop_get_status64(lo, (struct loop_info64 *) arg); break; default: err = lo->ioctl ? lo->ioctl(lo, cmd, arg) : -EINVAL; - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
| |