diff --git a/CHANGES b/CHANGES
index d34f9f77f1d9048af838267967754df9630fdc16..58a2ca682ae6a2d826f370d4c27c802e60c7837e 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,4 @@
 OpenLDAP 2.4 Change Log
 
 OpenLDAP 2.4.6 Engineering
+	Fixed slapo-rwm modlist handling (ITS#5124)
diff --git a/servers/slapd/overlays/rwm.c b/servers/slapd/overlays/rwm.c
index 031f9f5d3c22ec18a094af944d392cf81322c2a0..88e7146b7990c0248a724dbc59cbc30c4529eaa8 100644
--- a/servers/slapd/overlays/rwm.c
+++ b/servers/slapd/overlays/rwm.c
@@ -504,14 +504,10 @@ rwm_op_modify( Operation *op, SlapReply *rs )
 	isupdate = be_shadow_update( op );
 	for ( mlp = &op->orm_modlist; *mlp; ) {
 		int			is_oc = 0;
-		Modifications		*ml;
+		Modifications		*ml = *mlp;
 		struct ldapmapping	*mapping = NULL;
 
-		/* duplicate the modlist */
-		ml = ch_malloc( sizeof( Modifications ));
-		*ml = **mlp;
-		*mlp = ml;
-
+		/* ml points to a temporary mod until needs duplication */
 		if ( ml->sml_desc == slap_schema.si_ad_objectClass 
 				|| ml->sml_desc == slap_schema.si_ad_structuralObjectClass )
 		{
@@ -519,6 +515,15 @@ rwm_op_modify( Operation *op, SlapReply *rs )
 
 		} else if ( !isupdate && !get_relax( op ) && ml->sml_desc->ad_type->sat_no_user_mod  )
 		{
+			ml = ch_malloc( sizeof( Modifications ) );
+			*ml = **mlp;
+			if ( (*mlp)->sml_values ) {
+				ber_bvarray_dup_x( &ml->sml_values, (*mlp)->sml_values, NULL );
+				if ( (*mlp)->sml_nvalues ) {
+					ber_bvarray_dup_x( &ml->sml_nvalues, (*mlp)->sml_nvalues, NULL );
+				}
+			}
+			*mlp = ml;
 			goto next_mod;
 
 		} else {
@@ -533,6 +538,11 @@ rwm_op_modify( Operation *op, SlapReply *rs )
 			}
 		}
 
+		/* duplicate the modlist */
+		ml = ch_malloc( sizeof( Modifications ));
+		*ml = **mlp;
+		*mlp = ml;
+
 		if ( ml->sml_values != NULL ) {
 			int i, num;
 			struct berval *bva;