diff options
author | Alan Cox <alan@lxorguk.ukuu.org.uk> | 2008-07-25 04:48:15 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-07-25 13:53:43 -0400 |
commit | 11af7478addd34c42999b3b84095903ed9e67038 (patch) | |
tree | 90f5fb01fe1b49cef020c275f448d7eed2fbe3a9 /drivers/char/sx.c | |
parent | f6759fdcfd79ff1827fd5d4ddfe876164466d30d (diff) |
sx: push BKL down into the firmware ioctl handler
Also fix the capability checking for firmware load.
Signed-off-by: Alan Cox <alan@redhat.com>
Cc: Jiri Slaby <jirislaby@gmail.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/char/sx.c')
-rw-r--r-- | drivers/char/sx.c | 73 |
1 files changed, 43 insertions, 30 deletions
diff --git a/drivers/char/sx.c b/drivers/char/sx.c index 2162439bbe48..c385206f9db5 100644 --- a/drivers/char/sx.c +++ b/drivers/char/sx.c | |||
@@ -286,8 +286,8 @@ static void sx_close(void *ptr); | |||
286 | static int sx_chars_in_buffer(void *ptr); | 286 | static int sx_chars_in_buffer(void *ptr); |
287 | static int sx_init_board(struct sx_board *board); | 287 | static int sx_init_board(struct sx_board *board); |
288 | static int sx_init_portstructs(int nboards, int nports); | 288 | static int sx_init_portstructs(int nboards, int nports); |
289 | static int sx_fw_ioctl(struct inode *inode, struct file *filp, | 289 | static long sx_fw_ioctl(struct file *filp, unsigned int cmd, |
290 | unsigned int cmd, unsigned long arg); | 290 | unsigned long arg); |
291 | static int sx_init_drivers(void); | 291 | static int sx_init_drivers(void); |
292 | 292 | ||
293 | static struct tty_driver *sx_driver; | 293 | static struct tty_driver *sx_driver; |
@@ -396,7 +396,7 @@ static struct real_driver sx_real_driver = { | |||
396 | 396 | ||
397 | static const struct file_operations sx_fw_fops = { | 397 | static const struct file_operations sx_fw_fops = { |
398 | .owner = THIS_MODULE, | 398 | .owner = THIS_MODULE, |
399 | .ioctl = sx_fw_ioctl, | 399 | .unlocked_ioctl = sx_fw_ioctl, |
400 | }; | 400 | }; |
401 | 401 | ||
402 | static struct miscdevice sx_fw_device = { | 402 | static struct miscdevice sx_fw_device = { |
@@ -1686,10 +1686,10 @@ static int do_memtest_w(struct sx_board *board, int min, int max) | |||
1686 | } | 1686 | } |
1687 | #endif | 1687 | #endif |
1688 | 1688 | ||
1689 | static int sx_fw_ioctl(struct inode *inode, struct file *filp, | 1689 | static long sx_fw_ioctl(struct file *filp, unsigned int cmd, |
1690 | unsigned int cmd, unsigned long arg) | 1690 | unsigned long arg) |
1691 | { | 1691 | { |
1692 | int rc = 0; | 1692 | long rc = 0; |
1693 | int __user *descr = (int __user *)arg; | 1693 | int __user *descr = (int __user *)arg; |
1694 | int i; | 1694 | int i; |
1695 | static struct sx_board *board = NULL; | 1695 | static struct sx_board *board = NULL; |
@@ -1699,13 +1699,10 @@ static int sx_fw_ioctl(struct inode *inode, struct file *filp, | |||
1699 | 1699 | ||
1700 | func_enter(); | 1700 | func_enter(); |
1701 | 1701 | ||
1702 | #if 0 | 1702 | if (!capable(CAP_SYS_RAWIO)) |
1703 | /* Removed superuser check: Sysops can use the permissions on the device | ||
1704 | file to restrict access. Recommendation: Root only. (root.root 600) */ | ||
1705 | if (!capable(CAP_SYS_ADMIN)) { | ||
1706 | return -EPERM; | 1703 | return -EPERM; |
1707 | } | 1704 | |
1708 | #endif | 1705 | lock_kernel(); |
1709 | 1706 | ||
1710 | sx_dprintk(SX_DEBUG_FIRMWARE, "IOCTL %x: %lx\n", cmd, arg); | 1707 | sx_dprintk(SX_DEBUG_FIRMWARE, "IOCTL %x: %lx\n", cmd, arg); |
1711 | 1708 | ||
@@ -1720,19 +1717,23 @@ static int sx_fw_ioctl(struct inode *inode, struct file *filp, | |||
1720 | for (i = 0; i < SX_NBOARDS; i++) | 1717 | for (i = 0; i < SX_NBOARDS; i++) |
1721 | sx_dprintk(SX_DEBUG_FIRMWARE, "<%x> ", boards[i].flags); | 1718 | sx_dprintk(SX_DEBUG_FIRMWARE, "<%x> ", boards[i].flags); |
1722 | sx_dprintk(SX_DEBUG_FIRMWARE, "\n"); | 1719 | sx_dprintk(SX_DEBUG_FIRMWARE, "\n"); |
1720 | unlock_kernel(); | ||
1723 | return -EIO; | 1721 | return -EIO; |
1724 | } | 1722 | } |
1725 | 1723 | ||
1726 | switch (cmd) { | 1724 | switch (cmd) { |
1727 | case SXIO_SET_BOARD: | 1725 | case SXIO_SET_BOARD: |
1728 | sx_dprintk(SX_DEBUG_FIRMWARE, "set board to %ld\n", arg); | 1726 | sx_dprintk(SX_DEBUG_FIRMWARE, "set board to %ld\n", arg); |
1727 | rc = -EIO; | ||
1729 | if (arg >= SX_NBOARDS) | 1728 | if (arg >= SX_NBOARDS) |
1730 | return -EIO; | 1729 | break; |
1731 | sx_dprintk(SX_DEBUG_FIRMWARE, "not out of range\n"); | 1730 | sx_dprintk(SX_DEBUG_FIRMWARE, "not out of range\n"); |
1732 | if (!(boards[arg].flags & SX_BOARD_PRESENT)) | 1731 | if (!(boards[arg].flags & SX_BOARD_PRESENT)) |
1733 | return -EIO; | 1732 | break; |
1734 | sx_dprintk(SX_DEBUG_FIRMWARE, ".. and present!\n"); | 1733 | sx_dprintk(SX_DEBUG_FIRMWARE, ".. and present!\n"); |
1735 | board = &boards[arg]; | 1734 | board = &boards[arg]; |
1735 | rc = 0; | ||
1736 | /* FIXME: And this does ... nothing?? */ | ||
1736 | break; | 1737 | break; |
1737 | case SXIO_GET_TYPE: | 1738 | case SXIO_GET_TYPE: |
1738 | rc = -ENOENT; /* If we manage to miss one, return error. */ | 1739 | rc = -ENOENT; /* If we manage to miss one, return error. */ |
@@ -1746,7 +1747,7 @@ static int sx_fw_ioctl(struct inode *inode, struct file *filp, | |||
1746 | rc = SX_TYPE_SI; | 1747 | rc = SX_TYPE_SI; |
1747 | if (IS_EISA_BOARD(board)) | 1748 | if (IS_EISA_BOARD(board)) |
1748 | rc = SX_TYPE_SI; | 1749 | rc = SX_TYPE_SI; |
1749 | sx_dprintk(SX_DEBUG_FIRMWARE, "returning type= %d\n", rc); | 1750 | sx_dprintk(SX_DEBUG_FIRMWARE, "returning type= %ld\n", rc); |
1750 | break; | 1751 | break; |
1751 | case SXIO_DO_RAMTEST: | 1752 | case SXIO_DO_RAMTEST: |
1752 | if (sx_initialized) /* Already initialized: better not ramtest the board. */ | 1753 | if (sx_initialized) /* Already initialized: better not ramtest the board. */ |
@@ -1760,19 +1761,26 @@ static int sx_fw_ioctl(struct inode *inode, struct file *filp, | |||
1760 | rc = do_memtest(board, 0, 0x7ff8); | 1761 | rc = do_memtest(board, 0, 0x7ff8); |
1761 | /* if (!rc) rc = do_memtest_w (board, 0, 0x7ff8); */ | 1762 | /* if (!rc) rc = do_memtest_w (board, 0, 0x7ff8); */ |
1762 | } | 1763 | } |
1763 | sx_dprintk(SX_DEBUG_FIRMWARE, "returning memtest result= %d\n", | 1764 | sx_dprintk(SX_DEBUG_FIRMWARE, |
1764 | rc); | 1765 | "returning memtest result= %ld\n", rc); |
1765 | break; | 1766 | break; |
1766 | case SXIO_DOWNLOAD: | 1767 | case SXIO_DOWNLOAD: |
1767 | if (sx_initialized) /* Already initialized */ | 1768 | if (sx_initialized) {/* Already initialized */ |
1768 | return -EEXIST; | 1769 | rc = -EEXIST; |
1769 | if (!sx_reset(board)) | 1770 | break; |
1770 | return -EIO; | 1771 | } |
1772 | if (!sx_reset(board)) { | ||
1773 | rc = -EIO; | ||
1774 | break; | ||
1775 | } | ||
1771 | sx_dprintk(SX_DEBUG_INIT, "reset the board...\n"); | 1776 | sx_dprintk(SX_DEBUG_INIT, "reset the board...\n"); |
1772 | 1777 | ||
1773 | tmp = kmalloc(SX_CHUNK_SIZE, GFP_USER); | 1778 | tmp = kmalloc(SX_CHUNK_SIZE, GFP_USER); |
1774 | if (!tmp) | 1779 | if (!tmp) { |
1775 | return -ENOMEM; | 1780 | rc = -ENOMEM; |
1781 | break; | ||
1782 | } | ||
1783 | /* FIXME: check returns */ | ||
1776 | get_user(nbytes, descr++); | 1784 | get_user(nbytes, descr++); |
1777 | get_user(offset, descr++); | 1785 | get_user(offset, descr++); |
1778 | get_user(data, descr++); | 1786 | get_user(data, descr++); |
@@ -1782,7 +1790,8 @@ static int sx_fw_ioctl(struct inode *inode, struct file *filp, | |||
1782 | (i + SX_CHUNK_SIZE > nbytes) ? | 1790 | (i + SX_CHUNK_SIZE > nbytes) ? |
1783 | nbytes - i : SX_CHUNK_SIZE)) { | 1791 | nbytes - i : SX_CHUNK_SIZE)) { |
1784 | kfree(tmp); | 1792 | kfree(tmp); |
1785 | return -EFAULT; | 1793 | rc = -EFAULT; |
1794 | break; | ||
1786 | } | 1795 | } |
1787 | memcpy_toio(board->base2 + offset + i, tmp, | 1796 | memcpy_toio(board->base2 + offset + i, tmp, |
1788 | (i + SX_CHUNK_SIZE > nbytes) ? | 1797 | (i + SX_CHUNK_SIZE > nbytes) ? |
@@ -1798,13 +1807,17 @@ static int sx_fw_ioctl(struct inode *inode, struct file *filp, | |||
1798 | rc = sx_nports; | 1807 | rc = sx_nports; |
1799 | break; | 1808 | break; |
1800 | case SXIO_INIT: | 1809 | case SXIO_INIT: |
1801 | if (sx_initialized) /* Already initialized */ | 1810 | if (sx_initialized) { /* Already initialized */ |
1802 | return -EEXIST; | 1811 | rc = -EEXIST; |
1812 | break; | ||
1813 | } | ||
1803 | /* This is not allowed until all boards are initialized... */ | 1814 | /* This is not allowed until all boards are initialized... */ |
1804 | for (i = 0; i < SX_NBOARDS; i++) { | 1815 | for (i = 0; i < SX_NBOARDS; i++) { |
1805 | if ((boards[i].flags & SX_BOARD_PRESENT) && | 1816 | if ((boards[i].flags & SX_BOARD_PRESENT) && |
1806 | !(boards[i].flags & SX_BOARD_INITIALIZED)) | 1817 | !(boards[i].flags & SX_BOARD_INITIALIZED)) { |
1807 | return -EIO; | 1818 | rc = -EIO; |
1819 | break; | ||
1820 | } | ||
1808 | } | 1821 | } |
1809 | for (i = 0; i < SX_NBOARDS; i++) | 1822 | for (i = 0; i < SX_NBOARDS; i++) |
1810 | if (!(boards[i].flags & SX_BOARD_PRESENT)) | 1823 | if (!(boards[i].flags & SX_BOARD_PRESENT)) |
@@ -1832,10 +1845,10 @@ static int sx_fw_ioctl(struct inode *inode, struct file *filp, | |||
1832 | rc = sx_nports; | 1845 | rc = sx_nports; |
1833 | break; | 1846 | break; |
1834 | default: | 1847 | default: |
1835 | printk(KERN_WARNING "Unknown ioctl on firmware device (%x).\n", | 1848 | rc = -ENOTTY; |
1836 | cmd); | ||
1837 | break; | 1849 | break; |
1838 | } | 1850 | } |
1851 | unlock_kernel(); | ||
1839 | func_exit(); | 1852 | func_exit(); |
1840 | return rc; | 1853 | return rc; |
1841 | } | 1854 | } |