* [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
* 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
* [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
* 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
* [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 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).