From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-pj1-f54.google.com (mail-pj1-f54.google.com [209.85.216.54]) (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 1735D35C1A6 for ; Fri, 10 Jul 2026 20:53:56 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.216.54 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783716839; cv=none; b=s3xoUDSpMrjahKBPTkhedWnxs2XZDH96PiEAXU/eW7tp+iSEAjnTGeKkl6S10RsLFKTZSfhf9UGDhkVujBj3+XY9y88AmJEz/ilUO3CaBqjzlltnJv8EpbeC2ZE5jEFRBTeO3I4W0XKFwFLBSOH3WPIEHZYDlFfcznsokRb/2BU= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783716839; c=relaxed/simple; bh=oQbNURJxL+tjqWctpsqGm1Ty7qfTIql5z83UGi8D+2U=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=gwhQihDCgSxWE+Od60O4qgZxEheQOUYiIuIiFJ4tmceM2Aq7yD7HWdqSd3eHwg2mouckC8JnbO71o2GchfuTVlXoWJsIIgOQVH8ubgNvhgxwozgTyZ1XMl1rYKuf1uNCw3js0sMFyxHryk4BHl8P/zzGMlg5vNZ+QUKRI1XJ0Ag= 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=exdEfVzT; arc=none smtp.client-ip=209.85.216.54 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="exdEfVzT" Received: by mail-pj1-f54.google.com with SMTP id 98e67ed59e1d1-381c51fde6bso1379947a91.2 for ; Fri, 10 Jul 2026 13:53:56 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1783716836; x=1784321636; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=sCserWiFtJpC7hBtSNUd5SRB8rb8z/bWzdzLHsDDkzQ=; b=exdEfVzTkirQYZR79aeeak5D9efLhsTtokmZuHpgn8VXUeWKXJoWG81Vviiv3p8qHQ EZQZRhucKMm/lVlNi8u6rKvEQR2ilQkQXCgX/9Dg68+s7Q+OXVb1lpKqx49Q/j/KI2gN yk1aMpa0/eZA3sam+dXe3aV1TMT2LIPpnX9iCsGbgOecvGI/NFF4vOkjcVhOBA9YUGYg JKxZy4oVCj8imNI+s4/KrXpoO7GUhbkdiskNGvX2oxBwHtjfcOEmSGR0gqU9y3bxtYkj LJMnoyFP9mrLGo+Z1u87/y1cHzDv0q9kwdUIIJOuiwWwqFSavbslN0uIbizNabBGv6ye MstA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1783716836; x=1784321636; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=sCserWiFtJpC7hBtSNUd5SRB8rb8z/bWzdzLHsDDkzQ=; b=I7fLaWtWII7mCJdpXHQzsqIvWyqL5IvZRKmFBiGMrSZSo8O1NvGc3Rcmo6XV0pdnJP qXpBOeu/Ra77jGGBFxwK+JbbwgnKfJuq2nQTzXp8pfSMNh3ofJwiVHya78hd3WLriKB/ MxHUysNC+RwDU93IkSRuQCSpkYt1yP8D2kl2jZSkw20hCW6dgxd7LcC1ycqphFWZp9db 6aJCboYtsimkzCLqSyJFaMAak+iKWkAbAW4FDLKEnf05Bp32aiHZpP63TPesg/wWUXMV snDLc4lXFswSKiEO3MsBixN+bei7Sn6gAaavJXCMtK9bY5u25P40ZCZyr89TXxbeIOht yonQ== X-Forwarded-Encrypted: i=1; AHgh+RpJBcB0ls3GzcDq4T/BzwCnXs2U7HSlstXoraqA5t1nSYGJdqDX+JQ6D0PAhfkC8ZJlDpNc0w6ypaOn8AM=@vger.kernel.org X-Gm-Message-State: AOJu0YzfgQ/fRwln5Yb6qtH6XgzAQGcdpJUm4Righkp+wBEtPvUIUEv5 p+9wBc7B/Un//uADOZiPkTWkqcYWEwAr31obc0Ym56uByABcGINyj/+O X-Gm-Gg: AfdE7cktfK/mQ9pIzspkWS0PN+HeKOmaG/7eF969xbkcKdbEDpC8OAZF3WDTS0RRzxX OtZh72bJi2C4lMRoV+H5zhkcqf3RDENWhOfeUHbl/mmZo6RGkfaZBeTwRRJhutCRZuc1BrnhnQG yn/m91qqW0e/FAN0+qKDR0lEP/6+ta/lVKX1rHvozxpasmbZffE6D0KJaXttzktM0pPMuZvD10W KWUUaJCRz27/nfNR0FwQHWXitu9tzYnwkpLCEDnXq10EIoEuw0Gzy4jhzgAHJxI5dvB5Wv62b6+ OhHX5T8T3cdedUGqFQLT816LVqyjAK4cofQSamuUjr8gLn3FWztclGFXhXegLsJC/CJ/j9WtZi1 KrCoDvZTPiPLAyt+MrjmZ24J+OvMYBjev4y68/ioppViIHiCiIRqSfJl3pmV3HINJVmIoHp/pve ChWoFjSZHn74nYcFnJ8sXvcaetRlPKSm2/SJYBEusZPrD2DJPgcuYatQo= X-Received: by 2002:a05:6a21:46c5:b0:3bf:b40b:def2 with SMTP id adf61e73a8af0-3c11003092dmr563350637.9.1783716835815; Fri, 10 Jul 2026 13:53:55 -0700 (PDT) Received: from pop-os.scu.edu ([129.210.115.107]) by smtp.gmail.com with ESMTPSA id 5a478bee46e88-3119c2a7bb5sm21724371eec.25.2026.07.10.13.53.54 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 10 Jul 2026 13:53:55 -0700 (PDT) From: Cong Wang To: Richard Weinberger , Anton Ivanov , Johannes Berg Cc: Benjamin Berg , linux-um@lists.infradead.org, linux-kernel@vger.kernel.org, Cong Wang Subject: [RFC PATCH 1/6] pidfd: add pidfd_mmap()/pidfd_munmap() syscalls Date: Fri, 10 Jul 2026 13:53:19 -0700 Message-ID: <20260710205324.1343217-2-xiyou.wangcong@gmail.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260710205324.1343217-1-xiyou.wangcong@gmail.com> References: <20260710205324.1343217-1-xiyou.wangcong@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit From: Cong Wang A supervisor that may PTRACE_ATTACH a target installs or removes a mapping in the target's address space directly, without target-side cooperation. The backing fd is resolved in the *caller's* fd table, mirroring pidfd_getfd()'s cross-task install model. pidfd_mmap() takes an extensible struct pidfd_mmap_args (clone3/openat2 style, versioned by a leading size field) since an mmap-shaped call exceeds the 6-argument syscall limit. pidfd_munmap() is a flat 3-arg call. Both are gated by ptrace_may_access(PTRACE_MODE_ATTACH_REALCREDS) and wired for x86_64 and the asm-generic table. Assisted-by: Claude:claude-opus-4.8 Signed-off-by: Cong Wang --- arch/x86/entry/syscalls/syscall_64.tbl | 2 + include/linux/syscalls.h | 5 + include/uapi/linux/pidfd.h | 18 ++++ kernel/pid.c | 132 +++++++++++++++++++++++++ scripts/syscall.tbl | 2 + 5 files changed, 159 insertions(+) diff --git a/arch/x86/entry/syscalls/syscall_64.tbl b/arch/x86/entry/syscalls/syscall_64.tbl index 524155d655da..12e3cbeb0d2c 100644 --- a/arch/x86/entry/syscalls/syscall_64.tbl +++ b/arch/x86/entry/syscalls/syscall_64.tbl @@ -396,6 +396,8 @@ 469 common file_setattr sys_file_setattr 470 common listns sys_listns 471 common rseq_slice_yield sys_rseq_slice_yield +472 common pidfd_mmap sys_pidfd_mmap +473 common pidfd_munmap sys_pidfd_munmap # # Due to a historical design error, certain syscalls are numbered differently diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h index 874d9067a43b..301a2d80823b 100644 --- a/include/linux/syscalls.h +++ b/include/linux/syscalls.h @@ -78,6 +78,7 @@ struct statmount; struct mnt_id_req; struct ns_id_req; struct xattr_args; +struct pidfd_mmap_args; struct file_attr; #include @@ -986,6 +987,10 @@ asmlinkage long sys_pidfd_send_signal(int pidfd, int sig, siginfo_t __user *info, unsigned int flags); asmlinkage long sys_pidfd_getfd(int pidfd, int fd, unsigned int flags); +asmlinkage long sys_pidfd_mmap(int pidfd, struct pidfd_mmap_args __user *uargs, + unsigned int flags); +asmlinkage long sys_pidfd_munmap(int pidfd, unsigned long addr, + unsigned long len); asmlinkage long sys_landlock_create_ruleset(const struct landlock_ruleset_attr __user *attr, size_t size, __u32 flags); asmlinkage long sys_landlock_add_rule(int ruleset_fd, enum landlock_rule_type rule_type, diff --git a/include/uapi/linux/pidfd.h b/include/uapi/linux/pidfd.h index 0919246a1611..d68a11d844e3 100644 --- a/include/uapi/linux/pidfd.h +++ b/include/uapi/linux/pidfd.h @@ -107,6 +107,24 @@ struct pidfd_info { __u64 supported_mask; /* Mask flags that this kernel supports */ }; +/* + * Argument block for pidfd_mmap(). Extensible: @size is sizeof(struct) as + * known to userspace; the kernel zero-extends older/smaller structs and + * rejects unknown non-zero trailing bytes (see copy_struct_from_user()). + */ +struct pidfd_mmap_args { + __u64 size; /* sizeof(struct pidfd_mmap_args) */ + __u64 addr; /* MAP_FIXED target address, or 0 to let the kernel choose */ + __u64 len; /* length in bytes */ + __u64 prot; /* PROT_* protection bits */ + __u64 flags; /* MAP_* flags */ + __u64 pgoff; /* page offset into @fd */ + __s32 fd; /* backing fd in the caller's fd table, or -1 (MAP_ANONYMOUS) */ + __u32 __spare; /* must be zero */ +}; + +#define PIDFD_MMAP_ARGS_SIZE_VER0 56 /* sizeof first published struct */ + #define PIDFS_IOCTL_MAGIC 0xFF #define PIDFD_GET_CGROUP_NAMESPACE _IO(PIDFS_IOCTL_MAGIC, 1) diff --git a/kernel/pid.c b/kernel/pid.c index f55189a3d07d..d51471a36f3e 100644 --- a/kernel/pid.c +++ b/kernel/pid.c @@ -28,6 +28,12 @@ */ #include +#include +#include +#include +#include +#include +#include #include #include #include @@ -972,3 +978,129 @@ SYSCALL_DEFINE3(pidfd_getfd, int, pidfd, int, fd, return pidfd_getfd(pid, fd); } + +/* + * Resolve @pidfd to its task's mm, gated like a ptrace attach. On success the + * caller owns the returned mm reference and must mmput() it. Mirrors the + * cross-task authorization of pidfd_getfd(): a supervisor that may + * PTRACE_ATTACH the target may install into its address space. + */ +static int pidfd_target_mm(int pidfd, struct mm_struct **mmp) +{ + struct task_struct *task; + struct mm_struct *mm; + unsigned int f_flags; + + task = pidfd_get_task(pidfd, &f_flags); + if (IS_ERR(task)) + return PTR_ERR(task); + + if (!ptrace_may_access(task, PTRACE_MODE_ATTACH_REALCREDS)) { + put_task_struct(task); + return -EPERM; + } + + mm = get_task_mm(task); + put_task_struct(task); + if (!mm) + return -ESRCH; + + *mmp = mm; + return 0; +} + +/** + * sys_pidfd_mmap() - install a mapping into another process's address space. + * @pidfd: pidfd of the target task. + * @uargs: pointer to a struct pidfd_mmap_args describing the mapping. + * @flags: reserved, must be zero. + * + * The backing fd (if any) is resolved in the *caller's* fd table, so a + * supervisor maps from its own descriptors into the target -- the target + * never needs to receive the fd. Gated by ptrace_may_access(); LSM/fsnotify + * hooks run against the caller. + * + * Returns the mapped address on success, or a negative errno. + */ +SYSCALL_DEFINE3(pidfd_mmap, int, pidfd, struct pidfd_mmap_args __user *, uargs, + unsigned int, flags) +{ + struct pidfd_mmap_args args; + struct mm_struct *mm; + struct file *file = NULL; + unsigned long ret; + u64 usize; + int err; + + if (flags) + return -EINVAL; + + if (get_user(usize, &uargs->size)) + return -EFAULT; + if (usize < PIDFD_MMAP_ARGS_SIZE_VER0) + return -EINVAL; + if (usize > PAGE_SIZE) + return -E2BIG; + + err = copy_struct_from_user(&args, sizeof(args), uargs, usize); + if (err) + return err; + if (args.__spare) + return -EINVAL; + + if (args.flags & MAP_HUGETLB) + return -EINVAL; + if (args.addr != (unsigned long)args.addr || + args.len != (unsigned long)args.len || + args.prot != (unsigned long)args.prot || + args.flags != (unsigned long)args.flags || + args.pgoff != (unsigned long)args.pgoff) + return -EINVAL; + + err = pidfd_target_mm(pidfd, &mm); + if (err) + return err; + + if (!(args.flags & MAP_ANONYMOUS)) { + audit_mmap_fd(args.fd, args.flags); + file = fget(args.fd); + if (!file) { + ret = -EBADF; + goto out_mm; + } + } + + ret = vm_mmap_remote(mm, file, args.addr, args.len, args.prot, + args.flags, args.pgoff, 0); + + if (file) + fput(file); +out_mm: + mmput(mm); + return ret; +} + +/** + * sys_pidfd_munmap() - remove a mapping from another process's address space. + * @pidfd: pidfd of the target task. + * @addr: start address of the range to unmap. + * @len: length in bytes. + * + * Gated by ptrace_may_access(), like sys_pidfd_mmap(). + * + * Returns 0 on success, or a negative errno. + */ +SYSCALL_DEFINE3(pidfd_munmap, int, pidfd, unsigned long, addr, + unsigned long, len) +{ + struct mm_struct *mm; + int ret; + + ret = pidfd_target_mm(pidfd, &mm); + if (ret) + return ret; + + ret = vm_munmap_remote(mm, addr, len); + mmput(mm); + return ret; +} diff --git a/scripts/syscall.tbl b/scripts/syscall.tbl index 7a42b32b6577..f4fa7826232b 100644 --- a/scripts/syscall.tbl +++ b/scripts/syscall.tbl @@ -412,3 +412,5 @@ 469 common file_setattr sys_file_setattr 470 common listns sys_listns 471 common rseq_slice_yield sys_rseq_slice_yield +472 common pidfd_mmap sys_pidfd_mmap +473 common pidfd_munmap sys_pidfd_munmap -- 2.43.0