From nobody Sat Feb 7 21:24:39 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 E48D22C0F7F for ; Thu, 8 Jan 2026 05:07:53 +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=1767848876; cv=none; b=Tl1pUHu1CGL+2+gkGpN+5Tq6E7ybOM0Zt8yuVYSmQl3dVRi/+3ZF2Bb/aK4smZl2T4xVsC4MsZZbSmyGjXkSXTDwS+MdQvl9UboHVWC4EBm7D6tCUISzaqVSEfwh8F8w7Bwc4YRELt2skSUHwAiKAjHwat9LK87Rn8dglgzItFw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1767848876; c=relaxed/simple; bh=LNdHpOYhkvVAHh3PEnvRLPGEb6i8i1k190yRkr69lE8=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=EV9Dr3BgREop/7qhSxGpWR8yuOkNrfKtJ1Ylbus3OSCtI+lFTVIzCTJu3uZlIwwy9kGkgaH+6S+H43+caZT42PYWDLn6m/z9rxou5msPy/9F+DKr9oUuyetv+mvmuyTYIdGBI2qYDf9SX0GnhQkdqlSvOyLhFCqd1iQEzX0parU= 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=aQm7idG6; 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="aQm7idG6" Received: by mail-oo1-f73.google.com with SMTP id 006d021491bc7-65b26eca9c7so5727340eaf.0 for ; Wed, 07 Jan 2026 21:07:53 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1767848873; x=1768453673; 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=dZQOsX2pgJ2tnboOIsX6ynvBnKeb3FSCcqmuKWQBi3o=; b=aQm7idG6Y8g87Tiq+iYeWpgRtGJyR9GxZJL2qWkk1Mpex0dYB2FSa+FlKn2huOXG5X IOsATT1PUDq60qH3nOXOR9M+ldjznDn+KVVHQDSZeTBOpln0U0bAQmqwbxgo+p7huEmv F0RGbDBs8Il9IVQ9I2AW0j9fhLalHaZcFyIEruGDprYEUD1atGDRyFgBcPnKXGFAxHRN BV2t4Vw3Z5LGdBQkc86YsVkuAGFOMNec+OA7a4bxLFawz6bcCvXdIOr08GnFergcQarp /1bCRZnr9M4xev5emzx33g7F8pSEVxjcPTsSdtTe8TdoBkmKew/RkQai3lSprfLuCDr0 12zw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1767848873; x=1768453673; 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=dZQOsX2pgJ2tnboOIsX6ynvBnKeb3FSCcqmuKWQBi3o=; b=bRWvACHCfSLFQEK2FUF4kE/JsHL23mCyea1g+bJnrlsbvEpOTblyXd+GgqcTj4DITq iGpfI3hwNqaAj3pFNEPKATSx1Bwp/fYQmjMJwsc83Z3otUVCs5+KoYZXLZrbO1sNqizw u6WDqVccmqZTjnnWCZewqG375l3e9Z5Y51OzqxCZ7tRF4xB6mHSC82Br94OIS8Aw6jfW F3Xh7PJqUlqWaqkGvfG3v/db04iqOVS/weYR5IwbEUdDG627ymka5DmhHJUkbJa2hLIm u918q9aJXJEqksya62mf3xh0JXz39hq4wyq/gxlsEgaa3JcTVML2c9inqGJMLq6102qT C3Xw== X-Gm-Message-State: AOJu0YwmocRrI8eH903gU8FkOY9y+FTOs+ozDbSmNF6CZITQQk4JY3I9 JmkMr7Q2dsiegrS7LA2H8PwnS1O+24C4gTTg2Rg45T6l2OvdxWMsfZjC18ZKWn4ls3mCJqibcZI /mxjlDg== X-Google-Smtp-Source: AGHT+IFrclr5UQo7zl+uW+fx86un/1H6WIw+B6ZZGi+Mh3xwDR/cU/G0W87Tu8yHbTlESc7N66Kjw62yaIA= X-Received: from ilbdr9.prod.google.com ([2002:a05:6e02:3f09:b0:439:46f3:4729]) (user=avagin job=prod-delivery.src-stubby-dispatcher) by 2002:a4a:d666:0:b0:65c:f12c:e74e with SMTP id 006d021491bc7-65f54ec7815mr1678998eaf.6.1767848872864; Wed, 07 Jan 2026 21:07:52 -0800 (PST) Date: Thu, 8 Jan 2026 05:07:46 +0000 In-Reply-To: <20260108050748.520792-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: <20260108050748.520792-1-avagin@google.com> X-Mailer: git-send-email 2.52.0.351.gbe84eed79e-goog Message-ID: <20260108050748.520792-2-avagin@google.com> Subject: [PATCH 1/3] binfmt_elf_fdpic: fix AUXV size calculation for ELF_HWCAP3 and ELF_HWCAP4 From: Andrei Vagin To: Kees Cook Cc: linux-kernel@vger.kernel.org, linux-fsdevel@vger.kernel.org, linux-mm@kvack.org, criu@lists.linux.dev, Andrew Morton , 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 ELF_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 Fixes: 4e6e8c2b757f ("binfmt_elf: Wire up AT_HWCAP3 at AT_HWCAP4") Signed-off-by: Andrei Vagin Reviewed-by: Mark Brown Reviewed-by: Michal Koutn=C3=BD --- 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.52.0.351.gbe84eed79e-goog From nobody Sat Feb 7 21:24:39 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 368222D4B40 for ; Thu, 8 Jan 2026 05:07:55 +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=1767848877; cv=none; b=Abt9SKQXY/jO6AUG0o6vNId9h8hB1tY7I2biedHc92VxV2eXYCIqeXODGICmuMA3mf31OnHuhZkyctiJaBVmG4WngKmDg+AzTBCzn5CLnJ6S2evgDLpZ2s7lU8zytWBlfI1kT0GbCj6ns/lbevQFqWma/0PxUcT8M/MUPDUcHUE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1767848877; c=relaxed/simple; bh=xai/ZZ4nWO9LhAkDeI2fOyW7f7WEasHJs/SoRQMaWes=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=kUvmz6AP6y3esuWKN9k0g6UxCEiUaBHps7xNQr+RzsgQkFSL9c25/RbtN3Ijz4NI2gLUmYrvQ4NkWWQ5p6u0iKKRbehM0cYCQxio8oLiwGiugAmW48jiZKL6pKnmm3wzGp/496k89+dMY9O8lDZuNRIZwccVGJrccIW9fdNEAs8= 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=RlY9pZDX; 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="RlY9pZDX" Received: by mail-oo1-f73.google.com with SMTP id 006d021491bc7-65742f8c565so3592493eaf.1 for ; Wed, 07 Jan 2026 21:07:55 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1767848874; x=1768453674; 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=BM9pkeWkyDkeF/wsVeQk1KlrHlvWtFk07wiFD8D6vLQ=; b=RlY9pZDXvzwns8EbV7ZhOPRjVFVpH22XtqzAkijfpHua8bCTdNViBvqKmllmmWHrb9 mTEjw/pXEadX5qdXTTsWd2pu3husLDhxyswXClFhLMfb7ARa53ui7/xTIgVtY9Rh1u8K Z9D+aYa9fo+br7nKb/M12qZtRqGfQnn0ibwKcmniNfJANONE7etvIa9iMrudqAWetFDA THePIGADn6fQKLhIpNusYYkAEog6Rp2x+Aj7DglquZOV9m6g++v6VGLvcQOBT0XbqrZZ 3EwcspBcUwRg4IMSvyldLWdZ0mnAMQBRZPdQaqLum0lhYSb2fI1j9d4c0Rx5qy4t8Z/T L33Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1767848874; x=1768453674; 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=BM9pkeWkyDkeF/wsVeQk1KlrHlvWtFk07wiFD8D6vLQ=; b=nhYyDxfHlfoja0fkgeXjz+lTg6RJA3JKC/5kb4b6xNA2MPaj0ycHCGsGL8M7y7eu40 FuZftVHdnm5wWZ05QwKbhDJlQF9u7JN2afVTHu4M7gbfwGePP0s2EqWqD6Y++6fOVKGR oMIqqSfGucz0oiWLJjbOqu6HQ2OwGH8RzGl0SfbJs4JcAHiFb+NyEm2yzkMlESNN58zb YQqVlQEibW8sipYIyBdYX5sA1TNaIGH0bTa3TQ+vFIe7yfZVk80eYC0toyr7tBTr5t+/ 0AGPkeRl9sbYCDuUSLrl+yp9pyrON3T3Jj/wfoHeFQFzHh9R/KNykXpnTxIvTouIvMc1 fB1A== X-Gm-Message-State: AOJu0YwkvuK25PUBjtb6YJU6dJELEBC0jCiWDdaWkXVF9ORzYlTtcWau WJhWwDF78Bxl3aEklwxUI38Wzc+PoJTQt6nD2yv+W7k561hlBOf0uuzgXp43YzM+r9cAlgCxdEE DTfNFUw== X-Google-Smtp-Source: AGHT+IHignbPdIC8t4fB2nIzu96Ku0xOznzgAT1ynazkafzO6fVYBLy8OffFhZPxxjW0YPmoKPVOk64VQHI= X-Received: from iobjk24.prod.google.com ([2002:a05:6602:7218:b0:954:95ac:e0cc]) (user=avagin job=prod-delivery.src-stubby-dispatcher) by 2002:a05:6820:228f:b0:659:9a49:8f93 with SMTP id 006d021491bc7-65f54eea37dmr2056872eaf.12.1767848874105; Wed, 07 Jan 2026 21:07:54 -0800 (PST) Date: Thu, 8 Jan 2026 05:07:47 +0000 In-Reply-To: <20260108050748.520792-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: <20260108050748.520792-1-avagin@google.com> X-Mailer: git-send-email 2.52.0.351.gbe84eed79e-goog Message-ID: <20260108050748.520792-3-avagin@google.com> Subject: [PATCH 2/3] exec: inherit HWCAPs from the parent process From: Andrei Vagin To: Kees Cook Cc: linux-kernel@vger.kernel.org, linux-fsdevel@vger.kernel.org, linux-mm@kvack.org, criu@lists.linux.dev, Andrew Morton , 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 | 58 ++++++++++++++++++++++++++++++++++++++++ include/linux/binfmts.h | 11 ++++++++ include/linux/mm_types.h | 2 ++ kernel/fork.c | 3 +++ kernel/sys.c | 5 +++- 7 files changed, 86 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..94382285eeda 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,50 @@ 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_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--; + } + 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 +1911,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 42af2292951d..93e7aa929fda 100644 --- a/include/linux/mm_types.h +++ b/include/linux/mm_types.h @@ -1862,6 +1862,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..83283001abfb 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; @@ -2191,6 +2193,7 @@ static int prctl_set_auxv(struct mm_struct *mm, unsig= ned long addr, task_lock(current); memcpy(mm->saved_auxv, user_auxv, len); task_unlock(current); + mm_flags_set(MMF_USER_HWCAP, current->mm); =20 return 0; } --=20 2.52.0.351.gbe84eed79e-goog From nobody Sat Feb 7 21:24:39 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 4B2C22D7DCF for ; Thu, 8 Jan 2026 05:07:56 +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=1767848878; cv=none; b=ce8Yy8yiSJpOcgEdgI8y4mBYlt0mlwbuVEZggpjrVJqXORqSzDjmE+7QvesseDln7V8ufj6QOO4sjEsCAa+1ILaKjyXwu5ZQwmv25ZdkWV7arVp2jzqSUrN/cLqdidktqFrbCNtG7iannlPjnkNVPbeXzljin97ErzP4pMfTiCQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1767848878; c=relaxed/simple; bh=MP0u1zrI0fnXYNh85S3yYQJ3ZSNyI4Rv0qWzsYrRyFg=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=UTNYAyGuuvwS7XKJCo8W8+gzhOk8daef9R7Rcf+20Fof4PWR5unwbzAsjWEE/QNcLgpKZGJ+0asmR0U8SaSMCLU5nsIr6rN4u8poh86q2UFGEt5Fhq9s89Lq31GLNRqssEf3pHpDzOWJ/rXGijlQxqfZN1o9q8Qsn9j1h030ex8= 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=uO/D3DK1; 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="uO/D3DK1" Received: by mail-oo1-f74.google.com with SMTP id 006d021491bc7-65cfc52c912so4253275eaf.2 for ; Wed, 07 Jan 2026 21:07:56 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1767848875; x=1768453675; 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=Q1hhEQ/dcIyjHD8R0p3IwfdlLsdWEz7YcUZfHbTaGDU=; b=uO/D3DK1TyKgddVvxSuZgMgRcGbGhQycuCtzvG6S+bt7DUKSGpBz3dzSE7ftmb7sJq zE/NARxC/NDERLW9yeO0dspWPreNG0+IQjT9XlqCKNE3FKs6vsE8/ukuzgTPzUztCmpN LTJRqFzY/Kd5REdqOyTejFbpT2yqxKnjQgyNdGHQv7XVYga+r1Ea6+ZOb9BOcdszAdcE 0G7BWaNHUz9klzToS1CvatS1bjVgBLvEWDLRWycV4KCnKA4zLbQAmLQVQwwq07+71dn3 mPuNcq714HFK4c/n1sZpH3XcLlzSHiLPI8aOZEMJNzfmFbMnYFmkRAz5/W8eExZsPLI7 iBYA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1767848875; x=1768453675; 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=Q1hhEQ/dcIyjHD8R0p3IwfdlLsdWEz7YcUZfHbTaGDU=; b=BpnbkPJXTB9rQN9twv/XAUnyXZmT3dyuJJk2LIbqbii5ZzwwTXnfEtm505d1BjCtIG 4CC8c3dJaxHt4VoB6u0jLNtZtCq+tjsd3WR3pY84x0UED/bX2iJOBD7WsxEYaYHQJe2y PjsyLy4juPCVHApoLH+s5Jyffjt7n1tJHHMqRSIRy1c7+zv4fO47U1FWxHcE8h77AznE k/4d0tQmk/8wyOCO+q6WEHYNvUfkAf2RvwFmX8U7CiWZFwKuHx7yxoiWEy2LZvwiL+t5 dZITf8SCYJeHQ4j2Da+46QvxJf3CvcPt+Wd3APPUBhp0/8XWSocX0U7pCJU0ydeiWi9d KeNw== X-Gm-Message-State: AOJu0YwqNN3ZYWYCEoB+X4dHfzzbQSFH8FOxiBjaIq2iy0FDFt5VT5+R ShUYZ8dVzQdmIfQ4S2B4aezl5rWYFD5FepNsC94yJ6L0bYrj7CnbpmcWLKQNyNDiz830NipcDsv sxjc/BQ== X-Google-Smtp-Source: AGHT+IG6PRfdl7A+xXyBMjsVyyTg1K6TF0yM6mRQxM81LAutvzKwdfc7WseETy3uSVVUyTVIXphzxa2bYvw= X-Received: from iobid13.prod.google.com ([2002:a05:6602:6a8d:b0:954:45e5:5098]) (user=avagin job=prod-delivery.src-stubby-dispatcher) by 2002:a4a:cb10:0:b0:65b:38e2:33b5 with SMTP id 006d021491bc7-65f54f7b279mr1489724eaf.49.1767848875303; Wed, 07 Jan 2026 21:07:55 -0800 (PST) Date: Thu, 8 Jan 2026 05:07:48 +0000 In-Reply-To: <20260108050748.520792-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: <20260108050748.520792-1-avagin@google.com> X-Mailer: git-send-email 2.52.0.351.gbe84eed79e-goog Message-ID: <20260108050748.520792-4-avagin@google.com> Subject: [PATCH 3/3] selftests/exec: add test for HWCAP inheritance From: Andrei Vagin To: Kees Cook Cc: linux-kernel@vger.kernel.org, linux-fsdevel@vger.kernel.org, linux-mm@kvack.org, criu@lists.linux.dev, Andrew Morton , 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 | 104 +++++++++++++++++++ 3 files changed, 106 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..ef80a010765d --- /dev/null +++ b/tools/testing/selftests/exec/hwcap_inherit.c @@ -0,0 +1,104 @@ +// 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"); + 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.52.0.351.gbe84eed79e-goog