<feed xmlns='http://www.w3.org/2005/Atom'>
<title>kernel/linux.git/drivers/md/persistent-data/dm-array.c, branch v7.3-rc1</title>
<subtitle>Linux kernel stable tree (mirror)</subtitle>
<id>https://git.radix-linux.su/kernel/linux.git/atom?h=v7.3-rc1</id>
<link rel='self' href='https://git.radix-linux.su/kernel/linux.git/atom?h=v7.3-rc1'/>
<link rel='alternate' type='text/html' href='https://git.radix-linux.su/kernel/linux.git/'/>
<updated>2026-08-04T08:19:29+00:00</updated>
<entry>
<title>dm array: reject an array block whose value size is not the caller's</title>
<updated>2026-08-04T08:19:29+00:00</updated>
<author>
<name>Bryam Vargas</name>
<email>hexlabsecurity@proton.me</email>
</author>
<published>2026-07-31T22:54:55+00:00</published>
<link rel='alternate' type='text/html' href='https://git.radix-linux.su/kernel/linux.git/commit/?id=4538a287bdf5d0f9a379c678e5262b9f5783f547'/>
<id>urn:sha1:4538a287bdf5d0f9a379c678e5262b9f5783f547</id>
<content type='text'>
array_block_check() can only compare the header against itself, so a block
with value_size 4 and max_entries 1018 is internally consistent and passes.
dm-cache keeps two arrays -- mappings at 8 bytes and hints at 4 -- and the
roots for both live in the superblock. Point the mappings root at a hint
block and __load_mappings() walks it through an info whose value size is 8,
so element_at() strides 8 bytes over 4-byte entries and reaches offset 8160
of a 4096-byte block.

get_ablock() and __shadow_ablock() are the two places that hold the block
and the caller at once. Reject there when the two value sizes disagree.
Arrays only ever read their own blocks, so this fires on crafted metadata
only.

Fixes: 6513c29f44f2 ("dm persistent data: add transactional array")
Suggested-by: Ming-Hung Tsai &lt;mtsai@redhat.com&gt;
Cc: stable@vger.kernel.org
Signed-off-by: Bryam Vargas &lt;hexlabsecurity@proton.me&gt;
Reviewed-by: Ming-Hung Tsai &lt;mtsai@redhat.com&gt;
Signed-off-by: Mikulas Patocka &lt;mpatocka@redhat.com&gt;
</content>
</entry>
<entry>
<title>dm array: validate array block headers on read</title>
<updated>2026-08-04T08:19:19+00:00</updated>
<author>
<name>Bryam Vargas</name>
<email>hexlabsecurity@proton.me</email>
</author>
<published>2026-07-31T22:54:54+00:00</published>
<link rel='alternate' type='text/html' href='https://git.radix-linux.su/kernel/linux.git/commit/?id=2965787723084835b18dfe993cd450ebf5bd4540'/>
<id>urn:sha1:2965787723084835b18dfe993cd450ebf5bd4540</id>
<content type='text'>
array_block_check() validates blocknr and csum and nothing else, while
node_check(), next to it, has bounded the structural fields since both
were written. dm_array_cursor_next() takes its loop bound from the
on-disk nr_entries and element_at() is unguarded pointer arithmetic, so
a count larger than the block holds keeps the cursor in one block while
the index grows past it and the read walks off the dm-bufio buffer --
dm_cache_load_mappings() drives it once per cache block at activation.

Check the header against itself: reject a zero value_size, require
max_entries to equal calc_max_entries() for that value_size and block
size, and require nr_entries to fit. Equality rather than an upper bound,
since a count below the real capacity trips BUG_ON() in fill_ablock() and
trim_ablock(). Metadata dm-array writes satisfies all three.

Fixes: 6513c29f44f2 ("dm persistent data: add transactional array")
Suggested-by: Ming-Hung Tsai &lt;mtsai@redhat.com&gt;
Cc: stable@vger.kernel.org
Signed-off-by: Bryam Vargas &lt;hexlabsecurity@proton.me&gt;
Reviewed-by: Ming-Hung Tsai &lt;mtsai@redhat.com&gt;
Signed-off-by: Mikulas Patocka &lt;mpatocka@redhat.com&gt;
</content>
</entry>
<entry>
<title>dm array: fix cursor index when skipping across block boundaries</title>
<updated>2024-12-13T13:39:18+00:00</updated>
<author>
<name>Ming-Hung Tsai</name>
<email>mtsai@redhat.com</email>
</author>
<published>2024-12-05T11:41:53+00:00</published>
<link rel='alternate' type='text/html' href='https://git.radix-linux.su/kernel/linux.git/commit/?id=0bb1968da2737ba68fd63857d1af2b301a18d3bf'/>
<id>urn:sha1:0bb1968da2737ba68fd63857d1af2b301a18d3bf</id>
<content type='text'>
dm_array_cursor_skip() seeks to the target position by loading array
blocks iteratively until the specified number of entries to skip is
reached. When seeking across block boundaries, it uses
dm_array_cursor_next() to step into the next block.
dm_array_cursor_skip() must first move the cursor index to the end
of the current block; otherwise, the cursor position could incorrectly
remain in the same block, causing the actual number of skipped entries
to be much smaller than expected.

This bug affects cache resizing in v2 metadata and could lead to data
loss if the fast device is shrunk during the first-time resume. For
example:

1. create a cache metadata consists of 32768 blocks, with a dirty block
   assigned to the second bitmap block. cache_restore v1.0 is required.

cat &lt;&lt;EOF &gt;&gt; cmeta.xml
&lt;superblock uuid="" block_size="64" nr_cache_blocks="32768" \
policy="smq" hint_width="4"&gt;
  &lt;mappings&gt;
    &lt;mapping cache_block="32767" origin_block="0" dirty="true"/&gt;
  &lt;/mappings&gt;
&lt;/superblock&gt;
EOF
dmsetup create cmeta --table "0 8192 linear /dev/sdc 0"
cache_restore -i cmeta.xml -o /dev/mapper/cmeta --metadata-version=2

2. bring up the cache while attempt to discard all the blocks belonging
   to the second bitmap block (block# 32576 to 32767). The last command
   is expected to fail, but it actually succeeds.

dmsetup create cdata --table "0 2084864 linear /dev/sdc 8192"
dmsetup create corig --table "0 65536 linear /dev/sdc 2105344"
dmsetup create cache --table "0 65536 cache /dev/mapper/cmeta \
/dev/mapper/cdata /dev/mapper/corig 64 2 metadata2 writeback smq \
2 migration_threshold 0"

In addition to the reproducer described above, this fix can be
verified using the "array_cursor/skip" tests in dm-unit:
  dm-unit run /pdata/array_cursor/skip/ --kernel-dir &lt;KERNEL_DIR&gt;

Signed-off-by: Ming-Hung Tsai &lt;mtsai@redhat.com&gt;
Fixes: 9b696229aa7d ("dm persistent data: add cursor skip functions to the cursor APIs")
Reviewed-by: Joe Thornber &lt;thornber@redhat.com&gt;
Signed-off-by: Mike Snitzer &lt;snitzer@kernel.org&gt;
</content>
</entry>
<entry>
<title>dm array: fix unreleased btree blocks on closing a faulty array cursor</title>
<updated>2024-12-13T13:37:39+00:00</updated>
<author>
<name>Ming-Hung Tsai</name>
<email>mtsai@redhat.com</email>
</author>
<published>2024-12-05T11:41:52+00:00</published>
<link rel='alternate' type='text/html' href='https://git.radix-linux.su/kernel/linux.git/commit/?id=626f128ee9c4133b1cfce4be2b34a1508949370e'/>
<id>urn:sha1:626f128ee9c4133b1cfce4be2b34a1508949370e</id>
<content type='text'>
The cached block pointer in dm_array_cursor might be NULL if it reaches
an unreadable array block, or the array is empty. Therefore,
dm_array_cursor_end() should call dm_btree_cursor_end() unconditionally,
to prevent leaving unreleased btree blocks.

This fix can be verified using the "array_cursor/iterate/empty" test
in dm-unit:
  dm-unit run /pdata/array_cursor/iterate/empty --kernel-dir &lt;KERNEL_DIR&gt;

Signed-off-by: Ming-Hung Tsai &lt;mtsai@redhat.com&gt;
Fixes: fdd1315aa5f0 ("dm array: introduce cursor api")
Reviewed-by: Joe Thornber &lt;thornber@redhat.com&gt;
Signed-off-by: Mike Snitzer &lt;snitzer@kernel.org&gt;
</content>
</entry>
<entry>
<title>dm array: fix releasing a faulty array block twice in dm_array_cursor_end</title>
<updated>2024-12-13T13:33:38+00:00</updated>
<author>
<name>Ming-Hung Tsai</name>
<email>mtsai@redhat.com</email>
</author>
<published>2024-12-05T11:41:51+00:00</published>
<link rel='alternate' type='text/html' href='https://git.radix-linux.su/kernel/linux.git/commit/?id=f2893c0804d86230ffb8f1c8703fdbb18648abc8'/>
<id>urn:sha1:f2893c0804d86230ffb8f1c8703fdbb18648abc8</id>
<content type='text'>
When dm_bm_read_lock() fails due to locking or checksum errors, it
releases the faulty block implicitly while leaving an invalid output
pointer behind. The caller of dm_bm_read_lock() should not operate on
this invalid dm_block pointer, or it will lead to undefined result.
For example, the dm_array_cursor incorrectly caches the invalid pointer
on reading a faulty array block, causing a double release in
dm_array_cursor_end(), then hitting the BUG_ON in dm-bufio cache_put().

Reproduce steps:

1. initialize a cache device

dmsetup create cmeta --table "0 8192 linear /dev/sdc 0"
dmsetup create cdata --table "0 65536 linear /dev/sdc 8192"
dmsetup create corig --table "0 524288 linear /dev/sdc $262144"
dd if=/dev/zero of=/dev/mapper/cmeta bs=4k count=1
dmsetup create cache --table "0 524288 cache /dev/mapper/cmeta \
/dev/mapper/cdata /dev/mapper/corig 128 2 metadata2 writethrough smq 0"

2. wipe the second array block offline

dmsteup remove cache cmeta cdata corig
mapping_root=$(dd if=/dev/sdc bs=1c count=8 skip=192 \
2&gt;/dev/null | hexdump -e '1/8 "%u\n"')
ablock=$(dd if=/dev/sdc bs=1c count=8 skip=$((4096*mapping_root+2056)) \
2&gt;/dev/null | hexdump -e '1/8 "%u\n"')
dd if=/dev/zero of=/dev/sdc bs=4k count=1 seek=$ablock

3. try reopen the cache device

dmsetup create cmeta --table "0 8192 linear /dev/sdc 0"
dmsetup create cdata --table "0 65536 linear /dev/sdc 8192"
dmsetup create corig --table "0 524288 linear /dev/sdc $262144"
dmsetup create cache --table "0 524288 cache /dev/mapper/cmeta \
/dev/mapper/cdata /dev/mapper/corig 128 2 metadata2 writethrough smq 0"

Kernel logs:

(snip)
device-mapper: array: array_block_check failed: blocknr 0 != wanted 10
device-mapper: block manager: array validator check failed for block 10
device-mapper: array: get_ablock failed
device-mapper: cache metadata: dm_array_cursor_next for mapping failed
------------[ cut here ]------------
kernel BUG at drivers/md/dm-bufio.c:638!

Fix by setting the cached block pointer to NULL on errors.

In addition to the reproducer described above, this fix can be
verified using the "array_cursor/damaged" test in dm-unit:
  dm-unit run /pdata/array_cursor/damaged --kernel-dir &lt;KERNEL_DIR&gt;

Signed-off-by: Ming-Hung Tsai &lt;mtsai@redhat.com&gt;
Fixes: fdd1315aa5f0 ("dm array: introduce cursor api")
Reviewed-by: Joe Thornber &lt;thornber@redhat.com&gt;
Signed-off-by: Mike Snitzer &lt;snitzer@kernel.org&gt;
</content>
</entry>
<entry>
<title>dm: Constify struct dm_block_validator</title>
<updated>2024-07-19T10:08:15+00:00</updated>
<author>
<name>Christophe JAILLET</name>
<email>christophe.jaillet@wanadoo.fr</email>
</author>
<published>2024-07-14T07:13:56+00:00</published>
<link rel='alternate' type='text/html' href='https://git.radix-linux.su/kernel/linux.git/commit/?id=0b60be1628e3448fc96e28bde3d0b27e6d8743fc'/>
<id>urn:sha1:0b60be1628e3448fc96e28bde3d0b27e6d8743fc</id>
<content type='text'>
'struct dm_block_validator' are not modified in these drivers.

Constifying this structure moves some data to a read-only section, so
increase overall security.

On a x86_64, with allmodconfig, as an example:

Before:
======
   text	   data	    bss	    dec	    hex	filename
  32047	    920	     16	  32983	   80d7	drivers/md/dm-cache-metadata.o

After:
=====
   text	   data	    bss	    dec	    hex	filename
  32075	    896	     16	  32987	   80db	drivers/md/dm-cache-metadata.o

Signed-off-by: Christophe JAILLET &lt;christophe.jaillet@wanadoo.fr&gt;
Signed-off-by: Mikulas Patocka &lt;mpatocka@redhat.com&gt;
</content>
</entry>
<entry>
<title>dm: add missing blank line after declarations/fix those</title>
<updated>2023-02-14T19:23:07+00:00</updated>
<author>
<name>Heinz Mauelshagen</name>
<email>heinzm@redhat.com</email>
</author>
<published>2023-02-07T19:48:51+00:00</published>
<link rel='alternate' type='text/html' href='https://git.radix-linux.su/kernel/linux.git/commit/?id=b30f1607146c736684c069fe92dc39607d77d15f'/>
<id>urn:sha1:b30f1607146c736684c069fe92dc39607d77d15f</id>
<content type='text'>
Signed-off-by: Heinz Mauelshagen &lt;heinzm@redhat.com&gt;
Signed-off-by: Mike Snitzer &lt;snitzer@kernel.org&gt;
</content>
</entry>
<entry>
<title>dm: prefer '"%s...", __func__'</title>
<updated>2023-02-14T19:23:07+00:00</updated>
<author>
<name>Heinz Mauelshagen</name>
<email>heinzm@redhat.com</email>
</author>
<published>2023-02-06T22:42:32+00:00</published>
<link rel='alternate' type='text/html' href='https://git.radix-linux.su/kernel/linux.git/commit/?id=1c13188669282dac48f1e67d77f07a746a4899d7'/>
<id>urn:sha1:1c13188669282dac48f1e67d77f07a746a4899d7</id>
<content type='text'>
Signed-off-by: Heinz Mauelshagen &lt;heinzm@redhat.com&gt;
Signed-off-by: Mike Snitzer &lt;snitzer@kernel.org&gt;
</content>
</entry>
<entry>
<title>dm: add missing empty lines</title>
<updated>2023-02-14T19:23:06+00:00</updated>
<author>
<name>Heinz Mauelshagen</name>
<email>heinzm@redhat.com</email>
</author>
<published>2023-02-01T22:42:29+00:00</published>
<link rel='alternate' type='text/html' href='https://git.radix-linux.su/kernel/linux.git/commit/?id=0ef0b4717aa6849d251b23ae1efe93ca93af540b'/>
<id>urn:sha1:0ef0b4717aa6849d251b23ae1efe93ca93af540b</id>
<content type='text'>
Signed-off-by: Heinz Mauelshagen &lt;heinzm@redhat.com&gt;
Signed-off-by: Mike Snitzer &lt;snitzer@kernel.org&gt;
</content>
</entry>
<entry>
<title>dm: change "unsigned" to "unsigned int"</title>
<updated>2023-02-14T19:23:06+00:00</updated>
<author>
<name>Heinz Mauelshagen</name>
<email>heinzm@redhat.com</email>
</author>
<published>2023-01-25T20:14:58+00:00</published>
<link rel='alternate' type='text/html' href='https://git.radix-linux.su/kernel/linux.git/commit/?id=86a3238c7b9b759cb864f4f768ab2e24687dc0e6'/>
<id>urn:sha1:86a3238c7b9b759cb864f4f768ab2e24687dc0e6</id>
<content type='text'>
Signed-off-by: Heinz Mauelshagen &lt;heinzm@redhat.com&gt;
Signed-off-by: Mike Snitzer &lt;snitzer@kernel.org&gt;
</content>
</entry>
</feed>
