From patchwork Sun Jan 10 17:33:47 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexey Gladkov X-Patchwork-Id: 12009339 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-13.7 required=3.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 355C9C433E0 for ; Sun, 10 Jan 2021 17:36:33 +0000 (UTC) Received: from mother.openwall.net (mother.openwall.net [195.42.179.200]) by mail.kernel.org (Postfix) with SMTP id 7AEA5221E7 for ; Sun, 10 Jan 2021 17:36:32 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 7AEA5221E7 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=kernel-hardening-return-20633-kernel-hardening=archiver.kernel.org@lists.openwall.com Received: (qmail 13359 invoked by uid 550); 10 Jan 2021 17:35:17 -0000 Mailing-List: contact kernel-hardening-help@lists.openwall.com; run by ezmlm Precedence: bulk List-Post: List-Help: List-Unsubscribe: List-Subscribe: List-ID: Received: (qmail 12135 invoked from network); 10 Jan 2021 17:35:14 -0000 From: Alexey Gladkov To: LKML , Linux Containers , Kernel Hardening Cc: Alexey Gladkov , "Eric W . Biederman" , Kees Cook , Christian Brauner , Linus Torvalds Subject: [RFC PATCH v2 8/8] Move RLIMIT_NPROC check to the place where we increment the counter Date: Sun, 10 Jan 2021 18:33:47 +0100 Message-Id: <54b0cf752c2c275a164aa980e2d8e4e464797ca1.1610299858.git.gladkov.alexey@gmail.com> X-Mailer: git-send-email 2.29.2 In-Reply-To: References: MIME-Version: 1.0 X-Greylist: Sender succeeded SMTP AUTH, not delayed by milter-greylist-4.6.1 (raptor.unsafe.ru [5.9.43.93]); Sun, 10 Jan 2021 17:34:53 +0000 (UTC) After calling set_user(), we always have to call commit_creds() to apply new credentials upon the current task. There is no need to separate limit check and counter incrementing. Signed-off-by: Alexey Gladkov --- kernel/cred.c | 22 +++++++++++++++++----- kernel/sys.c | 13 ------------- 2 files changed, 17 insertions(+), 18 deletions(-) diff --git a/kernel/cred.c b/kernel/cred.c index 89a945571533..770447b4f4de 100644 --- a/kernel/cred.c +++ b/kernel/cred.c @@ -488,14 +488,26 @@ int commit_creds(struct cred *new) if (!gid_eq(new->fsgid, old->fsgid)) key_fsgid_changed(new); - /* do it - * RLIMIT_NPROC limits on user->processes have already been checked - * in set_user(). - */ alter_cred_subscribers(new, 2); if (new->user != old->user || new->user_ns != old->user_ns) { + bool overlimit; + set_cred_ucounts(new, new->user_ns, new->euid); - inc_rlimit_ucounts(new->ucounts, UCOUNT_RLIMIT_NPROC, 1); + + overlimit = inc_rlimit_ucounts_and_test(new->ucounts, UCOUNT_RLIMIT_NPROC, + 1, rlimit(RLIMIT_NPROC)); + + /* + * We don't fail in case of NPROC limit excess here because too many + * poorly written programs don't check set*uid() return code, assuming + * it never fails if called by root. We may still enforce NPROC limit + * for programs doing set*uid()+execve() by harmlessly deferring the + * failure to the execve() stage. + */ + if (overlimit && new->user != INIT_USER) + current->flags |= PF_NPROC_EXCEEDED; + else + current->flags &= ~PF_NPROC_EXCEEDED; } rcu_assign_pointer(task->real_cred, new); rcu_assign_pointer(task->cred, new); diff --git a/kernel/sys.c b/kernel/sys.c index c2734ab9474e..180c4e06064f 100644 --- a/kernel/sys.c +++ b/kernel/sys.c @@ -467,19 +467,6 @@ static int set_user(struct cred *new) if (!new_user) return -EAGAIN; - /* - * We don't fail in case of NPROC limit excess here because too many - * poorly written programs don't check set*uid() return code, assuming - * it never fails if called by root. We may still enforce NPROC limit - * for programs doing set*uid()+execve() by harmlessly deferring the - * failure to the execve() stage. - */ - if (is_ucounts_overlimit(new->ucounts, UCOUNT_RLIMIT_NPROC, rlimit(RLIMIT_NPROC)) && - new_user != INIT_USER) - current->flags |= PF_NPROC_EXCEEDED; - else - current->flags &= ~PF_NPROC_EXCEEDED; - free_uid(new->user); new->user = new_user; return 0;