spin_lock(&atm_dev_lock); 
down(&atm_dev_mutex); 
int atm_dev_ioctl(unsigned int cmd, void __user *arg){	void __user *buf;	int error, len, number, size = 0;	struct atm_dev *dev;	struct list_head *p;	int *tmp_buf, *tmp_p;	struct atm_iobuf __user *iobuf = arg;	struct atmif_sioc __user *sioc = arg;	switch (cmd) {		case ATM_GETNAMES:			if (get_user(buf, &iobuf->buffer))				return -EFAULT;			if (get_user(len, &iobuf->length))				return -EFAULT;			spin_lock(&atm_dev_lock);			list_for_each(p, &atm_devs)				size += sizeof(int);			if (size > len) {				spin_unlock(&atm_dev_lock);				return -E2BIG;			}			tmp_buf = kmalloc(size, GFP_ATOMIC);			if (!tmp_buf) {				spin_unlock(&atm_dev_lock);				return -ENOMEM;			}			tmp_p = tmp_buf;			list_for_each(p, &atm_devs) {				dev = list_entry(p, struct atm_dev, dev_list);				*tmp_p++ = dev->number;			}			spin_unlock(&atm_dev_lock);		        error = ((copy_to_user(buf, tmp_buf, size)) ||					put_user(size, &iobuf->length))						? -EFAULT : 0;			kfree(tmp_buf);			return error;		default:			break;	}	if (get_user(buf, &sioc->arg))		return -EFAULT;	if (get_user(len, &sioc->length))		return -EFAULT;	if (get_user(number, &sioc->number))		return -EFAULT;	if (!(dev = try_then_request_module(atm_dev_lookup(number),					    "atm-device-%d", number)))		return -ENODEV;		switch (cmd) {		case ATM_GETTYPE:			size = strlen(dev->type) + 1;			if (copy_to_user(buf, dev->type, size)) {				error = -EFAULT;				goto done;			}			break;		case ATM_GETESI:			size = ESI_LEN;			if (copy_to_user(buf, dev->esi, size)) {				error = -EFAULT;				goto done;			}			break;		case ATM_SETESI:			{				int i;				for (i = 0; i < ESI_LEN; i++)					if (dev->esi[i]) {						error = -EEXIST;						goto done;					}			}			/* fall through */		case ATM_SETESIF:			{				unsigned char esi[ESI_LEN];				if (!capable(CAP_NET_ADMIN)) {					error = -EPERM;					goto done;				}				if (copy_from_user(esi, buf, ESI_LEN)) {					error = -EFAULT;					goto done;				}				memcpy(dev->esi, esi, ESI_LEN);				error =  ESI_LEN;				goto done;			}		case ATM_GETSTATZ:			if (!capable(CAP_NET_ADMIN)) {				error = -EPERM;				goto done;			}			/* fall through */		case ATM_GETSTAT:			size = sizeof(struct atm_dev_stats);			error = fetch_stats(dev, buf, cmd == ATM_GETSTATZ);			if (error)				goto done;			break;		case ATM_GETCIRANGE:			size = sizeof(struct atm_cirange);			if (copy_to_user(buf, &dev->ci_range, size)) {				error = -EFAULT;				goto done;			}			break;		case ATM_GETLINKRATE:			size = sizeof(int);			if (copy_to_user(buf, &dev->link_rate, size)) {				error = -EFAULT;				goto done;			}			break;		case ATM_RSTADDR:			if (!capable(CAP_NET_ADMIN)) {				error = -EPERM;				goto done;			}			atm_reset_addr(dev, ATM_ADDR_LOCAL);			break;		case ATM_ADDADDR:		case ATM_DELADDR:		case ATM_ADDLECSADDR:		case ATM_DELLECSADDR:			if (!capable(CAP_NET_ADMIN)) {				error = -EPERM;				goto done;			}			{				struct sockaddr_atmsvc addr;				if (copy_from_user(&addr, buf, sizeof(addr))) {					error = -EFAULT;					goto done;				}				if (cmd == ATM_ADDADDR || cmd == ATM_ADDLECSADDR)					error = atm_add_addr(dev, &addr,							     (cmd == ATM_ADDADDR ?							      ATM_ADDR_LOCAL : ATM_ADDR_LECS));				else					error = atm_del_addr(dev, &addr,							     (cmd == ATM_DELADDR ?							      ATM_ADDR_LOCAL : ATM_ADDR_LECS));				goto done;			}		case ATM_GETADDR:		case ATM_GETLECSADDR:			error = atm_get_addr(dev, buf, len,					     (cmd == ATM_GETADDR ?					      ATM_ADDR_LOCAL : ATM_ADDR_LECS));			if (error < 0)				goto done;			size = error;			/* may return 0, but later on size == 0 means "don't			   write the length" */			error = put_user(size, &sioc->length)				? -EFAULT : 0;			goto done;		case ATM_SETLOOP:			if (__ATM_LM_XTRMT((int) (unsigned long) buf) &&			    __ATM_LM_XTLOC((int) (unsigned long) buf) >			    __ATM_LM_XTRMT((int) (unsigned long) buf)) {				error = -EINVAL;				goto done;			}			/* fall through */		case ATM_SETCIRANGE:		case SONET_GETSTATZ:		case SONET_SETDIAG:		case SONET_CLRDIAG:		case SONET_SETFRAMING:			if (!capable(CAP_NET_ADMIN)) {				error = -EPERM;				goto done;			}			/* fall through */		default:			if (!dev->ops->ioctl) {				error = -EINVAL;				goto done;			}			size = dev->ops->ioctl(dev, cmd, buf);			if (size < 0) {				error = (size == -ENOIOCTLCMD ? -EINVAL : size);				goto done;			}	}		if (size)		error = put_user(size, &sioc->length)			? -EFAULT : 0;	else		error = 0;done:	atm_dev_put(dev);	return error;}
4520	/local/tlutelli/issta_data/temp/c/2005_temp/2005/4520/aaaaaadbe7a663d110814db50fcbe7d320eb4c32/resources.c/buggy/net/atm/resources.c