]> git.karo-electronics.de Git - linux-beck.git/commitdiff
Merge 3.15-rc6 into driver-core-next
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 23 May 2014 01:13:53 +0000 (10:13 +0900)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 23 May 2014 01:13:53 +0000 (10:13 +0900)
We want the kernfs fixes in this branch as well for testing.

Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1  2 
fs/kernfs/file.c
include/linux/kernfs.h

diff --combined fs/kernfs/file.c
index 40251cd741a0835835d8565f7f855c2db0321576,5e9a80cfc3d8857c7cfe496eae627c921c47c6f2..e3d37f607f975dd06f6c9534b2dc929c3fa5fa21
@@@ -14,7 -14,6 +14,7 @@@
  #include <linux/poll.h>
  #include <linux/pagemap.h>
  #include <linux/sched.h>
 +#include <linux/fsnotify.h>
  
  #include "kernfs-internal.h"
  
@@@ -611,6 -610,7 +611,7 @@@ static void kernfs_put_open_node(struc
  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;
        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;
@@@ -788,48 -790,20 +791,48 @@@ static unsigned int kernfs_fop_poll(str
   */
  void kernfs_notify(struct kernfs_node *kn)
  {
 +      struct kernfs_root *root = kernfs_root(kn);
        struct kernfs_open_node *on;
 +      struct kernfs_super_info *info;
        unsigned long flags;
  
 +      if (WARN_ON(kernfs_type(kn) != KERNFS_FILE))
 +              return;
 +
 +      /* kick poll */
        spin_lock_irqsave(&kernfs_open_node_lock, flags);
  
 -      if (!WARN_ON(kernfs_type(kn) != KERNFS_FILE)) {
 -              on = kn->attr.open;
 -              if (on) {
 -                      atomic_inc(&on->event);
 -                      wake_up_interruptible(&on->poll);
 -              }
 +      on = kn->attr.open;
 +      if (on) {
 +              atomic_inc(&on->event);
 +              wake_up_interruptible(&on->poll);
        }
  
        spin_unlock_irqrestore(&kernfs_open_node_lock, flags);
 +
 +      /* kick fsnotify */
 +      mutex_lock(&kernfs_mutex);
 +
 +      list_for_each_entry(info, &root->supers, node) {
 +              struct inode *inode;
 +              struct dentry *dentry;
 +
 +              inode = ilookup(info->sb, kn->ino);
 +              if (!inode)
 +                      continue;
 +
 +              dentry = d_find_any_alias(inode);
 +              if (dentry) {
 +                      fsnotify_parent(NULL, dentry, FS_MODIFY);
 +                      fsnotify(inode, FS_MODIFY, inode, FSNOTIFY_EVENT_INODE,
 +                               NULL, 0);
 +                      dput(dentry);
 +              }
 +
 +              iput(inode);
 +      }
 +
 +      mutex_unlock(&kernfs_mutex);
  }
  EXPORT_SYMBOL_GPL(kernfs_notify);
  
diff --combined include/linux/kernfs.h
index 589318b73e6155f8be282e75e0bdaa471c566b7d,ca1be5c9136c4557de511143b4c9b36e1eec3734..c841688a78a3b166919135152f247a0cfc2fbb81
@@@ -50,7 -50,24 +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 */
@@@ -144,10 -161,6 +161,10 @@@ struct kernfs_root 
        /* private fields, do not use outside kernfs proper */
        struct ida              ino_ida;
        struct kernfs_syscall_ops *syscall_ops;
 +
 +      /* list of kernfs_super_info of this root, protected by kernfs_mutex */
 +      struct list_head        supers;
 +
        wait_queue_head_t       deactivate_waitq;
  };