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

problem with lifetime of krb5_ccache's...



Hello,

I've had a problem with krb5_ccache structs becoming invalid if they are used 
after the context struct they were created with gets freed.  The problem is 
that the krb5_ccache ops pointer is just a shallow copy from the context ops 
array and the cache ops pointer becomes invalid when the context is freed.

I hit this problem when dealing with pam modules- if you store a memory cache 
between pam calls you have problems if you try to copy that memory cache to a 
file one later.

Making a deep copy in allocate_ccache in krb5/cache.c fixes the problem for 
me.  It seems that this should be safe to do since the problem is the ops 
pointer in the krb5_ccache struct becoming invalid, but the actual data in 
the krb5_cc_ops struct should be the same since it's just function pointers + 
one char* anyway. 

I've attached a patch that fixes the problem for me.  Is this the right 
approach to fix this problem?

Wynn

Index: cache.c
===================================================================
RCS file: /col/csm/cvs/VAS/src/heimdal/lib/krb5/cache.c,v
retrieving revision 1.2
diff -u -p -B -w -r1.2 cache.c
--- cache.c	2002/05/29 15:23:50	1.2
+++ cache.c	2002/05/29 17:03:54
@@ -107,11 +107,34 @@ allocate_ccache (krb5_context context,
         krb5_set_error_string(context, "malloc: out of memory");
         return KRB5_CC_NOMEM;
     }
-    p->ops = ops;
+    
+    /* we make a deep copy so the ccache does not become invalid
+       when the context is free'd. krb5_cc_close free's all this
+       memory
+     */
+    p->ops = malloc(sizeof(*ops));
+    if( p->ops == NULL ) {
+        free(p);
+        krb5_set_error_string(context, "malloc: out of memory");
+        return KRB5_CC_NOMEM;
+    }
+    memcpy(p->ops, (const void*)ops, sizeof(*ops));
+    p->ops->prefix = strdup( ops->prefix );
+    if( p->ops->prefix == NULL ) {
+        free(p->ops);
+        free(p);
+        krb5_set_error_string(context, "malloc: out of memory");
+        return KRB5_CC_NOMEM;
+    }
+
     *id = p;
     ret = p->ops->resolve(context, id, residual);
     if( ret )
+    {
+        free(p->ops->prefix);
+        free(p->ops);
         free(p);
+    }
     return ret;
 }
 
@@ -265,8 +288,14 @@ krb5_cc_close(krb5_context context,
               krb5_ccache id) 
 {
     krb5_error_code ret;
+
     ret = id->ops->close(context, id);
+    
+    /* free all the memory since it was a deep copy */
+    free(id->ops->prefix);
+    free(id->ops);
     free(id);
+    
     return ret;
 }