Received: by 2002:a05:6a10:1a4d:0:0:0:0 with SMTP id nk13csp5348963pxb; Sun, 13 Feb 2022 17:58:01 -0800 (PST) X-Google-Smtp-Source: ABdhPJyyPf6cF2PhQLr3GhGuvMC31dU7W8VgG/o04YN8gSsYzVOhIKbVvwJL1az7zOyxR/6ac85R X-Received: by 2002:a17:90b:4c4a:: with SMTP id np10mr12105238pjb.164.1644803881570; Sun, 13 Feb 2022 17:58:01 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1644803881; cv=none; d=google.com; s=arc-20160816; b=tUsnxxHtrjP/E4IRlG9TBgZ1VZoUHh9MiKssVYDfQQMrmSgqAtoZB++ps+FJg7rNB7 vAVhenfZd5TT/lxTTHfvC+xlO/Uk4FrZSd0Hz78NxG35t+AF8kHSOtG8O8c0IYiYbQ54 cCGTJXMvJHqoITCaIAcHdox1YgV3IyXTIHbMSLJxXPfMnqUKpehoEx3EOUM6Z1cCWnWU FYzaAEWllf8o6yQc2YD8yI4QJq7lxsULl+JtokrvdAl0bDrplYVGN44Ju9ekEsKzprIV 0TMJ5jSMLxc4fVaP8WWgTWexWS0feeVK21ZKT+2CbG0WUgU8/Kurd23YuphiVRKT6FrK c0bA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:user-agent:in-reply-to:content-disposition :mime-version:references:message-id:subject:cc:to:from:date; bh=2T/6a/k/xBGX9DrFD09Ob2hPOJBRO13LoXBIeDmBZW0=; b=pwgjrOs2t8hWBv22WHe0Ixlrud1gXzXElch+hg4WwlaGki29N2IWp1ueIOvz2+Lqpu Nm55c/ywPAuLKhrTkc45Y0+Fa1ouvc/D1/j8toghzewc4WtalnOcYWV7+2Y226j8rsI/ Dx/IJ6aAZ2iW+eAtm3Xb/j6HiuSXpJYmFunqSEgugycsXljz9q5VO12f5cUCnNvF49QV osu1fv93bwVYBfUp9NqcBJAXdUYtpiZmMV0Wgc5xIVPBjqVlKylkO5/r1JLfYauUzCN9 ZupVeESnuungOIz+NR5U8m1fwK61RG42gSCkZ1wu5jrsnaOJ7MkrXfuTNnvHRE1ETJrW 4nZw== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id g66si11535824pgc.674.2022.02.13.17.57.33; Sun, 13 Feb 2022 17:58:01 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232134AbiBLWiC (ORCPT + 99 others); Sat, 12 Feb 2022 17:38:02 -0500 Received: from mxb-00190b01.gslb.pphosted.com ([23.128.96.19]:49936 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229532AbiBLWiA (ORCPT ); Sat, 12 Feb 2022 17:38:00 -0500 Received: from mother.openwall.net (mother.openwall.net [195.42.179.200]) by lindbergh.monkeyblade.net (Postfix) with SMTP id 923326476 for ; Sat, 12 Feb 2022 14:37:55 -0800 (PST) Received: (qmail 22387 invoked from network); 12 Feb 2022 22:37:54 -0000 Received: from localhost (HELO pvt.openwall.com) (127.0.0.1) by localhost with SMTP; 12 Feb 2022 22:37:54 -0000 Received: by pvt.openwall.com (Postfix, from userid 503) id 2BA26AB88C; Sat, 12 Feb 2022 23:36:39 +0100 (CET) Date: Sat, 12 Feb 2022 23:36:39 +0100 From: Solar Designer To: "Eric W. Biederman" Cc: linux-kernel@vger.kernel.org, Alexey Gladkov , Kees Cook , Shuah Khan , Christian Brauner , Ran Xiaokai , Michal Koutn?? , stable@vger.kernel.org Subject: Re: [PATCH 5/8] ucounts: Handle wrapping in is_ucounts_overlimit Message-ID: <20220212223638.GB29214@openwall.com> References: <87o83e2mbu.fsf@email.froward.int.ebiederm.org> <20220211021324.4116773-5-ebiederm@xmission.com> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20220211021324.4116773-5-ebiederm@xmission.com> User-Agent: Mutt/1.4.2.3i X-Spam-Status: No, score=-4.2 required=5.0 tests=BAYES_00,RCVD_IN_DNSWL_MED, RCVD_IN_MSPIKE_H3,RCVD_IN_MSPIKE_WL,SPF_HELO_NONE,SPF_PASS, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On Thu, Feb 10, 2022 at 08:13:21PM -0600, Eric W. Biederman wrote: > While examining is_ucounts_overlimit and reading the various messages > I realized that is_ucounts_overlimit fails to deal with counts that > may have wrapped. > > Being wrapped should be a transitory state for counts and they should > never be wrapped for long, but it can happen so handle it. > > Cc: stable@vger.kernel.org > Fixes: 21d1c5e386bc ("Reimplement RLIMIT_NPROC on top of ucounts") > Signed-off-by: "Eric W. Biederman" > --- > kernel/ucount.c | 3 ++- > 1 file changed, 2 insertions(+), 1 deletion(-) > > diff --git a/kernel/ucount.c b/kernel/ucount.c > index 65b597431c86..06ea04d44685 100644 > --- a/kernel/ucount.c > +++ b/kernel/ucount.c > @@ -350,7 +350,8 @@ bool is_ucounts_overlimit(struct ucounts *ucounts, enum ucount_type type, unsign > if (rlimit > LONG_MAX) > max = LONG_MAX; > for (iter = ucounts; iter; iter = iter->ns->ucounts) { > - if (get_ucounts_value(iter, type) > max) > + long val = get_ucounts_value(iter, type); > + if (val < 0 || val > max) > return true; > max = READ_ONCE(iter->ns->ucount_max[type]); > } You probably deliberately assume "gcc -fwrapv", but otherwise: As you're probably aware, a signed integer wrapping is undefined behavior in C. In the function above, "val" having wrapped to negative assumes we had occurred UB elsewhere. Further, there's an instance of UB in the function itself: bool is_ucounts_overlimit(struct ucounts *ucounts, enum ucount_type type, unsigned long rlimit) { struct ucounts *iter; long max = rlimit; if (rlimit > LONG_MAX) max = LONG_MAX; The assignment on "long max = rlimit;" would have already been UB if "rlimit > LONG_MAX", which is only checked afterwards. I think the above would be better written as: if (rlimit > LONG_MAX) rlimit = LONG_MAX; long max = rlimit; considering that "rlimit" is never used further in that function. And to more likely avoid wraparound of "val", perhaps have the limit at a value significantly lower than LONG_MAX, like half that? So: if (rlimit > LONG_MAX / 2) rlimit = LONG_MAX / 2; long max = rlimit; And sure, also keep the "val < 0" check as defensive programming, or you can do: if (rlimit > LONG_MAX / 2) rlimit = LONG_MAX / 2; [...] if ((unsigned long)get_ucounts_value(iter, type) > rlimit) return true; and drop both "val" and "max". However, this also assumes the return type of get_ucounts_value() doesn't become larger than "unsigned long". I assume that once is_ucounts_overlimit() returned true, it is expected the value would almost not grow further (except a little due to races). I also assume there's some reason a signed type is used there. Alexander