On Tue, Nov 03, 2015 at 21:40 +0100, Alexandr Nedvedicky wrote:
> Hello,
>
> Patch fixes potential use-after-free in pf_table.c:pfr_set_addrs():
>
> 463 for (i = 0; i < size; i++) {
> ...
> 483 q = pfr_lookup_addr(tmpkt, &ad, 1);
> 484 if (q != NULL) {
> 485 ad.pfra_fback = PFR_FB_DUPLICATE;
> 486 goto _skip;
> 487 }
> 488 p = pfr_create_kentry(&ad);
> 489 if (p == NULL)
> 490 senderr(ENOMEM);
> 491 if (pfr_route_kentry(tmpkt, p)) {
> 492 pfr_destroy_kentry(p);
> 493 ad.pfra_fback = PFR_FB_NONE;
> 494 } else {
> 495 SLIST_INSERT_HEAD(&addq, p, pfrke_workq);
> 496 ad.pfra_fback = PFR_FB_ADDED;
> 497 xadd++;
> 498 }
> 499 if (p->pfrke_type == PFRKE_COST)
> 500 kt->pfrkt_refcntcost++;
> 501 pfr_ktable_winfo_update(kt, p);
> 502 }
> 503 _skip:
> 504 if (flags & PFR_FLAG_FEEDBACK)
> 505 if (COPYOUT(&ad, addr+i, sizeof(ad), flags))
> 506 senderr(EFAULT);
> 507 }
>
>
> the things start to go downhill if PF takes branch at 492, where `p` gets
> freed. The code jumps to 499 & 501, where PF steps to dead pointer. I think
> the
> right thing is to use goto _skip; in that branch to avoid 499 et. al.
> completely.
>
I agree.
> path is below.
>
> OK?
>
OK mikeb
> thanks and
> regards
> sasha
>
> --------8<---------------8<---------------8<------------------8<--------
>
> Index: pf_table.c
> ===================================================================
> RCS file: /cvs/src/sys/net/pf_table.c,v
> retrieving revision 1.115
> diff -u -p -r1.115 pf_table.c
> --- pf_table.c 7 Oct 2015 11:57:44 -0000 1.115
> +++ pf_table.c 3 Nov 2015 20:15:26 -0000
> @@ -491,6 +491,7 @@ pfr_set_addrs(struct pfr_table *tbl, str
> if (pfr_route_kentry(tmpkt, p)) {
> pfr_destroy_kentry(p);
> ad.pfra_fback = PFR_FB_NONE;
> + goto _skip;
> } else {
> SLIST_INSERT_HEAD(&addq, p, pfrke_workq);
> ad.pfra_fback = PFR_FB_ADDED;
>