[PATCH v3 02/16] util: Add safety net of checks to ensure valid object

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

 



The virObject logic "assumes" that whatever is passed to its API's
would be some sort of virObjectPtr; however, if it is not then some
really bad things can happen.

So far there's been only virObject{Ref|Unref}, virObject{Lock|Unlock},
and virObjectIsClass and the virObject and virObjectLockable class
consumers have been well behaved and code well tested. Soon there will
be more consumers and one such consumer tripped over this during testing
by passing a virHashTablePtr to virObjectIsClass which ends up calling
virClassIsDerivedFrom using "obj->klass", which wasn't really a klass
object causing one of those bad things to happen.

To avoid the future possibility that a non virObject class memory was
passed to some virObject* API, this patch adds two new checks - one
to validate that the object has the 0xCAFExxxx value in obj->->u.s.magic
and the other to ensure obj->u.s.magic doesn't "wrap" some day to
0xCAFF0000 if we ever get that many object classes. The check is also
moved before the name VIR_STRDUP to avoid the extra VIR_FREE that would
be required on the failure path.

It is still left up to the caller to handle the failed API calls just
as it would be if it passed a NULL opaque pointer anyobj.

Signed-off-by: John Ferlan <jferlan@xxxxxxxxxx>
---
 src/util/virobject.c | 26 +++++++++++++++++++-------
 1 file changed, 19 insertions(+), 7 deletions(-)

diff --git a/src/util/virobject.c b/src/util/virobject.c
index ff9385b..443718b 100644
--- a/src/util/virobject.c
+++ b/src/util/virobject.c
@@ -47,14 +47,21 @@ struct _virClass {
     virObjectDisposeCallback dispose;
 };
 
+#define VIR_OBJECT_NOTVALID(obj) (!obj || ((obj->u.s.magic & 0xCAFE0000) != 0xCAFE0000))
+
 #define VIR_OBJECT_USAGE_PRINT_WARNING(anyobj, objclass)                    \
     do {                                                                    \
         virObjectPtr obj = anyobj;                                          \
-        if (!obj)                                                           \
-            VIR_WARN("Object cannot be NULL");                              \
-        else                                                                \
+        if (VIR_OBJECT_NOTVALID(obj)) {                                     \
+            if (!obj)                                                       \
+                VIR_WARN("Object cannot be NULL");                          \
+            else                                                            \
+                VIR_WARN("Object %p has a bad magic number %X",             \
+                         obj, obj->u.s.magic);                              \
+        } else {                                                            \
             VIR_WARN("Object %p (%s) is not a %s instance",                 \
                       anyobj, obj->klass->name, #objclass);                 \
+        }                                                                   \
     } while (0)
 
 static virClassPtr virObjectClass;
@@ -153,9 +160,14 @@ virClassNew(virClassPtr parent,
         goto error;
 
     klass->parent = parent;
+    klass->magic = virAtomicIntInc(&magicCounter);
+    if (klass->magic > 0xCAFEFFFF) {
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                       _("too many object classes defined"));
+        goto error;
+    }
     if (VIR_STRDUP(klass->name, name) < 0)
         goto error;
-    klass->magic = virAtomicIntInc(&magicCounter);
     klass->objectSize = objectSize;
     klass->dispose = dispose;
 
@@ -272,7 +284,7 @@ virObjectUnref(void *anyobj)
 {
     virObjectPtr obj = anyobj;
 
-    if (!obj)
+    if (VIR_OBJECT_NOTVALID(obj))
         return false;
 
     bool lastRef = virAtomicIntDecAndTest(&obj->u.s.refs);
@@ -311,7 +323,7 @@ virObjectRef(void *anyobj)
 {
     virObjectPtr obj = anyobj;
 
-    if (!obj)
+    if (VIR_OBJECT_NOTVALID(obj))
         return NULL;
     virAtomicIntInc(&obj->u.s.refs);
     PROBE(OBJECT_REF, "obj=%p", obj);
@@ -389,7 +401,7 @@ virObjectIsClass(void *anyobj,
                  virClassPtr klass)
 {
     virObjectPtr obj = anyobj;
-    if (!obj)
+    if (VIR_OBJECT_NOTVALID(obj))
         return false;
 
     return virClassIsDerivedFrom(obj->klass, klass);
-- 
2.9.4

--
libvir-list mailing list
libvir-list@xxxxxxxxxx
https://www.redhat.com/mailman/listinfo/libvir-list



[Index of Archives]     [Virt Tools]     [Libvirt Users]     [Lib OS Info]     [Fedora Users]     [Fedora Desktop]     [Fedora SELinux]     [Big List of Linux Books]     [Yosemite News]     [KDE Users]     [Fedora Tools]
  Powered by Linux