summaryrefslogtreecommitdiffstats
path: root/sys/netinet6
diff options
context:
space:
mode:
authorrwatson <rwatson@FreeBSD.org>2008-07-29 19:37:16 +0000
committerrwatson <rwatson@FreeBSD.org>2008-07-29 19:37:16 +0000
commit4082f248156aae5409102554cfe53d44d2f421e6 (patch)
tree5e289ab59443e0fdff6f3ba6d038b082ef4dd6fe /sys/netinet6
parent2f0c3f6d28da0886e68ac911efb23033c8b1e48f (diff)
downloadFreeBSD-src-4082f248156aae5409102554cfe53d44d2f421e6.zip
FreeBSD-src-4082f248156aae5409102554cfe53d44d2f421e6.tar.gz
When copying in and out current ICMPv6 filters on a raw IPv6 socket,
lock the inpcb and use a local stack variable to copy to/from userspace so that sooptcopyin()/sooptcopyout() aren't called while holding an rwlock. While here, fix a bug in which a failed sooptcopyin() might lead to partially consistent ICMPv6 filters on the socket by not ignoring the error returned by sooptcopyin(). MFC after: 2 weeks
Diffstat (limited to 'sys/netinet6')
-rw-r--r--sys/netinet6/icmp6.c20
1 files changed, 14 insertions, 6 deletions
diff --git a/sys/netinet6/icmp6.c b/sys/netinet6/icmp6.c
index 3fdff60..89fbe29 100644
--- a/sys/netinet6/icmp6.c
+++ b/sys/netinet6/icmp6.c
@@ -2715,14 +2715,18 @@ icmp6_ctloutput(struct socket *so, struct sockopt *sopt)
switch (optname) {
case ICMP6_FILTER:
{
- struct icmp6_filter *p;
+ struct icmp6_filter ic6f;
- if (optlen != sizeof(*p)) {
+ if (optlen != sizeof(ic6f)) {
error = EMSGSIZE;
break;
}
- error = sooptcopyin(sopt, inp->in6p_icmp6filt, optlen,
- optlen);
+ error = sooptcopyin(sopt, &ic6f, optlen, optlen);
+ if (error == 0) {
+ INP_WLOCK(inp);
+ *inp->in6p_icmp6filt = ic6f;
+ INP_WUNLOCK(inp);
+ }
break;
}
@@ -2736,8 +2740,12 @@ icmp6_ctloutput(struct socket *so, struct sockopt *sopt)
switch (optname) {
case ICMP6_FILTER:
{
- error = sooptcopyout(sopt, inp->in6p_icmp6filt,
- sizeof(struct icmp6_filter));
+ struct icmp6_filter ic6f;
+
+ INP_RLOCK(inp);
+ ic6f = *inp->in6p_icmp6filt;
+ INP_RUNLOCK(inp);
+ error = sooptcopyout(sopt, &ic6f, sizeof(ic6f));
break;
}
OpenPOWER on IntegriCloud