All of lore.kernel.org
 help / color / mirror / Atom feed
From: Toshi Kani <toshi.kani@hpe.com>
To: Borislav Petkov <bp@alien8.de>
Cc: mchehab@osg.samsung.com, dougthompson@xmission.com,
	linux-edac@vger.kernel.org, linux-kernel@vger.kernel.org,
	elliott@hpe.com, tony.luck@intel.com
Subject: Re: [PATCH v2 2/2] EDAC: Fix sysfs dimm_label store operation
Date: Thu, 24 Sep 2015 13:06:04 -0600	[thread overview]
Message-ID: <1443121564.25474.160.camel@hpe.com> (raw)
In-Reply-To: <20150924164830.GF3774@pd.tnic>

On Thu, 2015-09-24 at 18:48 +0200, Borislav Petkov wrote:
> On Tue, Sep 22, 2015 at 08:58:03AM -0600, Toshi Kani wrote:
> > Sysfs "dimm_label" and "chX_dimm_label" have the following issues
> > in their store operation.
> > 
> >  1) A newline-terminated input string causes redundant newlines
> > 
> >   # echo "test" > /sys/bus/mc0/devices/dimm0/dimm_label
> >   # cat  /sys/bus/mc0/devices/dimm0/dimm_label
> >   test
> > 
> >   #  od -bc /sys/bus/mc0/devices/dimm0/dimm_label
> >   0000000 164 145 163 164 012 012
> >             t   e   s   t  \n  \n
> >   0000006
> > 
> >  2) The original label string (31 characters) cannot be stored due to
> >     an improper size check
> > 
> >   # echo "CPU_SrcID#0_Ha#0_Chan#0_DIMM#0" \
> >   > /sys/bus/mc0/devices/dimm0/dimm_label
> >   # cat /sys/bus/mc0/devices/dimm0/dimm_label
> > 
> > 
> >   # od -bc /sys/bus/mc0/devices/dimm0/dimm_label
> >    0000000 012 012
> >             \n  \n
> >    0000002
> > 
> >  3) An input string longer than the buffer size results a wrong label
> >     info as it allows a retry with the remaining string.
> > 
> >   # echo "CPU_SrcID#0_Ha#0_Chan#0_DIMM#0_TEST" \
> >   > /sys/bus/mc0/devices/dimm0/dimm_label
> >   # cat  /sys/bus/mc0/devices/dimm0/dimm_label
> >   _TEST
> > 
> > Fix these issues by making the following changes:
> >  1) Replace a newline charactor at the end by setting a null. It also
> >     assures that the string is null-terminated within the size.
> >  2) Check the label buffer size with 'sizeof(dimm->label)'.
> >  3) Fail a request if its string exceeds the label buffer size.
> > 
> > Signed-off-by: Toshi Kani <toshi.kani@hpe.com>
> > Acked-by: Tony Luck <tony.luck@intel.com>
> > Cc: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
> > Cc: Borislav Petkov <bp@alien8.de>
> > Cc: Doug Thompson <dougthompson@xmission.com>
> > Cc: Robert Elliott <elliott@hpe.com>
> > Cc: Tony Luck <tony.luck@intel.com>
> > ---
> >  drivers/edac/edac_mc_sysfs.c |   20 ++++++++++----------
> >  1 file changed, 10 insertions(+), 10 deletions(-)
> 
> ...
> 
> > @@ -495,13 +495,13 @@ static ssize_t dimmdev_label_store(struct device *dev,
> >  {
> >  	struct dimm_info *dimm = to_dimm(dev);
> >  
> > -	ssize_t max_size = 0;
> > +	if (count == 0 || count > sizeof(dimm->label))
> > +		return -EINVAL;
> 
> $ echo "" > /sys/bus/mc0/devices/dimm0/dimm_label
> $ od -bc /sys/bus/mc0/devices/dimm0/dimm_label
> 0000000
> $ cat /sys/bus/mc0/devices/dimm0/dimm_label
> $
> 
> I don't think we want to allow empty labels. I guess something like this
> (2 because there's also the additional "\n"):

edac-utils(1) checks empty labels and shows them as "ch%d" [1].  So,
I think empty labels are supported today, and using 'echo "" >' seems
to be a legitimate way to set them empty if desired.

While looking at the count check, though, I noticed that 'echo -n'
does not send a null-terminated string (hence, the count check needs
to take it into account) since it simply calls putchar() to send '1'
only in the example below. [2]

  $ echo -n "1" | wc
        0       1       1

Attached is updated patch that handles the 'echo -n' case properly.
When an input string is not null-terminated, it appends
'\0' to the
end as long as it fits into the label buffer.

Thanks,
-Toshi

[1] https://github.com/grondo/edac-utils/search?utf8=%E2%9C%93&q=dimm_label_valid&type=Code
[2] http://git.savannah.gnu.org/cgit/coreutils.git/tree/src/echo.c

======
Subject: [PATCH v2 UPDATE 2/2] EDAC: Fix sysfs dimm_label store operation

Sysfs "dimm_label" and "chX_dimm_label" have the following issues
in their store operation.

 1) A newline-terminated input string causes redundant newlines

  # echo "test" > /sys/bus/mc0/devices/dimm0/dimm_label
  # cat  /sys/bus/mc0/devices/dimm0/dimm_label
  test

  #  od -bc /sys/bus/mc0/devices/dimm0/dimm_label
  0000000 164 145 163 164 012 012
            t   e   s   t  \n  \n
  0000006

 2) The original label string (31 characters) cannot be stored due to
    an improper size check

  # echo "CPU_SrcID#0_Ha#0_Chan#0_DIMM#0" \
  > /sys/bus/mc0/devices/dimm0/dimm_label
  # cat /sys/bus/mc0/devices/dimm0/dimm_label


  # od -bc /sys/bus/mc0/devices/dimm0/dimm_label
   0000000 012 012
            \n  \n
   0000002

 3) An input string longer than the buffer size results a wrong label
    info as it allows a retry with the remaining string.

  # echo "CPU_SrcID#0_Ha#0_Chan#0_DIMM#0_TEST" \
  > /sys/bus/mc0/devices/dimm0/dimm_label
  # cat  /sys/bus/mc0/devices/dimm0/dimm_label
  _TEST

Fix these issues by making the following changes:
 1) Replace a newline character at the end by setting a null. It also
    assures that the string is null-terminated in the label buffer.
 2) Check the label buffer size with 'sizeof(dimm->label)'.
 3) Fail a request if its string exceeds the label buffer size.

Signed-off-by: Toshi Kani <toshi.kani@hpe.com>
Acked-by: Tony Luck <tony.luck@intel.com>
Cc: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Doug Thompson <dougthompson@xmission.com>
Cc: Robert Elliott <elliott@hpe.com>
Cc: Tony Luck <tony.luck@intel.com>
---
 drivers/edac/edac_mc_sysfs.c |   34 ++++++++++++++++++++++++----------
 1 file changed, 24 insertions(+), 10 deletions(-)

diff --git a/drivers/edac/edac_mc_sysfs.c b/drivers/edac/edac_mc_sysfs.c
index 8983755..5252fb9 100644
--- a/drivers/edac/edac_mc_sysfs.c
+++ b/drivers/edac/edac_mc_sysfs.c
@@ -240,14 +240,21 @@ static ssize_t channel_dimm_label_store(struct device *dev,
 	struct csrow_info *csrow = to_csrow(dev);
 	unsigned chan = to_channel(mattr);
 	struct rank_info *rank = csrow->channels[chan];
+	size_t copy_count = count;
 
-	ssize_t max_size = 0;
+	if (count == 0)
+		return -EINVAL;
+
+	if (data[count - 1] == '\0' || data[count - 1] == '\n')
+		copy_count -= 1;
 
-	max_size = min((ssize_t) count, (ssize_t) EDAC_MC_LABEL_LEN - 1);
-	strncpy(rank->dimm->label, data, max_size);
-	rank->dimm->label[max_size] = '\0';
+	if (copy_count >= sizeof(rank->dimm->label))
+		return -EINVAL;
 
-	return max_size;
+	strncpy(rank->dimm->label, data, copy_count);
+	rank->dimm->label[copy_count] = '\0';
+
+	return count;
 }
 
 /* show function for dynamic chX_ce_count attribute */
@@ -494,14 +501,21 @@ static ssize_t dimmdev_label_store(struct device *dev,
 				   size_t count)
 {
 	struct dimm_info *dimm = to_dimm(dev);
+	size_t copy_count = count;
 
-	ssize_t max_size = 0;
+	if (count == 0)
+		return -EINVAL;
+
+	if (data[count - 1] == '\0' || data[count - 1] == '\n')
+		copy_count -= 1;
 
-	max_size = min((ssize_t) count, (ssize_t) EDAC_MC_LABEL_LEN - 1);
-	strncpy(dimm->label, data, max_size);
-	dimm->label[max_size] = '\0';
+	if (copy_count >= sizeof(dimm->label))
+		return -EINVAL;
 
-	return max_size;
+	strncpy(dimm->label, data, copy_count);
+	dimm->label[copy_count] = '\0';
+
+	return count;
 }
 
 static ssize_t dimmdev_size_show(struct device *dev,

  reply	other threads:[~2015-09-24 19:09 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-09-22 14:58 [PATCH v2 0/2] EDAC: Fix sysfs dimm_label show & store operations Toshi Kani
2015-09-22 14:58 ` [PATCH v2 1/2] EDAC: Fix sysfs dimm_label show operation Toshi Kani
2015-09-22 14:58 ` [PATCH v2 2/2] EDAC: Fix sysfs dimm_label store operation Toshi Kani
2015-09-24 16:48   ` Borislav Petkov
2015-09-24 19:06     ` Toshi Kani [this message]
2015-09-24 19:15       ` Borislav Petkov
2015-09-24 19:59         ` Toshi Kani
2015-09-25 17:49           ` Borislav Petkov

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=1443121564.25474.160.camel@hpe.com \
    --to=toshi.kani@hpe.com \
    --cc=bp@alien8.de \
    --cc=dougthompson@xmission.com \
    --cc=elliott@hpe.com \
    --cc=linux-edac@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mchehab@osg.samsung.com \
    --cc=tony.luck@intel.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.