* [PATCH] tmem fixes for Xen 4.5 - coverity inspired.
@ 2014-04-30 20:29 Konrad Rzeszutek Wilk
2014-04-30 20:29 ` [PATCH 1/4] xc/tmem: Free temporary buffer used during migration Konrad Rzeszutek Wilk
` (3 more replies)
0 siblings, 4 replies; 10+ messages in thread
From: Konrad Rzeszutek Wilk @ 2014-04-30 20:29 UTC (permalink / raw)
To: xen-devel, andrew.cooper3, jbeulich, keir
These patches are inspired by Coverity results - and I hope the
last of them in the 'tmem' department.
Please review, especially the:
[PATCH 4/4] tmem: fix Out-of-bounds read reported by Coverity
at your leisure.
tools/libxc/xc_domain_save.c | 8 +++++--
tools/libxc/xc_tmem.c | 51 ++++++++++++++++++++++++++------------------
tools/libxc/xenctrl.h | 2 +-
xen/common/tmem.c | 10 ++-------
4 files changed, 39 insertions(+), 32 deletions(-)
Bob Liu (2):
tmem: drop unnecessary lock in tmem_relinquish_pages()
tmem: fix Out-of-bounds read reported by Coverity
Konrad Rzeszutek Wilk (2):
xc/tmem: Free temporary buffer used during migration.
xc/tmem: Unchecked return value (v2).
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH 1/4] xc/tmem: Free temporary buffer used during migration.
2014-04-30 20:29 [PATCH] tmem fixes for Xen 4.5 - coverity inspired Konrad Rzeszutek Wilk
@ 2014-04-30 20:29 ` Konrad Rzeszutek Wilk
2014-04-30 20:43 ` Andrew Cooper
2014-04-30 20:29 ` [PATCH 2/4] xc/tmem: Unchecked return value (v2) Konrad Rzeszutek Wilk
` (2 subsequent siblings)
3 siblings, 1 reply; 10+ messages in thread
From: Konrad Rzeszutek Wilk @ 2014-04-30 20:29 UTC (permalink / raw)
To: xen-devel, andrew.cooper3, jbeulich, keir; +Cc: Konrad Rzeszutek Wilk
CID 1090388.
Within the loop reading the pool_id we set the buf:
if ( (buf = realloc(buf,bufsize)) == NULL )
and then continue on using it without freeing. Worst yet
there are multiple 'if (..) return -1' which do not free
the buffer.
As such insert a 'fail' goto label to free the buffer
and also add on the OK path a mechanism to free the buffer.
Replace all of the 'return -1' with a jump to the failed
label.
CC: Bob Liu <bob.liu@oracle.com>
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
---
tools/libxc/xc_tmem.c | 47 ++++++++++++++++++++++++++++-------------------
1 file changed, 28 insertions(+), 19 deletions(-)
diff --git a/tools/libxc/xc_tmem.c b/tools/libxc/xc_tmem.c
index 3261e10..12fa105 100644
--- a/tools/libxc/xc_tmem.c
+++ b/tools/libxc/xc_tmem.c
@@ -215,6 +215,7 @@ int xc_tmem_save(xc_interface *xch,
uint32_t pool_id;
uint32_t minusone = -1;
struct tmem_handle *h;
+ char *buf = NULL;
if ( xc_tmem_control(xch,0,TMEMC_SAVE_BEGIN,dom,live,0,0,NULL) <= 0 )
return 0;
@@ -249,7 +250,6 @@ int xc_tmem_save(xc_interface *xch,
uint64_t uuid[2];
uint32_t n_pages;
uint32_t pagesize;
- char *buf = NULL;
int bufsize = 0;
int checksum = 0;
@@ -263,13 +263,13 @@ int xc_tmem_save(xc_interface *xch,
n_pages = 0;
(void)xc_tmem_control(xch,i,TMEMC_SAVE_GET_POOL_UUID,dom,sizeof(uuid),0,0,&uuid);
if ( write_exact(io_fd, &pool_id, sizeof(pool_id)) )
- return -1;
+ goto failed;
if ( write_exact(io_fd, &flags, sizeof(flags)) )
- return -1;
+ goto failed;
if ( write_exact(io_fd, &n_pages, sizeof(n_pages)) )
- return -1;
+ goto failed;
if ( write_exact(io_fd, &uuid, sizeof(uuid)) )
- return -1;
+ goto failed;
if ( n_pages == 0 )
continue;
@@ -279,7 +279,7 @@ int xc_tmem_save(xc_interface *xch,
{
bufsize = pagesize + sizeof(struct tmem_handle);
if ( (buf = realloc(buf,bufsize)) == NULL )
- return -1;
+ goto failed;
}
for ( j = n_pages; j > 0; j-- )
{
@@ -290,21 +290,22 @@ int xc_tmem_save(xc_interface *xch,
{
h = (struct tmem_handle *)buf;
if ( write_exact(io_fd, &h->oid, sizeof(h->oid)) )
- return -1;
+ goto failed;
if ( write_exact(io_fd, &h->index, sizeof(h->index)) )
- return -1;
+ goto failed;
h++;
checksum += *(char *)h;
if ( write_exact(io_fd, h, pagesize) )
- return -1;
+ goto failed;
} else if ( ret == 0 ) {
continue;
} else {
/* page list terminator */
h = (struct tmem_handle *)buf;
h->oid[0] = h->oid[1] = h->oid[2] = -1L;
- if ( write_exact(io_fd, &h->oid, sizeof(h->oid)) )
- return -1;
+ if ( write_exact(io_fd, &h->oid, sizeof(h->oid)) ) {
+ goto failed;
+ }
break;
}
}
@@ -315,9 +316,13 @@ int xc_tmem_save(xc_interface *xch,
/* pool list terminator */
minusone = -1;
if ( write_exact(io_fd, &minusone, sizeof(minusone)) )
- return -1;
+ goto failed;
+ free(buf);
return 1;
+failed:
+ free(buf);
+ return -1;
}
/* only called for live migration */
@@ -386,6 +391,7 @@ int xc_tmem_restore(xc_interface *xch, int dom, int io_fd)
uint32_t minusone;
uint32_t weight, cap, flags;
int checksum = 0;
+ char *buf = NULL;
save_version = xc_tmem_control(xch,0,TMEMC_SAVE_GET_VERSION,dom,0,0,0,NULL);
if ( save_version == -1 )
@@ -423,7 +429,6 @@ int xc_tmem_restore(xc_interface *xch, int dom, int io_fd)
{
uint64_t uuid[2];
uint32_t n_pages;
- char *buf = NULL;
int bufsize = 0, pagesize;
int j;
@@ -445,7 +450,7 @@ int xc_tmem_restore(xc_interface *xch, int dom, int io_fd)
{
bufsize = pagesize;
if ( (buf = realloc(buf,bufsize)) == NULL )
- return -1;
+ goto failed;
}
for ( j = n_pages; j > 0; j-- )
{
@@ -453,20 +458,20 @@ int xc_tmem_restore(xc_interface *xch, int dom, int io_fd)
uint32_t index;
int rc;
if ( read_exact(io_fd, &oid, sizeof(oid)) )
- return -1;
+ goto failed;
if ( oid.oid[0] == -1L && oid.oid[1] == -1L && oid.oid[2] == -1L )
break;
if ( read_exact(io_fd, &index, sizeof(index)) )
- return -1;
+ goto failed;
if ( read_exact(io_fd, buf, pagesize) )
- return -1;
+ goto failed;
checksum += *buf;
if ( (rc = xc_tmem_control_oid(xch, pool_id,
TMEMC_RESTORE_PUT_PAGE, dom,
bufsize, index, oid, buf)) <= 0 )
{
DPRINTF("xc_tmem_restore: putting page failed, rc=%d\n",rc);
- return -1;
+ goto failed;
}
}
if ( n_pages )
@@ -474,9 +479,13 @@ int xc_tmem_restore(xc_interface *xch, int dom, int io_fd)
n_pages-j,dom,pool_id,checksum);
}
if ( pool_id != -1 )
- return -1;
+ goto failed;
+ free(buf);
return 0;
+failed:
+ free(buf);
+ return -1;
}
/* only called for live migration, must be called after suspend */
--
1.8.5.3
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH 2/4] xc/tmem: Unchecked return value (v2).
2014-04-30 20:29 [PATCH] tmem fixes for Xen 4.5 - coverity inspired Konrad Rzeszutek Wilk
2014-04-30 20:29 ` [PATCH 1/4] xc/tmem: Free temporary buffer used during migration Konrad Rzeszutek Wilk
@ 2014-04-30 20:29 ` Konrad Rzeszutek Wilk
2014-04-30 20:46 ` Andrew Cooper
2014-04-30 20:29 ` [PATCH 3/4] tmem: drop unnecessary lock in tmem_relinquish_pages() Konrad Rzeszutek Wilk
2014-04-30 20:29 ` [PATCH 4/4] tmem: fix Out-of-bounds read reported by Coverity Konrad Rzeszutek Wilk
3 siblings, 1 reply; 10+ messages in thread
From: Konrad Rzeszutek Wilk @ 2014-04-30 20:29 UTC (permalink / raw)
To: xen-devel, andrew.cooper3, jbeulich, keir; +Cc: Konrad Rzeszutek Wilk
CID 1055045 complains that the return value needs checking.
The tmem op is a flush call and there is no expectation
right now of any return besides zero. But just in case
this changes lets blow up.
CC: Bob Liu <bob.liu@oracle.com>
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
[v2: Add a comment why bailing out on xc_tmem_save_done is not needed]
---
tools/libxc/xc_domain_save.c | 8 ++++++--
tools/libxc/xc_tmem.c | 4 ++--
tools/libxc/xenctrl.h | 2 +-
3 files changed, 9 insertions(+), 5 deletions(-)
diff --git a/tools/libxc/xc_domain_save.c b/tools/libxc/xc_domain_save.c
index 71f9b59..b04e387 100644
--- a/tools/libxc/xc_domain_save.c
+++ b/tools/libxc/xc_domain_save.c
@@ -2107,8 +2107,12 @@ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iter
goto copypages;
}
- if ( tmem_saved != 0 && live )
- xc_tmem_save_done(xch, dom);
+ if ( tmem_saved != 0 && live && xc_tmem_save_done(xch, dom))
+ {
+ /* N.B. No need to bail out - we leak memory, but that is all assigned
+ * to the zombie guest. */
+ DPRINTF("Warning - failed to flush tmem on originating server.");
+ }
if ( live )
{
diff --git a/tools/libxc/xc_tmem.c b/tools/libxc/xc_tmem.c
index 12fa105..6e01a6a 100644
--- a/tools/libxc/xc_tmem.c
+++ b/tools/libxc/xc_tmem.c
@@ -356,9 +356,9 @@ int xc_tmem_save_extra(xc_interface *xch, int dom, int io_fd, int field_marker)
}
/* only called for live migration */
-void xc_tmem_save_done(xc_interface *xch, int dom)
+int xc_tmem_save_done(xc_interface *xch, int dom)
{
- xc_tmem_control(xch,0,TMEMC_SAVE_END,dom,0,0,0,NULL);
+ return xc_tmem_control(xch,0,TMEMC_SAVE_END,dom,0,0,0,NULL);
}
/* restore routines */
diff --git a/tools/libxc/xenctrl.h b/tools/libxc/xenctrl.h
index 02129f7..23630a7 100644
--- a/tools/libxc/xenctrl.h
+++ b/tools/libxc/xenctrl.h
@@ -2011,7 +2011,7 @@ int xc_tmem_control(xc_interface *xch,
int xc_tmem_auth(xc_interface *xch, int cli_id, char *uuid_str, int arg1);
int xc_tmem_save(xc_interface *xch, int dom, int live, int fd, int field_marker);
int xc_tmem_save_extra(xc_interface *xch, int dom, int fd, int field_marker);
-void xc_tmem_save_done(xc_interface *xch, int dom);
+int xc_tmem_save_done(xc_interface *xch, int dom);
int xc_tmem_restore(xc_interface *xch, int dom, int fd);
int xc_tmem_restore_extra(xc_interface *xch, int dom, int fd);
--
1.8.5.3
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH 3/4] tmem: drop unnecessary lock in tmem_relinquish_pages()
2014-04-30 20:29 [PATCH] tmem fixes for Xen 4.5 - coverity inspired Konrad Rzeszutek Wilk
2014-04-30 20:29 ` [PATCH 1/4] xc/tmem: Free temporary buffer used during migration Konrad Rzeszutek Wilk
2014-04-30 20:29 ` [PATCH 2/4] xc/tmem: Unchecked return value (v2) Konrad Rzeszutek Wilk
@ 2014-04-30 20:29 ` Konrad Rzeszutek Wilk
2014-04-30 20:29 ` [PATCH 4/4] tmem: fix Out-of-bounds read reported by Coverity Konrad Rzeszutek Wilk
3 siblings, 0 replies; 10+ messages in thread
From: Konrad Rzeszutek Wilk @ 2014-04-30 20:29 UTC (permalink / raw)
To: xen-devel, andrew.cooper3, jbeulich, keir; +Cc: Konrad Rzeszutek Wilk
From: Bob Liu <bob.liu@oracle.com>
CID 1150562
tmem_rwlock is unnecessary in tmem_relinquish_pages(), as
such lock is used as gate for hypercalls. However
tmem_relinquish_pages deals with pages that are no longer
owned by any domain - hence there is no need for tmem_rwlock.
Also the function is protected by the 'heap_lock' which
is the only calleer of this function.
This patch drops said lock.
Signed-off-by: Bob Liu <bob.liu@oracle.com>
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
---
xen/common/tmem.c | 6 ------
1 file changed, 6 deletions(-)
diff --git a/xen/common/tmem.c b/xen/common/tmem.c
index f7f828f..f2dc26e 100644
--- a/xen/common/tmem.c
+++ b/xen/common/tmem.c
@@ -2794,9 +2794,6 @@ void *tmem_relinquish_pages(unsigned int order, unsigned int memflags)
return NULL;
}
- if ( memflags & MEMF_tmem )
- read_lock(&tmem_rwlock);
-
while ( (pfp = tmem_page_list_get()) == NULL )
{
if ( (max_evictions-- <= 0) || !tmem_evict())
@@ -2812,9 +2809,6 @@ void *tmem_relinquish_pages(unsigned int order, unsigned int memflags)
relinq_pgs++;
}
- if ( memflags & MEMF_tmem )
- read_unlock(&tmem_rwlock);
-
return pfp;
}
--
1.8.5.3
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH 4/4] tmem: fix Out-of-bounds read reported by Coverity
2014-04-30 20:29 [PATCH] tmem fixes for Xen 4.5 - coverity inspired Konrad Rzeszutek Wilk
` (2 preceding siblings ...)
2014-04-30 20:29 ` [PATCH 3/4] tmem: drop unnecessary lock in tmem_relinquish_pages() Konrad Rzeszutek Wilk
@ 2014-04-30 20:29 ` Konrad Rzeszutek Wilk
2014-04-30 21:04 ` Andrew Cooper
3 siblings, 1 reply; 10+ messages in thread
From: Konrad Rzeszutek Wilk @ 2014-04-30 20:29 UTC (permalink / raw)
To: xen-devel, andrew.cooper3, jbeulich, keir; +Cc: Konrad Rzeszutek Wilk
From: Bob Liu <bob.liu@oracle.com>
CID 1198729, CID 1198730 and CID 1198734 complain about
"Out-of-bounds read".
This patch fixes them by casting the 'firstbyte' to (uint8_t).
Signed-off-by: Bob Liu <bob.liu@oracle.com>
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
---
xen/common/tmem.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/xen/common/tmem.c b/xen/common/tmem.c
index f2dc26e..506c6be 100644
--- a/xen/common/tmem.c
+++ b/xen/common/tmem.c
@@ -399,7 +399,7 @@ static void pcd_disassociate(struct tmem_page_descriptor *pgp, struct tmem_pool
{
struct tmem_page_content_descriptor *pcd = pgp->pcd;
struct page_info *pfp = pgp->pcd->pfp;
- uint16_t firstbyte = pgp->firstbyte;
+ uint8_t firstbyte = pgp->firstbyte;
char *pcd_tze = pgp->pcd->tze;
pagesize_t pcd_size = pcd->size;
pagesize_t pgp_size = pgp->size;
@@ -1231,7 +1231,7 @@ static bool_t tmem_try_to_evict_pgp(struct tmem_page_descriptor *pgp, bool_t *ho
struct tmem_object_root *obj = pgp->us.obj;
struct tmem_pool *pool = obj->pool;
struct client *client = pool->client;
- uint16_t firstbyte = pgp->firstbyte;
+ uint8_t firstbyte = pgp->firstbyte;
if ( pool->is_dying )
return 0;
--
1.8.5.3
^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH 1/4] xc/tmem: Free temporary buffer used during migration.
2014-04-30 20:29 ` [PATCH 1/4] xc/tmem: Free temporary buffer used during migration Konrad Rzeszutek Wilk
@ 2014-04-30 20:43 ` Andrew Cooper
0 siblings, 0 replies; 10+ messages in thread
From: Andrew Cooper @ 2014-04-30 20:43 UTC (permalink / raw)
To: Konrad Rzeszutek Wilk, xen-devel, jbeulich, keir
On 30/04/2014 21:29, Konrad Rzeszutek Wilk wrote:
> CID 1090388.
>
> Within the loop reading the pool_id we set the buf:
>
> if ( (buf = realloc(buf,bufsize)) == NULL )
>
> and then continue on using it without freeing. Worst yet
> there are multiple 'if (..) return -1' which do not free
> the buffer.
>
> As such insert a 'fail' goto label to free the buffer
> and also add on the OK path a mechanism to free the buffer.
>
> Replace all of the 'return -1' with a jump to the failed
> label.
>
> CC: Bob Liu <bob.liu@oracle.com>
> Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
> Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
> ---
> tools/libxc/xc_tmem.c | 47 ++++++++++++++++++++++++++++-------------------
> 1 file changed, 28 insertions(+), 19 deletions(-)
>
> diff --git a/tools/libxc/xc_tmem.c b/tools/libxc/xc_tmem.c
> index 3261e10..12fa105 100644
> --- a/tools/libxc/xc_tmem.c
> +++ b/tools/libxc/xc_tmem.c
> @@ -215,6 +215,7 @@ int xc_tmem_save(xc_interface *xch,
> uint32_t pool_id;
> uint32_t minusone = -1;
> struct tmem_handle *h;
> + char *buf = NULL;
>
> if ( xc_tmem_control(xch,0,TMEMC_SAVE_BEGIN,dom,live,0,0,NULL) <= 0 )
> return 0;
> @@ -249,7 +250,6 @@ int xc_tmem_save(xc_interface *xch,
> uint64_t uuid[2];
> uint32_t n_pages;
> uint32_t pagesize;
> - char *buf = NULL;
> int bufsize = 0;
> int checksum = 0;
>
> @@ -263,13 +263,13 @@ int xc_tmem_save(xc_interface *xch,
> n_pages = 0;
> (void)xc_tmem_control(xch,i,TMEMC_SAVE_GET_POOL_UUID,dom,sizeof(uuid),0,0,&uuid);
> if ( write_exact(io_fd, &pool_id, sizeof(pool_id)) )
> - return -1;
> + goto failed;
> if ( write_exact(io_fd, &flags, sizeof(flags)) )
> - return -1;
> + goto failed;
> if ( write_exact(io_fd, &n_pages, sizeof(n_pages)) )
> - return -1;
> + goto failed;
> if ( write_exact(io_fd, &uuid, sizeof(uuid)) )
> - return -1;
> + goto failed;
> if ( n_pages == 0 )
> continue;
>
> @@ -279,7 +279,7 @@ int xc_tmem_save(xc_interface *xch,
> {
> bufsize = pagesize + sizeof(struct tmem_handle);
> if ( (buf = realloc(buf,bufsize)) == NULL )
> - return -1;
> + goto failed;
> }
> for ( j = n_pages; j > 0; j-- )
> {
> @@ -290,21 +290,22 @@ int xc_tmem_save(xc_interface *xch,
> {
> h = (struct tmem_handle *)buf;
> if ( write_exact(io_fd, &h->oid, sizeof(h->oid)) )
> - return -1;
> + goto failed;
> if ( write_exact(io_fd, &h->index, sizeof(h->index)) )
> - return -1;
> + goto failed;
> h++;
> checksum += *(char *)h;
> if ( write_exact(io_fd, h, pagesize) )
> - return -1;
> + goto failed;
> } else if ( ret == 0 ) {
> continue;
> } else {
> /* page list terminator */
> h = (struct tmem_handle *)buf;
> h->oid[0] = h->oid[1] = h->oid[2] = -1L;
> - if ( write_exact(io_fd, &h->oid, sizeof(h->oid)) )
> - return -1;
> + if ( write_exact(io_fd, &h->oid, sizeof(h->oid)) ) {
> + goto failed;
> + }
Superfluous braces.
Otherwise, still fine.
~Andrew
> break;
> }
> }
> @@ -315,9 +316,13 @@ int xc_tmem_save(xc_interface *xch,
> /* pool list terminator */
> minusone = -1;
> if ( write_exact(io_fd, &minusone, sizeof(minusone)) )
> - return -1;
> + goto failed;
>
> + free(buf);
> return 1;
> +failed:
> + free(buf);
> + return -1;
> }
>
> /* only called for live migration */
> @@ -386,6 +391,7 @@ int xc_tmem_restore(xc_interface *xch, int dom, int io_fd)
> uint32_t minusone;
> uint32_t weight, cap, flags;
> int checksum = 0;
> + char *buf = NULL;
>
> save_version = xc_tmem_control(xch,0,TMEMC_SAVE_GET_VERSION,dom,0,0,0,NULL);
> if ( save_version == -1 )
> @@ -423,7 +429,6 @@ int xc_tmem_restore(xc_interface *xch, int dom, int io_fd)
> {
> uint64_t uuid[2];
> uint32_t n_pages;
> - char *buf = NULL;
> int bufsize = 0, pagesize;
> int j;
>
> @@ -445,7 +450,7 @@ int xc_tmem_restore(xc_interface *xch, int dom, int io_fd)
> {
> bufsize = pagesize;
> if ( (buf = realloc(buf,bufsize)) == NULL )
> - return -1;
> + goto failed;
> }
> for ( j = n_pages; j > 0; j-- )
> {
> @@ -453,20 +458,20 @@ int xc_tmem_restore(xc_interface *xch, int dom, int io_fd)
> uint32_t index;
> int rc;
> if ( read_exact(io_fd, &oid, sizeof(oid)) )
> - return -1;
> + goto failed;
> if ( oid.oid[0] == -1L && oid.oid[1] == -1L && oid.oid[2] == -1L )
> break;
> if ( read_exact(io_fd, &index, sizeof(index)) )
> - return -1;
> + goto failed;
> if ( read_exact(io_fd, buf, pagesize) )
> - return -1;
> + goto failed;
> checksum += *buf;
> if ( (rc = xc_tmem_control_oid(xch, pool_id,
> TMEMC_RESTORE_PUT_PAGE, dom,
> bufsize, index, oid, buf)) <= 0 )
> {
> DPRINTF("xc_tmem_restore: putting page failed, rc=%d\n",rc);
> - return -1;
> + goto failed;
> }
> }
> if ( n_pages )
> @@ -474,9 +479,13 @@ int xc_tmem_restore(xc_interface *xch, int dom, int io_fd)
> n_pages-j,dom,pool_id,checksum);
> }
> if ( pool_id != -1 )
> - return -1;
> + goto failed;
>
> + free(buf);
> return 0;
> +failed:
> + free(buf);
> + return -1;
> }
>
> /* only called for live migration, must be called after suspend */
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 2/4] xc/tmem: Unchecked return value (v2).
2014-04-30 20:29 ` [PATCH 2/4] xc/tmem: Unchecked return value (v2) Konrad Rzeszutek Wilk
@ 2014-04-30 20:46 ` Andrew Cooper
0 siblings, 0 replies; 10+ messages in thread
From: Andrew Cooper @ 2014-04-30 20:46 UTC (permalink / raw)
To: Konrad Rzeszutek Wilk, xen-devel, jbeulich, keir
On 30/04/2014 21:29, Konrad Rzeszutek Wilk wrote:
> CID 1055045 complains that the return value needs checking.
>
> The tmem op is a flush call and there is no expectation
> right now of any return besides zero. But just in case
> this changes lets blow up.
>
> CC: Bob Liu <bob.liu@oracle.com>
> Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
> [v2: Add a comment why bailing out on xc_tmem_save_done is not needed]
> ---
> tools/libxc/xc_domain_save.c | 8 ++++++--
> tools/libxc/xc_tmem.c | 4 ++--
> tools/libxc/xenctrl.h | 2 +-
> 3 files changed, 9 insertions(+), 5 deletions(-)
>
> diff --git a/tools/libxc/xc_domain_save.c b/tools/libxc/xc_domain_save.c
> index 71f9b59..b04e387 100644
> --- a/tools/libxc/xc_domain_save.c
> +++ b/tools/libxc/xc_domain_save.c
> @@ -2107,8 +2107,12 @@ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iter
> goto copypages;
> }
>
> - if ( tmem_saved != 0 && live )
> - xc_tmem_save_done(xch, dom);
> + if ( tmem_saved != 0 && live && xc_tmem_save_done(xch, dom))
Missing space before final bracket
> + {
> + /* N.B. No need to bail out - we leak memory, but that is all assigned
> + * to the zombie guest. */
> + DPRINTF("Warning - failed to flush tmem on originating server.");
> + }
And superfluous braces.
Functionally however, Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
~Andrew
>
> if ( live )
> {
> diff --git a/tools/libxc/xc_tmem.c b/tools/libxc/xc_tmem.c
> index 12fa105..6e01a6a 100644
> --- a/tools/libxc/xc_tmem.c
> +++ b/tools/libxc/xc_tmem.c
> @@ -356,9 +356,9 @@ int xc_tmem_save_extra(xc_interface *xch, int dom, int io_fd, int field_marker)
> }
>
> /* only called for live migration */
> -void xc_tmem_save_done(xc_interface *xch, int dom)
> +int xc_tmem_save_done(xc_interface *xch, int dom)
> {
> - xc_tmem_control(xch,0,TMEMC_SAVE_END,dom,0,0,0,NULL);
> + return xc_tmem_control(xch,0,TMEMC_SAVE_END,dom,0,0,0,NULL);
> }
>
> /* restore routines */
> diff --git a/tools/libxc/xenctrl.h b/tools/libxc/xenctrl.h
> index 02129f7..23630a7 100644
> --- a/tools/libxc/xenctrl.h
> +++ b/tools/libxc/xenctrl.h
> @@ -2011,7 +2011,7 @@ int xc_tmem_control(xc_interface *xch,
> int xc_tmem_auth(xc_interface *xch, int cli_id, char *uuid_str, int arg1);
> int xc_tmem_save(xc_interface *xch, int dom, int live, int fd, int field_marker);
> int xc_tmem_save_extra(xc_interface *xch, int dom, int fd, int field_marker);
> -void xc_tmem_save_done(xc_interface *xch, int dom);
> +int xc_tmem_save_done(xc_interface *xch, int dom);
> int xc_tmem_restore(xc_interface *xch, int dom, int fd);
> int xc_tmem_restore_extra(xc_interface *xch, int dom, int fd);
>
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 4/4] tmem: fix Out-of-bounds read reported by Coverity
2014-04-30 20:29 ` [PATCH 4/4] tmem: fix Out-of-bounds read reported by Coverity Konrad Rzeszutek Wilk
@ 2014-04-30 21:04 ` Andrew Cooper
2014-05-04 8:10 ` Bob Liu
0 siblings, 1 reply; 10+ messages in thread
From: Andrew Cooper @ 2014-04-30 21:04 UTC (permalink / raw)
To: Konrad Rzeszutek Wilk, xen-devel, jbeulich, keir
On 30/04/2014 21:29, Konrad Rzeszutek Wilk wrote:
> From: Bob Liu <bob.liu@oracle.com>
>
> CID 1198729, CID 1198730 and CID 1198734 complain about
> "Out-of-bounds read".
>
> This patch fixes them by casting the 'firstbyte' to (uint8_t).
>
> Signed-off-by: Bob Liu <bob.liu@oracle.com>
> Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
> ---
> xen/common/tmem.c | 4 ++--
> 1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/xen/common/tmem.c b/xen/common/tmem.c
> index f2dc26e..506c6be 100644
> --- a/xen/common/tmem.c
> +++ b/xen/common/tmem.c
> @@ -399,7 +399,7 @@ static void pcd_disassociate(struct tmem_page_descriptor *pgp, struct tmem_pool
> {
> struct tmem_page_content_descriptor *pcd = pgp->pcd;
> struct page_info *pfp = pgp->pcd->pfp;
> - uint16_t firstbyte = pgp->firstbyte;
> + uint8_t firstbyte = pgp->firstbyte;
Actually looking at these CIDs, I think this is a coverity bug rather
than a tmem bug.
The two asserts
ASSERT(firstbyte != NOT_SHAREABLE); /* for NOT_SHAREABLE being
(uint16_t)-1UL; */
ASSERT(firstbyte < 256);
Cause the coverity analysis engine to decide:
"cond_const: Checking firstbyte != 65535 implies that firstbyte and
pgp->firstbyte have the value 65535 on the false branch."
despite the fact that the second assert entirely covering the first.
Furthermore, I don't understand why the ASSERT() killpath isn't
invalidating any analysis on the false branch of an ASSERT().
If you are changing uint16_t to uint8_t, you can drop those two asserts
as well, as they become unconditionally true.
> char *pcd_tze = pgp->pcd->tze;
> pagesize_t pcd_size = pcd->size;
> pagesize_t pgp_size = pgp->size;
> @@ -1231,7 +1231,7 @@ static bool_t tmem_try_to_evict_pgp(struct tmem_page_descriptor *pgp, bool_t *ho
> struct tmem_object_root *obj = pgp->us.obj;
> struct tmem_pool *pool = obj->pool;
> struct client *client = pool->client;
> - uint16_t firstbyte = pgp->firstbyte;
> + uint8_t firstbyte = pgp->firstbyte;
>
> if ( pool->is_dying )
> return 0;
Given the "if ( firstbyte == NOT_SHAREABLE ) goto obj_unlock;", are you
certain this change is safe?
~Andrew
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 4/4] tmem: fix Out-of-bounds read reported by Coverity
2014-04-30 21:04 ` Andrew Cooper
@ 2014-05-04 8:10 ` Bob Liu
2014-05-05 11:08 ` Andrew Cooper
0 siblings, 1 reply; 10+ messages in thread
From: Bob Liu @ 2014-05-04 8:10 UTC (permalink / raw)
To: Andrew Cooper; +Cc: xen-devel, keir, jbeulich
Hi Andrew,
On 05/01/2014 05:04 AM, Andrew Cooper wrote:
> On 30/04/2014 21:29, Konrad Rzeszutek Wilk wrote:
>> From: Bob Liu <bob.liu@oracle.com>
>>
>> CID 1198729, CID 1198730 and CID 1198734 complain about
>> "Out-of-bounds read".
>>
>> This patch fixes them by casting the 'firstbyte' to (uint8_t).
>>
>> Signed-off-by: Bob Liu <bob.liu@oracle.com>
>> Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
>> ---
>> xen/common/tmem.c | 4 ++--
>> 1 file changed, 2 insertions(+), 2 deletions(-)
>>
>> diff --git a/xen/common/tmem.c b/xen/common/tmem.c
>> index f2dc26e..506c6be 100644
>> --- a/xen/common/tmem.c
>> +++ b/xen/common/tmem.c
>> @@ -399,7 +399,7 @@ static void pcd_disassociate(struct tmem_page_descriptor *pgp, struct tmem_pool
>> {
>> struct tmem_page_content_descriptor *pcd = pgp->pcd;
>> struct page_info *pfp = pgp->pcd->pfp;
>> - uint16_t firstbyte = pgp->firstbyte;
>> + uint8_t firstbyte = pgp->firstbyte;
>
> Actually looking at these CIDs, I think this is a coverity bug rather
> than a tmem bug.
>
Thanks for you review!
Yes, I also think so.
> The two asserts
>
> ASSERT(firstbyte != NOT_SHAREABLE); /* for NOT_SHAREABLE being
> (uint16_t)-1UL; */
> ASSERT(firstbyte < 256);
>
> Cause the coverity analysis engine to decide:
>
> "cond_const: Checking firstbyte != 65535 implies that firstbyte and
> pgp->firstbyte have the value 65535 on the false branch."
>
> despite the fact that the second assert entirely covering the first.
> Furthermore, I don't understand why the ASSERT() killpath isn't
> invalidating any analysis on the false branch of an ASSERT().
>
> If you are changing uint16_t to uint8_t, you can drop those two asserts
> as well, as they become unconditionally true.
>
Okay.
And since NOT_SHAREABLE has been checked before pcd_disassociate() every
time.
if ( tmem_dedup_enabled() && pgp->firstbyte != NOT_SHAREABLE )
pcd_disassociate(pgp,pool,0); /* pgp->size lost */
I think the casting from uint16_t to uint8_t in pcd_disassociate() is safe.
>> char *pcd_tze = pgp->pcd->tze;
>> pagesize_t pcd_size = pcd->size;
>> pagesize_t pgp_size = pgp->size;
>> @@ -1231,7 +1231,7 @@ static bool_t tmem_try_to_evict_pgp(struct tmem_page_descriptor *pgp, bool_t *ho
>> struct tmem_object_root *obj = pgp->us.obj;
>> struct tmem_pool *pool = obj->pool;
>> struct client *client = pool->client;
>> - uint16_t firstbyte = pgp->firstbyte;
>> + uint8_t firstbyte = pgp->firstbyte;
>>
>> if ( pool->is_dying )
>> return 0;
>
> Given the "if ( firstbyte == NOT_SHAREABLE ) goto obj_unlock;", are you
> certain this change is safe?
>
No, it's unsafe here. I think we can use pgp->firstbyte directly here.
How about this one?
>From 91469a2d85d0145d06fa048017d25d273ce4c0dc Mon Sep 17 00:00:00 2001
From: Bob Liu <bob.liu@oracle.com>
Date: Sun, 4 May 2014 15:59:09 +0800
Subject: [PATCH v2 4/4] tmem: fix Out-of-bounds read reported by Coverity
CID 1198729, CID 1198730 and CID 1198734 complain about
"Out-of-bounds read".
This patch fixes them by casting the 'firstbyte' to (uint8_t), some
unnecessary assertion also be dropped.
Signed-off-by: Bob Liu <bob.liu@oracle.com>
---
xen/common/tmem.c | 11 ++++-------
1 file changed, 4 insertions(+), 7 deletions(-)
diff --git a/xen/common/tmem.c b/xen/common/tmem.c
index f2dc26e..93235c6 100644
--- a/xen/common/tmem.c
+++ b/xen/common/tmem.c
@@ -399,7 +399,7 @@ static void pcd_disassociate(struct
tmem_page_descriptor *pgp, struct tmem_pool
{
struct tmem_page_content_descriptor *pcd = pgp->pcd;
struct page_info *pfp = pgp->pcd->pfp;
- uint16_t firstbyte = pgp->firstbyte;
+ uint8_t firstbyte = pgp->firstbyte;
char *pcd_tze = pgp->pcd->tze;
pagesize_t pcd_size = pcd->size;
pagesize_t pgp_size = pgp->size;
@@ -407,8 +407,6 @@ static void pcd_disassociate(struct
tmem_page_descriptor *pgp, struct tmem_pool
pagesize_t pcd_csize = pgp->pcd->size;
ASSERT(tmem_dedup_enabled());
- ASSERT(firstbyte != NOT_SHAREABLE);
- ASSERT(firstbyte < 256);
if ( have_pcd_rwlock )
ASSERT_WRITELOCK(&pcd_tree_rwlocks[firstbyte]);
@@ -1231,7 +1229,7 @@ static bool_t tmem_try_to_evict_pgp(struct
tmem_page_descriptor *pgp, bool_t *ho
struct tmem_object_root *obj = pgp->us.obj;
struct tmem_pool *pool = obj->pool;
struct client *client = pool->client;
- uint16_t firstbyte = pgp->firstbyte;
+ uint8_t firstbyte = pgp->firstbyte;
if ( pool->is_dying )
return 0;
@@ -1239,10 +1237,9 @@ static bool_t tmem_try_to_evict_pgp(struct
tmem_page_descriptor *pgp, bool_t *ho
{
if ( tmem_dedup_enabled() )
{
- firstbyte = pgp->firstbyte;
- if ( firstbyte == NOT_SHAREABLE )
+ if ( pgp->firstbyte == NOT_SHAREABLE )
goto obj_unlock;
- ASSERT(firstbyte < 256);
+ firstbyte = pgp->firstbyte;
if ( !write_trylock(&pcd_tree_rwlocks[firstbyte]) )
goto obj_unlock;
if ( pgp->pcd->pgp_ref_count > 1 && !pgp->eviction_attempted )
--
1.7.10.4
^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH 4/4] tmem: fix Out-of-bounds read reported by Coverity
2014-05-04 8:10 ` Bob Liu
@ 2014-05-05 11:08 ` Andrew Cooper
0 siblings, 0 replies; 10+ messages in thread
From: Andrew Cooper @ 2014-05-05 11:08 UTC (permalink / raw)
To: Bob Liu; +Cc: xen-devel, keir, jbeulich
On 04/05/2014 09:10, Bob Liu wrote:
> Hi Andrew,
>
> On 05/01/2014 05:04 AM, Andrew Cooper wrote:
>> On 30/04/2014 21:29, Konrad Rzeszutek Wilk wrote:
>>> From: Bob Liu <bob.liu@oracle.com>
>>>
>>> CID 1198729, CID 1198730 and CID 1198734 complain about
>>> "Out-of-bounds read".
>>>
>>> This patch fixes them by casting the 'firstbyte' to (uint8_t).
>>>
>>> Signed-off-by: Bob Liu <bob.liu@oracle.com>
>>> Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
>>> ---
>>> xen/common/tmem.c | 4 ++--
>>> 1 file changed, 2 insertions(+), 2 deletions(-)
>>>
>>> diff --git a/xen/common/tmem.c b/xen/common/tmem.c
>>> index f2dc26e..506c6be 100644
>>> --- a/xen/common/tmem.c
>>> +++ b/xen/common/tmem.c
>>> @@ -399,7 +399,7 @@ static void pcd_disassociate(struct tmem_page_descriptor *pgp, struct tmem_pool
>>> {
>>> struct tmem_page_content_descriptor *pcd = pgp->pcd;
>>> struct page_info *pfp = pgp->pcd->pfp;
>>> - uint16_t firstbyte = pgp->firstbyte;
>>> + uint8_t firstbyte = pgp->firstbyte;
>> Actually looking at these CIDs, I think this is a coverity bug rather
>> than a tmem bug.
>>
> Thanks for you review!
> Yes, I also think so.
>
>> The two asserts
>>
>> ASSERT(firstbyte != NOT_SHAREABLE); /* for NOT_SHAREABLE being
>> (uint16_t)-1UL; */
>> ASSERT(firstbyte < 256);
>>
>> Cause the coverity analysis engine to decide:
>>
>> "cond_const: Checking firstbyte != 65535 implies that firstbyte and
>> pgp->firstbyte have the value 65535 on the false branch."
>>
>> despite the fact that the second assert entirely covering the first.
>> Furthermore, I don't understand why the ASSERT() killpath isn't
>> invalidating any analysis on the false branch of an ASSERT().
>>
>> If you are changing uint16_t to uint8_t, you can drop those two asserts
>> as well, as they become unconditionally true.
>>
> Okay.
>
> And since NOT_SHAREABLE has been checked before pcd_disassociate() every
> time.
>
> if ( tmem_dedup_enabled() && pgp->firstbyte != NOT_SHAREABLE )
> pcd_disassociate(pgp,pool,0); /* pgp->size lost */
>
> I think the casting from uint16_t to uint8_t in pcd_disassociate() is safe.
>
>>> char *pcd_tze = pgp->pcd->tze;
>>> pagesize_t pcd_size = pcd->size;
>>> pagesize_t pgp_size = pgp->size;
>>> @@ -1231,7 +1231,7 @@ static bool_t tmem_try_to_evict_pgp(struct tmem_page_descriptor *pgp, bool_t *ho
>>> struct tmem_object_root *obj = pgp->us.obj;
>>> struct tmem_pool *pool = obj->pool;
>>> struct client *client = pool->client;
>>> - uint16_t firstbyte = pgp->firstbyte;
>>> + uint8_t firstbyte = pgp->firstbyte;
>>>
>>> if ( pool->is_dying )
>>> return 0;
>> Given the "if ( firstbyte == NOT_SHAREABLE ) goto obj_unlock;", are you
>> certain this change is safe?
>>
> No, it's unsafe here. I think we can use pgp->firstbyte directly here.
>
> How about this one?
>
> From 91469a2d85d0145d06fa048017d25d273ce4c0dc Mon Sep 17 00:00:00 2001
> From: Bob Liu <bob.liu@oracle.com>
> Date: Sun, 4 May 2014 15:59:09 +0800
> Subject: [PATCH v2 4/4] tmem: fix Out-of-bounds read reported by Coverity
>
> CID 1198729, CID 1198730 and CID 1198734 complain about
> "Out-of-bounds read".
>
> This patch fixes them by casting the 'firstbyte' to (uint8_t), some
> unnecessary assertion also be dropped.
>
> Signed-off-by: Bob Liu <bob.liu@oracle.com>
That looks better. Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
> ---
> xen/common/tmem.c | 11 ++++-------
> 1 file changed, 4 insertions(+), 7 deletions(-)
>
> diff --git a/xen/common/tmem.c b/xen/common/tmem.c
> index f2dc26e..93235c6 100644
> --- a/xen/common/tmem.c
> +++ b/xen/common/tmem.c
> @@ -399,7 +399,7 @@ static void pcd_disassociate(struct
> tmem_page_descriptor *pgp, struct tmem_pool
> {
> struct tmem_page_content_descriptor *pcd = pgp->pcd;
> struct page_info *pfp = pgp->pcd->pfp;
> - uint16_t firstbyte = pgp->firstbyte;
> + uint8_t firstbyte = pgp->firstbyte;
> char *pcd_tze = pgp->pcd->tze;
> pagesize_t pcd_size = pcd->size;
> pagesize_t pgp_size = pgp->size;
> @@ -407,8 +407,6 @@ static void pcd_disassociate(struct
> tmem_page_descriptor *pgp, struct tmem_pool
> pagesize_t pcd_csize = pgp->pcd->size;
>
> ASSERT(tmem_dedup_enabled());
> - ASSERT(firstbyte != NOT_SHAREABLE);
> - ASSERT(firstbyte < 256);
>
> if ( have_pcd_rwlock )
> ASSERT_WRITELOCK(&pcd_tree_rwlocks[firstbyte]);
> @@ -1231,7 +1229,7 @@ static bool_t tmem_try_to_evict_pgp(struct
> tmem_page_descriptor *pgp, bool_t *ho
> struct tmem_object_root *obj = pgp->us.obj;
> struct tmem_pool *pool = obj->pool;
> struct client *client = pool->client;
> - uint16_t firstbyte = pgp->firstbyte;
> + uint8_t firstbyte = pgp->firstbyte;
>
> if ( pool->is_dying )
> return 0;
> @@ -1239,10 +1237,9 @@ static bool_t tmem_try_to_evict_pgp(struct
> tmem_page_descriptor *pgp, bool_t *ho
> {
> if ( tmem_dedup_enabled() )
> {
> - firstbyte = pgp->firstbyte;
> - if ( firstbyte == NOT_SHAREABLE )
> + if ( pgp->firstbyte == NOT_SHAREABLE )
> goto obj_unlock;
> - ASSERT(firstbyte < 256);
> + firstbyte = pgp->firstbyte;
> if ( !write_trylock(&pcd_tree_rwlocks[firstbyte]) )
> goto obj_unlock;
> if ( pgp->pcd->pgp_ref_count > 1 && !pgp->eviction_attempted )
^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2014-05-05 11:08 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-04-30 20:29 [PATCH] tmem fixes for Xen 4.5 - coverity inspired Konrad Rzeszutek Wilk
2014-04-30 20:29 ` [PATCH 1/4] xc/tmem: Free temporary buffer used during migration Konrad Rzeszutek Wilk
2014-04-30 20:43 ` Andrew Cooper
2014-04-30 20:29 ` [PATCH 2/4] xc/tmem: Unchecked return value (v2) Konrad Rzeszutek Wilk
2014-04-30 20:46 ` Andrew Cooper
2014-04-30 20:29 ` [PATCH 3/4] tmem: drop unnecessary lock in tmem_relinquish_pages() Konrad Rzeszutek Wilk
2014-04-30 20:29 ` [PATCH 4/4] tmem: fix Out-of-bounds read reported by Coverity Konrad Rzeszutek Wilk
2014-04-30 21:04 ` Andrew Cooper
2014-05-04 8:10 ` Bob Liu
2014-05-05 11:08 ` Andrew Cooper
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).