return -ENOMEM;
 }
 
-static void nft_set_elem_expr_setup(const struct nft_set_ext *ext, int i,
-                                   struct nft_expr *expr_array[])
+static int nft_set_elem_expr_setup(struct nft_ctx *ctx,
+                                  const struct nft_set_ext *ext,
+                                  struct nft_expr *expr_array[],
+                                  u32 num_exprs)
 {
        struct nft_set_elem_expr *elem_expr = nft_set_ext_expr(ext);
-       struct nft_expr *expr = nft_setelem_expr_at(elem_expr, elem_expr->size);
+       struct nft_expr *expr;
+       int i, err;
+
+       for (i = 0; i < num_exprs; i++) {
+               expr = nft_setelem_expr_at(elem_expr, elem_expr->size);
+               err = nft_expr_clone(expr, expr_array[i]);
+               if (err < 0)
+                       goto err_elem_expr_setup;
+
+               elem_expr->size += expr_array[i]->ops->size;
+               nft_expr_destroy(ctx, expr_array[i]);
+               expr_array[i] = NULL;
+       }
+
+       return 0;
+
+err_elem_expr_setup:
+       for (; i < num_exprs; i++) {
+               nft_expr_destroy(ctx, expr_array[i]);
+               expr_array[i] = NULL;
+       }
 
-       memcpy(expr, expr_array[i], expr_array[i]->ops->size);
-       elem_expr->size += expr_array[i]->ops->size;
-       kfree(expr_array[i]);
-       expr_array[i] = NULL;
+       return -ENOMEM;
 }
 
 static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set,
                *nft_set_ext_obj(ext) = obj;
                obj->use++;
        }
-       for (i = 0; i < num_exprs; i++)
-               nft_set_elem_expr_setup(ext, i, expr_array);
+       err = nft_set_elem_expr_setup(ctx, ext, expr_array, num_exprs);
+       if (err < 0)
+               goto err_elem_expr;
 
        trans = nft_trans_elem_alloc(ctx, NFT_MSG_NEWSETELEM, set);
-       if (trans == NULL)
-               goto err_trans;
+       if (trans == NULL) {
+               err = -ENOMEM;
+               goto err_elem_expr;
+       }
 
        ext->genmask = nft_genmask_cur(ctx->net) | NFT_SET_ELEM_BUSY_MASK;
        err = set->ops->insert(ctx->net, set, &elem, &ext2);
        set->ops->remove(ctx->net, set, &elem);
 err_element_clash:
        kfree(trans);
-err_trans:
+err_elem_expr:
        if (obj)
                obj->use--;