Message ID | 20200302195352.226103-1-jannh@google.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | lib/refcount: Document interaction with PID_MAX_LIMIT | expand |
On Mon, Mar 02, 2020 at 08:53:52PM +0100, Jann Horn wrote: > Document the circumstances under which refcount_t's saturation mechanism > works deterministically. > > Signed-off-by: Jann Horn <jannh@google.com> Acked-by: Kees Cook <keescook@chromium.org> With one note below... > --- > include/linux/refcount.h | 19 ++++++++++++++----- > 1 file changed, 14 insertions(+), 5 deletions(-) > > diff --git a/include/linux/refcount.h b/include/linux/refcount.h > index 0ac50cf62d062..cf14db393d89d 100644 > --- a/include/linux/refcount.h > +++ b/include/linux/refcount.h > @@ -38,11 +38,20 @@ > * atomic operations, then the count will continue to edge closer to 0. If it > * reaches a value of 1 before /any/ of the threads reset it to the saturated > * value, then a concurrent refcount_dec_and_test() may erroneously free the > - * underlying object. Given the precise timing details involved with the > - * round-robin scheduling of each thread manipulating the refcount and the need > - * to hit the race multiple times in succession, there doesn't appear to be a > - * practical avenue of attack even if using refcount_add() operations with > - * larger increments. > + * underlying object. > + * Linux limits the maximum number of tasks to PID_MAX_LIMIT, which is currently > + * 0x400000 (and can't easily be raised in the future beyond FUTEX_TID_MASK). Maybe just to clarify and make readers not have to go search the source: "... beyond FUTEX_TID_MASK, which is UAPI defined as 0x3fffffff)." and is it worth showing the math on this, just to have it clearly stated? -Kees > + * With the current PID limit, if no batched refcounting operations are used and > + * the attacker can't repeatedly trigger kernel oopses in the middle of refcount > + * operations, this makes it impossible for a saturated refcount to leave the > + * saturation range, even if it is possible for multiple uses of the same > + * refcount to nest in the context of a single task. > + * If hundreds of references are added/removed with a single refcounting > + * operation, it may potentially be possible to leave the saturation range; but > + * given the precise timing details involved with the round-robin scheduling of > + * each thread manipulating the refcount and the need to hit the race multiple > + * times in succession, there doesn't appear to be a practical avenue of attack > + * even if using refcount_add() operations with larger increments. > * > * Memory ordering > * =============== > > base-commit: 98d54f81e36ba3bf92172791eba5ca5bd813989b > -- > 2.25.0.265.gbab2e86ba0-goog >
On Mon, Mar 2, 2020 at 11:37 PM Kees Cook <keescook@chromium.org> wrote: > On Mon, Mar 02, 2020 at 08:53:52PM +0100, Jann Horn wrote: > > Document the circumstances under which refcount_t's saturation mechanism > > works deterministically. > > > > Signed-off-by: Jann Horn <jannh@google.com> > > Acked-by: Kees Cook <keescook@chromium.org> > > With one note below... > > > --- > > include/linux/refcount.h | 19 ++++++++++++++----- > > 1 file changed, 14 insertions(+), 5 deletions(-) > > > > diff --git a/include/linux/refcount.h b/include/linux/refcount.h > > index 0ac50cf62d062..cf14db393d89d 100644 > > --- a/include/linux/refcount.h > > +++ b/include/linux/refcount.h > > @@ -38,11 +38,20 @@ > > * atomic operations, then the count will continue to edge closer to 0. If it > > * reaches a value of 1 before /any/ of the threads reset it to the saturated > > * value, then a concurrent refcount_dec_and_test() may erroneously free the > > - * underlying object. Given the precise timing details involved with the > > - * round-robin scheduling of each thread manipulating the refcount and the need > > - * to hit the race multiple times in succession, there doesn't appear to be a > > - * practical avenue of attack even if using refcount_add() operations with > > - * larger increments. > > + * underlying object. > > + * Linux limits the maximum number of tasks to PID_MAX_LIMIT, which is currently > > + * 0x400000 (and can't easily be raised in the future beyond FUTEX_TID_MASK). > > Maybe just to clarify and make readers not have to go search the source: > > "... beyond FUTEX_TID_MASK, which is UAPI defined as 0x3fffffff)." The value of that thing has changed three times in git history, and there is a comment in threads.h that refers to it as being 0x1fffffff; so I'm a bit hesitant to copy that around further. > and is it worth showing the math on this, just to have it clearly > stated? Hm, I suppose... I'll send a v2. > -Kees > > > + * With the current PID limit, if no batched refcounting operations are used and > > + * the attacker can't repeatedly trigger kernel oopses in the middle of refcount > > + * operations, this makes it impossible for a saturated refcount to leave the > > + * saturation range, even if it is possible for multiple uses of the same > > + * refcount to nest in the context of a single task. > > + * If hundreds of references are added/removed with a single refcounting > > + * operation, it may potentially be possible to leave the saturation range; but > > + * given the precise timing details involved with the round-robin scheduling of > > + * each thread manipulating the refcount and the need to hit the race multiple > > + * times in succession, there doesn't appear to be a practical avenue of attack > > + * even if using refcount_add() operations with larger increments.
diff --git a/include/linux/refcount.h b/include/linux/refcount.h index 0ac50cf62d062..cf14db393d89d 100644 --- a/include/linux/refcount.h +++ b/include/linux/refcount.h @@ -38,11 +38,20 @@ * atomic operations, then the count will continue to edge closer to 0. If it * reaches a value of 1 before /any/ of the threads reset it to the saturated * value, then a concurrent refcount_dec_and_test() may erroneously free the - * underlying object. Given the precise timing details involved with the - * round-robin scheduling of each thread manipulating the refcount and the need - * to hit the race multiple times in succession, there doesn't appear to be a - * practical avenue of attack even if using refcount_add() operations with - * larger increments. + * underlying object. + * Linux limits the maximum number of tasks to PID_MAX_LIMIT, which is currently + * 0x400000 (and can't easily be raised in the future beyond FUTEX_TID_MASK). + * With the current PID limit, if no batched refcounting operations are used and + * the attacker can't repeatedly trigger kernel oopses in the middle of refcount + * operations, this makes it impossible for a saturated refcount to leave the + * saturation range, even if it is possible for multiple uses of the same + * refcount to nest in the context of a single task. + * If hundreds of references are added/removed with a single refcounting + * operation, it may potentially be possible to leave the saturation range; but + * given the precise timing details involved with the round-robin scheduling of + * each thread manipulating the refcount and the need to hit the race multiple + * times in succession, there doesn't appear to be a practical avenue of attack + * even if using refcount_add() operations with larger increments. * * Memory ordering * ===============
Document the circumstances under which refcount_t's saturation mechanism works deterministically. Signed-off-by: Jann Horn <jannh@google.com> --- include/linux/refcount.h | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) base-commit: 98d54f81e36ba3bf92172791eba5ca5bd813989b