[PATCH 0/2] drbd: fix netlink string policy lengths, raise cpu-mask limit

Ionut Nechita <[email protected]> Sun, 2 Aug 2026 14:05:50 +0300
Newsgroups dev.linux.lists.drbd-dev,org.kernel.vger.linux-block,org.kernel.vger.linux-kernel
Message-ID <[email protected]>
Patch 1 fixes a regression from the conversion of the DRBD netlink code
away from genl_magic. All NLA_NUL_STRING policies now use the size of
the destination buffer as nla_policy.len, but for NUL strings that field
is the maximum string length excluding the terminating NUL. Every
affected attribute accepts one byte more than fits; nla_strscpy() then
truncates and returns -E2BIG into an unsigned length member, and that
value comes back out as a negative payload length passed to nla_put().
The details are in the patch.

The most realistic way to reach it is a shared secret of exactly
SHARED_SECRET_MAX characters, which is what "openssl rand -hex 32"
produces. Setting one is accepted, and the corruption then happens on
the next privileged status dump rather than at configuration time, so
cause and effect are not obviously related.

Patch 2 raises DRBD_CPU_MASK_SIZE from 32 to 256 so that a cpu-mask
covering more than 112 CPUs can be expressed at all. Userspace already
assumes the larger value.

The order matters: patch 2 on its own would keep the off-by-one and
merely move it from 32 to 256 characters.

For patch 1 I kept the change minimal and restored exactly the bound the
generated code used to emit. Tying each policy to its destination buffer
instead, e.g.

	.len = sizeof_field(struct res_opts, cpu_mask) - 1,

would make the invariant harder to break again, but that is more churn
than a fix during the -rc cycle should carry. I am happy to send it as a
follow-up if you would rather have it that way.

The commit patch 1 fixes first appeared in v7.2-rc1, so there is nothing
to back port to stable.

I found the problem by inspection while looking at the cpu-mask length
limit. There is no user report behind it, and I have not reproduced it
on a live system - I have no DRBD setup here. What I did verify:

  - the boundaries claimed for bitmap_parse(), by extracting the parser
    from lib/bitmap-str.c into a userspace harness: 31 characters
    describe at most 112 CPUs, 255 characters describe 908;
  - that the driver builds on next-20260731, x86_64 defconfig with
    CONFIG_BLK_DEV_DRBD=m, after each patch individually.

One note on patch 2: drbd-utils has carried DRBD_CPU_MASK_SIZE at 256 in
its own copy of these headers since 2023, so this only aligns the kernel
with what userspace already sends. Longer term the ambiguity between the
hex and the list format means a bitmap_parselist() based cpu-mask would
have to be a separate attribute; that is out of scope here.

Based on next-20260731.

Ionut Nechita (2):
  drbd: fix off-by-one in netlink NUL-string policy lengths
  drbd: increase maximum CPU mask size

 drivers/block/drbd/drbd_nl_gen.c | 18 +++++++++---------
 include/uapi/linux/drbd.h        |  7 ++++++-
 2 files changed, 15 insertions(+), 10 deletions(-)

--
2.55.0