aboutsummaryrefslogtreecommitdiff
path: root/sys/dev/netmap
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/netmap')
-rw-r--r--sys/dev/netmap/netmap.c1
-rw-r--r--sys/dev/netmap/netmap_bdg.c4
-rw-r--r--sys/dev/netmap/netmap_freebsd.c13
-rw-r--r--sys/dev/netmap/netmap_kern.h3
-rw-r--r--sys/dev/netmap/netmap_mem2.c22
-rw-r--r--sys/dev/netmap/netmap_vale.c24
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;
}