From patchwork Fri May 3 17:22:32 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Magali Lemes X-Patchwork-Id: 1931128 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.ubuntu.com (client-ip=185.125.189.65; helo=lists.ubuntu.com; envelope-from=kernel-team-bounces@lists.ubuntu.com; receiver=patchwork.ozlabs.org) Received: from lists.ubuntu.com (lists.ubuntu.com [185.125.189.65]) (using TLSv1.2 with cipher ECDHE-ECDSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4VWHgp1Cv3z1ybC for ; Sat, 4 May 2024 03:23:01 +1000 (AEST) Received: from localhost ([127.0.0.1] helo=lists.ubuntu.com) by lists.ubuntu.com with esmtp (Exim 4.86_2) (envelope-from ) id 1s2wcM-0002Vf-Hh; Fri, 03 May 2024 17:22:42 +0000 Received: from smtp-relay-internal-1.internal ([10.131.114.114] helo=smtp-relay-internal-1.canonical.com) by lists.ubuntu.com with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.86_2) (envelope-from ) id 1s2wcJ-0002V0-RS for kernel-team@lists.ubuntu.com; Fri, 03 May 2024 17:22:39 +0000 Received: from mail-pl1-f200.google.com (mail-pl1-f200.google.com [209.85.214.200]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by smtp-relay-internal-1.canonical.com (Postfix) with ESMTPS id B2F3F3F129 for ; Fri, 3 May 2024 17:22:39 +0000 (UTC) Received: by mail-pl1-f200.google.com with SMTP id d9443c01a7336-1ed057cc183so19986205ad.2 for ; Fri, 03 May 2024 10:22:39 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1714756958; x=1715361758; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=yJ6IT6KB8hzkU3BQnb+cJN/Ism0l8jlCFH/CMocuSLA=; b=K1TMtrFN+TVL9B7ny5W+Q7rq2dwGQysWiDkV1rLeUevSjd9rzNYvEVxyncxG5st8cg 8MfOeS9RrSSD6uWF4UNa1rwApHvItF2SWnsOqUpt9GiqXNkcmHTt/0XcWJgCNo+g1XBu sWgpbs6IKmdAe8asMsdFRQ+Ro9SOVKdxaxGaYfRq1wffo3XJ+RORl0zaU3kirjFyVs73 nB71OEzSMCJa76lJZG7tDg9LlpN9Xh0nR9pcC7ZiNVxCdKlaQgDHzUyDIGVXBF5oWfR1 FgHtxPMzGwmTooqXsa1I1RCJQQYizz6OdnQroncfVdhLpvLSMgTvNQo8gjalOjdsB0e1 t4DA== X-Gm-Message-State: AOJu0YyV2jLxKJrJEte6Y2dfpic/5Bsoyrsw12xAWUA4tvKqYeDOkilX npbtiX9cJvSbP3tK5vv6l5RVqzI8aSEFKPnjZ1hnJHpsFio/+cu+ZdrMAPYBMFCp2/ErJfRNjH5 UnXdqNkTDXk+NBbK2g49GLKaFB+MichR9f6qEmysef0Gp39QM7ZoYyAkVF2pFukfqMOI/ZFVJ9b qa1BVcQC1ilA== X-Received: by 2002:a17:902:e54d:b0:1e4:fd4:48d0 with SMTP id n13-20020a170902e54d00b001e40fd448d0mr3995725plf.62.1714756957853; Fri, 03 May 2024 10:22:37 -0700 (PDT) X-Google-Smtp-Source: AGHT+IHVdF1V4yUyM/X6BS0x/9p4D6QJpkmIFIqOlKu9uZvhQp7SVI78JwOGal40cAdtl8nMHxux1Q== X-Received: by 2002:a17:902:e54d:b0:1e4:fd4:48d0 with SMTP id n13-20020a170902e54d00b001e40fd448d0mr3995704plf.62.1714756957472; Fri, 03 May 2024 10:22:37 -0700 (PDT) Received: from magali.. ([2804:14c:14a:814f:3314:492e:f3c:afaf]) by smtp.gmail.com with ESMTPSA id i11-20020a17090332cb00b001e9685ad053sm3518503plr.248.2024.05.03.10.22.35 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 03 May 2024 10:22:36 -0700 (PDT) From: Magali Lemes To: kernel-team@lists.ubuntu.com Subject: [SRU][F/J/M][PATCH 1/1] md/raid5: fix atomicity violation in raid5_cache_count Date: Fri, 3 May 2024 14:22:32 -0300 Message-Id: <20240503172232.1232019-2-magali.lemes@canonical.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240503172232.1232019-1-magali.lemes@canonical.com> References: <20240503172232.1232019-1-magali.lemes@canonical.com> MIME-Version: 1.0 X-BeenThere: kernel-team@lists.ubuntu.com X-Mailman-Version: 2.1.20 Precedence: list List-Id: Kernel team discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: kernel-team-bounces@lists.ubuntu.com Sender: "kernel-team" From: Gui-Dong Han <2045gemini@gmail.com> [ Upstream commit dfd2bf436709b2bccb78c2dda550dde93700efa7 ] In raid5_cache_count(): if (conf->max_nr_stripes < conf->min_nr_stripes) return 0; return conf->max_nr_stripes - conf->min_nr_stripes; The current check is ineffective, as the values could change immediately after being checked. In raid5_set_cache_size(): ... conf->min_nr_stripes = size; ... while (size > conf->max_nr_stripes) conf->min_nr_stripes = conf->max_nr_stripes; ... Due to intermediate value updates in raid5_set_cache_size(), concurrent execution of raid5_cache_count() and raid5_set_cache_size() may lead to inconsistent reads of conf->max_nr_stripes and conf->min_nr_stripes. The current checks are ineffective as values could change immediately after being checked, raising the risk of conf->min_nr_stripes exceeding conf->max_nr_stripes and potentially causing an integer overflow. This possible bug is found by an experimental static analysis tool developed by our team. This tool analyzes the locking APIs to extract function pairs that can be concurrently executed, and then analyzes the instructions in the paired functions to identify possible concurrency bugs including data races and atomicity violations. The above possible bug is reported when our tool analyzes the source code of Linux 6.2. To resolve this issue, it is suggested to introduce local variables 'min_stripes' and 'max_stripes' in raid5_cache_count() to ensure the values remain stable throughout the check. Adding locks in raid5_cache_count() fails to resolve atomicity violations, as raid5_set_cache_size() may hold intermediate values of conf->min_nr_stripes while unlocked. With this patch applied, our tool no longer reports the bug, with the kernel configuration allyesconfig for x86_64. Due to the lack of associated hardware, we cannot test the patch in runtime testing, and just verify it according to the code logic. Fixes: edbe83ab4c27 ("md/raid5: allow the stripe_cache to grow and shrink.") Cc: stable@vger.kernel.org Signed-off-by: Gui-Dong Han <2045gemini@gmail.com> Reviewed-by: Yu Kuai Signed-off-by: Song Liu Link: https://lore.kernel.org/r/20240112071017.16313-1-2045gemini@gmail.com Signed-off-by: Song Liu Signed-off-by: Sasha Levin (cherry picked from commit 8ec4a68a25a231e2303716a0aba8ff1413d47c87 linux-6.6.y) CVE-2024-23307 Signed-off-by: Magali Lemes --- drivers/md/raid5.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 9444b06e23e0..1d5ff12e8d31 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -2420,7 +2420,7 @@ static int grow_one_stripe(struct r5conf *conf, gfp_t gfp) atomic_inc(&conf->active_stripes); raid5_release_stripe(sh); - conf->max_nr_stripes++; + WRITE_ONCE(conf->max_nr_stripes, conf->max_nr_stripes + 1); return 1; } @@ -2717,7 +2717,7 @@ static int drop_one_stripe(struct r5conf *conf) shrink_buffers(sh); free_stripe(conf->slab_cache, sh); atomic_dec(&conf->active_stripes); - conf->max_nr_stripes--; + WRITE_ONCE(conf->max_nr_stripes, conf->max_nr_stripes - 1); return 1; } @@ -6914,7 +6914,7 @@ raid5_set_cache_size(struct mddev *mddev, int size) if (size <= 16 || size > 32768) return -EINVAL; - conf->min_nr_stripes = size; + WRITE_ONCE(conf->min_nr_stripes, size); mutex_lock(&conf->cache_size_mutex); while (size < conf->max_nr_stripes && drop_one_stripe(conf)) @@ -6926,7 +6926,7 @@ raid5_set_cache_size(struct mddev *mddev, int size) mutex_lock(&conf->cache_size_mutex); while (size > conf->max_nr_stripes) if (!grow_one_stripe(conf, GFP_KERNEL)) { - conf->min_nr_stripes = conf->max_nr_stripes; + WRITE_ONCE(conf->min_nr_stripes, conf->max_nr_stripes); result = -ENOMEM; break; } @@ -7491,11 +7491,13 @@ static unsigned long raid5_cache_count(struct shrinker *shrink, struct shrink_control *sc) { struct r5conf *conf = container_of(shrink, struct r5conf, shrinker); + int max_stripes = READ_ONCE(conf->max_nr_stripes); + int min_stripes = READ_ONCE(conf->min_nr_stripes); - if (conf->max_nr_stripes < conf->min_nr_stripes) + if (max_stripes < min_stripes) /* unlikely, but not impossible */ return 0; - return conf->max_nr_stripes - conf->min_nr_stripes; + return max_stripes - min_stripes; } static struct r5conf *setup_conf(struct mddev *mddev)