From nobody Mon Apr 6 23:16:47 2026 Received: from mail-wr1-f73.google.com (mail-wr1-f73.google.com [209.85.221.73]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8F64B3C5DD4 for ; Tue, 17 Mar 2026 12:50:35 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.221.73 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773751837; cv=none; b=f4bIfbjUVvxTY+avhBD2m8GdTgBa/HTdORQyzipuCTdPg/41/0fxNcqJfOZvrrbih4sTPQ7sdm7U+aTzpmJeVWwW7j8n9BRLCk8HAW9S5GGygrvBRbsgjeAsN3KtZ4VSci1cWyugK44BGlciyCGi4ir7cPOCE0c+Q7GvdrYPHrA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773751837; c=relaxed/simple; bh=2g2CVk9p82pJR33U/dyoJK5o57kqiFJobI6zFGDWxl4=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=IfBOOHQK4FhJEJaZc8SJ768m7KuL31e5WXF5Q/4X2oYuu91wY2XJCEZEGjd2ZZzb6R3uIQn1eGAKXl90N5EVtv9CWt4zLQiwjg6S07JgCxrBIcI9YdgPNj3iHTArmCOq8HotSucAmqTPHwIFsaWVWEGYdnLV4lHd9+Mz2XCSqjk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--hmazur.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=FGDBXyUF; arc=none smtp.client-ip=209.85.221.73 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--hmazur.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="FGDBXyUF" Received: by mail-wr1-f73.google.com with SMTP id ffacd0b85a97d-43b47c19ed8so1814635f8f.1 for ; Tue, 17 Mar 2026 05:50:35 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20251104; t=1773751834; x=1774356634; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=80bKeW1QbA+rd5FHvp3sCEKth7+hZO62IH1Tt9MSVyQ=; b=FGDBXyUFHyfsleUWTo6Eavy2Cr0cq6OZgZKeltn/PY1zFb21vAyjk1lR/e6798rewk YoPnrlXoTH0nFmEr+qROo7cWDOjWNO2l/gw7JDWj12NPnIg8oJ+1KRDxf8VvMux8Z8Fv Qca3KSdJHroOv+vyD1syQeAoFJzZ+OuCFFbNydun/ZJTISnvjkmuVN+KqwDwXnGyH9hB UjlNv2YxPuPPHW0yLTG1/mFILakANoy4TnDzMlWSMbeybaJQ2BCw4iqaeqvzn/Rws3L8 hhA8wiP4FsYFmGWAlLiPSIDdGOgv6kLAD53PMi0BSyUE4w8WOK7A6q0e4/jMspzp8Ay8 WSqw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1773751834; x=1774356634; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=80bKeW1QbA+rd5FHvp3sCEKth7+hZO62IH1Tt9MSVyQ=; b=HXUT3Tv7IIODVul4/z/ShFwo5wGyVSIxWYlrFJ4QOcc233Nem+Cx2AoKcZpkZH9/fL dUdgg5MsJerE0LgRd1o0hi/KpqNer0696AiJkdRxnT6IEFhjhPbCO00iAIdnDvbczcpf RqrLV0pPjypDVMPsIj27Y5pTXrhYC/8Dsz9LB9TK1+IPfnXrgc+t/hrh6zG0EP/uY99j QXDtYIIPHi+FTZPRPy2HdkWatb77dO2xAWkPvCloS6BPSW5f25XPElvijztSNUp5aEII sxRfMt3pRR8HSIqTAGJiyYLyecO9QPnT78fLfCpjImtRa2Q66i4+FcolNyJcFGo7eo01 Dj1Q== X-Forwarded-Encrypted: i=1; AJvYcCXAlPc56atYYZX/OMf3EeFzIcf9XiBuvonOGu6t1Cl0dVhRswh1zz0Z34Rrvqco9WVxKASMMHionfpV58Y=@vger.kernel.org X-Gm-Message-State: AOJu0YxWo7M94FBp+kqbZpZ4K1Cn+3VcXDcQXusgaIcBMr/8P2KMf4k+ crkibVkUwM1aFDvsWVTGY5ETuudiuDmOy9Q5iRkdAT9VZDh/aNfICQ/pvLEmMjr30UfCspC0lId WWw3gcw== X-Received: from wrj13.prod.google.com ([2002:a5d:5a4d:0:b0:43b:458d:a320]) (user=hmazur job=prod-delivery.src-stubby-dispatcher) by 2002:a05:6000:2086:b0:439:b791:f920 with SMTP id ffacd0b85a97d-43a04d88460mr31112421f8f.17.1773751833804; Tue, 17 Mar 2026 05:50:33 -0700 (PDT) Date: Tue, 17 Mar 2026 12:50:20 +0000 In-Reply-To: <20260317125020.1293472-1-hmazur@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20260317125020.1293472-1-hmazur@google.com> X-Mailer: git-send-email 2.53.0.851.ga537e3e6e9-goog Message-ID: <20260317125020.1293472-2-hmazur@google.com> Subject: [PATCH v2 1/1] mm/execmem: Make the populate and alloc atomic From: Hubert Mazur To: Andrew Morton , Mike Rapoport Cc: Greg Kroah-Hartman , Stanislaw Kardach , Michal Krawczyk , Slawomir Rosek , Lukasz Majczak , linux-mm@kvack.org, linux-kernel@vger.kernel.org, Hubert Mazur Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" When a memory block is requested from the execmem manager, it tries to find a suitable fragment in the free_areas. In case there is no such block, a new memory area is added to free_areas and then allocated to the caller. Those two operations must be atomic to ensure that no other memory request consumes it. Signed-off-by: Hubert Mazur --- mm/execmem.c | 61 +++++++++++++++++++++++++++++----------------------- 1 file changed, 34 insertions(+), 27 deletions(-) diff --git a/mm/execmem.c b/mm/execmem.c index 810a4ba9c924..9043f0f8f61a 100644 --- a/mm/execmem.c +++ b/mm/execmem.c @@ -203,13 +203,6 @@ static int execmem_cache_add_locked(void *ptr, size_t = size, gfp_t gfp_mask) return mas_store_gfp(&mas, (void *)lower, gfp_mask); } =20 -static int execmem_cache_add(void *ptr, size_t size, gfp_t gfp_mask) -{ - guard(mutex)(&execmem_cache.mutex); - - return execmem_cache_add_locked(ptr, size, gfp_mask); -} - static bool within_range(struct execmem_range *range, struct ma_state *mas, size_t size) { @@ -225,18 +218,16 @@ static bool within_range(struct execmem_range *range,= struct ma_state *mas, return false; } =20 -static void *__execmem_cache_alloc(struct execmem_range *range, size_t siz= e) +static void *__execmem_cache_alloc_locked(struct execmem_range *range, siz= e_t size) { struct maple_tree *free_areas =3D &execmem_cache.free_areas; struct maple_tree *busy_areas =3D &execmem_cache.busy_areas; MA_STATE(mas_free, free_areas, 0, ULONG_MAX); MA_STATE(mas_busy, busy_areas, 0, ULONG_MAX); - struct mutex *mutex =3D &execmem_cache.mutex; unsigned long addr, last, area_size =3D 0; void *area, *ptr =3D NULL; int err; =20 - mutex_lock(mutex); mas_for_each(&mas_free, area, ULONG_MAX) { area_size =3D mas_range_len(&mas_free); =20 @@ -245,7 +236,7 @@ static void *__execmem_cache_alloc(struct execmem_range= *range, size_t size) } =20 if (area_size < size) - goto out_unlock; + return NULL; =20 addr =3D mas_free.index; last =3D mas_free.last; @@ -254,7 +245,7 @@ static void *__execmem_cache_alloc(struct execmem_range= *range, size_t size) mas_set_range(&mas_busy, addr, addr + size - 1); err =3D mas_store_gfp(&mas_busy, (void *)addr, GFP_KERNEL); if (err) - goto out_unlock; + return NULL; =20 mas_store_gfp(&mas_free, NULL, GFP_KERNEL); if (area_size > size) { @@ -268,19 +259,25 @@ static void *__execmem_cache_alloc(struct execmem_ran= ge *range, size_t size) err =3D mas_store_gfp(&mas_free, ptr, GFP_KERNEL); if (err) { mas_store_gfp(&mas_busy, NULL, GFP_KERNEL); - goto out_unlock; + return NULL; } } ptr =3D (void *)addr; =20 -out_unlock: - mutex_unlock(mutex); return ptr; } =20 -static int execmem_cache_populate(struct execmem_range *range, size_t size) +static void *__execmem_cache_alloc(struct execmem_range *range, size_t siz= e) +{ + guard(mutex)(&execmem_cache.mutex); + + return __execmem_cache_alloc_locked(range, size); +} + +static void *__execmem_cache_populate_alloc(struct execmem_range *range, s= ize_t size) { unsigned long vm_flags =3D VM_ALLOW_HUGE_VMAP; + struct mutex *mutex =3D &execmem_cache.mutex; struct vm_struct *vm; size_t alloc_size; int err =3D -ENOMEM; @@ -294,7 +291,7 @@ static int execmem_cache_populate(struct execmem_range = *range, size_t size) } =20 if (!p) - return err; + return NULL; =20 vm =3D find_vm_area(p); if (!vm) @@ -307,33 +304,43 @@ static int execmem_cache_populate(struct execmem_rang= e *range, size_t size) if (err) goto err_free_mem; =20 - err =3D execmem_cache_add(p, alloc_size, GFP_KERNEL); - if (err) + /* + * New memory blocks must be propagated and allocated as an atomic operat= ion, + * otherwise it may be consumed by a parallel call to the execmem_cache_a= lloc + * function. + */ + mutex_lock(mutex); + err =3D execmem_cache_add_locked(p, alloc_size, GFP_KERNEL); + if (err) { + mutex_unlock(mutex); goto err_reset_direct_map; + } =20 - return 0; + p =3D __execmem_cache_alloc_locked(range, size); + if (!p) { + mutex_unlock(mutex); + return NULL; + } + mutex_unlock(mutex); + + return p; =20 err_reset_direct_map: execmem_set_direct_map_valid(vm, true); err_free_mem: vfree(p); - return err; + return NULL; } =20 static void *execmem_cache_alloc(struct execmem_range *range, size_t size) { void *p; - int err; =20 p =3D __execmem_cache_alloc(range, size); if (p) return p; =20 - err =3D execmem_cache_populate(range, size); - if (err) - return NULL; - - return __execmem_cache_alloc(range, size); + return __execmem_cache_populate_alloc(range, size); } =20 static inline bool is_pending_free(void *ptr) --=20 2.53.0.851.ga537e3e6e9-goog