LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Linux - Mobile (http://www.linuxquestions.org/questions/linux-mobile-81/)
-   -   [tun.ko] Kernel Oops, expertise needed! (http://www.linuxquestions.org/questions/linux-mobile-81/%5Btun-ko%5D-kernel-oops-expertise-needed-935116/)

snempaa 03-18-2012 11:58 AM

[tun.ko] Kernel Oops, expertise needed!
 
Hello all,

First, some side info, skip the next paragraph to read about the kernel module problem.

A week ago I bought a Vodafone (Huawei) R201 device, which shares a 3g connection over wifi. The device runs the 2.6.25 linux kernel [PREEMPT, armv6l]. I've gained root access by looking into the firmware, found out the iptables blocks telnetd on all interfaces. Since the firmware was on a cramfs file, I could only change the binary's name to iptacles, so I got (root) telnet access after flashing the bogus rom (by pausing the original flashing process after the signature check, flipping the iptables bit and let the flash run -> in case people wonder how to do it and end up here through google: use a hex editor and process explorer. Ask me, but not in this thread.). After this little victory, I made some configtweaks (getting rid of max 5 connected clients) and I found the correct cross compiler and Linux kernel sources and started to cross compile the tuntap kernel module. I succeeded in this to me new task and insmod'ed the module correctly. Now the trouble starts.

When I try to run a piece of software that makes use of the tun driver (own test code and openvpn) , I get a kernel Oops, because of a null reference. Since this is all new to me and I'm out of own options now, maybe someone can point me in the right direction. Any help is appreciated. See relevant dmesg info below.

Also some info on the module (and a shipped one), the magic is the same:

gebruiker@generic ~ $ file *.ko
msm_serial_hs.ko: ELF 32-bit LSB relocatable, ARM, version 1 (SYSV), not stripped
tun.ko: ELF 32-bit LSB relocatable, ARM, version 1 (SYSV), not stripped

~ # /mnt/flash/bin/h
SEGV
~ # dmesg
Unable to handle kernel NULL pointer dereference at virtual address 00000024
pgd = c2ac8000
[00000024] *pgd=039c5031, *pte=00000000, *ppte=00000000
Internal error: Oops: 817 [#1] PREEMPT
Modules linked in: ar6000 tun msm_sdcc
CPU: 0 Not tainted (2.6.25 #1)
PC is at tun_setup+0x1c/0x7c [tun]
LR is at alloc_netdev_mq+0xac/0xd8
pc : [<bf006a40>] lr : [<c01b2f7c>] psr: 20000013
sp : c4f23e98 ip : c4f23eb0 fp : c4f23eac
r10: bf0073c8 r9 : bf006a24 r8 : 00000001
r7 : 00000050 r6 : 00000480 r5 : c2aea000 r4 : 00000000
r3 : 00000000 r2 : 00000020 r1 : 00000000 r0 : c2aea000
Flags: nzCv IRQs on FIQs on Mode SVC_32 ISA ARM Segment user
Control: 00c5387f Table: 02cc8008 DAC: 00000015
Process hans (pid: 2017, stack limit = 0xc4f22260)
Stack: (0xc4f23e98 to 0xc4f24000)
3e80: c2aea000 c2aea000
3ea0: c4f23edc c4f23eb0 c01b2f7c bf006a30 c004e430 00000001 bf00829c befc79f4
3ec0: bf00829c c4f22000 c4f23ee4 c355da40 c4f23f2c c4f23ee0 bf006eb4 c01b2edc
3ee0: c4f22000 00000000 00000000 00000000 00000000 00001001 00000000 00000000
3f00: 00000000 c355da40 400454ca befc79f4 00000036 c0022bc8 c4f22000 00000000
3f20: c4f23f4c c4f23f30 c00a3fa4 bf006b70 c4e05e00 c355da40 c475fda8 befc79f4
3f40: c4f23f7c c4f23f50 c00a426c c00a3f34 c355da40 00000004 c4f23f94 c355da40
3f60: fffffff7 400454ca c0022bc8 c4f22000 c4f23fa4 c4f23f80 c00a42dc c00a3fcc
3f80: 00000005 00000000 c4f23fa4 0000001c 00000005 00049efc 00000000 c4f23fa8
3fa0: c0022a20 c00a42a8 0000001c 00000005 00000004 400454ca befc79f4 befc79dc
3fc0: 0000001c 00000005 00049efc 00000036 00049004 00000007 000080b4 befc7a24
3fe0: 00000000 befc79c0 0001709c 0002a560 60000010 00000004 00000000 00000000
Backtrace:
[<bf006a24>] (tun_setup+0x0/0x7c [tun]) from [<c01b2f7c>] (alloc_netdev_mq+0xac/0xd8)
r5:c2aea000 r4:c2aea000
[<c01b2ed0>] (alloc_netdev_mq+0x0/0xd8) from [<bf006eb4>] (tun_chr_ioctl+0x350/0x65c [tun])
[<bf006b64>] (tun_chr_ioctl+0x0/0x65c [tun]) from [<c00a3fa4>] (vfs_ioctl+0x7c/0x98)
[<c00a3f28>] (vfs_ioctl+0x0/0x98) from [<c00a426c>] (do_vfs_ioctl+0x2ac/0x2dc)
r6:befc79f4 r5:c475fda8 r4:c355da40
[<c00a3fc0>] (do_vfs_ioctl+0x0/0x2dc) from [<c00a42dc>] (sys_ioctl+0x40/0x64)
r9:c4f22000 r8:c0022bc8 r6:400454ca r5:fffffff7 r4:c355da40
[<c00a429c>] (sys_ioctl+0x0/0x64) from [<c0022a20>] (ret_fast_syscall+0x0/0x2c)
r6:00049efc r5:00000005 r4:0000001c
Code: e590419c e3a03000 e2842020 e1a05000 (e5842024)
---[ end trace fff8bfea0c633eef ]---



ps. Useful info for r201 (rooted) owners : /mnt/flash is non-volatile, put a script called customer.rcS in /mnt/flash/ and it will run every boot. What I do there is insmod the sd drivers and mount a new (writable) filesystem with up to date binaries and a patched cms (the huawei primary binary). And of course the tun.ko whenever I fix this problem!

snempaa 03-18-2012 03:42 PM

Got some help from a good friend and found out with some printk's that the following function fails

drivers/net/tun.c :

static void tun_setup(struct net_device *dev)
{

struct tun_struct *tun = netdev_priv(dev); // dev->priv

skb_queue_head_init(&tun->readq);
init_waitqueue_head(&tun->read_wait);

tun->owner = -1;
tun->group = -1;

dev->open = tun_net_open;
dev->hard_start_xmit = tun_net_xmit;
dev->stop = tun_net_close;
dev->ethtool_ops = &tun_ethtool_ops;
dev->destructor = free_netdev;
}

tun = 0 after the netdev_priv(dev) call. (which actually is just a dev->priv call in netdevice.h.

Then we tried to find the place where priv get's initialized, which is in include/linux/netdevice.h:

extern struct net_device *alloc_netdev_mq(int sizeof_priv, const char *name,
void (*setup)(struct net_device *),
unsigned int queue_count);
#define alloc_netdev(sizeof_priv, name, setup) \
alloc_netdev_mq(sizeof_priv, name, setup, 1)

which is called with : alloc_netdev(80, "/dev/tun", tun_setup);

alloc_netdev_mq is in core/net/dev.c:

struct net_device *alloc_netdev_mq(int sizeof_priv, const char *name,
void (*setup)(struct net_device *), unsigned int queue_count)
{
void *p;
struct net_device *dev;
int alloc_size;

BUG_ON(strlen(name) >= sizeof(dev->name));

/* ensure 32-byte alignment of both the device and private area */
alloc_size = (sizeof(*dev) + NETDEV_ALIGN_CONST +
(sizeof(struct net_device_subqueue) * (queue_count - 1))) &
~NETDEV_ALIGN_CONST;
alloc_size += sizeof_priv + NETDEV_ALIGN_CONST;

p = kzalloc(alloc_size, GFP_KERNEL);
if (!p) {
printk(KERN_ERR "alloc_netdev: Unable to allocate device.\n");
return NULL;
}

dev = (struct net_device *)
(((long)p + NETDEV_ALIGN_CONST) & ~NETDEV_ALIGN_CONST);
dev->padded = (char *)dev - (char *)p;
dev->nd_net = &init_net;

if (sizeof_priv) {
dev->priv = ((char *)dev +
((sizeof(struct net_device) +
(sizeof(struct net_device_subqueue) *
(queue_count - 1)) + NETDEV_ALIGN_CONST)
& ~NETDEV_ALIGN_CONST));
}


dev->egress_subqueue_count = queue_count;

dev->get_stats = internal_stats;
netpoll_netdev_init(dev);
setup(dev);
strcpy(dev->name, name);
return dev;
}

And that's where I'm stuck, it looks like it should work;) I'm about to copy this code with constants into the tun class..

For referencing:

struct tun_struct {
struct list_head list;
unsigned long flags;
int attached;
uid_t owner;
gid_t group;

wait_queue_head_t read_wait;
struct sk_buff_head readq;

struct net_device *dev;

struct fasync_struct *fasync;

unsigned long if_flags;
u8 dev_addr[ETH_ALEN];
u32 chr_filter[2];
u32 net_filter[2];

#ifdef TUN_DEBUG
int debug;
#endif
};

snempaa 03-19-2012 09:27 AM

When I init dev->priv myself I get an exception later on, with the notice that I try to init a already initialized value. I can't seem to see where things go wrong. Anyone?

snempaa 03-21-2012 04:01 AM

Anyone? If rewritten the complete priv struct to be hold in the tun.c class instead of the netdevice class, but still I get an exception. I've tried the regular linux kernel, the special qualcomm MSM git repository, and many others, but they all have the same problems which let me end up with the kernel Oops (and a system crash).

snempaa 08-14-2012 06:28 AM

I found the correct sources here and got the kernel config from the rom. Then I crosscompiled the normal way and got this working module :

http://wouter.ru/tun.ko

Have fun with it too;)

nanosonde 09-11-2012 04:14 PM

Hi!

Can you write a few more details on how to access the firmware?
Have you been able to get the GPL sources from Huawei?

I am desperately searching such a small mobile device which runs Linux.
Until now I have always worked with my TP-Link MR3020 and openwrt.

Thanks!

snempaa 02-09-2013 03:08 PM

Hello my friends,

I started working with the r201 again and I need your help again! I am trying to get rid of the maximum of 5 connected clients in this device but that looked easier than it is.

Since the device runs hostapd i though just to change the configfile; doesn't work, gets detected by firmware and deauths the 6th client. Same when using wmiconfig to set maxsta to >5.

I found out that the max of 5 gets saved in NVRAM, along with ssid settings and other wifi settings. Since the settings is sent in the webinterface (ssid, maxAssoc) in JavaScript I used BURP as a proxy to change the values but again this (of course) gets checked serverside and fails.

On the server I found two libs, libnv.so and libnvram_api.so, which have some function calls to recv of set nvram values. I have no experience in working with shared libs and dynamic linking, but i have made the following code to talk to the lib:

Code:

#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>

int main(int argc, char **argv) {
    void *handle;
    int (*func)();
    char *error;
    handle = dlopen ("libnv.so", RTLD_LAZY);
    if (!handle) {
        fprintf (stderr, "%s\n", dlerror());
        exit(1);
    }
    dlerror();    /* Clear any existing error */
    func = dlsym(handle, "xdr_nv_recv_nv_wifi_sta_para");
    if ((error = dlerror()) != NULL)  {
        fprintf (stderr, "%s\n", error);
        exit(1);
        }
    printf ("%d\n", (*func)());
    dlclose(handle);
    return 0;
}

You can guess, it fails, since it depends on other source the know some enums/variables. When I strace, I see that the lib gets opened and right after, before the actual function call (function found by nm -D lbnv.so), the error gets written to stdout. What am I not seeing/knowing about dynamic linking to make this work?

Anybody?

Thanks in advance!

Cross compile command:
Code:

arm-none-linux-gnueabi-gcc ~/nv/testapp.c -o ~/nv/sharedlibtest -ldl
Code:

/mnt/sd # ./sharedlibtest
/opt/qcom/lib/libnv.so: undefined symbol: xdr_op_err_msg

Some info for nm:

Code:

000153d4 T xdr_nv_send_nv_wifi_st
00014bf4 T xdr_nv_send_nv_wifi_sta_para
...
000157b0 T xdr_nv_recv_nv_wifi_st
00014c98 T xdr_nv_recv_nv_wifi_sta_para
...
        U xdr_op_err_msg

ps. Maybe also usefull, I have no sources, headerfiles or whatever on all nvram libs / binaries (a test binary to read the values! and a binary for getting and setting mac/imei, although imei is in a strange format).

snempaa 02-09-2013 03:33 PM

Quote:

Originally Posted by nanosonde (Post 4777955)
Hi!

Can you write a few more details on how to access the firmware?
Have you been able to get the GPL sources from Huawei?

I am desperately searching such a small mobile device which runs Linux.
Until now I have always worked with my TP-Link MR3020 and openwrt.

Thanks!

No I just found a repo online (linux-msm) and found out that the kernel config was somewhere on the device itself (gzipped inside another gzip archive). With that info I could easily compile the tun.ko.
About flashing the device, I used a Windows VM for that. Download the firmware 'upgrade' from Vodafone, Process Explorer from Microsoft and a nice HexEditor for Windows. Open process explorer, run the upgradetool, find it in process explorer, properties, input/output and start the flashing process in the vodafone tool. When you see a large (39mb) write action to disk in proc. expl., suspend the process! Hopefully you timed that right (it has to be after the checksumcheck, but usually i get it right now), go to your users temp folder find the 39mb binary and open it with the hexeditor. Find iptables (third hit, where it is right between all the other filenames and change iptables to iptacles (but dont change the size of the file by renaming it completely!). Then start the process again and let it flash.

Your router will restart and after you connect you can telnet to 192.168.0.1 with user root ( no passwd! ). Since iptables broke the router functionality will not work, I have put a file in the non volatile part of the memory (/mnt/flash/)

/mnt/sd # cat /mnt/flash/bin/fixrouter
#!/bin/sh
/bin/iptacles -t nat -A POSTROUTING -o tun0 -j MASQUERADE
/bin/iptacles -A INPUT -p tcp -i rmnet0 --dport 23 -j DROP

(change tun0 to rmnet0 if you want to have it running like old times, or fix a nice script that mounts iptacles to iptables so the device manages the firewall again while not blocking port 23).

Other good info about the device; In the bootscripts of the device I found a check for /mnt/flash/customer.rcS so if you put a script there it will run at startup. For example, link to the fixrouter script from there.

snempaa 02-11-2013 03:28 AM

Yesterday I've tried to find out in which shared lib this symbol is defined, and found out it's defined in one of the qualcomm libs as well; but now I'd like to know how let my code know to find it there; do I need to get all the structures via dlopen or can I just static link this lib with my app (without header file)?

Code:

gebruiker@generiek:~/nv/lib$ ls -1|awk -F ' ' '{print "het gaat om : "$1; system("nm -D "$1" |grep xdr_op_err_msg")}'
het gaat om : libcm.so
        U xdr_op_err_msg
het gaat om : libcm.so.1
        U xdr_op_err_msg
het gaat om : libcm.so.1.0.0
        U xdr_op_err_msg
het gaat om : libdiag.so
het gaat om : libdiag.so.1
het gaat om : libdiag.so.1.0.0
het gaat om : libdsm.so
het gaat om : libdsm.so.1
het gaat om : libdsm.so.1.0.0
het gaat om : libdss.so
het gaat om : libdss.so.1
het gaat om : libdss.so.1.0.0
het gaat om : libmmgsdilib.so
        U xdr_op_err_msg
het gaat om : libmmgsdilib.so.1
        U xdr_op_err_msg
het gaat om : libmmgsdilib.so.1.0.0
        U xdr_op_err_msg
het gaat om : libmm-omxcore.so
het gaat om : libmm-omxcore.so.1
het gaat om : libmm-omxcore.so.1.0.0
het gaat om : libmvs.so
        U xdr_op_err_msg
het gaat om : libmvs.so.1
        U xdr_op_err_msg
het gaat om : libmvs.so.1.0.0
        U xdr_op_err_msg
het gaat om : libnvram_api.so
het gaat om : libnvram_api.so.1
het gaat om : libnvram_api.so.1.0.0
het gaat om : libnv.so
        U xdr_op_err_msg
het gaat om : libnv.so.1
        U xdr_op_err_msg
het gaat om : libnv.so.1.0.0
        U xdr_op_err_msg
het gaat om : liboem_rapi.so
        U xdr_op_err_msg
het gaat om : liboem_rapi.so.1
        U xdr_op_err_msg
het gaat om : liboem_rapi.so.1.0.0
        U xdr_op_err_msg
het gaat om : liboncrpc.so
0001c0b0 R xdr_op_err_msg
het gaat om : liboncrpc.so.1
0001c0b0 R xdr_op_err_msg
het gaat om : liboncrpc.so.1.0.0
0001c0b0 R xdr_op_err_msg

het gaat om : libpdapi.so
        U xdr_op_err_msg
het gaat om : libpdapi.so.1
        U xdr_op_err_msg
het gaat om : libpdapi.so.1.0.0
        U xdr_op_err_msg
het gaat om : libpdsm_atl.so
        U xdr_op_err_msg
het gaat om : libpdsm_atl.so.1
        U xdr_op_err_msg
het gaat om : libpdsm_atl.so.1.0.0
        U xdr_op_err_msg
het gaat om : libping_mdm.so
        U xdr_op_err_msg
het gaat om : libping_mdm.so.1
        U xdr_op_err_msg
het gaat om : libping_mdm.so.1.0.0
        U xdr_op_err_msg
het gaat om : libqmi.so
het gaat om : libqmi.so.1
het gaat om : libqmi.so.1.0.0
het gaat om : libqueue.so
het gaat om : libqueue.so.1
het gaat om : libqueue.so.1.0.0
het gaat om : libsdapi.so
het gaat om : libsdapi.so.1
het gaat om : libsdapi.so.1.0.0
het gaat om : libstringl.so
het gaat om : libstringl.so.1
het gaat om : libstringl.so.1.0.0
het gaat om : libsyswatch_util.so
het gaat om : libsyswatch_util.so.1
het gaat om : libsyswatch_util.so.1.0.0
het gaat om : libui_notify.so
het gaat om : libui_notify.so.1
het gaat om : libui_notify.so.1.0.0


snempaa 02-11-2013 10:14 AM

On a little break I copied all the libs on the r201 to my cross compiler environment and compiled the binary linked with liboncrpc, so I got rid of the error message. In exchange I got a SEGV! Looking into the strace logs I think I need to supply var pointer to the function. Now how to find out what kind of data the functions of the shared lib need... anyone?


All times are GMT -5. The time now is 09:04 PM.