[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-ID: <20130129185127.GA31811@raven>
Date: Tue, 29 Jan 2013 18:51:27 +0000
From: Tom Parkin <tparkin@...alix.com>
To: netdev <netdev@...r.kernel.org>
Subject: kmemleak complaints in ip6mr.c
I've discovered what may be a memory leak in ip6mr when using network
namespaces. Here's the kmemleak backtrace:
unreferenced object 0xf0d4a180 (size 96):
comm "ip", pid 6735, jiffies 4294949643 (age 73.268s)
hex dump (first 32 bytes):
68 a1 d4 f0 00 02 20 00 01 00 00 00 00 00 00 00 h..... .........
00 00 00 00 00 00 00 00 00 00 00 00 ff 7f 00 00 ................
backtrace:
[<c159b50c>] kmemleak_alloc+0x2c/0x60
[<c1139c23>] __kmalloc+0x1c3/0x240
[<c14e2627>] fib_default_rule_add+0x27/0x70
[<c157f8df>] ip6mr_net_init+0x6f/0x140
[<c14c4129>] ops_init+0x39/0x110
[<c14c425f>] setup_net+0x5f/0xf0
[<c14c46e4>] copy_net_ns+0x74/0xf0
[<c105fc81>] create_new_namespaces+0xd1/0x160
[<c105fedf>] unshare_nsproxy_namespaces+0x5f/0xa0
[<c1038a94>] sys_unshare+0x114/0x280
[<c15b7ecd>] sysenter_do_call+0x12/0x28
[<ffffffff>] 0xffffffff
I've reproduced this on a recent net-next kernel (master as of this
Monday or so, git hash cef401de7be8c4e155c6746bfccf721a4fa5fab9),
using the script attached inline below. The script is a trimmed down
version of something I have been using to stress test some l2tp_core
changes, but the ip6mr issue appears to exist on master as well as my
branch. To get this to show up on my AMD64x2 I typically have to run
the script twice -- the first time around I get a bunch of modprobe
complaints from kmemleak, and the second time around I get ip6mr
complaints.
I'm not sure whether the trace above represents a false positive or
not -- any thoughts?
Thanks,
Tom
#!/bin/bash
BRIDGE=br0
BASE_IP=172.16.0.0
PREFIX=24
MAX_CHILDREN=300
log() { echo -e "[$(date)] $@"; }
err() { log "ERROR: $@" 1>&2; false; }
die() { err "$@"; exit 1; }
dbg() { test -n "$DEBUG" && log "$@" 1>&2; }
# $1 -- ip as a dotted quad
ip_to_decimal()
{
local o1=${1%%.*}
local o2=$(echo "$1" | cut -d. -f2)
local o3=$(echo "$1" | cut -d. -f3)
local o4=${1##*.}
echo "($o1*(2^24)) + ($o2*(2^16)) + ($o3*(2^8)) + ($o4)" | bc
}
# $1 -- ip as a decimal number
decimal_to_ip()
{
local h=$(printf "%08x" "$1")
echo $(printf "%i" 0x${h:0:2}).$(printf "%i" 0x${h:2:2}).$(printf "%i" 0x${h:4:2}).$(printf "%i" 0x${h:6:2})
}
# $1 -- base
# $2 -- netmask
# $3 -- subnet index
offset_min_ipaddr()
{
local nwoff=$(echo "$3 * (2^(32-$2))" | bc)
local base=$(ip_to_decimal "$1")
decimal_to_ip $((base+nwoff+1))
}
#$1 -- lower bound
#$2 -- upper bound
brand() {
local r=$((RANDOM%$2))
test $r -lt $1 && r=$(brand $1 $2)
echo $r
}
# $1 -- network interface name
# $2 -- id
gen_script() {
local laddr=$(offset_min_ipaddr $BASE_IP $PREFIX $2)
local sleepfor=$(brand 0 5)
dbg "$2 : $1 : sleepfor $sleepfor"
cat << __EOF__
#!/bin/bash
ip addr add $laddr/255.255.0.0 dev $1 || exit 1
ip link set $1 up || exit 1
sleep $sleepfor
ip link set $1 down
__EOF__
}
# $1 -- netns
# $2 -- ve0
# $3 -- ve1
nsup() {
local netns="$1"
local ve0="$2"
local ve1="$3"
local ret=1
ip netns add $netns || return $ret
ip link add name $ve0 type veth peer name $ve1 && \
ip link set $ve1 netns $netns && \
brctl addif $BRIDGE $ve0 && \
ip link set $ve0 up && ret=0 || \
ip netns delete $netns
return $ret
}
# $1 -- netns
# $2 -- ve0
# $3 -- ve1
nsdown() {
local netns="$1"
local ve0="$2"
local ve1="$3"
ip link set $ve0 down
brctl delif $BRIDGE $ve0
ip link del $ve0
ip netns delete $netns
}
# $1 -- id
# $2 -- netns
do_netns() {
local id="$1"
local netns="$2"
local runscript=/tmp/${netns}_run.sh
local ve0=$(echo $netns | cut -d- -f1)-0
local ve1=$(echo $netns | cut -d- -f1)-1
dbg "$id : $netns"
if nsup $netns $ve0 $ve1
then
gen_script $ve1 $id > $runscript && chmod +x $runscript && \
ip netns exec $netns $runscript || \
err "$id : $netns failed to gen/exec ns script"
while ! nsdown $netns $ve0 $ve1 &> /dev/null; do sleep 1; done
rm $runscript
else
err "$id : $netns failed to come up"
fi
}
waitforchildren() {
local p=""
log "Wait for $(echo "$cpids" | wc -w) child scripts to complete"
dbg "cpids = $cpids"
for p in $cpids; do wait $p; done
cpids=""
}
#
# Entry point
#
trap waitforchildren EXIT
if ! brctl show | grep -q $BRIDGE
then
brctl addbr $BRIDGE || die "Failed to create bridge $BRIDGE"
ip link set $BRIDGE up || die "Failed to bring $BRIDGE up"
fi
c=0
cpids=""
while true
do
nchildren=$(brand 1 $MAX_CHILDREN)
echo clear > /sys/kernel/debug/kmemleak
log "Spawn $nchildren network namespaces"
for ((i=0;i<$nchildren;i++))
do
c=$((c+1))
netns=$(uuidgen)
( cpids=""; do_netns $c $netns ) &
cpids="$cpids $!"
done
waitforchildren
echo scan > /sys/kernel/debug/kmemleak
if test $(wc -l /sys/kernel/debug/kmemleak | cut -d" " -f1) -gt 0
then
die "Kernel memory leak detected: see /sys/kernel/debug/kmemleak"
fi
done
--
Tom Parkin
Katalix Systems Ltd
http://www.katalix.com
Catalysts for your Embedded Linux software development
Download attachment "signature.asc" of type "application/pgp-signature" (491 bytes)
Powered by blists - more mailing lists