git: 6b49d1194899 - main - kern: allow kern_shm_open2 of an anonymous preconstructed shmfd
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Sat, 26 Jul 2025 21:31:49 UTC
The branch main has been updated by kevans:
URL: https://cgit.FreeBSD.org/src/commit/?id=6b49d119489944abbef87b5892c21f65e7a7055e
commit 6b49d119489944abbef87b5892c21f65e7a7055e
Author: Kyle Evans <kevans@FreeBSD.org>
AuthorDate: 2025-07-14 23:28:35 +0000
Commit: Kyle Evans <kevans@FreeBSD.org>
CommitDate: 2025-07-26 21:31:40 +0000
kern: allow kern_shm_open2 of an anonymous preconstructed shmfd
The motivation here is for future changes to the coredump code to be
able to build up a coredump into a shmfd instead of a vnode, which then
gets tapped out to userland via a character device. This also opens up
the possibility that it's useful for the kernel to be able to construct
a shmfd and pass it out to a process that shouldn't need to write to it.
Reviewed by: emaste, kib, markj
Differential Revision: https://reviews.freebsd.org/D51336
---
sys/compat/linux/linux_file.c | 2 +-
sys/kern/uipc_shm.c | 50 +++++++++++++++++++++++++++++--------------
sys/sys/syscallsubr.h | 3 ++-
3 files changed, 37 insertions(+), 18 deletions(-)
diff --git a/sys/compat/linux/linux_file.c b/sys/compat/linux/linux_file.c
index 86834a7ecea8..a4be5313aa96 100644
--- a/sys/compat/linux/linux_file.c
+++ b/sys/compat/linux/linux_file.c
@@ -1792,7 +1792,7 @@ linux_memfd_create(struct thread *td, struct linux_memfd_create_args *args)
if ((flags & MFD_ALLOW_SEALING) != 0)
shmflags |= SHM_ALLOW_SEALING;
return (kern_shm_open2(td, SHM_ANON, oflags, 0, shmflags, NULL,
- memfd_name));
+ memfd_name, NULL));
}
int
diff --git a/sys/kern/uipc_shm.c b/sys/kern/uipc_shm.c
index 6f83b875a6b6..85fe48ddd466 100644
--- a/sys/kern/uipc_shm.c
+++ b/sys/kern/uipc_shm.c
@@ -1134,10 +1134,10 @@ shm_doremove(struct shm_mapping *map)
int
kern_shm_open2(struct thread *td, const char *userpath, int flags, mode_t mode,
- int shmflags, struct filecaps *fcaps, const char *name __unused)
+ int shmflags, struct filecaps *fcaps, const char *name __unused,
+ struct shmfd *shmfd)
{
struct pwddesc *pdp;
- struct shmfd *shmfd;
struct file *fp;
char *path;
void *rl_cookie;
@@ -1214,23 +1214,41 @@ kern_shm_open2(struct thread *td, const char *userpath, int flags, mode_t mode,
if (error != 0)
goto outnofp;
- /* A SHM_ANON path pointer creates an anonymous object. */
+ /*
+ * A SHM_ANON path pointer creates an anonymous object. We allow other
+ * parts of the kernel to pre-populate a shmfd and then materialize an
+ * fd for it here as a means to pass data back up to userland. This
+ * doesn't really make sense for named shm objects, but it makes plenty
+ * of sense for anonymous objects.
+ */
if (userpath == SHM_ANON) {
- /* A read-only anonymous object is pointless. */
- if ((flags & O_ACCMODE) == O_RDONLY) {
- error = EINVAL;
- goto out;
- }
- shmfd = shm_alloc(td->td_ucred, cmode, largepage);
- if (shmfd == NULL) {
- error = ENOMEM;
- goto out;
+ if (shmfd != NULL) {
+ shm_hold(shmfd);
+ } else {
+ /*
+ * A read-only anonymous object is pointless, unless it
+ * was pre-populated by the kernel with the expectation
+ * that a shmfd would later be created for userland to
+ * access it through.
+ */
+ if ((flags & O_ACCMODE) == O_RDONLY) {
+ error = EINVAL;
+ goto out;
+ }
+ shmfd = shm_alloc(td->td_ucred, cmode, largepage);
+ if (shmfd == NULL) {
+ error = ENOMEM;
+ goto out;
+ }
+
+ shmfd->shm_seals = initial_seals;
+ shmfd->shm_flags = shmflags;
}
- shmfd->shm_seals = initial_seals;
- shmfd->shm_flags = shmflags;
} else {
fnv = fnv_32_str(path, FNV1_32_INIT);
sx_xlock(&shm_dict_lock);
+
+ MPASS(shmfd == NULL);
shmfd = shm_lookup(path, fnv);
if (shmfd == NULL) {
/* Object does not yet exist, create it if requested. */
@@ -2173,7 +2191,7 @@ kern_shm_open(struct thread *td, const char *path, int flags, mode_t mode,
struct filecaps *caps)
{
- return (kern_shm_open2(td, path, flags, mode, 0, caps, NULL));
+ return (kern_shm_open2(td, path, flags, mode, 0, caps, NULL, NULL));
}
/*
@@ -2191,7 +2209,7 @@ sys_shm_open2(struct thread *td, struct shm_open2_args *uap)
{
return (kern_shm_open2(td, uap->path, uap->flags, uap->mode,
- uap->shmflags, NULL, uap->name));
+ uap->shmflags, NULL, uap->name, NULL));
}
int
diff --git a/sys/sys/syscallsubr.h b/sys/sys/syscallsubr.h
index fd183ffbc7a4..8237165b84ce 100644
--- a/sys/sys/syscallsubr.h
+++ b/sys/sys/syscallsubr.h
@@ -60,6 +60,7 @@ struct rusage;
struct sched_param;
struct sembuf;
union semun;
+struct shmfd;
struct sockaddr;
struct spacectl_range;
struct stat;
@@ -337,7 +338,7 @@ int kern_shm_open(struct thread *td, const char *userpath, int flags,
mode_t mode, struct filecaps *fcaps);
int kern_shm_open2(struct thread *td, const char *path, int flags,
mode_t mode, int shmflags, struct filecaps *fcaps,
- const char *name);
+ const char *name, struct shmfd *shmfd);
int kern_shmat(struct thread *td, int shmid, const void *shmaddr,
int shmflg);
int kern_shmctl(struct thread *td, int shmid, int cmd, void *buf,