All of lore.kernel.org
 help / color / mirror / Atom feed
From: Djalal Harouni <tixxdz@opendz.org>
To: "Eric W. Biederman" <ebiederm@xmission.com>,
	Kees Cook <keescook@chromium.org>,
	Al Viro <viro@zeniv.linux.org.uk>,
	Andrew Morton <akpm@linux-foundation.org>,
	Linus Torvalds <torvalds@linux-foundation.org>,
	Ingo Molnar <mingo@kernel.org>,
	"Serge E. Hallyn" <serge.hallyn@ubuntu.com>,
	Cyrill Gorcunov <gorcunov@openvz.org>,
	David Rientjes <rientjes@google.com>,
	LKML <linux-kernel@vger.kernel.org>,
	linux-fsdevel@vger.kernel.org,
	kernel-hardening@lists.openwall.com
Cc: tixxdz@gmail.com, Djalal Harouni <tixxdz@opendz.org>
Subject: [PATCH v2 2/9] procfs: add proc_allow_access() to check if file's opener may access task
Date: Tue,  1 Oct 2013 21:26:11 +0100	[thread overview]
Message-ID: <1380659178-28605-3-git-send-email-tixxdz@opendz.org> (raw)
In-Reply-To: <1380659178-28605-1-git-send-email-tixxdz@opendz.org>

Since /proc entries varies at runtime, permission checks need to happen
during each system call.

However even with that /proc file descriptors can be passed to a more
privileged process (e.g. a suid-exec) which will pass the classic
ptrace_may_access() permission check. The open() call will be issued in
general by an unprivileged process while the disclosure of sensitive
/proc information will happen using a more privileged process at
read(),write()...

Therfore we need a more sophisticated check to detect if the cred of the
process have changed, and if the cred of the original opener that are
stored in the file->f_cred have enough permission to access the task's
/proc entries during read(), write()...

Add the proc_allow_access() function that will receive the file->f_cred
as an argument, and tries to check if the opener had enough permission
to access the task's /proc entries.

This function should be used with the ptrace_may_access() check.

Cc: Kees Cook <keescook@chromium.org>
Suggested-by: Eric W. Biederman <ebiederm@xmission.com>
Signed-off-by: Djalal Harouni <tixxdz@opendz.org>
---
 fs/proc/base.c     | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 fs/proc/internal.h |  2 ++
 2 files changed, 58 insertions(+)

diff --git a/fs/proc/base.c b/fs/proc/base.c
index e834946..c29eeae 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -168,6 +168,62 @@ int proc_same_open_cred(const struct cred *fcred)
 		cap_issubset(cred->cap_permitted, fcred->cap_permitted));
 }
 
+/* Returns 0 on success, -errno on denial. */
+static int __proc_allow_access(const struct cred *cred,
+			       struct task_struct *task, unsigned int mode)
+{
+	int ret = 0;
+	const struct cred *tcred;
+	const struct cred *fcred = cred;
+
+	rcu_read_lock();
+	tcred = __task_cred(task);
+	if (uid_eq(fcred->uid, tcred->euid) &&
+	    uid_eq(fcred->uid, tcred->suid) &&
+	    uid_eq(fcred->uid, tcred->uid)  &&
+	    gid_eq(fcred->gid, tcred->egid) &&
+	    gid_eq(fcred->gid, tcred->sgid) &&
+	    gid_eq(fcred->gid, tcred->gid))
+		goto out;
+
+	if (mode & PTRACE_MODE_NOAUDIT)
+		ret = security_capable_noaudit(fcred, tcred->user_ns,
+					       CAP_SYS_PTRACE);
+	else
+		ret = security_capable(fcred, tcred->user_ns,
+				       CAP_SYS_PTRACE);
+
+out:
+	rcu_read_unlock();
+	return !ret ? ret : -EPERM;
+}
+
+/**
+ * proc_allow_access - Check if the file's opener had enough permissions
+ * to access the target process.
+ * @fcred:  The file's opener cred (file->f_cred)
+ * @task:  The target task we want to inspect
+ * @mode:  The ptrace mode
+ *
+ * Return a non-zero if the file's opener had enough permissions to
+ * access the task's /proc entries.
+ *
+ * Since this function will check the permissions of the opener
+ * against the target task, it can be used to protect /proc files
+ * from opening a /proc file descriptor and do a suid-exec.
+ *
+ * Callers must hold the task->signal->cred_guard_mutex
+ */
+int proc_allow_access(const struct cred *fcred,
+		      struct task_struct *task, unsigned int mode)
+{
+	int ret;
+	task_lock(task);
+	ret = __proc_allow_access(fcred, task, mode);
+	task_unlock(task);
+	return !ret;
+}
+
 /*
  * Count the number of hardlinks for the pid_entry table, excluding the .
  * and .. links.
diff --git a/fs/proc/internal.h b/fs/proc/internal.h
index e2459f4..c3f3c34 100644
--- a/fs/proc/internal.h
+++ b/fs/proc/internal.h
@@ -159,6 +159,8 @@ extern int proc_pid_statm(struct seq_file *, struct pid_namespace *,
 /*
  * base.c
  */
+extern int proc_allow_access(const struct cred *,
+			     struct task_struct *, unsigned int);
 extern int proc_same_open_cred(const struct cred *);
 extern const struct dentry_operations pid_dentry_operations;
 extern int pid_getattr(struct vfsmount *, struct dentry *, struct kstat *);
-- 
1.7.11.7


WARNING: multiple messages have this Message-ID (diff)
From: Djalal Harouni <tixxdz@opendz.org>
To: "Eric W. Biederman" <ebiederm@xmission.com>,
	Kees Cook <keescook@chromium.org>,
	Al Viro <viro@zeniv.linux.org.uk>,
	Andrew Morton <akpm@linux-foundation.org>,
	Linus Torvalds <torvalds@linux-foundation.org>,
	Ingo Molnar <mingo@kernel.org>,
	"Serge E. Hallyn" <serge.hallyn@ubuntu.com>,
	Cyrill Gorcunov <gorcunov@openvz.org>,
	David Rientjes <rientjes@google.com>,
	LKML <linux-kernel@vger.kernel.org>,
	linux-fsdevel@vger.kernel.org,
	kernel-hardening@lists.openwall.com
Cc: tixxdz@gmail.com, Djalal Harouni <tixxdz@opendz.org>
Subject: [kernel-hardening] [PATCH v2 2/9] procfs: add proc_allow_access() to check if file's opener may access task
Date: Tue,  1 Oct 2013 21:26:11 +0100	[thread overview]
Message-ID: <1380659178-28605-3-git-send-email-tixxdz@opendz.org> (raw)
In-Reply-To: <1380659178-28605-1-git-send-email-tixxdz@opendz.org>

Since /proc entries varies at runtime, permission checks need to happen
during each system call.

However even with that /proc file descriptors can be passed to a more
privileged process (e.g. a suid-exec) which will pass the classic
ptrace_may_access() permission check. The open() call will be issued in
general by an unprivileged process while the disclosure of sensitive
/proc information will happen using a more privileged process at
read(),write()...

Therfore we need a more sophisticated check to detect if the cred of the
process have changed, and if the cred of the original opener that are
stored in the file->f_cred have enough permission to access the task's
/proc entries during read(), write()...

Add the proc_allow_access() function that will receive the file->f_cred
as an argument, and tries to check if the opener had enough permission
to access the task's /proc entries.

This function should be used with the ptrace_may_access() check.

Cc: Kees Cook <keescook@chromium.org>
Suggested-by: Eric W. Biederman <ebiederm@xmission.com>
Signed-off-by: Djalal Harouni <tixxdz@opendz.org>
---
 fs/proc/base.c     | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 fs/proc/internal.h |  2 ++
 2 files changed, 58 insertions(+)

diff --git a/fs/proc/base.c b/fs/proc/base.c
index e834946..c29eeae 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -168,6 +168,62 @@ int proc_same_open_cred(const struct cred *fcred)
 		cap_issubset(cred->cap_permitted, fcred->cap_permitted));
 }
 
+/* Returns 0 on success, -errno on denial. */
+static int __proc_allow_access(const struct cred *cred,
+			       struct task_struct *task, unsigned int mode)
+{
+	int ret = 0;
+	const struct cred *tcred;
+	const struct cred *fcred = cred;
+
+	rcu_read_lock();
+	tcred = __task_cred(task);
+	if (uid_eq(fcred->uid, tcred->euid) &&
+	    uid_eq(fcred->uid, tcred->suid) &&
+	    uid_eq(fcred->uid, tcred->uid)  &&
+	    gid_eq(fcred->gid, tcred->egid) &&
+	    gid_eq(fcred->gid, tcred->sgid) &&
+	    gid_eq(fcred->gid, tcred->gid))
+		goto out;
+
+	if (mode & PTRACE_MODE_NOAUDIT)
+		ret = security_capable_noaudit(fcred, tcred->user_ns,
+					       CAP_SYS_PTRACE);
+	else
+		ret = security_capable(fcred, tcred->user_ns,
+				       CAP_SYS_PTRACE);
+
+out:
+	rcu_read_unlock();
+	return !ret ? ret : -EPERM;
+}
+
+/**
+ * proc_allow_access - Check if the file's opener had enough permissions
+ * to access the target process.
+ * @fcred:  The file's opener cred (file->f_cred)
+ * @task:  The target task we want to inspect
+ * @mode:  The ptrace mode
+ *
+ * Return a non-zero if the file's opener had enough permissions to
+ * access the task's /proc entries.
+ *
+ * Since this function will check the permissions of the opener
+ * against the target task, it can be used to protect /proc files
+ * from opening a /proc file descriptor and do a suid-exec.
+ *
+ * Callers must hold the task->signal->cred_guard_mutex
+ */
+int proc_allow_access(const struct cred *fcred,
+		      struct task_struct *task, unsigned int mode)
+{
+	int ret;
+	task_lock(task);
+	ret = __proc_allow_access(fcred, task, mode);
+	task_unlock(task);
+	return !ret;
+}
+
 /*
  * Count the number of hardlinks for the pid_entry table, excluding the .
  * and .. links.
diff --git a/fs/proc/internal.h b/fs/proc/internal.h
index e2459f4..c3f3c34 100644
--- a/fs/proc/internal.h
+++ b/fs/proc/internal.h
@@ -159,6 +159,8 @@ extern int proc_pid_statm(struct seq_file *, struct pid_namespace *,
 /*
  * base.c
  */
+extern int proc_allow_access(const struct cred *,
+			     struct task_struct *, unsigned int);
 extern int proc_same_open_cred(const struct cred *);
 extern const struct dentry_operations pid_dentry_operations;
 extern int pid_getattr(struct vfsmount *, struct dentry *, struct kstat *);
-- 
1.7.11.7

  parent reply	other threads:[~2013-10-01 20:29 UTC|newest]

Thread overview: 179+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-10-01 20:26 [PATCH v2 0/9] procfs: protect /proc/<pid>/* files with file->f_cred Djalal Harouni
2013-10-01 20:26 ` [kernel-hardening] " Djalal Harouni
2013-10-01 20:26 ` [PATCH v2 1/9] procfs: add proc_same_open_cred() to check if the cred have changed Djalal Harouni
2013-10-01 20:26   ` [kernel-hardening] " Djalal Harouni
2013-10-01 20:26 ` Djalal Harouni [this message]
2013-10-01 20:26   ` [kernel-hardening] [PATCH v2 2/9] procfs: add proc_allow_access() to check if file's opener may access task Djalal Harouni
2013-10-02  1:36   ` Andy Lutomirski
2013-10-02  1:36     ` [kernel-hardening] " Andy Lutomirski
2013-10-02 14:55     ` Djalal Harouni
2013-10-02 14:55       ` [kernel-hardening] " Djalal Harouni
2013-10-02 16:44       ` Andy Lutomirski
2013-10-02 16:44         ` [kernel-hardening] " Andy Lutomirski
2013-10-03 14:36         ` Djalal Harouni
2013-10-03 14:36           ` [kernel-hardening] " Djalal Harouni
2013-10-03 15:12           ` Andy Lutomirski
2013-10-03 15:12             ` [kernel-hardening] " Andy Lutomirski
2013-10-03 15:12             ` Andy Lutomirski
2013-10-03 19:29             ` Djalal Harouni
2013-10-03 19:29               ` [kernel-hardening] " Djalal Harouni
2013-10-03 19:29               ` Djalal Harouni
2013-10-03 19:37               ` Andy Lutomirski
2013-10-03 19:37                 ` [kernel-hardening] " Andy Lutomirski
2013-10-03 19:37                 ` Andy Lutomirski
2013-10-03 20:13                 ` Djalal Harouni
2013-10-03 20:13                   ` [kernel-hardening] " Djalal Harouni
2013-10-03 20:13                   ` Djalal Harouni
2013-10-03 21:09                   ` Andy Lutomirski
2013-10-03 21:09                     ` [kernel-hardening] " Andy Lutomirski
2013-10-03 21:09                     ` Andy Lutomirski
2013-10-04  8:59                     ` Djalal Harouni
2013-10-04  8:59                       ` [kernel-hardening] " Djalal Harouni
2013-10-04  8:59                       ` Djalal Harouni
2013-10-04 15:40                       ` Andy Lutomirski
2013-10-04 15:40                         ` [kernel-hardening] " Andy Lutomirski
2013-10-04 15:40                         ` Andy Lutomirski
2013-10-04 18:23                         ` Djalal Harouni
2013-10-04 18:23                           ` [kernel-hardening] " Djalal Harouni
2013-10-04 18:23                           ` Djalal Harouni
2013-10-04 18:34                           ` Andy Lutomirski
2013-10-04 18:34                             ` [kernel-hardening] " Andy Lutomirski
2013-10-04 18:34                             ` Andy Lutomirski
2013-10-04 19:11                             ` Djalal Harouni
2013-10-04 19:11                               ` [kernel-hardening] " Djalal Harouni
2013-10-04 19:11                               ` Djalal Harouni
2013-10-04 19:16                               ` Andy Lutomirski
2013-10-04 19:16                                 ` [kernel-hardening] " Andy Lutomirski
2013-10-04 19:16                                 ` Andy Lutomirski
2013-10-04 19:27                                 ` Djalal Harouni
2013-10-04 19:27                                   ` [kernel-hardening] " Djalal Harouni
2013-10-04 19:27                                   ` Djalal Harouni
2013-10-04 19:32                                   ` Andy Lutomirski
2013-10-04 19:32                                     ` [kernel-hardening] " Andy Lutomirski
2013-10-04 19:32                                     ` Andy Lutomirski
2013-10-04 19:41                                     ` Djalal Harouni
2013-10-04 19:41                                       ` [kernel-hardening] " Djalal Harouni
2013-10-04 19:41                                       ` Djalal Harouni
2013-10-04 22:17                                       ` Andy Lutomirski
2013-10-04 22:17                                         ` [kernel-hardening] " Andy Lutomirski
2013-10-04 22:17                                         ` Andy Lutomirski
2013-10-04 22:55                                         ` Eric W. Biederman
2013-10-04 22:55                                           ` [kernel-hardening] " Eric W. Biederman
2013-10-04 22:55                                           ` Eric W. Biederman
2013-10-04 22:59                                           ` Andy Lutomirski
2013-10-04 22:59                                             ` [kernel-hardening] " Andy Lutomirski
2013-10-04 22:59                                             ` Andy Lutomirski
2013-10-04 23:08                                             ` Andy Lutomirski
2013-10-04 23:08                                               ` [kernel-hardening] " Andy Lutomirski
2013-10-04 23:08                                               ` Andy Lutomirski
2013-10-05  0:35                                             ` Eric W. Biederman
2013-10-05  0:35                                               ` [kernel-hardening] " Eric W. Biederman
2013-10-05  0:35                                               ` Eric W. Biederman
2013-10-09 10:35                                               ` Djalal Harouni
2013-10-09 10:35                                                 ` [kernel-hardening] " Djalal Harouni
2013-10-09 10:35                                                 ` Djalal Harouni
2013-10-05 13:23                                         ` Djalal Harouni
2013-10-05 13:23                                           ` [kernel-hardening] " Djalal Harouni
2013-10-05 13:23                                           ` Djalal Harouni
2013-10-07 21:41                                           ` Andy Lutomirski
2013-10-07 21:41                                             ` [kernel-hardening] " Andy Lutomirski
2013-10-07 21:41                                             ` Andy Lutomirski
2013-10-09 10:54                                             ` Djalal Harouni
2013-10-09 10:54                                               ` [kernel-hardening] " Djalal Harouni
2013-10-09 10:54                                               ` Djalal Harouni
2013-10-09 11:15                                               ` Djalal Harouni
2013-10-09 11:15                                                 ` [kernel-hardening] " Djalal Harouni
2013-10-09 11:15                                                 ` Djalal Harouni
2013-10-09 17:27                                               ` Andy Lutomirski
2013-10-09 17:27                                                 ` [kernel-hardening] " Andy Lutomirski
2013-10-09 17:27                                                 ` Andy Lutomirski
2013-10-13 10:18                                                 ` Djalal Harouni
2013-10-13 10:18                                                   ` [kernel-hardening] " Djalal Harouni
2013-10-13 10:18                                                   ` Djalal Harouni
2013-10-01 20:26 ` [PATCH v2 3/9] procfs: Document the proposed solution to protect procfs entries Djalal Harouni
2013-10-01 20:26   ` [kernel-hardening] " Djalal Harouni
2013-10-01 20:26 ` [PATCH v2 4/9] procfs: make /proc/*/{stack,syscall} 0400 Djalal Harouni
2013-10-01 20:26   ` [kernel-hardening] " Djalal Harouni
2013-10-01 20:26 ` [PATCH v2 5/9] procfs: make /proc entries that use seq files able to access file->f_cred Djalal Harouni
2013-10-01 20:26   ` [kernel-hardening] " Djalal Harouni
2013-10-01 20:26 ` [PATCH v2 6/9] procfs: add permission checks on the file's opener of /proc/*/stat Djalal Harouni
2013-10-01 20:26   ` [kernel-hardening] " Djalal Harouni
2013-10-02  1:39   ` Andy Lutomirski
2013-10-02  1:39     ` [kernel-hardening] " Andy Lutomirski
2013-10-02 15:14     ` Djalal Harouni
2013-10-02 15:14       ` [kernel-hardening] " Djalal Harouni
2013-10-02 16:46       ` Andy Lutomirski
2013-10-02 16:46         ` [kernel-hardening] " Andy Lutomirski
2013-10-02 19:00         ` Djalal Harouni
2013-10-02 19:00           ` [kernel-hardening] " Djalal Harouni
2013-10-01 20:26 ` [PATCH v2 7/9] procfs: add permission checks on the file's opener of /proc/*/personality Djalal Harouni
2013-10-01 20:26   ` [kernel-hardening] " Djalal Harouni
2013-10-01 20:26 ` [PATCH v2 8/9] procfs: improve permission checks on /proc/*/stack Djalal Harouni
2013-10-01 20:26   ` [kernel-hardening] " Djalal Harouni
2013-10-01 20:26 ` [PATCH v2 9/9] procfs: improve permission checks on /proc/*/syscall Djalal Harouni
2013-10-01 20:26   ` [kernel-hardening] " Djalal Harouni
2013-10-02  1:40 ` [PATCH v2 0/9] procfs: protect /proc/<pid>/* files with file->f_cred Andy Lutomirski
2013-10-02  1:40   ` [kernel-hardening] " Andy Lutomirski
2013-10-02 14:37   ` Djalal Harouni
2013-10-02 14:37     ` [kernel-hardening] " Djalal Harouni
2013-10-02 16:51     ` Andy Lutomirski
2013-10-02 16:51       ` [kernel-hardening] " Andy Lutomirski
2013-10-02 17:48       ` Kees Cook
2013-10-02 17:48         ` [kernel-hardening] " Kees Cook
2013-10-02 17:48         ` Kees Cook
2013-10-02 18:00         ` Andy Lutomirski
2013-10-02 18:00           ` [kernel-hardening] " Andy Lutomirski
2013-10-02 18:00           ` Andy Lutomirski
2013-10-02 18:07           ` Kees Cook
2013-10-02 18:07             ` [kernel-hardening] " Kees Cook
2013-10-02 18:07             ` Kees Cook
2013-10-03 23:14             ` Julien Tinnes
2013-10-03 23:14               ` [kernel-hardening] " Julien Tinnes
2013-10-03 23:14               ` Julien Tinnes
2013-10-02 18:26           ` Djalal Harouni
2013-10-02 18:26             ` [kernel-hardening] " Djalal Harouni
2013-10-02 18:26             ` Djalal Harouni
2013-10-02 18:41             ` Djalal Harouni
2013-10-02 18:41               ` [kernel-hardening] " Djalal Harouni
2013-10-02 18:41               ` Djalal Harouni
2013-10-02 18:22         ` Djalal Harouni
2013-10-02 18:22           ` [kernel-hardening] " Djalal Harouni
2013-10-02 18:22           ` Djalal Harouni
2013-10-02 18:35           ` Kees Cook
2013-10-02 18:35             ` [kernel-hardening] " Kees Cook
2013-10-02 18:35             ` Kees Cook
2013-10-02 18:48             ` Djalal Harouni
2013-10-02 18:48               ` [kernel-hardening] " Djalal Harouni
2013-10-02 18:48               ` Djalal Harouni
2013-10-02 19:43               ` Kees Cook
2013-10-02 19:43                 ` [kernel-hardening] " Kees Cook
2013-10-02 19:43                 ` Kees Cook
2013-10-03  6:12               ` Ingo Molnar
2013-10-03  6:12                 ` [kernel-hardening] " Ingo Molnar
2013-10-03  6:12                 ` Ingo Molnar
2013-10-03 12:29                 ` Djalal Harouni
2013-10-03 12:29                   ` [kernel-hardening] " Djalal Harouni
2013-10-03 12:29                   ` Djalal Harouni
2013-10-03 15:15                   ` Andy Lutomirski
2013-10-03 15:15                     ` [kernel-hardening] " Andy Lutomirski
2013-10-03 15:15                     ` Andy Lutomirski
2013-10-03 15:40                     ` Djalal Harouni
2013-10-03 15:40                       ` [kernel-hardening] " Djalal Harouni
2013-10-03 15:40                       ` Djalal Harouni
2013-10-03 15:50                       ` Andy Lutomirski
2013-10-03 15:50                         ` [kernel-hardening] " Andy Lutomirski
2013-10-03 15:50                         ` Andy Lutomirski
2013-10-03 18:37                         ` Djalal Harouni
2013-10-03 18:37                           ` [kernel-hardening] " Djalal Harouni
2013-10-03 18:37                           ` Djalal Harouni
2013-10-04  9:05                 ` Djalal Harouni
2013-10-04  9:05                   ` [kernel-hardening] " Djalal Harouni
2013-10-04  9:05                   ` Djalal Harouni
2013-10-02 18:12       ` Djalal Harouni
2013-10-02 18:12         ` [kernel-hardening] " Djalal Harouni
2013-10-03  6:22         ` Ingo Molnar
2013-10-03  6:22           ` [kernel-hardening] " Ingo Molnar
2013-10-03 12:56           ` Djalal Harouni
2013-10-03 12:56             ` [kernel-hardening] " Djalal Harouni
2013-10-03 13:39             ` Ingo Molnar
2013-10-03 13:39               ` [kernel-hardening] " Ingo Molnar

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=1380659178-28605-3-git-send-email-tixxdz@opendz.org \
    --to=tixxdz@opendz.org \
    --cc=akpm@linux-foundation.org \
    --cc=ebiederm@xmission.com \
    --cc=gorcunov@openvz.org \
    --cc=keescook@chromium.org \
    --cc=kernel-hardening@lists.openwall.com \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mingo@kernel.org \
    --cc=rientjes@google.com \
    --cc=serge.hallyn@ubuntu.com \
    --cc=tixxdz@gmail.com \
    --cc=torvalds@linux-foundation.org \
    --cc=viro@zeniv.linux.org.uk \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.