Linux Btrfs filesystem development
 help / color / mirror / Atom feed
* [PATCH] btrfs: Introduce compile time structure size check
@ 2018-07-12  6:19 Qu Wenruo
  2018-07-12  6:27 ` Nikolay Borisov
  2018-07-13 14:34 ` David Sterba
  0 siblings, 2 replies; 9+ messages in thread
From: Qu Wenruo @ 2018-07-12  6:19 UTC (permalink / raw)
  To: linux-btrfs

Introduce a new macro based compile time check for ioctl structures.

The new macro is BTRFS_ASSERT_SIZE(), which is mostly copied from
VMMDEV_ASSERT_SIZE().

Such check is only added to structure pended to power of 2.
And exposed one structure, btrfs_ioctl_get_dev_stats() is not aligned
well.
The misalign is introduced by commit b27f7c0c150f ("btrfs: join DEV_STATS
ioctls to one").

Signed-off-by: Qu Wenruo <wqu@suse.com>
---
 include/uapi/linux/btrfs.h | 18 +++++++++++++++++-
 1 file changed, 17 insertions(+), 1 deletion(-)

diff --git a/include/uapi/linux/btrfs.h b/include/uapi/linux/btrfs.h
index 5ca1d21fc4a7..be1213c10080 100644
--- a/include/uapi/linux/btrfs.h
+++ b/include/uapi/linux/btrfs.h
@@ -22,6 +22,14 @@
 #include <linux/types.h>
 #include <linux/ioctl.h>
 
+/*
+ * Compile time check on structure size, same method as
+ * VMMDEV_ASSERT_SIZE() from linux/vbox_vmmdev_types.h, to trigger a negative
+ * array size at compile time if size doesn't match.
+ */
+#define BTRFS_ASSERT_SIZE(type, size) \
+	typedef char type ## _asrt_size[1 - 2 * !!(sizeof(struct type) != (size))]
+
 #define BTRFS_IOCTL_MAGIC 0x94
 #define BTRFS_VOL_NAME_MAX 255
 #define BTRFS_LABEL_SIZE 256
@@ -32,6 +40,7 @@ struct btrfs_ioctl_vol_args {
 	__s64 fd;
 	char name[BTRFS_PATH_NAME_MAX + 1];
 };
+BTRFS_ASSERT_SIZE(btrfs_ioctl_vol_args, 4096);
 
 #define BTRFS_DEVICE_PATH_NAME_MAX	1024
 #define BTRFS_SUBVOL_NAME_MAX 		4039
@@ -171,6 +180,7 @@ struct btrfs_ioctl_scrub_args {
 	/* pad to 1k */
 	__u64 unused[(1024-32-sizeof(struct btrfs_scrub_progress))/8];
 };
+BTRFS_ASSERT_SIZE(btrfs_ioctl_scrub_args, 1024);
 
 #define BTRFS_IOCTL_DEV_REPLACE_CONT_READING_FROM_SRCDEV_MODE_ALWAYS	0
 #define BTRFS_IOCTL_DEV_REPLACE_CONT_READING_FROM_SRCDEV_MODE_AVOID	1
@@ -223,6 +233,7 @@ struct btrfs_ioctl_dev_info_args {
 	__u64 unused[379];			/* pad to 4k */
 	__u8 path[BTRFS_DEVICE_PATH_NAME_MAX];	/* out */
 };
+BTRFS_ASSERT_SIZE(btrfs_ioctl_dev_info_args, 4096);
 
 struct btrfs_ioctl_fs_info_args {
 	__u64 max_id;				/* out */
@@ -234,6 +245,7 @@ struct btrfs_ioctl_fs_info_args {
 	__u32 reserved32;
 	__u64 reserved[122];			/* pad to 1k */
 };
+BTRFS_ASSERT_SIZE(btrfs_ioctl_fs_info_args, 1024);
 
 /*
  * feature flags
@@ -414,6 +426,7 @@ struct btrfs_ioctl_balance_args {
 
 	__u64 unused[72];			/* pad to 1k */
 };
+BTRFS_ASSERT_SIZE(btrfs_ioctl_balance_args, 1024);
 
 #define BTRFS_INO_LOOKUP_PATH_MAX 4080
 struct btrfs_ioctl_ino_lookup_args {
@@ -421,6 +434,7 @@ struct btrfs_ioctl_ino_lookup_args {
 	__u64 objectid;
 	char name[BTRFS_INO_LOOKUP_PATH_MAX];
 };
+BTRFS_ASSERT_SIZE(btrfs_ioctl_ino_lookup_args, 4096);
 
 #define BTRFS_INO_LOOKUP_USER_PATH_MAX (4080 - BTRFS_VOL_NAME_MAX - 1)
 struct btrfs_ioctl_ino_lookup_user_args {
@@ -436,6 +450,7 @@ struct btrfs_ioctl_ino_lookup_user_args {
 	 */
 	char path[BTRFS_INO_LOOKUP_USER_PATH_MAX];
 };
+BTRFS_ASSERT_SIZE(btrfs_ioctl_ino_lookup_args, 4096);
 
 /* Search criteria for the btrfs SEARCH ioctl family. */
 struct btrfs_ioctl_search_key {
@@ -664,8 +679,9 @@ struct btrfs_ioctl_get_dev_stats {
 	/* out values: */
 	__u64 values[BTRFS_DEV_STAT_VALUES_MAX];
 
-	__u64 unused[128 - 2 - BTRFS_DEV_STAT_VALUES_MAX]; /* pad to 1k */
+	__u64 unused[128 - 3 - BTRFS_DEV_STAT_VALUES_MAX]; /* pad to 1k */
 };
+BTRFS_ASSERT_SIZE(btrfs_ioctl_get_dev_stats, 1024);
 
 #define BTRFS_QUOTA_CTL_ENABLE	1
 #define BTRFS_QUOTA_CTL_DISABLE	2
-- 
2.18.0


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Re: [PATCH] btrfs: Introduce compile time structure size check
  2018-07-12  6:19 [PATCH] btrfs: Introduce compile time structure size check Qu Wenruo
@ 2018-07-12  6:27 ` Nikolay Borisov
  2018-07-12  6:56   ` Qu Wenruo
  2018-07-13 14:34 ` David Sterba
  1 sibling, 1 reply; 9+ messages in thread
From: Nikolay Borisov @ 2018-07-12  6:27 UTC (permalink / raw)
  To: Qu Wenruo, linux-btrfs



On 12.07.2018 09:19, Qu Wenruo wrote:
> Introduce a new macro based compile time check for ioctl structures.
> 
> The new macro is BTRFS_ASSERT_SIZE(), which is mostly copied from
> VMMDEV_ASSERT_SIZE().
> 
> Such check is only added to structure pended to power of 2.
> And exposed one structure, btrfs_ioctl_get_dev_stats() is not aligned
> well.
> The misalign is introduced by commit b27f7c0c150f ("btrfs: join DEV_STATS
> ioctls to one").

So what's the negative effect if a structure is not aligned to a power of 2?

> 
> Signed-off-by: Qu Wenruo <wqu@suse.com>
> ---
>  include/uapi/linux/btrfs.h | 18 +++++++++++++++++-
>  1 file changed, 17 insertions(+), 1 deletion(-)
> 
> diff --git a/include/uapi/linux/btrfs.h b/include/uapi/linux/btrfs.h
> index 5ca1d21fc4a7..be1213c10080 100644
> --- a/include/uapi/linux/btrfs.h
> +++ b/include/uapi/linux/btrfs.h
> @@ -22,6 +22,14 @@
>  #include <linux/types.h>
>  #include <linux/ioctl.h>
>  
> +/*
> + * Compile time check on structure size, same method as
> + * VMMDEV_ASSERT_SIZE() from linux/vbox_vmmdev_types.h, to trigger a negative
> + * array size at compile time if size doesn't match.
> + */
> +#define BTRFS_ASSERT_SIZE(type, size) \
> +	typedef char type ## _asrt_size[1 - 2 * !!(sizeof(struct type) != (size))]
> +
>  #define BTRFS_IOCTL_MAGIC 0x94
>  #define BTRFS_VOL_NAME_MAX 255
>  #define BTRFS_LABEL_SIZE 256
> @@ -32,6 +40,7 @@ struct btrfs_ioctl_vol_args {
>  	__s64 fd;
>  	char name[BTRFS_PATH_NAME_MAX + 1];
>  };
> +BTRFS_ASSERT_SIZE(btrfs_ioctl_vol_args, 4096);
>  
>  #define BTRFS_DEVICE_PATH_NAME_MAX	1024
>  #define BTRFS_SUBVOL_NAME_MAX 		4039
> @@ -171,6 +180,7 @@ struct btrfs_ioctl_scrub_args {
>  	/* pad to 1k */
>  	__u64 unused[(1024-32-sizeof(struct btrfs_scrub_progress))/8];
>  };
> +BTRFS_ASSERT_SIZE(btrfs_ioctl_scrub_args, 1024);
>  
>  #define BTRFS_IOCTL_DEV_REPLACE_CONT_READING_FROM_SRCDEV_MODE_ALWAYS	0
>  #define BTRFS_IOCTL_DEV_REPLACE_CONT_READING_FROM_SRCDEV_MODE_AVOID	1
> @@ -223,6 +233,7 @@ struct btrfs_ioctl_dev_info_args {
>  	__u64 unused[379];			/* pad to 4k */
>  	__u8 path[BTRFS_DEVICE_PATH_NAME_MAX];	/* out */
>  };
> +BTRFS_ASSERT_SIZE(btrfs_ioctl_dev_info_args, 4096);
>  
>  struct btrfs_ioctl_fs_info_args {
>  	__u64 max_id;				/* out */
> @@ -234,6 +245,7 @@ struct btrfs_ioctl_fs_info_args {
>  	__u32 reserved32;
>  	__u64 reserved[122];			/* pad to 1k */
>  };
> +BTRFS_ASSERT_SIZE(btrfs_ioctl_fs_info_args, 1024);
>  
>  /*
>   * feature flags
> @@ -414,6 +426,7 @@ struct btrfs_ioctl_balance_args {
>  
>  	__u64 unused[72];			/* pad to 1k */
>  };
> +BTRFS_ASSERT_SIZE(btrfs_ioctl_balance_args, 1024);
>  
>  #define BTRFS_INO_LOOKUP_PATH_MAX 4080
>  struct btrfs_ioctl_ino_lookup_args {
> @@ -421,6 +434,7 @@ struct btrfs_ioctl_ino_lookup_args {
>  	__u64 objectid;
>  	char name[BTRFS_INO_LOOKUP_PATH_MAX];
>  };
> +BTRFS_ASSERT_SIZE(btrfs_ioctl_ino_lookup_args, 4096);
>  
>  #define BTRFS_INO_LOOKUP_USER_PATH_MAX (4080 - BTRFS_VOL_NAME_MAX - 1)
>  struct btrfs_ioctl_ino_lookup_user_args {
> @@ -436,6 +450,7 @@ struct btrfs_ioctl_ino_lookup_user_args {
>  	 */
>  	char path[BTRFS_INO_LOOKUP_USER_PATH_MAX];
>  };
> +BTRFS_ASSERT_SIZE(btrfs_ioctl_ino_lookup_args, 4096);
>  
>  /* Search criteria for the btrfs SEARCH ioctl family. */
>  struct btrfs_ioctl_search_key {
> @@ -664,8 +679,9 @@ struct btrfs_ioctl_get_dev_stats {
>  	/* out values: */
>  	__u64 values[BTRFS_DEV_STAT_VALUES_MAX];
>  
> -	__u64 unused[128 - 2 - BTRFS_DEV_STAT_VALUES_MAX]; /* pad to 1k */
> +	__u64 unused[128 - 3 - BTRFS_DEV_STAT_VALUES_MAX]; /* pad to 1k */
>  };
> +BTRFS_ASSERT_SIZE(btrfs_ioctl_get_dev_stats, 1024);
>  
>  #define BTRFS_QUOTA_CTL_ENABLE	1
>  #define BTRFS_QUOTA_CTL_DISABLE	2
> 

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH] btrfs: Introduce compile time structure size check
  2018-07-12  6:27 ` Nikolay Borisov
@ 2018-07-12  6:56   ` Qu Wenruo
  2018-07-13 14:34     ` David Sterba
  0 siblings, 1 reply; 9+ messages in thread
From: Qu Wenruo @ 2018-07-12  6:56 UTC (permalink / raw)
  To: Nikolay Borisov, Qu Wenruo, linux-btrfs



On 2018年07月12日 14:27, Nikolay Borisov wrote:
> 
> 
> On 12.07.2018 09:19, Qu Wenruo wrote:
>> Introduce a new macro based compile time check for ioctl structures.
>>
>> The new macro is BTRFS_ASSERT_SIZE(), which is mostly copied from
>> VMMDEV_ASSERT_SIZE().
>>
>> Such check is only added to structure pended to power of 2.
>> And exposed one structure, btrfs_ioctl_get_dev_stats() is not aligned
>> well.
>> The misalign is introduced by commit b27f7c0c150f ("btrfs: join DEV_STATS
>> ioctls to one").
> 
> So what's the negative effect if a structure is not aligned to a power of 2?

No real negative effect, until one day one may find the comment is not
correct.

Thanks,
Qu

> 
>>
>> Signed-off-by: Qu Wenruo <wqu@suse.com>
>> ---
>>  include/uapi/linux/btrfs.h | 18 +++++++++++++++++-
>>  1 file changed, 17 insertions(+), 1 deletion(-)
>>
>> diff --git a/include/uapi/linux/btrfs.h b/include/uapi/linux/btrfs.h
>> index 5ca1d21fc4a7..be1213c10080 100644
>> --- a/include/uapi/linux/btrfs.h
>> +++ b/include/uapi/linux/btrfs.h
>> @@ -22,6 +22,14 @@
>>  #include <linux/types.h>
>>  #include <linux/ioctl.h>
>>  
>> +/*
>> + * Compile time check on structure size, same method as
>> + * VMMDEV_ASSERT_SIZE() from linux/vbox_vmmdev_types.h, to trigger a negative
>> + * array size at compile time if size doesn't match.
>> + */
>> +#define BTRFS_ASSERT_SIZE(type, size) \
>> +	typedef char type ## _asrt_size[1 - 2 * !!(sizeof(struct type) != (size))]
>> +
>>  #define BTRFS_IOCTL_MAGIC 0x94
>>  #define BTRFS_VOL_NAME_MAX 255
>>  #define BTRFS_LABEL_SIZE 256
>> @@ -32,6 +40,7 @@ struct btrfs_ioctl_vol_args {
>>  	__s64 fd;
>>  	char name[BTRFS_PATH_NAME_MAX + 1];
>>  };
>> +BTRFS_ASSERT_SIZE(btrfs_ioctl_vol_args, 4096);
>>  
>>  #define BTRFS_DEVICE_PATH_NAME_MAX	1024
>>  #define BTRFS_SUBVOL_NAME_MAX 		4039
>> @@ -171,6 +180,7 @@ struct btrfs_ioctl_scrub_args {
>>  	/* pad to 1k */
>>  	__u64 unused[(1024-32-sizeof(struct btrfs_scrub_progress))/8];
>>  };
>> +BTRFS_ASSERT_SIZE(btrfs_ioctl_scrub_args, 1024);
>>  
>>  #define BTRFS_IOCTL_DEV_REPLACE_CONT_READING_FROM_SRCDEV_MODE_ALWAYS	0
>>  #define BTRFS_IOCTL_DEV_REPLACE_CONT_READING_FROM_SRCDEV_MODE_AVOID	1
>> @@ -223,6 +233,7 @@ struct btrfs_ioctl_dev_info_args {
>>  	__u64 unused[379];			/* pad to 4k */
>>  	__u8 path[BTRFS_DEVICE_PATH_NAME_MAX];	/* out */
>>  };
>> +BTRFS_ASSERT_SIZE(btrfs_ioctl_dev_info_args, 4096);
>>  
>>  struct btrfs_ioctl_fs_info_args {
>>  	__u64 max_id;				/* out */
>> @@ -234,6 +245,7 @@ struct btrfs_ioctl_fs_info_args {
>>  	__u32 reserved32;
>>  	__u64 reserved[122];			/* pad to 1k */
>>  };
>> +BTRFS_ASSERT_SIZE(btrfs_ioctl_fs_info_args, 1024);
>>  
>>  /*
>>   * feature flags
>> @@ -414,6 +426,7 @@ struct btrfs_ioctl_balance_args {
>>  
>>  	__u64 unused[72];			/* pad to 1k */
>>  };
>> +BTRFS_ASSERT_SIZE(btrfs_ioctl_balance_args, 1024);
>>  
>>  #define BTRFS_INO_LOOKUP_PATH_MAX 4080
>>  struct btrfs_ioctl_ino_lookup_args {
>> @@ -421,6 +434,7 @@ struct btrfs_ioctl_ino_lookup_args {
>>  	__u64 objectid;
>>  	char name[BTRFS_INO_LOOKUP_PATH_MAX];
>>  };
>> +BTRFS_ASSERT_SIZE(btrfs_ioctl_ino_lookup_args, 4096);
>>  
>>  #define BTRFS_INO_LOOKUP_USER_PATH_MAX (4080 - BTRFS_VOL_NAME_MAX - 1)
>>  struct btrfs_ioctl_ino_lookup_user_args {
>> @@ -436,6 +450,7 @@ struct btrfs_ioctl_ino_lookup_user_args {
>>  	 */
>>  	char path[BTRFS_INO_LOOKUP_USER_PATH_MAX];
>>  };
>> +BTRFS_ASSERT_SIZE(btrfs_ioctl_ino_lookup_args, 4096);
>>  
>>  /* Search criteria for the btrfs SEARCH ioctl family. */
>>  struct btrfs_ioctl_search_key {
>> @@ -664,8 +679,9 @@ struct btrfs_ioctl_get_dev_stats {
>>  	/* out values: */
>>  	__u64 values[BTRFS_DEV_STAT_VALUES_MAX];
>>  
>> -	__u64 unused[128 - 2 - BTRFS_DEV_STAT_VALUES_MAX]; /* pad to 1k */
>> +	__u64 unused[128 - 3 - BTRFS_DEV_STAT_VALUES_MAX]; /* pad to 1k */
>>  };
>> +BTRFS_ASSERT_SIZE(btrfs_ioctl_get_dev_stats, 1024);
>>  
>>  #define BTRFS_QUOTA_CTL_ENABLE	1
>>  #define BTRFS_QUOTA_CTL_DISABLE	2
>>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH] btrfs: Introduce compile time structure size check
  2018-07-12  6:19 [PATCH] btrfs: Introduce compile time structure size check Qu Wenruo
  2018-07-12  6:27 ` Nikolay Borisov
@ 2018-07-13 14:34 ` David Sterba
  2018-07-13 14:36   ` Qu Wenruo
  1 sibling, 1 reply; 9+ messages in thread
From: David Sterba @ 2018-07-13 14:34 UTC (permalink / raw)
  To: Qu Wenruo; +Cc: linux-btrfs

On Thu, Jul 12, 2018 at 02:19:07PM +0800, Qu Wenruo wrote:
> Introduce a new macro based compile time check for ioctl structures.
> 
> The new macro is BTRFS_ASSERT_SIZE(), which is mostly copied from
> VMMDEV_ASSERT_SIZE().

The macro should be generic, there's nothing specific to btrfs. There's
a similar one in the progs.

> Such check is only added to structure pended to power of 2.

There's no constraint about power of 2 sizes, it works for any size.

> And exposed one structure, btrfs_ioctl_get_dev_stats() is not aligned
> well.
> The misalign is introduced by commit b27f7c0c150f ("btrfs: join DEV_STATS
> ioctls to one").

Yeah, that was an oversight, so the correct value to check against is
1024 + 8 = 1032, see ioctl.h in progs.

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH] btrfs: Introduce compile time structure size check
  2018-07-12  6:56   ` Qu Wenruo
@ 2018-07-13 14:34     ` David Sterba
  0 siblings, 0 replies; 9+ messages in thread
From: David Sterba @ 2018-07-13 14:34 UTC (permalink / raw)
  To: Qu Wenruo; +Cc: Nikolay Borisov, Qu Wenruo, linux-btrfs

On Thu, Jul 12, 2018 at 02:56:55PM +0800, Qu Wenruo wrote:
> 
> 
> On 2018年07月12日 14:27, Nikolay Borisov wrote:
> > 
> > 
> > On 12.07.2018 09:19, Qu Wenruo wrote:
> >> Introduce a new macro based compile time check for ioctl structures.
> >>
> >> The new macro is BTRFS_ASSERT_SIZE(), which is mostly copied from
> >> VMMDEV_ASSERT_SIZE().
> >>
> >> Such check is only added to structure pended to power of 2.
> >> And exposed one structure, btrfs_ioctl_get_dev_stats() is not aligned
> >> well.
> >> The misalign is introduced by commit b27f7c0c150f ("btrfs: join DEV_STATS
> >> ioctls to one").
> > 
> > So what's the negative effect if a structure is not aligned to a power of 2?
> 
> No real negative effect, until one day one may find the comment is not
> correct.

So the comment needs to be fixed.

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH] btrfs: Introduce compile time structure size check
  2018-07-13 14:34 ` David Sterba
@ 2018-07-13 14:36   ` Qu Wenruo
  2018-07-13 14:46     ` David Sterba
  0 siblings, 1 reply; 9+ messages in thread
From: Qu Wenruo @ 2018-07-13 14:36 UTC (permalink / raw)
  To: dsterba, Qu Wenruo, linux-btrfs


[-- Attachment #1.1: Type: text/plain, Size: 1150 bytes --]



On 2018年07月13日 22:34, David Sterba wrote:
> On Thu, Jul 12, 2018 at 02:19:07PM +0800, Qu Wenruo wrote:
>> Introduce a new macro based compile time check for ioctl structures.
>>
>> The new macro is BTRFS_ASSERT_SIZE(), which is mostly copied from
>> VMMDEV_ASSERT_SIZE().
> 
> The macro should be generic, there's nothing specific to btrfs. There's
> a similar one in the progs.
> 
>> Such check is only added to structure pended to power of 2.
> 
> There's no constraint about power of 2 sizes, it works for any size.

While some structure doesn't do padding at all, and it looks like they
may get expanded later.
Do we really need to limit the size right now?

> 
>> And exposed one structure, btrfs_ioctl_get_dev_stats() is not aligned
>> well.
>> The misalign is introduced by commit b27f7c0c150f ("btrfs: join DEV_STATS
>> ioctls to one").
> 
> Yeah, that was an oversight, so the correct value to check against is
> 1024 + 8 = 1032, see ioctl.h in progs.

Can't we just revert to 1024?
That plus 8 doesn't really look well, and shrink the size shouldn't
bring any problem AFAIK.

Thanks,
Qu


> 


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH] btrfs: Introduce compile time structure size check
  2018-07-13 14:36   ` Qu Wenruo
@ 2018-07-13 14:46     ` David Sterba
  2018-07-13 14:57       ` Qu Wenruo
  0 siblings, 1 reply; 9+ messages in thread
From: David Sterba @ 2018-07-13 14:46 UTC (permalink / raw)
  To: Qu Wenruo; +Cc: dsterba, Qu Wenruo, linux-btrfs

On Fri, Jul 13, 2018 at 10:36:42PM +0800, Qu Wenruo wrote:
> 
> 
> On 2018年07月13日 22:34, David Sterba wrote:
> > On Thu, Jul 12, 2018 at 02:19:07PM +0800, Qu Wenruo wrote:
> >> Introduce a new macro based compile time check for ioctl structures.
> >>
> >> The new macro is BTRFS_ASSERT_SIZE(), which is mostly copied from
> >> VMMDEV_ASSERT_SIZE().
> > 
> > The macro should be generic, there's nothing specific to btrfs. There's
> > a similar one in the progs.
> > 
> >> Such check is only added to structure pended to power of 2.
> > 
> > There's no constraint about power of 2 sizes, it works for any size.
> 
> While some structure doesn't do padding at all, and it looks like they
> may get expanded later.
> Do we really need to limit the size right now?

The size of an ioctl structure is part of kernel<->userspace API and
must not change once public. The ioctl number is calculated using the
structure size.

> >> And exposed one structure, btrfs_ioctl_get_dev_stats() is not aligned
> >> well.
> >> The misalign is introduced by commit b27f7c0c150f ("btrfs: join DEV_STATS
> >> ioctls to one").
> > 
> > Yeah, that was an oversight, so the correct value to check against is
> > 1024 + 8 = 1032, see ioctl.h in progs.
> 
> Can't we just revert to 1024?

Answered by the above, we absolutely cannot change the numbers now.

> That plus 8 doesn't really look well, and shrink the size shouldn't
> bring any problem AFAIK.

See

https://elixir.bootlin.com/linux/latest/source/include/uapi/asm-generic/ioctl.h#L88

for _IOWR definition,

btrfs-progs:ioctl.h

817 #define BTRFS_IOC_GET_DEV_STATS _IOWR(BTRFS_IOCTL_MAGIC, 52, \
818                                       struct btrfs_ioctl_get_dev_stats)

kernel:fs/btrfs/ioctl.c

5914         case BTRFS_IOC_GET_DEV_STATS:
5915                 return btrfs_ioctl_get_dev_stats(fs_info, argp);

The values must match, otherwise dev stats will randomly break on
old/new kernel and progs combinations.

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH] btrfs: Introduce compile time structure size check
  2018-07-13 14:46     ` David Sterba
@ 2018-07-13 14:57       ` Qu Wenruo
  2018-07-13 15:25         ` David Sterba
  0 siblings, 1 reply; 9+ messages in thread
From: Qu Wenruo @ 2018-07-13 14:57 UTC (permalink / raw)
  To: dsterba, Qu Wenruo, Qu Wenruo, linux-btrfs


[-- Attachment #1.1: Type: text/plain, Size: 2712 bytes --]



On 2018年07月13日 22:46, David Sterba wrote:
> On Fri, Jul 13, 2018 at 10:36:42PM +0800, Qu Wenruo wrote:
>>
>>
>> On 2018年07月13日 22:34, David Sterba wrote:
>>> On Thu, Jul 12, 2018 at 02:19:07PM +0800, Qu Wenruo wrote:
>>>> Introduce a new macro based compile time check for ioctl structures.
>>>>
>>>> The new macro is BTRFS_ASSERT_SIZE(), which is mostly copied from
>>>> VMMDEV_ASSERT_SIZE().
>>>
>>> The macro should be generic, there's nothing specific to btrfs. There's
>>> a similar one in the progs.
>>>
>>>> Such check is only added to structure pended to power of 2.
>>>
>>> There's no constraint about power of 2 sizes, it works for any size.
>>
>> While some structure doesn't do padding at all, and it looks like they
>> may get expanded later.
>> Do we really need to limit the size right now?
> 
> The size of an ioctl structure is part of kernel<->userspace API and
> must not change once public. The ioctl number is calculated using the
> structure size.
> 
>>>> And exposed one structure, btrfs_ioctl_get_dev_stats() is not aligned
>>>> well.
>>>> The misalign is introduced by commit b27f7c0c150f ("btrfs: join DEV_STATS
>>>> ioctls to one").
>>>
>>> Yeah, that was an oversight, so the correct value to check against is
>>> 1024 + 8 =032, see ioctl.h in progs.
>>
>> Can't we just revert to 1024?
> 
> Answered by the above, we absolutely cannot change the numbers now.
> 
>> That plus 8 doesn't really look well, and shrink the size shouldn't
>> bring any problem AFAIK.
> 
> See
> 
> https://elixir.bootlin.com/linux/latest/source/include/uapi/asm-generic/ioctl.h#L88
> 
> for _IOWR definition,
> 
> btrfs-progs:ioctl.h
> 
> 817 #define BTRFS_IOC_GET_DEV_STATS _IOWR(BTRFS_IOCTL_MAGIC, 52, \
> 818                                       struct btrfs_ioctl_get_dev_stats)
> 
> kernel:fs/btrfs/ioctl.c
> 
> 5914         case BTRFS_IOC_GET_DEV_STATS:
> 5915                 return btrfs_ioctl_get_dev_stats(fs_info, argp);
> 
> The values must match, otherwise dev stats will randomly break on
> old/new kernel and progs combinations.

Ok, for old kernel and new progs, if that 1024 bytes from progs is
allocated from stack we indeed could screw up user space stack memory.

While for old progs and new kernel it won't cause any problem though.

I'll keep the ugly unaligned number in next version.

But really, we should have such alignment check way before we find the
mismatch.

Thanks,
Qu

> --
> To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH] btrfs: Introduce compile time structure size check
  2018-07-13 14:57       ` Qu Wenruo
@ 2018-07-13 15:25         ` David Sterba
  0 siblings, 0 replies; 9+ messages in thread
From: David Sterba @ 2018-07-13 15:25 UTC (permalink / raw)
  To: Qu Wenruo; +Cc: dsterba, Qu Wenruo, Qu Wenruo, linux-btrfs

On Fri, Jul 13, 2018 at 10:57:07PM +0800, Qu Wenruo wrote:
> 
> 
> On 2018年07月13日 22:46, David Sterba wrote:
> > On Fri, Jul 13, 2018 at 10:36:42PM +0800, Qu Wenruo wrote:
> >>
> >>
> >> On 2018年07月13日 22:34, David Sterba wrote:
> >>> On Thu, Jul 12, 2018 at 02:19:07PM +0800, Qu Wenruo wrote:
> >>>> Introduce a new macro based compile time check for ioctl structures.
> >>>>
> >>>> The new macro is BTRFS_ASSERT_SIZE(), which is mostly copied from
> >>>> VMMDEV_ASSERT_SIZE().
> >>>
> >>> The macro should be generic, there's nothing specific to btrfs. There's
> >>> a similar one in the progs.
> >>>
> >>>> Such check is only added to structure pended to power of 2.
> >>>
> >>> There's no constraint about power of 2 sizes, it works for any size.
> >>
> >> While some structure doesn't do padding at all, and it looks like they
> >> may get expanded later.
> >> Do we really need to limit the size right now?
> > 
> > The size of an ioctl structure is part of kernel<->userspace API and
> > must not change once public. The ioctl number is calculated using the
> > structure size.
> > 
> >>>> And exposed one structure, btrfs_ioctl_get_dev_stats() is not aligned
> >>>> well.
> >>>> The misalign is introduced by commit b27f7c0c150f ("btrfs: join DEV_STATS
> >>>> ioctls to one").
> >>>
> >>> Yeah, that was an oversight, so the correct value to check against is
> >>> 1024 + 8 =032, see ioctl.h in progs.
> >>
> >> Can't we just revert to 1024?
> > 
> > Answered by the above, we absolutely cannot change the numbers now.
> > 
> >> That plus 8 doesn't really look well, and shrink the size shouldn't
> >> bring any problem AFAIK.
> > 
> > See
> > 
> > https://elixir.bootlin.com/linux/latest/source/include/uapi/asm-generic/ioctl.h#L88
> > 
> > for _IOWR definition,
> > 
> > btrfs-progs:ioctl.h
> > 
> > 817 #define BTRFS_IOC_GET_DEV_STATS _IOWR(BTRFS_IOCTL_MAGIC, 52, \
> > 818                                       struct btrfs_ioctl_get_dev_stats)
> > 
> > kernel:fs/btrfs/ioctl.c
> > 
> > 5914         case BTRFS_IOC_GET_DEV_STATS:
> > 5915                 return btrfs_ioctl_get_dev_stats(fs_info, argp);
> > 
> > The values must match, otherwise dev stats will randomly break on
> > old/new kernel and progs combinations.
> 
> Ok, for old kernel and new progs, if that 1024 bytes from progs is
> allocated from stack we indeed could screw up user space stack memory.

The main concern is the ioctl number, but the structure size must match
too of course as it's copied back from kernel.

But the ioctl number is the interface, so the userspace calls
ioctl(NUMBER, ...) that krenel answers by looing up the right handler
for the NUMBER.

If there are two numbers, then patched userspace will get only ENOTTY
which translates to 'no such ioctl'.

> While for old progs and new kernel it won't cause any problem though.
> 
> I'll keep the ugly unaligned number in next version.
> 
> But really, we should have such alignment check way before we find the
> mismatch.

This unfortunatelly escaped during the review, now we have to live with
that but besides that it's not a power of two (which would be arbitrary
as well), I don't se any problem.

We have a worse problem with the send ioctl structure when there's a
pointer that's of different size on 32bit and 64bit so there needs to be
stub ioctls and structures so all the combinations work. Interfaces are
hard.

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2018-07-13 15:40 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2018-07-12  6:19 [PATCH] btrfs: Introduce compile time structure size check Qu Wenruo
2018-07-12  6:27 ` Nikolay Borisov
2018-07-12  6:56   ` Qu Wenruo
2018-07-13 14:34     ` David Sterba
2018-07-13 14:34 ` David Sterba
2018-07-13 14:36   ` Qu Wenruo
2018-07-13 14:46     ` David Sterba
2018-07-13 14:57       ` Qu Wenruo
2018-07-13 15:25         ` David Sterba

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox