From: Josef Bacik <josef@toxicpanda.com>
To: Christian Brauner <brauner@kernel.org>,
James Bottomley <James.Bottomley@HansenPartnership.com>,
Andrew Halaney <andrew@amutable.com>,
Jeremy Bingham <jbingham@gmail.com>,
Tahera Fahimi <taherafahimi@linux.microsoft.com>,
Serge Hallyn <sergeh@kernel.org>
Cc: linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org,
Josef Bacik <josef@toxicpanda.com>
Subject: [PATCH RFC v3 39/90] fork: add tasks that start out with nothing
Date: Thu, 05 Nov 2026 15:02:31 +0000 [thread overview]
Message-ID: <20261105-b4-cells-v3-39-bc9095937a84@toxicpanda.com> (raw)
In-Reply-To: <20261105-b4-cells-v3-0-bc9095937a84@toxicpanda.com>
To start a program in a container today, a process forks. The child then
gets rid of everything it inherited and should not keep, one call at a
time: file descriptors, the working directory, the controlling terminal,
credentials. Whatever it forgets leaks into the container. Until it is
done, it runs code of the parent while it is partly inside of the
container and partly outside.
Add kernel_clone_args.embryo, which makes copy_process() create a task
that has nothing to get rid of. The task works like a usermode helper: it
runs a kernel function and returns to user mode once kernel_execve() has
succeeded. From the start it has no mm, an empty file table, no blocked or
pending signals, and no controlling terminal. It never executes an
instruction of its creator.
The task is called an embryo until its exec has succeeded. struct embryo
describes what it will become, and task_struct.embryo is set for as long
as it is an embryo.
An embryo still inherits resource limits, scheduling attributes, seccomp
filters and LSM state. For the last two this is deliberate: what a
confined task spawns is confined in the same way.
Nothing sets kernel_clone_args.embryo yet. The following patches add the
interface.
Signed-off-by: Josef Bacik <josef@toxicpanda.com>
---
include/linux/cell.h | 24 +++++++++
include/linux/sched.h | 6 +++
include/linux/sched/task.h | 3 ++
kernel/embryo.c | 127 +++++++++++++++++++++++++++++++++++++++++++++
kernel/fork.c | 39 +++++++++++---
5 files changed, 192 insertions(+), 7 deletions(-)
diff --git a/include/linux/cell.h b/include/linux/cell.h
index 564c3e86f3bd..f9975b0fb65c 100644
--- a/include/linux/cell.h
+++ b/include/linux/cell.h
@@ -193,4 +193,28 @@ static inline void cell_root(struct cell *cell, struct path *root) { }
static inline struct cgroup *cell_budget(struct cell *cell) { return NULL; }
#endif
+/* Embryo tasks. */
+#ifdef CONFIG_CELLS
+
+/**
+ * task_is_embryo - is a task still on its way to its first exec?
+ * @task: a task
+ *
+ * Return: true from the time PIDFD_CMD_START made @task until its exec has
+ * succeeded or it is on its way out.
+ */
+static inline bool task_is_embryo(const struct task_struct *task)
+{
+ return READ_ONCE(task->embryo);
+}
+
+void embryo_fork_finish(struct kernel_clone_args *args, struct task_struct *p);
+
+#else
+
+static inline bool task_is_embryo(const struct task_struct *task) { return false; }
+static inline void embryo_fork_finish(struct kernel_clone_args *a, struct task_struct *p) { }
+
+#endif
+
#endif /* _LINUX_CELL_H */
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 1c93da75226e..3dbe7c13da3b 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -85,6 +85,7 @@ struct sighand_struct;
struct signal_struct;
struct task_delay_info;
struct task_exec_state;
+struct embryo;
struct task_group;
struct task_struct;
struct timespec64;
@@ -983,6 +984,11 @@ struct task_struct {
struct task_exec_state __rcu *exec_state;
+#ifdef CONFIG_CELLS
+ /* Set from PIDFD_CMD_START until the first exec has succeeded. */
+ struct embryo *embryo;
+#endif
+
int exit_state;
int exit_code;
int exit_signal;
diff --git a/include/linux/sched/task.h b/include/linux/sched/task.h
index eaf939ac4bef..97e3675101bd 100644
--- a/include/linux/sched/task.h
+++ b/include/linux/sched/task.h
@@ -21,6 +21,8 @@ struct css_set;
#define CLONE_LEGACY_FLAGS 0xffffffffULL
struct cell;
+struct embryo;
+
struct kernel_clone_args {
u64 flags;
int __user *pidfd;
@@ -48,6 +50,7 @@ struct kernel_clone_args {
unsigned int kill_seq;
struct pid *pid;
struct cell *cell;
+ struct embryo *embryo;
};
/*
diff --git a/kernel/embryo.c b/kernel/embryo.c
new file mode 100644
index 000000000000..163115c56ab4
--- /dev/null
+++ b/kernel/embryo.c
@@ -0,0 +1,127 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Empty pidfds: fsopen() for processes.
+ *
+ * pidfd_open() with PIDFD_EMPTY returns a pidfd that no task is attached to yet.
+ * It is a pidfd like any other, on a struct pid that has no numbers, so whatever
+ * it is passed to finds no task. Whoever has it says with pidfd_configure() what
+ * the task is to be like and starts it. Only then is there a task, which never
+ * runs a single instruction of its creator's and execs. The creator does not
+ * fork.
+ *
+ * The task is an embryo until its exec has succeeded. It has no mm and an empty
+ * file table. What it is to reach, it is given. It does inherit attributes of
+ * whoever started it, as any new task does, see
+ * Documentation/userspace-api/cells.rst.
+ *
+ * It takes the shape of a usermode helper: a task with a kernel function to
+ * run, that returns to user mode once kernel_execve() has succeeded.
+ */
+#include <linux/binfmts.h>
+#include <linux/cell.h>
+#include <linux/completion.h>
+#include <linux/cred.h>
+#include <linux/fdtable.h>
+#include <linux/file.h>
+#include <linux/fs.h>
+#include <linux/io_uring.h>
+#include <linux/personality.h>
+#include <linux/nsproxy.h>
+#include <linux/pid.h>
+#include <linux/pidfs.h>
+#include <linux/proc_fs.h>
+#include <linux/sched/signal.h>
+#include <linux/sched/task.h>
+#include <linux/sched/user.h>
+#include <linux/security.h>
+#include <linux/slab.h>
+#include <linux/syscalls.h>
+#include <linux/user_namespace.h>
+#include <net/af_unix.h>
+#include <uapi/linux/pidfd.h>
+
+struct embryo_strings {
+ char *block; /* NUL terminated strings, back to back */
+ const char **vec; /* NULL terminated, points into @block */
+};
+
+struct embryo {
+ struct rcu_head rcu;
+ refcount_t ref;
+ struct mutex lock; /* everything down to @result */
+ bool started;
+ bool settled; /* there is a task, or never will be */
+
+ char *exec;
+ struct embryo_strings argv;
+ struct embryo_strings envp;
+
+ struct pid *pid; /* the reference alloc_pid_struct() returned */
+ struct cell *cell; /* where the task is going to be */
+
+ int result;
+ struct completion done; /* embryo -> starter */
+};
+
+static void embryo_strings_free(struct embryo_strings *s)
+{
+ kvfree(s->block);
+ kvfree(s->vec);
+ s->block = NULL;
+ s->vec = NULL;
+}
+
+/*
+ * What was configured has been used, or never will be. The pidfd may be around
+ * for long, and must not keep the other end of a pipe from seeing the last
+ * writer go.
+ */
+static void embryo_drop_config(struct embryo *e)
+{
+ kfree(e->exec);
+ e->exec = NULL;
+ embryo_strings_free(&e->argv);
+ embryo_strings_free(&e->envp);
+}
+
+static void embryo_put(struct embryo *e)
+{
+ if (!e || !refcount_dec_and_test(&e->ref))
+ return;
+
+ embryo_drop_config(e);
+ cell_put(e->cell);
+ kfree_rcu(e, rcu);
+}
+
+/**
+ * embryo_fork_finish - done creating an embryo, one way or the other
+ * @args: the arguments of the clone, with @args->embryo set
+ * @p: what copy_process() returned, a task or an ERR_PTR()
+ *
+ * Unlocks the cell, which embryo_start() had locked.
+ *
+ * Context: kernel_clone(), before the new task is woken.
+ */
+void embryo_fork_finish(struct kernel_clone_args *args, struct task_struct *p)
+{
+ struct embryo *e = args->embryo;
+
+ if (!IS_ERR(p))
+ cell_task_spawned(args->cell);
+ cell_fork_finish(args->cell);
+
+ /* Nothing has happened yet, see embryo_start(). */
+ if (p == ERR_PTR(-ERESTARTNOINTR)) {
+ embryo_put(e);
+ return;
+ }
+
+ /* From here on the pidfd polls like any other. */
+ WRITE_ONCE(e->settled, true);
+ if (IS_ERR(p)) {
+ wake_up_all(&e->pid->wait_pidfd);
+ /* The reference that was to be the task's. */
+ embryo_put(e);
+ }
+}
diff --git a/kernel/fork.c b/kernel/fork.c
index 4db060281448..119b59f30f4d 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -1565,7 +1565,7 @@ static struct mm_struct *dup_mm(struct task_struct *tsk,
return NULL;
}
-static int copy_mm(u64 clone_flags, struct task_struct *tsk)
+static int copy_mm(u64 clone_flags, struct task_struct *tsk, bool embryo)
{
struct mm_struct *mm, *oldmm;
@@ -1583,9 +1583,12 @@ static int copy_mm(u64 clone_flags, struct task_struct *tsk)
* Are we cloning a kernel thread?
*
* We need to steal a active VM for that..
+ *
+ * An embryo is in the same position until it execs. It must never
+ * get to see the mm of whoever created it.
*/
oldmm = current->mm;
- if (!oldmm)
+ if (!oldmm || embryo)
return 0;
if (clone_flags & CLONE_VM) {
@@ -1693,10 +1696,19 @@ static int copy_fs(u64 clone_flags, struct task_struct *tsk,
}
static int copy_files(u64 clone_flags, struct task_struct *tsk,
- int no_files)
+ int no_files, bool embryo)
{
struct files_struct *oldf, *newf;
+ /* An empty table. What pidfd_configure() was given goes in there. */
+ if (embryo) {
+ newf = dup_fd(&init_files, NULL);
+ if (IS_ERR(newf))
+ return PTR_ERR(newf);
+ tsk->files = newf;
+ return 0;
+ }
+
/*
* A background process may not have any files ...
*/
@@ -2187,6 +2199,14 @@ __latent_entropy struct task_struct *copy_process(
}
if (args->io_thread)
p->flags |= PF_IO_WORKER;
+#ifdef CONFIG_CELLS
+ p->embryo = args->embryo;
+ if (args->embryo) {
+ sigemptyset(&p->blocked);
+ sigemptyset(&p->saved_sigmask);
+ clear_tsk_restore_sigmask(p);
+ }
+#endif
if (args->name)
strscpy_pad(p->comm, args->name, sizeof(p->comm));
@@ -2330,7 +2350,7 @@ __latent_entropy struct task_struct *copy_process(
retval = copy_semundo(clone_flags, p);
if (retval)
goto bad_fork_cleanup_security;
- retval = copy_files(clone_flags, p, args->no_files);
+ retval = copy_files(clone_flags, p, args->no_files, args->embryo);
if (retval)
goto bad_fork_cleanup_semundo;
retval = copy_fs(clone_flags, p,
@@ -2344,7 +2364,7 @@ __latent_entropy struct task_struct *copy_process(
retval = copy_signal(clone_flags, p);
if (retval)
goto bad_fork_cleanup_sighand;
- retval = copy_mm(clone_flags, p);
+ retval = copy_mm(clone_flags, p, args->embryo);
if (retval)
goto bad_fork_cleanup_signal;
retval = copy_namespaces(clone_flags, p, args->cell);
@@ -2568,8 +2588,10 @@ __latent_entropy struct task_struct *copy_process(
WRITE_ONCE(ns->child_reaper, p);
p->signal->flags |= SIGNAL_UNKILLABLE;
}
- p->signal->shared_pending.signal = delayed.signal;
- p->signal->tty = tty_kref_get(current->signal->tty);
+ if (!args->embryo)
+ p->signal->shared_pending.signal = delayed.signal;
+ if (!args->embryo)
+ p->signal->tty = tty_kref_get(current->signal->tty);
/*
* Inherit has_child_subreaper flag under the same
* tasklist_lock with adding child to the process tree
@@ -2817,6 +2839,9 @@ pid_t kernel_clone(struct kernel_clone_args *args)
p = copy_process(NULL, trace, NUMA_NO_NODE, args);
add_latent_entropy();
+ if (args->embryo)
+ embryo_fork_finish(args, p);
+
if (IS_ERR(p))
return PTR_ERR(p);
--
2.55.0
next prev parent reply other threads:[~2026-11-05 15:14 UTC|newest]
Thread overview: 93+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-05 14:56 [PATCH RFC v3 00/90] cells: a container as one kernel object Josef Bacik
2026-11-05 14:56 ` [PATCH RFC v3 01/90] Documentation: add a design document for cells Josef Bacik
2026-11-05 17:06 ` Serge E. Hallyn
2026-11-05 18:23 ` Josef Bacik
2026-11-05 14:56 ` [PATCH RFC v3 02/90] Documentation: add examples " Josef Bacik
2026-11-05 14:56 ` [PATCH RFC v3 03/90] cells: reserve a window of ids Josef Bacik
2026-11-05 14:56 ` [PATCH RFC v3 04/90] user_namespace: let a cell own a user namespace Josef Bacik
2026-11-05 14:56 ` [PATCH RFC v3 05/90] user_namespace: refuse setns() into a cell Josef Bacik
2026-11-05 14:56 ` [PATCH RFC v3 06/90] capability: give the owner no say over " Josef Bacik
2026-11-05 14:56 ` [PATCH RFC v3 07/90] ucount: count the id blocks a user holds Josef Bacik
2026-11-05 14:56 ` [PATCH RFC v3 08/90] user_namespace: let the kernel map the ids of a cell Josef Bacik
2026-11-05 14:57 ` [PATCH RFC v3 09/90] user_namespace: keep legacy maps out of the window Josef Bacik
2026-11-05 14:57 ` [PATCH RFC v3 10/90] user: add uid_range_in_use() Josef Bacik
2026-11-05 14:57 ` [PATCH RFC v3 11/90] keys: add key_user_range_in_use() Josef Bacik
2026-11-05 14:57 ` [PATCH RFC v3 12/90] fs: add kuid_has_fsmapping() and kgid_has_fsmapping() Josef Bacik
2026-11-05 14:57 ` [PATCH RFC v3 13/90] fs: never store an id that was lent to a cell Josef Bacik
2026-11-05 14:57 ` [PATCH RFC v3 14/90] fs: take no id of a cell for a mount option Josef Bacik
2026-11-05 14:57 ` [PATCH RFC v3 15/90] fs: let an idmapping pin the ids of a cell Josef Bacik
2026-11-05 14:57 ` [PATCH RFC v3 16/90] cgroup: let a cgroup become the budget " Josef Bacik
2026-11-05 14:57 ` [PATCH RFC v3 17/90] cgroup: add cgroup_cell_chown() Josef Bacik
2026-11-05 14:57 ` [PATCH RFC v3 18/90] cgroup: give the budget of a cell back Josef Bacik
2026-11-05 14:57 ` [PATCH RFC v3 19/90] cgroup: add cgroup_cell_kill() Josef Bacik
2026-11-05 14:57 ` [PATCH RFC v3 20/90] cgroup: root a cgroup namespace at a given cgroup Josef Bacik
2026-11-05 14:57 ` [PATCH RFC v3 21/90] fs: seal a mount namespace for a cell Josef Bacik
2026-11-05 14:57 ` [PATCH RFC v3 22/90] nsfs: make open_namespace() available outside of fs/ Josef Bacik
2026-11-05 14:57 ` [PATCH RFC v3 23/90] nsproxy: build the nsproxy the tasks of a cell share Josef Bacik
2026-11-05 15:02 ` [PATCH RFC v3 24/90] cells: add the cell object and cell_create() Josef Bacik
2026-11-05 15:02 ` [PATCH RFC v3 25/90] cells: add cell_kill() Josef Bacik
2026-11-05 15:02 ` [PATCH RFC v3 26/90] cells: add cell_configure() Josef Bacik
2026-11-05 15:02 ` [PATCH RFC v3 27/90] cells: add the "budget" slot Josef Bacik
2026-11-05 15:02 ` [PATCH RFC v3 28/90] cells: add the "root" slot Josef Bacik
2026-11-05 15:02 ` [PATCH RFC v3 29/90] cells: add the "ids" slot, for a single id Josef Bacik
2026-11-05 15:02 ` [PATCH RFC v3 30/90] cells: lend a cell a block of ids Josef Bacik
2026-11-05 15:02 ` [PATCH RFC v3 31/90] cells: reserve the "spawn" slot Josef Bacik
2026-11-05 15:02 ` [PATCH RFC v3 32/90] cells: add CELL_CMD_SEAL Josef Bacik
2026-11-05 15:02 ` [PATCH RFC v3 33/90] cells: add cell_open() Josef Bacik
2026-11-05 15:02 ` [PATCH RFC v3 34/90] pid: allocate a struct pid ahead of its numbers Josef Bacik
2026-11-05 15:02 ` [PATCH RFC v3 35/90] fork: let copy_process() place a task in a cell Josef Bacik
2026-11-05 15:02 ` [PATCH RFC v3 36/90] cgroup: fork a task of a cell into the budget Josef Bacik
2026-11-05 15:02 ` [PATCH RFC v3 37/90] x86: give a task without an mm no user state Josef Bacik
2026-11-05 15:02 ` [PATCH RFC v3 38/90] uprobes: cope with a new task that has no mm Josef Bacik
2026-11-05 15:02 ` Josef Bacik [this message]
2026-11-05 15:02 ` [PATCH RFC v3 40/90] pidfd: add PIDFD_EMPTY Josef Bacik
2026-11-05 15:02 ` [PATCH RFC v3 41/90] pidfd: add pidfd_configure() Josef Bacik
2026-11-05 15:02 ` [PATCH RFC v3 42/90] pidfd: let pidfd_configure() place files Josef Bacik
2026-11-05 15:02 ` [PATCH RFC v3 43/90] pidfd: let pidfd_configure() set credentials Josef Bacik
2026-11-05 15:02 ` [PATCH RFC v3 44/90] pidfd: let pidfd_configure() name a cgroup to start in Josef Bacik
2026-11-05 15:02 ` [PATCH RFC v3 45/90] ptrace: keep everybody off an embryo Josef Bacik
2026-11-05 15:02 ` [PATCH RFC v3 46/90] cells: end a cell when its init exits Josef Bacik
2026-11-05 15:02 ` [PATCH RFC v3 47/90] cells: refuse a task of a cell a change of namespaces Josef Bacik
2026-11-05 15:02 ` [PATCH RFC v3 48/90] fs: refuse a task of a cell a new mount namespace Josef Bacik
2026-11-05 15:02 ` [PATCH RFC v3 49/90] nsproxy: refuse to enter a namespace of a cell Josef Bacik
2026-11-05 15:02 ` [PATCH RFC v3 50/90] cgroup: keep a task of a cell within the budget Josef Bacik
2026-11-05 15:02 ` [PATCH RFC v3 51/90] cgroup: let nothing but a spawn into a budget Josef Bacik
2026-11-05 15:02 ` [PATCH RFC v3 52/90] kernfs: let a filesystem refuse a change to a node Josef Bacik
2026-11-05 15:02 ` [PATCH RFC v3 53/90] cgroup: let a cell change nothing outside its budget Josef Bacik
2026-11-05 15:02 ` [PATCH RFC v3 54/90] cgroup: leave the limits of a budget to who is above Josef Bacik
2026-11-05 15:02 ` [PATCH RFC v3 55/90] fs: let a filesystem hold ids that go with the cell Josef Bacik
2026-11-05 15:02 ` [PATCH RFC v3 56/90] cgroup: let a cell make cgroups below its budget Josef Bacik
2026-11-05 15:02 ` [PATCH RFC v3 57/90] resctrl: let a cell change nothing Josef Bacik
2026-11-05 15:02 ` [PATCH RFC v3 58/90] cred: let no id count across cells Josef Bacik
2026-11-05 15:02 ` [PATCH RFC v3 59/90] ptrace: refuse PTRACE_TRACEME " Josef Bacik
2026-11-05 15:02 ` [PATCH RFC v3 60/90] keys: ignore an equal uid or gid " Josef Bacik
2026-11-05 15:02 ` [PATCH RFC v3 61/90] fs: accept a cellfd for MOUNT_ATTR_IDMAP Josef Bacik
2026-11-05 15:02 ` [PATCH RFC v3 62/90] fs: let a cell set no set-id bits Josef Bacik
2026-11-05 15:02 ` [PATCH RFC v3 63/90] fs: drop privileges from what a cell may write to Josef Bacik
2026-11-05 15:02 ` [PATCH RFC v3 64/90] cells: add the "caps" slot Josef Bacik
2026-11-05 15:02 ` [PATCH RFC v3 65/90] capabilities: take nothing from a file in a cell Josef Bacik
2026-11-05 15:02 ` [PATCH RFC v3 66/90] capabilities: let a cell shrink its bounding sets Josef Bacik
2026-11-05 15:02 ` [PATCH RFC v3 67/90] af_unix: deliver ancillary data only within a cell Josef Bacik
2026-11-05 15:03 ` [PATCH RFC v3 68/90] af_unix: tell a sender that control data will not cross Josef Bacik
2026-11-05 15:03 ` [PATCH RFC v3 69/90] net: do not identify a peer in another cell Josef Bacik
2026-11-05 15:03 ` [PATCH RFC v3 70/90] seccomp: let a listener put no file into a cell Josef Bacik
2026-11-05 15:03 ` [PATCH RFC v3 71/90] umh: run no program for a task of " Josef Bacik
2026-11-05 15:03 ` [PATCH RFC v3 72/90] coredump: let no core dump leave " Josef Bacik
2026-11-05 15:03 ` [PATCH RFC v3 73/90] cells: add the "net" slot Josef Bacik
2026-11-05 15:03 ` [PATCH RFC v3 74/90] net: give a cell without a network no sockets Josef Bacik
2026-11-05 15:03 ` [PATCH RFC v3 75/90] net: add net_may() Josef Bacik
2026-11-05 15:03 ` [PATCH RFC v3 76/90] rtnetlink: use net_may() for requests that change state Josef Bacik
2026-11-05 15:03 ` [PATCH RFC v3 77/90] net: use net_may() in the configuration ioctls Josef Bacik
2026-11-05 15:03 ` [PATCH RFC v3 78/90] netfilter: use net_may() for configuration Josef Bacik
2026-11-05 15:03 ` [PATCH RFC v3 79/90] tun: use net_may() to create and attach to devices Josef Bacik
2026-11-05 15:03 ` [PATCH RFC v3 80/90] net: use net_may() for the net sysctls Josef Bacik
2026-11-05 15:03 ` [PATCH RFC v3 81/90] net: use net_may() for privileged socket options Josef Bacik
2026-11-05 15:03 ` [PATCH RFC v3 82/90] net: use net_may() for raw and packet sockets Josef Bacik
2026-11-05 15:03 ` [PATCH RFC v3 83/90] cells: add the "net-rights" slot Josef Bacik
2026-11-05 15:03 ` [PATCH RFC v3 84/90] net: honour the rights of a cell in net_may() Josef Bacik
2026-11-05 15:03 ` [PATCH RFC v3 85/90] tun: ignore an equal uid or gid across cells Josef Bacik
2026-11-05 15:03 ` [PATCH RFC v3 86/90] cells: add cell_info() Josef Bacik
2026-11-05 15:03 ` [PATCH RFC v3 87/90] cells: add CONFIG_CELLS Josef Bacik
2026-11-05 15:03 ` [PATCH RFC v3 88/90] arch: wire up the cell system calls Josef Bacik
2026-11-05 15:03 ` [PATCH RFC v3 89/90] MAINTAINERS: add an entry for cells Josef Bacik
2026-11-05 15:03 ` [PATCH RFC v3 90/90] selftests: add tests " Josef Bacik
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261105-b4-cells-v3-39-bc9095937a84@toxicpanda.com \
--to=josef@toxicpanda.com \
--cc=James.Bottomley@HansenPartnership.com \
--cc=andrew@amutable.com \
--cc=brauner@kernel.org \
--cc=jbingham@gmail.com \
--cc=linux-fsdevel@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=sergeh@kernel.org \
--cc=taherafahimi@linux.microsoft.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®