diff options
Diffstat (limited to 'net/netfilter')
-rw-r--r-- | net/netfilter/nf_sockopt.c | 36 | ||||
-rw-r--r-- | net/netfilter/nfnetlink_log.c | 13 | ||||
-rw-r--r-- | net/netfilter/xt_tcpudp.c | 2 |
3 files changed, 19 insertions, 32 deletions
diff --git a/net/netfilter/nf_sockopt.c b/net/netfilter/nf_sockopt.c index 8b8ece7..e32761c 100644 --- a/net/netfilter/nf_sockopt.c +++ b/net/netfilter/nf_sockopt.c @@ -55,18 +55,7 @@ EXPORT_SYMBOL(nf_register_sockopt); void nf_unregister_sockopt(struct nf_sockopt_ops *reg) { - /* No point being interruptible: we're probably in cleanup_module() */ - restart: mutex_lock(&nf_sockopt_mutex); - if (reg->use != 0) { - /* To be woken by nf_sockopt call... */ - /* FIXME: Stuart Young's name appears gratuitously. */ - set_current_state(TASK_UNINTERRUPTIBLE); - reg->cleanup_task = current; - mutex_unlock(&nf_sockopt_mutex); - schedule(); - goto restart; - } list_del(®->list); mutex_unlock(&nf_sockopt_mutex); } @@ -86,10 +75,11 @@ static int nf_sockopt(struct sock *sk, int pf, int val, list_for_each(i, &nf_sockopts) { ops = (struct nf_sockopt_ops *)i; if (ops->pf == pf) { + if (!try_module_get(ops->owner)) + goto out_nosup; if (get) { if (val >= ops->get_optmin && val < ops->get_optmax) { - ops->use++; mutex_unlock(&nf_sockopt_mutex); ret = ops->get(sk, val, opt, len); goto out; @@ -97,23 +87,20 @@ static int nf_sockopt(struct sock *sk, int pf, int val, } else { if (val >= ops->set_optmin && val < ops->set_optmax) { - ops->use++; mutex_unlock(&nf_sockopt_mutex); ret = ops->set(sk, val, opt, *len); goto out; } } + module_put(ops->owner); } } + out_nosup: mutex_unlock(&nf_sockopt_mutex); return -ENOPROTOOPT; out: - mutex_lock(&nf_sockopt_mutex); - ops->use--; - if (ops->cleanup_task) - wake_up_process(ops->cleanup_task); - mutex_unlock(&nf_sockopt_mutex); + module_put(ops->owner); return ret; } @@ -144,10 +131,12 @@ static int compat_nf_sockopt(struct sock *sk, int pf, int val, list_for_each(i, &nf_sockopts) { ops = (struct nf_sockopt_ops *)i; if (ops->pf == pf) { + if (!try_module_get(ops->owner)) + goto out_nosup; + if (get) { if (val >= ops->get_optmin && val < ops->get_optmax) { - ops->use++; mutex_unlock(&nf_sockopt_mutex); if (ops->compat_get) ret = ops->compat_get(sk, @@ -160,7 +149,6 @@ static int compat_nf_sockopt(struct sock *sk, int pf, int val, } else { if (val >= ops->set_optmin && val < ops->set_optmax) { - ops->use++; mutex_unlock(&nf_sockopt_mutex); if (ops->compat_set) ret = ops->compat_set(sk, @@ -171,17 +159,15 @@ static int compat_nf_sockopt(struct sock *sk, int pf, int val, goto out; } } + module_put(ops->owner); } } + out_nosup: mutex_unlock(&nf_sockopt_mutex); return -ENOPROTOOPT; out: - mutex_lock(&nf_sockopt_mutex); - ops->use--; - if (ops->cleanup_task) - wake_up_process(ops->cleanup_task); - mutex_unlock(&nf_sockopt_mutex); + module_put(ops->owner); return ret; } diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c index e185a5b..2351533 100644 --- a/net/netfilter/nfnetlink_log.c +++ b/net/netfilter/nfnetlink_log.c @@ -58,7 +58,6 @@ struct nfulnl_instance { unsigned int qlen; /* number of nlmsgs in skb */ struct sk_buff *skb; /* pre-allocatd skb */ - struct nlmsghdr *lastnlh; /* netlink header of last msg in skb */ struct timer_list timer; int peer_pid; /* PID of the peer process */ @@ -345,10 +344,12 @@ static struct sk_buff *nfulnl_alloc_skb(unsigned int inst_size, static int __nfulnl_send(struct nfulnl_instance *inst) { - int status; + int status = -1; if (inst->qlen > 1) - inst->lastnlh->nlmsg_type = NLMSG_DONE; + NLMSG_PUT(inst->skb, 0, 0, + NLMSG_DONE, + sizeof(struct nfgenmsg)); status = nfnetlink_unicast(inst->skb, inst->peer_pid, MSG_DONTWAIT); if (status < 0) { @@ -358,8 +359,8 @@ __nfulnl_send(struct nfulnl_instance *inst) inst->qlen = 0; inst->skb = NULL; - inst->lastnlh = NULL; +nlmsg_failure: return status; } @@ -538,7 +539,6 @@ __build_packet_message(struct nfulnl_instance *inst, } nlh->nlmsg_len = inst->skb->tail - old_tail; - inst->lastnlh = nlh; return 0; nlmsg_failure: @@ -644,7 +644,8 @@ nfulnl_log_packet(unsigned int pf, } if (inst->qlen >= qthreshold || - (inst->skb && size > skb_tailroom(inst->skb))) { + (inst->skb && size > + skb_tailroom(inst->skb) - sizeof(struct nfgenmsg))) { /* either the queue len is too high or we don't have * enough room in the skb left. flush to userspace. */ UDEBUG("flushing old skb\n"); diff --git a/net/netfilter/xt_tcpudp.c b/net/netfilter/xt_tcpudp.c index ab7d845..223f9bd 100644 --- a/net/netfilter/xt_tcpudp.c +++ b/net/netfilter/xt_tcpudp.c @@ -188,7 +188,7 @@ udp_checkentry(const char *tablename, void *matchinfo, unsigned int hook_mask) { - const struct xt_tcp *udpinfo = matchinfo; + const struct xt_udp *udpinfo = matchinfo; /* Must specify no unknown invflags */ return !(udpinfo->invflags & ~XT_UDP_INV_MASK); |