diff options
Diffstat (limited to 'net/core')
-rw-r--r-- | net/core/rtnetlink.c | 24 | ||||
-rw-r--r-- | net/core/skbuff.c | 23 |
2 files changed, 25 insertions, 22 deletions
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index a6882686ca3a..76321ea442c3 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c | |||
@@ -1498,6 +1498,7 @@ static int do_setlink(const struct sk_buff *skb, | |||
1498 | goto errout; | 1498 | goto errout; |
1499 | } | 1499 | } |
1500 | if (!netlink_ns_capable(skb, net->user_ns, CAP_NET_ADMIN)) { | 1500 | if (!netlink_ns_capable(skb, net->user_ns, CAP_NET_ADMIN)) { |
1501 | put_net(net); | ||
1501 | err = -EPERM; | 1502 | err = -EPERM; |
1502 | goto errout; | 1503 | goto errout; |
1503 | } | 1504 | } |
@@ -2685,13 +2686,20 @@ static int rtnl_bridge_getlink(struct sk_buff *skb, struct netlink_callback *cb) | |||
2685 | int idx = 0; | 2686 | int idx = 0; |
2686 | u32 portid = NETLINK_CB(cb->skb).portid; | 2687 | u32 portid = NETLINK_CB(cb->skb).portid; |
2687 | u32 seq = cb->nlh->nlmsg_seq; | 2688 | u32 seq = cb->nlh->nlmsg_seq; |
2688 | struct nlattr *extfilt; | ||
2689 | u32 filter_mask = 0; | 2689 | u32 filter_mask = 0; |
2690 | 2690 | ||
2691 | extfilt = nlmsg_find_attr(cb->nlh, sizeof(struct ifinfomsg), | 2691 | if (nlmsg_len(cb->nlh) > sizeof(struct ifinfomsg)) { |
2692 | IFLA_EXT_MASK); | 2692 | struct nlattr *extfilt; |
2693 | if (extfilt) | 2693 | |
2694 | filter_mask = nla_get_u32(extfilt); | 2694 | extfilt = nlmsg_find_attr(cb->nlh, sizeof(struct ifinfomsg), |
2695 | IFLA_EXT_MASK); | ||
2696 | if (extfilt) { | ||
2697 | if (nla_len(extfilt) < sizeof(filter_mask)) | ||
2698 | return -EINVAL; | ||
2699 | |||
2700 | filter_mask = nla_get_u32(extfilt); | ||
2701 | } | ||
2702 | } | ||
2695 | 2703 | ||
2696 | rcu_read_lock(); | 2704 | rcu_read_lock(); |
2697 | for_each_netdev_rcu(net, dev) { | 2705 | for_each_netdev_rcu(net, dev) { |
@@ -2798,6 +2806,9 @@ static int rtnl_bridge_setlink(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
2798 | if (br_spec) { | 2806 | if (br_spec) { |
2799 | nla_for_each_nested(attr, br_spec, rem) { | 2807 | nla_for_each_nested(attr, br_spec, rem) { |
2800 | if (nla_type(attr) == IFLA_BRIDGE_FLAGS) { | 2808 | if (nla_type(attr) == IFLA_BRIDGE_FLAGS) { |
2809 | if (nla_len(attr) < sizeof(flags)) | ||
2810 | return -EINVAL; | ||
2811 | |||
2801 | have_flags = true; | 2812 | have_flags = true; |
2802 | flags = nla_get_u16(attr); | 2813 | flags = nla_get_u16(attr); |
2803 | break; | 2814 | break; |
@@ -2868,6 +2879,9 @@ static int rtnl_bridge_dellink(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
2868 | if (br_spec) { | 2879 | if (br_spec) { |
2869 | nla_for_each_nested(attr, br_spec, rem) { | 2880 | nla_for_each_nested(attr, br_spec, rem) { |
2870 | if (nla_type(attr) == IFLA_BRIDGE_FLAGS) { | 2881 | if (nla_type(attr) == IFLA_BRIDGE_FLAGS) { |
2882 | if (nla_len(attr) < sizeof(flags)) | ||
2883 | return -EINVAL; | ||
2884 | |||
2871 | have_flags = true; | 2885 | have_flags = true; |
2872 | flags = nla_get_u16(attr); | 2886 | flags = nla_get_u16(attr); |
2873 | break; | 2887 | break; |
diff --git a/net/core/skbuff.c b/net/core/skbuff.c index c16615bfb61e..32e31c299631 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c | |||
@@ -552,20 +552,13 @@ static void kfree_skbmem(struct sk_buff *skb) | |||
552 | case SKB_FCLONE_CLONE: | 552 | case SKB_FCLONE_CLONE: |
553 | fclones = container_of(skb, struct sk_buff_fclones, skb2); | 553 | fclones = container_of(skb, struct sk_buff_fclones, skb2); |
554 | 554 | ||
555 | /* Warning : We must perform the atomic_dec_and_test() before | 555 | /* The clone portion is available for |
556 | * setting skb->fclone back to SKB_FCLONE_FREE, otherwise | 556 | * fast-cloning again. |
557 | * skb_clone() could set clone_ref to 2 before our decrement. | ||
558 | * Anyway, if we are going to free the structure, no need to | ||
559 | * rewrite skb->fclone. | ||
560 | */ | 557 | */ |
561 | if (atomic_dec_and_test(&fclones->fclone_ref)) { | 558 | skb->fclone = SKB_FCLONE_FREE; |
559 | |||
560 | if (atomic_dec_and_test(&fclones->fclone_ref)) | ||
562 | kmem_cache_free(skbuff_fclone_cache, fclones); | 561 | kmem_cache_free(skbuff_fclone_cache, fclones); |
563 | } else { | ||
564 | /* The clone portion is available for | ||
565 | * fast-cloning again. | ||
566 | */ | ||
567 | skb->fclone = SKB_FCLONE_FREE; | ||
568 | } | ||
569 | break; | 562 | break; |
570 | } | 563 | } |
571 | } | 564 | } |
@@ -887,11 +880,7 @@ struct sk_buff *skb_clone(struct sk_buff *skb, gfp_t gfp_mask) | |||
887 | if (skb->fclone == SKB_FCLONE_ORIG && | 880 | if (skb->fclone == SKB_FCLONE_ORIG && |
888 | n->fclone == SKB_FCLONE_FREE) { | 881 | n->fclone == SKB_FCLONE_FREE) { |
889 | n->fclone = SKB_FCLONE_CLONE; | 882 | n->fclone = SKB_FCLONE_CLONE; |
890 | /* As our fastclone was free, clone_ref must be 1 at this point. | 883 | atomic_inc(&fclones->fclone_ref); |
891 | * We could use atomic_inc() here, but it is faster | ||
892 | * to set the final value. | ||
893 | */ | ||
894 | atomic_set(&fclones->fclone_ref, 2); | ||
895 | } else { | 884 | } else { |
896 | if (skb_pfmemalloc(skb)) | 885 | if (skb_pfmemalloc(skb)) |
897 | gfp_mask |= __GFP_MEMALLOC; | 886 | gfp_mask |= __GFP_MEMALLOC; |