From patchwork Wed May 12 18:47:13 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chris Wright X-Patchwork-Id: 99080 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter.kernel.org (8.14.3/8.14.3) with ESMTP id o4CIlwHH014836 for ; Wed, 12 May 2010 18:47:58 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754924Ab0ELSrd (ORCPT ); Wed, 12 May 2010 14:47:33 -0400 Received: from sous-sol.org ([216.99.217.87]:55672 "EHLO sequoia.sous-sol.org" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1754771Ab0ELSrc (ORCPT ); Wed, 12 May 2010 14:47:32 -0400 Received: from sequoia.sous-sol.org (sequoia.sous-sol.org [127.0.0.1]) by sequoia.sous-sol.org (8.14.3/8.14.3) with ESMTP id o4CIlDQG005860; Wed, 12 May 2010 11:47:13 -0700 Received: (from chrisw@localhost) by sequoia.sous-sol.org (8.14.3/8.14.3/Submit) id o4CIlDe1005857; Wed, 12 May 2010 11:47:13 -0700 Date: Wed, 12 May 2010 11:47:13 -0700 From: Chris Wright To: greg@kroah.com, jbarnes@virtuousgeek.org, matthew@wil.cx Cc: linux-pci@vger.kernel.org, linux-kernel@vger.kernel.org, kvm@vger.kernel.org, ddutile@redhat.com, alex.williamson@redhat.com Subject: [RFC PATCH] sysfs: bin_attr permission checking Message-ID: <20100512184713.GV28034@sequoia.sous-sol.org> MIME-Version: 1.0 Content-Disposition: inline User-Agent: Mutt/1.5.20 (2009-08-17) X-Virus-Scanned: clamav-milter 0.95.3 at sequoia.sous-sol.org X-Virus-Status: Clean X-Spam-Status: No, score=-2.9 required=5.0 tests=ALL_TRUSTED,BAYES_00, T_RP_MATCHES_RCVD autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on sequoia.sous-sol.org Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.3 (demeter.kernel.org [140.211.167.41]); Wed, 12 May 2010 18:47:59 +0000 (UTC) --- a/drivers/pci/pci-sysfs.c +++ b/drivers/pci/pci-sysfs.c @@ -23,6 +23,7 @@ #include #include #include +#include #include "pci.h" static int sysfs_initialized; /* = 0 */ @@ -356,16 +357,18 @@ boot_vga_show(struct device *dev, struct struct device_attribute vga_attr = __ATTR_RO(boot_vga); static ssize_t -pci_read_config(struct kobject *kobj, struct bin_attribute *bin_attr, - char *buf, loff_t off, size_t count) +pci_read_config(struct file *file, struct kobject *kobj, + struct bin_attribute *bin_attr, char *buf, loff_t off, + size_t count) { struct pci_dev *dev = to_pci_dev(container_of(kobj,struct device,kobj)); + struct inode *inode = file->f_path.dentry->d_inode; unsigned int size = 64; loff_t init_off = off; u8 *data = (u8*) buf; /* Several chips lock up trying to read undefined config space */ - if (capable(CAP_SYS_ADMIN)) { + if (capable(CAP_SYS_ADMIN) || is_owner_or_cap(inode)) { size = dev->cfg_size; } else if (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS) { size = 128; @@ -924,7 +927,7 @@ static struct bin_attribute pci_config_a .mode = S_IRUGO | S_IWUSR, }, .size = PCI_CFG_SPACE_SIZE, - .read = pci_read_config, + .read_file = pci_read_config, .write = pci_write_config, }; @@ -934,7 +937,7 @@ static struct bin_attribute pcie_config_ .mode = S_IRUGO | S_IWUSR, }, .size = PCI_CFG_SPACE_EXP_SIZE, - .read = pci_read_config, + .read_file = pci_read_config, .write = pci_write_config, }; --- a/fs/sysfs/bin.c +++ b/fs/sysfs/bin.c @@ -46,9 +46,9 @@ struct bin_buffer { }; static int -fill_read(struct dentry *dentry, char *buffer, loff_t off, size_t count) +fill_read(struct file *file, char *buffer, loff_t off, size_t count) { - struct sysfs_dirent *attr_sd = dentry->d_fsdata; + struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata; struct bin_attribute *attr = attr_sd->s_bin_attr.bin_attr; struct kobject *kobj = attr_sd->s_parent->s_dir.kobj; int rc; @@ -58,7 +58,9 @@ fill_read(struct dentry *dentry, char *b return -ENODEV; rc = -EIO; - if (attr->read) + if (attr->read_file) + rc = attr->read_file(file, kobj, attr, buffer, off, count); + else if (attr->read) rc = attr->read(kobj, attr, buffer, off, count); sysfs_put_active_two(attr_sd); @@ -70,8 +72,7 @@ static ssize_t read(struct file *file, char __user *userbuf, size_t bytes, loff_t *off) { struct bin_buffer *bb = file->private_data; - struct dentry *dentry = file->f_path.dentry; - int size = dentry->d_inode->i_size; + int size = file->f_path.dentry->d_inode->i_size; loff_t offs = *off; int count = min_t(size_t, bytes, PAGE_SIZE); char *temp; @@ -92,7 +93,7 @@ read(struct file *file, char __user *use mutex_lock(&bb->mutex); - count = fill_read(dentry, bb->buffer, offs, count); + count = fill_read(file, bb->buffer, offs, count); if (count < 0) { mutex_unlock(&bb->mutex); goto out_free; @@ -405,7 +406,8 @@ static int open(struct inode * inode, st error = -EACCES; if ((file->f_mode & FMODE_WRITE) && !(attr->write || attr->mmap)) goto err_out; - if ((file->f_mode & FMODE_READ) && !(attr->read || attr->mmap)) + if ((file->f_mode & FMODE_READ) && + !(attr->read || attr->read_file || attr->mmap)) goto err_out; error = -ENOMEM; --- a/include/linux/sysfs.h +++ b/include/linux/sysfs.h @@ -66,6 +66,8 @@ struct bin_attribute { struct attribute attr; size_t size; void *private; + ssize_t (*read_file)(struct file *,struct kobject *, struct bin_attribute *, + char *, loff_t, size_t); ssize_t (*read)(struct kobject *, struct bin_attribute *, char *, loff_t, size_t); ssize_t (*write)(struct kobject *, struct bin_attribute *,