From: alexander.levin@verizon.com
To: "linux-kernel@vger.kernel.org" <linux-kernel@vger.kernel.org>,
"stable@vger.kernel.org" <stable@vger.kernel.org>
Cc: Liping Zhang <zlpnobody@gmail.com>,
Pablo Neira Ayuso <pablo@netfilter.org>,
alexander.levin@verizon.com
Subject: [PATCH AUTOSEL for 4.9 053/100] netfilter: nfnl_cthelper: fix a race when walk the nf_ct_helper_hash table
Date: Wed, 13 Dec 2017 01:57:35 +0000 [thread overview]
Message-ID: <20171213015722.6722-28-alexander.levin@verizon.com> (raw)
In-Reply-To: <20171213015722.6722-1-alexander.levin@verizon.com>
From: Liping Zhang <zlpnobody@gmail.com>
[ Upstream commit 83d90219a5df8d950855ce73229a97b63605c317 ]
The nf_ct_helper_hash table is protected by nf_ct_helper_mutex, while
nfct_helper operation is protected by nfnl_lock(NFNL_SUBSYS_CTHELPER).
So it's possible that one CPU is walking the nf_ct_helper_hash for
cthelper add/get/del, another cpu is doing nf_conntrack_helpers_unregister
at the same time. This is dangrous, and may cause use after free error.
Note, delete operation will flush all cthelpers added via nfnetlink, so
using rcu to do protect is not easy.
Now introduce a dummy list to record all the cthelpers added via
nfnetlink, then we can walk the dummy list instead of walking the
nf_ct_helper_hash. Also, keep nfnl_cthelper_dump_table unchanged, it
may be invoked without nfnl_lock(NFNL_SUBSYS_CTHELPER) held.
Signed-off-by: Liping Zhang <zlpnobody@gmail.com>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Signed-off-by: Sasha Levin <alexander.levin@verizon.com>
---
net/netfilter/nfnetlink_cthelper.c | 177 +++++++++++++++++--------------------
1 file changed, 81 insertions(+), 96 deletions(-)
diff --git a/net/netfilter/nfnetlink_cthelper.c b/net/netfilter/nfnetlink_cthelper.c
index ad65eb548157..28d065394c09 100644
--- a/net/netfilter/nfnetlink_cthelper.c
+++ b/net/netfilter/nfnetlink_cthelper.c
@@ -32,6 +32,13 @@ MODULE_LICENSE("GPL");
MODULE_AUTHOR("Pablo Neira Ayuso <pablo@netfilter.org>");
MODULE_DESCRIPTION("nfnl_cthelper: User-space connection tracking helpers");
+struct nfnl_cthelper {
+ struct list_head list;
+ struct nf_conntrack_helper helper;
+};
+
+static LIST_HEAD(nfnl_cthelper_list);
+
static int
nfnl_userspace_cthelper(struct sk_buff *skb, unsigned int protoff,
struct nf_conn *ct, enum ip_conntrack_info ctinfo)
@@ -205,14 +212,16 @@ nfnl_cthelper_create(const struct nlattr * const tb[],
struct nf_conntrack_tuple *tuple)
{
struct nf_conntrack_helper *helper;
+ struct nfnl_cthelper *nfcth;
int ret;
if (!tb[NFCTH_TUPLE] || !tb[NFCTH_POLICY] || !tb[NFCTH_PRIV_DATA_LEN])
return -EINVAL;
- helper = kzalloc(sizeof(struct nf_conntrack_helper), GFP_KERNEL);
- if (helper == NULL)
+ nfcth = kzalloc(sizeof(*nfcth), GFP_KERNEL);
+ if (nfcth == NULL)
return -ENOMEM;
+ helper = &nfcth->helper;
ret = nfnl_cthelper_parse_expect_policy(helper, tb[NFCTH_POLICY]);
if (ret < 0)
@@ -249,11 +258,12 @@ nfnl_cthelper_create(const struct nlattr * const tb[],
if (ret < 0)
goto err2;
+ list_add_tail(&nfcth->list, &nfnl_cthelper_list);
return 0;
err2:
kfree(helper->expect_policy);
err1:
- kfree(helper);
+ kfree(nfcth);
return ret;
}
@@ -379,7 +389,8 @@ static int nfnl_cthelper_new(struct net *net, struct sock *nfnl,
const char *helper_name;
struct nf_conntrack_helper *cur, *helper = NULL;
struct nf_conntrack_tuple tuple;
- int ret = 0, i;
+ struct nfnl_cthelper *nlcth;
+ int ret = 0;
if (!tb[NFCTH_NAME] || !tb[NFCTH_TUPLE])
return -EINVAL;
@@ -390,31 +401,22 @@ static int nfnl_cthelper_new(struct net *net, struct sock *nfnl,
if (ret < 0)
return ret;
- rcu_read_lock();
- for (i = 0; i < nf_ct_helper_hsize && !helper; i++) {
- hlist_for_each_entry_rcu(cur, &nf_ct_helper_hash[i], hnode) {
+ list_for_each_entry(nlcth, &nfnl_cthelper_list, list) {
+ cur = &nlcth->helper;
- /* skip non-userspace conntrack helpers. */
- if (!(cur->flags & NF_CT_HELPER_F_USERSPACE))
- continue;
+ if (strncmp(cur->name, helper_name, NF_CT_HELPER_NAME_LEN))
+ continue;
- if (strncmp(cur->name, helper_name,
- NF_CT_HELPER_NAME_LEN) != 0)
- continue;
+ if ((tuple.src.l3num != cur->tuple.src.l3num ||
+ tuple.dst.protonum != cur->tuple.dst.protonum))
+ continue;
- if ((tuple.src.l3num != cur->tuple.src.l3num ||
- tuple.dst.protonum != cur->tuple.dst.protonum))
- continue;
+ if (nlh->nlmsg_flags & NLM_F_EXCL)
+ return -EEXIST;
- if (nlh->nlmsg_flags & NLM_F_EXCL) {
- ret = -EEXIST;
- goto err;
- }
- helper = cur;
- break;
- }
+ helper = cur;
+ break;
}
- rcu_read_unlock();
if (helper == NULL)
ret = nfnl_cthelper_create(tb, &tuple);
@@ -422,9 +424,6 @@ static int nfnl_cthelper_new(struct net *net, struct sock *nfnl,
ret = nfnl_cthelper_update(tb, helper);
return ret;
-err:
- rcu_read_unlock();
- return ret;
}
static int
@@ -588,11 +587,12 @@ static int nfnl_cthelper_get(struct net *net, struct sock *nfnl,
struct sk_buff *skb, const struct nlmsghdr *nlh,
const struct nlattr * const tb[])
{
- int ret = -ENOENT, i;
+ int ret = -ENOENT;
struct nf_conntrack_helper *cur;
struct sk_buff *skb2;
char *helper_name = NULL;
struct nf_conntrack_tuple tuple;
+ struct nfnl_cthelper *nlcth;
bool tuple_set = false;
if (nlh->nlmsg_flags & NLM_F_DUMP) {
@@ -613,45 +613,39 @@ static int nfnl_cthelper_get(struct net *net, struct sock *nfnl,
tuple_set = true;
}
- for (i = 0; i < nf_ct_helper_hsize; i++) {
- hlist_for_each_entry_rcu(cur, &nf_ct_helper_hash[i], hnode) {
+ list_for_each_entry(nlcth, &nfnl_cthelper_list, list) {
+ cur = &nlcth->helper;
+ if (helper_name &&
+ strncmp(cur->name, helper_name, NF_CT_HELPER_NAME_LEN))
+ continue;
- /* skip non-userspace conntrack helpers. */
- if (!(cur->flags & NF_CT_HELPER_F_USERSPACE))
- continue;
+ if (tuple_set &&
+ (tuple.src.l3num != cur->tuple.src.l3num ||
+ tuple.dst.protonum != cur->tuple.dst.protonum))
+ continue;
- if (helper_name && strncmp(cur->name, helper_name,
- NF_CT_HELPER_NAME_LEN) != 0) {
- continue;
- }
- if (tuple_set &&
- (tuple.src.l3num != cur->tuple.src.l3num ||
- tuple.dst.protonum != cur->tuple.dst.protonum))
- continue;
-
- skb2 = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
- if (skb2 == NULL) {
- ret = -ENOMEM;
- break;
- }
+ skb2 = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
+ if (skb2 == NULL) {
+ ret = -ENOMEM;
+ break;
+ }
- ret = nfnl_cthelper_fill_info(skb2, NETLINK_CB(skb).portid,
- nlh->nlmsg_seq,
- NFNL_MSG_TYPE(nlh->nlmsg_type),
- NFNL_MSG_CTHELPER_NEW, cur);
- if (ret <= 0) {
- kfree_skb(skb2);
- break;
- }
+ ret = nfnl_cthelper_fill_info(skb2, NETLINK_CB(skb).portid,
+ nlh->nlmsg_seq,
+ NFNL_MSG_TYPE(nlh->nlmsg_type),
+ NFNL_MSG_CTHELPER_NEW, cur);
+ if (ret <= 0) {
+ kfree_skb(skb2);
+ break;
+ }
- ret = netlink_unicast(nfnl, skb2, NETLINK_CB(skb).portid,
- MSG_DONTWAIT);
- if (ret > 0)
- ret = 0;
+ ret = netlink_unicast(nfnl, skb2, NETLINK_CB(skb).portid,
+ MSG_DONTWAIT);
+ if (ret > 0)
+ ret = 0;
- /* this avoids a loop in nfnetlink. */
- return ret == -EAGAIN ? -ENOBUFS : ret;
- }
+ /* this avoids a loop in nfnetlink. */
+ return ret == -EAGAIN ? -ENOBUFS : ret;
}
return ret;
}
@@ -662,10 +656,10 @@ static int nfnl_cthelper_del(struct net *net, struct sock *nfnl,
{
char *helper_name = NULL;
struct nf_conntrack_helper *cur;
- struct hlist_node *tmp;
struct nf_conntrack_tuple tuple;
bool tuple_set = false, found = false;
- int i, j = 0, ret;
+ struct nfnl_cthelper *nlcth, *n;
+ int j = 0, ret;
if (tb[NFCTH_NAME])
helper_name = nla_data(tb[NFCTH_NAME]);
@@ -678,30 +672,27 @@ static int nfnl_cthelper_del(struct net *net, struct sock *nfnl,
tuple_set = true;
}
- for (i = 0; i < nf_ct_helper_hsize; i++) {
- hlist_for_each_entry_safe(cur, tmp, &nf_ct_helper_hash[i],
- hnode) {
- /* skip non-userspace conntrack helpers. */
- if (!(cur->flags & NF_CT_HELPER_F_USERSPACE))
- continue;
+ list_for_each_entry_safe(nlcth, n, &nfnl_cthelper_list, list) {
+ cur = &nlcth->helper;
+ j++;
- j++;
+ if (helper_name &&
+ strncmp(cur->name, helper_name, NF_CT_HELPER_NAME_LEN))
+ continue;
- if (helper_name && strncmp(cur->name, helper_name,
- NF_CT_HELPER_NAME_LEN) != 0) {
- continue;
- }
- if (tuple_set &&
- (tuple.src.l3num != cur->tuple.src.l3num ||
- tuple.dst.protonum != cur->tuple.dst.protonum))
- continue;
+ if (tuple_set &&
+ (tuple.src.l3num != cur->tuple.src.l3num ||
+ tuple.dst.protonum != cur->tuple.dst.protonum))
+ continue;
- found = true;
- nf_conntrack_helper_unregister(cur);
- kfree(cur->expect_policy);
- kfree(cur);
- }
+ found = true;
+ nf_conntrack_helper_unregister(cur);
+ kfree(cur->expect_policy);
+
+ list_del(&nlcth->list);
+ kfree(nlcth);
}
+
/* Make sure we return success if we flush and there is no helpers */
return (found || j == 0) ? 0 : -ENOENT;
}
@@ -750,22 +741,16 @@ static int __init nfnl_cthelper_init(void)
static void __exit nfnl_cthelper_exit(void)
{
struct nf_conntrack_helper *cur;
- struct hlist_node *tmp;
- int i;
+ struct nfnl_cthelper *nlcth, *n;
nfnetlink_subsys_unregister(&nfnl_cthelper_subsys);
- for (i=0; i<nf_ct_helper_hsize; i++) {
- hlist_for_each_entry_safe(cur, tmp, &nf_ct_helper_hash[i],
- hnode) {
- /* skip non-userspace conntrack helpers. */
- if (!(cur->flags & NF_CT_HELPER_F_USERSPACE))
- continue;
+ list_for_each_entry_safe(nlcth, n, &nfnl_cthelper_list, list) {
+ cur = &nlcth->helper;
- nf_conntrack_helper_unregister(cur);
- kfree(cur->expect_policy);
- kfree(cur);
- }
+ nf_conntrack_helper_unregister(cur);
+ kfree(cur->expect_policy);
+ kfree(nlcth);
}
}
--
2.11.0
next prev parent reply other threads:[~2017-12-13 2:41 UTC|newest]
Thread overview: 75+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-12-13 1:57 [PATCH AUTOSEL for 4.9 026/100] r8152: fix the rx early size of RTL8153 alexander.levin
2017-12-13 1:57 ` [PATCH AUTOSEL for 4.9 027/100] tipc: fix nametbl deadlock at tipc_nametbl_unsubscribe alexander.levin
2017-12-13 1:57 ` [PATCH AUTOSEL for 4.9 029/100] pinctrl: st: add irq_request/release_resources callbacks alexander.levin
2017-12-13 1:57 ` [PATCH AUTOSEL for 4.9 028/100] inet: frag: release spinlock before calling icmp_send() alexander.levin
2017-12-13 1:57 ` [PATCH AUTOSEL for 4.9 032/100] KVM: x86: correct async page present tracepoint alexander.levin
2017-12-13 1:57 ` [PATCH AUTOSEL for 4.9 030/100] scsi: lpfc: Fix PT2PT PRLI reject alexander.levin
2017-12-13 1:57 ` [PATCH AUTOSEL for 4.9 031/100] kvm: vmx: Flush TLB when the APIC-access address changes alexander.levin
2017-12-13 1:57 ` [PATCH AUTOSEL for 4.9 033/100] KVM: VMX: Fix enable VPID conditions alexander.levin
2017-12-13 1:57 ` [PATCH AUTOSEL for 4.9 034/100] ARM: dts: ti: fix PCI bus dtc warnings alexander.levin
2017-12-13 1:57 ` [PATCH AUTOSEL for 4.9 036/100] i2c: mux: pca954x: Add missing pca9546 definition to chip_desc alexander.levin
2017-12-13 1:57 ` [PATCH AUTOSEL for 4.9 035/100] hwmon: (asus_atk0110) fix uninitialized data access alexander.levin
2017-12-13 1:57 ` [PATCH AUTOSEL for 4.9 037/100] HID: xinmo: fix for out of range for THT 2P arcade controller alexander.levin
2017-12-13 1:57 ` [PATCH AUTOSEL for 4.9 038/100] ASoC: STI: Fix reader substream pointer set alexander.levin
2017-12-13 1:57 ` [PATCH AUTOSEL for 4.9 041/100] s390/qeth: no ETH header for outbound AF_IUCV alexander.levin
2017-12-13 1:57 ` [PATCH AUTOSEL for 4.9 039/100] r8152: prevent the driver from transmitting packets with carrier off alexander.levin
2017-12-13 1:57 ` [PATCH AUTOSEL for 4.9 040/100] s390/qeth: size calculation outbound buffers alexander.levin
2017-12-13 1:57 ` [PATCH AUTOSEL for 4.9 044/100] IB/core: Protect against self-requeue of a cq work item alexander.levin
2017-12-13 1:57 ` [PATCH AUTOSEL for 4.9 043/100] i40iw: Receive netdev events post INET_NOTIFIER state alexander.levin
2017-12-13 1:57 ` [PATCH AUTOSEL for 4.9 045/100] infiniband: Fix alignment of mmap cookies to support VIPT caching alexander.levin
2017-12-13 1:57 ` [PATCH AUTOSEL for 4.9 042/100] bna: avoid writing uninitialized data into hw registers alexander.levin
2017-12-13 1:57 ` [PATCH AUTOSEL for 4.9 047/100] net: Do not allow negative values for busy_read and busy_poll sysctl interfaces alexander.levin
2017-12-13 1:57 ` [PATCH AUTOSEL for 4.9 050/100] i40e: Do not enable NAPI on q_vectors that have no rings alexander.levin
2017-12-13 1:57 ` [PATCH AUTOSEL for 4.9 046/100] nbd: set queue timeout properly alexander.levin
2017-12-13 1:57 ` [PATCH AUTOSEL for 4.9 049/100] IB/rxe: increment msn only when completing a request alexander.levin
2017-12-13 1:57 ` [PATCH AUTOSEL for 4.9 048/100] IB/rxe: double free on error alexander.levin
2017-12-13 1:57 ` [PATCH AUTOSEL for 4.9 052/100] irda: vlsi_ir: fix check for DMA mapping errors alexander.levin
2017-12-13 1:57 ` alexander.levin [this message]
2017-12-13 1:57 ` [PATCH AUTOSEL for 4.9 051/100] RDMA/iser: Fix possible mr leak on device removal event alexander.levin
2017-12-13 1:57 ` [PATCH AUTOSEL for 4.9 056/100] cpufreq: Fix creation of symbolic links to policy directories alexander.levin
2017-12-13 1:57 ` [PATCH AUTOSEL for 4.9 054/100] netfilter: nf_nat_snmp: Fix panic when snmp_trap_helper fails to register alexander.levin
2017-12-13 1:57 ` [PATCH AUTOSEL for 4.9 057/100] net: ipconfig: fix ic_close_devs() use-after-free alexander.levin
2017-12-13 1:57 ` [PATCH AUTOSEL for 4.9 055/100] ARM: dts: am335x-evmsk: adjust mmc2 param to allow suspend alexander.levin
2017-12-13 1:57 ` [PATCH AUTOSEL for 4.9 061/100] isdn: kcapi: avoid uninitialized data alexander.levin
2017-12-13 1:57 ` [PATCH AUTOSEL for 4.9 060/100] virtio_balloon: prevent uninitialized variable use alexander.levin
2017-12-13 1:57 ` [PATCH AUTOSEL for 4.9 059/100] virtio-balloon: use actual number of stats for stats queue buffers alexander.levin
2017-12-13 1:57 ` [PATCH AUTOSEL for 4.9 058/100] KVM: pci-assign: do not map smm memory slot pages in vt-d page tables alexander.levin
2017-12-13 1:57 ` [PATCH AUTOSEL for 4.9 063/100] xhci: plat: Register shutdown for xhci_plat alexander.levin
2017-12-13 1:57 ` [PATCH AUTOSEL for 4.9 062/100] net: moxa: fix TX overrun memory leak alexander.levin
2017-12-13 1:57 ` [PATCH AUTOSEL for 4.9 064/100] netfilter: nfnetlink_queue: fix secctx " alexander.levin
2017-12-13 1:57 ` [PATCH AUTOSEL for 4.9 065/100] Btrfs: fix an integer overflow check alexander.levin
2017-12-13 1:57 ` [PATCH AUTOSEL for 4.9 069/100] backlight: pwm_bl: Fix overflow condition alexander.levin
2017-12-13 1:57 ` [PATCH AUTOSEL for 4.9 068/100] bnxt_en: Fix NULL pointer dereference in reopen failure path alexander.levin
2017-12-13 1:57 ` [PATCH AUTOSEL for 4.9 067/100] cpuidle: powernv: Pass correct drv->cpumask for registration alexander.levin
2017-12-13 1:57 ` [PATCH AUTOSEL for 4.9 066/100] ARM: dma-mapping: disallow dma_get_sgtable() for non-kernel managed memory alexander.levin
2017-12-13 1:57 ` [PATCH AUTOSEL for 4.9 072/100] crypto: talitos - fix memory corruption on SEC2 alexander.levin
2017-12-13 1:57 ` [PATCH AUTOSEL for 4.9 073/100] crypto: crypto4xx - increase context and scatter ring buffer elements alexander.levin
2017-12-13 1:57 ` [PATCH AUTOSEL for 4.9 071/100] crypto: talitos - fix AEAD test failures alexander.levin
2017-12-13 1:57 ` [PATCH AUTOSEL for 4.9 070/100] crypto: talitos - fix ctr-aes-talitos alexander.levin
2017-12-13 1:57 ` [PATCH AUTOSEL for 4.9 077/100] PCI: Avoid bus reset if bridge itself is broken alexander.levin
2017-12-13 1:57 ` [PATCH AUTOSEL for 4.9 074/100] rtc: pl031: make interrupt optional alexander.levin
2017-12-13 1:57 ` [PATCH AUTOSEL for 4.9 075/100] kvm, mm: account kvm related kmem slabs to kmemcg alexander.levin
2017-12-13 1:57 ` [PATCH AUTOSEL for 4.9 076/100] net: phy: at803x: Change error to EINVAL for invalid MAC alexander.levin
2017-12-13 1:57 ` [PATCH AUTOSEL for 4.9 079/100] scsi: mpt3sas: Fix IO error occurs on pulling out a drive from RAID1 volume created on two SATA drive alexander.levin
2017-12-13 1:57 ` [PATCH AUTOSEL for 4.9 078/100] scsi: cxgb4i: fix Tx skb leak alexander.levin
2017-12-13 1:57 ` [PATCH AUTOSEL for 4.9 080/100] PCI: Create SR-IOV virtfn/physfn links before attaching driver alexander.levin
2017-12-13 1:57 ` [PATCH AUTOSEL for 4.9 081/100] PM / OPP: Move error message to debug level alexander.levin
2017-12-13 1:57 ` [PATCH AUTOSEL for 4.9 083/100] ixgbe: fix use of uninitialized padding alexander.levin
2017-12-13 1:57 ` [PATCH AUTOSEL for 4.9 084/100] IB/rxe: check for allocation failure on elem alexander.levin
2017-12-13 1:57 ` [PATCH AUTOSEL for 4.9 082/100] igb: check memory allocation failure alexander.levin
2017-12-13 1:57 ` [PATCH AUTOSEL for 4.9 085/100] PCI/AER: Report non-fatal errors only to the affected endpoint alexander.levin
2017-12-13 1:57 ` [PATCH AUTOSEL for 4.9 088/100] ASoC: img-parallel-out: Add pm_runtime_get/put to set_fmt callback alexander.levin
2017-12-13 1:57 ` [PATCH AUTOSEL for 4.9 086/100] tracing: Exclude 'generic fields' from histograms alexander.levin
2017-12-13 1:57 ` [PATCH AUTOSEL for 4.9 089/100] powerpc/xmon: Avoid tripping SMP hardlockup watchdog alexander.levin
2017-12-13 1:57 ` [PATCH AUTOSEL for 4.9 087/100] percpu: don't forget to free the temporary struct pcpu_alloc_info alexander.levin
2017-12-13 1:57 ` [PATCH AUTOSEL for 4.9 091/100] scsi: lpfc: Fix secure firmware updates alexander.levin
2017-12-13 1:57 ` [PATCH AUTOSEL for 4.9 093/100] vfio/pci: Virtualize Maximum Payload Size alexander.levin
2017-12-13 1:57 ` [PATCH AUTOSEL for 4.9 092/100] scsi: lpfc: PLOGI failures during NPIV testing alexander.levin
2017-12-13 1:57 ` [PATCH AUTOSEL for 4.9 090/100] fm10k: fix mis-ordered parameters in declaration for .ndo_set_vf_bw alexander.levin
2017-12-13 1:57 ` [PATCH AUTOSEL for 4.9 097/100] clk: sunxi-ng: sun6i: Rename HDMI DDC clock to avoid name collision alexander.levin
2017-12-13 1:57 ` [PATCH AUTOSEL for 4.9 095/100] net: ipv6: send NS for DAD when link operationally up alexander.levin
2017-12-13 1:57 ` [PATCH AUTOSEL for 4.9 096/100] staging: greybus: light: Release memory obtained by kasprintf alexander.levin
2017-12-13 1:57 ` [PATCH AUTOSEL for 4.9 094/100] fm10k: ensure we process SM mbx when processing VF mbx alexander.levin
2017-12-13 1:57 ` [PATCH AUTOSEL for 4.9 100/100] cpuidle: fix broadcast control when broadcast can not be entered alexander.levin
2017-12-13 1:57 ` [PATCH AUTOSEL for 4.9 099/100] rtc: set the alarm to the next expiring timer alexander.levin
2017-12-13 1:57 ` [PATCH AUTOSEL for 4.9 098/100] tcp: fix under-evaluated ssthresh in TCP Vegas alexander.levin
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=20171213015722.6722-28-alexander.levin@verizon.com \
--to=alexander.levin@verizon.com \
--cc=linux-kernel@vger.kernel.org \
--cc=pablo@netfilter.org \
--cc=stable@vger.kernel.org \
--cc=zlpnobody@gmail.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®