Date: Mon, 21 May 2012 22:21:00 +0000 (UTC) From: "Alexander V. Chernikov" <melifaro@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r235747 - head/sys/net Message-ID: <201205212221.q4LML09n076128@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: melifaro Date: Mon May 21 22:21:00 2012 New Revision: 235747 URL: http://svn.freebsd.org/changeset/base/235747 Log: Make most BPF ioctls() SMP-safe. Approved by: kib(mentor) MFC in: 4 weeks Modified: head/sys/net/bpf.c Modified: head/sys/net/bpf.c ============================================================================== --- head/sys/net/bpf.c Mon May 21 22:19:19 2012 (r235746) +++ head/sys/net/bpf.c Mon May 21 22:21:00 2012 (r235747) @@ -1229,7 +1229,9 @@ bpfioctl(struct cdev *dev, u_long cmd, c case BIOCGDLTLIST32: case BIOCGRTIMEOUT32: case BIOCSRTIMEOUT32: + BPFD_LOCK(d); d->bd_compat32 = 1; + BPFD_UNLOCK(d); } #endif @@ -1274,7 +1276,9 @@ bpfioctl(struct cdev *dev, u_long cmd, c * Get buffer len [for read()]. */ case BIOCGBLEN: + BPFD_LOCK(d); *(u_int *)addr = d->bd_bufsize; + BPFD_UNLOCK(d); break; /* @@ -1329,10 +1333,12 @@ bpfioctl(struct cdev *dev, u_long cmd, c * Get current data link type. */ case BIOCGDLT: + BPF_LOCK(); if (d->bd_bif == NULL) error = EINVAL; else *(u_int *)addr = d->bd_bif->bif_dlt; + BPF_UNLOCK(); break; /* @@ -1347,6 +1353,7 @@ bpfioctl(struct cdev *dev, u_long cmd, c list32 = (struct bpf_dltlist32 *)addr; dltlist.bfl_len = list32->bfl_len; dltlist.bfl_list = PTRIN(list32->bfl_list); + BPF_LOCK(); if (d->bd_bif == NULL) error = EINVAL; else { @@ -1354,15 +1361,18 @@ bpfioctl(struct cdev *dev, u_long cmd, c if (error == 0) list32->bfl_len = dltlist.bfl_len; } + BPF_UNLOCK(); break; } #endif case BIOCGDLTLIST: + BPF_LOCK(); if (d->bd_bif == NULL) error = EINVAL; else error = bpf_getdltlist(d, (struct bpf_dltlist *)addr); + BPF_UNLOCK(); break; /* @@ -1381,6 +1391,7 @@ bpfioctl(struct cdev *dev, u_long cmd, c * Get interface name. */ case BIOCGETIF: + BPF_LOCK(); if (d->bd_bif == NULL) error = EINVAL; else { @@ -1390,6 +1401,7 @@ bpfioctl(struct cdev *dev, u_long cmd, c strlcpy(ifr->ifr_name, ifp->if_xname, sizeof(ifr->ifr_name)); } + BPF_UNLOCK(); break; /* @@ -1481,7 +1493,9 @@ bpfioctl(struct cdev *dev, u_long cmd, c * Set immediate mode. */ case BIOCIMMEDIATE: + BPFD_LOCK(d); d->bd_immediate = *(u_int *)addr; + BPFD_UNLOCK(d); break; case BIOCVERSION: @@ -1497,21 +1511,27 @@ bpfioctl(struct cdev *dev, u_long cmd, c * Get "header already complete" flag */ case BIOCGHDRCMPLT: + BPFD_LOCK(d); *(u_int *)addr = d->bd_hdrcmplt; + BPFD_UNLOCK(d); break; /* * Set "header already complete" flag */ case BIOCSHDRCMPLT: + BPFD_LOCK(d); d->bd_hdrcmplt = *(u_int *)addr ? 1 : 0; + BPFD_UNLOCK(d); break; /* * Get packet direction flag */ case BIOCGDIRECTION: + BPFD_LOCK(d); *(u_int *)addr = d->bd_direction; + BPFD_UNLOCK(d); break; /* @@ -1526,7 +1546,9 @@ bpfioctl(struct cdev *dev, u_long cmd, c case BPF_D_IN: case BPF_D_INOUT: case BPF_D_OUT: + BPFD_LOCK(d); d->bd_direction = direction; + BPFD_UNLOCK(d); break; default: error = EINVAL; @@ -1538,7 +1560,9 @@ bpfioctl(struct cdev *dev, u_long cmd, c * Get packet timestamp format and resolution. */ case BIOCGTSTAMP: + BPFD_LOCK(d); *(u_int *)addr = d->bd_tstamp; + BPFD_UNLOCK(d); break; /* @@ -1557,26 +1581,38 @@ bpfioctl(struct cdev *dev, u_long cmd, c break; case BIOCFEEDBACK: + BPFD_LOCK(d); d->bd_feedback = *(u_int *)addr; + BPFD_UNLOCK(d); break; case BIOCLOCK: + BPFD_LOCK(d); d->bd_locked = 1; + BPFD_UNLOCK(d); break; case FIONBIO: /* Non-blocking I/O */ break; case FIOASYNC: /* Send signal on receive packets */ + BPFD_LOCK(d); d->bd_async = *(int *)addr; + BPFD_UNLOCK(d); break; case FIOSETOWN: + /* + * XXX: Add some sort of locking here? + * fsetown() can sleep. + */ error = fsetown(*(int *)addr, &d->bd_sigio); break; case FIOGETOWN: + BPFD_LOCK(d); *(int *)addr = fgetown(&d->bd_sigio); + BPFD_UNLOCK(d); break; /* This is deprecated, FIOSETOWN should be used instead. */ @@ -1597,16 +1633,23 @@ bpfioctl(struct cdev *dev, u_long cmd, c if (sig >= NSIG) error = EINVAL; - else + else { + BPFD_LOCK(d); d->bd_sig = sig; + BPFD_UNLOCK(d); + } break; } case BIOCGRSIG: + BPFD_LOCK(d); *(u_int *)addr = d->bd_sig; + BPFD_UNLOCK(d); break; case BIOCGETBUFMODE: + BPFD_LOCK(d); *(u_int *)addr = d->bd_bufmode; + BPFD_UNLOCK(d); break; case BIOCSETBUFMODE: @@ -2544,24 +2587,22 @@ bpf_getdltlist(struct bpf_d *d, struct b struct ifnet *ifp; struct bpf_if *bp; + BPF_LOCK_ASSERT(); + ifp = d->bd_bif->bif_ifp; n = 0; error = 0; - BPF_LOCK(); LIST_FOREACH(bp, &bpf_iflist, bif_next) { if (bp->bif_ifp != ifp) continue; if (bfl->bfl_list != NULL) { - if (n >= bfl->bfl_len) { - BPF_UNLOCK(); + if (n >= bfl->bfl_len) return (ENOMEM); - } error = copyout(&bp->bif_dlt, bfl->bfl_list + n, sizeof(u_int)); } n++; } - BPF_UNLOCK(); bfl->bfl_len = n; return (error); }
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201205212221.q4LML09n076128>