ext4: Conditionally define compat ioctl numbers
PATCH 1/2 ext4: Conditionally define compat ioctl numbers
It is unnecessary, and in general impossible, to define the compat ioctl numbers except when building the filesystem with CONFIG_COMPAT defined.
--- fs/ext4/ext4.h | 2 ++ 1 files changed, 2 insertions(+), 0 deletions(-)
fs/ext4/ext4.h +2 -0
@@ -398,6 +398,7 @@ struct ext4_new_group_data {#define EXT4_IOC_ALLOC_DA_BLKS _IO('f', 12)#define EXT4_IOC_MOVE_EXT _IOWR('f', 15, struct move_extent) +#if defined(__KERNEL__) && defined(CONFIG_COMPAT )/* * ioctl commands in 32 bit emulation */
@@ -413,6 +414,7 @@ struct ext4_new_group_data {#endif #define EXT4_IOC32_GETVERSION_OLD FS_IOC32_GETVERSION#define EXT4_IOC32_SETVERSION_OLD FS_IOC32_SETVERSION +#endif /*
Signature · 1 line
1.7.1
PATCH 2/2 ext4: Fix compat EXT4_IOC_ADD_GROUP
struct ext4_new_group_input needs to be converted because u64 has only 32-bit alignment on some 32-bit architectures, notably i386.
---
Found and tested by myself on a Debian 2.6.32 kernel. This patch is based on linux-next.
Ben.
fs/ext4/ext4.h | 16 ++++++++++++++++ fs/ext4/ioctl.c | 25 +++++++++++++++++++++++-- 2 files changed, 39 insertions(+), 2 deletions(-)
fs/ext4/ext4.h +16 -0
@@ -29,6 +29,9 @@#include <linux/wait.h> #include <linux/blockgroup_lock.h> #include <linux/percpu_counter.h> +#ifdef __KERNEL__ +#include <linux/compat.h> +#endif /* * The fourth extended filesystem constants/structures
@@ -332,6 +335,18 @@ struct ext4_new_group_input {__u16 unused; }; +#if defined(__KERNEL__) && defined(CONFIG_COMPAT ) +struct compat_ext4_new_group_input { +u32 group; +compat_u64 block_bitmap; +compat_u64 inode_bitmap; +compat_u64 inode_table; +u32 blocks_count; +u16 reserved_blocks; +u16 unused; +}; +#endif +/* The struct ext4_new_group_input in kernel space, with free_blocks_count */ struct ext4_new_group_data {__u32 group;
@@ -409,6 +424,7 @@ struct ext4_new_group_data {#define EXT4_IOC32_GETRSVSZ _IOR('f', 5, int)#define EXT4_IOC32_SETRSVSZ _IOW('f', 6, int)#define EXT4_IOC32_GROUP_EXTEND _IOW('f', 7, unsigned int) +#define EXT4_IOC32_GROUP_ADD _IOW('f', 8, struct compat_ext4_new_group_input)#ifdef CONFIG_JBD2_DEBUG #define EXT4_IOC32_WAIT_FOR_READONLY _IOR('f', 99, int)#endif
fs/ext4/ioctl.c +23 -2
@@ -373,8 +373,29 @@ long ext4_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)case EXT4_IOC32_SETRSVSZ : cmd =EXT4_IOC_SETRSVSZ ;break ; -case EXT4_IOC_GROUP_ADD : -break ; +case EXT4_IOC32_GROUP_ADD : { +struct compat_ext4_new_group_input __user *uinput; +struct ext4_new_group_input input; +mm_segment_t old_fs; +int err; + + uinput =compat_ptr (arg); + err =get_user (input.group, &uinput->group); + err |=get_user (input.block_bitmap, &uinput->block_bitmap); + err |=get_user (input.inode_bitmap, &uinput->inode_bitmap); + err |=get_user (input.inode_table, &uinput->inode_table); + err |=get_user (input.blocks_count, &uinput->blocks_count); + err |=get_user (input.reserved_blocks, + &uinput->reserved_blocks); +if (err) +return -EFAULT ; + old_fs =get_fs (); +set_fs (KERNEL_DS ); + err =ext4_ioctl (file,EXT4_IOC_GROUP_ADD , + (unsigned long ) &input); +set_fs (old_fs); +return err; + }case EXT4_IOC_MOVE_EXT :break ;default :
Signature · 1 line
1.7.1
Re: [PATCH 2/2] ext4: Fix compat EXT4_IOC_ADD_GROUP
Quoted 2 lines · Ben Hutchings
struct
ext4_new_group_inputneeds to be converted because u64 has only 32-bit alignment on some 32-bit architectures, notably i386.
Sigh, it would have been nice to catch this when ext4_new_group_input was first created.
I don't mind fixing the kernel, since this is clearly broken. However, we may as well go ahead and declare a new struct ext4_new_group_input that has the right alignment, rename and deprecate the old one (have resize2fs prefer the new one if available) and take the old one out in a few years. I hate this business of keeping around old cruft like this forever.
struct compat_ext4_new_group_input {
u32 group;
u64 block_bitmap;
u64 inode_bitmap;
u64 inode_table;
u32 blocks_count;
u16 reserved_blocks;
u16 unused;
};struct ext4_new_group_input {
u64 group;
u64 block_bitmap;
u64 inode_bitmap;
u64 inode_table;
u64 blocks_count;
u32 reserved_blocks;
u32 unused;
};#define EXT2_IOC_GROUP_ADD _IOW('f', 8,struct ext2_new_group_input)
#define EXT4_IOC_GROUP_ADD_OLD _IOW('f', 8,struct compat_ext4_new_group_input)
#define EXT4_IOC_GROUP_ADD _IOW('f', 8,struct ext4_new_group_input)
The resize/online.c code already has compat support for both 32-bit and 64-bit IOC numbers, so it isn't much effort to have it try a third variant for a couple of years.
Quoted 63 lines
fs/ext4/ext4.h +12
-0+#if defined(__KERNEL__) && defined(CONFIG_COMPAT ) +struct compat_ext4_new_group_input { +u32 group; +compat_u64 block_bitmap; +compat_u64 inode_bitmap; +compat_u64 inode_table; +u32 blocks_count; +u16 reserved_blocks; +u16 unused; +}; +#endif +/* The struct
ext4_new_group_inputin kernel space, withfree_blocks_count*/struct ext4_new_group_data { __u32 group;fs/ext4/ext4.h +1
-0@@ -409,6 +424,7 @@ struct ext4_new_group_data {#define EXT4_IOC32_GETRSVSZ _IOR('f', 5, int)#define EXT4_IOC32_SETRSVSZ _IOW('f', 6, int)#define EXT4_IOC32_GROUP_EXTEND _IOW('f', 7, unsigned int) +#define EXT4_IOC32_GROUP_ADD _IOW('f', 8, struct compat_ext4_new_group_input)#ifdef CONFIG_JBD2_DEBUG #define EXT4_IOC32_WAIT_FOR_READONLY _IOR('f', 99, int)#endif fs/ext4/ioctl.c +23
-2@@ -373,8 +373,29 @@ long ext4_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)case EXT4_IOC32_SETRSVSZ : cmd =EXT4_IOC_SETRSVSZ ;break ; -case EXT4_IOC_GROUP_ADD : -break ; +case EXT4_IOC32_GROUP_ADD : { +struct compat_ext4_new_group_input __user *uinput; +struct ext4_new_group_input input; +mm_segment_t old_fs; +int err; + + uinput =compat_ptr (arg); + err =get_user (input.group, &uinput->group); + err |=get_user (input.block_bitmap, &uinput->block_bitmap); + err |=get_user (input.inode_bitmap, &uinput->inode_bitmap); + err |=get_user (input.inode_table, &uinput->inode_table); + err |=get_user (input.blocks_count, &uinput->blocks_count); + err |=get_user (input.reserved_blocks, + &uinput->reserved_blocks); +if (err) +return -EFAULT ; + old_fs =get_fs (); +set_fs (KERNEL_DS ); + err =ext4_ioctl (file,EXT4_IOC_GROUP_ADD , + (unsigned long ) &input); +set_fs (old_fs); +return err; + }case EXT4_IOC_MOVE_EXT :break ;default :Signature · 1 line
1.7.1
Cheers, Andreas
--
Andreas Dilger
Lustre Technical Lead
Oracle Corporation Canada Inc.
[email protected]
maintainerRe: [PATCH 2/2] ext4: Fix compat EXT4_IOC_ADD_GROUP
Quoted 4 lines · Andreas Dilger
Quoted 2 lines · Ben Hutchings
struct
ext4_new_group_inputneeds to be converted because u64 has only 32-bit alignment on some 32-bit architectures, notably i386.
Quoted 8 lines
Sigh, it would have been nice to catch this when
ext4_new_group_inputwas first created.I don't mind fixing the kernel, since this is clearly broken. However, we may as well go ahead and declare a new struct
ext4_new_group_inputthat has the right alignment, rename and deprecate the old one (have resize2fs prefer the new one if available) and take the old one out in a few years. I hate this business of keeping around old cruft like this forever.
Well, in the long run we need a new ioctl which is compatible with flex_bg, which means doing multiple groups at once, and letting the kernel do much more of the work of selecting the block and inode numbers. And of course to support 2**64 blocks we need to support the meta_bg style of resizing. So we need to do some thinking about how to support resizing in the long-term anyway.
- Ted
[email protected]
maintainerRe: [PATCH 2/2] ext4: Fix compat EXT4_IOC_ADD_GROUP
In reply to Ben HutchingsQuoted 5 lines · Ben Hutchings
struct
ext4_new_group_inputneeds to be converted because u64 has only 32-bit alignment on some 32-bit architectures, notably i386.Signed-off-by Ben Hutchings <[email protected]>---
Thanks for your patches. Both have been applied to the ext4 tree.
- Ted
[email protected]
maintainerQuoted 3 lines · Ben Hutchings
It is unnecessary, and in general impossible, to define the compat ioctl numbers except when building the filesystem with
CONFIG_COMPATdefined.
Umm.... why? (The impossible part) I think I'm missing something here.
- Ted
[email protected]
maintainerQuoted 7 lines · On Tue, May 25, 2010 at 11:15:48AM -0400, [email protected] wrote:
Quoted 3 lines · Ben Hutchings
It is unnecessary, and in general impossible, to define the compat ioctl numbers except when building the filesystem with
CONFIG_COMPATdefined.Umm.... why? (The impossible part) I think I'm missing something here.
Oh, right. The type widths might not be guaranteed (or even defined). Never mind...
- Ted