2011-11-22 05:10:51 +00:00
/*
* net / core / netprio_cgroup . c Priority Control Group
*
* This program is free software ; you can redistribute it and / or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation ; either version
* 2 of the License , or ( at your option ) any later version .
*
* Authors : Neil Horman < nhorman @ tuxdriver . com >
*/
2012-05-16 19:58:40 +00:00
# define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
2011-11-22 05:10:51 +00:00
# include <linux/module.h>
# include <linux/slab.h>
# include <linux/types.h>
# include <linux/string.h>
# include <linux/errno.h>
# include <linux/skbuff.h>
# include <linux/cgroup.h>
# include <linux/rcupdate.h>
# include <linux/atomic.h>
# include <net/rtnetlink.h>
# include <net/pkt_cls.h>
# include <net/sock.h>
# include <net/netprio_cgroup.h>
# define PRIOIDX_SZ 128
static unsigned long prioidx_map [ PRIOIDX_SZ ] ;
static DEFINE_SPINLOCK ( prioidx_map_lock ) ;
static atomic_t max_prioidx = ATOMIC_INIT ( 0 ) ;
static inline struct cgroup_netprio_state * cgrp_netprio_state ( struct cgroup * cgrp )
{
return container_of ( cgroup_subsys_state ( cgrp , net_prio_subsys_id ) ,
struct cgroup_netprio_state , css ) ;
}
static int get_prioidx ( u32 * prio )
{
unsigned long flags ;
u32 prioidx ;
spin_lock_irqsave ( & prioidx_map_lock , flags ) ;
prioidx = find_first_zero_bit ( prioidx_map , sizeof ( unsigned long ) * PRIOIDX_SZ ) ;
2012-02-03 05:18:43 +00:00
if ( prioidx = = sizeof ( unsigned long ) * PRIOIDX_SZ ) {
spin_unlock_irqrestore ( & prioidx_map_lock , flags ) ;
return - ENOSPC ;
}
2011-11-22 05:10:51 +00:00
set_bit ( prioidx , prioidx_map ) ;
2012-07-04 23:28:40 +00:00
if ( atomic_read ( & max_prioidx ) < prioidx )
atomic_set ( & max_prioidx , prioidx ) ;
2011-11-22 05:10:51 +00:00
spin_unlock_irqrestore ( & prioidx_map_lock , flags ) ;
* prio = prioidx ;
return 0 ;
}
static void put_prioidx ( u32 idx )
{
unsigned long flags ;
spin_lock_irqsave ( & prioidx_map_lock , flags ) ;
clear_bit ( idx , prioidx_map ) ;
spin_unlock_irqrestore ( & prioidx_map_lock , flags ) ;
}
net: cgroup: fix access the unallocated memory in netprio cgroup
there are some out of bound accesses in netprio cgroup.
now before accessing the dev->priomap.priomap array,we only check
if the dev->priomap exist.and because we don't want to see
additional bound checkings in fast path, so we should make sure
that dev->priomap is null or array size of dev->priomap.priomap
is equal to max_prioidx + 1;
so in write_priomap logic,we should call extend_netdev_table when
dev->priomap is null and dev->priomap.priomap_len < max_len.
and in cgrp_create->update_netdev_tables logic,we should call
extend_netdev_table only when dev->priomap exist and
dev->priomap.priomap_len < max_len.
and it's not needed to call update_netdev_tables in write_priomap,
we can only allocate the net device's priomap which we change through
net_prio.ifpriomap.
this patch also add a return value for update_netdev_tables &
extend_netdev_table, so when new_priomap is allocated failed,
write_priomap will stop to access the priomap,and return -ENOMEM
back to the userspace to tell the user what happend.
Change From v3:
1. add rtnl protect when reading max_prioidx in write_priomap.
2. only call extend_netdev_table when map->priomap_len < max_len,
this will make sure array size of dev->map->priomap always
bigger than any prioidx.
3. add a function write_update_netdev_table to make codes clear.
Change From v2:
1. protect extend_netdev_table by RTNL.
2. when extend_netdev_table failed,call dev_put to reduce device's refcount.
Signed-off-by: Gao feng <gaofeng@cn.fujitsu.com>
Cc: Neil Horman <nhorman@tuxdriver.com>
Cc: Eric Dumazet <edumazet@google.com>
Acked-by: Neil Horman <nhorman@tuxdriver.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2012-07-11 21:50:15 +00:00
static int extend_netdev_table ( struct net_device * dev , u32 new_len )
2011-11-22 05:10:51 +00:00
{
size_t new_size = sizeof ( struct netprio_map ) +
( ( sizeof ( u32 ) * new_len ) ) ;
struct netprio_map * new_priomap = kzalloc ( new_size , GFP_KERNEL ) ;
struct netprio_map * old_priomap ;
int i ;
old_priomap = rtnl_dereference ( dev - > priomap ) ;
if ( ! new_priomap ) {
2012-05-16 19:58:40 +00:00
pr_warn ( " Unable to alloc new priomap! \n " ) ;
net: cgroup: fix access the unallocated memory in netprio cgroup
there are some out of bound accesses in netprio cgroup.
now before accessing the dev->priomap.priomap array,we only check
if the dev->priomap exist.and because we don't want to see
additional bound checkings in fast path, so we should make sure
that dev->priomap is null or array size of dev->priomap.priomap
is equal to max_prioidx + 1;
so in write_priomap logic,we should call extend_netdev_table when
dev->priomap is null and dev->priomap.priomap_len < max_len.
and in cgrp_create->update_netdev_tables logic,we should call
extend_netdev_table only when dev->priomap exist and
dev->priomap.priomap_len < max_len.
and it's not needed to call update_netdev_tables in write_priomap,
we can only allocate the net device's priomap which we change through
net_prio.ifpriomap.
this patch also add a return value for update_netdev_tables &
extend_netdev_table, so when new_priomap is allocated failed,
write_priomap will stop to access the priomap,and return -ENOMEM
back to the userspace to tell the user what happend.
Change From v3:
1. add rtnl protect when reading max_prioidx in write_priomap.
2. only call extend_netdev_table when map->priomap_len < max_len,
this will make sure array size of dev->map->priomap always
bigger than any prioidx.
3. add a function write_update_netdev_table to make codes clear.
Change From v2:
1. protect extend_netdev_table by RTNL.
2. when extend_netdev_table failed,call dev_put to reduce device's refcount.
Signed-off-by: Gao feng <gaofeng@cn.fujitsu.com>
Cc: Neil Horman <nhorman@tuxdriver.com>
Cc: Eric Dumazet <edumazet@google.com>
Acked-by: Neil Horman <nhorman@tuxdriver.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2012-07-11 21:50:15 +00:00
return - ENOMEM ;
2011-11-22 05:10:51 +00:00
}
for ( i = 0 ;
old_priomap & & ( i < old_priomap - > priomap_len ) ;
i + + )
new_priomap - > priomap [ i ] = old_priomap - > priomap [ i ] ;
new_priomap - > priomap_len = new_len ;
rcu_assign_pointer ( dev - > priomap , new_priomap ) ;
if ( old_priomap )
kfree_rcu ( old_priomap , rcu ) ;
net: cgroup: fix access the unallocated memory in netprio cgroup
there are some out of bound accesses in netprio cgroup.
now before accessing the dev->priomap.priomap array,we only check
if the dev->priomap exist.and because we don't want to see
additional bound checkings in fast path, so we should make sure
that dev->priomap is null or array size of dev->priomap.priomap
is equal to max_prioidx + 1;
so in write_priomap logic,we should call extend_netdev_table when
dev->priomap is null and dev->priomap.priomap_len < max_len.
and in cgrp_create->update_netdev_tables logic,we should call
extend_netdev_table only when dev->priomap exist and
dev->priomap.priomap_len < max_len.
and it's not needed to call update_netdev_tables in write_priomap,
we can only allocate the net device's priomap which we change through
net_prio.ifpriomap.
this patch also add a return value for update_netdev_tables &
extend_netdev_table, so when new_priomap is allocated failed,
write_priomap will stop to access the priomap,and return -ENOMEM
back to the userspace to tell the user what happend.
Change From v3:
1. add rtnl protect when reading max_prioidx in write_priomap.
2. only call extend_netdev_table when map->priomap_len < max_len,
this will make sure array size of dev->map->priomap always
bigger than any prioidx.
3. add a function write_update_netdev_table to make codes clear.
Change From v2:
1. protect extend_netdev_table by RTNL.
2. when extend_netdev_table failed,call dev_put to reduce device's refcount.
Signed-off-by: Gao feng <gaofeng@cn.fujitsu.com>
Cc: Neil Horman <nhorman@tuxdriver.com>
Cc: Eric Dumazet <edumazet@google.com>
Acked-by: Neil Horman <nhorman@tuxdriver.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2012-07-11 21:50:15 +00:00
return 0 ;
}
static int write_update_netdev_table ( struct net_device * dev )
{
int ret = 0 ;
u32 max_len ;
struct netprio_map * map ;
rtnl_lock ( ) ;
max_len = atomic_read ( & max_prioidx ) + 1 ;
map = rtnl_dereference ( dev - > priomap ) ;
if ( ! map | | map - > priomap_len < max_len )
ret = extend_netdev_table ( dev , max_len ) ;
rtnl_unlock ( ) ;
return ret ;
2011-11-22 05:10:51 +00:00
}
net: cgroup: fix access the unallocated memory in netprio cgroup
there are some out of bound accesses in netprio cgroup.
now before accessing the dev->priomap.priomap array,we only check
if the dev->priomap exist.and because we don't want to see
additional bound checkings in fast path, so we should make sure
that dev->priomap is null or array size of dev->priomap.priomap
is equal to max_prioidx + 1;
so in write_priomap logic,we should call extend_netdev_table when
dev->priomap is null and dev->priomap.priomap_len < max_len.
and in cgrp_create->update_netdev_tables logic,we should call
extend_netdev_table only when dev->priomap exist and
dev->priomap.priomap_len < max_len.
and it's not needed to call update_netdev_tables in write_priomap,
we can only allocate the net device's priomap which we change through
net_prio.ifpriomap.
this patch also add a return value for update_netdev_tables &
extend_netdev_table, so when new_priomap is allocated failed,
write_priomap will stop to access the priomap,and return -ENOMEM
back to the userspace to tell the user what happend.
Change From v3:
1. add rtnl protect when reading max_prioidx in write_priomap.
2. only call extend_netdev_table when map->priomap_len < max_len,
this will make sure array size of dev->map->priomap always
bigger than any prioidx.
3. add a function write_update_netdev_table to make codes clear.
Change From v2:
1. protect extend_netdev_table by RTNL.
2. when extend_netdev_table failed,call dev_put to reduce device's refcount.
Signed-off-by: Gao feng <gaofeng@cn.fujitsu.com>
Cc: Neil Horman <nhorman@tuxdriver.com>
Cc: Eric Dumazet <edumazet@google.com>
Acked-by: Neil Horman <nhorman@tuxdriver.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2012-07-11 21:50:15 +00:00
static int update_netdev_tables ( void )
2011-11-22 05:10:51 +00:00
{
net: cgroup: fix access the unallocated memory in netprio cgroup
there are some out of bound accesses in netprio cgroup.
now before accessing the dev->priomap.priomap array,we only check
if the dev->priomap exist.and because we don't want to see
additional bound checkings in fast path, so we should make sure
that dev->priomap is null or array size of dev->priomap.priomap
is equal to max_prioidx + 1;
so in write_priomap logic,we should call extend_netdev_table when
dev->priomap is null and dev->priomap.priomap_len < max_len.
and in cgrp_create->update_netdev_tables logic,we should call
extend_netdev_table only when dev->priomap exist and
dev->priomap.priomap_len < max_len.
and it's not needed to call update_netdev_tables in write_priomap,
we can only allocate the net device's priomap which we change through
net_prio.ifpriomap.
this patch also add a return value for update_netdev_tables &
extend_netdev_table, so when new_priomap is allocated failed,
write_priomap will stop to access the priomap,and return -ENOMEM
back to the userspace to tell the user what happend.
Change From v3:
1. add rtnl protect when reading max_prioidx in write_priomap.
2. only call extend_netdev_table when map->priomap_len < max_len,
this will make sure array size of dev->map->priomap always
bigger than any prioidx.
3. add a function write_update_netdev_table to make codes clear.
Change From v2:
1. protect extend_netdev_table by RTNL.
2. when extend_netdev_table failed,call dev_put to reduce device's refcount.
Signed-off-by: Gao feng <gaofeng@cn.fujitsu.com>
Cc: Neil Horman <nhorman@tuxdriver.com>
Cc: Eric Dumazet <edumazet@google.com>
Acked-by: Neil Horman <nhorman@tuxdriver.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2012-07-11 21:50:15 +00:00
int ret = 0 ;
2011-11-22 05:10:51 +00:00
struct net_device * dev ;
net: cgroup: fix access the unallocated memory in netprio cgroup
there are some out of bound accesses in netprio cgroup.
now before accessing the dev->priomap.priomap array,we only check
if the dev->priomap exist.and because we don't want to see
additional bound checkings in fast path, so we should make sure
that dev->priomap is null or array size of dev->priomap.priomap
is equal to max_prioidx + 1;
so in write_priomap logic,we should call extend_netdev_table when
dev->priomap is null and dev->priomap.priomap_len < max_len.
and in cgrp_create->update_netdev_tables logic,we should call
extend_netdev_table only when dev->priomap exist and
dev->priomap.priomap_len < max_len.
and it's not needed to call update_netdev_tables in write_priomap,
we can only allocate the net device's priomap which we change through
net_prio.ifpriomap.
this patch also add a return value for update_netdev_tables &
extend_netdev_table, so when new_priomap is allocated failed,
write_priomap will stop to access the priomap,and return -ENOMEM
back to the userspace to tell the user what happend.
Change From v3:
1. add rtnl protect when reading max_prioidx in write_priomap.
2. only call extend_netdev_table when map->priomap_len < max_len,
this will make sure array size of dev->map->priomap always
bigger than any prioidx.
3. add a function write_update_netdev_table to make codes clear.
Change From v2:
1. protect extend_netdev_table by RTNL.
2. when extend_netdev_table failed,call dev_put to reduce device's refcount.
Signed-off-by: Gao feng <gaofeng@cn.fujitsu.com>
Cc: Neil Horman <nhorman@tuxdriver.com>
Cc: Eric Dumazet <edumazet@google.com>
Acked-by: Neil Horman <nhorman@tuxdriver.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2012-07-11 21:50:15 +00:00
u32 max_len ;
2011-11-22 05:10:51 +00:00
struct netprio_map * map ;
rtnl_lock ( ) ;
net: cgroup: fix access the unallocated memory in netprio cgroup
there are some out of bound accesses in netprio cgroup.
now before accessing the dev->priomap.priomap array,we only check
if the dev->priomap exist.and because we don't want to see
additional bound checkings in fast path, so we should make sure
that dev->priomap is null or array size of dev->priomap.priomap
is equal to max_prioidx + 1;
so in write_priomap logic,we should call extend_netdev_table when
dev->priomap is null and dev->priomap.priomap_len < max_len.
and in cgrp_create->update_netdev_tables logic,we should call
extend_netdev_table only when dev->priomap exist and
dev->priomap.priomap_len < max_len.
and it's not needed to call update_netdev_tables in write_priomap,
we can only allocate the net device's priomap which we change through
net_prio.ifpriomap.
this patch also add a return value for update_netdev_tables &
extend_netdev_table, so when new_priomap is allocated failed,
write_priomap will stop to access the priomap,and return -ENOMEM
back to the userspace to tell the user what happend.
Change From v3:
1. add rtnl protect when reading max_prioidx in write_priomap.
2. only call extend_netdev_table when map->priomap_len < max_len,
this will make sure array size of dev->map->priomap always
bigger than any prioidx.
3. add a function write_update_netdev_table to make codes clear.
Change From v2:
1. protect extend_netdev_table by RTNL.
2. when extend_netdev_table failed,call dev_put to reduce device's refcount.
Signed-off-by: Gao feng <gaofeng@cn.fujitsu.com>
Cc: Neil Horman <nhorman@tuxdriver.com>
Cc: Eric Dumazet <edumazet@google.com>
Acked-by: Neil Horman <nhorman@tuxdriver.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2012-07-11 21:50:15 +00:00
max_len = atomic_read ( & max_prioidx ) + 1 ;
2011-11-22 05:10:51 +00:00
for_each_netdev ( & init_net , dev ) {
map = rtnl_dereference ( dev - > priomap ) ;
net: cgroup: fix access the unallocated memory in netprio cgroup
there are some out of bound accesses in netprio cgroup.
now before accessing the dev->priomap.priomap array,we only check
if the dev->priomap exist.and because we don't want to see
additional bound checkings in fast path, so we should make sure
that dev->priomap is null or array size of dev->priomap.priomap
is equal to max_prioidx + 1;
so in write_priomap logic,we should call extend_netdev_table when
dev->priomap is null and dev->priomap.priomap_len < max_len.
and in cgrp_create->update_netdev_tables logic,we should call
extend_netdev_table only when dev->priomap exist and
dev->priomap.priomap_len < max_len.
and it's not needed to call update_netdev_tables in write_priomap,
we can only allocate the net device's priomap which we change through
net_prio.ifpriomap.
this patch also add a return value for update_netdev_tables &
extend_netdev_table, so when new_priomap is allocated failed,
write_priomap will stop to access the priomap,and return -ENOMEM
back to the userspace to tell the user what happend.
Change From v3:
1. add rtnl protect when reading max_prioidx in write_priomap.
2. only call extend_netdev_table when map->priomap_len < max_len,
this will make sure array size of dev->map->priomap always
bigger than any prioidx.
3. add a function write_update_netdev_table to make codes clear.
Change From v2:
1. protect extend_netdev_table by RTNL.
2. when extend_netdev_table failed,call dev_put to reduce device's refcount.
Signed-off-by: Gao feng <gaofeng@cn.fujitsu.com>
Cc: Neil Horman <nhorman@tuxdriver.com>
Cc: Eric Dumazet <edumazet@google.com>
Acked-by: Neil Horman <nhorman@tuxdriver.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2012-07-11 21:50:15 +00:00
/*
* don ' t allocate priomap if we didn ' t
* change net_prio . ifpriomap ( map = = NULL ) ,
* this will speed up skb_update_prio .
*/
if ( map & & map - > priomap_len < max_len ) {
ret = extend_netdev_table ( dev , max_len ) ;
if ( ret < 0 )
break ;
}
2011-11-22 05:10:51 +00:00
}
rtnl_unlock ( ) ;
net: cgroup: fix access the unallocated memory in netprio cgroup
there are some out of bound accesses in netprio cgroup.
now before accessing the dev->priomap.priomap array,we only check
if the dev->priomap exist.and because we don't want to see
additional bound checkings in fast path, so we should make sure
that dev->priomap is null or array size of dev->priomap.priomap
is equal to max_prioidx + 1;
so in write_priomap logic,we should call extend_netdev_table when
dev->priomap is null and dev->priomap.priomap_len < max_len.
and in cgrp_create->update_netdev_tables logic,we should call
extend_netdev_table only when dev->priomap exist and
dev->priomap.priomap_len < max_len.
and it's not needed to call update_netdev_tables in write_priomap,
we can only allocate the net device's priomap which we change through
net_prio.ifpriomap.
this patch also add a return value for update_netdev_tables &
extend_netdev_table, so when new_priomap is allocated failed,
write_priomap will stop to access the priomap,and return -ENOMEM
back to the userspace to tell the user what happend.
Change From v3:
1. add rtnl protect when reading max_prioidx in write_priomap.
2. only call extend_netdev_table when map->priomap_len < max_len,
this will make sure array size of dev->map->priomap always
bigger than any prioidx.
3. add a function write_update_netdev_table to make codes clear.
Change From v2:
1. protect extend_netdev_table by RTNL.
2. when extend_netdev_table failed,call dev_put to reduce device's refcount.
Signed-off-by: Gao feng <gaofeng@cn.fujitsu.com>
Cc: Neil Horman <nhorman@tuxdriver.com>
Cc: Eric Dumazet <edumazet@google.com>
Acked-by: Neil Horman <nhorman@tuxdriver.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2012-07-11 21:50:15 +00:00
return ret ;
2011-11-22 05:10:51 +00:00
}
2012-01-31 13:47:36 +08:00
static struct cgroup_subsys_state * cgrp_create ( struct cgroup * cgrp )
2011-11-22 05:10:51 +00:00
{
struct cgroup_netprio_state * cs ;
net: cgroup: fix access the unallocated memory in netprio cgroup
there are some out of bound accesses in netprio cgroup.
now before accessing the dev->priomap.priomap array,we only check
if the dev->priomap exist.and because we don't want to see
additional bound checkings in fast path, so we should make sure
that dev->priomap is null or array size of dev->priomap.priomap
is equal to max_prioidx + 1;
so in write_priomap logic,we should call extend_netdev_table when
dev->priomap is null and dev->priomap.priomap_len < max_len.
and in cgrp_create->update_netdev_tables logic,we should call
extend_netdev_table only when dev->priomap exist and
dev->priomap.priomap_len < max_len.
and it's not needed to call update_netdev_tables in write_priomap,
we can only allocate the net device's priomap which we change through
net_prio.ifpriomap.
this patch also add a return value for update_netdev_tables &
extend_netdev_table, so when new_priomap is allocated failed,
write_priomap will stop to access the priomap,and return -ENOMEM
back to the userspace to tell the user what happend.
Change From v3:
1. add rtnl protect when reading max_prioidx in write_priomap.
2. only call extend_netdev_table when map->priomap_len < max_len,
this will make sure array size of dev->map->priomap always
bigger than any prioidx.
3. add a function write_update_netdev_table to make codes clear.
Change From v2:
1. protect extend_netdev_table by RTNL.
2. when extend_netdev_table failed,call dev_put to reduce device's refcount.
Signed-off-by: Gao feng <gaofeng@cn.fujitsu.com>
Cc: Neil Horman <nhorman@tuxdriver.com>
Cc: Eric Dumazet <edumazet@google.com>
Acked-by: Neil Horman <nhorman@tuxdriver.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2012-07-11 21:50:15 +00:00
int ret = - EINVAL ;
2011-11-22 05:10:51 +00:00
cs = kzalloc ( sizeof ( * cs ) , GFP_KERNEL ) ;
if ( ! cs )
return ERR_PTR ( - ENOMEM ) ;
net: cgroup: fix access the unallocated memory in netprio cgroup
there are some out of bound accesses in netprio cgroup.
now before accessing the dev->priomap.priomap array,we only check
if the dev->priomap exist.and because we don't want to see
additional bound checkings in fast path, so we should make sure
that dev->priomap is null or array size of dev->priomap.priomap
is equal to max_prioidx + 1;
so in write_priomap logic,we should call extend_netdev_table when
dev->priomap is null and dev->priomap.priomap_len < max_len.
and in cgrp_create->update_netdev_tables logic,we should call
extend_netdev_table only when dev->priomap exist and
dev->priomap.priomap_len < max_len.
and it's not needed to call update_netdev_tables in write_priomap,
we can only allocate the net device's priomap which we change through
net_prio.ifpriomap.
this patch also add a return value for update_netdev_tables &
extend_netdev_table, so when new_priomap is allocated failed,
write_priomap will stop to access the priomap,and return -ENOMEM
back to the userspace to tell the user what happend.
Change From v3:
1. add rtnl protect when reading max_prioidx in write_priomap.
2. only call extend_netdev_table when map->priomap_len < max_len,
this will make sure array size of dev->map->priomap always
bigger than any prioidx.
3. add a function write_update_netdev_table to make codes clear.
Change From v2:
1. protect extend_netdev_table by RTNL.
2. when extend_netdev_table failed,call dev_put to reduce device's refcount.
Signed-off-by: Gao feng <gaofeng@cn.fujitsu.com>
Cc: Neil Horman <nhorman@tuxdriver.com>
Cc: Eric Dumazet <edumazet@google.com>
Acked-by: Neil Horman <nhorman@tuxdriver.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2012-07-11 21:50:15 +00:00
if ( cgrp - > parent & & cgrp_netprio_state ( cgrp - > parent ) - > prioidx )
goto out ;
2011-11-22 05:10:51 +00:00
ret = get_prioidx ( & cs - > prioidx ) ;
net: cgroup: fix access the unallocated memory in netprio cgroup
there are some out of bound accesses in netprio cgroup.
now before accessing the dev->priomap.priomap array,we only check
if the dev->priomap exist.and because we don't want to see
additional bound checkings in fast path, so we should make sure
that dev->priomap is null or array size of dev->priomap.priomap
is equal to max_prioidx + 1;
so in write_priomap logic,we should call extend_netdev_table when
dev->priomap is null and dev->priomap.priomap_len < max_len.
and in cgrp_create->update_netdev_tables logic,we should call
extend_netdev_table only when dev->priomap exist and
dev->priomap.priomap_len < max_len.
and it's not needed to call update_netdev_tables in write_priomap,
we can only allocate the net device's priomap which we change through
net_prio.ifpriomap.
this patch also add a return value for update_netdev_tables &
extend_netdev_table, so when new_priomap is allocated failed,
write_priomap will stop to access the priomap,and return -ENOMEM
back to the userspace to tell the user what happend.
Change From v3:
1. add rtnl protect when reading max_prioidx in write_priomap.
2. only call extend_netdev_table when map->priomap_len < max_len,
this will make sure array size of dev->map->priomap always
bigger than any prioidx.
3. add a function write_update_netdev_table to make codes clear.
Change From v2:
1. protect extend_netdev_table by RTNL.
2. when extend_netdev_table failed,call dev_put to reduce device's refcount.
Signed-off-by: Gao feng <gaofeng@cn.fujitsu.com>
Cc: Neil Horman <nhorman@tuxdriver.com>
Cc: Eric Dumazet <edumazet@google.com>
Acked-by: Neil Horman <nhorman@tuxdriver.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2012-07-11 21:50:15 +00:00
if ( ret < 0 ) {
2012-05-16 19:58:40 +00:00
pr_warn ( " No space in priority index array \n " ) ;
net: cgroup: fix access the unallocated memory in netprio cgroup
there are some out of bound accesses in netprio cgroup.
now before accessing the dev->priomap.priomap array,we only check
if the dev->priomap exist.and because we don't want to see
additional bound checkings in fast path, so we should make sure
that dev->priomap is null or array size of dev->priomap.priomap
is equal to max_prioidx + 1;
so in write_priomap logic,we should call extend_netdev_table when
dev->priomap is null and dev->priomap.priomap_len < max_len.
and in cgrp_create->update_netdev_tables logic,we should call
extend_netdev_table only when dev->priomap exist and
dev->priomap.priomap_len < max_len.
and it's not needed to call update_netdev_tables in write_priomap,
we can only allocate the net device's priomap which we change through
net_prio.ifpriomap.
this patch also add a return value for update_netdev_tables &
extend_netdev_table, so when new_priomap is allocated failed,
write_priomap will stop to access the priomap,and return -ENOMEM
back to the userspace to tell the user what happend.
Change From v3:
1. add rtnl protect when reading max_prioidx in write_priomap.
2. only call extend_netdev_table when map->priomap_len < max_len,
this will make sure array size of dev->map->priomap always
bigger than any prioidx.
3. add a function write_update_netdev_table to make codes clear.
Change From v2:
1. protect extend_netdev_table by RTNL.
2. when extend_netdev_table failed,call dev_put to reduce device's refcount.
Signed-off-by: Gao feng <gaofeng@cn.fujitsu.com>
Cc: Neil Horman <nhorman@tuxdriver.com>
Cc: Eric Dumazet <edumazet@google.com>
Acked-by: Neil Horman <nhorman@tuxdriver.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2012-07-11 21:50:15 +00:00
goto out ;
}
ret = update_netdev_tables ( ) ;
if ( ret < 0 ) {
put_prioidx ( cs - > prioidx ) ;
goto out ;
2011-11-22 05:10:51 +00:00
}
return & cs - > css ;
net: cgroup: fix access the unallocated memory in netprio cgroup
there are some out of bound accesses in netprio cgroup.
now before accessing the dev->priomap.priomap array,we only check
if the dev->priomap exist.and because we don't want to see
additional bound checkings in fast path, so we should make sure
that dev->priomap is null or array size of dev->priomap.priomap
is equal to max_prioidx + 1;
so in write_priomap logic,we should call extend_netdev_table when
dev->priomap is null and dev->priomap.priomap_len < max_len.
and in cgrp_create->update_netdev_tables logic,we should call
extend_netdev_table only when dev->priomap exist and
dev->priomap.priomap_len < max_len.
and it's not needed to call update_netdev_tables in write_priomap,
we can only allocate the net device's priomap which we change through
net_prio.ifpriomap.
this patch also add a return value for update_netdev_tables &
extend_netdev_table, so when new_priomap is allocated failed,
write_priomap will stop to access the priomap,and return -ENOMEM
back to the userspace to tell the user what happend.
Change From v3:
1. add rtnl protect when reading max_prioidx in write_priomap.
2. only call extend_netdev_table when map->priomap_len < max_len,
this will make sure array size of dev->map->priomap always
bigger than any prioidx.
3. add a function write_update_netdev_table to make codes clear.
Change From v2:
1. protect extend_netdev_table by RTNL.
2. when extend_netdev_table failed,call dev_put to reduce device's refcount.
Signed-off-by: Gao feng <gaofeng@cn.fujitsu.com>
Cc: Neil Horman <nhorman@tuxdriver.com>
Cc: Eric Dumazet <edumazet@google.com>
Acked-by: Neil Horman <nhorman@tuxdriver.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2012-07-11 21:50:15 +00:00
out :
kfree ( cs ) ;
return ERR_PTR ( ret ) ;
2011-11-22 05:10:51 +00:00
}
2012-01-31 13:47:36 +08:00
static void cgrp_destroy ( struct cgroup * cgrp )
2011-11-22 05:10:51 +00:00
{
struct cgroup_netprio_state * cs ;
struct net_device * dev ;
struct netprio_map * map ;
cs = cgrp_netprio_state ( cgrp ) ;
rtnl_lock ( ) ;
for_each_netdev ( & init_net , dev ) {
map = rtnl_dereference ( dev - > priomap ) ;
2012-07-08 21:45:10 +00:00
if ( map & & cs - > prioidx < map - > priomap_len )
2011-11-22 05:10:51 +00:00
map - > priomap [ cs - > prioidx ] = 0 ;
}
rtnl_unlock ( ) ;
put_prioidx ( cs - > prioidx ) ;
kfree ( cs ) ;
}
static u64 read_prioidx ( struct cgroup * cgrp , struct cftype * cft )
{
return ( u64 ) cgrp_netprio_state ( cgrp ) - > prioidx ;
}
static int read_priomap ( struct cgroup * cont , struct cftype * cft ,
struct cgroup_map_cb * cb )
{
struct net_device * dev ;
u32 prioidx = cgrp_netprio_state ( cont ) - > prioidx ;
u32 priority ;
struct netprio_map * map ;
rcu_read_lock ( ) ;
for_each_netdev_rcu ( & init_net , dev ) {
map = rcu_dereference ( dev - > priomap ) ;
2012-07-08 21:45:10 +00:00
priority = ( map & & prioidx < map - > priomap_len ) ? map - > priomap [ prioidx ] : 0 ;
2011-11-22 05:10:51 +00:00
cb - > fill ( cb , dev - > name , priority ) ;
}
rcu_read_unlock ( ) ;
return 0 ;
}
static int write_priomap ( struct cgroup * cgrp , struct cftype * cft ,
const char * buffer )
{
char * devname = kstrdup ( buffer , GFP_KERNEL ) ;
int ret = - EINVAL ;
u32 prioidx = cgrp_netprio_state ( cgrp ) - > prioidx ;
unsigned long priority ;
char * priostr ;
struct net_device * dev ;
struct netprio_map * map ;
if ( ! devname )
return - ENOMEM ;
/*
* Minimally sized valid priomap string
*/
if ( strlen ( devname ) < 3 )
goto out_free_devname ;
priostr = strstr ( devname , " " ) ;
if ( ! priostr )
goto out_free_devname ;
/*
* Separate the devname from the associated priority
* and advance the priostr poitner to the priority value
*/
* priostr = ' \0 ' ;
priostr + + ;
/*
* If the priostr points to NULL , we ' re at the end of the passed
* in string , and its not a valid write
*/
if ( * priostr = = ' \0 ' )
goto out_free_devname ;
ret = kstrtoul ( priostr , 10 , & priority ) ;
if ( ret < 0 )
goto out_free_devname ;
ret = - ENODEV ;
dev = dev_get_by_name ( & init_net , devname ) ;
if ( ! dev )
goto out_free_devname ;
net: cgroup: fix access the unallocated memory in netprio cgroup
there are some out of bound accesses in netprio cgroup.
now before accessing the dev->priomap.priomap array,we only check
if the dev->priomap exist.and because we don't want to see
additional bound checkings in fast path, so we should make sure
that dev->priomap is null or array size of dev->priomap.priomap
is equal to max_prioidx + 1;
so in write_priomap logic,we should call extend_netdev_table when
dev->priomap is null and dev->priomap.priomap_len < max_len.
and in cgrp_create->update_netdev_tables logic,we should call
extend_netdev_table only when dev->priomap exist and
dev->priomap.priomap_len < max_len.
and it's not needed to call update_netdev_tables in write_priomap,
we can only allocate the net device's priomap which we change through
net_prio.ifpriomap.
this patch also add a return value for update_netdev_tables &
extend_netdev_table, so when new_priomap is allocated failed,
write_priomap will stop to access the priomap,and return -ENOMEM
back to the userspace to tell the user what happend.
Change From v3:
1. add rtnl protect when reading max_prioidx in write_priomap.
2. only call extend_netdev_table when map->priomap_len < max_len,
this will make sure array size of dev->map->priomap always
bigger than any prioidx.
3. add a function write_update_netdev_table to make codes clear.
Change From v2:
1. protect extend_netdev_table by RTNL.
2. when extend_netdev_table failed,call dev_put to reduce device's refcount.
Signed-off-by: Gao feng <gaofeng@cn.fujitsu.com>
Cc: Neil Horman <nhorman@tuxdriver.com>
Cc: Eric Dumazet <edumazet@google.com>
Acked-by: Neil Horman <nhorman@tuxdriver.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2012-07-11 21:50:15 +00:00
ret = write_update_netdev_table ( dev ) ;
if ( ret < 0 )
goto out_put_dev ;
2011-11-22 05:10:51 +00:00
rcu_read_lock ( ) ;
map = rcu_dereference ( dev - > priomap ) ;
if ( map )
map - > priomap [ prioidx ] = priority ;
rcu_read_unlock ( ) ;
net: cgroup: fix access the unallocated memory in netprio cgroup
there are some out of bound accesses in netprio cgroup.
now before accessing the dev->priomap.priomap array,we only check
if the dev->priomap exist.and because we don't want to see
additional bound checkings in fast path, so we should make sure
that dev->priomap is null or array size of dev->priomap.priomap
is equal to max_prioidx + 1;
so in write_priomap logic,we should call extend_netdev_table when
dev->priomap is null and dev->priomap.priomap_len < max_len.
and in cgrp_create->update_netdev_tables logic,we should call
extend_netdev_table only when dev->priomap exist and
dev->priomap.priomap_len < max_len.
and it's not needed to call update_netdev_tables in write_priomap,
we can only allocate the net device's priomap which we change through
net_prio.ifpriomap.
this patch also add a return value for update_netdev_tables &
extend_netdev_table, so when new_priomap is allocated failed,
write_priomap will stop to access the priomap,and return -ENOMEM
back to the userspace to tell the user what happend.
Change From v3:
1. add rtnl protect when reading max_prioidx in write_priomap.
2. only call extend_netdev_table when map->priomap_len < max_len,
this will make sure array size of dev->map->priomap always
bigger than any prioidx.
3. add a function write_update_netdev_table to make codes clear.
Change From v2:
1. protect extend_netdev_table by RTNL.
2. when extend_netdev_table failed,call dev_put to reduce device's refcount.
Signed-off-by: Gao feng <gaofeng@cn.fujitsu.com>
Cc: Neil Horman <nhorman@tuxdriver.com>
Cc: Eric Dumazet <edumazet@google.com>
Acked-by: Neil Horman <nhorman@tuxdriver.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2012-07-11 21:50:15 +00:00
out_put_dev :
2011-11-22 05:10:51 +00:00
dev_put ( dev ) ;
out_free_devname :
kfree ( devname ) ;
return ret ;
}
static struct cftype ss_files [ ] = {
{
. name = " prioidx " ,
. read_u64 = read_prioidx ,
} ,
{
. name = " ifpriomap " ,
. read_map = read_priomap ,
. write_string = write_priomap ,
} ,
2012-04-01 12:09:55 -07:00
{ } /* terminate */
2011-11-22 05:10:51 +00:00
} ;
2012-04-01 12:09:55 -07:00
struct cgroup_subsys net_prio_subsys = {
. name = " net_prio " ,
. create = cgrp_create ,
. destroy = cgrp_destroy ,
# ifdef CONFIG_NETPRIO_CGROUP
. subsys_id = net_prio_subsys_id ,
# endif
2012-04-01 12:09:55 -07:00
. base_cftypes = ss_files ,
2012-04-01 12:09:55 -07:00
. module = THIS_MODULE
} ;
2011-11-22 05:10:51 +00:00
static int netprio_device_event ( struct notifier_block * unused ,
unsigned long event , void * ptr )
{
struct net_device * dev = ptr ;
struct netprio_map * old ;
/*
* Note this is called with rtnl_lock held so we have update side
* protection on our rcu assignments
*/
switch ( event ) {
case NETDEV_UNREGISTER :
old = rtnl_dereference ( dev - > priomap ) ;
2011-11-23 07:09:32 +00:00
RCU_INIT_POINTER ( dev - > priomap , NULL ) ;
2011-11-22 05:10:51 +00:00
if ( old )
kfree_rcu ( old , rcu ) ;
break ;
}
return NOTIFY_DONE ;
}
static struct notifier_block netprio_device_notifier = {
. notifier_call = netprio_device_event
} ;
static int __init init_cgroup_netprio ( void )
{
int ret ;
ret = cgroup_load_subsys ( & net_prio_subsys ) ;
if ( ret )
goto out ;
# ifndef CONFIG_NETPRIO_CGROUP
smp_wmb ( ) ;
net_prio_subsys_id = net_prio_subsys . subsys_id ;
# endif
register_netdevice_notifier ( & netprio_device_notifier ) ;
out :
return ret ;
}
static void __exit exit_cgroup_netprio ( void )
{
struct netprio_map * old ;
struct net_device * dev ;
unregister_netdevice_notifier ( & netprio_device_notifier ) ;
cgroup_unload_subsys ( & net_prio_subsys ) ;
# ifndef CONFIG_NETPRIO_CGROUP
net_prio_subsys_id = - 1 ;
synchronize_rcu ( ) ;
# endif
rtnl_lock ( ) ;
for_each_netdev ( & init_net , dev ) {
old = rtnl_dereference ( dev - > priomap ) ;
2011-11-23 07:09:32 +00:00
RCU_INIT_POINTER ( dev - > priomap , NULL ) ;
2011-11-22 05:10:51 +00:00
if ( old )
kfree_rcu ( old , rcu ) ;
}
rtnl_unlock ( ) ;
}
module_init ( init_cgroup_netprio ) ;
module_exit ( exit_cgroup_netprio ) ;
MODULE_LICENSE ( " GPL v2 " ) ;