diff --git a/drivers/connector/connector.c b/drivers/connector/connector.c index a44db75bc25b..a905f7820331 100644 --- a/drivers/connector/connector.c +++ b/drivers/connector/connector.c @@ -128,7 +128,7 @@ EXPORT_SYMBOL_GPL(cn_netlink_send); */ static int cn_call_callback(struct cn_msg *msg, void (*destruct_data)(void *), void *data) { - struct cn_callback_entry *__cbq; + struct cn_callback_entry *__cbq, *__new_cbq; struct cn_dev *dev = &cdev; int err = -ENODEV; @@ -148,27 +148,27 @@ static int cn_call_callback(struct cn_msg *msg, void (*destruct_data)(void *), v } else { struct cn_callback_data *d; - __cbq = kzalloc(sizeof(*__cbq), GFP_ATOMIC); - if (__cbq) { - d = &__cbq->data; + err = -ENOMEM; + __new_cbq = kzalloc(sizeof(struct cn_callback_entry), GFP_ATOMIC); + if (__new_cbq) { + d = &__new_cbq->data; d->callback_priv = msg; d->callback = __cbq->data.callback; d->ddata = data; d->destruct_data = destruct_data; - d->free = __cbq; + d->free = __new_cbq; - INIT_WORK(&__cbq->work, + INIT_WORK(&__new_cbq->work, &cn_queue_wrapper); - + if (queue_work(dev->cbdev->cn_queue, - &__cbq->work)) + &__new_cbq->work)) err = 0; else { - kfree(__cbq); + kfree(__new_cbq); err = -EINVAL; } - } else - err = -ENOMEM; + } } break; } diff --git a/include/net/xfrm.h b/include/net/xfrm.h index 92a1fc46ea59..5a00aa85b756 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h @@ -988,8 +988,9 @@ extern int xfrm_policy_walk(u8 type, int (*func)(struct xfrm_policy *, int, int, int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl); struct xfrm_policy *xfrm_policy_bysel_ctx(u8 type, int dir, struct xfrm_selector *sel, - struct xfrm_sec_ctx *ctx, int delete); -struct xfrm_policy *xfrm_policy_byid(u8, int dir, u32 id, int delete); + struct xfrm_sec_ctx *ctx, int delete, + int *err); +struct xfrm_policy *xfrm_policy_byid(u8, int dir, u32 id, int delete, int *err); void xfrm_policy_flush(u8 type, struct xfrm_audit *audit_info); u32 xfrm_get_acqseq(void); void xfrm_alloc_spi(struct xfrm_state *x, __be32 minspi, __be32 maxspi); diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c index 6845a258408f..f3a2e29be40c 100644 --- a/net/bridge/br_if.c +++ b/net/bridge/br_if.c @@ -428,6 +428,10 @@ int br_add_if(struct net_bridge *br, struct net_device *dev) spin_lock_bh(&br->lock); br_stp_recalculate_bridge_id(br); br_features_recompute(br); + + if ((dev->flags & IFF_UP) && netif_carrier_ok(dev) && + (br->dev->flags & IFF_UP)) + br_stp_enable_port(p); spin_unlock_bh(&br->lock); dev_set_mtu(br->dev, br_min_mtu(br)); diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c index 5361a4d8e13b..746f79d104b3 100644 --- a/net/dccp/ccids/ccid3.c +++ b/net/dccp/ccids/ccid3.c @@ -545,12 +545,7 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) /* set idle flag */ hctx->ccid3hctx_idle = 1; break; - case TFRC_SSTATE_NO_SENT: - /* - * XXX when implementing bidirectional rx/tx check this again - */ - DCCP_WARN("Illegal ACK received - no packet sent\n"); - /* fall through */ + case TFRC_SSTATE_NO_SENT: /* fall through */ case TFRC_SSTATE_TERM: /* ignore feedback when closing */ break; } diff --git a/net/dccp/input.c b/net/dccp/input.c index 287099f7f042..78b043c458bf 100644 --- a/net/dccp/input.c +++ b/net/dccp/input.c @@ -248,18 +248,8 @@ int dccp_rcv_established(struct sock *sk, struct sk_buff *skb, DCCP_ACKVEC_STATE_RECEIVED)) goto discard; - /* - * Deliver to the CCID module in charge. - * FIXME: Currently DCCP operates one-directional only, i.e. a listening - * server is not at the same time a connecting client. There is - * not much sense in delivering to both rx/tx sides at the moment - * (only one is active at a time); when moving to bidirectional - * service, this needs to be revised. - */ - if (dccp_sk(sk)->dccps_role == DCCP_ROLE_CLIENT) - ccid_hc_tx_packet_recv(dp->dccps_hc_tx_ccid, sk, skb); - else /* listening or connected server */ - ccid_hc_rx_packet_recv(dp->dccps_hc_rx_ccid, sk, skb); + ccid_hc_rx_packet_recv(dp->dccps_hc_rx_ccid, sk, skb); + ccid_hc_tx_packet_recv(dp->dccps_hc_tx_ccid, sk, skb); return __dccp_rcv_established(sk, skb, dh, len); discard: @@ -494,11 +484,8 @@ int dccp_rcv_state_process(struct sock *sk, struct sk_buff *skb, DCCP_ACKVEC_STATE_RECEIVED)) goto discard; - /* XXX see the comments in dccp_rcv_established about this */ - if (dccp_sk(sk)->dccps_role == DCCP_ROLE_CLIENT) - ccid_hc_tx_packet_recv(dp->dccps_hc_tx_ccid, sk, skb); - else - ccid_hc_rx_packet_recv(dp->dccps_hc_rx_ccid, sk, skb); + ccid_hc_rx_packet_recv(dp->dccps_hc_rx_ccid, sk, skb); + ccid_hc_tx_packet_recv(dp->dccps_hc_tx_ccid, sk, skb); } /* diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index ce6c46034314..fc620a7c1db4 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -1215,6 +1215,7 @@ int __udp4_lib_rcv(struct sk_buff *skb, struct hlist_head udptable[], if (ulen < sizeof(*uh) || pskb_trim_rcsum(skb, ulen)) goto short_packet; + uh = skb->h.uh; udp4_csum_init(skb, uh); diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index e16f1bba5dff..a7fee6b27320 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -342,10 +342,6 @@ static struct inet6_dev * ipv6_add_dev(struct net_device *dev) } #endif - if (netif_carrier_ok(dev)) - ndev->if_flags |= IF_READY; - - ipv6_mc_init_dev(ndev); ndev->tstamp = jiffies; #ifdef CONFIG_SYSCTL diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c index 286c86735aed..4e0561a082d0 100644 --- a/net/ipv6/ipv6_sockglue.c +++ b/net/ipv6/ipv6_sockglue.c @@ -795,11 +795,15 @@ int compat_ipv6_setsockopt(struct sock *sk, int level, int optname, EXPORT_SYMBOL(compat_ipv6_setsockopt); #endif -static int ipv6_getsockopt_sticky(struct sock *sk, struct ipv6_opt_hdr *hdr, +static int ipv6_getsockopt_sticky(struct sock *sk, struct ipv6_txoptions *opt, char __user *optval, int len) { - if (!hdr) + struct ipv6_opt_hdr *hdr; + + if (!opt || !opt->hopopt) return 0; + hdr = opt->hopopt; + len = min_t(int, len, ipv6_optlen(hdr)); if (copy_to_user(optval, hdr, ipv6_optlen(hdr))) return -EFAULT; @@ -940,7 +944,7 @@ static int do_ipv6_getsockopt(struct sock *sk, int level, int optname, { lock_sock(sk); - len = ipv6_getsockopt_sticky(sk, np->opt->hopopt, + len = ipv6_getsockopt_sticky(sk, np->opt, optval, len); release_sock(sk); return put_user(len, optlen); diff --git a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c index 6f19c4a49560..d1102455668d 100644 --- a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c +++ b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c @@ -257,6 +257,7 @@ static unsigned int ipv6_conntrack_in(unsigned int hooknum, } nf_conntrack_get(reasm->nfct); (*pskb)->nfct = reasm->nfct; + (*pskb)->nfctinfo = reasm->nfctinfo; return NF_ACCEPT; } diff --git a/net/key/af_key.c b/net/key/af_key.c index 1c58204d767e..a4e7e2db0ff3 100644 --- a/net/key/af_key.c +++ b/net/key/af_key.c @@ -1467,9 +1467,6 @@ static int pfkey_delete(struct sock *sk, struct sk_buff *skb, struct sadb_msg *h err = xfrm_state_delete(x); - xfrm_audit_log(audit_get_loginuid(current->audit_context), 0, - AUDIT_MAC_IPSEC_DELSA, err ? 0 : 1, NULL, x); - if (err < 0) goto out; @@ -1478,6 +1475,8 @@ static int pfkey_delete(struct sock *sk, struct sk_buff *skb, struct sadb_msg *h c.event = XFRM_MSG_DELSA; km_state_notify(x, &c); out: + xfrm_audit_log(audit_get_loginuid(current->audit_context), 0, + AUDIT_MAC_IPSEC_DELSA, err ? 0 : 1, NULL, x); xfrm_state_put(x); return err; @@ -2294,14 +2293,12 @@ static int pfkey_spddelete(struct sock *sk, struct sk_buff *skb, struct sadb_msg } xp = xfrm_policy_bysel_ctx(XFRM_POLICY_TYPE_MAIN, pol->sadb_x_policy_dir-1, - &sel, tmp.security, 1); + &sel, tmp.security, 1, &err); security_xfrm_policy_free(&tmp); if (xp == NULL) return -ENOENT; - err = security_xfrm_policy_delete(xp); - xfrm_audit_log(audit_get_loginuid(current->audit_context), 0, AUDIT_MAC_IPSEC_DELSPD, err ? 0 : 1, xp, NULL); @@ -2539,7 +2536,7 @@ static int pfkey_migrate(struct sock *sk, struct sk_buff *skb, static int pfkey_spdget(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, void **ext_hdrs) { unsigned int dir; - int err; + int err = 0, delete; struct sadb_x_policy *pol; struct xfrm_policy *xp; struct km_event c; @@ -2551,16 +2548,20 @@ static int pfkey_spdget(struct sock *sk, struct sk_buff *skb, struct sadb_msg *h if (dir >= XFRM_POLICY_MAX) return -EINVAL; + delete = (hdr->sadb_msg_type == SADB_X_SPDDELETE2); xp = xfrm_policy_byid(XFRM_POLICY_TYPE_MAIN, dir, pol->sadb_x_policy_id, - hdr->sadb_msg_type == SADB_X_SPDDELETE2); + delete, &err); if (xp == NULL) return -ENOENT; - err = 0; + if (delete) { + xfrm_audit_log(audit_get_loginuid(current->audit_context), 0, + AUDIT_MAC_IPSEC_DELSPD, err ? 0 : 1, xp, NULL); - c.seq = hdr->sadb_msg_seq; - c.pid = hdr->sadb_msg_pid; - if (hdr->sadb_msg_type == SADB_X_SPDDELETE2) { + if (err) + goto out; + c.seq = hdr->sadb_msg_seq; + c.pid = hdr->sadb_msg_pid; c.data.byid = 1; c.event = XFRM_MSG_DELPOLICY; km_policy_notify(xp, dir, &c); @@ -2568,6 +2569,7 @@ static int pfkey_spdget(struct sock *sk, struct sk_buff *skb, struct sadb_msg *h err = key_pol_get_resp(sk, xp, hdr, dir); } +out: xfrm_pol_put(xp); return err; } diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c index 91a0972ec117..5cb30ebba0f4 100644 --- a/net/netfilter/nfnetlink_log.c +++ b/net/netfilter/nfnetlink_log.c @@ -486,7 +486,7 @@ __build_packet_message(struct nfulnl_instance *inst, * for physical device (when called from ipv4) */ NFA_PUT(inst->skb, NFULA_IFINDEX_OUTDEV, sizeof(tmp_uint), &tmp_uint); - if (skb->nf_bridge) { + if (skb->nf_bridge && skb->nf_bridge->physoutdev) { tmp_uint = htonl(skb->nf_bridge->physoutdev->ifindex); NFA_PUT(inst->skb, NFULA_IFINDEX_PHYSOUTDEV, @@ -615,7 +615,7 @@ nfulnl_log_packet(unsigned int pf, plen = 0; if (prefix) - plen = strlen(prefix); + plen = strlen(prefix) + 1; /* all macros expand to constant values at compile time */ /* FIXME: do we want to make the size calculation conditional based on diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index 946b715db5ec..0c3a70ac5075 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c @@ -735,12 +735,14 @@ EXPORT_SYMBOL(xfrm_policy_insert); struct xfrm_policy *xfrm_policy_bysel_ctx(u8 type, int dir, struct xfrm_selector *sel, - struct xfrm_sec_ctx *ctx, int delete) + struct xfrm_sec_ctx *ctx, int delete, + int *err) { struct xfrm_policy *pol, *ret; struct hlist_head *chain; struct hlist_node *entry; + *err = 0; write_lock_bh(&xfrm_policy_lock); chain = policy_hash_bysel(sel, sel->family, dir); ret = NULL; @@ -750,6 +752,11 @@ struct xfrm_policy *xfrm_policy_bysel_ctx(u8 type, int dir, xfrm_sec_ctx_match(ctx, pol->security)) { xfrm_pol_hold(pol); if (delete) { + *err = security_xfrm_policy_delete(pol); + if (*err) { + write_unlock_bh(&xfrm_policy_lock); + return pol; + } hlist_del(&pol->bydst); hlist_del(&pol->byidx); xfrm_policy_count[dir]--; @@ -768,12 +775,14 @@ struct xfrm_policy *xfrm_policy_bysel_ctx(u8 type, int dir, } EXPORT_SYMBOL(xfrm_policy_bysel_ctx); -struct xfrm_policy *xfrm_policy_byid(u8 type, int dir, u32 id, int delete) +struct xfrm_policy *xfrm_policy_byid(u8 type, int dir, u32 id, int delete, + int *err) { struct xfrm_policy *pol, *ret; struct hlist_head *chain; struct hlist_node *entry; + *err = 0; write_lock_bh(&xfrm_policy_lock); chain = xfrm_policy_byidx + idx_hash(id); ret = NULL; @@ -781,6 +790,11 @@ struct xfrm_policy *xfrm_policy_byid(u8 type, int dir, u32 id, int delete) if (pol->type == type && pol->index == id) { xfrm_pol_hold(pol); if (delete) { + *err = security_xfrm_policy_delete(pol); + if (*err) { + write_unlock_bh(&xfrm_policy_lock); + return pol; + } hlist_del(&pol->bydst); hlist_del(&pol->byidx); xfrm_policy_count[dir]--; diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index 956cfe0ff7f8..96789952f6a3 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c @@ -530,9 +530,6 @@ static int xfrm_del_sa(struct sk_buff *skb, struct nlmsghdr *nlh, err = xfrm_state_delete(x); - xfrm_audit_log(NETLINK_CB(skb).loginuid, NETLINK_CB(skb).sid, - AUDIT_MAC_IPSEC_DELSA, err ? 0 : 1, NULL, x); - if (err < 0) goto out; @@ -542,6 +539,8 @@ static int xfrm_del_sa(struct sk_buff *skb, struct nlmsghdr *nlh, km_state_notify(x, &c); out: + xfrm_audit_log(NETLINK_CB(skb).loginuid, NETLINK_CB(skb).sid, + AUDIT_MAC_IPSEC_DELSA, err ? 0 : 1, NULL, x); xfrm_state_put(x); return err; } @@ -1254,7 +1253,7 @@ static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh, return err; if (p->index) - xp = xfrm_policy_byid(type, p->dir, p->index, delete); + xp = xfrm_policy_byid(type, p->dir, p->index, delete, &err); else { struct rtattr *rt = xfrma[XFRMA_SEC_CTX-1]; struct xfrm_policy tmp; @@ -1270,7 +1269,8 @@ static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh, if ((err = security_xfrm_policy_alloc(&tmp, uctx))) return err; } - xp = xfrm_policy_bysel_ctx(type, p->dir, &p->sel, tmp.security, delete); + xp = xfrm_policy_bysel_ctx(type, p->dir, &p->sel, tmp.security, + delete, &err); security_xfrm_policy_free(&tmp); } if (xp == NULL) @@ -1288,8 +1288,6 @@ static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh, MSG_DONTWAIT); } } else { - err = security_xfrm_policy_delete(xp); - xfrm_audit_log(NETLINK_CB(skb).loginuid, NETLINK_CB(skb).sid, AUDIT_MAC_IPSEC_DELSPD, err ? 0 : 1, xp, NULL); @@ -1303,9 +1301,8 @@ static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh, km_policy_notify(xp, p->dir, &c); } - xfrm_pol_put(xp); - out: + xfrm_pol_put(xp); return err; } @@ -1502,7 +1499,7 @@ static int xfrm_add_pol_expire(struct sk_buff *skb, struct nlmsghdr *nlh, return err; if (p->index) - xp = xfrm_policy_byid(type, p->dir, p->index, 0); + xp = xfrm_policy_byid(type, p->dir, p->index, 0, &err); else { struct rtattr *rt = xfrma[XFRMA_SEC_CTX-1]; struct xfrm_policy tmp; @@ -1518,13 +1515,14 @@ static int xfrm_add_pol_expire(struct sk_buff *skb, struct nlmsghdr *nlh, if ((err = security_xfrm_policy_alloc(&tmp, uctx))) return err; } - xp = xfrm_policy_bysel_ctx(type, p->dir, &p->sel, tmp.security, 0); + xp = xfrm_policy_bysel_ctx(type, p->dir, &p->sel, tmp.security, + 0, &err); security_xfrm_policy_free(&tmp); } if (xp == NULL) - return err; - read_lock(&xp->lock); + return -ENOENT; + read_lock(&xp->lock); if (xp->dead) { read_unlock(&xp->lock); goto out;