* [PATCH 1/1] netfilter: Added nfct_seqadj_ext_add() for ftp's conntrack.
@ 2025-10-14 11:43 Andrii Melnychenko
2025-10-14 12:25 ` Florian Westphal
2025-10-15 4:15 ` kernel test robot
0 siblings, 2 replies; 3+ messages in thread
From: Andrii Melnychenko @ 2025-10-14 11:43 UTC (permalink / raw)
To: pablo, kadlec, fw, phil
Cc: davem, edumazet, kuba, pabeni, horms, netfilter-devel, coreteam,
netdev, linux-kernel
There was an issue with NAT'ed ftp and replaced messages
for PASV/EPSV mode. "New" IP in the message may have a
different length that would require sequence adjustment.
Signed-off-by: Andrii Melnychenko <a.melnychenko@vyos.io>
---
net/netfilter/nf_conntrack_ftp.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/net/netfilter/nf_conntrack_ftp.c b/net/netfilter/nf_conntrack_ftp.c
index 617f744a2..555ff77f4 100644
--- a/net/netfilter/nf_conntrack_ftp.c
+++ b/net/netfilter/nf_conntrack_ftp.c
@@ -390,6 +390,8 @@ static int help(struct sk_buff *skb,
/* Until there's been traffic both ways, don't look in packets. */
if (ctinfo != IP_CT_ESTABLISHED &&
ctinfo != IP_CT_ESTABLISHED_REPLY) {
+ if (!nf_ct_is_confirmed(ct))
+ nfct_seqadj_ext_add(ct);
pr_debug("ftp: Conntrackinfo = %u\n", ctinfo);
return NF_ACCEPT;
}
--
2.43.0
^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [PATCH 1/1] netfilter: Added nfct_seqadj_ext_add() for ftp's conntrack.
2025-10-14 11:43 [PATCH 1/1] netfilter: Added nfct_seqadj_ext_add() for ftp's conntrack Andrii Melnychenko
@ 2025-10-14 12:25 ` Florian Westphal
2025-10-15 4:15 ` kernel test robot
1 sibling, 0 replies; 3+ messages in thread
From: Florian Westphal @ 2025-10-14 12:25 UTC (permalink / raw)
To: Andrii Melnychenko
Cc: pablo, kadlec, phil, davem, edumazet, kuba, pabeni, horms,
netfilter-devel, coreteam, netdev, linux-kernel
Andrii Melnychenko <a.melnychenko@vyos.io> wrote:
> There was an issue with NAT'ed ftp and replaced messages
> for PASV/EPSV mode. "New" IP in the message may have a
> different length that would require sequence adjustment.
This needs a 'Fixes' tag.
And it needs an explanation why this bug is specific to ftp.
Lastly, why is this needed in the first place?
nf_nat_ftp() sets up the expectation callback to 'nf_nat_follow_master'.
That calls nf_nat_setup_info() which is supposed to add the seqadj extension
since connection has helper and is subject to nat.
And if nat isn't active, why do we need to seqadj extension?
No NAT, no command channel address rewrites.
It would be good to have a test case for this too, the nat helpers
have 0 coverage.
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH 1/1] netfilter: Added nfct_seqadj_ext_add() for ftp's conntrack.
2025-10-14 11:43 [PATCH 1/1] netfilter: Added nfct_seqadj_ext_add() for ftp's conntrack Andrii Melnychenko
2025-10-14 12:25 ` Florian Westphal
@ 2025-10-15 4:15 ` kernel test robot
1 sibling, 0 replies; 3+ messages in thread
From: kernel test robot @ 2025-10-15 4:15 UTC (permalink / raw)
To: Andrii Melnychenko, pablo, kadlec, fw, phil
Cc: oe-kbuild-all, davem, edumazet, kuba, pabeni, horms,
netfilter-devel, coreteam, netdev, linux-kernel
Hi Andrii,
kernel test robot noticed the following build errors:
[auto build test ERROR on netfilter-nf/main]
[also build test ERROR on nf-next/master horms-ipvs/master linus/master v6.18-rc1 next-20251014]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Andrii-Melnychenko/netfilter-Added-nfct_seqadj_ext_add-for-ftp-s-conntrack/20251014-194524
base: https://git.kernel.org/pub/scm/linux/kernel/git/netfilter/nf.git main
patch link: https://lore.kernel.org/r/20251014114334.4167561-1-a.melnychenko%40vyos.io
patch subject: [PATCH 1/1] netfilter: Added nfct_seqadj_ext_add() for ftp's conntrack.
config: m68k-multi_defconfig (https://download.01.org/0day-ci/archive/20251015/202510151220.i78zzYsl-lkp@intel.com/config)
compiler: m68k-linux-gcc (GCC) 15.1.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20251015/202510151220.i78zzYsl-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202510151220.i78zzYsl-lkp@intel.com/
All errors (new ones prefixed by >>):
net/netfilter/nf_conntrack_ftp.c: In function 'help':
>> net/netfilter/nf_conntrack_ftp.c:394:25: error: implicit declaration of function 'nfct_seqadj_ext_add'; did you mean 'nf_ct_helper_ext_add'? [-Wimplicit-function-declaration]
394 | nfct_seqadj_ext_add(ct);
| ^~~~~~~~~~~~~~~~~~~
| nf_ct_helper_ext_add
vim +394 net/netfilter/nf_conntrack_ftp.c
368
369 static int help(struct sk_buff *skb,
370 unsigned int protoff,
371 struct nf_conn *ct,
372 enum ip_conntrack_info ctinfo)
373 {
374 unsigned int dataoff, datalen;
375 const struct tcphdr *th;
376 struct tcphdr _tcph;
377 const char *fb_ptr;
378 int ret;
379 u32 seq;
380 int dir = CTINFO2DIR(ctinfo);
381 unsigned int matchlen, matchoff;
382 struct nf_ct_ftp_master *ct_ftp_info = nfct_help_data(ct);
383 struct nf_conntrack_expect *exp;
384 union nf_inet_addr *daddr;
385 struct nf_conntrack_man cmd = {};
386 unsigned int i;
387 int found = 0, ends_in_nl;
388 typeof(nf_nat_ftp_hook) nf_nat_ftp;
389
390 /* Until there's been traffic both ways, don't look in packets. */
391 if (ctinfo != IP_CT_ESTABLISHED &&
392 ctinfo != IP_CT_ESTABLISHED_REPLY) {
393 if (!nf_ct_is_confirmed(ct))
> 394 nfct_seqadj_ext_add(ct);
395 pr_debug("ftp: Conntrackinfo = %u\n", ctinfo);
396 return NF_ACCEPT;
397 }
398
399 if (unlikely(skb_linearize(skb)))
400 return NF_DROP;
401
402 th = skb_header_pointer(skb, protoff, sizeof(_tcph), &_tcph);
403 if (th == NULL)
404 return NF_ACCEPT;
405
406 dataoff = protoff + th->doff * 4;
407 /* No data? */
408 if (dataoff >= skb->len) {
409 pr_debug("ftp: dataoff(%u) >= skblen(%u)\n", dataoff,
410 skb->len);
411 return NF_ACCEPT;
412 }
413 datalen = skb->len - dataoff;
414
415 /* seqadj (nat) uses ct->lock internally, nf_nat_ftp would cause deadlock */
416 spin_lock_bh(&nf_ftp_lock);
417 fb_ptr = skb->data + dataoff;
418
419 ends_in_nl = (fb_ptr[datalen - 1] == '\n');
420 seq = ntohl(th->seq) + datalen;
421
422 /* Look up to see if we're just after a \n. */
423 if (!find_nl_seq(ntohl(th->seq), ct_ftp_info, dir)) {
424 /* We're picking up this, clear flags and let it continue */
425 if (unlikely(ct_ftp_info->flags[dir] & NF_CT_FTP_SEQ_PICKUP)) {
426 ct_ftp_info->flags[dir] ^= NF_CT_FTP_SEQ_PICKUP;
427 goto skip_nl_seq;
428 }
429
430 /* Now if this ends in \n, update ftp info. */
431 pr_debug("nf_conntrack_ftp: wrong seq pos %s(%u) or %s(%u)\n",
432 ct_ftp_info->seq_aft_nl_num[dir] > 0 ? "" : "(UNSET)",
433 ct_ftp_info->seq_aft_nl[dir][0],
434 ct_ftp_info->seq_aft_nl_num[dir] > 1 ? "" : "(UNSET)",
435 ct_ftp_info->seq_aft_nl[dir][1]);
436 ret = NF_ACCEPT;
437 goto out_update_nl;
438 }
439
440 skip_nl_seq:
441 /* Initialize IP/IPv6 addr to expected address (it's not mentioned
442 in EPSV responses) */
443 cmd.l3num = nf_ct_l3num(ct);
444 memcpy(cmd.u3.all, &ct->tuplehash[dir].tuple.src.u3.all,
445 sizeof(cmd.u3.all));
446
447 for (i = 0; i < ARRAY_SIZE(search[dir]); i++) {
448 found = find_pattern(fb_ptr, datalen,
449 search[dir][i].pattern,
450 search[dir][i].plen,
451 search[dir][i].skip,
452 search[dir][i].term,
453 &matchoff, &matchlen,
454 &cmd,
455 search[dir][i].getnum);
456 if (found) break;
457 }
458 if (found == -1) {
459 /* We don't usually drop packets. After all, this is
460 connection tracking, not packet filtering.
461 However, it is necessary for accurate tracking in
462 this case. */
463 nf_ct_helper_log(skb, ct, "partial matching of `%s'",
464 search[dir][i].pattern);
465 ret = NF_DROP;
466 goto out;
467 } else if (found == 0) { /* No match */
468 ret = NF_ACCEPT;
469 goto out_update_nl;
470 }
471
472 pr_debug("conntrack_ftp: match `%.*s' (%u bytes at %u)\n",
473 matchlen, fb_ptr + matchoff,
474 matchlen, ntohl(th->seq) + matchoff);
475
476 exp = nf_ct_expect_alloc(ct);
477 if (exp == NULL) {
478 nf_ct_helper_log(skb, ct, "cannot alloc expectation");
479 ret = NF_DROP;
480 goto out;
481 }
482
483 /* We refer to the reverse direction ("!dir") tuples here,
484 * because we're expecting something in the other direction.
485 * Doesn't matter unless NAT is happening. */
486 daddr = &ct->tuplehash[!dir].tuple.dst.u3;
487
488 /* Update the ftp info */
489 if ((cmd.l3num == nf_ct_l3num(ct)) &&
490 memcmp(&cmd.u3.all, &ct->tuplehash[dir].tuple.src.u3.all,
491 sizeof(cmd.u3.all))) {
492 /* Enrico Scholz's passive FTP to partially RNAT'd ftp
493 server: it really wants us to connect to a
494 different IP address. Simply don't record it for
495 NAT. */
496 if (cmd.l3num == PF_INET) {
497 pr_debug("NOT RECORDING: %pI4 != %pI4\n",
498 &cmd.u3.ip,
499 &ct->tuplehash[dir].tuple.src.u3.ip);
500 } else {
501 pr_debug("NOT RECORDING: %pI6 != %pI6\n",
502 cmd.u3.ip6,
503 ct->tuplehash[dir].tuple.src.u3.ip6);
504 }
505
506 /* Thanks to Cristiano Lincoln Mattos
507 <lincoln@cesar.org.br> for reporting this potential
508 problem (DMZ machines opening holes to internal
509 networks, or the packet filter itself). */
510 if (!loose) {
511 ret = NF_ACCEPT;
512 goto out_put_expect;
513 }
514 daddr = &cmd.u3;
515 }
516
517 nf_ct_expect_init(exp, NF_CT_EXPECT_CLASS_DEFAULT, cmd.l3num,
518 &ct->tuplehash[!dir].tuple.src.u3, daddr,
519 IPPROTO_TCP, NULL, &cmd.u.tcp.port);
520
521 /* Now, NAT might want to mangle the packet, and register the
522 * (possibly changed) expectation itself. */
523 nf_nat_ftp = rcu_dereference(nf_nat_ftp_hook);
524 if (nf_nat_ftp && ct->status & IPS_NAT_MASK)
525 ret = nf_nat_ftp(skb, ctinfo, search[dir][i].ftptype,
526 protoff, matchoff, matchlen, exp);
527 else {
528 /* Can't expect this? Best to drop packet now. */
529 if (nf_ct_expect_related(exp, 0) != 0) {
530 nf_ct_helper_log(skb, ct, "cannot add expectation");
531 ret = NF_DROP;
532 } else
533 ret = NF_ACCEPT;
534 }
535
536 out_put_expect:
537 nf_ct_expect_put(exp);
538
539 out_update_nl:
540 /* Now if this ends in \n, update ftp info. Seq may have been
541 * adjusted by NAT code. */
542 if (ends_in_nl)
543 update_nl_seq(ct, seq, ct_ftp_info, dir, skb);
544 out:
545 spin_unlock_bh(&nf_ftp_lock);
546 return ret;
547 }
548
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2025-10-15 4:17 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-10-14 11:43 [PATCH 1/1] netfilter: Added nfct_seqadj_ext_add() for ftp's conntrack Andrii Melnychenko
2025-10-14 12:25 ` Florian Westphal
2025-10-15 4:15 ` kernel test robot
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).