From nobody Tue Feb 10 06:04:47 2026 Received: from mail-oa1-f73.google.com (mail-oa1-f73.google.com [209.85.160.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 E529B41C2E8 for ; Mon, 9 Feb 2026 19:06:16 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.160.73 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770663977; cv=none; b=JNs5rKJwhMHwfFlsMlJoxPwy7DH4x/Zp7ug2YUE/Hsk23V/RyEgX/T26M38DKHy61W1xhxo8lwMM1vtXvVHF4Sw1RSYPxqFThTZeKOW0rly+9RuC4pn9PfgwCfFOTQ55etgWhI4uYHoOmS9Y8Z+/nswQJxnBw0jJgeGFz2OLFqE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770663977; c=relaxed/simple; bh=NqG7bVpGByzbqLWbObaiJ3BzJR9rD0Wj+d/HvIRik1k=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=eM5/tkhAqo38HxTQaxE6u6HMx8tmD2O+8kPAVCjDaFsiE4DojOKM/oBa3KrPOO0QDu0fEvAXx1QngatbdbtQvY4AYal3oNv3GzTthmBIZXPlw1y90yLweqKuUHv44TFAjq2KGnZC7h4G/qS3bDZvET1OCRd6xewjVc8RQ744C8s= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--avagin.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=wzoT48Q7; arc=none smtp.client-ip=209.85.160.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--avagin.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="wzoT48Q7" Received: by mail-oa1-f73.google.com with SMTP id 586e51a60fabf-409037c3f0bso12796128fac.1 for ; Mon, 09 Feb 2026 11:06:16 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1770663976; x=1771268776; darn=vger.kernel.org; h=content-transfer-encoding:cc:to:from:subject:message-id:references :mime-version:in-reply-to:date:from:to:cc:subject:date:message-id :reply-to; bh=vdr4V4HK4nTpFzygAIFcY2is0P9+eeyi+VB04pSk0Ms=; b=wzoT48Q7WXvmfnEojSogq6/DuFg9uMxvgnaWs4LEnaf+OJoin5NjuTJSFHnjoX1EXM PjQjrNEw7TDA0cEW6Nz7lTtgK+6Cn1/6Aa4F2ncfCjiqGtAo2ZD27GXmIRuSw5nEIa2p 1fzyEwEbcMI2OKVC10nAfFfbV8O81bPR0XyoATrDhXTdGIs0vrxFpykRZBtZ8yJhvaII Gw1K2Ovuf30SAzNmqTbOFAR4X6aovVIbPHGxOfZBRHqHxMcMhpiVn5td+rgh9OBZYzeF gW6dQ73xK3r0LbGHyR+PKInVC9/VrFWQtaQBMtOeIxxaOSEkQ2ytR0YTYyPwlVklhamp 0HpQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1770663976; x=1771268776; h=content-transfer-encoding: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=vdr4V4HK4nTpFzygAIFcY2is0P9+eeyi+VB04pSk0Ms=; b=kcHGCUvIxDTEs+i5awNUwo8R6y2ZsSRFxAXGBHvb12rEGeFLMfM3aVqHwc+c1pf7gr QQY9asKl0DOmsquobkp3Lb8QvwBzhimM6oCOz7hfq6bZifOOF+aX0poa5x2jVdzhfmNS CzAWsQ9VhmP20l+FTrPv+NPLdslR16CzJJwsBXgbJQ9mVkY2+9vjB9R+ml0qRtjmNjs/ EmHMedkL7FqVVK9UVY3Nfb6pfE7ra93LI5qRF2rb1bcCng71vLj5MdXRtSvIAHuRkK1A zi/GNVeSnRFOEFY9uZgJeDTCPjtpYWCYrp9zXsqeIRHfTt3/1cMdHNo2PQOvAusxlGcH owcA== X-Forwarded-Encrypted: i=1; AJvYcCVYzkitugNN4ClV148qXu2mX2OVRQL7zpyjl6oREznRpeds19NR094AIkHtDLudWQtdj29fonKuP7v12bk=@vger.kernel.org X-Gm-Message-State: AOJu0Yyir/CM852DWYFHKIBMIjSylm3weflKo1F2ofVvZGic2z4ioGeV NnHUrfWg/kPyWxaXGUMoeafk6c3CEnCT1wZDXq80KhJCJ9KSBN4rhiBLT7cKhQr0L9IRHdCD/aK DabMvlg== X-Received: from jajt22.prod.google.com ([2002:a05:6638:2056:b0:5ce:8aec:982c]) (user=avagin job=prod-delivery.src-stubby-dispatcher) by 2002:a4a:e54e:0:b0:66d:f051:e91f with SMTP id 006d021491bc7-66df0613260mr3273923eaf.23.1770663975878; Mon, 09 Feb 2026 11:06:15 -0800 (PST) Date: Mon, 9 Feb 2026 19:06:02 +0000 In-Reply-To: <20260209190605.1564597-1-avagin@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20260209190605.1564597-1-avagin@google.com> X-Mailer: git-send-email 2.53.0.239.g8d8fc8a987-goog Message-ID: <20260209190605.1564597-2-avagin@google.com> Subject: [PATCH 1/4] binfmt_elf_fdpic: fix AUXV size calculation for ELF_HWCAP3 and ELF_HWCAP4 From: Andrei Vagin To: Kees Cook , Andrew Morton Cc: Cyrill Gorcunov , Mike Rapoport , Alexander Mikhalitsyn , linux-kernel@vger.kernel.org, linux-fsdevel@vger.kernel.org, linux-mm@kvack.org, criu@lists.linux.dev, Chen Ridong , Christian Brauner , David Hildenbrand , Eric Biederman , Lorenzo Stoakes , Michal Koutny , Andrei Vagin , Mark Brown , Max Filippov Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Commit 4e6e8c2b757f ("binfmt_elf: Wire up AT_HWCAP3 at AT_HWCAP4") added support for AT_HWCAP3 and AT_HWCAP4, but it missed updating the AUX vector size calculation in create_elf_fdpic_tables() and AT_VECTOR_SIZE_BASE in include/linux/auxvec.h. Similar to the fix for AT_HWCAP2 in commit c6a09e342f8e ("binfmt_elf_fdpic: fix AUXV size calculation when ELF_HWCAP2 is defined"), this omission leads to a mismatch between the reserved space and the actual number of AUX entries, eventually triggering a kernel BUG_ON(csp !=3D sp). Fix this by incrementing nitems when ELF_HWCAP3 or ELF_HWCAP4 are defined and updating AT_VECTOR_SIZE_BASE. Cc: Mark Brown Cc: Max Filippov Reviewed-by: Michal Koutn=C3=BD Reviewed-by: Mark Brown Fixes: 4e6e8c2b757f ("binfmt_elf: Wire up AT_HWCAP3 at AT_HWCAP4") Signed-off-by: Andrei Vagin --- fs/binfmt_elf_fdpic.c | 6 ++++++ include/linux/auxvec.h | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/fs/binfmt_elf_fdpic.c b/fs/binfmt_elf_fdpic.c index 48fd2de3bca0..a3d4e6973b29 100644 --- a/fs/binfmt_elf_fdpic.c +++ b/fs/binfmt_elf_fdpic.c @@ -595,6 +595,12 @@ static int create_elf_fdpic_tables(struct linux_binprm= *bprm, #ifdef ELF_HWCAP2 nitems++; #endif +#ifdef ELF_HWCAP3 + nitems++; +#endif +#ifdef ELF_HWCAP4 + nitems++; +#endif =20 csp =3D sp; sp -=3D nitems * 2 * sizeof(unsigned long); diff --git a/include/linux/auxvec.h b/include/linux/auxvec.h index 407f7005e6d6..8bcb9b726262 100644 --- a/include/linux/auxvec.h +++ b/include/linux/auxvec.h @@ -4,6 +4,6 @@ =20 #include =20 -#define AT_VECTOR_SIZE_BASE 22 /* NEW_AUX_ENT entries in auxiliary table */ +#define AT_VECTOR_SIZE_BASE 24 /* NEW_AUX_ENT entries in auxiliary table */ /* number of "#define AT_.*" above, minus {AT_NULL, AT_IGNORE, AT_NOTELF= } */ #endif /* _LINUX_AUXVEC_H */ --=20 2.53.0.239.g8d8fc8a987-goog From nobody Tue Feb 10 06:04:47 2026 Received: from mail-oo1-f74.google.com (mail-oo1-f74.google.com [209.85.161.74]) (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 20FBB4219FD for ; Mon, 9 Feb 2026 19:06:18 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.161.74 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770663978; cv=none; b=iZxwuYRyUaTk22O/Ejgp5wKTRTHHj11VUW5EprsoIHlIVPd5DH4rsog2H2X5+QE9lTtxzTSNr+LFbd97+CZHspufjOMAmIjf/Pz4VCn08vQibZOmO9uG3e6pEPFys+6/FNAyF7YJxomCqkaR4pXVpBeSdrkL6DUqZXTipmhK4FI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770663978; c=relaxed/simple; bh=KXOEZJA8uLY54mQOX/8O8xLWaBAubA8yzr+1rqzHlac=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=XCjWMPNzYDNm7DWLA7xjA3bvkr3nMgA6iqEEboyHG1sOl/4jyHBCCn/2qsy3hJ+WpnWwWLR9OWUvRx6fUgMG36qdn75N3k6i8LSbzreaVdfNhy4OHK9SCv8fKJWxFEW1WnooqC1h4cOJXAYGPUStwnJAICutb7AWBlWKCkAOyMc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--avagin.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=DFYBuETU; arc=none smtp.client-ip=209.85.161.74 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--avagin.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="DFYBuETU" Received: by mail-oo1-f74.google.com with SMTP id 006d021491bc7-66304fd62ebso20017608eaf.3 for ; Mon, 09 Feb 2026 11:06:17 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1770663977; x=1771268777; 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=IZa/we8GMlNVxSd3WNL/zoRo7U46nDF+PjWI/oy/N/4=; b=DFYBuETUnYfY3e/SMzsgXemtwi1EDx4x83xyKiFq08YCZ6ZAJjHleM39ailVsIoQ2Y n3Kyv8hkMdD8V4b2v1S9MGQthAyloVgF2oe8NWaYg7+OWG41UbCdo8mtbtBzA9pOxByn czaSc2EE1TZEi+fvi5HONTOrjyk0ba60H0tVLB7/W5UTssbW1+/MsmBglEVUDtg/KF4d FCO+jg+BgZBfa2NUfMjkTG2Ip/WAysdxyp2AO3vCX2HX2shwWyP+0fAxmR2SAKqOCvIL avuSCSOu1wZ13v7Q/t3MZ0/1fCupT7EIIAYARc0S4kDE59PNRonZqfmOpfb8o8NOhUa9 g7bw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1770663977; x=1771268777; 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=IZa/we8GMlNVxSd3WNL/zoRo7U46nDF+PjWI/oy/N/4=; b=ucbUiKjDN0a3y8CyMCRlqZK5Af67Gt24BmHsFB1WJSoIxAw5FEeE1dmZxbc1DOPkrg SkF1vwoznxpNo4fSMl6bMAHSQhM2JdcwvSYvKDcyarRLLJ5XQGpWL7Eizoc6ybxxz7DB RsbHU1XshEDa0lR6XrqS9O3fx/9lSP5cGcnsCgaAVtcJS+v2vbUMDQ/abnK1yJxjtq1A ANFVsNZPyOpbQhv6df2gnej1GBszU3Y4Xe/dj4XuE17kuZMRTWriWzmFzgjs1HjkRK94 4CgJ/PjE0KZOn7uI5ac0UWtrpZwwxjdsAJf5igQhj+g9HBBJKCzQ0i4JnNVKtZltZw3x KrQw== X-Forwarded-Encrypted: i=1; AJvYcCUnNi6ZlZ3Yug6X5RHZCxNqb4O+l8P1XBh70DU/JgTf5PDlDOXB1T1Lw7PxTIBmKF2HB8Qa0UG69e1DgrA=@vger.kernel.org X-Gm-Message-State: AOJu0YyLN9peYA1JivFG7fY+j6kjimNxWFRB9oNyvx4o0QTT0p0p1vyz hZEPnuEGuxiQQfR2gb+1tArOISEgaOu6raCW472GQAz3doTK5aeGPgy1LH9G1duyoGua3zcJarf TKbSNAQ== X-Received: from ilbbb5.prod.google.com ([2002:a05:6e02:5:b0:48d:a328:15c4]) (user=avagin job=prod-delivery.src-stubby-dispatcher) by 2002:a05:6820:81d6:b0:65c:fb86:8a8e with SMTP id 006d021491bc7-66d331ce2dbmr5150912eaf.36.1770663977154; Mon, 09 Feb 2026 11:06:17 -0800 (PST) Date: Mon, 9 Feb 2026 19:06:03 +0000 In-Reply-To: <20260209190605.1564597-1-avagin@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20260209190605.1564597-1-avagin@google.com> X-Mailer: git-send-email 2.53.0.239.g8d8fc8a987-goog Message-ID: <20260209190605.1564597-3-avagin@google.com> Subject: [PATCH 2/4] exec: inherit HWCAPs from the parent process From: Andrei Vagin To: Kees Cook , Andrew Morton Cc: Cyrill Gorcunov , Mike Rapoport , Alexander Mikhalitsyn , linux-kernel@vger.kernel.org, linux-fsdevel@vger.kernel.org, linux-mm@kvack.org, criu@lists.linux.dev, Chen Ridong , Christian Brauner , David Hildenbrand , Eric Biederman , Lorenzo Stoakes , Michal Koutny , Andrei Vagin Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Introduces a mechanism to inherit hardware capabilities (AT_HWCAP, AT_HWCAP2, etc.) from a parent process when they have been modified via prctl. To support C/R operations (snapshots, live migration) in heterogeneous clusters, we must ensure that processes utilize CPU features available on all potential target nodes. To solve this, we need to advertise a common feature set across the cluster. This patch adds a new mm flag MMF_USER_HWCAP, which is set when the auxiliary vector is modified via prctl(PR_SET_MM, PR_SET_MM_AUXV). When execve() is called, if the current process has MMF_USER_HWCAP set, the HWCAP values are extracted from the current auxiliary vector and stored in the linux_binprm structure. These values are then used to populate the auxiliary vector of the new process, effectively inheriting the hardware capabilities. The inherited HWCAPs are masked with the hardware capabilities supported by the current kernel to ensure that we don't report more features than actually supported. This is important to avoid unexpected behavior, especially for processes with additional privileges. Signed-off-by: Andrei Vagin --- fs/binfmt_elf.c | 8 +++--- fs/binfmt_elf_fdpic.c | 8 +++--- fs/exec.c | 61 ++++++++++++++++++++++++++++++++++++++++ include/linux/binfmts.h | 11 ++++++++ include/linux/mm_types.h | 2 ++ kernel/fork.c | 3 ++ kernel/sys.c | 5 +++- 7 files changed, 89 insertions(+), 9 deletions(-) diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c index 3eb734c192e9..aec129e33f0b 100644 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c @@ -246,7 +246,7 @@ create_elf_tables(struct linux_binprm *bprm, const stru= ct elfhdr *exec, */ ARCH_DLINFO; #endif - NEW_AUX_ENT(AT_HWCAP, ELF_HWCAP); + NEW_AUX_ENT(AT_HWCAP, bprm->hwcap); NEW_AUX_ENT(AT_PAGESZ, ELF_EXEC_PAGESIZE); NEW_AUX_ENT(AT_CLKTCK, CLOCKS_PER_SEC); NEW_AUX_ENT(AT_PHDR, phdr_addr); @@ -264,13 +264,13 @@ create_elf_tables(struct linux_binprm *bprm, const st= ruct elfhdr *exec, NEW_AUX_ENT(AT_SECURE, bprm->secureexec); NEW_AUX_ENT(AT_RANDOM, (elf_addr_t)(unsigned long)u_rand_bytes); #ifdef ELF_HWCAP2 - NEW_AUX_ENT(AT_HWCAP2, ELF_HWCAP2); + NEW_AUX_ENT(AT_HWCAP2, bprm->hwcap2); #endif #ifdef ELF_HWCAP3 - NEW_AUX_ENT(AT_HWCAP3, ELF_HWCAP3); + NEW_AUX_ENT(AT_HWCAP3, bprm->hwcap3); #endif #ifdef ELF_HWCAP4 - NEW_AUX_ENT(AT_HWCAP4, ELF_HWCAP4); + NEW_AUX_ENT(AT_HWCAP4, bprm->hwcap4); #endif NEW_AUX_ENT(AT_EXECFN, bprm->exec); if (k_platform) { diff --git a/fs/binfmt_elf_fdpic.c b/fs/binfmt_elf_fdpic.c index a3d4e6973b29..55b482f03c82 100644 --- a/fs/binfmt_elf_fdpic.c +++ b/fs/binfmt_elf_fdpic.c @@ -629,15 +629,15 @@ static int create_elf_fdpic_tables(struct linux_binpr= m *bprm, */ ARCH_DLINFO; #endif - NEW_AUX_ENT(AT_HWCAP, ELF_HWCAP); + NEW_AUX_ENT(AT_HWCAP, bprm->hwcap); #ifdef ELF_HWCAP2 - NEW_AUX_ENT(AT_HWCAP2, ELF_HWCAP2); + NEW_AUX_ENT(AT_HWCAP2, bprm->hwcap2); #endif #ifdef ELF_HWCAP3 - NEW_AUX_ENT(AT_HWCAP3, ELF_HWCAP3); + NEW_AUX_ENT(AT_HWCAP3, bprm->hwcap3); #endif #ifdef ELF_HWCAP4 - NEW_AUX_ENT(AT_HWCAP4, ELF_HWCAP4); + NEW_AUX_ENT(AT_HWCAP4, bprm->hwcap4); #endif NEW_AUX_ENT(AT_PAGESZ, PAGE_SIZE); NEW_AUX_ENT(AT_CLKTCK, CLOCKS_PER_SEC); diff --git a/fs/exec.c b/fs/exec.c index 9d5ebc9d15b0..7401efbe4ba0 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -1462,6 +1462,17 @@ static struct linux_binprm *alloc_bprm(int fd, struc= t filename *filename, int fl */ bprm->is_check =3D !!(flags & AT_EXECVE_CHECK); =20 + bprm->hwcap =3D ELF_HWCAP; +#ifdef ELF_HWCAP2 + bprm->hwcap2 =3D ELF_HWCAP2; +#endif +#ifdef ELF_HWCAP3 + bprm->hwcap3 =3D ELF_HWCAP3; +#endif +#ifdef ELF_HWCAP4 + bprm->hwcap4 =3D ELF_HWCAP4; +#endif + retval =3D bprm_mm_init(bprm); if (!retval) return bprm; @@ -1780,6 +1791,53 @@ static int bprm_execve(struct linux_binprm *bprm) return retval; } =20 +static void inherit_hwcap(struct linux_binprm *bprm) +{ + int i, n; + +#ifdef ELF_HWCAP4 + n =3D 4; +#elif defined(ELF_HWCAP3) + n =3D 3; +#elif defined(ELF_HWCAP2) + n =3D 2; +#else + n =3D 1; +#endif + + for (i =3D 0; n && i < AT_VECTOR_SIZE; i +=3D 2) { + long val =3D current->mm->saved_auxv[i + 1]; + + switch (current->mm->saved_auxv[i]) { + case AT_NULL: + goto done; + case AT_HWCAP: + bprm->hwcap =3D val & ELF_HWCAP; + break; +#ifdef ELF_HWCAP2 + case AT_HWCAP2: + bprm->hwcap2 =3D val & ELF_HWCAP2; + break; +#endif +#ifdef ELF_HWCAP3 + case AT_HWCAP3: + bprm->hwcap3 =3D val & ELF_HWCAP3; + break; +#endif +#ifdef ELF_HWCAP4 + case AT_HWCAP4: + bprm->hwcap4 =3D val & ELF_HWCAP4; + break; +#endif + default: + continue; + } + n--; + } +done: + mm_flags_set(MMF_USER_HWCAP, bprm->mm); +} + static int do_execveat_common(int fd, struct filename *filename, struct user_arg_ptr argv, struct user_arg_ptr envp, @@ -1856,6 +1914,9 @@ static int do_execveat_common(int fd, struct filename= *filename, current->comm, bprm->filename); } =20 + if (mm_flags_test(MMF_USER_HWCAP, current->mm)) + inherit_hwcap(bprm); + retval =3D bprm_execve(bprm); out_free: free_bprm(bprm); diff --git a/include/linux/binfmts.h b/include/linux/binfmts.h index 65abd5ab8836..94a3dcf9b1d2 100644 --- a/include/linux/binfmts.h +++ b/include/linux/binfmts.h @@ -2,6 +2,7 @@ #ifndef _LINUX_BINFMTS_H #define _LINUX_BINFMTS_H =20 +#include #include #include #include @@ -67,6 +68,16 @@ struct linux_binprm { unsigned long exec; =20 struct rlimit rlim_stack; /* Saved RLIMIT_STACK used during exec. */ + unsigned long hwcap; +#ifdef ELF_HWCAP2 + unsigned long hwcap2; +#endif +#ifdef ELF_HWCAP3 + unsigned long hwcap3; +#endif +#ifdef ELF_HWCAP4 + unsigned long hwcap4; +#endif =20 char buf[BINPRM_BUF_SIZE]; } __randomize_layout; diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h index 78950eb8926d..68c9131dceee 100644 --- a/include/linux/mm_types.h +++ b/include/linux/mm_types.h @@ -1871,6 +1871,8 @@ enum { #define MMF_TOPDOWN 31 /* mm searches top down by default */ #define MMF_TOPDOWN_MASK BIT(MMF_TOPDOWN) =20 +#define MMF_USER_HWCAP 32 /* user-defined HWCAPs */ + #define MMF_INIT_LEGACY_MASK (MMF_DUMPABLE_MASK | MMF_DUMP_FILTER_MASK |\ MMF_DISABLE_THP_MASK | MMF_HAS_MDWE_MASK |\ MMF_VM_MERGE_ANY_MASK | MMF_TOPDOWN_MASK) diff --git a/kernel/fork.c b/kernel/fork.c index b1f3915d5f8e..0091315643de 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -1103,6 +1103,9 @@ static struct mm_struct *mm_init(struct mm_struct *mm= , struct task_struct *p, =20 __mm_flags_overwrite_word(mm, mmf_init_legacy_flags(flags)); mm->def_flags =3D current->mm->def_flags & VM_INIT_DEF_MASK; + + if (mm_flags_test(MMF_USER_HWCAP, current->mm)) + mm_flags_set(MMF_USER_HWCAP, mm); } else { __mm_flags_overwrite_word(mm, default_dump_filter); mm->def_flags =3D 0; diff --git a/kernel/sys.c b/kernel/sys.c index 8d199cf457ae..6fbd7be21a5f 100644 --- a/kernel/sys.c +++ b/kernel/sys.c @@ -2157,8 +2157,10 @@ static int prctl_set_mm_map(int opt, const void __us= er *addr, unsigned long data * not introduce additional locks here making the kernel * more complex. */ - if (prctl_map.auxv_size) + if (prctl_map.auxv_size) { memcpy(mm->saved_auxv, user_auxv, sizeof(user_auxv)); + mm_flags_set(MMF_USER_HWCAP, current->mm); + } =20 mmap_read_unlock(mm); return 0; @@ -2190,6 +2192,7 @@ static int prctl_set_auxv(struct mm_struct *mm, unsig= ned long addr, =20 task_lock(current); memcpy(mm->saved_auxv, user_auxv, len); + mm_flags_set(MMF_USER_HWCAP, current->mm); task_unlock(current); =20 return 0; --=20 2.53.0.239.g8d8fc8a987-goog From nobody Tue Feb 10 06:04:47 2026 Received: from mail-oo1-f73.google.com (mail-oo1-f73.google.com [209.85.161.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 592404218B6 for ; Mon, 9 Feb 2026 19:06:19 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.161.73 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770663979; cv=none; b=gj06XxUNZEGM0vAUn3kd1/XJQVDC6kjt4ICkj1bmnhaKyjUIrRpQ4ifJdd60pRjTUWHtSMbVZbbeQ47O+btFTmKgV1ULaS3Og9G2o4rxt4b27EvO1fpoGOcqTiDNV2UeganTVMU8BYPBSRPMrToRvLjgw4BQoXBHhEc74LqKu9A= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770663979; c=relaxed/simple; bh=77kGZVNaKYz+QXGZQBlLxOKMlsctKpB/eDPJq1uQV94=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=DrKXUK/MsE/Ow4Wq2216SCnaDJDoiNyv+JioObdLnMSx6l83yt7XddsDMQ/RhRdbD5DinqPTF/kfvzGlgOp+umzFQKakgdPalN6S0AN0nbYnnWGmKyxzbikf3JHl3hOjZ6kUn2eSo64n2ZcmloCVzXOruaBglqzEM86QdJHUtkU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--avagin.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=yUhqOWxR; arc=none smtp.client-ip=209.85.161.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--avagin.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="yUhqOWxR" Received: by mail-oo1-f73.google.com with SMTP id 006d021491bc7-66b24a54973so7505667eaf.0 for ; Mon, 09 Feb 2026 11:06:19 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1770663978; x=1771268778; 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=I4G/yDIBINwPi2+ikRkQ7TO2ayApdYAt//QBA3TmHUE=; b=yUhqOWxRhqST4aV+4mP0MkcQsUiaezX0zZVEpJAJvHNrrw14frzINT7E76YB5TSrUB 1JulcVK/wxgbwJaGFsy4mU5aV1PsBT4jmPiSLzmUVgcXnH1TZKDxYAcUN3mkmSXrb1Gg D1DwxzFvmIhUHDZozxZ2TkFoaosPRJprAJJjwlWLj9DfO6GLDtjsCMntjqhYHuxF2+CN wyhAZV5MueUrHAtar1/eeCOHiSHx/muaiKjrwrp7B6EuNPXeJB5M332U8kAg5OB4TVeT Z+byHlm6RcyCkxWimUT1JZr1czIsWtmeBRSiqq4bIQhtZMWiRSO4u5i9H+rFKkUFAJBK JPdQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1770663978; x=1771268778; 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=I4G/yDIBINwPi2+ikRkQ7TO2ayApdYAt//QBA3TmHUE=; b=dmNplSehlp1xJ03W/waNPZp2jP58wvDdVcXFC6jde+BAU970AhNnCkd4shdcU5ZLjt 7Ff1c2hIEDWZaNNWglkKegTMgpZ8zuOHjbdQMgjLe2jFH7w3+JBIx5cP6wUpsDyIaL26 gD+gUintDzjX3rvBcXEHCUyJgVnt8e3ts68IshT9NUtZEKtcKwWp+R8eIpGeUdRtAXJF OnGAimJLCWUfAf9sbBx0RdFt/GBnwboL4G04sz1Mo0Z5wSdhNMOa1xq2ttzgmC/OxJcq L/L22LfB0yGorKPNYepxOa21oKxYNJoTV7LRdUXWBVbOhVGptgqCEZgWj+2ozT9Ew5JW 131Q== X-Forwarded-Encrypted: i=1; AJvYcCWzn8/sx4PA/dXF/xU/KyITU7poFmPqYCwuNqMEXVMGrBs9rTnwTfkp173+R7VUfaq5AknNGnCGqXP0XXE=@vger.kernel.org X-Gm-Message-State: AOJu0Yy+gqwrgPT6g9N6q6MZrBhRZfF+IPfv6MMBwexNJbNZULJoZuQi fHPSnT4r2yhemyMEKYwxeZ4FhjRFQ9owOySw/NW05mKiWc1zrSnTgxVSj5pWmR/lk1iEih3AVGr hyDNN4A== X-Received: from ilsl17.prod.google.com ([2002:a05:6e02:5d1:b0:447:81b5:ae2a]) (user=avagin job=prod-delivery.src-stubby-dispatcher) by 2002:a05:6820:1356:b0:667:7e1a:204a with SMTP id 006d021491bc7-66d0d10b35bmr5231904eaf.71.1770663978454; Mon, 09 Feb 2026 11:06:18 -0800 (PST) Date: Mon, 9 Feb 2026 19:06:04 +0000 In-Reply-To: <20260209190605.1564597-1-avagin@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20260209190605.1564597-1-avagin@google.com> X-Mailer: git-send-email 2.53.0.239.g8d8fc8a987-goog Message-ID: <20260209190605.1564597-4-avagin@google.com> Subject: [PATCH 3/4] mm: synchronize saved_auxv access with arg_lock From: Andrei Vagin To: Kees Cook , Andrew Morton Cc: Cyrill Gorcunov , Mike Rapoport , Alexander Mikhalitsyn , linux-kernel@vger.kernel.org, linux-fsdevel@vger.kernel.org, linux-mm@kvack.org, criu@lists.linux.dev, Chen Ridong , Christian Brauner , David Hildenbrand , Eric Biederman , Lorenzo Stoakes , Michal Koutny , Andrei Vagin Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" The mm->saved_auxv array stores the auxiliary vector, which can be modified via prctl(PR_SET_MM_AUXV) or prctl(PR_SET_MM_MAP). Previously, accesses to saved_auxv were not synchronized. This was a intentional trade-off, as the vector was only used to provide information to userspace via /proc/PID/auxv or prctl(PR_GET_AUXV), and consistency between the auxv values left to userspace. With the introduction of hardware capability (HWCAP) inheritance during execve, the kernel now relies on the contents of saved_auxv to configure the execution environment of new processes. An unsynchronized read during execve could result in a new process inheriting an inconsistent set of capabilities if the parent process updates its auxiliary vector concurrently. While it is still not strictly required to guarantee the consistency of auxv values on the kernel side, doing so is relatively straightforward. This change implements synchronization using arg_lock. Signed-off-by: Andrei Vagin --- fs/exec.c | 8 ++++++-- fs/proc/base.c | 12 +++++++++--- kernel/fork.c | 7 ++++++- kernel/sys.c | 29 ++++++++++++++--------------- 4 files changed, 35 insertions(+), 21 deletions(-) diff --git a/fs/exec.c b/fs/exec.c index 7401efbe4ba0..d7e3ad8c8051 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -1793,6 +1793,7 @@ static int bprm_execve(struct linux_binprm *bprm) =20 static void inherit_hwcap(struct linux_binprm *bprm) { + struct mm_struct *mm =3D current->mm; int i, n; =20 #ifdef ELF_HWCAP4 @@ -1805,10 +1806,12 @@ static void inherit_hwcap(struct linux_binprm *bprm) n =3D 1; #endif =20 + spin_lock(&mm->arg_lock); for (i =3D 0; n && i < AT_VECTOR_SIZE; i +=3D 2) { - long val =3D current->mm->saved_auxv[i + 1]; + unsigned long type =3D mm->saved_auxv[i]; + unsigned long val =3D mm->saved_auxv[i + 1]; =20 - switch (current->mm->saved_auxv[i]) { + switch (type) { case AT_NULL: goto done; case AT_HWCAP: @@ -1835,6 +1838,7 @@ static void inherit_hwcap(struct linux_binprm *bprm) n--; } done: + spin_unlock(&mm->arg_lock); mm_flags_set(MMF_USER_HWCAP, bprm->mm); } =20 diff --git a/fs/proc/base.c b/fs/proc/base.c index 4eec684baca9..09d887741268 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -1083,14 +1083,20 @@ static ssize_t auxv_read(struct file *file, char __= user *buf, { struct mm_struct *mm =3D file->private_data; unsigned int nwords =3D 0; + unsigned long saved_auxv[AT_VECTOR_SIZE]; =20 if (!mm) return 0; + + spin_lock(&mm->arg_lock); + memcpy(saved_auxv, mm->saved_auxv, sizeof(saved_auxv)); + spin_unlock(&mm->arg_lock); + do { nwords +=3D 2; - } while (mm->saved_auxv[nwords - 2] !=3D 0); /* AT_NULL */ - return simple_read_from_buffer(buf, count, ppos, mm->saved_auxv, - nwords * sizeof(mm->saved_auxv[0])); + } while (saved_auxv[nwords - 2] !=3D 0); /* AT_NULL */ + return simple_read_from_buffer(buf, count, ppos, saved_auxv, + nwords * sizeof(saved_auxv[0])); } =20 static const struct file_operations proc_auxv_operations =3D { diff --git a/kernel/fork.c b/kernel/fork.c index 0091315643de..c0a3dd94df22 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -1104,8 +1104,13 @@ static struct mm_struct *mm_init(struct mm_struct *m= m, struct task_struct *p, __mm_flags_overwrite_word(mm, mmf_init_legacy_flags(flags)); mm->def_flags =3D current->mm->def_flags & VM_INIT_DEF_MASK; =20 - if (mm_flags_test(MMF_USER_HWCAP, current->mm)) + if (mm_flags_test(MMF_USER_HWCAP, current->mm)) { + spin_lock(¤t->mm->arg_lock); mm_flags_set(MMF_USER_HWCAP, mm); + memcpy(mm->saved_auxv, current->mm->saved_auxv, + sizeof(mm->saved_auxv)); + spin_unlock(¤t->mm->arg_lock); + } } else { __mm_flags_overwrite_word(mm, default_dump_filter); mm->def_flags =3D 0; diff --git a/kernel/sys.c b/kernel/sys.c index 6fbd7be21a5f..eafb5f75cb5c 100644 --- a/kernel/sys.c +++ b/kernel/sys.c @@ -2147,20 +2147,11 @@ static int prctl_set_mm_map(int opt, const void __u= ser *addr, unsigned long data mm->arg_end =3D prctl_map.arg_end; mm->env_start =3D prctl_map.env_start; mm->env_end =3D prctl_map.env_end; - spin_unlock(&mm->arg_lock); - - /* - * Note this update of @saved_auxv is lockless thus - * if someone reads this member in procfs while we're - * updating -- it may get partly updated results. It's - * known and acceptable trade off: we leave it as is to - * not introduce additional locks here making the kernel - * more complex. - */ if (prctl_map.auxv_size) { - memcpy(mm->saved_auxv, user_auxv, sizeof(user_auxv)); mm_flags_set(MMF_USER_HWCAP, current->mm); + memcpy(mm->saved_auxv, user_auxv, sizeof(user_auxv)); } + spin_unlock(&mm->arg_lock); =20 mmap_read_unlock(mm); return 0; @@ -2190,10 +2181,10 @@ static int prctl_set_auxv(struct mm_struct *mm, uns= igned long addr, =20 BUILD_BUG_ON(sizeof(user_auxv) !=3D sizeof(mm->saved_auxv)); =20 - task_lock(current); - memcpy(mm->saved_auxv, user_auxv, len); + spin_lock(&mm->arg_lock); mm_flags_set(MMF_USER_HWCAP, current->mm); - task_unlock(current); + memcpy(mm->saved_auxv, user_auxv, len); + spin_unlock(&mm->arg_lock); =20 return 0; } @@ -2466,9 +2457,17 @@ static inline int prctl_get_mdwe(unsigned long arg2,= unsigned long arg3, static int prctl_get_auxv(void __user *addr, unsigned long len) { struct mm_struct *mm =3D current->mm; + unsigned long auxv[AT_VECTOR_SIZE]; unsigned long size =3D min_t(unsigned long, sizeof(mm->saved_auxv), len); =20 - if (size && copy_to_user(addr, mm->saved_auxv, size)) + if (!size) + return sizeof(mm->saved_auxv); + + spin_lock(&mm->arg_lock); + memcpy(auxv, mm->saved_auxv, size); + spin_unlock(&mm->arg_lock); + + if (copy_to_user(addr, auxv, size)) return -EFAULT; return sizeof(mm->saved_auxv); } --=20 2.53.0.239.g8d8fc8a987-goog From nobody Tue Feb 10 06:04:47 2026 Received: from mail-oa1-f74.google.com (mail-oa1-f74.google.com [209.85.160.74]) (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 D58AA421883 for ; Mon, 9 Feb 2026 19:06:20 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.160.74 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770663981; cv=none; b=U0mrT7Q/sMW84ZyZYFvy0dMS/EdEj0/0C/1tBgruQSXG1cMOIQET4CzA2bht8cLKoRFlZOLU5OjYxo6WUL4AzuJ3pAb/MdTV/8AM6rx9w/6WatkkzxzPIV/2ORhBREWmIrd5vRgeSINgMWKa639Sqi4Yn69swYHMaoVf2BodCpA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770663981; c=relaxed/simple; bh=t1eYTgIQfsUjEcHPxFna7n0kTRcRTM8rS8PN9kAqxRM=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=EwImxhbfnBo82tj38qlyfMexUrphHLF9Q5OaE3xigeND6w8443u8sUd3Zh9+waLyk+CBcJ7fA6Hpt+e+/ICG+DI4XiLV7mM5NKaBVZv/xeBaRsMajvxbVyK3kViPSBL2/UvCZ+4OSMVxJy7DKVTZF6vd0/19lrWjTfUmD+P7NYc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--avagin.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=gxbZ7qeY; arc=none smtp.client-ip=209.85.160.74 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--avagin.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="gxbZ7qeY" Received: by mail-oa1-f74.google.com with SMTP id 586e51a60fabf-409682c1693so14240023fac.1 for ; Mon, 09 Feb 2026 11:06:20 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1770663980; x=1771268780; 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=Y3gza5co478YYPeHfG5MnlQXarASyDN4UjfFwF45d5I=; b=gxbZ7qeY5hoMxfxjp/HAdqbdg+E2mNZuW2m95ulTq1KtUhwA1ZUB1X4O93kyNxPCFa hu75jryXeTjgN4HDfBy7jdKSQ/jcoAdYIqu4P5KxgB0+6VhwnK4JXsKsyywKN0ggXxl7 3wo+m4MeX29LGuOFg5RTEdkOKthfoWpzGt75EN7jsMMxuSySSHJ9lbb7qWrwu2tJ7yii xrwLaAKfk+J7KRtUWc6b832RBOAr0TsOO7v88384PWBsHq+l8FvwnVWu+lVdACz6+k0E nAoVlMWyAz93s3MzLIq+WNo73m4xTpd0ARhxAhSLPfyz38b2/xHZUlRW+1seAUSJ1IOq TjVQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1770663980; x=1771268780; 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=Y3gza5co478YYPeHfG5MnlQXarASyDN4UjfFwF45d5I=; b=ggVrxmCSZ3L8Kv2GKlsvliosbgP24uruJlcdXw5yZVtw0XMsqafoU5DsWG2dGEnJMm 3zNxyter+nxw2VcSTZOfJG6tUeJRLo1BVl6yyqiIcnPgO5ARNerlX7cvymjj6buhXsDD WqQMXcse3azD7jctZoeQIWHvLP1JobnBLj1AJMLDbt5nOOC1uTIjEzXQxwdtL7AQlCrF jGHHX4Q9VdlDXRmU/lQsNYCyCxKaxguWOmKleRlstTt6futAzTx96w99p9v9jWkReXLE qpWDwCGzc7/hGjgTidBrIzPGvFf4tzsJpn8fJT+IjMVmIyoI0BH1W5yPcPcSNf75RX6A xWaw== X-Forwarded-Encrypted: i=1; AJvYcCVJ/VwupdP0lIKkKA6l5qUnNwq8JcJospiN4+0Serw6bplN1LMg5irk+Es8jRgx70jt3QxtihFq91fjxGo=@vger.kernel.org X-Gm-Message-State: AOJu0YwcRTILRONfl/jDXz0U1te0Oz9INgwFjqNQZkWrMXnfF6ELMbjm makHbDf7ss1GYiDHJEO/EoY2WqAgFDAMBx6iRr4BJsk7mJGlsHmV3vNuPglgJF9yxr2QQMJRsBM NvO5Plw== X-Received: from oalg15.prod.google.com ([2002:a05:6870:85cf:b0:404:59ca:ea1c]) (user=avagin job=prod-delivery.src-stubby-dispatcher) by 2002:a05:6870:b414:b0:3d1:a15c:f06a with SMTP id 586e51a60fabf-40bf30182b4mr364249fac.0.1770663979793; Mon, 09 Feb 2026 11:06:19 -0800 (PST) Date: Mon, 9 Feb 2026 19:06:05 +0000 In-Reply-To: <20260209190605.1564597-1-avagin@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20260209190605.1564597-1-avagin@google.com> X-Mailer: git-send-email 2.53.0.239.g8d8fc8a987-goog Message-ID: <20260209190605.1564597-5-avagin@google.com> Subject: [PATCH 4/4] selftests/exec: add test for HWCAP inheritance From: Andrei Vagin To: Kees Cook , Andrew Morton Cc: Cyrill Gorcunov , Mike Rapoport , Alexander Mikhalitsyn , linux-kernel@vger.kernel.org, linux-fsdevel@vger.kernel.org, linux-mm@kvack.org, criu@lists.linux.dev, Chen Ridong , Christian Brauner , David Hildenbrand , Eric Biederman , Lorenzo Stoakes , Michal Koutny , Andrei Vagin Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Verify that HWCAPs are correctly inherited/preserved across execve() when modified via prctl(PR_SET_MM_AUXV). The test performs the following steps: * reads the current AUXV using prctl(PR_GET_AUXV); * finds an HWCAP entry and toggles its most significant bit; * replaces the AUXV of the current process with the modified one using prctl(PR_SET_MM, PR_SET_MM_AUXV); * executes itself to verify that the new program sees the modified HWCAP value. Signed-off-by: Andrei Vagin --- tools/testing/selftests/exec/.gitignore | 1 + tools/testing/selftests/exec/Makefile | 1 + tools/testing/selftests/exec/hwcap_inherit.c | 105 +++++++++++++++++++ 3 files changed, 107 insertions(+) create mode 100644 tools/testing/selftests/exec/hwcap_inherit.c diff --git a/tools/testing/selftests/exec/.gitignore b/tools/testing/selfte= sts/exec/.gitignore index 7f3d1ae762ec..2ff245fd0ba6 100644 --- a/tools/testing/selftests/exec/.gitignore +++ b/tools/testing/selftests/exec/.gitignore @@ -19,3 +19,4 @@ null-argv xxxxxxxx* pipe S_I*.test +hwcap_inherit \ No newline at end of file diff --git a/tools/testing/selftests/exec/Makefile b/tools/testing/selftest= s/exec/Makefile index 45a3cfc435cf..e73005965e05 100644 --- a/tools/testing/selftests/exec/Makefile +++ b/tools/testing/selftests/exec/Makefile @@ -20,6 +20,7 @@ TEST_FILES :=3D Makefile TEST_GEN_PROGS +=3D recursion-depth TEST_GEN_PROGS +=3D null-argv TEST_GEN_PROGS +=3D check-exec +TEST_GEN_PROGS +=3D hwcap_inherit =20 EXTRA_CLEAN :=3D $(OUTPUT)/subdir.moved $(OUTPUT)/execveat.moved $(OUTPUT)= /xxxxx* \ $(OUTPUT)/S_I*.test diff --git a/tools/testing/selftests/exec/hwcap_inherit.c b/tools/testing/s= elftests/exec/hwcap_inherit.c new file mode 100644 index 000000000000..1b43b2dbb1d0 --- /dev/null +++ b/tools/testing/selftests/exec/hwcap_inherit.c @@ -0,0 +1,105 @@ +// SPDX-License-Identifier: GPL-2.0 + +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../kselftest.h" + +static int find_msb(unsigned long v) +{ + return sizeof(v)*8 - __builtin_clzl(v) - 1; +} + +int main(int argc, char *argv[]) +{ + unsigned long auxv[1024], hwcap, new_hwcap, hwcap_idx; + int size, hwcap_type =3D 0, hwcap_feature, count, status; + char hwcap_str[32], hwcap_type_str[32]; + pid_t pid; + + if (argc > 1 && strcmp(argv[1], "verify") =3D=3D 0) { + unsigned long type =3D strtoul(argv[2], NULL, 16); + unsigned long expected =3D strtoul(argv[3], NULL, 16); + unsigned long hwcap =3D getauxval(type); + + if (hwcap !=3D expected) { + ksft_print_msg("HWCAP mismatch: type %lx, expected %lx, got %lx\n", + type, expected, hwcap); + return 1; + } + ksft_print_msg("HWCAP matched: %lx\n", hwcap); + return 0; + } + + ksft_print_header(); + ksft_set_plan(1); + + size =3D prctl(PR_GET_AUXV, auxv, sizeof(auxv), 0, 0); + if (size =3D=3D -1) + ksft_exit_fail_perror("prctl(PR_GET_AUXV)"); + + count =3D size / sizeof(unsigned long); + + /* Find the "latest" feature and try to mask it out. */ + for (int i =3D 0; i < count - 1; i +=3D 2) { + hwcap =3D auxv[i + 1]; + if (hwcap =3D=3D 0) + continue; + switch (auxv[i]) { + case AT_HWCAP4: + case AT_HWCAP3: + case AT_HWCAP2: + case AT_HWCAP: + hwcap_type =3D auxv[i]; + hwcap_feature =3D find_msb(hwcap); + hwcap_idx =3D i + 1; + break; + default: + continue; + } + } + if (hwcap_type =3D=3D 0) + ksft_exit_skip("No features found, skipping test\n"); + hwcap =3D auxv[hwcap_idx]; + new_hwcap =3D hwcap ^ (1UL << hwcap_feature); + auxv[hwcap_idx] =3D new_hwcap; + + if (prctl(PR_SET_MM, PR_SET_MM_AUXV, auxv, size, 0) < 0) { + if (errno =3D=3D EPERM) + ksft_exit_skip("prctl(PR_SET_MM_AUXV) requires CAP_SYS_RESOURCE\n"); + ksft_exit_fail_perror("prctl(PR_SET_MM_AUXV)"); + } + + pid =3D fork(); + if (pid < 0) + ksft_exit_fail_perror("fork"); + if (pid =3D=3D 0) { + char *new_argv[] =3D { argv[0], "verify", hwcap_type_str, hwcap_str, NUL= L }; + + snprintf(hwcap_str, sizeof(hwcap_str), "%lx", new_hwcap); + snprintf(hwcap_type_str, sizeof(hwcap_type_str), "%x", hwcap_type); + + execv(argv[0], new_argv); + perror("execv"); + exit(1); + } + + if (waitpid(pid, &status, 0) =3D=3D -1) + ksft_exit_fail_perror("waitpid"); + if (status !=3D 0) + ksft_exit_fail_msg("HWCAP inheritance failed (status %d)\n", status); + + ksft_test_result_pass("HWCAP inheritance succeeded\n"); + ksft_exit_pass(); + return 0; +} --=20 2.53.0.239.g8d8fc8a987-goog