All of lore.kernel.org
 help / color / mirror / Atom feed
From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
To: linux-kernel@vger.kernel.org
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
	stable@vger.kernel.org,
	"Steven J. Magnani" <steve@digidescorp.com>,
	Jan Kara <jack@suse.cz>
Subject: [PATCH 4.19 57/91] udf: Fix incorrect final NOT_ALLOCATED (hole) extent length
Date: Fri, 12 Jul 2019 14:19:00 +0200	[thread overview]
Message-ID: <20190712121624.789594115@linuxfoundation.org> (raw)
In-Reply-To: <20190712121621.422224300@linuxfoundation.org>

From: Steven J. Magnani <steve.magnani@digidescorp.com>

commit fa33cdbf3eceb0206a4f844fe91aeebcf6ff2b7a upstream.

In some cases, using the 'truncate' command to extend a UDF file results
in a mismatch between the length of the file's extents (specifically, due
to incorrect length of the final NOT_ALLOCATED extent) and the information
(file) length. The discrepancy can prevent other operating systems
(i.e., Windows 10) from opening the file.

Two particular errors have been observed when extending a file:

1. The final extent is larger than it should be, having been rounded up
   to a multiple of the block size.

B. The final extent is not shorter than it should be, due to not having
   been updated when the file's information length was increased.

[JK: simplified udf_do_extend_final_block(), fixed up some types]

Fixes: 2c948b3f86e5 ("udf: Avoid IO in udf_clear_inode")
CC: stable@vger.kernel.org
Signed-off-by: Steven J. Magnani <steve@digidescorp.com>
Link: https://lore.kernel.org/r/1561948775-5878-1-git-send-email-steve@digidescorp.com
Signed-off-by: Jan Kara <jack@suse.cz>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

---
 fs/udf/inode.c |   93 ++++++++++++++++++++++++++++++++++++---------------------
 1 file changed, 60 insertions(+), 33 deletions(-)

--- a/fs/udf/inode.c
+++ b/fs/udf/inode.c
@@ -470,13 +470,15 @@ static struct buffer_head *udf_getblk(st
 	return NULL;
 }
 
-/* Extend the file by 'blocks' blocks, return the number of extents added */
+/* Extend the file with new blocks totaling 'new_block_bytes',
+ * return the number of extents added
+ */
 static int udf_do_extend_file(struct inode *inode,
 			      struct extent_position *last_pos,
 			      struct kernel_long_ad *last_ext,
-			      sector_t blocks)
+			      loff_t new_block_bytes)
 {
-	sector_t add;
+	uint32_t add;
 	int count = 0, fake = !(last_ext->extLength & UDF_EXTENT_LENGTH_MASK);
 	struct super_block *sb = inode->i_sb;
 	struct kernel_lb_addr prealloc_loc = {};
@@ -486,7 +488,7 @@ static int udf_do_extend_file(struct ino
 
 	/* The previous extent is fake and we should not extend by anything
 	 * - there's nothing to do... */
-	if (!blocks && fake)
+	if (!new_block_bytes && fake)
 		return 0;
 
 	iinfo = UDF_I(inode);
@@ -517,13 +519,12 @@ static int udf_do_extend_file(struct ino
 	/* Can we merge with the previous extent? */
 	if ((last_ext->extLength & UDF_EXTENT_FLAG_MASK) ==
 					EXT_NOT_RECORDED_NOT_ALLOCATED) {
-		add = ((1 << 30) - sb->s_blocksize -
-			(last_ext->extLength & UDF_EXTENT_LENGTH_MASK)) >>
-			sb->s_blocksize_bits;
-		if (add > blocks)
-			add = blocks;
-		blocks -= add;
-		last_ext->extLength += add << sb->s_blocksize_bits;
+		add = (1 << 30) - sb->s_blocksize -
+			(last_ext->extLength & UDF_EXTENT_LENGTH_MASK);
+		if (add > new_block_bytes)
+			add = new_block_bytes;
+		new_block_bytes -= add;
+		last_ext->extLength += add;
 	}
 
 	if (fake) {
@@ -544,28 +545,27 @@ static int udf_do_extend_file(struct ino
 	}
 
 	/* Managed to do everything necessary? */
-	if (!blocks)
+	if (!new_block_bytes)
 		goto out;
 
 	/* All further extents will be NOT_RECORDED_NOT_ALLOCATED */
 	last_ext->extLocation.logicalBlockNum = 0;
 	last_ext->extLocation.partitionReferenceNum = 0;
-	add = (1 << (30-sb->s_blocksize_bits)) - 1;
-	last_ext->extLength = EXT_NOT_RECORDED_NOT_ALLOCATED |
-				(add << sb->s_blocksize_bits);
+	add = (1 << 30) - sb->s_blocksize;
+	last_ext->extLength = EXT_NOT_RECORDED_NOT_ALLOCATED | add;
 
 	/* Create enough extents to cover the whole hole */
-	while (blocks > add) {
-		blocks -= add;
+	while (new_block_bytes > add) {
+		new_block_bytes -= add;
 		err = udf_add_aext(inode, last_pos, &last_ext->extLocation,
 				   last_ext->extLength, 1);
 		if (err)
 			return err;
 		count++;
 	}
-	if (blocks) {
+	if (new_block_bytes) {
 		last_ext->extLength = EXT_NOT_RECORDED_NOT_ALLOCATED |
-			(blocks << sb->s_blocksize_bits);
+			new_block_bytes;
 		err = udf_add_aext(inode, last_pos, &last_ext->extLocation,
 				   last_ext->extLength, 1);
 		if (err)
@@ -596,6 +596,24 @@ out:
 	return count;
 }
 
+/* Extend the final block of the file to final_block_len bytes */
+static void udf_do_extend_final_block(struct inode *inode,
+				      struct extent_position *last_pos,
+				      struct kernel_long_ad *last_ext,
+				      uint32_t final_block_len)
+{
+	struct super_block *sb = inode->i_sb;
+	uint32_t added_bytes;
+
+	added_bytes = final_block_len -
+		      (last_ext->extLength & (sb->s_blocksize - 1));
+	last_ext->extLength += added_bytes;
+	UDF_I(inode)->i_lenExtents += added_bytes;
+
+	udf_write_aext(inode, last_pos, &last_ext->extLocation,
+			last_ext->extLength, 1);
+}
+
 static int udf_extend_file(struct inode *inode, loff_t newsize)
 {
 
@@ -605,10 +623,12 @@ static int udf_extend_file(struct inode
 	int8_t etype;
 	struct super_block *sb = inode->i_sb;
 	sector_t first_block = newsize >> sb->s_blocksize_bits, offset;
+	unsigned long partial_final_block;
 	int adsize;
 	struct udf_inode_info *iinfo = UDF_I(inode);
 	struct kernel_long_ad extent;
-	int err;
+	int err = 0;
+	int within_final_block;
 
 	if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT)
 		adsize = sizeof(struct short_ad);
@@ -618,18 +638,8 @@ static int udf_extend_file(struct inode
 		BUG();
 
 	etype = inode_bmap(inode, first_block, &epos, &eloc, &elen, &offset);
+	within_final_block = (etype != -1);
 
-	/* File has extent covering the new size (could happen when extending
-	 * inside a block)? */
-	if (etype != -1)
-		return 0;
-	if (newsize & (sb->s_blocksize - 1))
-		offset++;
-	/* Extended file just to the boundary of the last file block? */
-	if (offset == 0)
-		return 0;
-
-	/* Truncate is extending the file by 'offset' blocks */
 	if ((!epos.bh && epos.offset == udf_file_entry_alloc_offset(inode)) ||
 	    (epos.bh && epos.offset == sizeof(struct allocExtDesc))) {
 		/* File has no extents at all or has empty last
@@ -643,7 +653,22 @@ static int udf_extend_file(struct inode
 				      &extent.extLength, 0);
 		extent.extLength |= etype << 30;
 	}
-	err = udf_do_extend_file(inode, &epos, &extent, offset);
+
+	partial_final_block = newsize & (sb->s_blocksize - 1);
+
+	/* File has extent covering the new size (could happen when extending
+	 * inside a block)?
+	 */
+	if (within_final_block) {
+		/* Extending file within the last file block */
+		udf_do_extend_final_block(inode, &epos, &extent,
+					  partial_final_block);
+	} else {
+		loff_t add = ((loff_t)offset << sb->s_blocksize_bits) |
+			     partial_final_block;
+		err = udf_do_extend_file(inode, &epos, &extent, add);
+	}
+
 	if (err < 0)
 		goto out;
 	err = 0;
@@ -745,6 +770,7 @@ static sector_t inode_getblk(struct inod
 	/* Are we beyond EOF? */
 	if (etype == -1) {
 		int ret;
+		loff_t hole_len;
 		isBeyondEOF = true;
 		if (count) {
 			if (c)
@@ -760,7 +786,8 @@ static sector_t inode_getblk(struct inod
 			startnum = (offset > 0);
 		}
 		/* Create extents for the hole between EOF and offset */
-		ret = udf_do_extend_file(inode, &prev_epos, laarr, offset);
+		hole_len = (loff_t)offset << inode->i_blkbits;
+		ret = udf_do_extend_file(inode, &prev_epos, laarr, hole_len);
 		if (ret < 0) {
 			*err = ret;
 			newblock = 0;



  parent reply	other threads:[~2019-07-12 12:22 UTC|newest]

Thread overview: 101+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-07-12 12:18 [PATCH 4.19 00/91] 4.19.59-stable review Greg Kroah-Hartman
2019-07-12 12:18 ` [PATCH 4.19 01/91] crypto: talitos - fix hash on SEC1 Greg Kroah-Hartman
2019-07-12 12:18 ` [PATCH 4.19 02/91] crypto: talitos - rename alternative AEAD algos Greg Kroah-Hartman
2019-07-12 12:18 ` [PATCH 4.19 03/91] soc: brcmstb: Fix error path for unsupported CPUs Greg Kroah-Hartman
2019-07-12 12:18 ` [PATCH 4.19 04/91] soc: bcm: brcmstb: biuctrl: Register writes require a barrier Greg Kroah-Hartman
2019-07-12 12:18 ` [PATCH 4.19 05/91] Input: elantech - enable middle button support on 2 ThinkPads Greg Kroah-Hartman
2019-07-12 12:18 ` [PATCH 4.19 06/91] samples, bpf: fix to change the buffer size for read() Greg Kroah-Hartman
2019-07-12 12:18 ` [PATCH 4.19 07/91] samples, bpf: suppress compiler warning Greg Kroah-Hartman
2019-07-12 12:18 ` [PATCH 4.19 08/91] mac80211: fix rate reporting inside cfg80211_calculate_bitrate_he() Greg Kroah-Hartman
2019-07-12 12:18 ` [PATCH 4.19 09/91] bpf: sockmap, fix use after free from sleep in psock backlog workqueue Greg Kroah-Hartman
2019-07-12 12:18 ` [PATCH 4.19 10/91] soundwire: stream: fix out of boundary access on port properties Greg Kroah-Hartman
2019-07-12 12:18 ` [PATCH 4.19 11/91] staging:iio:ad7150: fix threshold mode config bit Greg Kroah-Hartman
2019-07-12 12:18 ` [PATCH 4.19 12/91] mac80211: mesh: fix RCU warning Greg Kroah-Hartman
2019-07-12 12:18 ` [PATCH 4.19 13/91] mac80211: free peer keys before vif down in mesh Greg Kroah-Hartman
2019-07-12 12:18 ` [PATCH 4.19 14/91] mwifiex: Fix possible buffer overflows at parsing bss descriptor Greg Kroah-Hartman
2019-07-12 12:18 ` [PATCH 4.19 15/91] iwlwifi: Fix double-free problems in iwl_req_fw_callback() Greg Kroah-Hartman
2019-07-12 12:18 ` [PATCH 4.19 16/91] mwifiex: Fix heap overflow in mwifiex_uap_parse_tail_ies() Greg Kroah-Hartman
2019-07-12 12:18 ` [PATCH 4.19 17/91] soundwire: intel: set dai min and max channels correctly Greg Kroah-Hartman
2019-07-12 12:18 ` [PATCH 4.19 18/91] dt-bindings: can: mcp251x: add mcp25625 support Greg Kroah-Hartman
2019-07-12 12:18 ` [PATCH 4.19 19/91] can: mcp251x: add support for mcp25625 Greg Kroah-Hartman
2019-07-12 12:18 ` [PATCH 4.19 20/91] can: m_can: implement errata "Needless activation of MRAF irq" Greg Kroah-Hartman
2019-07-12 12:18 ` [PATCH 4.19 21/91] can: af_can: Fix error path of can_init() Greg Kroah-Hartman
2019-07-12 12:18 ` [PATCH 4.19 22/91] net: phy: rename Asix Electronics PHY driver Greg Kroah-Hartman
2019-07-12 12:18 ` [PATCH 4.19 23/91] ibmvnic: Do not close unopened driver during reset Greg Kroah-Hartman
2019-07-12 12:18 ` [PATCH 4.19 24/91] ibmvnic: Refresh device multicast list after reset Greg Kroah-Hartman
2019-07-12 12:18 ` [PATCH 4.19 25/91] ibmvnic: Fix unchecked return codes of memory allocations Greg Kroah-Hartman
2019-07-12 12:18 ` [PATCH 4.19 26/91] ARM: dts: am335x phytec boards: Fix cd-gpios active level Greg Kroah-Hartman
2019-07-12 12:18 ` [PATCH 4.19 27/91] s390/boot: disable address-of-packed-member warning Greg Kroah-Hartman
2019-07-12 12:18 ` [PATCH 4.19 28/91] drm/vmwgfx: Honor the sg list segment size limitation Greg Kroah-Hartman
2019-07-12 12:18 ` [PATCH 4.19 29/91] drm/vmwgfx: fix a warning due to missing dma_parms Greg Kroah-Hartman
2019-07-12 12:18 ` [PATCH 4.19 30/91] riscv: Fix udelay in RV32 Greg Kroah-Hartman
2019-07-12 12:18 ` [PATCH 4.19 31/91] Input: imx_keypad - make sure keyboard can always wake up system Greg Kroah-Hartman
2019-07-12 12:18 ` [PATCH 4.19 32/91] KVM: arm/arm64: vgic: Fix kvm_device leak in vgic_its_destroy Greg Kroah-Hartman
2019-07-12 12:18 ` [PATCH 4.19 33/91] mlxsw: spectrum: Disallow prio-tagged packets when PVID is removed Greg Kroah-Hartman
2019-07-12 12:18 ` [PATCH 4.19 34/91] ARM: davinci: da850-evm: call regulator_has_full_constraints() Greg Kroah-Hartman
2019-07-12 12:18 ` [PATCH 4.19 35/91] ARM: davinci: da8xx: specify dma_coherent_mask for lcdc Greg Kroah-Hartman
2019-07-12 12:18 ` [PATCH 4.19 36/91] mac80211: only warn once on chanctx_conf being NULL Greg Kroah-Hartman
2019-07-12 12:18 ` [PATCH 4.19 37/91] mac80211: do not start any work during reconfigure flow Greg Kroah-Hartman
2019-07-12 12:18 ` [PATCH 4.19 38/91] bpf, devmap: Fix premature entry free on destroying map Greg Kroah-Hartman
2019-07-12 12:18 ` [PATCH 4.19 39/91] bpf, devmap: Add missing bulk queue free Greg Kroah-Hartman
2019-07-12 12:18 ` [PATCH 4.19 40/91] bpf, devmap: Add missing RCU read lock on flush Greg Kroah-Hartman
2019-07-12 12:18 ` [PATCH 4.19 41/91] bpf, x64: fix stack layout of JITed bpf code Greg Kroah-Hartman
2019-07-12 12:18 ` [PATCH 4.19 42/91] qmi_wwan: add support for QMAP padding in the RX path Greg Kroah-Hartman
2019-07-12 12:18 ` [PATCH 4.19 43/91] qmi_wwan: avoid RCU stalls on device disconnect when in QMAP mode Greg Kroah-Hartman
2019-07-12 12:18 ` [PATCH 4.19 44/91] qmi_wwan: extend permitted QMAP mux_id value range Greg Kroah-Hartman
2019-07-12 12:18 ` [PATCH 4.19 45/91] mmc: core: complete HS400 before checking status Greg Kroah-Hartman
2019-07-12 12:18 ` [PATCH 4.19 46/91] md: fix for divide error in status_resync Greg Kroah-Hartman
2019-07-12 12:18 ` [PATCH 4.19 47/91] bnx2x: Check if transceiver implements DDM before access Greg Kroah-Hartman
2019-07-12 12:18 ` [PATCH 4.19 48/91] drm: return -EFAULT if copy_to_user() fails Greg Kroah-Hartman
2019-07-12 12:18 ` [PATCH 4.19 49/91] ip6_tunnel: allow not to count pkts on tstats by passing dev as NULL Greg Kroah-Hartman
2019-07-12 12:18 ` [PATCH 4.19 50/91] net: lio_core: fix potential sign-extension overflow on large shift Greg Kroah-Hartman
2019-07-12 12:18 ` [PATCH 4.19 51/91] scsi: qedi: Check targetname while finding boot target information Greg Kroah-Hartman
2019-07-12 12:18 ` [PATCH 4.19 52/91] quota: fix a problem about transfer quota Greg Kroah-Hartman
2019-07-12 12:18 ` [PATCH 4.19 53/91] net: dsa: mv88e6xxx: fix shift of FID bits in mv88e6185_g1_vtu_loadpurge() Greg Kroah-Hartman
2019-07-12 12:18 ` [PATCH 4.19 54/91] NFS4: Only set creation opendata if O_CREAT Greg Kroah-Hartman
2019-07-12 12:18 ` [PATCH 4.19 55/91] net :sunrpc :clnt :Fix xps refcount imbalance on the error path Greg Kroah-Hartman
2019-07-12 12:18 ` [PATCH 4.19 56/91] fscrypt: dont set policy for a dead directory Greg Kroah-Hartman
2019-07-12 12:19 ` Greg Kroah-Hartman [this message]
2019-07-12 12:19 ` [PATCH 4.19 58/91] media: stv0297: fix frequency range limit Greg Kroah-Hartman
2019-07-12 12:19 ` [PATCH 4.19 59/91] ALSA: usb-audio: Fix parse of UAC2 Extension Units Greg Kroah-Hartman
2019-07-12 12:19 ` [PATCH 4.19 60/91] ALSA: hda/realtek - Headphone Mic cant record after S3 Greg Kroah-Hartman
2019-07-12 12:19 ` [PATCH 4.19 61/91] block, bfq: NULL out the bic when its no longer valid Greg Kroah-Hartman
2019-07-12 12:19 ` [PATCH 4.19 62/91] perf pmu: Fix uncore PMU alias list for ARM64 Greg Kroah-Hartman
2019-07-12 12:19   ` Greg Kroah-Hartman
2019-07-12 12:19 ` [PATCH 4.19 63/91] x86/ptrace: Fix possible spectre-v1 in ptrace_get_debugreg() Greg Kroah-Hartman
2019-07-12 12:19 ` [PATCH 4.19 64/91] x86/tls: Fix possible spectre-v1 in do_get_thread_area() Greg Kroah-Hartman
2019-07-12 12:19 ` [PATCH 4.19 65/91] Documentation: Add section about CPU vulnerabilities for Spectre Greg Kroah-Hartman
2019-07-12 12:19 ` [PATCH 4.19 66/91] Documentation/admin: Remove the vsyscall=native documentation Greg Kroah-Hartman
2019-07-12 12:19 ` [PATCH 4.19 67/91] mwifiex: Abort at too short BSS descriptor element Greg Kroah-Hartman
2019-07-12 12:19 ` [PATCH 4.19 68/91] mwifiex: Dont abort on small, spec-compliant vendor IEs Greg Kroah-Hartman
2019-07-12 12:19 ` [PATCH 4.19 69/91] USB: serial: ftdi_sio: add ID for isodebug v1 Greg Kroah-Hartman
2019-07-12 12:19 ` [PATCH 4.19 70/91] USB: serial: option: add support for GosunCn ME3630 RNDIS mode Greg Kroah-Hartman
2019-07-12 12:19 ` [PATCH 4.19 71/91] Revert "serial: 8250: Dont service RX FIFO if interrupts are disabled" Greg Kroah-Hartman
2019-07-12 12:19 ` [PATCH 4.19 72/91] p54usb: Fix race between disconnect and firmware loading Greg Kroah-Hartman
2019-07-12 12:19 ` [PATCH 4.19 73/91] usb: gadget: ether: Fix race between gether_disconnect and rx_submit Greg Kroah-Hartman
2019-07-12 12:19 ` [PATCH 4.19 74/91] usb: dwc2: use a longer AHB idle timeout in dwc2_core_reset() Greg Kroah-Hartman
2019-07-12 12:19 ` [PATCH 4.19 75/91] usb: renesas_usbhs: add a workaround for a race condition of workqueue Greg Kroah-Hartman
2019-07-12 12:19 ` [PATCH 4.19 76/91] drivers/usb/typec/tps6598x.c: fix portinfo width Greg Kroah-Hartman
2019-07-12 12:19 ` [PATCH 4.19 77/91] drivers/usb/typec/tps6598x.c: fix 4CC cmd write Greg Kroah-Hartman
2019-07-12 12:19 ` [PATCH 4.19 78/91] staging: comedi: dt282x: fix a null pointer deref on interrupt Greg Kroah-Hartman
2019-07-12 12:19 ` [PATCH 4.19 79/91] staging: comedi: amplc_pci230: fix " Greg Kroah-Hartman
2019-07-12 12:19 ` [PATCH 4.19 80/91] HID: Add another Primax PIXART OEM mouse quirk Greg Kroah-Hartman
2019-07-12 12:19 ` [PATCH 4.19 81/91] lkdtm: support llvm-objcopy Greg Kroah-Hartman
2019-07-12 12:19 ` [PATCH 4.19 82/91] binder: fix memory leak in error path Greg Kroah-Hartman
2019-07-12 12:19 ` [PATCH 4.19 83/91] carl9170: fix misuse of device driver API Greg Kroah-Hartman
2019-07-12 12:19 ` [PATCH 4.19 84/91] VMCI: Fix integer overflow in VMCI handle arrays Greg Kroah-Hartman
2019-07-12 12:19 ` [PATCH 4.19 85/91] MIPS: Remove superfluous check for __linux__ Greg Kroah-Hartman
2019-07-12 12:19 ` [PATCH 4.19 86/91] staging: fsl-dpaa2/ethsw: fix memory leak of switchdev_work Greg Kroah-Hartman
2019-07-12 12:19 ` [PATCH 4.19 87/91] staging: bcm2835-camera: Replace spinlock protecting context_map with mutex Greg Kroah-Hartman
2019-07-12 12:19 ` [PATCH 4.19 88/91] staging: bcm2835-camera: Ensure all buffers are returned on disable Greg Kroah-Hartman
2019-07-12 12:19 ` [PATCH 4.19 89/91] staging: bcm2835-camera: Remove check of the number of buffers supplied Greg Kroah-Hartman
2019-07-12 12:19 ` [PATCH 4.19 90/91] staging: bcm2835-camera: Handle empty EOS buffers whilst streaming Greg Kroah-Hartman
2019-07-12 12:19 ` [PATCH 4.19 91/91] staging: rtl8712: reduce stack usage, again Greg Kroah-Hartman
2019-07-12 13:36 ` [PATCH 4.19 00/91] 4.19.59-stable review Jon Hunter
2019-07-12 13:36   ` Jon Hunter
2019-07-12 22:06 ` shuah
2019-07-12 23:53 ` kernelci.org bot
2019-07-13  1:50 ` Naresh Kamboju
2019-07-13 20:39 ` Luke Nowakowski-Krijger
2019-07-13 22:05 ` Guenter Roeck
2019-07-14  5:34 ` Kelsey Skunberg

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=20190712121624.789594115@linuxfoundation.org \
    --to=gregkh@linuxfoundation.org \
    --cc=jack@suse.cz \
    --cc=linux-kernel@vger.kernel.org \
    --cc=stable@vger.kernel.org \
    --cc=steve@digidescorp.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 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.