[PATCH 1/2 nf] netfilter: seqadj: Fix some possible panics of seqadj when mem is exhausted

Subsystems: netfilter, networking [general], the rest

STALE3681d

4 messages, 3 authors, 2016-09-16 · open the first message on its own page

[PATCH 1/2 nf] netfilter: seqadj: Fix some possible panics of seqadj when mem is exhausted

From: <hidden>
Date: 2016-09-02 01:48:56

From: Gao Feng <redacted>

When memory is exhausted, nfct_seqadj_ext_add may fail to add the seqadj
extension. But these interface functions nf_ct_seqadj_init and
nf_ct_seq_adjust don't check if they get the valid seqadj pointer by the
nfct_seqadj, while nf_ct_seqadj_set and nf_ct_seq_offset perform that
check. So the system would be panic when nfct_seqadj_ext_add failed.

Signed-off-by: Gao Feng <redacted>
---
 net/netfilter/nf_conntrack_seqadj.c | 16 ++++++++++++++--
 1 file changed, 14 insertions(+), 2 deletions(-)
diff --git a/net/netfilter/nf_conntrack_seqadj.c b/net/netfilter/nf_conntrack_seqadj.c
index dff0f0c..2a2fd0e 100644
--- a/net/netfilter/nf_conntrack_seqadj.c
+++ b/net/netfilter/nf_conntrack_seqadj.c
@@ -16,9 +16,14 @@ int nf_ct_seqadj_init(struct nf_conn *ct, enum ip_conntrack_info ctinfo,
 	if (off == 0)
 		return 0;
 
+	seqadj = nfct_seqadj(ct);
+	if (unlikely(!seqadj)) {
+		WARN_ONCE(1, "Missing nfct_seqadj_ext_add() setup call\n");
+		return 0;
+	}
+
 	set_bit(IPS_SEQ_ADJUST_BIT, &ct->status);
 
-	seqadj = nfct_seqadj(ct);
 	this_way = &seqadj->seq[dir];
 	this_way->offset_before	 = off;
 	this_way->offset_after	 = off;
@@ -171,6 +176,11 @@ int nf_ct_seq_adjust(struct sk_buff *skb,
 	struct nf_ct_seqadj *this_way, *other_way;
 	int res;
 
+	if (unlikely(!seqadj)) {
+		WARN_ONCE(1, "Missing nfct_seqadj_ext_add() setup call\n");
+		return 0;
+	}
+
 	this_way  = &seqadj->seq[dir];
 	other_way = &seqadj->seq[!dir];
 
@@ -218,8 +228,10 @@ s32 nf_ct_seq_offset(const struct nf_conn *ct,
 	struct nf_conn_seqadj *seqadj = nfct_seqadj(ct);
 	struct nf_ct_seqadj *this_way;
 
-	if (!seqadj)
+	if (unlikely(!seqadj)) {
+		WARN_ONCE(1, "Missing nfct_seqadj_ext_add() setup call\n");
 		return 0;
+	}
 
 	this_way = &seqadj->seq[dir];
 	return after(seq, this_way->correction_pos) ?
-- 
1.9.1

Re: [PATCH 1/2 nf] netfilter: seqadj: Fix some possible panics of seqadj when mem is exhausted

From: Liping Zhang <hidden>
Date: 2016-09-02 04:50:48

Hi Feng,
2016-09-02 9:48 GMT+08:00  [off-list ref]:
quoted hunk
From: Gao Feng <redacted>
@@ -171,6 +176,11 @@ int nf_ct_seq_adjust(struct sk_buff *skb,
        struct nf_ct_seqadj *this_way, *other_way;
        int res;

+       if (unlikely(!seqadj)) {
IPS_SEQ_ADJUST_BIT will be tested before we call nf_ct_seq_adjust(),
so I think seqadj
will never be NULL here.
quoted hunk
+               WARN_ONCE(1, "Missing nfct_seqadj_ext_add() setup call\n");
+               return 0;
+       }
+
        this_way  = &seqadj->seq[dir];
        other_way = &seqadj->seq[!dir];
@@ -218,8 +228,10 @@ s32 nf_ct_seq_offset(const struct nf_conn *ct,
        struct nf_conn_seqadj *seqadj = nfct_seqadj(ct);
        struct nf_ct_seqadj *this_way;

-       if (!seqadj)
+       if (unlikely(!seqadj)) {
+               WARN_ONCE(1, "Missing nfct_seqadj_ext_add() setup call\n");
But in nf_ct_seq_offset, seqadj is likely to be NULL, see the function
call path:
tcp_packet->tcp_in_window->nf_ct_seq_offset, so WARN_ONCE seems unnecessary.
                return 0;
+       }

Re: [PATCH 1/2 nf] netfilter: seqadj: Fix some possible panics of seqadj when mem is exhausted

From: Gao Feng <hidden>
Date: 2016-09-02 04:57:33

Hi Liping,

On Fri, Sep 2, 2016 at 12:50 PM, Liping Zhang [off-list ref] wrote:
Hi Feng,
2016-09-02 9:48 GMT+08:00  [off-list ref]:
quoted
From: Gao Feng <redacted>
@@ -171,6 +176,11 @@ int nf_ct_seq_adjust(struct sk_buff *skb,
        struct nf_ct_seqadj *this_way, *other_way;
        int res;

+       if (unlikely(!seqadj)) {
IPS_SEQ_ADJUST_BIT will be tested before we call nf_ct_seq_adjust(),
so I think seqadj
will never be NULL here.
Thanks. I didn't check  IPS_SEQ_ADJUST_BIT  flag.
quoted
+               WARN_ONCE(1, "Missing nfct_seqadj_ext_add() setup call\n");
+               return 0;
+       }
+
        this_way  = &seqadj->seq[dir];
        other_way = &seqadj->seq[!dir];
@@ -218,8 +228,10 @@ s32 nf_ct_seq_offset(const struct nf_conn *ct,
        struct nf_conn_seqadj *seqadj = nfct_seqadj(ct);
        struct nf_ct_seqadj *this_way;

-       if (!seqadj)
+       if (unlikely(!seqadj)) {
+               WARN_ONCE(1, "Missing nfct_seqadj_ext_add() setup call\n");
But in nf_ct_seq_offset, seqadj is likely to be NULL, see the function
call path:
tcp_packet->tcp_in_window->nf_ct_seq_offset, so WARN_ONCE seems unnecessary.
quoted
                return 0;
+       }
Get it. It could be NULL.

Then only nf_ct_seqadj_init is necessary to check seqadj.
I will update this patch.

Regards
Feng

[lkp] [netfilter] 68263ddb47: WARNING: CPU: 0 PID: 1225 at net/netfilter/nf_conntrack_seqadj.c:232 nf_ct_seq_offset+0x7a/0x9a

From: kernel test robot <hidden>
Date: 2016-09-16 14:04:49

FYI, we noticed the following commit:

https://github.com/0day-ci/linux fgao-ikuai8-com/netfilter-seqadj-Fix-some-possible-panics-of-seqadj-when-mem-is-exhausted/20160902-095727
commit 68263ddb4777cc996868498e3d56f616851966d2 ("netfilter: seqadj: Fix some possible panics of seqadj when mem is exhausted")

in testcase: boot

on test machine: qemu-system-x86_64 -enable-kvm -m 320M

caused below changes:


+------------------------------------------------------------------+------------+------------+
|                                                                  | c73c248490 | 68263ddb47 |
+------------------------------------------------------------------+------------+------------+
| boot_successes                                                   | 7          | 0          |
| boot_failures                                                    | 7          | 14         |
| BUG:kernel_reboot-without-warning_in_test_stage                  | 7          |            |
| WARNING:at_net/netfilter/nf_conntrack_seqadj.c:#nf_ct_seq_offset | 0          | 14         |
| calltrace:SyS_connect                                            | 0          | 14         |
| calltrace:SyS_socketcall                                         | 0          | 14         |
| invoked_oom-killer:gfp_mask=0x                                   | 0          | 1          |
| Mem-Info                                                         | 0          | 1          |
+------------------------------------------------------------------+------------+------------+



[   22.475640] e1000: eth0 NIC Link is Up 1000 Mbps Full Duplex, Flow Control: RX
[   22.602089] Kernel tests: Boot OK!
[   23.465616] ------------[ cut here ]------------
[   23.466477] WARNING: CPU: 0 PID: 1225 at net/netfilter/nf_conntrack_seqadj.c:232 nf_ct_seq_offset+0x7a/0x9a
[   23.468458] Missing nfct_seqadj_ext_add() setup call
[   23.469319] CPU: 0 PID: 1225 Comm: busybox Not tainted 4.8.0-rc2-00241-g68263dd #1
[   23.470629] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Debian-1.8.2-1 04/01/2014
[   23.472138]  00000000 8ca4db58 8ca4db28 8a045c76 8ca4db44 89e4a2a3 000000e8 8a97c7b6
[   23.491476]  00000001 00000000 00000001 8ca4db60 89e4a2e7 00000009 00000000 8ca4db58
[   23.493027]  8b2c55b0 8ca4db74 8ca4db80 8a97c7b6 8b2c55da 000000e8 8b2c55b0 8e358000
[   23.494559] Call Trace:
[   23.495013]  [<8a045c76>] dump_stack+0x16/0x18
[   23.495777]  [<89e4a2a3>] __warn+0xaa/0xc1
[   23.496500]  [<8a97c7b6>] ? nf_ct_seq_offset+0x7a/0x9a
[   23.497392]  [<89e4a2e7>] warn_slowpath_fmt+0x2d/0x32
[   23.498270]  [<8a97c7b6>] nf_ct_seq_offset+0x7a/0x9a
[   23.499134]  [<8a97b2a3>] tcp_packet+0x63f/0xb93
[   23.499924]  [<89f39167>] ? cache_alloc_refill+0x203/0x80a
[   23.500896]  [<89e6863e>] ? preempt_count_sub+0x8f/0xd4
[   23.501824]  [<8a976d99>] ? nf_conntrack_in+0x2f9/0x53e
[   23.502747]  [<8a976dc2>] ? nf_conntrack_in+0x322/0x53e
[   23.521594]  [<89e6863e>] ? preempt_count_sub+0x8f/0xd4
[   23.522508]  [<8a976f5b>] nf_conntrack_in+0x4bb/0x53e
[   23.523399]  [<8a9e6a9a>] ipv4_conntrack_local+0x40/0x48
[   23.524338]  [<8a9729c5>] nf_iterate+0x3b/0x8e
[   23.525128]  [<8a972a5f>] nf_hook_slow+0x47/0xc7
[   23.525925]  [<8a9a47f1>] __ip_local_out+0xdb/0xea
[   23.526766]  [<8a9a3750>] ? ip_options_rcv_srr+0x30e/0x30e
[   23.527785]  [<8a9a4818>] ip_local_out+0x18/0x9e
[   23.528600]  [<8a9a4dd8>] ip_queue_xmit+0x395/0x41e
[   23.529469]  [<8a9b93cb>] tcp_transmit_skb+0x701/0x740
[   23.530420]  [<8a9bbcba>] tcp_connect+0x65a/0x6be
[   23.531247]  [<8a9bd9e3>] tcp_v4_connect+0x41d/0x45c
[   23.532115]  [<8a9d1a6c>] __inet_stream_connect+0x77/0x27e
[   23.533107]  [<89e6863e>] ? preempt_count_sub+0x8f/0xd4
[   23.534018]  [<89e4d8e1>] ? __local_bh_enable_ip+0xc4/0xea
[   23.534949]  [<8a9d1c9e>] inet_stream_connect+0x2b/0x3e
[   23.535862]  [<8a935255>] SyS_connect+0x77/0x9d
[   23.536662]  [<89f74959>] ? __fd_install+0x163/0x1c5
[   23.538079]  [<89e6863e>] ? preempt_count_sub+0x8f/0xd4





Thanks,
Xiaolong
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help