Bug 9416

Summary: Linux Kernel isdn_net_setcfg buffer overflow
Product: Drivers Reporter: ADLab (adlab)
Component: ISDNAssignee: Karsten Keil (kernel)
Status: CLOSED CODE_FIX    
Severity: normal CC: adlab, ismail
Priority: P1    
Hardware: All   
OS: Linux   
Kernel Version: Linux-Kernel-2.6.23 Subsystem:
Regression: --- Bisected commit-id:

Description ADLab 2007-11-20 00:02:25 UTC
Linux Kernel isdn_net_setcfg buffer overflow
[AD_LAB-0719]
Class: Design Error
DATE:19/11/2007
Vulnerable:
	<=Linux-Kernel-2.6.23
Vendor:
	http://www.kernel.org

I.DESCRIPTION: 
-------------
	Linux kernel is an open source operating system.

	The Linux kernel is prone to an buffer overflow vulnerability. This issue is
due to a design error in the 'isdn_net_setcfg()' function.

II.DETAILS:
----------
	There is a buffer overflow vulnerability in function isdn_net_setcfg().

	In function isdn_ioctl, isdn_net_setcfg will be invoked.

isdn_ioctl (drivers/isdn/i4l/isdn_common.c):

1270 isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
	...
	...
1410                 case IIOCNETSCF:
1411                         /* Set configurable parameters of a network-interface */
1412                         if (arg) {
1413                                 if (copy_from_user(&cfg, argp, sizeof(cfg)))   *** <- cfg is user-controlled
1414                                         return -EFAULT;
1415                                 return isdn_net_setcfg(&cfg);	*** <- call isdn_net_setcfg()
1416                         } else
1417                                 return -EINVAL;
	...

At line 1413, the 'cfg' is read from user-space. so the 'cfg' is user-controlled.
At line 1415, function isdn_net_setcfg() is invoked. The '&cfg' is passed to isdn_net_setcfg() as an argument.

isdn_net_setcfg (drivers/isdn/i41/isdn_net.c):

2664 isdn_net_setcfg(isdn_net_ioctl_cfg * cfg)
2665 {
	...
2777                 if (cfg->exclusive > 0) {
2778                         unsigned long flags;
2779 
2780                         /* If binding is exclusive, try to grab the channel */
2781                         spin_lock_irqsave(&dev->lock, flags);
2782                         if ((i = isdn_get_free_channel(ISDN_USAGE_NET,
2783                                 lp->l2_proto, lp->l3_proto, drvidx,
2784                                 chidx, lp->msn)) < 0) {
2785                                 /* Grab failed, because desired channel is in use */
2786                                 lp->exclusive = -1;
2787                                 spin_unlock_irqrestore(&dev->lock, flags);
2788                                 return -EBUSY;
2789                         }
2790                         /* All went ok, so update isdninfo */
2791                         dev->usage[i] = ISDN_USAGE_EXCLUSIVE;
2792                         isdn_info_update();
2793                         spin_unlock_irqrestore(&dev->lock, flags);
2794                         lp->exclusive = i;
2795                 } else {
2796                         /* Non-exclusive binding or unbind. */
2797                         lp->exclusive = -1;
2798                         if ((lp->pre_device != -1) && (cfg->exclusive == -1)) {
2799                                 isdn_unexclusive_channel(lp->pre_device, lp->pre_channel);
2800                                 isdn_free_channel(lp->pre_device, lp->pre_channel, ISDN_USAGE_NET);
2801                                 drvidx = -1;
2802                                 chidx = -1;
2803                         }
2804                 }
2805                 strcpy(lp->msn, cfg->eaz);		*** <- Possible overrun of lp->msn by cfg-eaz
2806                 lp->pre_device = drvidx;
2807                 lp->pre_channel = chidx;
2808                 lp->onhtime = cfg->onhtime;
2809                 lp->charge = cfg->charge;
	...
2884         return -ENODEV;
2885 }

	At line 2805, function strcpy() is invoked. The size of argument lp->msn is 32 and cfg->eaz is 256.
Because the data of '*cfg' is user-controlled (so cfg->eaz is user-controlled), it's possible to overrun 
destination string lp->msn by string cfg->eaz. When the length of string 'cfg->eaz' is greater than 32, 
a buffer overflow will occur.


III.CREDIT: 
----------
    Venustech AD-LAB discovered this vuln. Thanks to all Venustech AD-Lab guys. Thanks to Coolq.


V.DISCLAIMS:
-----------

The information in this bulletin is provided "AS IS" without warranty of any
kind. In no event shall we be liable for any damages whatsoever including direct,
indirect, incidental, consequential, loss of business profits or special damages. 

Copyright 1996-2007 VENUSTECH. All Rights Reserved. Terms of use.

VENUSTECH Security Lab 
VENUSTECH INFORMATION TECHNOLOGY CO.,LTD(http://www.venustech.com.cn)

Security
Trusted {Solution} Provider
Service
Comment 1 Martin J. Bligh 2007-11-20 08:10:46 UTC
Appreciate you looking for vulnerabilities within Linux.

If you could file them under the appropriate category for the problem, or if in doubt under "Other/Other" rather than "Other/Bug Tracker", it'd help us out a lot. That category is for bugs against the bugzilla setup itself.

If you're in doubt of the owner, you can always assign them to "bugme-janitors@lists.osdl.org", but bugme-admin isn't a good choice.

Thanks,
The Admins ;-)
Comment 2 Ismail Donmez 2007-11-28 14:49:47 UTC
Since this is assigned a CVE, I wonder if there is a fix for this planned for mainline?
Comment 3 Karsten Keil 2007-11-29 08:21:52 UTC
Patches are already submitted, and I think they are in Linus tree now, patches are under evaluation for the stable series.
Comment 4 Karsten Keil 2007-11-29 08:23:10 UTC
So I think we can close this now.