[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Xen-devel] [PATCH]: fix crash in various tools by permitting xs_*() with NULL path



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@xxxxxxxxxxxxx>
> 
> 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@xxxxxxxxxx>

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;
        



_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.