From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-wr1-f47.google.com (mail-wr1-f47.google.com [209.85.221.47]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 7ECDB3D7D67 for ; Wed, 24 Jun 2026 14:52:57 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.221.47 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1782312780; cv=none; b=BoaGZA6cRgsSvLbnO2G5FTkC3GRMiR+y2x2/xVXAR75gFpPSfQTPIhKiVaJf7+uL+9zsEsyM1mNpkPI9jmoljHpxBeRJJXDgjaaDfRjZVj+FhiEn+Hm9dEHGpEcQa/clYibYV3EIqM1kuVgpklzADQUo5WctY4vjOdRiRPByETk= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1782312780; c=relaxed/simple; bh=i+1zfmoF6Ni0osWFykDwF6eI1O/z6HU8tXuesOETdq4=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=FGuUeeHDN/z7O2VBBazS90fwQBINq18iW1rRiG4c98EPeVoV/0y6a4xhR1bnmCWsAE31s/87zCOVW29xGi8jVMpXJAfhAeJw9XkgTpgEHtFsqy2A37dOFEf5ikZvBdB0L11ESY1E7RqOER24t6vhAdKLtZSQlzzqN7MkZn5j97g= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=f63sDwJS; arc=none smtp.client-ip=209.85.221.47 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="f63sDwJS" Received: by mail-wr1-f47.google.com with SMTP id ffacd0b85a97d-461edb387ddso1322177f8f.3 for ; Wed, 24 Jun 2026 07:52:57 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1782312776; x=1782917576; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=lEW+ehp8fdxrw4rnlcdItkyNhL9TC1RVDN+JA5R/x0E=; b=f63sDwJSkoG6dpphemIf2rfqh3q6QFQUsZGsEc4Heq6BFnlOgmOCc6Q2VuMT/2weF7 ojk9YKbpoTGfC36nBLaOqO/P+5gKCFLhjkI4v8Yn1nYEeBQpfkuf4Gk41U2I5kyu4mFL yujPmh4dwQwzJJ9VEWogLwRbt5txCaNFEuANj4HohWG9ype+unQJ/jBfF0q39/+P7JMU zzk02Vcq/eDBAXpgPR5OR2WB9OXW+rVwvRrzf8/Xk6UZ1zPb9lKmqAx/IfTSeDSXA0zL i/4YexwLlxWBdLVLItljzQMu2EJdPxrdZ8LFpNCSmnY+O2e0831PXoFrl3H1i8asgiI1 v9Tg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1782312776; x=1782917576; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=lEW+ehp8fdxrw4rnlcdItkyNhL9TC1RVDN+JA5R/x0E=; b=cigDmy0eEInW6smwEu9W/B1ey5me5yFoJlL5ot/s0FEXk+UuvYyzx4qXDw7WKM4SCm cqarxqrK8ZBoPnGGa7s7jLntasBybnAP319AlOq38hyZ6fVk5CSaYe4PW8AZF4JdazXy 1gtqBCEvxdoVWWYgVO4wyCOjZdFFRvlJa6D90ym/l7/ZCpvRex3hvH6Mx05Jgsfo7nxX kT1ZuY1kdnkBW5LycHQoBaz7XAeALjmse9vW0m371kttkILIQ30ek77H77sBOwNklYeY SLCEps7x7PN5FZ/rchRoJaU83OqCR5XI3SFZ4urTZiKu7HXlxmxXrL/slxZ4zVbXJgHu 9b7w== X-Forwarded-Encrypted: i=1; AFNElJ/awuAiVVX0ESnpJvI6r0+mFSWFchXxy8OkgCTbX/oEXbZ0ImmzWUeqh5pH+fzbosehxOhv0ZqLxwN3axM=@vger.kernel.org X-Gm-Message-State: AOJu0Yx7eG0zvxwBKDY1MpCMm9BqGjEpkjbRNHfy7PJVwJDnKleszCnq 4XnGDktQdfP2Eakf0bfORYh82sr/RBkkpkLjojtYlTM/6NeUnzplVFB6 X-Gm-Gg: AfdE7cmDrsb22bTlBaYIch6mNbiBQncjlsbzkaiwqISxBSUom/0XhpCAMTqUGpe7a+F PUlUBaU1HIAbGGTQDYWjQ3J90K5Lgq2pUKiQtpBJErpyKsUwohrE2JJAxqq2DBUokVWHBdiVrrD 8QcvMWRcl6QOfwTqDGncngXYNn1EhoUE3cbbfWo4Twigs/HQIc39838SG02mXcZkms0jVUURIiE bhcODGmWxAV1Aa5K2bfLZaA/Dw73BjFP+4s3B2O1yv+6RiRj0qJL+qdu3q6QJ3zynUA5/Zb55sT khMXNn8ceAHoh5abLDfaqjgJrz6u21JUA66gmCjvogzW3TpgM0VffKDyivmwsxh61j774GmC+qf 12jZyYCqWrSoYZVfLd97d42zrfiuK/W0Ev9qvatxblm4BiUyl9UAQmyJQrRBf43JwlvBAqn/jee bj+BDi3DN20Y67N2JkGLSWsbzGmDSwcqKWQ10aHzwfvlbDddkeFRM4Ax8tDHp9cx1T9++Q7w== X-Received: by 2002:a05:600d:8489:10b0:492:4161:ae9d with SMTP id 5b1f17b1804b1-49260849b3bmr43023205e9.8.1782312775542; Wed, 24 Jun 2026 07:52:55 -0700 (PDT) Received: from snowdrop.snailnet.com (82-69-66-36.dsl.in-addr.zen.co.uk. [82.69.66.36]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-4924923392dsm735988005e9.2.2026.06.24.07.52.55 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 24 Jun 2026 07:52:55 -0700 (PDT) From: David Laight To: Mikulas Patocka , Tony Asleson , "Bryn M . Reeves" , Alasdair Kergon , Mike Snitzer , Benjamin Marzinski , dm-devel@lists.linux.dev, linux-kernel@vger.kernel.org Cc: David Laight Subject: [PATCH 2/3] dm: list_devices(): Only process devices once Date: Wed, 24 Jun 2026 15:52:42 +0100 Message-Id: <20260624145243.2736-3-david.laight.linux@gmail.com> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20260624145243.2736-1-david.laight.linux@gmail.com> References: <20260624145243.2736-1-david.laight.linux@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Instead of doing a prescan to determine the length of buffer required, checking the supplied buffer is big enough, and then doing a second scan to fill the output buffer just do a single scan and detect when the buffer is too short. For additional safety only call strlen() once and use the returned length for everything (incuding the copy). Ensure than all the pad bytes between the entries are zero. Signed-off-by: David Laight --- drivers/md/dm-ioctl.c | 87 ++++++++++++++++++++----------------------- 1 file changed, 40 insertions(+), 47 deletions(-) diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c index 6234cb8b86b7..57cfbc12c0ce 100644 --- a/drivers/md/dm-ioctl.c +++ b/drivers/md/dm-ioctl.c @@ -605,79 +605,72 @@ static int list_devices(struct file *filp, struct dm_ioctl *param, size_t param_ { struct rb_node *n; struct hash_cell *hc; - size_t len, needed = 0; - struct gendisk *disk; - struct dm_name_list *orig_nl, *nl, *old_nl = NULL; + size_t len; + struct dm_name_list *nl, *old_nl = NULL; + void *result_start, *result_limit; uint32_t *event_nr; - down_write(&_hash_lock); - - /* - * Loop through all the devices working out how much - * space we need. - */ - for (n = rb_first(&name_rb_tree); n; n = rb_next(n)) { - hc = container_of(n, struct hash_cell, name_node); - if (!filter_device(hc, param->name, param->uuid)) - continue; - needed += align_val(offsetof(struct dm_name_list, name) + strlen(hc->name) + 1); - needed += align_val(sizeof(uint32_t) * 2); - if (param->flags & DM_UUID_FLAG && hc->uuid) - needed += align_val(strlen(hc->uuid) + 1); - } - /* * Grab our output buffer. */ - nl = orig_nl = get_result_buffer(param, param_size, &len); - if (len < needed || len < sizeof(nl->dev)) { - param->flags |= DM_BUFFER_FULL_FLAG; - goto out; - } - param->data_size = param->data_start + needed; + nl = result_start = get_result_buffer(param, param_size, &len); + result_limit = result_start + len; - nl->dev = 0; /* Flags no data */ + if (len >= sizeof(*nl)) + nl->dev = 0; /* Flags no data */ + + down_write(&_hash_lock); /* - * Now loop through filling out the names. + * Loop through filling out the names. */ for (n = rb_first(&name_rb_tree); n; n = rb_next(n)) { - void *uuid_ptr; + void *next_nl; hc = container_of(n, struct hash_cell, name_node); if (!filter_device(hc, param->name, param->uuid)) continue; - if (old_nl) - old_nl->next = (uint32_t) ((void *) nl - - (void *) old_nl); - disk = dm_disk(hc->md); - nl->dev = huge_encode_dev(disk_devt(disk)); - nl->next = 0; - strcpy(nl->name, hc->name); - old_nl = nl; - event_nr = align_ptr(nl->name + strlen(hc->name) + 1); + len = strlen(hc->name); + event_nr = align_ptr(nl->name + len + 1); + next_nl = event_nr + 2; + if (next_nl > result_limit) + break; + + ((u64 *)event_nr)[-1] = 0; + memcpy(nl->name, hc->name, len); + + nl->dev = huge_encode_dev(disk_devt(dm_disk(hc->md))); + event_nr[0] = dm_get_event_nr(hc->md); event_nr[1] = 0; - uuid_ptr = align_ptr(event_nr + 2); + if (param->flags & DM_UUID_FLAG) { if (hc->uuid) { + len = strlen(hc->uuid); + next_nl = align_ptr(next_nl + len + 1); + if (next_nl > result_limit) + break; event_nr[1] |= DM_NAME_LIST_FLAG_HAS_UUID; - strcpy(uuid_ptr, hc->uuid); - uuid_ptr = align_ptr(uuid_ptr + strlen(hc->uuid) + 1); + ((u64 *)next_nl)[-1] = 0; + memcpy(event_nr + 2, hc->uuid, len); } else { event_nr[1] |= DM_NAME_LIST_FLAG_DOESNT_HAVE_UUID; } } - nl = uuid_ptr; + nl->next = next_nl - (void *)nl; + old_nl = nl; + nl = next_nl; } - /* - * If mismatch happens, security may be compromised due to buffer - * overflow, so it's better to crash. - */ - BUG_ON((char *)nl - (char *)orig_nl != needed); - out: + if (old_nl) + old_nl->next = 0; + + if (n) + param->flags |= DM_BUFFER_FULL_FLAG; + else + param->data_size = param->data_start + ((void *)nl - result_start); + up_write(&_hash_lock); return 0; } -- 2.39.5