Skip to content

Commit e31ea09

Browse files
committed
Wrap ingester Push errors to avoid retaining any reference to unsafe data
Signed-off-by: Bryan Boreham <[email protected]>
1 parent cfc25fd commit e31ea09

File tree

3 files changed

+13
-16
lines changed

3 files changed

+13
-16
lines changed

pkg/ingester/errors.go

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import (
44
"fmt"
55
"net/http"
66

7-
"github.com/pkg/errors"
87
"github.com/prometheus/prometheus/pkg/labels"
98
"github.com/weaveworks/common/httpgrpc"
109
)
@@ -50,11 +49,6 @@ func makeMetricLimitError(errorType string, labels labels.Labels, err error) err
5049
}
5150
}
5251

53-
func (e *validationError) WrapWithUser(userID string) *validationError {
54-
e.err = wrapWithUser(e.err, userID)
55-
return e
56-
}
57-
5852
func (e *validationError) Error() string {
5953
if e.err == nil {
6054
return e.errorType
@@ -65,14 +59,15 @@ func (e *validationError) Error() string {
6559
return fmt.Sprintf("%s for series %s", e.err.Error(), e.labels.String())
6660
}
6761

68-
// WrappedError returns a HTTP gRPC error than is correctly forwarded over gRPC.
69-
func (e *validationError) WrappedError() error {
62+
// returns a HTTP gRPC error than is correctly forwarded over gRPC, with no reference to `e` retained.
63+
func grpcForwardableError(userID string, code int, e error) error {
7064
return httpgrpc.ErrorFromHTTPResponse(&httpgrpc.HTTPResponse{
71-
Code: int32(e.code),
72-
Body: []byte(e.Error()),
65+
Code: int32(code),
66+
Body: []byte(wrapWithUser(e, userID).Error()),
7367
})
7468
}
7569

70+
// Note: does not retain a reference to `err`
7671
func wrapWithUser(err error, userID string) error {
77-
return errors.Wrapf(err, "user=%s", userID)
72+
return fmt.Errorf("user=%s: %s", userID, err)
7873
}

pkg/ingester/ingester.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,8 @@ func (i *Ingester) Push(ctx old_ctx.Context, req *client.WriteRequest) (*client.
277277
return i.v2Push(ctx, req)
278278
}
279279

280+
// NOTE: because we use `unsafe` in deserialisation, we must not
281+
// retain anything from `req` past the call to ReuseSlice
280282
defer client.ReuseSlice(req.Timeseries)
281283

282284
userID, err := user.ExtractOrgID(ctx)
@@ -299,8 +301,6 @@ func (i *Ingester) Push(ctx old_ctx.Context, req *client.WriteRequest) (*client.
299301
}
300302
}
301303

302-
// NOTE: because we use `unsafe` in deserialisation, we must not
303-
// retain anything from `req` past the call to ReuseSlice
304304
for _, ts := range req.Timeseries {
305305
for _, s := range ts.Samples {
306306
// append() copies the memory in `ts.Labels` except on the error path
@@ -316,13 +316,13 @@ func (i *Ingester) Push(ctx old_ctx.Context, req *client.WriteRequest) (*client.
316316
}
317317

318318
// non-validation error: abandon this request
319-
return nil, wrapWithUser(err, userID)
319+
return nil, grpcForwardableError(userID, http.StatusInternalServerError, err)
320320
}
321321
}
322322

323323
if lastPartialErr != nil {
324-
// WrappedError turns the error into a string so it no longer references `req`
325-
return &client.WriteResponse{}, lastPartialErr.WrapWithUser(userID).WrappedError()
324+
// grpcForwardableError turns the error into a string so it no longer references `req`
325+
return &client.WriteResponse{}, grpcForwardableError(userID, lastPartialErr.code, lastPartialErr)
326326
}
327327

328328
if record != nil {

pkg/ingester/ingester_v2.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,8 @@ func NewV2(cfg Config, clientConfig client.Config, limits *validation.Overrides,
105105
func (i *Ingester) v2Push(ctx old_ctx.Context, req *client.WriteRequest) (*client.WriteResponse, error) {
106106
var firstPartialErr error
107107

108+
// NOTE: because we use `unsafe` in deserialisation, we must not
109+
// retain anything from `req` past the call to ReuseSlice
108110
defer client.ReuseSlice(req.Timeseries)
109111

110112
userID, err := user.ExtractOrgID(ctx)

0 commit comments

Comments
 (0)