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
This commit is contained in:
rwatson 2008-07-29 19:37:16 +00:00
parent 2f0c3f6d28
commit 4082f24815

View File

@ -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;
}