Linux-NVME Archive on lore.kernel.org
 help / color / mirror / Atom feed
From: bmarzins@redhat.com (Benjamin Marzinski)
Subject: [PATCH 4/4] libmultipath: fix over-long NVME WWIDs
Date: Fri, 14 Jul 2017 17:38:02 -0500	[thread overview]
Message-ID: <20170714223802.GD2940@octiron.msp.redhat.com> (raw)
In-Reply-To: <20170714113209.17177-5-mwilck@suse.com>

ACK, with one small nit below.

-Ben

On Fri, Jul 14, 2017@01:32:09PM +0200, Martin Wilck wrote:
> Fix for NVME wwids looking like this:
> nvme.0000-3163653363666438366239656630386200-4c696e75780000000000000000000000000000000000000000000000000000000000000000000000-00000002
> which are encountered in some combinations of Linux NVME host and target,
> where the 2nd field represents the serial number (SN) and the 3rd the
> model number (MN).
> 
> The device mapper allows map names only up to 128 characters.
> Strip the "00" sequences at the end of the serial and model field,
> they are hex-encoded 0-bytes which are forbidden by the NVME spec
> anyway.
> 
> Signed-off-by: Martin Wilck <mwilck at suse.com>
> ---
>  libmultipath/discovery.c | 79 ++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 79 insertions(+)
> 
> diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c
> index 9951af84..f46b9b17 100644
> --- a/libmultipath/discovery.c
> +++ b/libmultipath/discovery.c
> @@ -1598,6 +1598,82 @@ get_prio (struct path * pp)
>  	return 0;
>  }
>  
> +/*
> + * Mangle string of length *len starting at start
> + * by removing character sequence "00" (hex for a 0 byte),
> + * starting at end, backwards.
> + * Changes the value of *len if characters were removed.
> + * Returns a pointer to the position where "end" was moved to.
> + */
> +static char
> +*skip_zeroes_backward(char* start, int *len, char *end)
> +{
> +	char *p = end;
> +
> +	while (p >= start + 2 && *(p - 1) == '0' && *(p - 2) == '0')
> +		p -= 2;
> +
> +	if (p == end)
> +		return p;
> +
> +	memmove(p, end, start + *len + 1 - end);
> +	*len -= end - p;
> +
> +	return p;
> +}
> +
> +/*
> + * Fix for NVME wwids looking like this:
> + * nvme.0000-3163653363666438366239656630386200-4c696e75780000000000000000000000000000000000000000000000000000000000000000000000-00000002
> + * which are encountered in some combinations of Linux NVME host and target.
> + * The '00' are hex-encoded 0-bytes which are forbidden in the serial (SN)
> + * and model (MN) fields. Discard them.
> + * If a WWID of the above type is found, sets pp->wwid and returns a value > 0.
> + * Otherwise, returns 0.
> + */
> +static int
> +fix_broken_nvme_wwid(struct path *pp, const char *value, int size)
> +{
> +	static const char _nvme[] = "nvme.";
> +	int len, i;
> +	char mangled[256];
> +	char *p;
> +
> +	len = strlen(value);
> +	if (len >= sizeof(mangled) || len + 1 < size)
> +		return 0;

Don't we check (len + 1 < size) before calling this? It seems odd to
return that we can't do anything when in reality, we simply don't need
to do anything.

-Ben

> +
> +	/* Check that value starts with "nvme.%04x-" */
> +	if (memcmp(value, _nvme, sizeof(_nvme) - 1) || value[9] != '-')
> +		return 0;
> +	for (i = 5; i < 9; i++)
> +		if (!isxdigit(value[i]))
> +			return 0;
> +
> +	memcpy(mangled, value, len + 1);
> +
> +	/* search end of "model" part and strip trailing '00' */
> +	p = memrchr(mangled, '-', len);
> +	if (p == NULL)
> +		return 0;
> +
> +	p = skip_zeroes_backward(mangled, &len, p);
> +
> +	/* search end of "serial" part */
> +	p = memrchr(mangled, '-', p - mangled);
> +	if (p == NULL || memrchr(mangled, '-', p - mangled) != mangled + 9)
> +	    /* We expect exactly 3 '-' in the value */
> +		return 0;
> +
> +	p = skip_zeroes_backward(mangled, &len, p);
> +	if (len >= size)
> +		return 0;
> +
> +	memcpy(pp->wwid, mangled, len + 1);
> +	condlog(2, "%s: over-long WWID shortened to %s", pp->dev, pp->wwid);
> +	return len;
> +}
> +
>  static int
>  get_udev_uid(struct path * pp, char *uid_attribute, struct udev_device *udev)
>  {
> @@ -1609,6 +1685,9 @@ get_udev_uid(struct path * pp, char *uid_attribute, struct udev_device *udev)
>  		value = getenv(uid_attribute);
>  	if (value && strlen(value)) {
>  		if (strlen(value) + 1 > WWID_SIZE) {
> +			len = fix_broken_nvme_wwid(pp, value, WWID_SIZE);
> +			if (len > 0)
> +				return len;
>  			condlog(0, "%s: wwid overflow", pp->dev);
>  			len = WWID_SIZE;
>  		} else {
> -- 
> 2.13.2

  reply	other threads:[~2017-07-14 22:38 UTC|newest]

Thread overview: 19+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-07-14 11:32 [PATCH 0/4] libmultipath: Fixes for NVME / NVMEoF Martin Wilck
2017-07-14 11:32 ` [PATCH 1/4] libmultipath: get_udev_uid: make sure pp->wwid is 0-terminated Martin Wilck
2017-07-14 14:56   ` [dm-devel] " Bart Van Assche
2017-07-14 19:21     ` Martin Wilck
2017-07-14 20:21       ` Bart Van Assche
2017-07-14 21:21         ` Martin Wilck
2017-07-14 21:27           ` Bart Van Assche
2017-07-14 22:17   ` Benjamin Marzinski
2017-07-14 11:32 ` [PATCH 2/4] libmultipath: drop uevent_can_discard_by_devpath Martin Wilck
2017-07-14 22:18   ` [dm-devel] " Schremmer, Steven
2017-07-14 22:29   ` Benjamin Marzinski
2017-07-17  1:12   ` Guan Junxiong
2017-07-14 11:32 ` [PATCH 3/4] libmultipath: only listen for uevents with DEVTYPE=disk Martin Wilck
2017-07-14 22:16   ` [dm-devel] " Schremmer, Steven
2017-07-14 22:29   ` Benjamin Marzinski
2017-07-17  1:12   ` Guan Junxiong
2017-07-14 11:32 ` [PATCH 4/4] libmultipath: fix over-long NVME WWIDs Martin Wilck
2017-07-14 22:38   ` Benjamin Marzinski [this message]
2017-07-17  1:13   ` Guan Junxiong

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20170714223802.GD2940@octiron.msp.redhat.com \
    --to=bmarzins@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox