http://bugzilla.suse.com/show_bug.cgi?id=1106751
http://bugzilla.suse.com/show_bug.cgi?id=1106751#c1
Fabian Vogt changed:
What |Removed |Added
----------------------------------------------------------------------------
CC| |kstreitova@suse.com
--- Comment #1 from Fabian Vogt ---
The missing module is: bpfilter!
in ip_sockglue.c:
int ip_setsockopt(struct sock *sk, int level, int optname, char __user *optval,
unsigned int optlen) {
int err;
...
err = do_ip_setsockopt(sk, level, optname, optval, optlen);
#ifdef CONFIG_BPFILTER
if (optname >= BPFILTER_IPT_SO_SET_REPLACE && optname <
BPFILTER_IPT_SET_MAX)
err = bpfilter_ip_set_sockopt(sk, optname, optval, optlen);
#endif
#ifdef CONFIG_NETFILTER
/* we need to exclude all possible ENOPROTOOPTs except default case */
if (err == -ENOPROTOOPT && optname != IP_HDRINCL && ...)
err = nf_setsockopt(sk, PF_INET, optname, optval, optlen);
#endif
}
we see that nf_setsockopt is only called if bpfilter_ip_set_sockopt returns
-ENOPROTOOPT.
However, it does the following:
int (*bpfilter_process_sockopt)(struct sock *sk, int optname,
char __user *optval,
unsigned int optlen, bool is_set);
EXPORT_SYMBOL_GPL(bpfilter_process_sockopt);
...
if (!bpfilter_process_sockopt) {
int err = request_module("bpfilter");
if (err)
return err;
if (!bpfilter_process_sockopt)
return -ECHILD;
}
return bpfilter_process_sockopt(sk, optname, optval, optlen, is_set);
It implements lazy-loading of the module on the first call and if that fails,
returns
a value != -ENOPROTOOPT, which thus breaks netfilter. Here the value is 256,
which is
not even an error code and actually ends up in the userspace program.
Confirmed by systemtap (forcing err to -92) and loading bpfilter also makes it
succeed.
@kstreitova: This was actually handled wrongly in iptables itself, a missing
memset(&info, 0, sizeof(info)); in libiptc.c caused it to read garbage. It
would be nice
to have that fixed as well, even if it's ultimately a kernel bug.
--
You are receiving this mail because:
You are on the CC list for the bug.