2022-11-21 03:01:28

by Zhen Lei

[permalink] [raw]
Subject: [PATCH v2 0/2] fs: clear a UBSAN shift-out-of-bounds warning

v1 -- > v2:
1. Replace INT_LIMIT(loff_t) with OFFSET_MAX in btrfs.
2. Replace INT_LIMIT() with type_max().

Zhen Lei (2):
btrfs: replace INT_LIMIT(loff_t) with OFFSET_MAX
fs: clear a UBSAN shift-out-of-bounds warning

fs/btrfs/ordered-data.c | 6 +++---
include/linux/fs.h | 5 ++---
2 files changed, 5 insertions(+), 6 deletions(-)

--
2.25.1



2022-11-21 03:12:18

by Zhen Lei

[permalink] [raw]
Subject: [PATCH v2 1/2] btrfs: replace INT_LIMIT(loff_t) with OFFSET_MAX

OFFSET_MAX is self-annotated and more readable.

Signed-off-by: Zhen Lei <[email protected]>
---
fs/btrfs/ordered-data.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/fs/btrfs/ordered-data.c b/fs/btrfs/ordered-data.c
index e54f8280031fa14..100d9f4836b177d 100644
--- a/fs/btrfs/ordered-data.c
+++ b/fs/btrfs/ordered-data.c
@@ -761,11 +761,11 @@ int btrfs_wait_ordered_range(struct inode *inode, u64 start, u64 len)
struct btrfs_ordered_extent *ordered;

if (start + len < start) {
- orig_end = INT_LIMIT(loff_t);
+ orig_end = OFFSET_MAX;
} else {
orig_end = start + len - 1;
- if (orig_end > INT_LIMIT(loff_t))
- orig_end = INT_LIMIT(loff_t);
+ if (orig_end > OFFSET_MAX)
+ orig_end = OFFSET_MAX;
}

/* start IO across the range first to instantiate any delalloc
--
2.25.1


2022-11-21 03:16:02

by Zhen Lei

[permalink] [raw]
Subject: [PATCH v2 2/2] fs: clear a UBSAN shift-out-of-bounds warning

UBSAN: shift-out-of-bounds in fs/locks.c:2572:16
left shift of 1 by 63 places cannot be represented in type 'long long int'

Switch the calculation method to type_max() can help us eliminate this
false positive.

On the other hand, the old implementation has problems with char and
short types, although not currently involved.
printf("%d: %x\n", sizeof(char), INT_LIMIT(char));
printf("%d: %x\n", sizeof(short), INT_LIMIT(short));
1: ffffff7f
2: ffff7fff

Suggested-by: Eric Biggers <[email protected]>
Signed-off-by: Zhen Lei <[email protected]>
---
include/linux/fs.h | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/include/linux/fs.h b/include/linux/fs.h
index e654435f16512c1..a384741b1449457 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1131,9 +1131,8 @@ struct file_lock_context {

/* The following constant reflects the upper bound of the file/locking space */
#ifndef OFFSET_MAX
-#define INT_LIMIT(x) (~((x)1 << (sizeof(x)*8 - 1)))
-#define OFFSET_MAX INT_LIMIT(loff_t)
-#define OFFT_OFFSET_MAX INT_LIMIT(off_t)
+#define OFFSET_MAX type_max(loff_t)
+#define OFFT_OFFSET_MAX type_max(off_t)
#endif

extern void send_sigio(struct fown_struct *fown, int fd, int band);
--
2.25.1


2022-11-21 17:49:40

by David Sterba

[permalink] [raw]
Subject: Re: [PATCH v2 1/2] btrfs: replace INT_LIMIT(loff_t) with OFFSET_MAX

On Mon, Nov 21, 2022 at 10:44:17AM +0800, Zhen Lei wrote:
> OFFSET_MAX is self-annotated and more readable.
>
> Signed-off-by: Zhen Lei <[email protected]>

Acked-by: David Sterba <[email protected]>

2022-11-21 20:38:01

by Eric Biggers

[permalink] [raw]
Subject: Re: [PATCH v2 2/2] fs: clear a UBSAN shift-out-of-bounds warning

On Mon, Nov 21, 2022 at 10:44:18AM +0800, Zhen Lei wrote:
> UBSAN: shift-out-of-bounds in fs/locks.c:2572:16
> left shift of 1 by 63 places cannot be represented in type 'long long int'
>
> Switch the calculation method to type_max() can help us eliminate this
> false positive.
>
> On the other hand, the old implementation has problems with char and
> short types, although not currently involved.
> printf("%d: %x\n", sizeof(char), INT_LIMIT(char));
> printf("%d: %x\n", sizeof(short), INT_LIMIT(short));
> 1: ffffff7f
> 2: ffff7fff
>
> Suggested-by: Eric Biggers <[email protected]>
> Signed-off-by: Zhen Lei <[email protected]>
> ---
> include/linux/fs.h | 5 ++---
> 1 file changed, 2 insertions(+), 3 deletions(-)
>
> diff --git a/include/linux/fs.h b/include/linux/fs.h
> index e654435f16512c1..a384741b1449457 100644
> --- a/include/linux/fs.h
> +++ b/include/linux/fs.h
> @@ -1131,9 +1131,8 @@ struct file_lock_context {
>
> /* The following constant reflects the upper bound of the file/locking space */
> #ifndef OFFSET_MAX
> -#define INT_LIMIT(x) (~((x)1 << (sizeof(x)*8 - 1)))
> -#define OFFSET_MAX INT_LIMIT(loff_t)
> -#define OFFT_OFFSET_MAX INT_LIMIT(off_t)
> +#define OFFSET_MAX type_max(loff_t)
> +#define OFFT_OFFSET_MAX type_max(off_t)
> #endif
>
> extern void send_sigio(struct fown_struct *fown, int fd, int band);
> --

Reviewed-by: Eric Biggers <[email protected]>

- Eric

2022-11-21 20:39:14

by Eric Biggers

[permalink] [raw]
Subject: Re: [PATCH v2 1/2] btrfs: replace INT_LIMIT(loff_t) with OFFSET_MAX

On Mon, Nov 21, 2022 at 10:44:17AM +0800, Zhen Lei wrote:
> OFFSET_MAX is self-annotated and more readable.
>
> Signed-off-by: Zhen Lei <[email protected]>
> ---
> fs/btrfs/ordered-data.c | 6 +++---
> 1 file changed, 3 insertions(+), 3 deletions(-)
>
> diff --git a/fs/btrfs/ordered-data.c b/fs/btrfs/ordered-data.c
> index e54f8280031fa14..100d9f4836b177d 100644
> --- a/fs/btrfs/ordered-data.c
> +++ b/fs/btrfs/ordered-data.c
> @@ -761,11 +761,11 @@ int btrfs_wait_ordered_range(struct inode *inode, u64 start, u64 len)
> struct btrfs_ordered_extent *ordered;
>
> if (start + len < start) {
> - orig_end = INT_LIMIT(loff_t);
> + orig_end = OFFSET_MAX;
> } else {
> orig_end = start + len - 1;
> - if (orig_end > INT_LIMIT(loff_t))
> - orig_end = INT_LIMIT(loff_t);
> + if (orig_end > OFFSET_MAX)
> + orig_end = OFFSET_MAX;
> }
>
> /* start IO across the range first to instantiate any delalloc
> --

Reviewed-by: Eric Biggers <[email protected]>

- Eric

2022-11-25 07:04:22

by Al Viro

[permalink] [raw]
Subject: Re: [PATCH v2 0/2] fs: clear a UBSAN shift-out-of-bounds warning

On Mon, Nov 21, 2022 at 10:44:16AM +0800, Zhen Lei wrote:
> v1 -- > v2:
> 1. Replace INT_LIMIT(loff_t) with OFFSET_MAX in btrfs.
> 2. Replace INT_LIMIT() with type_max().

Looks fine, except that I'd rather go for commit message
along the lines of "INT_LIMIT tries to do what type_max does,
except that type_max doesn't rely upon undefined behaviour;
might as well use type_max() instead"

If you want to credit UBSAN - sure, no problem, just don't
clutter the commit message with that. As it is, it reads
as "make $TOOL STFU"...

2022-11-25 08:44:12

by Zhen Lei

[permalink] [raw]
Subject: Re: [PATCH v2 0/2] fs: clear a UBSAN shift-out-of-bounds warning



On 2022/11/25 14:43, Al Viro wrote:
> On Mon, Nov 21, 2022 at 10:44:16AM +0800, Zhen Lei wrote:
>> v1 -- > v2:
>> 1. Replace INT_LIMIT(loff_t) with OFFSET_MAX in btrfs.
>> 2. Replace INT_LIMIT() with type_max().
>
> Looks fine, except that I'd rather go for commit message
> along the lines of "INT_LIMIT tries to do what type_max does,
> except that type_max doesn't rely upon undefined behaviour;
> might as well use type_max() instead"

Very good. Do I send v3, or do you update it?

>
> If you want to credit UBSAN - sure, no problem, just don't
> clutter the commit message with that. As it is, it reads
> as "make $TOOL STFU"...

Okay, I'll pay attention next time. This USBAN problem is relatively
simple and can be located without relying on other information, so I
omitted the rest.

After changing to your suggested description, it seems that there is
no need to mention UBSAN, after all, it is just a false positive and
there is no real problem.

>
> .
>

--
Regards,
Zhen Lei