Răsfoiți Sursa

Ticket 47803 - syncrepl crash if attribute list is non-empty

Bug Description:  if the list of requested attributes in a persistent
			sync repl request was set, the server could
			crash after a modify operation which should
			send an entry

Fix Description:   the reason for the crash was that the list of requested
			attributes was freed when the original search
			operation was completed. In the persit phase this
			list was still accessed.
			To fix it, a copy of the orignal op had to be used
                        and the list of requested attr duplicated and set
			in the copy of the op.
			unfortunately a reference to the original op is
			still needed as the disconnet code sets the abandonned
                        flag to the original op
			To be able to duplicate an operation, some methods to get
			and set operation attributes had to be provided

https://fedorahosted.org/389/ticket/47803

Reviewed by: RichM. ThanksRichM. Thanks
Ludwig Krispenz 11 ani în urmă
părinte
comite
a81a3ead42

+ 1 - 0
ldap/servers/plugins/sync/sync.h

@@ -158,6 +158,7 @@ typedef struct sync_queue_node {
  */
 typedef struct sync_request {
 	Slapi_PBlock	*req_pblock;
+	Slapi_Operation	*req_orig_op;
 	PRLock		*req_lock;
 	PRThread	*req_tid;
 	char 		*req_orig_base;

+ 3 - 5
ldap/servers/plugins/sync/sync_persist.c

@@ -292,6 +292,7 @@ sync_persist_add (Slapi_PBlock *pb)
 	if ( SYNC_IS_INITIALIZED() && NULL != pb ) {
 		/* Create the new node */
 		req = sync_request_alloc();
+		slapi_pblock_get(pb, SLAPI_OPERATION, &req->req_orig_op); /* neede to access original op */
 		req->req_pblock = sync_pblock_copy(pb);
 		slapi_pblock_get(pb, SLAPI_ORIGINAL_TARGET_DN, &base);
 		req->req_orig_base = slapi_ch_strdup(base);
@@ -566,7 +567,7 @@ sync_send_results( void *arg )
 	SyncQueueNode *qnode, *qnodenext;
 	int conn_acq_flag = 0;
 	Slapi_Connection *conn = NULL;
-	Slapi_Operation *op = NULL;
+	Slapi_Operation *op = req->req_orig_op;
 	int rc;
 	PRUint64 connid;
 	int opid;
@@ -574,7 +575,6 @@ sync_send_results( void *arg )
 	slapi_pblock_get(req->req_pblock, SLAPI_CONN_ID, &connid);
 	slapi_pblock_get(req->req_pblock, SLAPI_OPERATION_ID, &opid);
 	slapi_pblock_get(req->req_pblock, SLAPI_CONNECTION, &conn);
-	slapi_pblock_get(req->req_pblock, SLAPI_OPERATION, &op);
 
 	conn_acq_flag = sync_acquire_connection (conn);
 	if (conn_acq_flag) {
@@ -587,9 +587,7 @@ sync_send_results( void *arg )
 
 	while ( (conn_acq_flag == 0) && !req->req_complete && !plugin_closing) {
 		/* Check for an abandoned operation */
-		Slapi_Operation *op;
-		slapi_pblock_get(req->req_pblock, SLAPI_OPERATION, &op);
-		if ( op == NULL || slapi_op_abandoned( req->req_pblock ) ) {
+		if ( op == NULL || slapi_is_operation_abandoned( op ) ) {
 			slapi_log_error(SLAPI_LOG_PLUGIN, "Content Synchronization Search",
 						"conn=%" NSPRIu64 " op=%d Operation no longer active - terminating\n",
 						(long long unsigned int)connid, opid);

+ 13 - 3
ldap/servers/plugins/sync/sync_util.c

@@ -644,18 +644,21 @@ Slapi_PBlock *
 sync_pblock_copy(Slapi_PBlock *src)
 {
 	Slapi_Operation *operation;
+	Slapi_Operation *operation_new;
 	Slapi_Connection *connection;
 	int *scope;
 	int *deref;
 	int *filter_normalized;
 	char *fstr;
 	char **attrs, **attrs_dup;
+	char **reqattrs, **reqattrs_dup;
 	int *attrsonly;
 	int *isroot;
 	int *sizelimit;
 	int *timelimit;
 	struct slapdplugin *pi;
-
+	ber_int_t msgid;
+        ber_tag_t tag;
 
 	slapi_pblock_get( src, SLAPI_OPERATION, &operation );
 	slapi_pblock_get( src, SLAPI_CONNECTION, &connection );
@@ -664,6 +667,7 @@ sync_pblock_copy(Slapi_PBlock *src)
 	slapi_pblock_get( src, SLAPI_PLUGIN_SYNTAX_FILTER_NORMALIZED, &filter_normalized );
 	slapi_pblock_get( src, SLAPI_SEARCH_STRFILTER, &fstr );
 	slapi_pblock_get( src, SLAPI_SEARCH_ATTRS, &attrs );
+	slapi_pblock_get( src, SLAPI_SEARCH_REQATTRS, &reqattrs );
 	slapi_pblock_get( src, SLAPI_SEARCH_ATTRSONLY, &attrsonly );
 	slapi_pblock_get( src, SLAPI_REQUESTOR_ISROOT, &isroot );
 	slapi_pblock_get( src, SLAPI_SEARCH_SIZELIMIT, &sizelimit );
@@ -671,15 +675,21 @@ sync_pblock_copy(Slapi_PBlock *src)
 	slapi_pblock_get( src, SLAPI_PLUGIN, &pi);
 
 	Slapi_PBlock *dest = slapi_pblock_new();
-
-	slapi_pblock_set( dest, SLAPI_OPERATION, operation );
+	operation_new = slapi_operation_new(0);
+	msgid = slapi_operation_get_msgid(operation);
+	slapi_operation_set_msgid(operation_new, msgid);
+	tag = slapi_operation_get_tag(operation);
+	slapi_operation_set_tag(operation_new, tag);
+	slapi_pblock_set( dest, SLAPI_OPERATION, operation_new );
 	slapi_pblock_set( dest, SLAPI_CONNECTION, connection );
 	slapi_pblock_set( dest, SLAPI_SEARCH_SCOPE, &scope );
 	slapi_pblock_set( dest, SLAPI_SEARCH_DEREF, &deref );
 	slapi_pblock_set( dest, SLAPI_PLUGIN_SYNTAX_FILTER_NORMALIZED, &filter_normalized );
 	slapi_pblock_set( dest, SLAPI_SEARCH_STRFILTER, slapi_ch_strdup(fstr) );
 	attrs_dup = slapi_ch_array_dup(attrs);
+	reqattrs_dup = slapi_ch_array_dup(reqattrs);
 	slapi_pblock_set( dest, SLAPI_SEARCH_ATTRS, attrs_dup );
+	slapi_pblock_set( dest, SLAPI_SEARCH_REQATTRS, reqattrs_dup );
 	slapi_pblock_set( dest, SLAPI_SEARCH_ATTRSONLY, &attrsonly );
 	slapi_pblock_set( dest, SLAPI_REQUESTOR_ISROOT, &isroot );
 	slapi_pblock_set( dest, SLAPI_SEARCH_SIZELIMIT, &sizelimit );

+ 38 - 0
ldap/servers/slapd/operation.c

@@ -51,6 +51,15 @@
 #include "slap.h"
 #include "fe.h"
 
+int
+slapi_is_operation_abandoned( Slapi_Operation *op )
+{
+	if (op) {
+		return( op->o_status == SLAPI_OP_STATUS_ABANDONED );
+	}
+	return 0;
+}
+
 int
 slapi_op_abandoned( Slapi_PBlock *pb )
 {
@@ -192,6 +201,11 @@ operation_init(Slapi_Operation *o, int flags)
 
 }
 
+Slapi_Operation *
+slapi_operation_new(int flags)
+{
+	return (operation_new(flags));
+}
 /*
  * Allocate a new Slapi_Operation.
  * The flag parameter indicates whether the the operation is
@@ -427,6 +441,30 @@ struct slapi_operation_parameters *operation_parameters_new()
 	return (slapi_operation_parameters *)slapi_ch_calloc (1, sizeof (slapi_operation_parameters));
 }
 
+ber_tag_t
+slapi_operation_get_tag(Slapi_Operation *op)
+{
+	return op->o_tag;
+}
+
+ber_int_t
+slapi_operation_get_msgid(Slapi_Operation *op)
+{
+	return op->o_msgid;
+}
+
+void
+slapi_operation_set_tag(Slapi_Operation *op, ber_tag_t tag)
+{
+	op->o_tag = tag;
+}
+
+void
+slapi_operation_set_msgid(Slapi_Operation *op, ber_int_t msgid)
+{
+	op->o_msgid = msgid;
+}
+
 LDAPMod **
 copy_mods(LDAPMod **orig_mods)
 {

+ 12 - 0
ldap/servers/slapd/pblock.c

@@ -1463,6 +1463,12 @@ slapi_pblock_get( Slapi_PBlock *pblock, int arg, void *value )
 			(*(char ***)value) = pblock->pb_op->o_params.p.p_search.search_gerattrs;
 		}
 		break;
+	case SLAPI_SEARCH_REQATTRS:
+		if(pblock->pb_op!=NULL)
+		{
+			(*(char ***)value) = pblock->pb_op->o_searchattrs;
+		}
+		break;
 	case SLAPI_SEARCH_ATTRSONLY:
 		if(pblock->pb_op!=NULL)
 		{
@@ -3104,6 +3110,12 @@ slapi_pblock_set( Slapi_PBlock *pblock, int arg, void *value )
 			pblock->pb_op->o_params.p.p_search.search_gerattrs = (char **) value;
 		}
 		break;
+	case SLAPI_SEARCH_REQATTRS:
+		if(pblock->pb_op!=NULL)
+		{
+			pblock->pb_op->o_searchattrs = (char **) value;
+		}
+		break;
 	case SLAPI_SEARCH_ATTRSONLY:
 		if(pblock->pb_op!=NULL)
 		{

+ 7 - 0
ldap/servers/slapd/slapi-plugin.h

@@ -5145,16 +5145,22 @@ Slapi_Value *slapi_valueset_find(const Slapi_Attr *a, const Slapi_ValueSet *vs,
  * operation routines
  */
 int slapi_op_abandoned( Slapi_PBlock *pb );
+int slapi_is_operation_abandoned( Slapi_Operation *op );
 unsigned long slapi_op_get_type(Slapi_Operation * op);
 void slapi_operation_set_flag(Slapi_Operation *op, unsigned long flag);
 void slapi_operation_clear_flag(Slapi_Operation *op, unsigned long flag);
 int slapi_operation_is_flag_set(Slapi_Operation *op, unsigned long flag);
+ber_tag_t slapi_operation_get_tag(Slapi_Operation *op);
+ber_int_t slapi_operation_get_msgid(Slapi_Operation *op);
+void slapi_operation_set_tag(Slapi_Operation *op, ber_tag_t tag);
+void slapi_operation_set_msgid(Slapi_Operation *op, ber_int_t msgid);
 int slapi_op_reserved(Slapi_PBlock *pb);
 void slapi_operation_set_csngen_handler ( Slapi_Operation *op, void *callback );
 void slapi_operation_set_replica_attr_handler ( Slapi_Operation *op, void *callback );
 int slapi_operation_get_replica_attr ( Slapi_PBlock *pb, Slapi_Operation *op, const char *type, void *value );
 char *slapi_op_type_to_string(unsigned long type);
 int slapi_op_internal( Slapi_PBlock *pb );
+Slapi_Operation *slapi_operation_new(int flags);
 
 /*
  * connection routines
@@ -7157,6 +7163,7 @@ typedef struct slapi_plugindesc {
 #define SLAPI_SEARCH_STRFILTER      115
 #define SLAPI_SEARCH_ATTRS          116
 #define SLAPI_SEARCH_GERATTRS       1160
+#define SLAPI_SEARCH_REQATTRS       1161
 #define SLAPI_SEARCH_ATTRSONLY      117
 #define SLAPI_SEARCH_IS_AND         118