[PATCH RESEND 0/1] ocfs2: fix reflink preserve cleanup issue

Heming Zhao posted 1 patch 1 month, 4 weeks ago
fs/ocfs2/xattr.c | 4 ++++
1 file changed, 4 insertions(+)
[PATCH RESEND 0/1] ocfs2: fix reflink preserve cleanup issue
Posted by Heming Zhao 1 month, 4 weeks ago
why resend?
I pasted incorrect ocfs2-tools test cases.
(only modified the cover-letter; no code changes)
-----

Linus and Andrew are busy, so I don't include them in the patch review phase.
This patch continues Linus's job to fix the remaining issue in the reflink
preserve path.

The patch passed the following tests.

from xfstests:

```
./check -g quick -T -b -s ocfs2 -e generic/032 -e generic/076 \
-e generic/081 -e generic/266 -e generic/272 -e generic/281 \
-e generic/331 -e generic/338 -e generic/347 -e generic/361 \
-e generic/479 -e generic/480 -e generic/628 -e generic/629 \
-e generic/648 -e generic/650
```


from ocfs2-test:

```
single_run-WIP.sh -f 1 -k /usr/local/ocfs2-test/tmp/linux-2.6.39.tar.gz -l /usr/local/ocfs2-test/log -m /mnt/ocfs2 -d /dev/vde -b 4096 -c 32768 -s pcmk -n hacluster -t inline,xattr,reflink

discontig_runner.sh -f 1 -d /dev/vde -b 4096 -c 32768 -s pcmk -n hacluster /mnt/ocfs2
```

special test:
(reflink command is from ocfs2-tools)

```
## this case will leave one entry after cleanup job
## create file
cp /usr/bin/basename /mnt/ocfs2/a0
## set OCFS2_XATTR_INDEX_POSIX_ACL_ACCESS
setfacl -m u:ocfs2test:rwx /mnt/ocfs2/a0
## check, will output: "user:ocfs2test:rwx"
getfacl /mnt/ocfs2/a0
## set OCFS2_XATTR_INDEX_USER, don't trigger cleanup
setfattr -n user.comment -v "tst-xattr" /mnt/ocfs2/a0
## check, will output: "tst-xattr"
getfattr -n user.comment /mnt/ocfs2/a0
## set OCFS2_XATTR_INDEX_SECURITY
setfattr -n security.selinux -v "unconfined_u:object_r:user_home_t:s0" /mnt/ocfs2/a0
## reflink non-preserve
reflink /mnt/ocfs2/a0 /mnt/ocfs2/ra0
## reflink preserve
reflink -p /mnt/ocfs2/a0 /mnt/ocfs2/ra0-p
## check
getfacl /mnt/ocfs2/ra0  # "user:ocfs2test:rwx" non-exist
getfacl /mnt/ocfs2/ra0-p
getfattr -n user.comment /mnt/ocfs2/ra0 # "tst-xattr" exist
getfattr -n user.comment /mnt/ocfs2/ra0-p
getfattr -n security.selinux /mnt/ocfs2/ra0 # no security attr item
getfattr -n security.selinux /mnt/ocfs2/ra0-p


## this case will trigger cleaning up all array entries.
## create file. then set file with OCFS2_XATTR_INDEX_POSIX_ACL_ACCESS and 
## OCFS2_XATTR_INDEX_SECURITY
cp /usr/bin/basename /mnt/ocfs2/b0
setfacl -m u:ocfs2test:rwx /mnt/ocfs2/b0
setfattr -n security.selinux -v "unconfined_u:object_r:user_home_t:s0" /mnt/ocfs2/b0
## reflink non-preserve
reflink /mnt/ocfs2/b0 /mnt/ocfs2/rb0
## reflink preserve
reflink -p /mnt/ocfs2/b0 /mnt/ocfs2/rb0-p
## check
getfacl /mnt/ocfs2/rb0 # "user:ocfs2test:rwx" non-exist
getfacl /mnt/ocfs2/rb0-p
getfattr -n security.selinux /mnt/ocfs2/rb0 # no security attr item
getfattr -n security.selinux /mnt/ocfs2/rb0-p
```


Heming Zhao (1):
  ocfs2: fix reflink preserve cleanup issue

 fs/ocfs2/xattr.c | 4 ++++
 1 file changed, 4 insertions(+)

-- 
2.43.0
Re: [PATCH RESEND 0/1] ocfs2: fix reflink preserve cleanup issue
Posted by Heming Zhao 1 month, 2 weeks ago
ping...

On Wed, Dec 10, 2025 at 09:57:23AM +0800, Heming Zhao wrote:
> why resend?
> I pasted incorrect ocfs2-tools test cases.
> (only modified the cover-letter; no code changes)
> -----
> 
> Linus and Andrew are busy, so I don't include them in the patch review phase.
> This patch continues Linus's job to fix the remaining issue in the reflink
> preserve path.
> 
> The patch passed the following tests.
> 
> from xfstests:
> 
> ```
> ./check -g quick -T -b -s ocfs2 -e generic/032 -e generic/076 \
> -e generic/081 -e generic/266 -e generic/272 -e generic/281 \
> -e generic/331 -e generic/338 -e generic/347 -e generic/361 \
> -e generic/479 -e generic/480 -e generic/628 -e generic/629 \
> -e generic/648 -e generic/650
> ```
> 
> 
> from ocfs2-test:
> 
> ```
> single_run-WIP.sh -f 1 -k /usr/local/ocfs2-test/tmp/linux-2.6.39.tar.gz -l /usr/local/ocfs2-test/log -m /mnt/ocfs2 -d /dev/vde -b 4096 -c 32768 -s pcmk -n hacluster -t inline,xattr,reflink
> 
> discontig_runner.sh -f 1 -d /dev/vde -b 4096 -c 32768 -s pcmk -n hacluster /mnt/ocfs2
> ```
> 
> special test:
> (reflink command is from ocfs2-tools)
> 
> ```
> ## this case will leave one entry after cleanup job
> ## create file
> cp /usr/bin/basename /mnt/ocfs2/a0
> ## set OCFS2_XATTR_INDEX_POSIX_ACL_ACCESS
> setfacl -m u:ocfs2test:rwx /mnt/ocfs2/a0
> ## check, will output: "user:ocfs2test:rwx"
> getfacl /mnt/ocfs2/a0
> ## set OCFS2_XATTR_INDEX_USER, don't trigger cleanup
> setfattr -n user.comment -v "tst-xattr" /mnt/ocfs2/a0
> ## check, will output: "tst-xattr"
> getfattr -n user.comment /mnt/ocfs2/a0
> ## set OCFS2_XATTR_INDEX_SECURITY
> setfattr -n security.selinux -v "unconfined_u:object_r:user_home_t:s0" /mnt/ocfs2/a0
> ## reflink non-preserve
> reflink /mnt/ocfs2/a0 /mnt/ocfs2/ra0
> ## reflink preserve
> reflink -p /mnt/ocfs2/a0 /mnt/ocfs2/ra0-p
> ## check
> getfacl /mnt/ocfs2/ra0  # "user:ocfs2test:rwx" non-exist
> getfacl /mnt/ocfs2/ra0-p
> getfattr -n user.comment /mnt/ocfs2/ra0 # "tst-xattr" exist
> getfattr -n user.comment /mnt/ocfs2/ra0-p
> getfattr -n security.selinux /mnt/ocfs2/ra0 # no security attr item
> getfattr -n security.selinux /mnt/ocfs2/ra0-p
> 
> 
> ## this case will trigger cleaning up all array entries.
> ## create file. then set file with OCFS2_XATTR_INDEX_POSIX_ACL_ACCESS and 
> ## OCFS2_XATTR_INDEX_SECURITY
> cp /usr/bin/basename /mnt/ocfs2/b0
> setfacl -m u:ocfs2test:rwx /mnt/ocfs2/b0
> setfattr -n security.selinux -v "unconfined_u:object_r:user_home_t:s0" /mnt/ocfs2/b0
> ## reflink non-preserve
> reflink /mnt/ocfs2/b0 /mnt/ocfs2/rb0
> ## reflink preserve
> reflink -p /mnt/ocfs2/b0 /mnt/ocfs2/rb0-p
> ## check
> getfacl /mnt/ocfs2/rb0 # "user:ocfs2test:rwx" non-exist
> getfacl /mnt/ocfs2/rb0-p
> getfattr -n security.selinux /mnt/ocfs2/rb0 # no security attr item
> getfattr -n security.selinux /mnt/ocfs2/rb0-p
> ```
> 
> 
> Heming Zhao (1):
>   ocfs2: fix reflink preserve cleanup issue
> 
>  fs/ocfs2/xattr.c | 4 ++++
>  1 file changed, 4 insertions(+)
> 
> -- 
> 2.43.0
>
Re: [PATCH RESEND 0/1] ocfs2: fix reflink preserve cleanup issue
Posted by Andrew Morton 2 weeks, 4 days ago
On Thu, 18 Dec 2025 22:42:12 +0800 Heming Zhao <heming.zhao@suse.com> wrote:

> ping...
> 

yes please ;)  Some review input would be reassuring, thanks.

btw, I forgot to ask: what are the worst-case userspace-visible runtime
effects of this bug?

IOW, is a -stable backport desirable?


From: Heming Zhao <heming.zhao@suse.com>
Subject: ocfs2: fix reflink preserve cleanup issue
Date: Wed, 10 Dec 2025 09:57:24 +0800

commit c06c303832ec ("ocfs2: fix xattr array entry __counted_by error")
doesn't handle all cases and the cleanup job for preserved xattr entries
still has bug:
- the 'last' pointer should be shifted by one unit after cleanup
  an array entry.
- current code logic doesn't cleanup the first entry when xh_count is 1.

Note, commit c06c303832ec is also a bug fix for 0fe9b66c65f3.

Link: https://lkml.kernel.org/r/20251210015725.8409-2-heming.zhao@suse.com
Fixes: 0fe9b66c65f3 ("ocfs2: Add preserve to reflink.")
Signed-off-by: Heming Zhao <heming.zhao@suse.com>
Cc: Mark Fasheh <mark@fasheh.com>
Cc: Joel Becker <jlbec@evilplan.org>
Cc: Junxiao Bi <junxiao.bi@oracle.com>
Cc: Joseph Qi <jiangqi903@gmail.com>
Cc: Changwei Ge <gechangwei@live.cn>
Cc: Jun Piao <piaojun@huawei.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
---

 fs/ocfs2/xattr.c |    4 ++++
 1 file changed, 4 insertions(+)

--- a/fs/ocfs2/xattr.c~ocfs2-fix-reflink-preserve-cleanup-issue
+++ a/fs/ocfs2/xattr.c
@@ -6395,6 +6395,10 @@ static int ocfs2_reflink_xattr_header(ha
 					(void *)last - (void *)xe);
 				memset(last, 0,
 				       sizeof(struct ocfs2_xattr_entry));
+				last = &new_xh->xh_entries[le16_to_cpu(new_xh->xh_count)] - 1;
+			} else {
+				memset(xe, 0, sizeof(struct ocfs2_xattr_entry));
+				last = NULL;
 			}
 
 			/*
_
Re: [PATCH RESEND 0/1] ocfs2: fix reflink preserve cleanup issue
Posted by Heming Zhao 2 weeks, 3 days ago
On Mon, Jan 19, 2026 at 03:53:53PM -0800, Andrew Morton wrote:
> On Thu, 18 Dec 2025 22:42:12 +0800 Heming Zhao <heming.zhao@suse.com> wrote:
> 
> > ping...
> > 
> 
> yes please ;)  Some review input would be reassuring, thanks.
> 
> btw, I forgot to ask: what are the worst-case userspace-visible runtime
> effects of this bug?

The worst-case scenario was fixed in commit c06c303832ec ('ocfs2: fix xattr array
entry __counted_by error'). It resolved an out-of-bounds (OOB) issue that could
have caused the kernel to crash.

In patch commit log, there are two issues:
1> the 'last' pointer should be shifted by one unit after cleanup
   an array entry.
2> current code logic doesn't cleanup the first entry when xh_count is 1.

The following points should be noted:

Regarding <1>: after commit c06c303832ec, the last pointer doesn't shift. The
code always clears the last array element.

Regarding <2>: Since the existing code correctly updates new_xh->xh_count, the
xattrs can still be displayed correctly (shown as empty) even if the first entry
is not cleared, as the logic relies on the count.

> 
> IOW, is a -stable backport desirable?

Yes

- Heming
> 
> 
> From: Heming Zhao <heming.zhao@suse.com>
> Subject: ocfs2: fix reflink preserve cleanup issue
> Date: Wed, 10 Dec 2025 09:57:24 +0800
> 
> commit c06c303832ec ("ocfs2: fix xattr array entry __counted_by error")
> doesn't handle all cases and the cleanup job for preserved xattr entries
> still has bug:
> - the 'last' pointer should be shifted by one unit after cleanup
>   an array entry.
> - current code logic doesn't cleanup the first entry when xh_count is 1.
> 
> Note, commit c06c303832ec is also a bug fix for 0fe9b66c65f3.
> 
> Link: https://lkml.kernel.org/r/20251210015725.8409-2-heming.zhao@suse.com
> Fixes: 0fe9b66c65f3 ("ocfs2: Add preserve to reflink.")
> Signed-off-by: Heming Zhao <heming.zhao@suse.com>
> Cc: Mark Fasheh <mark@fasheh.com>
> Cc: Joel Becker <jlbec@evilplan.org>
> Cc: Junxiao Bi <junxiao.bi@oracle.com>
> Cc: Joseph Qi <jiangqi903@gmail.com>
> Cc: Changwei Ge <gechangwei@live.cn>
> Cc: Jun Piao <piaojun@huawei.com>
> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
> ---
> 
>  fs/ocfs2/xattr.c |    4 ++++
>  1 file changed, 4 insertions(+)
> 
> --- a/fs/ocfs2/xattr.c~ocfs2-fix-reflink-preserve-cleanup-issue
> +++ a/fs/ocfs2/xattr.c
> @@ -6395,6 +6395,10 @@ static int ocfs2_reflink_xattr_header(ha
>  					(void *)last - (void *)xe);
>  				memset(last, 0,
>  				       sizeof(struct ocfs2_xattr_entry));
> +				last = &new_xh->xh_entries[le16_to_cpu(new_xh->xh_count)] - 1;
> +			} else {
> +				memset(xe, 0, sizeof(struct ocfs2_xattr_entry));
> +				last = NULL;
>  			}
>  
>  			/*
> _
>