diff options
Diffstat (limited to 'drivers/char')
39 files changed, 221 insertions, 77 deletions
diff --git a/drivers/char/agp/frontend.c b/drivers/char/agp/frontend.c index e6cb1ab03e06..a96f3197e60f 100644 --- a/drivers/char/agp/frontend.c +++ b/drivers/char/agp/frontend.c @@ -39,6 +39,7 @@ #include <linux/mm.h> #include <linux/fs.h> #include <linux/sched.h> +#include <linux/smp_lock.h> #include <asm/uaccess.h> #include <asm/pgtable.h> #include "agp.h" @@ -677,6 +678,7 @@ static int agp_open(struct inode *inode, struct file *file) struct agp_client *client; int rc = -ENXIO; + lock_kernel(); mutex_lock(&(agp_fe.agp_mutex)); if (minor != AGPGART_MINOR) @@ -703,12 +705,14 @@ static int agp_open(struct inode *inode, struct file *file) agp_insert_file_private(priv); DBG("private=%p, client=%p", priv, client); mutex_unlock(&(agp_fe.agp_mutex)); + unlock_kernel(); return 0; err_out_nomem: rc = -ENOMEM; err_out: mutex_unlock(&(agp_fe.agp_mutex)); + unlock_kernel(); return rc; } diff --git a/drivers/char/apm-emulation.c b/drivers/char/apm-emulation.c index cdd876dbb2b0..da8a1658a273 100644 --- a/drivers/char/apm-emulation.c +++ b/drivers/char/apm-emulation.c @@ -13,6 +13,7 @@ #include <linux/module.h> #include <linux/poll.h> #include <linux/slab.h> +#include <linux/smp_lock.h> #include <linux/proc_fs.h> #include <linux/seq_file.h> #include <linux/miscdevice.h> @@ -416,6 +417,7 @@ static int apm_open(struct inode * inode, struct file * filp) { struct apm_user *as; + lock_kernel(); as = kzalloc(sizeof(*as), GFP_KERNEL); if (as) { /* @@ -435,6 +437,7 @@ static int apm_open(struct inode * inode, struct file * filp) filp->private_data = as; } + unlock_kernel(); return as ? 0 : -ENOMEM; } diff --git a/drivers/char/briq_panel.c b/drivers/char/briq_panel.c index b6f2639f903d..d8cff909001c 100644 --- a/drivers/char/briq_panel.c +++ b/drivers/char/briq_panel.c @@ -6,6 +6,7 @@ #include <linux/module.h> +#include <linux/smp_lock.h> #include <linux/types.h> #include <linux/errno.h> #include <linux/tty.h> @@ -67,11 +68,15 @@ static void set_led(char state) static int briq_panel_open(struct inode *ino, struct file *filep) { - /* enforce single access */ - if (vfd_is_open) + lock_kernel(); + /* enforce single access, vfd_is_open is protected by BKL */ + if (vfd_is_open) { + unlock_kernel(); return -EBUSY; + } vfd_is_open = 1; + unlock_kernel(); return 0; } diff --git a/drivers/char/cs5535_gpio.c b/drivers/char/cs5535_gpio.c index c0a4a0bb509e..04ba906b4880 100644 --- a/drivers/char/cs5535_gpio.c +++ b/drivers/char/cs5535_gpio.c @@ -17,6 +17,7 @@ #include <linux/cdev.h> #include <linux/ioport.h> #include <linux/pci.h> +#include <linux/smp_lock.h> #include <asm/uaccess.h> #include <asm/io.h> @@ -157,6 +158,7 @@ static int cs5535_gpio_open(struct inode *inode, struct file *file) { u32 m = iminor(inode); + cycle_kernel_lock(); /* the mask says which pins are usable by this driver */ if ((mask & (1 << m)) == 0) return -EINVAL; diff --git a/drivers/char/drm/drm_fops.c b/drivers/char/drm/drm_fops.c index d2e6da85f58a..851a53f1acce 100644 --- a/drivers/char/drm/drm_fops.c +++ b/drivers/char/drm/drm_fops.c @@ -37,6 +37,7 @@ #include "drmP.h" #include "drm_sarea.h" #include <linux/poll.h> +#include <linux/smp_lock.h> static int drm_open_helper(struct inode *inode, struct file *filp, struct drm_device * dev); @@ -174,12 +175,14 @@ int drm_stub_open(struct inode *inode, struct file *filp) DRM_DEBUG("\n"); + /* BKL pushdown: note that nothing else serializes idr_find() */ + lock_kernel(); minor = idr_find(&drm_minors_idr, minor_id); if (!minor) - return -ENODEV; + goto out; if (!(dev = minor->dev)) - return -ENODEV; + goto out; old_fops = filp->f_op; filp->f_op = fops_get(&dev->driver->fops); @@ -189,6 +192,8 @@ int drm_stub_open(struct inode *inode, struct file *filp) } fops_put(old_fops); +out: + unlock_kernel(); return err; } diff --git a/drivers/char/ds1286.c b/drivers/char/ds1286.c index ea35ab2c9909..fb584938c9c3 100644 --- a/drivers/char/ds1286.c +++ b/drivers/char/ds1286.c @@ -27,6 +27,7 @@ * option) any later version. */ #include <linux/ds1286.h> +#include <linux/smp_lock.h> #include <linux/types.h> #include <linux/errno.h> #include <linux/miscdevice.h> @@ -252,6 +253,7 @@ static int ds1286_ioctl(struct inode *inode, struct file *file, static int ds1286_open(struct inode *inode, struct file *file) { + lock_kernel(); spin_lock_irq(&ds1286_lock); if (ds1286_status & RTC_IS_OPEN) @@ -260,10 +262,12 @@ static int ds1286_open(struct inode *inode, struct file *file) ds1286_status |= RTC_IS_OPEN; spin_unlock_irq(&ds1286_lock); + unlock_kernel(); return 0; out_busy: spin_lock_irq(&ds1286_lock); + unlock_kernel(); return -EBUSY; } diff --git a/drivers/char/ds1620.c b/drivers/char/ds1620.c index 334ad5bbe6b6..34275c6f1da2 100644 --- a/drivers/char/ds1620.c +++ b/drivers/char/ds1620.c @@ -8,6 +8,7 @@ #include <linux/proc_fs.h> #include <linux/capability.h> #include <linux/init.h> +#include <linux/smp_lock.h> #include <asm/hardware.h> #include <asm/mach-types.h> @@ -208,6 +209,12 @@ static void ds1620_read_state(struct therm *therm) therm->hi = cvt_9_to_int(ds1620_in(THERM_READ_TH, 9)); } +static int ds1620_open(struct inode *inode, struct file *file) +{ + cycle_kernel_lock(); + return nonseekable_open(inode, file); +} + static ssize_t ds1620_read(struct file *file, char __user *buf, size_t count, loff_t *ptr) { @@ -336,7 +343,7 @@ static struct proc_dir_entry *proc_therm_ds1620; static const struct file_operations ds1620_fops = { .owner = THIS_MODULE, - .open = nonseekable_open, + .open = ds1620_open, .read = ds1620_read, .ioctl = ds1620_ioctl, }; diff --git a/drivers/char/dsp56k.c b/drivers/char/dsp56k.c index a69c65283260..7bf7485377e6 100644 --- a/drivers/char/dsp56k.c +++ b/drivers/char/dsp56k.c @@ -33,6 +33,7 @@ #include <linux/mm.h> #include <linux/init.h> #include <linux/device.h> +#include <linux/smp_lock.h> #include <asm/atarihw.h> #include <asm/traps.h> @@ -436,13 +437,17 @@ static unsigned int dsp56k_poll(struct file *file, poll_table *wait) static int dsp56k_open(struct inode *inode, struct file *file) { int dev = iminor(inode) & 0x0f; + int ret = 0; + lock_kernel(); switch(dev) { case DSP56K_DEV_56001: - if (test_and_set_bit(0, &dsp56k.in_use)) - return -EBUSY; + if (test_and_set_bit(0, &dsp56k.in_use)) { + ret = -EBUSY; + goto out; + } dsp56k.timeout = TIMEOUT; dsp56k.maxio = MAXIO; @@ -458,10 +463,11 @@ static int dsp56k_open(struct inode *inode, struct file *file) break; default: - return -ENODEV; + ret = -ENODEV; } - - return 0; +out: + unlock_kernel(); + return ret; } static int dsp56k_release(struct inode *inode, struct file *file) diff --git a/drivers/char/dtlk.c b/drivers/char/dtlk.c index abde6ddefe69..6b900b297cc6 100644 --- a/drivers/char/dtlk.c +++ b/drivers/char/dtlk.c @@ -56,6 +56,7 @@ #include <linux/errno.h> /* for -EBUSY */ #include <linux/ioport.h> /* for request_region */ #include <linux/delay.h> /* for loops_per_jiffy */ +#include <linux/smp_lock.h> /* cycle_kernel_lock() */ #include <asm/io.h> /* for inb_p, outb_p, inb, outb, etc. */ #include <asm/uaccess.h> /* for get_user, etc. */ #include <linux/wait.h> /* for wait_queue */ @@ -288,10 +289,12 @@ static int dtlk_ioctl(struct inode *inode, } } +/* Note that nobody ever sets dtlk_busy... */ static int dtlk_open(struct inode *inode, struct file *file) { TRACE_TEXT("(dtlk_open"); + cycle_kernel_lock(); nonseekable_open(inode, file); switch (iminor(inode)) { case DTLK_MINOR: diff --git a/drivers/char/efirtc.c b/drivers/char/efirtc.c index 49233f589874..d57ca3e4e534 100644 --- a/drivers/char/efirtc.c +++ b/drivers/char/efirtc.c @@ -28,6 +28,7 @@ */ +#include <linux/smp_lock.h> #include <linux/types.h> #include <linux/errno.h> #include <linux/miscdevice.h> @@ -272,6 +273,7 @@ efi_rtc_open(struct inode *inode, struct file *file) * We do accept multiple open files at the same time as we * synchronize on the per call operation. */ + cycle_kernel_lock(); return 0; } diff --git a/drivers/char/genrtc.c b/drivers/char/genrtc.c index 69f0a2993af0..aac0985a572b 100644 --- a/drivers/char/genrtc.c +++ b/drivers/char/genrtc.c @@ -51,6 +51,7 @@ #include <linux/init.h> #include <linux/poll.h> #include <linux/proc_fs.h> +#include <linux/smp_lock.h> #include <linux/workqueue.h> #include <asm/uaccess.h> @@ -338,12 +339,16 @@ static int gen_rtc_ioctl(struct inode *inode, struct file *file, static int gen_rtc_open(struct inode *inode, struct file *file) { - if (gen_rtc_status & RTC_IS_OPEN) + lock_kernel(); + if (gen_rtc_status & RTC_IS_OPEN) { + unlock_kernel(); return -EBUSY; + } gen_rtc_status |= RTC_IS_OPEN; gen_rtc_irq_data = 0; irq_active = 0; + unlock_kernel(); return 0; } diff --git a/drivers/char/hpet.c b/drivers/char/hpet.c index e7fb0bca3667..fb0a85a1eb36 100644 --- a/drivers/char/hpet.c +++ b/drivers/char/hpet.c @@ -14,6 +14,7 @@ #include <linux/interrupt.h> #include <linux/module.h> #include <linux/kernel.h> +#include <linux/smp_lock.h> #include <linux/types.h> #include <linux/miscdevice.h> #include <linux/major.h> @@ -193,6 +194,7 @@ static int hpet_open(struct inode *inode, struct file *file) if (file->f_mode & FMODE_WRITE) return -EINVAL; + lock_kernel(); spin_lock_irq(&hpet_lock); for (devp = NULL, hpetp = hpets; hpetp && !devp; hpetp = hpetp->hp_next) @@ -207,6 +209,7 @@ static int hpet_open(struct inode *inode, struct file *file) if (!devp) { spin_unlock_irq(&hpet_lock); + unlock_kernel(); return -EBUSY; } @@ -214,6 +217,7 @@ static int hpet_open(struct inode *inode, struct file *file) devp->hd_irqdata = 0; devp->hd_flags |= HPET_OPEN; spin_unlock_irq(&hpet_lock); + unlock_kernel(); return 0; } diff --git a/drivers/char/hw_random/core.c b/drivers/char/hw_random/core.c index 662d60e44e9a..e5d583c84e4f 100644 --- a/drivers/char/hw_random/core.c +++ b/drivers/char/hw_random/core.c @@ -37,6 +37,7 @@ #include <linux/kernel.h> #include <linux/fs.h> #include <linux/sched.h> +#include <linux/smp_lock.h> #include <linux/init.h> #include <linux/miscdevice.h> #include <linux/delay.h> @@ -86,6 +87,7 @@ static int rng_dev_open(struct inode *inode, struct file *filp) return -EINVAL; if (filp->f_mode & FMODE_WRITE) return -EINVAL; + cycle_kernel_lock(); return 0; } diff --git a/drivers/char/ip2/ip2main.c b/drivers/char/ip2/ip2main.c index c12cf8fc4be0..61b6fe4156bb 100644 --- a/drivers/char/ip2/ip2main.c +++ b/drivers/char/ip2/ip2main.c @@ -98,6 +98,7 @@ #include <linux/major.h> #include <linux/wait.h> #include <linux/device.h> +#include <linux/smp_lock.h> #include <linux/tty.h> #include <linux/tty_flip.h> @@ -2908,42 +2909,11 @@ ip2_ipl_ioctl ( struct inode *pInode, struct file *pFile, UINT cmd, ULONG arg ) static int ip2_ipl_open( struct inode *pInode, struct file *pFile ) { - unsigned int iplminor = iminor(pInode); - i2eBordStrPtr pB; - i2ChanStrPtr pCh; #ifdef IP2DEBUG_IPL printk (KERN_DEBUG "IP2IPL: open\n" ); #endif - - switch(iplminor) { - // These are the IPL devices - case 0: - case 4: - case 8: - case 12: - break; - - // These are the status devices - case 1: - case 5: - case 9: - case 13: - break; - - // These are the debug devices - case 2: - case 6: - case 10: - case 14: - pB = i2BoardPtrTable[iplminor / 4]; - pCh = (i2ChanStrPtr) pB->i2eChannelPtr; - break; - - // This is the trace device - case 3: - break; - } + cycle_kernel_lock(); return 0; } diff --git a/drivers/char/ip27-rtc.c b/drivers/char/ip27-rtc.c index 86e6538a77b0..ec9d0443d92c 100644 --- a/drivers/char/ip27-rtc.c +++ b/drivers/char/ip27-rtc.c @@ -27,6 +27,7 @@ #include <linux/bcd.h> #include <linux/module.h> #include <linux/kernel.h> +#include <linux/smp_lock.h> #include <linux/types.h> #include <linux/miscdevice.h> #include <linux/ioport.h> @@ -163,15 +164,18 @@ static long rtc_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) static int rtc_open(struct inode *inode, struct file *file) { + lock_kernel(); spin_lock_irq(&rtc_lock); if (rtc_status & RTC_IS_OPEN) { spin_unlock_irq(&rtc_lock); + unlock_kernel(); return -EBUSY; } rtc_status |= RTC_IS_OPEN; spin_unlock_irq(&rtc_lock); + unlock_kernel(); return 0; } diff --git a/drivers/char/ipmi/ipmi_devintf.c b/drivers/char/ipmi/ipmi_devintf.c index 0246a2b8ce48..c11a40483459 100644 --- a/drivers/char/ipmi/ipmi_devintf.c +++ b/drivers/char/ipmi/ipmi_devintf.c @@ -43,6 +43,7 @@ #include <linux/init.h> #include <linux/device.h> #include <linux/compat.h> +#include <linux/smp_lock.h> struct ipmi_file_private { @@ -100,7 +101,9 @@ static int ipmi_fasync(int fd, struct file *file, int on) struct ipmi_file_private *priv = file->private_data; int result; + lock_kernel(); /* could race against open() otherwise */ result = fasync_helper(fd, file, on, &priv->fasync_queue); + unlock_kernel(); return (result); } @@ -121,6 +124,7 @@ static int ipmi_open(struct inode *inode, struct file *file) if (!priv) return -ENOMEM; + lock_kernel(); priv->file = file; rv = ipmi_create_user(if_num, @@ -129,7 +133,7 @@ static int ipmi_open(struct inode *inode, struct file *file) &(priv->user)); if (rv) { kfree(priv); - return rv; + goto out; } file->private_data = priv; @@ -144,7 +148,9 @@ static int ipmi_open(struct inode *inode, struct file *file) priv->default_retries = -1; priv->default_retry_time_ms = 0; - return 0; +out: + unlock_kernel(); + return rv; } static int ipmi_release(struct inode *inode, struct file *file) diff --git a/drivers/char/ipmi/ipmi_watchdog.c b/drivers/char/ipmi/ipmi_watchdog.c index 0e6df289cb46..235fab0bdf79 100644 --- a/drivers/char/ipmi/ipmi_watchdog.c +++ b/drivers/char/ipmi/ipmi_watchdog.c @@ -35,6 +35,7 @@ #include <linux/moduleparam.h> #include <linux/ipmi.h> #include <linux/ipmi_smi.h> +#include <linux/smp_lock.h> #include <linux/watchdog.h> #include <linux/miscdevice.h> #include <linux/init.h> @@ -818,6 +819,8 @@ static int ipmi_open(struct inode *ino, struct file *filep) if (test_and_set_bit(0, &ipmi_wdog_open)) return -EBUSY; + cycle_kernel_lock(); + /* * Don't start the timer now, let it start on the * first heartbeat. diff --git a/drivers/char/lcd.c b/drivers/char/lcd.c index 4fe9206f84de..1c29b20e4f4c 100644 --- a/drivers/char/lcd.c +++ b/drivers/char/lcd.c @@ -20,6 +20,7 @@ #include <linux/mc146818rtc.h> #include <linux/netdevice.h> #include <linux/sched.h> +#include <linux/smp_lock.h> #include <linux/delay.h> #include <asm/io.h> @@ -414,6 +415,8 @@ static int lcd_ioctl(struct inode *inode, struct file *file, static int lcd_open(struct inode *inode, struct file *file) { + cycle_kernel_lock(); + if (!lcd_present) return -ENXIO; else diff --git a/drivers/char/lp.c b/drivers/char/lp.c index 60ac642752be..71abb4c33aa2 100644 --- a/drivers/char/lp.c +++ b/drivers/char/lp.c @@ -126,6 +126,7 @@ #include <linux/device.h> #include <linux/wait.h> #include <linux/jiffies.h> +#include <linux/smp_lock.h> #include <linux/parport.h> #undef LP_STATS @@ -489,14 +490,21 @@ static ssize_t lp_read(struct file * file, char __user * buf, static int lp_open(struct inode * inode, struct file * file) { unsigned int minor = iminor(inode); + int ret = 0; - if (minor >= LP_NO) - return -ENXIO; - if ((LP_F(minor) & LP_EXIST) == 0) - return -ENXIO; - if (test_and_set_bit(LP_BUSY_BIT_POS, &LP_F(minor))) - return -EBUSY; - + lock_kernel(); + if (minor >= LP_NO) { + ret = -ENXIO; + goto out; + } + if ((LP_F(minor) & LP_EXIST) == 0) { + ret = -ENXIO; + goto out; + } + if (test_and_set_bit(LP_BUSY_BIT_POS, &LP_F(minor))) { + ret = -EBUSY; + goto out; + } /* If ABORTOPEN is set and the printer is offline or out of paper, we may still want to open it to perform ioctl()s. Therefore we have commandeered O_NONBLOCK, even though it is being used in @@ -510,21 +518,25 @@ static int lp_open(struct inode * inode, struct file * file) if (status & LP_POUTPA) { printk(KERN_INFO "lp%d out of paper\n", minor); LP_F(minor) &= ~LP_BUSY; - return -ENOSPC; + ret = -ENOSPC; + goto out; } else if (!(status & LP_PSELECD)) { printk(KERN_INFO "lp%d off-line\n", minor); LP_F(minor) &= ~LP_BUSY; - return -EIO; + ret = -EIO; + goto out; } else if (!(status & LP_PERRORP)) { printk(KERN_ERR "lp%d printer error\n", minor); LP_F(minor) &= ~LP_BUSY; - return -EIO; + ret = -EIO; + goto out; } } lp_table[minor].lp_buffer = kmalloc(LP_BUFFER_SIZE, GFP_KERNEL); if (!lp_table[minor].lp_buffer) { LP_F(minor) &= ~LP_BUSY; - return -ENOMEM; + ret = -ENOMEM; + goto out; } /* Determine if the peripheral supports ECP mode */ lp_claim_parport_or_block (&lp_table[minor]); @@ -540,7 +552,9 @@ static int lp_open(struct inode * inode, struct file * file) parport_negotiate (lp_table[minor].dev->port, IEEE1284_MODE_COMPAT); lp_release_parport (&lp_table[minor]); lp_table[minor].current_mode = IEEE1284_MODE_COMPAT; - return 0; +out: + unlock_kernel(); + return ret; } static int lp_release(struct inode * inode, struct file * file) diff --git a/drivers/char/mbcs.c b/drivers/char/mbcs.c index f4716ad7348a..acd8e9ed474a 100644 --- a/drivers/char/mbcs.c +++ b/drivers/char/mbcs.c @@ -24,6 +24,7 @@ #include <linux/mm.h> #include <linux/uio.h> #include <linux/mutex.h> +#include <linux/smp_lock.h> #include <asm/io.h> #include <asm/uaccess.h> #include <asm/system.h> @@ -382,15 +383,19 @@ static int mbcs_open(struct inode *ip, struct file *fp) struct mbcs_soft *soft; int minor; + lock_kernel(); minor = iminor(ip); + /* Nothing protects access to this list... */ list_for_each_entry(soft, &soft_list, list) { if (soft->nasid == minor) { fp->private_data = soft->cxdev; + unlock_kernel(); return 0; } } + unlock_kernel(); return -ENODEV; } diff --git a/drivers/char/mem.c b/drivers/char/mem.c index 934ffafedaea..070e22e8ea9e 100644 --- a/drivers/char/mem.c +++ b/drivers/char/mem.c @@ -26,6 +26,7 @@ #include <linux/bootmem.h> #include <linux/splice.h> #include <linux/pfn.h> +#include <linux/smp_lock.h> #include <asm/uaccess.h> #include <asm/io.h> @@ -889,6 +890,9 @@ static const struct file_operations kmsg_fops = { static int memory_open(struct inode * inode, struct file * filp) { + int ret = 0; + + lock_kernel(); switch (iminor(inode)) { case 1: filp->f_op = &mem_fops; @@ -932,11 +936,13 @@ static int memory_open(struct inode * inode, struct file * filp) break; #endif default: + unlock_kernel(); return -ENXIO; } if (filp->f_op && filp->f_op->open) - return filp->f_op->open(inode,filp); - return 0; + ret = filp->f_op->open(inode,filp); + unlock_kernel(); + return ret; } static const struct file_operations memory_fops = { diff --git a/drivers/char/misc.c b/drivers/char/misc.c index eaace0db0ff4..6e1563c3d30a 100644 --- a/drivers/char/misc.c +++ b/drivers/char/misc.c @@ -49,6 +49,7 @@ #include <linux/device.h> #include <linux/tty.h> #include <linux/kmod.h> +#include <linux/smp_lock.h> /* * Head entry for the doubly linked miscdevice list @@ -118,6 +119,7 @@ static int misc_open(struct inode * inode, struct file * file) int err = -ENODEV; const struct file_operations *old_fops, *new_fops = NULL; + lock_kernel(); mutex_lock(&misc_mtx); list_for_each_entry(c, &misc_list, list) { @@ -155,6 +157,7 @@ static int misc_open(struct inode * inode, struct file * file) fops_put(old_fops); fail: mutex_unlock(&misc_mtx); + unlock_kernel(); return err; } diff --git a/drivers/char/mwave/mwavedd.c b/drivers/char/mwave/mwavedd.c index 8d14823b0514..50243fcd87e8 100644 --- a/drivers/char/mwave/mwavedd.c +++ b/drivers/char/mwave/mwavedd.c @@ -56,6 +56,7 @@ #include <linux/serial.h> #include <linux/sched.h> #include <linux/spinlock.h> +#include <linux/smp_lock.h> #include <linux/delay.h> #include <linux/serial_8250.h> #include "smapi.h" @@ -100,6 +101,7 @@ static int mwave_open(struct inode *inode, struct file *file) PRINTK_2(TRACE_MWAVE, "mwavedd::mwave_open, exit return retval %x\n", retval); + cycle_kernel_lock(); return retval; } diff --git a/drivers/char/nvram.c b/drivers/char/nvram.c index 98dec380af49..197cd7a0c332 100644 --- a/drivers/char/nvram.c +++ b/drivers/char/nvram.c @@ -107,6 +107,7 @@ #include <linux/init.h> #include <linux/proc_fs.h> #include <linux/spinlock.h> +#include <linux/smp_lock.h> #include <asm/io.h> #include <asm/uaccess.h> @@ -333,12 +334,14 @@ nvram_ioctl(struct inode *inode, struct file *file, static int nvram_open(struct inode *inode, struct file *file) { + lock_kernel(); spin_lock(&nvram_state_lock); if ((nvram_open_cnt && (file->f_flags & O_EXCL)) || (nvram_open_mode & NVRAM_EXCL) || ((file->f_mode & 2) && (nvram_open_mode & NVRAM_WRITE))) { spin_unlock(&nvram_state_lock); + unlock_kernel(); return -EBUSY; } @@ -349,6 +352,7 @@ nvram_open(struct inode *inode, struct file *file) nvram_open_cnt++; spin_unlock(&nvram_state_lock); + unlock_kernel(); return 0; } diff --git a/drivers/char/pc8736x_gpio.c b/drivers/char/pc8736x_gpio.c index ecfaf180e5bd..b930de50407a 100644 --- a/drivers/char/pc8736x_gpio.c +++ b/drivers/char/pc8736x_gpio.c @@ -20,6 +20,7 @@ #include <linux/mutex.h> #include <linux/nsc_gpio.h> #include <linux/platform_device.h> +#include <linux/smp_lock.h> #include <asm/uaccess.h> #define DEVNAME "pc8736x_gpio" @@ -217,6 +218,7 @@ static int pc8736x_gpio_open(struct inode *inode, struct file *file) unsigned m = iminor(inode); file->private_data = &pc8736x_gpio_ops; + cycle_kernel_lock(); dev_dbg(&pdev->dev, "open %d\n", m); if (m >= PC8736X_GPIO_CT) diff --git a/drivers/char/ppdev.c b/drivers/char/ppdev.c index 3aab837d9480..f6e6acadd9a0 100644 --- a/drivers/char/ppdev.c +++ b/drivers/char/ppdev.c @@ -66,6 +66,7 @@ #include <linux/poll.h> #include <linux/major.h> #include <linux/ppdev.h> +#include <linux/smp_lock.h> #include <asm/uaccess.h> #define PP_VERSION "ppdev: user-space parallel port driver" @@ -638,6 +639,7 @@ static int pp_open (struct inode * inode, struct file * file) unsigned int minor = iminor(inode); struct pp_struct *pp; + cycle_kernel_lock(); if (minor >= PARPORT_MAX) return -ENXIO; diff --git a/drivers/char/raw.c b/drivers/char/raw.c index bbfa0e241cba..505fcbe884a4 100644 --- a/drivers/char/raw.c +++ b/drivers/char/raw.c @@ -19,6 +19,7 @@ #include <linux/cdev.h> #include <linux/device.h> #include <linux/mutex.h> +#include <linux/smp_lock.h> #include <asm/uaccess.h> @@ -53,6 +54,7 @@ static int raw_open(struct inode *inode, struct file *filp) return 0; } + lock_kernel(); mutex_lock(&raw_mutex); /* @@ -79,6 +81,7 @@ static int raw_open(struct inode *inode, struct file *filp) bdev->bd_inode->i_mapping; filp->private_data = bdev; mutex_unlock(&raw_mutex); + unlock_kernel(); return 0; out2: diff --git a/drivers/char/rtc.c b/drivers/char/rtc.c index 909cac93fa2a..fa92a8af5a5a 100644 --- a/drivers/char/rtc.c +++ b/drivers/char/rtc.c @@ -73,6 +73,7 @@ #include <linux/proc_fs.h> #include <linux/seq_file.h> #include <linux/spinlock.h> +#include <linux/smp_lock.h> #include <linux/sysctl.h> #include <linux/wait.h> #include <linux/bcd.h> @@ -734,6 +735,7 @@ static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, * needed here. Or anywhere else in this driver. */ static int rtc_open(struct inode *inode, struct file *file) { + lock_kernel(); spin_lock_irq(&rtc_lock); if (rtc_status & RTC_IS_OPEN) @@ -743,10 +745,12 @@ static int rtc_open(struct inode *inode, struct file *file) rtc_irq_data = 0; spin_unlock_irq(&rtc_lock); + unlock_kernel(); return 0; out_busy: spin_unlock_irq(&rtc_lock); + unlock_kernel(); return -EBUSY; } diff --git a/drivers/char/scx200_gpio.c b/drivers/char/scx200_gpio.c index 99e5272e3c53..1d9100561c8a 100644 --- a/drivers/char/scx200_gpio.c +++ b/drivers/char/scx200_gpio.c @@ -12,6 +12,7 @@ #include <linux/kernel.h> #include <linux/init.h> #include <linux/platform_device.h> +#include <linux/smp_lock.h> #include <asm/uaccess.h> #include <asm/io.h> @@ -51,6 +52,7 @@ static int scx200_gpio_open(struct inode *inode, struct file *file) unsigned m = iminor(inode); file->private_data = &scx200_gpio_ops; + cycle_kernel_lock(); if (m >= MAX_PINS) return -EINVAL; return nonseekable_open(inode, file); diff --git a/drivers/char/snsc.c b/drivers/char/snsc.c index 8fe099a41065..0b799ac1b049 100644 --- a/drivers/char/snsc.c +++ b/drivers/char/snsc.c @@ -21,6 +21,7 @@ #include <linux/poll.h> #include <linux/module.h> #include <linux/slab.h> +#include <linux/smp_lock.h> #include <asm/sn/io.h> #include <asm/sn/sn_sal.h> #include <asm/sn/module.h> @@ -104,6 +105,7 @@ scdrv_open(struct inode *inode, struct file *file) file->private_data = sd; /* hook this subchannel up to the system controller interrupt */ + lock_kernel(); rv = request_irq(SGI_UART_VECTOR, scdrv_interrupt, IRQF_SHARED | IRQF_DISABLED, SYSCTL_BASENAME, sd); @@ -111,9 +113,10 @@ scdrv_open(struct inode *inode, struct file *file) ia64_sn_irtr_close(sd->sd_nasid, sd->sd_subch); kfree(sd); printk("%s: irq request failed (%d)\n", __func__, rv); + unlock_kernel(); return -EBUSY; } - + unlock_kernel(); return 0; } diff --git a/drivers/char/sonypi.c b/drivers/char/sonypi.c index 58533de59027..85e0eb76eeab 100644 --- a/drivers/char/sonypi.c +++ b/drivers/char/sonypi.c @@ -49,6 +49,7 @@ #include <linux/err.h> #include <linux/kfifo.h> #include <linux/platform_device.h> +#include <linux/smp_lock.h> #include <asm/uaccess.h> #include <asm/io.h> @@ -906,12 +907,14 @@ static int sonypi_misc_release(struct inode *inode, struct file *file) static int sonypi_misc_open(struct inode *inode, struct file *file) { + lock_kernel(); mutex_lock(&sonypi_device.lock); /* Flush input queue on first open */ if (!sonypi_device.open_count) kfifo_reset(sonypi_device.fifo); sonypi_device.open_count++; mutex_unlock(&sonypi_device.lock); + unlock_kernel(); return 0; } diff --git a/drivers/char/tb0219.c b/drivers/char/tb0219.c index 4c431cb7cf1b..6062b62800fd 100644 --- a/drivers/char/tb0219.c +++ b/drivers/char/tb0219.c @@ -21,6 +21,7 @@ #include <linux/fs.h> #include <linux/init.h> #include <linux/module.h> +#include <linux/smp_lock.h> #include <asm/io.h> #include <asm/reboot.h> @@ -236,6 +237,7 @@ static int tanbac_tb0219_open(struct inode *inode, struct file *file) { unsigned int minor; + cycle_kernel_lock(); minor = iminor(inode); switch (minor) { case 0: diff --git a/drivers/char/tlclk.c b/drivers/char/tlclk.c index 35e58030d296..8f2284be68e1 100644 --- a/drivers/char/tlclk.c +++ b/drivers/char/tlclk.c @@ -36,6 +36,7 @@ #include <linux/ioport.h> #include <linux/interrupt.h> #include <linux/spinlock.h> +#include <linux/smp_lock.h> #include <linux/timer.h> #include <linux/sysfs.h> #include <linux/device.h> @@ -204,11 +205,14 @@ static int tlclk_open(struct inode *inode, struct file *filp) { int result; - if (test_and_set_bit(0, &useflags)) - return -EBUSY; + lock_kernel(); + if (test_and_set_bit(0, &useflags)) { + result = -EBUSY; /* this legacy device is always one per system and it doesn't * know how to handle multiple concurrent clients. */ + goto out; + } /* Make sure there is no interrupt pending while * initialising interrupt handler */ @@ -218,13 +222,14 @@ static int tlclk_open(struct inode *inode, struct file *filp) * we can't share this IRQ */ result = request_irq(telclk_interrupt, &tlclk_interrupt, IRQF_DISABLED, "telco_clock", tlclk_interrupt); - if (result == -EBUSY) { + if (result == -EBUSY) printk(KERN_ERR "tlclk: Interrupt can't be reserved.\n"); - return -EBUSY; - } - inb(TLCLK_REG6); /* Clear interrupt events */ + else + inb(TLCLK_REG6); /* Clear interrupt events */ - return 0; +out: + unlock_kernel(); + return result; } static int tlclk_release(struct inode *inode, struct file *filp) diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c index a5d8bcb40000..e1fc193d9396 100644 --- a/drivers/char/tpm/tpm.c +++ b/drivers/char/tpm/tpm.c @@ -26,6 +26,7 @@ #include <linux/poll.h> #include <linux/mutex.h> #include <linux/spinlock.h> +#include <linux/smp_lock.h> #include "tpm.h" @@ -897,6 +898,7 @@ int tpm_open(struct inode *inode, struct file *file) int rc = 0, minor = iminor(inode); struct tpm_chip *chip = NULL, *pos; + lock_kernel(); spin_lock(&driver_lock); list_for_each_entry(pos, &tpm_chip_list, list) { @@ -926,16 +928,19 @@ int tpm_open(struct inode *inode, struct file *file) if (chip->data_buffer == NULL) { chip->num_opens--; put_device(chip->dev); + unlock_kernel(); return -ENOMEM; } atomic_set(&chip->data_pending, 0); file->private_data = chip; + unlock_kernel(); return 0; err_out: spin_unlock(&driver_lock); + unlock_kernel(); return rc; } EXPORT_SYMBOL_GPL(tpm_open); diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index 750131010af0..047a17339f83 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c @@ -2665,7 +2665,7 @@ static void release_dev(struct file *filp) * ->siglock protects ->signal/->sighand */ -static int tty_open(struct inode *inode, struct file *filp) +static int __tty_open(struct inode *inode, struct file *filp) { struct tty_struct *tty; int noctty, retval; @@ -2779,6 +2779,19 @@ got_driver: return 0; } +/* BKL pushdown: scary code avoidance wrapper */ +static int tty_open(struct inode *inode, struct file *filp) +{ + int ret; + + lock_kernel(); + ret = __tty_open(inode, filp); + unlock_kernel(); + return ret; +} + + + #ifdef CONFIG_UNIX98_PTYS /** * ptmx_open - open a unix 98 pty master @@ -2792,7 +2805,7 @@ got_driver: * allocated_ptys_lock handles the list of free pty numbers */ -static int ptmx_open(struct inode *inode, struct file *filp) +static int __ptmx_open(struct inode *inode, struct file *filp) { struct tty_struct *tty; int retval; @@ -2831,6 +2844,16 @@ out: devpts_kill_index(index); return retval; } + +static int ptmx_open(struct inode *inode, struct file *filp) +{ + int ret; + + lock_kernel(); + ret = __ptmx_open(inode, filp); + unlock_kernel(); + return ret; +} #endif /** @@ -2886,15 +2909,16 @@ static int tty_fasync(int fd, struct file *filp, int on) { struct tty_struct *tty; unsigned long flags; - int retval; + int retval = 0; + lock_kernel(); tty = (struct tty_struct *)filp->private_data; if (tty_paranoia_check(tty, filp->f_path.dentry->d_inode, "tty_fasync")) - return 0; + goto out; retval = fasync_helper(fd, filp, on, &tty->fasync); if (retval <= 0) - return retval; + goto out; if (on) { enum pid_type type; @@ -2912,12 +2936,15 @@ static int tty_fasync(int fd, struct file *filp, int on) spin_unlock_irqrestore(&tty->ctrl_lock, flags); retval = __f_setown(filp, pid, type, 0); if (retval) - return retval; + goto out; } else { if (!tty->fasync && !waitqueue_active(&tty->read_wait)) tty->minimum_to_wake = N_TTY_BUF_SIZE; } - return 0; + retval = 0; +out: + unlock_kernel(); + return retval; } /** diff --git a/drivers/char/vc_screen.c b/drivers/char/vc_screen.c index 83aeedda200c..eebfad2777d2 100644 --- a/drivers/char/vc_screen.c +++ b/drivers/char/vc_screen.c @@ -34,6 +34,7 @@ #include <linux/kbd_kern.h> #include <linux/console.h> #include <linux/device.h> +#include <linux/smp_lock.h> #include <asm/uaccess.h> #include <asm/byteorder.h> @@ -460,9 +461,13 @@ static int vcs_open(struct inode *inode, struct file *filp) { unsigned int currcons = iminor(inode) & 127; + int ret = 0; + + lock_kernel(); if(currcons && !vc_cons_allocated(currcons-1)) - return -ENXIO; - return 0; + ret = -ENXIO; + unlock_kernel(); + return ret; } static const struct file_operations vcs_fops = { diff --git a/drivers/char/viotape.c b/drivers/char/viotape.c index c39ddaff5e8f..977f7d35e769 100644 --- a/drivers/char/viotape.c +++ b/drivers/char/viotape.c @@ -46,6 +46,7 @@ #include <linux/completion.h> #include <linux/proc_fs.h> #include <linux/seq_file.h> +#include <linux/smp_lock.h> #include <asm/uaccess.h> #include <asm/ioctls.h> @@ -687,6 +688,7 @@ static int viotap_open(struct inode *inode, struct file *file) if (op == NULL) return -ENOMEM; + lock_kernel(); get_dev_info(file->f_path.dentry->d_inode, &devi); /* Note: We currently only support one mode! */ @@ -717,6 +719,7 @@ static int viotap_open(struct inode *inode, struct file *file) free_op: free_op_struct(op); + unlock_kernel(); return ret; } diff --git a/drivers/char/vr41xx_giu.c b/drivers/char/vr41xx_giu.c index e5ed09192be8..ffe9b4e3072e 100644 --- a/drivers/char/vr41xx_giu.c +++ b/drivers/char/vr41xx_giu.c @@ -27,6 +27,7 @@ #include <linux/kernel.h> #include <linux/module.h> #include <linux/platform_device.h> +#include <linux/smp_lock.h> #include <linux/spinlock.h> #include <linux/types.h> @@ -547,6 +548,7 @@ static int gpio_open(struct inode *inode, struct file *file) { unsigned int pin; + cycle_kernel_lock(); pin = iminor(inode); if (pin >= giu_nr_pins) return -EBADF; diff --git a/drivers/char/xilinx_hwicap/xilinx_hwicap.c b/drivers/char/xilinx_hwicap/xilinx_hwicap.c index 3edf1fc12963..1e1b81e57cdc 100644 --- a/drivers/char/xilinx_hwicap/xilinx_hwicap.c +++ b/drivers/char/xilinx_hwicap/xilinx_hwicap.c @@ -85,6 +85,7 @@ #include <linux/poll.h> #include <linux/proc_fs.h> #include <linux/mutex.h> +#include <linux/smp_lock.h> #include <linux/sysctl.h> #include <linux/version.h> #include <linux/fs.h> @@ -504,11 +505,12 @@ static int hwicap_open(struct inode *inode, struct file *file) struct hwicap_drvdata *drvdata; int status; + lock_kernel(); drvdata = container_of(inode->i_cdev, struct hwicap_drvdata, cdev); status = mutex_lock_interruptible(&drvdata->sem); if (status) - return status; + goto out; if (drvdata->is_open) { status = -EBUSY; @@ -528,6 +530,8 @@ static int hwicap_open(struct inode *inode, struct file *file) error: mutex_unlock(&drvdata->sem); + out: + unlock_kernel(); return status; } |