From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
To: stable@vger.kernel.org
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
patches@lists.linux.dev,
Ross Lagerwall <ross.lagerwall@citrix.com>,
Paul Durrant <paul@xen.org>, Juergen Gross <jgross@suse.com>,
Sasha Levin <sashal@kernel.org>
Subject: [PATCH 4.19 13/49] xen/netback: Ensure protocol headers dont fall in the non-linear area
Date: Mon, 12 Dec 2022 14:18:51 +0100 [thread overview]
Message-ID: <20221212130914.349633578@linuxfoundation.org> (raw)
In-Reply-To: <20221212130913.666185567@linuxfoundation.org>
From: Ross Lagerwall <ross.lagerwall@citrix.com>
[ Upstream commit ad7f402ae4f466647c3a669b8a6f3e5d4271c84a ]
In some cases, the frontend may send a packet where the protocol headers
are spread across multiple slots. This would result in netback creating
an skb where the protocol headers spill over into the non-linear area.
Some drivers and NICs don't handle this properly resulting in an
interface reset or worse.
This issue was introduced by the removal of an unconditional skb pull in
the tx path to improve performance. Fix this without reintroducing the
pull by setting up grant copy ops for as many slots as needed to reach
the XEN_NETBACK_TX_COPY_LEN size. Adjust the rest of the code to handle
multiple copy operations per skb.
This is XSA-423 / CVE-2022-3643.
Fixes: 7e5d7753956b ("xen-netback: remove unconditional __pskb_pull_tail() in guest Tx path")
Signed-off-by: Ross Lagerwall <ross.lagerwall@citrix.com>
Reviewed-by: Paul Durrant <paul@xen.org>
Signed-off-by: Juergen Gross <jgross@suse.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/net/xen-netback/netback.c | 223 ++++++++++++++++--------------
1 file changed, 123 insertions(+), 100 deletions(-)
diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c
index 4d0d5501ca56..eeaf8a33b61c 100644
--- a/drivers/net/xen-netback/netback.c
+++ b/drivers/net/xen-netback/netback.c
@@ -323,10 +323,13 @@ static int xenvif_count_requests(struct xenvif_queue *queue,
struct xenvif_tx_cb {
- u16 pending_idx;
+ u16 copy_pending_idx[XEN_NETBK_LEGACY_SLOTS_MAX + 1];
+ u8 copy_count;
};
#define XENVIF_TX_CB(skb) ((struct xenvif_tx_cb *)(skb)->cb)
+#define copy_pending_idx(skb, i) (XENVIF_TX_CB(skb)->copy_pending_idx[i])
+#define copy_count(skb) (XENVIF_TX_CB(skb)->copy_count)
static inline void xenvif_tx_create_map_op(struct xenvif_queue *queue,
u16 pending_idx,
@@ -361,31 +364,93 @@ static inline struct sk_buff *xenvif_alloc_skb(unsigned int size)
return skb;
}
-static struct gnttab_map_grant_ref *xenvif_get_requests(struct xenvif_queue *queue,
- struct sk_buff *skb,
- struct xen_netif_tx_request *txp,
- struct gnttab_map_grant_ref *gop,
- unsigned int frag_overflow,
- struct sk_buff *nskb)
+static void xenvif_get_requests(struct xenvif_queue *queue,
+ struct sk_buff *skb,
+ struct xen_netif_tx_request *first,
+ struct xen_netif_tx_request *txfrags,
+ unsigned *copy_ops,
+ unsigned *map_ops,
+ unsigned int frag_overflow,
+ struct sk_buff *nskb,
+ unsigned int extra_count,
+ unsigned int data_len)
{
struct skb_shared_info *shinfo = skb_shinfo(skb);
skb_frag_t *frags = shinfo->frags;
- u16 pending_idx = XENVIF_TX_CB(skb)->pending_idx;
- int start;
+ u16 pending_idx;
pending_ring_idx_t index;
unsigned int nr_slots;
+ struct gnttab_copy *cop = queue->tx_copy_ops + *copy_ops;
+ struct gnttab_map_grant_ref *gop = queue->tx_map_ops + *map_ops;
+ struct xen_netif_tx_request *txp = first;
+
+ nr_slots = shinfo->nr_frags + 1;
+
+ copy_count(skb) = 0;
+
+ /* Create copy ops for exactly data_len bytes into the skb head. */
+ __skb_put(skb, data_len);
+ while (data_len > 0) {
+ int amount = data_len > txp->size ? txp->size : data_len;
+
+ cop->source.u.ref = txp->gref;
+ cop->source.domid = queue->vif->domid;
+ cop->source.offset = txp->offset;
+
+ cop->dest.domid = DOMID_SELF;
+ cop->dest.offset = (offset_in_page(skb->data +
+ skb_headlen(skb) -
+ data_len)) & ~XEN_PAGE_MASK;
+ cop->dest.u.gmfn = virt_to_gfn(skb->data + skb_headlen(skb)
+ - data_len);
+
+ cop->len = amount;
+ cop->flags = GNTCOPY_source_gref;
- nr_slots = shinfo->nr_frags;
+ index = pending_index(queue->pending_cons);
+ pending_idx = queue->pending_ring[index];
+ callback_param(queue, pending_idx).ctx = NULL;
+ copy_pending_idx(skb, copy_count(skb)) = pending_idx;
+ copy_count(skb)++;
+
+ cop++;
+ data_len -= amount;
- /* Skip first skb fragment if it is on same page as header fragment. */
- start = (frag_get_pending_idx(&shinfo->frags[0]) == pending_idx);
+ if (amount == txp->size) {
+ /* The copy op covered the full tx_request */
+
+ memcpy(&queue->pending_tx_info[pending_idx].req,
+ txp, sizeof(*txp));
+ queue->pending_tx_info[pending_idx].extra_count =
+ (txp == first) ? extra_count : 0;
+
+ if (txp == first)
+ txp = txfrags;
+ else
+ txp++;
+ queue->pending_cons++;
+ nr_slots--;
+ } else {
+ /* The copy op partially covered the tx_request.
+ * The remainder will be mapped.
+ */
+ txp->offset += amount;
+ txp->size -= amount;
+ }
+ }
- for (shinfo->nr_frags = start; shinfo->nr_frags < nr_slots;
- shinfo->nr_frags++, txp++, gop++) {
+ for (shinfo->nr_frags = 0; shinfo->nr_frags < nr_slots;
+ shinfo->nr_frags++, gop++) {
index = pending_index(queue->pending_cons++);
pending_idx = queue->pending_ring[index];
- xenvif_tx_create_map_op(queue, pending_idx, txp, 0, gop);
+ xenvif_tx_create_map_op(queue, pending_idx, txp,
+ txp == first ? extra_count : 0, gop);
frag_set_pending_idx(&frags[shinfo->nr_frags], pending_idx);
+
+ if (txp == first)
+ txp = txfrags;
+ else
+ txp++;
}
if (frag_overflow) {
@@ -406,7 +471,8 @@ static struct gnttab_map_grant_ref *xenvif_get_requests(struct xenvif_queue *que
skb_shinfo(skb)->frag_list = nskb;
}
- return gop;
+ (*copy_ops) = cop - queue->tx_copy_ops;
+ (*map_ops) = gop - queue->tx_map_ops;
}
static inline void xenvif_grant_handle_set(struct xenvif_queue *queue,
@@ -442,7 +508,7 @@ static int xenvif_tx_check_gop(struct xenvif_queue *queue,
struct gnttab_copy **gopp_copy)
{
struct gnttab_map_grant_ref *gop_map = *gopp_map;
- u16 pending_idx = XENVIF_TX_CB(skb)->pending_idx;
+ u16 pending_idx;
/* This always points to the shinfo of the skb being checked, which
* could be either the first or the one on the frag_list
*/
@@ -453,24 +519,37 @@ static int xenvif_tx_check_gop(struct xenvif_queue *queue,
struct skb_shared_info *first_shinfo = NULL;
int nr_frags = shinfo->nr_frags;
const bool sharedslot = nr_frags &&
- frag_get_pending_idx(&shinfo->frags[0]) == pending_idx;
+ frag_get_pending_idx(&shinfo->frags[0]) ==
+ copy_pending_idx(skb, copy_count(skb) - 1);
int i, err;
- /* Check status of header. */
- err = (*gopp_copy)->status;
- if (unlikely(err)) {
- if (net_ratelimit())
- netdev_dbg(queue->vif->dev,
- "Grant copy of header failed! status: %d pending_idx: %u ref: %u\n",
- (*gopp_copy)->status,
- pending_idx,
- (*gopp_copy)->source.u.ref);
- /* The first frag might still have this slot mapped */
- if (!sharedslot)
- xenvif_idx_release(queue, pending_idx,
- XEN_NETIF_RSP_ERROR);
+ for (i = 0; i < copy_count(skb); i++) {
+ int newerr;
+
+ /* Check status of header. */
+ pending_idx = copy_pending_idx(skb, i);
+
+ newerr = (*gopp_copy)->status;
+ if (likely(!newerr)) {
+ /* The first frag might still have this slot mapped */
+ if (i < copy_count(skb) - 1 || !sharedslot)
+ xenvif_idx_release(queue, pending_idx,
+ XEN_NETIF_RSP_OKAY);
+ } else {
+ err = newerr;
+ if (net_ratelimit())
+ netdev_dbg(queue->vif->dev,
+ "Grant copy of header failed! status: %d pending_idx: %u ref: %u\n",
+ (*gopp_copy)->status,
+ pending_idx,
+ (*gopp_copy)->source.u.ref);
+ /* The first frag might still have this slot mapped */
+ if (i < copy_count(skb) - 1 || !sharedslot)
+ xenvif_idx_release(queue, pending_idx,
+ XEN_NETIF_RSP_ERROR);
+ }
+ (*gopp_copy)++;
}
- (*gopp_copy)++;
check_frags:
for (i = 0; i < nr_frags; i++, gop_map++) {
@@ -517,14 +596,6 @@ static int xenvif_tx_check_gop(struct xenvif_queue *queue,
if (err)
continue;
- /* First error: if the header haven't shared a slot with the
- * first frag, release it as well.
- */
- if (!sharedslot)
- xenvif_idx_release(queue,
- XENVIF_TX_CB(skb)->pending_idx,
- XEN_NETIF_RSP_OKAY);
-
/* Invalidate preceding fragments of this skb. */
for (j = 0; j < i; j++) {
pending_idx = frag_get_pending_idx(&shinfo->frags[j]);
@@ -794,7 +865,6 @@ static void xenvif_tx_build_gops(struct xenvif_queue *queue,
unsigned *copy_ops,
unsigned *map_ops)
{
- struct gnttab_map_grant_ref *gop = queue->tx_map_ops;
struct sk_buff *skb, *nskb;
int ret;
unsigned int frag_overflow;
@@ -876,8 +946,12 @@ static void xenvif_tx_build_gops(struct xenvif_queue *queue,
continue;
}
+ data_len = (txreq.size > XEN_NETBACK_TX_COPY_LEN) ?
+ XEN_NETBACK_TX_COPY_LEN : txreq.size;
+
ret = xenvif_count_requests(queue, &txreq, extra_count,
txfrags, work_to_do);
+
if (unlikely(ret < 0))
break;
@@ -903,9 +977,8 @@ static void xenvif_tx_build_gops(struct xenvif_queue *queue,
index = pending_index(queue->pending_cons);
pending_idx = queue->pending_ring[index];
- data_len = (txreq.size > XEN_NETBACK_TX_COPY_LEN &&
- ret < XEN_NETBK_LEGACY_SLOTS_MAX) ?
- XEN_NETBACK_TX_COPY_LEN : txreq.size;
+ if (ret >= XEN_NETBK_LEGACY_SLOTS_MAX - 1 && data_len < txreq.size)
+ data_len = txreq.size;
skb = xenvif_alloc_skb(data_len);
if (unlikely(skb == NULL)) {
@@ -916,8 +989,6 @@ static void xenvif_tx_build_gops(struct xenvif_queue *queue,
}
skb_shinfo(skb)->nr_frags = ret;
- if (data_len < txreq.size)
- skb_shinfo(skb)->nr_frags++;
/* At this point shinfo->nr_frags is in fact the number of
* slots, which can be as large as XEN_NETBK_LEGACY_SLOTS_MAX.
*/
@@ -979,54 +1050,19 @@ static void xenvif_tx_build_gops(struct xenvif_queue *queue,
type);
}
- XENVIF_TX_CB(skb)->pending_idx = pending_idx;
-
- __skb_put(skb, data_len);
- queue->tx_copy_ops[*copy_ops].source.u.ref = txreq.gref;
- queue->tx_copy_ops[*copy_ops].source.domid = queue->vif->domid;
- queue->tx_copy_ops[*copy_ops].source.offset = txreq.offset;
-
- queue->tx_copy_ops[*copy_ops].dest.u.gmfn =
- virt_to_gfn(skb->data);
- queue->tx_copy_ops[*copy_ops].dest.domid = DOMID_SELF;
- queue->tx_copy_ops[*copy_ops].dest.offset =
- offset_in_page(skb->data) & ~XEN_PAGE_MASK;
-
- queue->tx_copy_ops[*copy_ops].len = data_len;
- queue->tx_copy_ops[*copy_ops].flags = GNTCOPY_source_gref;
-
- (*copy_ops)++;
-
- if (data_len < txreq.size) {
- frag_set_pending_idx(&skb_shinfo(skb)->frags[0],
- pending_idx);
- xenvif_tx_create_map_op(queue, pending_idx, &txreq,
- extra_count, gop);
- gop++;
- } else {
- frag_set_pending_idx(&skb_shinfo(skb)->frags[0],
- INVALID_PENDING_IDX);
- memcpy(&queue->pending_tx_info[pending_idx].req,
- &txreq, sizeof(txreq));
- queue->pending_tx_info[pending_idx].extra_count =
- extra_count;
- }
-
- queue->pending_cons++;
-
- gop = xenvif_get_requests(queue, skb, txfrags, gop,
- frag_overflow, nskb);
+ xenvif_get_requests(queue, skb, &txreq, txfrags, copy_ops,
+ map_ops, frag_overflow, nskb, extra_count,
+ data_len);
__skb_queue_tail(&queue->tx_queue, skb);
queue->tx.req_cons = idx;
- if (((gop-queue->tx_map_ops) >= ARRAY_SIZE(queue->tx_map_ops)) ||
+ if ((*map_ops >= ARRAY_SIZE(queue->tx_map_ops)) ||
(*copy_ops >= ARRAY_SIZE(queue->tx_copy_ops)))
break;
}
- (*map_ops) = gop - queue->tx_map_ops;
return;
}
@@ -1105,9 +1141,8 @@ static int xenvif_tx_submit(struct xenvif_queue *queue)
while ((skb = __skb_dequeue(&queue->tx_queue)) != NULL) {
struct xen_netif_tx_request *txp;
u16 pending_idx;
- unsigned data_len;
- pending_idx = XENVIF_TX_CB(skb)->pending_idx;
+ pending_idx = copy_pending_idx(skb, 0);
txp = &queue->pending_tx_info[pending_idx].req;
/* Check the remap error code. */
@@ -1126,18 +1161,6 @@ static int xenvif_tx_submit(struct xenvif_queue *queue)
continue;
}
- data_len = skb->len;
- callback_param(queue, pending_idx).ctx = NULL;
- if (data_len < txp->size) {
- /* Append the packet payload as a fragment. */
- txp->offset += data_len;
- txp->size -= data_len;
- } else {
- /* Schedule a response immediately. */
- xenvif_idx_release(queue, pending_idx,
- XEN_NETIF_RSP_OKAY);
- }
-
if (txp->flags & XEN_NETTXF_csum_blank)
skb->ip_summed = CHECKSUM_PARTIAL;
else if (txp->flags & XEN_NETTXF_data_validated)
@@ -1314,7 +1337,7 @@ static inline void xenvif_tx_dealloc_action(struct xenvif_queue *queue)
/* Called after netfront has transmitted */
int xenvif_tx_action(struct xenvif_queue *queue, int budget)
{
- unsigned nr_mops, nr_cops = 0;
+ unsigned nr_mops = 0, nr_cops = 0;
int work_done, ret;
if (unlikely(!tx_work_todo(queue)))
--
2.35.1
next prev parent reply other threads:[~2022-12-12 13:49 UTC|newest]
Thread overview: 57+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-12-12 13:18 [PATCH 4.19 00/49] 4.19.269-rc1 review Greg Kroah-Hartman
2022-12-12 13:18 ` [PATCH 4.19 01/49] arm: dts: rockchip: fix node name for hym8563 rtc Greg Kroah-Hartman
2022-12-12 13:18 ` [PATCH 4.19 02/49] ARM: dts: rockchip: fix ir-receiver node names Greg Kroah-Hartman
2022-12-12 13:18 ` [PATCH 4.19 03/49] ARM: 9251/1: perf: Fix stacktraces for tracepoint events in THUMB2 kernels Greg Kroah-Hartman
2022-12-12 13:18 ` [PATCH 4.19 04/49] ARM: 9266/1: mm: fix no-MMU ZERO_PAGE() implementation Greg Kroah-Hartman
2022-12-12 13:18 ` [PATCH 4.19 05/49] ARM: dts: rockchip: disable arm_global_timer on rk3066 and rk3188 Greg Kroah-Hartman
2022-12-12 13:18 ` [PATCH 4.19 06/49] 9p/fd: Use P9_HDRSZ for header size Greg Kroah-Hartman
2022-12-12 13:18 ` [PATCH 4.19 07/49] ALSA: seq: Fix function prototype mismatch in snd_seq_expand_var_event Greg Kroah-Hartman
2022-12-12 13:18 ` [PATCH 4.19 08/49] ASoC: soc-pcm: Add NULL check in BE reparenting Greg Kroah-Hartman
2022-12-12 13:18 ` [PATCH 4.19 09/49] regulator: twl6030: fix get status of twl6032 regulators Greg Kroah-Hartman
2022-12-12 13:18 ` [PATCH 4.19 10/49] fbcon: Use kzalloc() in fbcon_prepare_logo() Greg Kroah-Hartman
2022-12-12 13:18 ` [PATCH 4.19 11/49] 9p/xen: check logical size for buffer size Greg Kroah-Hartman
2022-12-12 13:18 ` [PATCH 4.19 12/49] net: usb: qmi_wwan: add u-blox 0x1342 composition Greg Kroah-Hartman
2022-12-12 13:18 ` Greg Kroah-Hartman [this message]
2022-12-12 13:18 ` [PATCH 4.19 14/49] xen/netback: do some code cleanup Greg Kroah-Hartman
2022-12-12 13:18 ` [PATCH 4.19 15/49] xen/netback: dont call kfree_skb() with interrupts disabled Greg Kroah-Hartman
2022-12-12 13:18 ` [PATCH 4.19 16/49] rcutorture: Automatically create initrd directory Greg Kroah-Hartman
2022-12-12 13:18 ` [PATCH 4.19 17/49] media: v4l2-dv-timings.c: fix too strict blanking sanity checks Greg Kroah-Hartman
2022-12-12 13:18 ` [PATCH 4.19 18/49] memcg: fix possible use-after-free in memcg_write_event_control() Greg Kroah-Hartman
2022-12-12 13:18 ` [PATCH 4.19 19/49] KVM: s390: vsie: Fix the initialization of the epoch extension (epdx) field Greg Kroah-Hartman
2022-12-12 13:18 ` [PATCH 4.19 20/49] HID: hid-lg4ff: Add check for empty lbuf Greg Kroah-Hartman
2022-12-12 13:18 ` [PATCH 4.19 21/49] HID: core: fix shift-out-of-bounds in hid_report_raw_event Greg Kroah-Hartman
2022-12-12 13:19 ` [PATCH 4.19 22/49] ieee802154: cc2520: Fix error return code in cc2520_hw_init() Greg Kroah-Hartman
2022-12-12 13:19 ` [PATCH 4.19 23/49] ca8210: Fix crash by zero initializing data Greg Kroah-Hartman
2022-12-12 13:19 ` [PATCH 4.19 24/49] gpio: amd8111: Fix PCI device reference count leak Greg Kroah-Hartman
2022-12-12 13:19 ` [PATCH 4.19 25/49] e1000e: Fix TX dispatch condition Greg Kroah-Hartman
2022-12-12 13:19 ` [PATCH 4.19 26/49] igb: Allocate MSI-X vector when testing Greg Kroah-Hartman
2022-12-12 13:19 ` [PATCH 4.19 27/49] Bluetooth: 6LoWPAN: add missing hci_dev_put() in get_l2cap_conn() Greg Kroah-Hartman
2022-12-12 13:19 ` [PATCH 4.19 28/49] Bluetooth: Fix not cleanup led when bt_init fails Greg Kroah-Hartman
2022-12-12 13:19 ` [PATCH 4.19 29/49] selftests: rtnetlink: correct xfrm policy rule in kci_test_ipsec_offload Greg Kroah-Hartman
2022-12-12 13:19 ` [PATCH 4.19 30/49] mac802154: fix missing INIT_LIST_HEAD in ieee802154_if_add() Greg Kroah-Hartman
2022-12-12 13:19 ` [PATCH 4.19 31/49] net: encx24j600: Add parentheses to fix precedence Greg Kroah-Hartman
2022-12-12 13:19 ` [PATCH 4.19 32/49] net: encx24j600: Fix invalid logic in reading of MISTAT register Greg Kroah-Hartman
2022-12-12 13:19 ` [PATCH 4.19 33/49] xen-netfront: Fix NULL sring after live migration Greg Kroah-Hartman
2022-12-12 13:19 ` [PATCH 4.19 34/49] net: mvneta: Prevent out of bounds read in mvneta_config_rss() Greg Kroah-Hartman
2022-12-12 13:19 ` [PATCH 4.19 35/49] i40e: Fix not setting default xps_cpus after reset Greg Kroah-Hartman
2022-12-12 13:19 ` [PATCH 4.19 36/49] i40e: Fix for VF MAC address 0 Greg Kroah-Hartman
2022-12-12 13:19 ` [PATCH 4.19 37/49] i40e: Disallow ip4 and ip6 l4_4_bytes Greg Kroah-Hartman
2022-12-12 13:19 ` [PATCH 4.19 38/49] NFC: nci: Bounds check struct nfc_target arrays Greg Kroah-Hartman
2022-12-12 13:19 ` [PATCH 4.19 39/49] nvme initialize core quirks before calling nvme_init_subsystem Greg Kroah-Hartman
2022-12-12 13:19 ` [PATCH 4.19 40/49] net: stmmac: fix "snps,axi-config" node property parsing Greg Kroah-Hartman
2022-12-12 13:19 ` [PATCH 4.19 41/49] net: hisilicon: Fix potential use-after-free in hisi_femac_rx() Greg Kroah-Hartman
2022-12-12 13:19 ` [PATCH 4.19 42/49] net: hisilicon: Fix potential use-after-free in hix5hd2_rx() Greg Kroah-Hartman
2022-12-12 13:19 ` [PATCH 4.19 43/49] tipc: Fix potential OOB in tipc_link_proto_rcv() Greg Kroah-Hartman
2022-12-12 13:19 ` [PATCH 4.19 44/49] ethernet: aeroflex: fix potential skb leak in greth_init_rings() Greg Kroah-Hartman
2022-12-12 13:19 ` [PATCH 4.19 45/49] xen/netback: fix build warning Greg Kroah-Hartman
2022-12-12 13:19 ` [PATCH 4.19 46/49] net: plip: dont call kfree_skb/dev_kfree_skb() under spin_lock_irq() Greg Kroah-Hartman
2022-12-12 13:19 ` [PATCH 4.19 47/49] ipv6: avoid use-after-free in ip6_fragment() Greg Kroah-Hartman
2022-12-12 13:19 ` [PATCH 4.19 48/49] net: mvneta: Fix an out of bounds check Greg Kroah-Hartman
2022-12-12 13:19 ` [PATCH 4.19 49/49] can: esd_usb: Allow REC and TEC to return to zero Greg Kroah-Hartman
2022-12-12 18:14 ` [PATCH 4.19 00/49] 4.19.269-rc1 review Pavel Machek
2022-12-12 20:22 ` Slade Watkins
2022-12-13 0:04 ` Shuah Khan
2022-12-13 0:24 ` Guenter Roeck
2022-12-13 11:53 ` Naresh Kamboju
2022-12-13 19:27 ` Giulio Benetti
2022-12-13 12:01 ` Sudip Mukherjee (Codethink)
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=20221212130914.349633578@linuxfoundation.org \
--to=gregkh@linuxfoundation.org \
--cc=jgross@suse.com \
--cc=patches@lists.linux.dev \
--cc=paul@xen.org \
--cc=ross.lagerwall@citrix.com \
--cc=sashal@kernel.org \
--cc=stable@vger.kernel.org \
/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