diff options
Diffstat (limited to 'sys/dev/netmap')
| -rw-r--r-- | sys/dev/netmap/netmap.c | 1 | ||||
| -rw-r--r-- | sys/dev/netmap/netmap_bdg.c | 4 | ||||
| -rw-r--r-- | sys/dev/netmap/netmap_freebsd.c | 13 | ||||
| -rw-r--r-- | sys/dev/netmap/netmap_kern.h | 3 | ||||
| -rw-r--r-- | sys/dev/netmap/netmap_mem2.c | 22 | ||||
| -rw-r--r-- | sys/dev/netmap/netmap_vale.c | 24 |
6 files changed, 51 insertions, 16 deletions
diff --git a/sys/dev/netmap/netmap.c b/sys/dev/netmap/netmap.c index f531151fb656..6f79c2c45b39 100644 --- a/sys/dev/netmap/netmap.c +++ b/sys/dev/netmap/netmap.c @@ -3503,6 +3503,7 @@ nmreq_copyin(struct nmreq_header *hdr, int nr_body_is_user) /* check optsz and nro_size to avoid for possible integer overflows of rqsz */ if ((optsz > NETMAP_REQ_MAXSIZE) || (opt->nro_size > NETMAP_REQ_MAXSIZE) || (rqsz + optsz > NETMAP_REQ_MAXSIZE) + || (p - ker + optsz > bufsz) || (optsz > 0 && rqsz + optsz <= rqsz)) { error = EMSGSIZE; goto out_restore; diff --git a/sys/dev/netmap/netmap_bdg.c b/sys/dev/netmap/netmap_bdg.c index bcb45f55d160..1fe5052448f8 100644 --- a/sys/dev/netmap/netmap_bdg.c +++ b/sys/dev/netmap/netmap_bdg.c @@ -1043,6 +1043,10 @@ netmap_bdg_config(struct nm_ifreq *nr) struct nm_bridge *b; int error = EINVAL; + if (strnlen(nr->nifr_name, sizeof(nr->nifr_name)) >= + sizeof(nr->nifr_name)) + return error; + NMG_LOCK(); b = nm_find_bridge(nr->nifr_name, 0, NULL); if (!b) { diff --git a/sys/dev/netmap/netmap_freebsd.c b/sys/dev/netmap/netmap_freebsd.c index 9fb4370129f3..409b273e6442 100644 --- a/sys/dev/netmap/netmap_freebsd.c +++ b/sys/dev/netmap/netmap_freebsd.c @@ -119,6 +119,7 @@ nm_os_selinfo_uninit(NM_SELINFO_T *si) taskqueue_drain(si->ntfytq, &si->ntfytask); taskqueue_free(si->ntfytq); si->ntfytq = NULL; + seldrain(&si->si); knlist_delete(&si->si.si_note, curthread, /*islocked=*/0); knlist_destroy(&si->si.si_note); /* now we don't need the mutex anymore */ @@ -1451,24 +1452,24 @@ netmap_kqfilter(struct cdev *dev, struct knote *kn) if (ev != EVFILT_READ && ev != EVFILT_WRITE) { nm_prerr("bad filter request %d", ev); - return 1; + return EINVAL; } error = devfs_get_cdevpriv((void**)&priv); if (error) { nm_prerr("device not yet setup"); - return 1; + return error; } + NMG_LOCK(); na = priv->np_na; if (na == NULL) { + NMG_UNLOCK(); nm_prerr("no netmap adapter for this file descriptor"); - return 1; + return ENOENT; } /* the si is indicated in the priv */ si = priv->np_si[(ev == EVFILT_WRITE) ? NR_TX : NR_RX]; - kn->kn_fop = (ev == EVFILT_WRITE) ? - &netmap_wfiltops : &netmap_rfiltops; + kn->kn_fop = (ev == EVFILT_WRITE) ? &netmap_wfiltops : &netmap_rfiltops; kn->kn_hook = priv; - NMG_LOCK(); si->kqueue_users++; nm_prinf("kqueue users for %s: %d", si->mtxname, si->kqueue_users); NMG_UNLOCK(); diff --git a/sys/dev/netmap/netmap_kern.h b/sys/dev/netmap/netmap_kern.h index 931bf7cd332b..704b880b3232 100644 --- a/sys/dev/netmap/netmap_kern.h +++ b/sys/dev/netmap/netmap_kern.h @@ -1015,6 +1015,9 @@ struct netmap_vp_adapter { /* VALE software port */ u_int mfs; /* Last source MAC on this port */ uint64_t last_smac; + + /* Buffer for ifnet driver name */ + char *name; }; diff --git a/sys/dev/netmap/netmap_mem2.c b/sys/dev/netmap/netmap_mem2.c index 865a663da364..2d77acbbb06c 100644 --- a/sys/dev/netmap/netmap_mem2.c +++ b/sys/dev/netmap/netmap_mem2.c @@ -39,6 +39,7 @@ #ifdef __FreeBSD__ #include <sys/types.h> #include <sys/domainset.h> +#include <sys/limits.h> #include <sys/malloc.h> #include <sys/kernel.h> /* MALLOC_DEFINE */ #include <sys/proc.h> @@ -1992,6 +1993,7 @@ static int netmap_mem2_rings_create(struct netmap_mem_d *nmd, struct netmap_adapter *na) { enum txrx t; + int error; for_rx_tx(t) { u_int i; @@ -2011,11 +2013,20 @@ netmap_mem2_rings_create(struct netmap_mem_d *nmd, struct netmap_adapter *na) if (netmap_debug & NM_DEBUG_MEM) nm_prinf("creating %s", kring->name); ndesc = kring->nkr_num_slots; - len = sizeof(struct netmap_ring) + - ndesc * sizeof(struct netmap_slot); + if (ndesc >= UINT_MAX / sizeof(struct netmap_slot)) { + error = EINVAL; + goto cleanup; + } + len = ndesc * sizeof(struct netmap_slot); + if (len + sizeof(struct netmap_ring) < len) { + error = EINVAL; + goto cleanup; + } + len += sizeof(struct netmap_ring); ring = netmap_ring_malloc(nmd, len); if (ring == NULL) { nm_prerr("Cannot allocate %s_ring", nm_txrx2str(t)); + error = ENOMEM; goto cleanup; } nm_prdis("txring at %p", ring); @@ -2040,7 +2051,10 @@ netmap_mem2_rings_create(struct netmap_mem_d *nmd, struct netmap_adapter *na) if (netmap_debug & NM_DEBUG_MEM) nm_prinf("allocating buffers for %s", kring->name); if (netmap_new_bufs(nmd, ring->slot, ndesc)) { - nm_prerr("Cannot allocate buffers for %s_ring", nm_txrx2str(t)); + nm_prerr( + "Cannot allocate buffers for %s_ring", + nm_txrx2str(t)); + error = ENOMEM; goto cleanup; } } else { @@ -2064,7 +2078,7 @@ cleanup: * to do the cleanup */ - return ENOMEM; + return error; } static void diff --git a/sys/dev/netmap/netmap_vale.c b/sys/dev/netmap/netmap_vale.c index 21a067715814..df167912f96f 100644 --- a/sys/dev/netmap/netmap_vale.c +++ b/sys/dev/netmap/netmap_vale.c @@ -1352,6 +1352,7 @@ nm_vi_destroy(const char *name) { if_t ifp; struct netmap_vp_adapter *vpna; + char *viname; int error; ifp = ifunit_ref(name); @@ -1386,9 +1387,12 @@ nm_vi_destroy(const char *name) /* Linux requires all the references are released * before unregister */ + viname = vpna->name; + vpna->name = NULL; netmap_detach(ifp); if_rele(ifp); nm_os_vi_detach(ifp); + nm_os_free(viname); return 0; err: @@ -1420,6 +1424,7 @@ netmap_vi_create(struct nmreq_header *hdr, int autodelete) if_t ifp; struct netmap_vp_adapter *vpna; struct netmap_mem_d *nmd = NULL; + char *name; int error; if (hdr->nr_reqtype != NETMAP_REQ_REGISTER) { @@ -1429,10 +1434,14 @@ netmap_vi_create(struct nmreq_header *hdr, int autodelete) /* don't include VALE prefix */ if (!strncmp(hdr->nr_name, NM_BDG_NAME, strlen(NM_BDG_NAME))) return EINVAL; - if (strlen(hdr->nr_name) >= IFNAMSIZ) { + if (strnlen(hdr->nr_name, sizeof(hdr->nr_name)) >= IFNAMSIZ) return EINVAL; - } - ifp = ifunit_ref(hdr->nr_name); + name = nm_os_malloc(strlen(hdr->nr_name) + 1); + if (name == NULL) + return ENOMEM; + strlcpy(name, hdr->nr_name, strlen(hdr->nr_name) + 1); + + ifp = ifunit_ref(name); if (ifp) { /* already exist, cannot create new one */ error = EEXIST; NMG_LOCK(); @@ -1443,11 +1452,11 @@ netmap_vi_create(struct nmreq_header *hdr, int autodelete) } NMG_UNLOCK(); if_rele(ifp); - return error; + goto err_0; } - error = nm_os_vi_persist(hdr->nr_name, &ifp); + error = nm_os_vi_persist(name, &ifp); if (error) - return error; + goto err_0; NMG_LOCK(); if (req->nr_mem_id) { @@ -1464,6 +1473,7 @@ netmap_vi_create(struct nmreq_header *hdr, int autodelete) nm_prerr("error %d", error); goto err_1; } + vpna->name = name; /* persist-specific routines */ vpna->up.nm_bdg_ctl = netmap_vp_bdg_ctl; if (!autodelete) { @@ -1491,6 +1501,8 @@ err_1: netmap_mem_put(nmd); NMG_UNLOCK(); nm_os_vi_detach(ifp); +err_0: + nm_os_free(name); return error; } |
