Skip to content

Commit

Permalink
Merge tag 'driver-core-3.15-rc6' of git://git.kernel.org/pub/scm/linu…
Browse files Browse the repository at this point in the history
…x/kernel/git/gregkh/driver-core

Pull driver core fixes from Greg KH:
 "Here are two driver core (well, sysfs) fixes for 3.15-rc6 that resolve
  some reported issues and a regression from 3.13"

* tag 'driver-core-3.15-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core:
  sysfs: make sure read buffer is zeroed
  kernfs, sysfs, cgroup: restrict extra perm check on open to sysfs
  • Loading branch information
torvalds committed May 21, 2014
2 parents 957cf25 + f5c16f2 commit 439c610
Show file tree
Hide file tree
Showing 4 changed files with 32 additions and 10 deletions.
17 changes: 10 additions & 7 deletions fs/kernfs/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -610,6 +610,7 @@ static void kernfs_put_open_node(struct kernfs_node *kn,
static int kernfs_fop_open(struct inode *inode, struct file *file)
{
struct kernfs_node *kn = file->f_path.dentry->d_fsdata;
struct kernfs_root *root = kernfs_root(kn);
const struct kernfs_ops *ops;
struct kernfs_open_file *of;
bool has_read, has_write, has_mmap;
Expand All @@ -624,14 +625,16 @@ static int kernfs_fop_open(struct inode *inode, struct file *file)
has_write = ops->write || ops->mmap;
has_mmap = ops->mmap;

/* check perms and supported operations */
if ((file->f_mode & FMODE_WRITE) &&
(!(inode->i_mode & S_IWUGO) || !has_write))
goto err_out;
/* see the flag definition for details */
if (root->flags & KERNFS_ROOT_EXTRA_OPEN_PERM_CHECK) {
if ((file->f_mode & FMODE_WRITE) &&
(!(inode->i_mode & S_IWUGO) || !has_write))
goto err_out;

if ((file->f_mode & FMODE_READ) &&
(!(inode->i_mode & S_IRUGO) || !has_read))
goto err_out;
if ((file->f_mode & FMODE_READ) &&
(!(inode->i_mode & S_IRUGO) || !has_read))
goto err_out;
}

/* allocate a kernfs_open_file for the file */
error = -ENOMEM;
Expand Down
3 changes: 2 additions & 1 deletion fs/sysfs/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,13 @@ static int sysfs_kf_seq_show(struct seq_file *sf, void *v)
ssize_t count;
char *buf;

/* acquire buffer and ensure that it's >= PAGE_SIZE */
/* acquire buffer and ensure that it's >= PAGE_SIZE and clear */
count = seq_get_buf(sf, &buf);
if (count < PAGE_SIZE) {
seq_commit(sf, -1);
return 0;
}
memset(buf, 0, PAGE_SIZE);

/*
* Invoke show(). Control may reach here via seq file lseek even
Expand Down
3 changes: 2 additions & 1 deletion fs/sysfs/mount.c
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,8 @@ int __init sysfs_init(void)
{
int err;

sysfs_root = kernfs_create_root(NULL, 0, NULL);
sysfs_root = kernfs_create_root(NULL, KERNFS_ROOT_EXTRA_OPEN_PERM_CHECK,
NULL);
if (IS_ERR(sysfs_root))
return PTR_ERR(sysfs_root);

Expand Down
19 changes: 18 additions & 1 deletion include/linux/kernfs.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,24 @@ enum kernfs_node_flag {

/* @flags for kernfs_create_root() */
enum kernfs_root_flag {
KERNFS_ROOT_CREATE_DEACTIVATED = 0x0001,
/*
* kernfs_nodes are created in the deactivated state and invisible.
* They require explicit kernfs_activate() to become visible. This
* can be used to make related nodes become visible atomically
* after all nodes are created successfully.
*/
KERNFS_ROOT_CREATE_DEACTIVATED = 0x0001,

/*
* For regular flies, if the opener has CAP_DAC_OVERRIDE, open(2)
* succeeds regardless of the RW permissions. sysfs had an extra
* layer of enforcement where open(2) fails with -EACCES regardless
* of CAP_DAC_OVERRIDE if the permission doesn't have the
* respective read or write access at all (none of S_IRUGO or
* S_IWUGO) or the respective operation isn't implemented. The
* following flag enables that behavior.
*/
KERNFS_ROOT_EXTRA_OPEN_PERM_CHECK = 0x0002,
};

/* type-specific structures for kernfs_node union members */
Expand Down

0 comments on commit 439c610

Please sign in to comment.