From nobody Wed Apr 1 09:43:20 2026 Received: from mail-wm1-f45.google.com (mail-wm1-f45.google.com [209.85.128.45]) (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 CDCFF397E86 for ; Mon, 30 Mar 2026 20:29:15 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.45 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774902558; cv=none; b=Cl5u5RY98zf+a24tsVBAKgvlRbc1gwdoOR4xAk0bXHrGW7aN/Tv7Fmxj6sDyGYBW9QlEjdy6c9XpvEJ6e4DEL2ITWaJBdxqv27XparsxPyNY/PXtCiZ7riYvgHv98GD4qHH4hlgcArv7wBLv0kg4uZveGJsOt4qRdL2grBW+ddw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774902558; c=relaxed/simple; bh=Nf+Dt9sI+XuRWZ3JS4YVvNlBemGVo5EJjRd8QYxELO4=; h=From:To:Cc:Subject:Date:Message-ID:MIME-Version; b=i5whE2ePi4GH5NAKxtQP4dV5vqKngZbMBWTH+nfoQqwPKW2IJAx+W6rdL1e9xLl1o0/p0PdNdpqDm1OdRs+BgPVHJsSpD9t4xYb4m0QVx3Ob3V+Euprsm+ECdNREpoMFGedu3lcqOL9TlnK9+AiV0JGUzWivOsROmu9DhmO755k= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=cdrEMz9B; arc=none smtp.client-ip=209.85.128.45 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="cdrEMz9B" Received: by mail-wm1-f45.google.com with SMTP id 5b1f17b1804b1-487035181a7so32872745e9.2 for ; Mon, 30 Mar 2026 13:29:15 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1774902554; x=1775507354; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to; bh=jgku29mUT83lD8y7CN581AIB6Twx2GMJTRo8ZlVZhlE=; b=cdrEMz9BmRaHKqFc1dtjiQuAGZphv5/6m3sc9jc5J/uodTkXuutVefXncO1kC2vuIn wveaKmDwnkHFCTqjlC77HgnA7F4zESTEWw2fOeRrjykUVuHb8gkhjpmPOzuplKBBafA8 0OVzBrQ1gdBaDasrC0f7hcfymAsU8koM791bgJbngB8qTmhVi8wAmQv5r5sRE0uHwca6 OXylauVI3c7NFYBZKtFn0lY1z307KN11nfjBTPas9oGaJqnaMUCchObKvhJn2dGAcLQh 0jQ5ueYLkjh/ofz+/PVyxnIZnKCXuDpvtDge/yYoWYK4kmyRPA0vNAZoWYGBnse6C/dL 6+8Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1774902554; x=1775507354; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-gg:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=jgku29mUT83lD8y7CN581AIB6Twx2GMJTRo8ZlVZhlE=; b=lw/H/WKgrMSxZYwaLxzdO6fE7mZ6VJZw8MIhgcZHOi+O7x7Wi2zd1etNdV04ynimzY ag8drY0bh5RuZZlZMRbXG+W60wNSycA3mr/Q8pMkIw3aZtzRuUcqds4qcsG/Ck7kfbTd okUqvTauDrhbplZWybZnHYIc3TBFfUDJNXHt9kv4pN7//MOm2Tm0fjnsYFx+3TeF8Ask JmhNYvzrs5BkMSAdr1XY8V6IMbc8NJlUhvPIscH7V5EeDUEWs3DdaoBmwOu7HJT+YBYt UDa19hSyyjGNz4CKWFFSqcCooi5GF9q3V6g89chQQ21nmMB9CwaY53nuEOlfyosN3WzW fnOA== X-Forwarded-Encrypted: i=1; AJvYcCX3+2C9cVklM2LBrCPI3w1TYDnyjeSYfMSWL0atuTHPo2epp2wR1tBKtnWh1MWClIFQfW+WVgm4NtRHw2A=@vger.kernel.org X-Gm-Message-State: AOJu0Yw9Qq76uKvBJmaSEG3V53mXA6z/jQ28XaN0dB8axKJP2PN+nFif pgqE88+FaWK/xpJX8GE1xdrkulvsKJOxhJDh9vhATV1BVTPSEVNxVNhg X-Gm-Gg: ATEYQzwh0O4/pMWVSjByyIlBYuB+akbbokZV4qavOp8hOqQ55V4mE+oRd/ONTvcdUcg 13EYMu+7K1dladE7RcFiRQ7zEtSqPufng5bhylVQ0eg1BmQ6Dckiie2ImgEMACLMHjnEaB1/kWV QXXCx26hrY1Hx887GVxFrb7RGN9ZYThjLICSC2M/zTFoSbkuvZ/hCgCWvGX3SdwnUMiS3aW7U5z fFdKh7HQhMUwAYK854mEqW3Z8qFx8dorVB4ToOA6eTWtZ1KSCqwnsLoVknUZf9jURdVnGcJFUsv /tsp7EjzOI2yjU25BC/S6N2esvcltDp31p00+V84IDezuKDergwigPEpvaf3mBtQs7Smdlt5YU3 krlUL/n8Oe94iPSDi6P6ri13Z7OzsWa9PAXM8k/x5F+Ij8ixTTCE+QsG5Jh3y0Yg7ql2BYaB9G6 dPYvnP8jnne+k5ihytnVxz5QCCshUgg7uMgllo6fJTZDYRTMZN/8NuSJhD1me9Bdtx9cqjBZ6Pd OdLu/B4cX5ep5ecKkGhl3c= X-Received: by 2002:a05:600c:4e15:b0:485:35ee:f836 with SMTP id 5b1f17b1804b1-48727d5a191mr239440995e9.2.1774902553673; Mon, 30 Mar 2026 13:29:13 -0700 (PDT) Received: from dohko.chello.ie (188-141-5-72.dynamic.upc.ie. [188.141.5.72]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-48722be608bsm456579915e9.0.2026.03.30.13.29.12 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 30 Mar 2026 13:29:13 -0700 (PDT) From: David Carlier To: Peter Xu , Andrew Morton Cc: Mike Rapoport , linux-mm@kvack.org, linux-kernel@vger.kernel.org, David Carlier Subject: [PATCH v2] mm/userfaultfd: detect VMA replacement after copy retry in mfill_copy_folio_retry() Date: Mon, 30 Mar 2026 21:29:09 +0100 Message-ID: <20260330202909.136776-1-devnexen@gmail.com> X-Mailer: git-send-email 2.53.0 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" In mfill_copy_folio_retry(), all locks are dropped to retry copy_from_user() with page faults enabled. During this window, the VMA can be replaced entirely (e.g. munmap + mmap + UFFDIO_REGISTER by another thread), but the caller proceeds with a folio allocated from the original VMA's backing store. Checking ops alone is insufficient: the replacement VMA could be the same type (e.g. shmem -> shmem) with identical flags but a different backing inode. Take a snapshot of the VMA's inode and flags before dropping locks, and compare after re-acquiring them. If anything changed, bail out with -EAGAIN. Suggested-by: Peter Xu Signed-off-by: David Carlier --- mm/userfaultfd.c | 64 ++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 57 insertions(+), 7 deletions(-) diff --git a/mm/userfaultfd.c b/mm/userfaultfd.c index 481ec7eb4442..22e82f953eb5 100644 --- a/mm/userfaultfd.c +++ b/mm/userfaultfd.c @@ -443,33 +443,83 @@ static int mfill_copy_folio_locked(struct folio *foli= o, unsigned long src_addr) return ret; } =20 +struct vma_snapshot { + struct inode *inode; + vm_flags_t flags; +}; + +static void vma_snapshot_take(struct vm_area_struct *vma, + struct vma_snapshot *s) +{ + s->flags =3D vma->vm_flags; + if (vma->vm_file) { + s->inode =3D vma->vm_file->f_inode; + ihold(s->inode); + } else { + s->inode =3D NULL; + } +} + +static bool vma_snapshot_changed(struct vm_area_struct *vma, + struct vma_snapshot *s) +{ + if (s->flags !=3D vma->vm_flags) + return true; + + if (s->inode && vma->vm_file->f_inode !=3D s->inode) + return true; + + if (!s->inode && !vma_is_anonymous(vma)) + return true; + + return false; +} + +static void vma_snapshot_release(struct vma_snapshot *s) +{ + if (s->inode) { + iput(s->inode); + s->inode =3D NULL; + } +} + static int mfill_copy_folio_retry(struct mfill_state *state, struct folio = *folio) { unsigned long src_addr =3D state->src_addr; + struct vma_snapshot s; void *kaddr; int err; =20 + /* Take a quick snapshot of the current vma */ + vma_snapshot_take(state->vma, &s); + /* retry copying with mm_lock dropped */ mfill_put_vma(state); =20 kaddr =3D kmap_local_folio(folio, 0); err =3D copy_from_user(kaddr, (const void __user *) src_addr, PAGE_SIZE); kunmap_local(kaddr); - if (unlikely(err)) - return -EFAULT; + if (unlikely(err)) { + err =3D -EFAULT; + goto out; + } =20 flush_dcache_folio(folio); =20 /* reget VMA and PMD, they could change underneath us */ err =3D mfill_get_vma(state); if (err) - return err; + goto out; =20 - err =3D mfill_establish_pmd(state); - if (err) - return err; + if (vma_snapshot_changed(state->vma, &s)) { + err =3D -EAGAIN; + goto out; + } =20 - return 0; + err =3D mfill_establish_pmd(state); +out: + vma_snapshot_release(&s); + return err; } =20 static int __mfill_atomic_pte(struct mfill_state *state, --=20 2.53.0