* [PATCH]: fix crash in various tools by permitting xs_*() with NULL path
@ 2010-07-20 15:55 Gianni Tedesco
2010-07-20 16:27 ` Ian Jackson
0 siblings, 1 reply; 9+ messages in thread
From: Gianni Tedesco @ 2010-07-20 15:55 UTC (permalink / raw)
To: Xen Devel
Many tools generate xenstore paths and then perform operations on those
paths without checking for NULL. The problem with this is that xs_single
and xs_talkv use iovecs where len is set to strlen(NULL) + 1 leading to
a deref.
While strictly this may be considered a bug in the tools it makes sense
to consider making these no-ops as a convenience measure.
If the iov_len for NULL is set to 0 then this causes xenstored not to
respond and for the client to hang indefinitely. For this reason the
entry to each affected library function is modified to check for NULL.
I have left xs_watch and xs_unwatch as before since there is no
reasonable no-op implementation that I can think of.
Signed-off-by: Gianni Tedesco <gianni.tedesco@citrix.com>
xenstore/xs.c | 18 ++++++++++++++++++
xenstore/xs.h | 4 ++++
3 files changed, 23 insertions(+), 1 deletion(-)
diff -r 108ee7b37ac4 tools/xenstore/xs.c
--- a/tools/xenstore/xs.c Tue Jul 20 15:01:15 2010 +0100
+++ b/tools/xenstore/xs.c Tue Jul 20 16:44:43 2010 +0100
@@ -474,6 +474,9 @@
char *strings, *p, **ret;
unsigned int len;
+ if ( NULL == path )
+ return NULL;
+
strings = xs_single(h, t, XS_DIRECTORY, path, &len);
if (!strings)
return NULL;
@@ -503,6 +506,8 @@
void *xs_read(struct xs_handle *h, xs_transaction_t t,
const char *path, unsigned int *len)
{
+ if ( NULL == path )
+ return NULL;
return xs_single(h, t, XS_READ, path, len);
}
@@ -514,6 +519,9 @@
{
struct iovec iovec[2];
+ if ( NULL == path )
+ return true;
+
iovec[0].iov_base = (void *)path;
iovec[0].iov_len = strlen(path) + 1;
iovec[1].iov_base = (void *)data;
@@ -529,6 +537,8 @@
bool xs_mkdir(struct xs_handle *h, xs_transaction_t t,
const char *path)
{
+ if ( NULL == path )
+ return true;
return xs_bool(xs_single(h, t, XS_MKDIR, path, NULL));
}
@@ -538,6 +548,8 @@
bool xs_rm(struct xs_handle *h, xs_transaction_t t,
const char *path)
{
+ if ( NULL == path )
+ return true;
return xs_bool(xs_single(h, t, XS_RM, path, NULL));
}
@@ -552,6 +564,9 @@
unsigned int len;
struct xs_permissions *ret;
+ if ( NULL == path )
+ return NULL;
+
strings = xs_single(h, t, XS_GET_PERMS, path, &len);
if (!strings)
return NULL;
@@ -587,6 +602,9 @@
unsigned int i;
struct iovec iov[1+num_perms];
+ if ( NULL == path )
+ return true;
+
iov[0].iov_base = (void *)path;
iov[0].iov_len = strlen(path) + 1;
diff -r 108ee7b37ac4 tools/xenstore/xs.h
--- a/tools/xenstore/xs.h Tue Jul 20 15:01:15 2010 +0100
+++ b/tools/xenstore/xs.h Tue Jul 20 16:44:43 2010 +0100
@@ -110,6 +110,8 @@
* When the node (or any child) changes, fd will become readable.
* Token is returned when watch is read, to allow matching.
* Returns false on failure.
+ *
+ * path must be non-NULL
*/
bool xs_watch(struct xs_handle *h, const char *path, const char *token);
@@ -124,6 +126,8 @@
/* Remove a watch on a node: implicitly acks any outstanding watch.
* Returns false on failure (no watch on that node).
+ *
+ * path must be non-NULL
*/
bool xs_unwatch(struct xs_handle *h, const char *path, const char *token);
^ permalink raw reply [flat|nested] 9+ messages in thread* Re: [PATCH]: fix crash in various tools by permitting xs_*() with NULL path 2010-07-20 15:55 [PATCH]: fix crash in various tools by permitting xs_*() with NULL path Gianni Tedesco @ 2010-07-20 16:27 ` Ian Jackson 2010-07-20 17:02 ` Gianni Tedesco ` (3 more replies) 0 siblings, 4 replies; 9+ messages in thread From: Ian Jackson @ 2010-07-20 16:27 UTC (permalink / raw) To: Gianni Tedesco; +Cc: Xen Devel Gianni Tedesco writes ("[Xen-devel] [PATCH]: fix crash in various tools by permitting xs_*() with NULL path"): > Many tools generate xenstore paths and then perform operations on those > paths without checking for NULL. Do they ? Those tools are buggy. > While strictly this may be considered a bug in the tools it makes sense > to consider making these no-ops as a convenience measure. I think this is fine for things like deletion but not otherwise. So I think in the case of libxenstore only xs_rm should be modified like this. > @@ -503,6 +506,8 @@ > void *xs_read(struct xs_handle *h, xs_transaction_t t, > const char *path, unsigned int *len) > { > + if ( NULL == path ) > + return NULL; > return xs_single(h, t, XS_READ, path, len); > } > This pattern is wrong. Firstly, all functions in libxenstore set errno when returning errors and if you are going to return NULL you need to to do so as well. Secondly, it is not appropriate to turn xs_read(,,NULL,) into an error. It should crash. Compare the C standard library. If you call fprintf(NULL,...) it doesn't return EOF setting errno to EFAULT, it coredumps, and rightly so. Finally, to review this patch, it would be much more helpful if you used a diff tool which includes the function name in the diff output. Without that we have to apply the patch to a tree of our own and regenerate the diff. > + * > + * path must be non-NULL This should not be added here. Competent C programmers will not expect to be able to pass NULL to things unless told they can. So the assumption is the other way around. You should add a note saying that NULL is permitted where it is. Nacked-by: Ian Jackson <ian.jackson@eu.citrix.com> Sorry, Ian. ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH]: fix crash in various tools by permitting xs_*() with NULL path 2010-07-20 16:27 ` Ian Jackson @ 2010-07-20 17:02 ` Gianni Tedesco 2010-07-26 9:45 ` Paolo Bonzini 2010-07-20 17:16 ` Gianni Tedesco ` (2 subsequent siblings) 3 siblings, 1 reply; 9+ messages in thread From: Gianni Tedesco @ 2010-07-20 17:02 UTC (permalink / raw) To: Ian Jackson; +Cc: Xen Devel On Tue, 2010-07-20 at 17:27 +0100, Ian Jackson wrote: > Gianni Tedesco writes ("[Xen-devel] [PATCH]: fix crash in various tools by permitting xs_*() with NULL path"): > > Many tools generate xenstore paths and then perform operations on those > > paths without checking for NULL. > > Do they ? Those tools are buggy. Yes, but for example libxl has around 300 calls to libxl_sprintf() which are used un-checked as xenstore paths... We could either check every result or check for ENOMEM in one place and abort() since NULL deref has much the same effect. > > While strictly this may be considered a bug in the tools it makes sense > > to consider making these no-ops as a convenience measure. > > I think this is fine for things like deletion but not otherwise. So I > think in the case of libxenstore only xs_rm should be modified like > this. I'm not so sure, I think NULL path should have some coherent meaning - whether that's just to segfault or something else is another discussion. > > @@ -503,6 +506,8 @@ > > void *xs_read(struct xs_handle *h, xs_transaction_t t, > > const char *path, unsigned int *len) > > { > > + if ( NULL == path ) > > + return NULL; > > return xs_single(h, t, XS_READ, path, len); > > } > > > > This pattern is wrong. Firstly, all functions in libxenstore set > errno when returning errors and if you are going to return NULL you > need to to do so as well. Secondly, it is not appropriate to turn > xs_read(,,NULL,) into an error. It should crash. > > Compare the C standard library. If you call fprintf(NULL,...) it > doesn't return EOF setting errno to EFAULT, it coredumps, and rightly > so. On the contrary open(NULL, O_RDONLY) will... The difference is FILE * is a struct wheras the change I am proposing in this case is to treat NULL as the empty string in the case of paths. > Finally, to review this patch, it would be much more helpful if you > used a diff tool which includes the function name in the diff output. > Without that we have to apply the patch to a tree of our own and > regenerate the diff. good point > > + * > > + * path must be non-NULL > > This should not be added here. Competent C programmers will not > expect to be able to pass NULL to things unless told they can. So the > assumption is the other way around. You should add a note saying > that NULL is permitted where it is. OK > Nacked-by: Ian Jackson <ian.jackson@eu.citrix.com> > > Sorry, > Ian. How about the following? If this is a total no-go then I'll fix the callers. Thanks for review Signed-off-by: Gianni Tedesco <gianni.tedesco@citrix.com> diff -r 108ee7b37ac4 tools/xenstore/xs.h --- a/tools/xenstore/xs.h Tue Jul 20 15:01:15 2010 +0100 +++ b/tools/xenstore/xs.h Tue Jul 20 17:56:34 2010 +0100 @@ -34,6 +34,11 @@ typedef uint32_t xs_transaction_t; /* On failure, these routines set errno. */ +/* In general path may be NULL and represents the empty string, + * write type operations will always succeed and read type operations + * will always fail. The watch/unwatch operations will segfault. + */ + /* Connect to the xs daemon. * Returns a handle or NULL. */ diff -r 108ee7b37ac4 tools/xenstore/xs.c --- a/tools/xenstore/xs.c Tue Jul 20 15:01:15 2010 +0100 +++ b/tools/xenstore/xs.c Tue Jul 20 17:56:34 2010 +0100 @@ -474,6 +474,11 @@ char **xs_directory(struct xs_handle *h, char *strings, *p, **ret; unsigned int len; + if ( NULL == path ) { + errno = ENOENT; + return NULL; + } + strings = xs_single(h, t, XS_DIRECTORY, path, &len); if (!strings) return NULL; @@ -503,6 +508,10 @@ char **xs_directory(struct xs_handle *h, void *xs_read(struct xs_handle *h, xs_transaction_t t, const char *path, unsigned int *len) { + if ( NULL == path ) { + errno = ENOENT; + return NULL; + } return xs_single(h, t, XS_READ, path, len); } @@ -514,6 +523,9 @@ bool xs_write(struct xs_handle *h, xs_tr { struct iovec iovec[2]; + if ( NULL == path ) + return true; + iovec[0].iov_base = (void *)path; iovec[0].iov_len = strlen(path) + 1; iovec[1].iov_base = (void *)data; @@ -529,6 +541,8 @@ bool xs_write(struct xs_handle *h, xs_tr bool xs_mkdir(struct xs_handle *h, xs_transaction_t t, const char *path) { + if ( NULL == path ) + return true; return xs_bool(xs_single(h, t, XS_MKDIR, path, NULL)); } @@ -538,6 +552,8 @@ bool xs_mkdir(struct xs_handle *h, xs_tr bool xs_rm(struct xs_handle *h, xs_transaction_t t, const char *path) { + if ( NULL == path ) + return true; return xs_bool(xs_single(h, t, XS_RM, path, NULL)); } @@ -552,6 +568,11 @@ struct xs_permissions *xs_get_permission unsigned int len; struct xs_permissions *ret; + if ( NULL == path ) { + errno = ENOENT; + return NULL; + } + strings = xs_single(h, t, XS_GET_PERMS, path, &len); if (!strings) return NULL; @@ -587,6 +608,9 @@ bool xs_set_permissions(struct xs_handle unsigned int i; struct iovec iov[1+num_perms]; + if ( NULL == path ) + return true; + iov[0].iov_base = (void *)path; iov[0].iov_len = strlen(path) + 1; ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH]: fix crash in various tools by permitting xs_*() with NULL path 2010-07-20 17:02 ` Gianni Tedesco @ 2010-07-26 9:45 ` Paolo Bonzini 0 siblings, 0 replies; 9+ messages in thread From: Paolo Bonzini @ 2010-07-26 9:45 UTC (permalink / raw) To: Gianni Tedesco; +Cc: Xen Devel, Ian Jackson On 07/20/2010 07:02 PM, Gianni Tedesco wrote: > On the contrary open(NULL, O_RDONLY) will... The difference is FILE * is > a struct wheras the change I am proposing in this case is to treat NULL > as the empty string in the case of paths. Returning EFAULT is one possible outcome, but a SIGSEGV or SIGBUS is also valid according to POSIX. Paolo ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH]: fix crash in various tools by permitting xs_*() with NULL path 2010-07-20 16:27 ` Ian Jackson 2010-07-20 17:02 ` Gianni Tedesco @ 2010-07-20 17:16 ` Gianni Tedesco 2010-07-20 17:32 ` [PATCH]: fix segfault in xl destroy when xenstore has been fowled up Gianni Tedesco 2010-07-21 8:41 ` [PATCH]: fix crash in various tools by permitting xs_*() with NULL path Ian Campbell 3 siblings, 0 replies; 9+ messages in thread From: Gianni Tedesco @ 2010-07-20 17:16 UTC (permalink / raw) To: Ian Jackson; +Cc: Xen Devel, Stefano Stabellini On Tue, 2010-07-20 at 17:27 +0100, Ian Jackson wrote: > Gianni Tedesco writes ("[Xen-devel] [PATCH]: fix crash in various tools by permitting xs_*() with NULL path"): > > Many tools generate xenstore paths and then perform operations on those > > paths without checking for NULL. > > Do they ? Those tools are buggy. > > > While strictly this may be considered a bug in the tools it makes sense > > to consider making these no-ops as a convenience measure. > > I think this is fine for things like deletion but not otherwise. So I > think in the case of libxenstore only xs_rm should be modified like > this. I may be defeating my own argument but here is an alternative (let's forget strdup() out of memory case and let it crash and burn): 8<--------------------- Fix segfault in xl destroy when xenstore has been fowled up libxl_dirname() returns NULL if a string is passed to it which doesn't look like a xenstore key. During xl destroy libxl_dirname is used to generate an xs path in order to remove device backend keys. If a nonsense key has been put in there resulting in NULL backend path this will crash xl. diff -r 1eea12f66951 tools/libxl/libxl_device.c --- a/tools/libxl/libxl_device.c Tue Jul 20 17:14:43 2010 +0100 +++ b/tools/libxl/libxl_device.c Tue Jul 20 18:05:19 2010 +0100 @@ -344,7 +344,8 @@ int libxl_devices_destroy(struct libxl_c } for (i = 0; i < n; i++) { flexarray_get(toremove, i, (void**) &path); - xs_rm(clone.xsh, XBT_NULL, path); + if ( path ) + xs_rm(clone.xsh, XBT_NULL, path); } flexarray_free(toremove); libxl_ctx_free(&clone); ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH]: fix segfault in xl destroy when xenstore has been fowled up 2010-07-20 16:27 ` Ian Jackson 2010-07-20 17:02 ` Gianni Tedesco 2010-07-20 17:16 ` Gianni Tedesco @ 2010-07-20 17:32 ` Gianni Tedesco 2010-07-21 13:48 ` Stefano Stabellini 2010-07-21 8:41 ` [PATCH]: fix crash in various tools by permitting xs_*() with NULL path Ian Campbell 3 siblings, 1 reply; 9+ messages in thread From: Gianni Tedesco @ 2010-07-20 17:32 UTC (permalink / raw) To: Ian Jackson; +Cc: Xen Devel, Stefano Stabellini Oops, forgot signed off by and change subject 8<--------------------- Fix segfault in xl destroy when xenstore has been fowled up libxl_dirname() returns NULL if a string is passed to it which doesn't look like a xenstore key. During xl destroy libxl_dirname is used to generate an xs path in order to remove device backend keys. If a nonsense key has been put in there resulting in NULL backend path this will crash xl. Signed-off-by: <gianni.tedesco@citrix.com> diff -r 1eea12f66951 tools/libxl/libxl_device.c --- a/tools/libxl/libxl_device.c Tue Jul 20 17:14:43 2010 +0100 +++ b/tools/libxl/libxl_device.c Tue Jul 20 18:05:19 2010 +0100 @@ -344,7 +344,8 @@ int libxl_devices_destroy(struct libxl_c } for (i = 0; i < n; i++) { flexarray_get(toremove, i, (void**) &path); - xs_rm(clone.xsh, XBT_NULL, path); + if ( path ) + xs_rm(clone.xsh, XBT_NULL, path); } flexarray_free(toremove); libxl_ctx_free(&clone); ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH]: fix segfault in xl destroy when xenstore has been fowled up 2010-07-20 17:32 ` [PATCH]: fix segfault in xl destroy when xenstore has been fowled up Gianni Tedesco @ 2010-07-21 13:48 ` Stefano Stabellini 2010-07-21 13:59 ` Ian Jackson 0 siblings, 1 reply; 9+ messages in thread From: Stefano Stabellini @ 2010-07-21 13:48 UTC (permalink / raw) To: Gianni Tedesco (3P); +Cc: Xen Devel, Ian Jackson, Stefano Stabellini On Tue, 20 Jul 2010, Gianni Tedesco (3P) wrote: > Oops, forgot signed off by and change subject > > 8<--------------------- > Fix segfault in xl destroy when xenstore has been fowled up > > libxl_dirname() returns NULL if a string is passed to it which doesn't > look like a xenstore key. During xl destroy libxl_dirname is used to > generate an xs path in order to remove device backend keys. If a > nonsense key has been put in there resulting in NULL backend path this > will crash xl. > > Signed-off-by: <gianni.tedesco@citrix.com> > > diff -r 1eea12f66951 tools/libxl/libxl_device.c > --- a/tools/libxl/libxl_device.c Tue Jul 20 17:14:43 2010 +0100 > +++ b/tools/libxl/libxl_device.c Tue Jul 20 18:05:19 2010 +0100 > @@ -344,7 +344,8 @@ int libxl_devices_destroy(struct libxl_c > } > for (i = 0; i < n; i++) { > flexarray_get(toremove, i, (void**) &path); > - xs_rm(clone.xsh, XBT_NULL, path); > + if ( path ) > + xs_rm(clone.xsh, XBT_NULL, path); > } > flexarray_free(toremove); > libxl_ctx_free(&clone); > I prefer the other approach. ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH]: fix segfault in xl destroy when xenstore has been fowled up 2010-07-21 13:48 ` Stefano Stabellini @ 2010-07-21 13:59 ` Ian Jackson 0 siblings, 0 replies; 9+ messages in thread From: Ian Jackson @ 2010-07-21 13:59 UTC (permalink / raw) To: Stefano Stabellini; +Cc: Xen Devel, Gianni Tedesco (3P) Stefano Stabellini writes ("Re: [Xen-devel] [PATCH]: fix segfault in xl destroy when xenstore has been fowled up"): > I prefer the other approach. Yes, for xs_rm I agree. Ian. ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH]: fix crash in various tools by permitting xs_*() with NULL path 2010-07-20 16:27 ` Ian Jackson ` (2 preceding siblings ...) 2010-07-20 17:32 ` [PATCH]: fix segfault in xl destroy when xenstore has been fowled up Gianni Tedesco @ 2010-07-21 8:41 ` Ian Campbell 3 siblings, 0 replies; 9+ messages in thread From: Ian Campbell @ 2010-07-21 8:41 UTC (permalink / raw) To: Ian Jackson; +Cc: Xen Devel, Gianni Tedesco On Tue, 2010-07-20 at 17:27 +0100, Ian Jackson wrote: > > Finally, to review this patch, it would be much more helpful if you > used a diff tool which includes the function name in the diff output. > Without that we have to apply the patch to a tree of our own and > regenerate the diff. The lack of this has annoyed me about mercurial for some time and this message provoked me into looking again at how to make it work. So for the benefit of others: "hg diff -p" seems to work (this option didn't exist last time I looked, which I admit was years ago) and adding [diff] showfunc = True to ~/.hgrc also works and seems to extend to "hg email" and "hg tip" (which do not take a -p) as well so is probably sufficient for most usecases. Hurrah. Ian. ^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2010-07-26 9:45 UTC | newest] Thread overview: 9+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2010-07-20 15:55 [PATCH]: fix crash in various tools by permitting xs_*() with NULL path Gianni Tedesco 2010-07-20 16:27 ` Ian Jackson 2010-07-20 17:02 ` Gianni Tedesco 2010-07-26 9:45 ` Paolo Bonzini 2010-07-20 17:16 ` Gianni Tedesco 2010-07-20 17:32 ` [PATCH]: fix segfault in xl destroy when xenstore has been fowled up Gianni Tedesco 2010-07-21 13:48 ` Stefano Stabellini 2010-07-21 13:59 ` Ian Jackson 2010-07-21 8:41 ` [PATCH]: fix crash in various tools by permitting xs_*() with NULL path Ian Campbell
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).