aboutsummaryrefslogtreecommitdiffstats
path: root/net/core
diff options
context:
space:
mode:
Diffstat (limited to 'net/core')
-rw-r--r--net/core/rtnetlink.c24
-rw-r--r--net/core/skbuff.c23
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;