On Mon, Apr 24, 2023 at 06:31:03PM +0300, Vitaliy Makkoveev wrote: > ... and use it to protect route labels storage. This time it is not > clean, which lock protects it because we holding kernel and net locks in > various combinations while accessing it. I see no reason to put kernel > lock to all the places. Also netlock could not be used, because rtfree() > which calls rtlabel_unref() has unknown netlock state within. > > This new `rtlabel_mtx' mutex(9) protects `rt_labels' list and `label' > entry dereference. Since we don't export 'rt_label' structure, I want to > keep this lock private to net/route.c. For this reason rtlabel_id2name() > now copies label string to externally passed buffer instead of returning > address of `rt_labels' list data. This is the way which rtlabel_id2sa() > already works. > > ok?
I did run this though perform test. Full regress still running due to unrelated tree breakage. I don't expect fallout. OK bluhm@ > Index: sys/net/if.c > =================================================================== > RCS file: /cvs/src/sys/net/if.c,v > retrieving revision 1.692 > diff -u -p -r1.692 if.c > --- sys/net/if.c 22 Apr 2023 04:39:46 -0000 1.692 > +++ sys/net/if.c 24 Apr 2023 15:11:33 -0000 > @@ -2383,7 +2383,6 @@ ifioctl_get(u_long cmd, caddr_t data) > char ifrtlabelbuf[RTLABEL_LEN]; > int error = 0; > size_t bytesdone; > - const char *label; > > switch(cmd) { > case SIOCGIFCONF: > @@ -2458,9 +2457,8 @@ ifioctl_get(u_long cmd, caddr_t data) > break; > > case SIOCGIFRTLABEL: > - if (ifp->if_rtlabelid && > - (label = rtlabel_id2name(ifp->if_rtlabelid)) != NULL) { > - strlcpy(ifrtlabelbuf, label, RTLABEL_LEN); > + if (ifp->if_rtlabelid && rtlabel_id2name(ifp->if_rtlabelid, > + ifrtlabelbuf, RTLABEL_LEN) != NULL) { > error = copyoutstr(ifrtlabelbuf, ifr->ifr_data, > RTLABEL_LEN, &bytesdone); > } else > Index: sys/net/pf_ioctl.c > =================================================================== > RCS file: /cvs/src/sys/net/pf_ioctl.c,v > retrieving revision 1.397 > diff -u -p -r1.397 pf_ioctl.c > --- sys/net/pf_ioctl.c 6 Jan 2023 17:44:34 -0000 1.397 > +++ sys/net/pf_ioctl.c 24 Apr 2023 15:11:33 -0000 > @@ -491,14 +491,10 @@ pf_rtlabel_remove(struct pf_addr_wrap *a > void > pf_rtlabel_copyout(struct pf_addr_wrap *a) > { > - const char *name; > - > if (a->type == PF_ADDR_RTLABEL && a->v.rtlabel) { > - if ((name = rtlabel_id2name(a->v.rtlabel)) == NULL) > + if (rtlabel_id2name(a->v.rtlabel, a->v.rtlabelname, > + sizeof(a->v.rtlabelname)) == NULL) > strlcpy(a->v.rtlabelname, "?", > - sizeof(a->v.rtlabelname)); > - else > - strlcpy(a->v.rtlabelname, name, > sizeof(a->v.rtlabelname)); > } > } > Index: sys/net/route.c > =================================================================== > RCS file: /cvs/src/sys/net/route.c,v > retrieving revision 1.416 > diff -u -p -r1.416 route.c > --- sys/net/route.c 28 Jan 2023 10:17:16 -0000 1.416 > +++ sys/net/route.c 24 Apr 2023 15:11:33 -0000 > @@ -113,6 +113,7 @@ > #include <sys/queue.h> > #include <sys/pool.h> > #include <sys/atomic.h> > +#include <sys/mutex.h> > > #include <net/if.h> > #include <net/if_var.h> > @@ -137,6 +138,12 @@ > #include <net/bfd.h> > #endif > > +/* > + * Locks used to protect struct members: > + * I immutable after creation > + * L rtlabel_mtx > + */ > + > #define ROUNDUP(a) (a>0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : > sizeof(long)) > > /* Give some jitter to hash, to avoid synchronization between routers. */ > @@ -163,13 +170,15 @@ static int rt_copysa(struct sockaddr *, > #define LABELID_MAX 50000 > > struct rt_label { > - TAILQ_ENTRY(rt_label) rtl_entry; > - char rtl_name[RTLABEL_LEN]; > - u_int16_t rtl_id; > - int rtl_ref; > + TAILQ_ENTRY(rt_label) rtl_entry; /* [L] */ > + char rtl_name[RTLABEL_LEN]; /* [I] */ > + u_int16_t rtl_id; /* [I] */ > + int rtl_ref; /* [L] */ > }; > > -TAILQ_HEAD(rt_labels, rt_label) rt_labels = > TAILQ_HEAD_INITIALIZER(rt_labels); > +TAILQ_HEAD(rt_labels, rt_label) rt_labels = > + TAILQ_HEAD_INITIALIZER(rt_labels); /* [L] */ > +struct mutex rtlabel_mtx = MUTEX_INITIALIZER(IPL_NET); > > void > route_init(void) > @@ -1603,15 +1612,17 @@ u_int16_t > rtlabel_name2id(char *name) > { > struct rt_label *label, *p; > - u_int16_t new_id = 1; > + u_int16_t new_id = 1, id = 0; > > if (!name[0]) > return (0); > > + mtx_enter(&rtlabel_mtx); > TAILQ_FOREACH(label, &rt_labels, rtl_entry) > if (strcmp(name, label->rtl_name) == 0) { > label->rtl_ref++; > - return (label->rtl_id); > + id = label->rtl_id; > + goto out; > } > > /* > @@ -1625,11 +1636,11 @@ rtlabel_name2id(char *name) > new_id = p->rtl_id + 1; > } > if (new_id > LABELID_MAX) > - return (0); > + goto out; > > label = malloc(sizeof(*label), M_RTABLE, M_NOWAIT|M_ZERO); > if (label == NULL) > - return (0); > + goto out; > strlcpy(label->rtl_name, name, sizeof(label->rtl_name)); > label->rtl_id = new_id; > label->rtl_ref++; > @@ -1639,14 +1650,20 @@ rtlabel_name2id(char *name) > else /* either list empty or no free slot in between */ > TAILQ_INSERT_TAIL(&rt_labels, label, rtl_entry); > > - return (label->rtl_id); > + id = label->rtl_id; > +out: > + mtx_leave(&rtlabel_mtx); > + > + return (id); > } > > const char * > -rtlabel_id2name(u_int16_t id) > +rtlabel_id2name_locked(u_int16_t id) > { > struct rt_label *label; > > + MUTEX_ASSERT_LOCKED(&rtlabel_mtx); > + > TAILQ_FOREACH(label, &rt_labels, rtl_entry) > if (label->rtl_id == id) > return (label->rtl_name); > @@ -1654,18 +1671,44 @@ rtlabel_id2name(u_int16_t id) > return (NULL); > } > > +const char * > +rtlabel_id2name(u_int16_t id, char *rtlabelbuf, size_t sz) > +{ > + const char *label; > + > + if (id == 0) > + return (NULL); > + > + mtx_enter(&rtlabel_mtx); > + if ((label = rtlabel_id2name_locked(id)) != NULL) > + strlcpy(rtlabelbuf, label, sz); > + mtx_leave(&rtlabel_mtx); > + > + if (label == NULL) > + return (NULL); > + > + return (rtlabelbuf); > +} > + > struct sockaddr * > rtlabel_id2sa(u_int16_t labelid, struct sockaddr_rtlabel *sa_rl) > { > const char *label; > > - if (labelid == 0 || (label = rtlabel_id2name(labelid)) == NULL) > + if (labelid == 0) > return (NULL); > > - bzero(sa_rl, sizeof(*sa_rl)); > - sa_rl->sr_len = sizeof(*sa_rl); > - sa_rl->sr_family = AF_UNSPEC; > - strlcpy(sa_rl->sr_label, label, sizeof(sa_rl->sr_label)); > + mtx_enter(&rtlabel_mtx); > + if ((label = rtlabel_id2name_locked(labelid)) != NULL) { > + bzero(sa_rl, sizeof(*sa_rl)); > + sa_rl->sr_len = sizeof(*sa_rl); > + sa_rl->sr_family = AF_UNSPEC; > + strlcpy(sa_rl->sr_label, label, sizeof(sa_rl->sr_label)); > + } > + mtx_leave(&rtlabel_mtx); > + > + if (label == NULL) > + return (NULL); > > return ((struct sockaddr *)sa_rl); > } > @@ -1678,6 +1721,7 @@ rtlabel_unref(u_int16_t id) > if (id == 0) > return; > > + mtx_enter(&rtlabel_mtx); > TAILQ_FOREACH_SAFE(p, &rt_labels, rtl_entry, next) { > if (id == p->rtl_id) { > if (--p->rtl_ref == 0) { > @@ -1687,6 +1731,7 @@ rtlabel_unref(u_int16_t id) > break; > } > } > + mtx_leave(&rtlabel_mtx); > } > > int > Index: sys/net/route.h > =================================================================== > RCS file: /cvs/src/sys/net/route.h,v > retrieving revision 1.198 > diff -u -p -r1.198 route.h > --- sys/net/route.h 28 Jan 2023 10:17:16 -0000 1.198 > +++ sys/net/route.h 24 Apr 2023 15:11:33 -0000 > @@ -416,7 +416,8 @@ struct rttimer_queue { > int rtq_timeout; /* [T] */ > }; > > -const char *rtlabel_id2name(u_int16_t); > +const char *rtlabel_id2name_locked(u_int16_t); > +const char *rtlabel_id2name(u_int16_t, char *, size_t); > u_int16_t rtlabel_name2id(char *); > struct sockaddr *rtlabel_id2sa(u_int16_t, struct sockaddr_rtlabel *); > void rtlabel_unref(u_int16_t);