Re: [Qemu-devel] [PATCH 04/14] qemu-nbd: Simplify --partition handling

2018-12-10 Thread Eric Blake

On 11/30/18 4:03 PM, Eric Blake wrote:

Our open-coding of strtol handling forgot to handle overflow
conditions. What's more, since we insiste on a user-supplied
partition to be non-zero, we can use 0 rather than -1 for our
initial value to distinguish when a partition is not being
served, for slightly more optimal code.

Signed-off-by: Eric Blake 
---
  qemu-nbd.c | 14 +-
  1 file changed, 5 insertions(+), 9 deletions(-)

diff --git a/qemu-nbd.c b/qemu-nbd.c
index 55e29bd9a7e..866e64779f1 100644
--- a/qemu-nbd.c
+++ b/qemu-nbd.c
@@ -546,7 +546,7 @@ int main(int argc, char **argv)
  int opt_ind = 0;
  char *end;
  int flags = BDRV_O_RDWR;
-int partition = -1;
+int partition = 0;
  int ret = 0;
  bool seen_cache = false;
  bool seen_discard = false;
@@ -685,13 +685,9 @@ int main(int argc, char **argv)
  flags &= ~BDRV_O_RDWR;
  break;
  case 'P':
-partition = strtol(optarg, , 0);
-if (*end) {
-error_report("Invalid partition `%s'", optarg);
-exit(EXIT_FAILURE);
-}
-if (partition < 1 || partition > 8) {
-error_report("Invalid partition %d", partition);
+if (qemu_strtoi(optarg, NULL, 0, ) < 0 ||


Hmm - the fact that 'char *end' is not a dead variable means there are 
more uses of strtoll() that need fixing. I'll get those in v2.


--
Eric Blake, Principal Software Engineer
Red Hat, Inc.   +1-919-301-3266
Virtualization:  qemu.org | libvirt.org



Re: [Qemu-devel] [PATCH 04/14] qemu-nbd: Simplify --partition handling

2018-12-05 Thread Eric Blake

On 12/5/18 10:26 AM, Eric Blake wrote:


is it possible, that "char *ep" remains uninitialized, and than we access
it in check_strtox_error? I don's see in strtol spec a guarantee of 
setting

endptr on failure path.


C99 7.10.1.4 P5-7 requires strtoll() and friends to assign through 
'endptr' if it is non-NULL, for both success and ERANGE failure cases. 
POSIX then further requires 'endptr' to be set for EINVAL failures due 
to out-of-range 'base' (not that we have any such callers), and permits 
(but does not require) the empty string to cause an EINVAL failure (but 
whether or not EINVAL happened, 'endptr' is still set).  There are no 
other possible failures, so no, we are not dereferencing an 
uninitialized variable in check_strtox_error.


Correction, quoting POSIX:

http://pubs.opengroup.org/onlinepubs/9699919799/functions/strtol.html

APPLICATION USAGE

Since the value of *endptr is unspecified if the value of base is 
not supported, applications should either ensure that base has a 
supported value (0 or between 2 and 36) before the call, or check for an 
[EINVAL] error before examining *endptr.


So yes, we CAN end up transferring an uninitialized variable into the 
caller's non-NULL endpointer if the caller passes an out-of-range base 
(this particular caller passes NULL for an endpointer, and an in-range 
base, so it's not an issue).  Might be worth a separate patch to assert 
that base is in range for all of the qemu_strto* helpers, if we are 
worried (I'm not).


--
Eric Blake, Principal Software Engineer
Red Hat, Inc.   +1-919-301-3266
Virtualization:  qemu.org | libvirt.org



Re: [Qemu-devel] [PATCH 04/14] qemu-nbd: Simplify --partition handling

2018-12-05 Thread Eric Blake

On 12/5/18 9:40 AM, Vladimir Sementsov-Ogievskiy wrote:

01.12.2018 1:03, Eric Blake wrote:

Our open-coding of strtol handling forgot to handle overflow
conditions. What's more, since we insiste on a user-supplied
partition to be non-zero, we can use 0 rather than -1 for our
initial value to distinguish when a partition is not being
served, for slightly more optimal code.




-if (partition < 1 || partition > 8) {
-error_report("Invalid partition %d", partition);
+if (qemu_strtoi(optarg, NULL, 0, ) < 0 ||


I decided to look into qemu_strtoi, hmm.

is it possible, that "char *ep" remains uninitialized, and than we access
it in check_strtox_error? I don's see in strtol spec a guarantee of setting
endptr on failure path.


C99 7.10.1.4 P5-7 requires strtoll() and friends to assign through 
'endptr' if it is non-NULL, for both success and ERANGE failure cases. 
POSIX then further requires 'endptr' to be set for EINVAL failures due 
to out-of-range 'base' (not that we have any such callers), and permits 
(but does not require) the empty string to cause an EINVAL failure (but 
whether or not EINVAL happened, 'endptr' is still set).  There are no 
other possible failures, so no, we are not dereferencing an 
uninitialized variable in check_strtox_error.






+partition < 1 || partition > 8) {


don't you like brace on separate line after multi-line conditions?


CODING_STYLE is silent on the matter; checkpatch.pl allows either style 
for multi-line, while requesting the same line as the condition for 
one-line (see commit a97ceca57).  But since I'm already in the habit of 
putting { right after the condition because of checkpatch, I don't go 
out of my way to put it on its own line after multi-line conditionals. 
I don't think it matters too much.


--
Eric Blake, Principal Software Engineer
Red Hat, Inc.   +1-919-301-3266
Virtualization:  qemu.org | libvirt.org



Re: [Qemu-devel] [PATCH 04/14] qemu-nbd: Simplify --partition handling

2018-12-05 Thread Vladimir Sementsov-Ogievskiy
01.12.2018 1:03, Eric Blake wrote:
> Our open-coding of strtol handling forgot to handle overflow
> conditions. What's more, since we insiste on a user-supplied
> partition to be non-zero, we can use 0 rather than -1 for our
> initial value to distinguish when a partition is not being
> served, for slightly more optimal code.
> 
> Signed-off-by: Eric Blake 
> ---
>   qemu-nbd.c | 14 +-
>   1 file changed, 5 insertions(+), 9 deletions(-)
> 
> diff --git a/qemu-nbd.c b/qemu-nbd.c
> index 55e29bd9a7e..866e64779f1 100644
> --- a/qemu-nbd.c
> +++ b/qemu-nbd.c
> @@ -546,7 +546,7 @@ int main(int argc, char **argv)
>   int opt_ind = 0;
>   char *end;
>   int flags = BDRV_O_RDWR;
> -int partition = -1;
> +int partition = 0;
>   int ret = 0;
>   bool seen_cache = false;
>   bool seen_discard = false;
> @@ -685,13 +685,9 @@ int main(int argc, char **argv)
>   flags &= ~BDRV_O_RDWR;
>   break;
>   case 'P':
> -partition = strtol(optarg, , 0);
> -if (*end) {
> -error_report("Invalid partition `%s'", optarg);
> -exit(EXIT_FAILURE);
> -}
> -if (partition < 1 || partition > 8) {
> -error_report("Invalid partition %d", partition);
> +if (qemu_strtoi(optarg, NULL, 0, ) < 0 ||

I decided to look into qemu_strtoi, hmm.

is it possible, that "char *ep" remains uninitialized, and than we access
it in check_strtox_error? I don's see in strtol spec a guarantee of setting
endptr on failure path.


> +partition < 1 || partition > 8) {

don't you like brace on separate line after multi-line conditions?

> +error_report("Invalid partition %s", optarg);
>   exit(EXIT_FAILURE);
>   }
>   break;
> @@ -1004,7 +1000,7 @@ int main(int argc, char **argv)
>   }
>   fd_size -= dev_offset;
> 
> -if (partition != -1) {
> +if (partition) {
>   ret = find_partition(blk, partition, _offset, _size);
>   if (ret < 0) {
>   error_report("Could not find partition %d: %s", partition,
> 

Reviewed-by: Vladimir Sementsov-Ogievskiy 

-- 
Best regards,
Vladimir


Re: [Qemu-devel] [PATCH 04/14] qemu-nbd: Simplify --partition handling

2018-11-30 Thread Eric Blake

On 11/30/18 4:26 PM, Richard W.M. Jones wrote:

On Fri, Nov 30, 2018 at 04:03:33PM -0600, Eric Blake wrote:

Our open-coding of strtol handling forgot to handle overflow
conditions. What's more, since we insiste on a user-supplied


"insist"


(Ever wonder if I stick in a typo on purpose, just to see who reviews 
closely?)





partition to be non-zero, we can use 0 rather than -1 for our
initial value to distinguish when a partition is not being
served, for slightly more optimal code.

Signed-off-by: Eric Blake 
---
  qemu-nbd.c | 14 +-
  1 file changed, 5 insertions(+), 9 deletions(-)




+if (qemu_strtoi(optarg, NULL, 0, ) < 0 ||
+partition < 1 || partition > 8) {
+error_report("Invalid partition %s", optarg);


Pffft only supporting a mere 8 partitions :-?  I raised the limits in
nbdkit recently so it can handle an infinite number of partitions :-)


nbdkit also handles GPT partitions. qemu-nbd is still stuck on MBR:

static int find_partition(BlockBackend *blk, int partition,
  off_t *offset, off_t *size)
{
struct partition_record mbr[4];
uint8_t data[MBR_SIZE];

and if I read git blame correctly, the partition code in qemu-nbd is 
mostly untouched since Fabrice committed Anthony's initial 
implementation in 2008.


Also, reading the code, I see that qemu-nbd allows partitions 5-8 
because it reads through the extended partition descriptor in 4 to 
expose the logical partitions within; which nbdkit can't do yet :)




Anyway, it's a problem with the existing code, so doesn't affect the
review.


Indeed, and with nbdkit around, I'm wondering if I should deprecate 
'qemu-nbd --partition' and just point people to nbdkit instead 
(provided, of course, that nbdkit learns logical partitions).


Even if you have a qcow2 image with MBR partitions, and where we don't 
want to write a qcow2 plugin in nbdkit, you can still always rewrite:


client -> qemu-nbd --partition=1

into

client -> nbdkit --filter=partition nbd partition=1 -> qemu-nbd

(although I don't know what the performance penalty would be)

--
Eric Blake, Principal Software Engineer
Red Hat, Inc.   +1-919-301-3266
Virtualization:  qemu.org | libvirt.org



Re: [Qemu-devel] [PATCH 04/14] qemu-nbd: Simplify --partition handling

2018-11-30 Thread Richard W.M. Jones
On Fri, Nov 30, 2018 at 04:03:33PM -0600, Eric Blake wrote:
> Our open-coding of strtol handling forgot to handle overflow
> conditions. What's more, since we insiste on a user-supplied

"insist"

> partition to be non-zero, we can use 0 rather than -1 for our
> initial value to distinguish when a partition is not being
> served, for slightly more optimal code.
> 
> Signed-off-by: Eric Blake 
> ---
>  qemu-nbd.c | 14 +-
>  1 file changed, 5 insertions(+), 9 deletions(-)
> 
> diff --git a/qemu-nbd.c b/qemu-nbd.c
> index 55e29bd9a7e..866e64779f1 100644
> --- a/qemu-nbd.c
> +++ b/qemu-nbd.c
> @@ -546,7 +546,7 @@ int main(int argc, char **argv)
>  int opt_ind = 0;
>  char *end;
>  int flags = BDRV_O_RDWR;
> -int partition = -1;
> +int partition = 0;
>  int ret = 0;
>  bool seen_cache = false;
>  bool seen_discard = false;
> @@ -685,13 +685,9 @@ int main(int argc, char **argv)
>  flags &= ~BDRV_O_RDWR;
>  break;
>  case 'P':
> -partition = strtol(optarg, , 0);
> -if (*end) {
> -error_report("Invalid partition `%s'", optarg);
> -exit(EXIT_FAILURE);
> -}
> -if (partition < 1 || partition > 8) {
> -error_report("Invalid partition %d", partition);
> +if (qemu_strtoi(optarg, NULL, 0, ) < 0 ||
> +partition < 1 || partition > 8) {
> +error_report("Invalid partition %s", optarg);

Pffft only supporting a mere 8 partitions :-?  I raised the limits in
nbdkit recently so it can handle an infinite number of partitions :-)

Anyway, it's a problem with the existing code, so doesn't affect the
review.

>  exit(EXIT_FAILURE);
>  }
>  break;
> @@ -1004,7 +1000,7 @@ int main(int argc, char **argv)
>  }
>  fd_size -= dev_offset;
> 
> -if (partition != -1) {
> +if (partition) {
>  ret = find_partition(blk, partition, _offset, _size);
>  if (ret < 0) {
>  error_report("Could not find partition %d: %s", partition,
> -- 
> 2.17.2

Reviewed-by: Richard W.M. Jones 

Rich.

-- 
Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones
Read my programming and virtualization blog: http://rwmj.wordpress.com
virt-builder quickly builds VMs from scratch
http://libguestfs.org/virt-builder.1.html



[Qemu-devel] [PATCH 04/14] qemu-nbd: Simplify --partition handling

2018-11-30 Thread Eric Blake
Our open-coding of strtol handling forgot to handle overflow
conditions. What's more, since we insiste on a user-supplied
partition to be non-zero, we can use 0 rather than -1 for our
initial value to distinguish when a partition is not being
served, for slightly more optimal code.

Signed-off-by: Eric Blake 
---
 qemu-nbd.c | 14 +-
 1 file changed, 5 insertions(+), 9 deletions(-)

diff --git a/qemu-nbd.c b/qemu-nbd.c
index 55e29bd9a7e..866e64779f1 100644
--- a/qemu-nbd.c
+++ b/qemu-nbd.c
@@ -546,7 +546,7 @@ int main(int argc, char **argv)
 int opt_ind = 0;
 char *end;
 int flags = BDRV_O_RDWR;
-int partition = -1;
+int partition = 0;
 int ret = 0;
 bool seen_cache = false;
 bool seen_discard = false;
@@ -685,13 +685,9 @@ int main(int argc, char **argv)
 flags &= ~BDRV_O_RDWR;
 break;
 case 'P':
-partition = strtol(optarg, , 0);
-if (*end) {
-error_report("Invalid partition `%s'", optarg);
-exit(EXIT_FAILURE);
-}
-if (partition < 1 || partition > 8) {
-error_report("Invalid partition %d", partition);
+if (qemu_strtoi(optarg, NULL, 0, ) < 0 ||
+partition < 1 || partition > 8) {
+error_report("Invalid partition %s", optarg);
 exit(EXIT_FAILURE);
 }
 break;
@@ -1004,7 +1000,7 @@ int main(int argc, char **argv)
 }
 fd_size -= dev_offset;

-if (partition != -1) {
+if (partition) {
 ret = find_partition(blk, partition, _offset, _size);
 if (ret < 0) {
 error_report("Could not find partition %d: %s", partition,
-- 
2.17.2