Re: [v3] amd64: simplify TSC sync testing

2022-07-19 Thread Masato Asou
Sorry, my latest reply.

I tested your patch on my Proxmox Virtual Environment on Ryzen7 box.
It works fine for me.

OpenBSD 7.1-current (GENERIC.MP) #1: Wed Jul 20 14:15:23 JST 2022
a...@pve-obsd.my.domain:/usr/src/sys/arch/amd64/compile/GENERIC.MP
real mem = 17162952704 (16367MB)
avail mem = 16625430528 (15855MB)
random: good seed from bootblocks
mpath0 at root
scsibus0 at mpath0: 256 targets
mainbus0 at root
bios0 at mainbus0: SMBIOS rev. 2.8 @ 0xf59c0 (10 entries)
bios0: vendor SeaBIOS version "rel-1.15.0-0-g2dd4b9b3f840-prebuilt.qemu.org" 
date 04/01/2014
bios0: QEMU Standard PC (i440FX + PIIX, 1996)
acpi0 at bios0: ACPI 1.0
acpi0: sleep states S3 S4 S5
acpi0: tables DSDT FACP APIC SSDT HPET WAET
acpi0: wakeup devices
acpitimer0 at acpi0: 3579545 Hz, 24 bits
acpimadt0 at acpi0 addr 0xfee0: PC-AT compat
cpu0 at mainbus0: apid 0 (boot processor)
cpu0: Common KVM processor, 3593.56 MHz, 0f-06-01
cpu0: 
FPU,VME,DE,PSE,TSC,MSR,PAE,MCE,CX8,APIC,SEP,MTRR,PGE,MCA,CMOV,PAT,PSE36,CFLUSH,MMX,FXSR,SSE,SSE2,HTT,SSE3,CX16,x2APIC,HV,NXE,LONG,LAHF,CMPLEG
cpu0: 64KB 64b/line 2-way D-cache, 64KB 64b/line 2-way I-cache
cpu0: 512KB 64b/line 16-way L2 cache
cpu0: smt 0, core 0, package 0
mtrr: Pentium Pro MTRR support, 8 var ranges, 88 fixed ranges
cpu0: apic clock running at 999MHz
cpu1 at mainbus0: apid 1 (application processor)
cpu1: Common KVM processor, 3593.23 MHz, 0f-06-01
cpu1: 
FPU,VME,DE,PSE,TSC,MSR,PAE,MCE,CX8,APIC,SEP,MTRR,PGE,MCA,CMOV,PAT,PSE36,CFLUSH,MMX,FXSR,SSE,SSE2,HTT,SSE3,CX16,x2APIC,HV,NXE,LONG,LAHF,CMPLEG
cpu1: 64KB 64b/line 2-way D-cache, 64KB 64b/line 2-way I-cache
cpu1: 512KB 64b/line 16-way L2 cache
cpu1: smt 0, core 1, package 0
cpu2 at mainbus0: apid 2 (application processor)
cpu2: Common KVM processor, 3593.22 MHz, 0f-06-01
cpu2: 
FPU,VME,DE,PSE,TSC,MSR,PAE,MCE,CX8,APIC,SEP,MTRR,PGE,MCA,CMOV,PAT,PSE36,CFLUSH,MMX,FXSR,SSE,SSE2,HTT,SSE3,CX16,x2APIC,HV,NXE,LONG,LAHF,CMPLEG
cpu2: 64KB 64b/line 2-way D-cache, 64KB 64b/line 2-way I-cache
cpu2: 512KB 64b/line 16-way L2 cache
cpu2: smt 0, core 2, package 0
cpu3 at mainbus0: apid 3 (application processor)
cpu3: Common KVM processor, 3593.21 MHz, 0f-06-01
cpu3: 
FPU,VME,DE,PSE,TSC,MSR,PAE,MCE,CX8,APIC,SEP,MTRR,PGE,MCA,CMOV,PAT,PSE36,CFLUSH,MMX,FXSR,SSE,SSE2,HTT,SSE3,CX16,x2APIC,HV,NXE,LONG,LAHF,CMPLEG
cpu3: 64KB 64b/line 2-way D-cache, 64KB 64b/line 2-way I-cache
cpu3: 512KB 64b/line 16-way L2 cache
cpu3: smt 0, core 3, package 0
cpu4 at mainbus0: apid 4 (application processor)
cpu4: Common KVM processor, 3593.23 MHz, 0f-06-01
cpu4: 
FPU,VME,DE,PSE,TSC,MSR,PAE,MCE,CX8,APIC,SEP,MTRR,PGE,MCA,CMOV,PAT,PSE36,CFLUSH,MMX,FXSR,SSE,SSE2,HTT,SSE3,CX16,x2APIC,HV,NXE,LONG,LAHF,CMPLEG
cpu4: 64KB 64b/line 2-way D-cache, 64KB 64b/line 2-way I-cache
cpu4: 512KB 64b/line 16-way L2 cache
cpu4: smt 0, core 4, package 0
cpu5 at mainbus0: apid 5 (application processor)
cpu5: Common KVM processor, 3593.23 MHz, 0f-06-01
cpu5: 
FPU,VME,DE,PSE,TSC,MSR,PAE,MCE,CX8,APIC,SEP,MTRR,PGE,MCA,CMOV,PAT,PSE36,CFLUSH,MMX,FXSR,SSE,SSE2,HTT,SSE3,CX16,x2APIC,HV,NXE,LONG,LAHF,CMPLEG
cpu5: 64KB 64b/line 2-way D-cache, 64KB 64b/line 2-way I-cache
cpu5: 512KB 64b/line 16-way L2 cache
cpu5: smt 0, core 5, package 0
cpu6 at mainbus0: apid 6 (application processor)
cpu6: Common KVM processor, 3593.22 MHz, 0f-06-01
cpu6: 
FPU,VME,DE,PSE,TSC,MSR,PAE,MCE,CX8,APIC,SEP,MTRR,PGE,MCA,CMOV,PAT,PSE36,CFLUSH,MMX,FXSR,SSE,SSE2,HTT,SSE3,CX16,x2APIC,HV,NXE,LONG,LAHF,CMPLEG
cpu6: 64KB 64b/line 2-way D-cache, 64KB 64b/line 2-way I-cache
cpu6: 512KB 64b/line 16-way L2 cache
cpu6: smt 0, core 6, package 0
cpu7 at mainbus0: apid 7 (application processor)
cpu7: Common KVM processor, 3593.23 MHz, 0f-06-01
cpu7: 
FPU,VME,DE,PSE,TSC,MSR,PAE,MCE,CX8,APIC,SEP,MTRR,PGE,MCA,CMOV,PAT,PSE36,CFLUSH,MMX,FXSR,SSE,SSE2,HTT,SSE3,CX16,x2APIC,HV,NXE,LONG,LAHF,CMPLEG
cpu7: 64KB 64b/line 2-way D-cache, 64KB 64b/line 2-way I-cache
cpu7: 512KB 64b/line 16-way L2 cache
cpu7: smt 0, core 7, package 0
ioapic0 at mainbus0: apid 0 pa 0xfec0, version 11, 24 pins
acpihpet0 at acpi0: 1 Hz
acpiprt0 at acpi0: bus 0 (PCI0)
"ACPI0006" at acpi0 not configured
acpipci0 at acpi0 PCI0
acpicmos0 at acpi0
"PNP0A06" at acpi0 not configured
"PNP0A06" at acpi0 not configured
"PNP0A06" at acpi0 not configured
"QEMU0002" at acpi0 not configured
"ACPI0010" at acpi0 not configured
"QEMUVGID" at acpi0 not configured
acpicpu0 at acpi0: C1(@1 halt!)
acpicpu1 at acpi0: C1(@1 halt!)
acpicpu2 at acpi0: C1(@1 halt!)
acpicpu3 at acpi0: C1(@1 halt!)
acpicpu4 at acpi0: C1(@1 halt!)
acpicpu5 at acpi0: C1(@1 halt!)
acpicpu6 at acpi0: C1(@1 halt!)
acpicpu7 at acpi0: C1(@1 halt!)
pvbus0 at mainbus0: KVM
pvclock0 at pvbus0
pci0 at mainbus0 bus 0
pchb0 at pci0 dev 0 function 0 "Intel 82441FX" rev 0x02
pcib0 at pci0 dev 1 function 0 "Intel 82371SB ISA" rev 0x00
pciide0 at pci0 dev 1 function 1 "Intel 82371SB IDE" rev 0x00: DMA, channel 0 
wired to compatibility, channel 1 wired to compatibility
wd0 at pciide0 channel 0 drive 0: 
wd0: 16-sector PIO, LBA48, 65

Re: pf: pool for pf_anchor

2022-07-19 Thread Alexander Bluhm
On Tue, Jul 19, 2022 at 07:18:54PM +0200, Moritz Buhl wrote:
> A solution would be to move the allocation of the pf_anchor struct
> into a pool.  One final question would be regarding the size of the
> hiwat or hardlimit.  Any suggestions?

10 seems way to low.  We want to limit resource abuse.  But regular
users should never hit this.  Especially existing configurations
should still work after upgrade.

Perhaps 512 anchors.  Noone shoul ever need more than 512 anchors :-)

> Any other comments?

Please do not use PR_WAITOK in pool_init() unless you know what you
are doing.  I think it should work, but who knows.  The other pf
pools have 0 flags, just use that.

Comment says rs_malloc is needed to compile pfctl.  Have you tested
that?

Replacing M_WAITOK|M_CANFAIL|M_ZERO with PR_NOWAIT|PR_ZERO looks
wrong.  PR_WAITOK|PR_LIMITFAIL|PR_ZERO should do something equivalent.

I am not sure if pf_find_anchor() should fail if the limit is hit.
It uses only a temporary buffer.  All calls to pf_find_ruleset()
should be checked whether permanent failure, after the limit has
been reached, is what we want.  Or we keep the malloc there?

bluhm

> Index: sys/net/pf.c
> ===
> RCS file: /mount/openbsd/cvs/src/sys/net/pf.c,v
> retrieving revision 1.1135
> diff -u -p -r1.1135 pf.c
> --- sys/net/pf.c  28 Jun 2022 13:48:06 -  1.1135
> +++ sys/net/pf.c  19 Jul 2022 11:34:23 -
> @@ -269,6 +269,7 @@ void   pf_log_matches(struct pf_pdesc 
> *
>  
>  extern struct pool pfr_ktable_pl;
>  extern struct pool pfr_kentry_pl;
> +extern struct pool pf_anchor_pl;
>  
>  struct pf_pool_limit pf_pool_limits[PF_LIMIT_MAX] = {
>   { &pf_state_pl, PFSTATE_HIWAT, PFSTATE_HIWAT },
> @@ -276,7 +277,8 @@ struct pf_pool_limit pf_pool_limits[PF_L
>   { &pf_frent_pl, PFFRAG_FRENT_HIWAT, PFFRAG_FRENT_HIWAT },
>   { &pfr_ktable_pl, PFR_KTABLE_HIWAT, PFR_KTABLE_HIWAT },
>   { &pfr_kentry_pl, PFR_KENTRY_HIWAT, PFR_KENTRY_HIWAT },
> - { &pf_pktdelay_pl, PF_PKTDELAY_MAXPKTS, PF_PKTDELAY_MAXPKTS }
> + { &pf_pktdelay_pl, PF_PKTDELAY_MAXPKTS, PF_PKTDELAY_MAXPKTS },
> + { &pf_anchor_pl, PF_ANCHOR_HIWAT, PF_ANCHOR_HIWAT }
>  };
>  
>  #define BOUND_IFACE(r, k) \
> Index: sys/net/pf_ioctl.c
> ===
> RCS file: /mount/openbsd/cvs/src/sys/net/pf_ioctl.c,v
> retrieving revision 1.382
> diff -u -p -r1.382 pf_ioctl.c
> --- sys/net/pf_ioctl.c26 Jun 2022 11:37:08 -  1.382
> +++ sys/net/pf_ioctl.c19 Jul 2022 16:56:23 -
> @@ -191,6 +191,8 @@ pfattach(int num)
>   IPL_SOFTNET, 0, "pftag", NULL);
>   pool_init(&pf_pktdelay_pl, sizeof(struct pf_pktdelay), 0,
>   IPL_SOFTNET, 0, "pfpktdelay", NULL);
> + pool_init(&pf_anchor_pl, sizeof(struct pf_anchor), 0,
> + IPL_SOFTNET, PR_WAITOK, "pfanchor", NULL);
>  
>   hfsc_initialize();
>   pfr_initialize();
> @@ -200,6 +202,8 @@ pfattach(int num)
>  
>   pool_sethardlimit(pf_pool_limits[PF_LIMIT_STATES].pp,
>   pf_pool_limits[PF_LIMIT_STATES].limit, NULL, 0);
> + pool_sethardlimit(pf_pool_limits[PF_LIMIT_ANCHORS].pp,
> + pf_pool_limits[PF_LIMIT_ANCHORS].limit, NULL, 0);
>  
>   if (physmem <= atop(100*1024*1024))
>   pf_pool_limits[PF_LIMIT_TABLE_ENTRIES].limit =
> Index: sys/net/pf_ruleset.c
> ===
> RCS file: /mount/openbsd/cvs/src/sys/net/pf_ruleset.c,v
> retrieving revision 1.18
> diff -u -p -r1.18 pf_ruleset.c
> --- sys/net/pf_ruleset.c  27 Dec 2018 16:54:01 -  1.18
> +++ sys/net/pf_ruleset.c  19 Jul 2022 12:56:35 -
> @@ -40,6 +40,7 @@
>  #ifdef _KERNEL
>  #include 
>  #include 
> +#include 
>  #endif /* _KERNEL */
>  #include 
>  
> @@ -55,6 +56,7 @@
>  #endif /* INET6 */
>  
>  
> +struct pool  pf_anchor_pl;
>  #ifdef _KERNEL
>  #define rs_malloc(x) malloc(x, M_TEMP, M_WAITOK|M_CANFAIL|M_ZERO)
>  #define rs_free(x, siz)  free(x, M_TEMP, siz)
> @@ -107,12 +109,12 @@ pf_find_anchor(const char *path)
>  {
>   struct pf_anchor*key, *found;
>  
> - key = rs_malloc(sizeof(*key));
> + key = pool_get(&pf_anchor_pl, PR_NOWAIT | PR_ZERO);
>   if (key == NULL)
>   return (NULL);
>   strlcpy(key->path, path, sizeof(key->path));
>   found = RB_FIND(pf_anchor_global, &pf_anchors, key);
> - rs_free(key, sizeof(*key));
> + pool_put(&pf_anchor_pl, key);
>   return (found);
>  }
>  
> @@ -184,7 +186,7 @@ pf_create_anchor(struct pf_anchor *paren
>   ((parent != NULL) && (strlen(parent->path) >= PF_ANCHOR_MAXPATH)))
>   return (NULL);
>  
> - anchor = rs_malloc(sizeof(*anchor));
> + anchor = pool_get(&pf_anchor_pl, PR_NOWAIT | PR_ZERO);
>   if (anchor == NULL)
>   return (NULL);
>  
> @@ -204,7 +206,7 @@ pf_create_anchor(struct pf_anchor *paren
>

pf: pool for pf_anchor

2022-07-19 Thread Moritz Buhl
Dear tech@,

I am investigating a syzkaller reproducer found in the
"no output from test machine (7)" crashes:
https://syzkaller.appspot.com/bug?id=d93e92fde3857c69df2cf46b4244d9814c4318a7
https://syzkaller.appspot.com/text?tag=ReproC&x=116ee2e008

The code calls DIOCXBEGIN, with different anchor names
until the malloc bucket for size 2048 fills up.
So the following reproducer does the same:

#include 
#include 
#include 

#include 
#include 
#include 
#include 

int calls;
void
iterate(char *str)
{
char *end = str + 64;
*end = '\0';
while (*str == '\255') {
*str = '\1';
str++;
}

if (str == end) return;

if (*str == '\0') *str = '\1';
*str = ++*str;
}

int
main(void)
{
struct pfioc_trans trans;
struct pfioc_trans_e elem;
int fd, ret;
char it[64] = "\0";

fd = open("/dev/pf", O_RDWR);

while (1) {
trans.size = 1;
trans.esize = 0x408;
trans.array = &elem;
elem.type = 0;
iterate(it);
strcpy(elem.anchor, it);
elem.ticket = 0;
calls++;
if (ioctl(fd, DIOCXBEGIN, &trans) == -1)
err(1, "icoctl: %d calls, '%s'", calls, elem.anchor);
}
}

A solution would be to move the allocation of the pf_anchor struct
into a pool.  One final question would be regarding the size of the
hiwat or hardlimit.  Any suggestions?

Any other comments?

mbuhl


Index: sys/net/pf.c
===
RCS file: /mount/openbsd/cvs/src/sys/net/pf.c,v
retrieving revision 1.1135
diff -u -p -r1.1135 pf.c
--- sys/net/pf.c28 Jun 2022 13:48:06 -  1.1135
+++ sys/net/pf.c19 Jul 2022 11:34:23 -
@@ -269,6 +269,7 @@ void pf_log_matches(struct pf_pdesc 
*
 
 extern struct pool pfr_ktable_pl;
 extern struct pool pfr_kentry_pl;
+extern struct pool pf_anchor_pl;
 
 struct pf_pool_limit pf_pool_limits[PF_LIMIT_MAX] = {
{ &pf_state_pl, PFSTATE_HIWAT, PFSTATE_HIWAT },
@@ -276,7 +277,8 @@ struct pf_pool_limit pf_pool_limits[PF_L
{ &pf_frent_pl, PFFRAG_FRENT_HIWAT, PFFRAG_FRENT_HIWAT },
{ &pfr_ktable_pl, PFR_KTABLE_HIWAT, PFR_KTABLE_HIWAT },
{ &pfr_kentry_pl, PFR_KENTRY_HIWAT, PFR_KENTRY_HIWAT },
-   { &pf_pktdelay_pl, PF_PKTDELAY_MAXPKTS, PF_PKTDELAY_MAXPKTS }
+   { &pf_pktdelay_pl, PF_PKTDELAY_MAXPKTS, PF_PKTDELAY_MAXPKTS },
+   { &pf_anchor_pl, PF_ANCHOR_HIWAT, PF_ANCHOR_HIWAT }
 };
 
 #define BOUND_IFACE(r, k) \
Index: sys/net/pf_ioctl.c
===
RCS file: /mount/openbsd/cvs/src/sys/net/pf_ioctl.c,v
retrieving revision 1.382
diff -u -p -r1.382 pf_ioctl.c
--- sys/net/pf_ioctl.c  26 Jun 2022 11:37:08 -  1.382
+++ sys/net/pf_ioctl.c  19 Jul 2022 16:56:23 -
@@ -191,6 +191,8 @@ pfattach(int num)
IPL_SOFTNET, 0, "pftag", NULL);
pool_init(&pf_pktdelay_pl, sizeof(struct pf_pktdelay), 0,
IPL_SOFTNET, 0, "pfpktdelay", NULL);
+   pool_init(&pf_anchor_pl, sizeof(struct pf_anchor), 0,
+   IPL_SOFTNET, PR_WAITOK, "pfanchor", NULL);
 
hfsc_initialize();
pfr_initialize();
@@ -200,6 +202,8 @@ pfattach(int num)
 
pool_sethardlimit(pf_pool_limits[PF_LIMIT_STATES].pp,
pf_pool_limits[PF_LIMIT_STATES].limit, NULL, 0);
+   pool_sethardlimit(pf_pool_limits[PF_LIMIT_ANCHORS].pp,
+   pf_pool_limits[PF_LIMIT_ANCHORS].limit, NULL, 0);
 
if (physmem <= atop(100*1024*1024))
pf_pool_limits[PF_LIMIT_TABLE_ENTRIES].limit =
Index: sys/net/pf_ruleset.c
===
RCS file: /mount/openbsd/cvs/src/sys/net/pf_ruleset.c,v
retrieving revision 1.18
diff -u -p -r1.18 pf_ruleset.c
--- sys/net/pf_ruleset.c27 Dec 2018 16:54:01 -  1.18
+++ sys/net/pf_ruleset.c19 Jul 2022 12:56:35 -
@@ -40,6 +40,7 @@
 #ifdef _KERNEL
 #include 
 #include 
+#include 
 #endif /* _KERNEL */
 #include 
 
@@ -55,6 +56,7 @@
 #endif /* INET6 */
 
 
+struct poolpf_anchor_pl;
 #ifdef _KERNEL
 #define rs_malloc(x)   malloc(x, M_TEMP, M_WAITOK|M_CANFAIL|M_ZERO)
 #define rs_free(x, siz)free(x, M_TEMP, siz)
@@ -107,12 +109,12 @@ pf_find_anchor(const char *path)
 {
struct pf_anchor*key, *found;
 
-   key = rs_malloc(sizeof(*key));
+   key = pool_get(&pf_anchor_pl, PR_NOWAIT | PR_ZERO);
if (key == NULL)
return (NULL);
strlcpy(key->path, path, sizeof(key->path));
found = RB_FIND(pf_anchor_global, &pf_anchors, key);
-   rs_free(key, sizeof(*key));
+   pool_put(&pf_anchor_pl, key);
return (found);
 }
 
@@ -184,7 +186,7 @@ pf_create_anchor(struct pf_anchor *paren
((parent != NULL) && (strlen(parent->path

Re: bgpd aspath_extract overflow check

2022-07-19 Thread Claudio Jeker
On Tue, Jul 19, 2022 at 12:31:47PM +0200, Theo Buehler wrote:
> On Tue, Jul 19, 2022 at 11:43:25AM +0200, Claudio Jeker wrote:
> > aspath_extract() should do at least a minimal overflow check and not
> > access memory after the segment. Can't use fatalx here because bgpctl
> > also uses this function. Instead return 0, that is an invalid ASN.
> > No code will check the return value but that is fine since all callers
> > ensure that pos does not overflow.
> 
> There are a few calls of the form
> 
>   as = aspath_extract(seg, seg_len - 1)
> 
> where seg_len = ptr[1], so a priori pos == -1 seems possible. Should the
> check not be
> 
>   if (pos < 0 || pos >= ptr[1])
>   return 0;
> 
> to exclude an access at ptr[-2]?

Makes sense. It is again not really an issue because aspath_verify()
filters those ASPATHs out and aspath_extract() should only be called on
valid ASPATHs.

I will commit this with the pos < 0 check.
 
> > 
> > -- 
> > :wq Claudio
> > 
> > Index: util.c
> > ===
> > RCS file: /cvs/src/usr.sbin/bgpd/util.c,v
> > retrieving revision 1.69
> > diff -u -p -r1.69 util.c
> > --- util.c  28 Jun 2022 05:49:05 -  1.69
> > +++ util.c  28 Jun 2022 08:31:10 -
> > @@ -364,7 +364,7 @@ aspath_strlen(void *data, uint16_t len)
> >  /*
> >   * Extract the asnum out of the as segment at the specified position.
> >   * Direct access is not possible because of non-aligned reads.
> > - * ATTENTION: no bounds checks are done.
> > + * Only works on verified 4-byte AS paths.
> >   */
> >  uint32_t
> >  aspath_extract(const void *seg, int pos)
> > @@ -372,6 +372,9 @@ aspath_extract(const void *seg, int pos)
> > const u_char*ptr = seg;
> > uint32_t as;
> >  
> > +   /* minimal overflow check, return 0 since that is an invalid ASN */
> > +   if (pos >= ptr[1])
> > +   return (0);
> > ptr += 2 + sizeof(uint32_t) * pos;
> > memcpy(&as, ptr, sizeof(uint32_t));
> > return (ntohl(as));
> > 
> 

-- 
:wq Claudio



Re: bgpd aspath_extract overflow check

2022-07-19 Thread Theo Buehler
On Tue, Jul 19, 2022 at 11:43:25AM +0200, Claudio Jeker wrote:
> aspath_extract() should do at least a minimal overflow check and not
> access memory after the segment. Can't use fatalx here because bgpctl
> also uses this function. Instead return 0, that is an invalid ASN.
> No code will check the return value but that is fine since all callers
> ensure that pos does not overflow.

There are a few calls of the form

as = aspath_extract(seg, seg_len - 1)

where seg_len = ptr[1], so a priori pos == -1 seems possible. Should the
check not be

if (pos < 0 || pos >= ptr[1])
return 0;

to exclude an access at ptr[-2]?

> 
> -- 
> :wq Claudio
> 
> Index: util.c
> ===
> RCS file: /cvs/src/usr.sbin/bgpd/util.c,v
> retrieving revision 1.69
> diff -u -p -r1.69 util.c
> --- util.c28 Jun 2022 05:49:05 -  1.69
> +++ util.c28 Jun 2022 08:31:10 -
> @@ -364,7 +364,7 @@ aspath_strlen(void *data, uint16_t len)
>  /*
>   * Extract the asnum out of the as segment at the specified position.
>   * Direct access is not possible because of non-aligned reads.
> - * ATTENTION: no bounds checks are done.
> + * Only works on verified 4-byte AS paths.
>   */
>  uint32_t
>  aspath_extract(const void *seg, int pos)
> @@ -372,6 +372,9 @@ aspath_extract(const void *seg, int pos)
>   const u_char*ptr = seg;
>   uint32_t as;
>  
> + /* minimal overflow check, return 0 since that is an invalid ASN */
> + if (pos >= ptr[1])
> + return (0);
>   ptr += 2 + sizeof(uint32_t) * pos;
>   memcpy(&as, ptr, sizeof(uint32_t));
>   return (ntohl(as));
> 



Re: bgpd name struct kroute_full vars kf

2022-07-19 Thread Theo Buehler
On Tue, Jul 19, 2022 at 12:08:40PM +0200, Claudio Jeker wrote:
> Use kf for all struct kroute_full variables in bgpd. This makes the code
> more consistent.

ok



bgpd name struct kroute_full vars kf

2022-07-19 Thread Claudio Jeker
Use kf for all struct kroute_full variables in bgpd. This makes the code
more consistent.

-- 
:wq Claudio

Index: kroute.c
===
RCS file: /cvs/src/usr.sbin/bgpd/kroute.c,v
retrieving revision 1.273
diff -u -p -r1.273 kroute.c
--- kroute.c18 Jul 2022 23:09:44 -  1.273
+++ kroute.c19 Jul 2022 10:05:51 -
@@ -471,22 +471,22 @@ ktable_exists(u_int rtableid, u_int *rdo
 }
 
 int
-kr_change(u_int rtableid, struct kroute_full *kl)
+kr_change(u_int rtableid, struct kroute_full *kf)
 {
struct ktable   *kt;
 
if ((kt = ktable_get(rtableid)) == NULL)
/* too noisy during reloads, just ignore */
return (0);
-   switch (kl->prefix.aid) {
+   switch (kf->prefix.aid) {
case AID_INET:
-   return (kr4_change(kt, kl));
+   return (kr4_change(kt, kf));
case AID_INET6:
-   return (kr6_change(kt, kl));
+   return (kr6_change(kt, kf));
case AID_VPN_IPv4:
-   return (krVPN4_change(kt, kl));
+   return (krVPN4_change(kt, kf));
case AID_VPN_IPv6:
-   return (krVPN6_change(kt, kl));
+   return (krVPN6_change(kt, kf));
}
log_warnx("%s: not handled AID", __func__);
return (-1);
@@ -764,7 +764,7 @@ krVPN6_change(struct ktable *kt, struct 
 }
 
 int
-kr_delete(u_int rtableid, struct kroute_full *kl)
+kr_delete(u_int rtableid, struct kroute_full *kf)
 {
struct ktable   *kt;
 
@@ -772,15 +772,15 @@ kr_delete(u_int rtableid, struct kroute_
/* too noisy during reloads, just ignore */
return (0);
 
-   switch (kl->prefix.aid) {
+   switch (kf->prefix.aid) {
case AID_INET:
-   return (kr4_delete(kt, kl));
+   return (kr4_delete(kt, kf));
case AID_INET6:
-   return (kr6_delete(kt, kl));
+   return (kr6_delete(kt, kf));
case AID_VPN_IPv4:
-   return (krVPN4_delete(kt, kl));
+   return (krVPN4_delete(kt, kf));
case AID_VPN_IPv6:
-   return (krVPN6_delete(kt, kl));
+   return (krVPN6_delete(kt, kf));
}
log_warnx("%s: not handled AID", __func__);
return (-1);
@@ -819,11 +819,11 @@ kr_flush(u_int rtableid)
 }
 
 int
-kr4_delete(struct ktable *kt, struct kroute_full *kl)
+kr4_delete(struct ktable *kt, struct kroute_full *kf)
 {
struct kroute   *kr;
 
-   if ((kr = kroute_find(kt, &kl->prefix, kl->prefixlen,
+   if ((kr = kroute_find(kt, &kf->prefix, kf->prefixlen,
RTP_MINE)) == NULL)
return (0);
 
@@ -839,11 +839,11 @@ kr4_delete(struct ktable *kt, struct kro
 }
 
 int
-kr6_delete(struct ktable *kt, struct kroute_full *kl)
+kr6_delete(struct ktable *kt, struct kroute_full *kf)
 {
struct kroute6  *kr6;
 
-   if ((kr6 = kroute6_find(kt, &kl->prefix, kl->prefixlen,
+   if ((kr6 = kroute6_find(kt, &kf->prefix, kf->prefixlen,
RTP_MINE)) == NULL)
return (0);
 
@@ -859,11 +859,11 @@ kr6_delete(struct ktable *kt, struct kro
 }
 
 int
-krVPN4_delete(struct ktable *kt, struct kroute_full *kl)
+krVPN4_delete(struct ktable *kt, struct kroute_full *kf)
 {
struct kroute   *kr;
 
-   if ((kr = kroute_find(kt, &kl->prefix, kl->prefixlen,
+   if ((kr = kroute_find(kt, &kf->prefix, kf->prefixlen,
RTP_MINE)) == NULL)
return (0);
 
@@ -879,11 +879,11 @@ krVPN4_delete(struct ktable *kt, struct 
 }
 
 int
-krVPN6_delete(struct ktable *kt, struct kroute_full *kl)
+krVPN6_delete(struct ktable *kt, struct kroute_full *kf)
 {
struct kroute6  *kr6;
 
-   if ((kr6 = kroute6_find(kt, &kl->prefix, kl->prefixlen,
+   if ((kr6 = kroute6_find(kt, &kf->prefix, kf->prefixlen,
RTP_MINE)) == NULL)
return (0);
 
@@ -3042,7 +3042,7 @@ fetchtable(struct ktable *kt)
int  mib[7];
char*buf = NULL, *next, *lim;
struct rt_msghdr*rtm;
-   struct kroute_full   kl;
+   struct kroute_full   kf;
struct kroute   *kr;
struct kroute6  *kr6;
 
@@ -3079,49 +3079,49 @@ fetchtable(struct ktable *kt)
if (rtm->rtm_version != RTM_VERSION)
continue;
 
-   if (dispatch_rtmsg_addr(rtm, &kl) == -1)
+   if (dispatch_rtmsg_addr(rtm, &kf) == -1)
continue;
 
-   if (kl.prefix.aid == AID_INET) {
+   if (kf.prefix.aid == AID_INET) {
if ((kr = calloc(1, sizeof(*kr))) == NULL) {
log_warn("%s", __func__);
return (-1);
}
-   kr->prefix.s_addr = kl.prefix.v4.s_addr;
-   kr->pr

bgpd aspath_extract overflow check

2022-07-19 Thread Claudio Jeker
aspath_extract() should do at least a minimal overflow check and not
access memory after the segment. Can't use fatalx here because bgpctl
also uses this function. Instead return 0, that is an invalid ASN.
No code will check the return value but that is fine since all callers
ensure that pos does not overflow.

-- 
:wq Claudio

Index: util.c
===
RCS file: /cvs/src/usr.sbin/bgpd/util.c,v
retrieving revision 1.69
diff -u -p -r1.69 util.c
--- util.c  28 Jun 2022 05:49:05 -  1.69
+++ util.c  28 Jun 2022 08:31:10 -
@@ -364,7 +364,7 @@ aspath_strlen(void *data, uint16_t len)
 /*
  * Extract the asnum out of the as segment at the specified position.
  * Direct access is not possible because of non-aligned reads.
- * ATTENTION: no bounds checks are done.
+ * Only works on verified 4-byte AS paths.
  */
 uint32_t
 aspath_extract(const void *seg, int pos)
@@ -372,6 +372,9 @@ aspath_extract(const void *seg, int pos)
const u_char*ptr = seg;
uint32_t as;
 
+   /* minimal overflow check, return 0 since that is an invalid ASN */
+   if (pos >= ptr[1])
+   return (0);
ptr += 2 + sizeof(uint32_t) * pos;
memcpy(&as, ptr, sizeof(uint32_t));
return (ntohl(as));