]> git.ipfire.org Git - people/pmueller/ipfire-2.x.git/blobdiff - src/patches/suse-2.6.27.31/patches.suse/fs-may_iops.diff
Added missing Xen Kernel Patches which were not commited because
[people/pmueller/ipfire-2.x.git] / src / patches / suse-2.6.27.31 / patches.suse / fs-may_iops.diff
diff --git a/src/patches/suse-2.6.27.31/patches.suse/fs-may_iops.diff b/src/patches/suse-2.6.27.31/patches.suse/fs-may_iops.diff
new file mode 100644 (file)
index 0000000..9ee1ae6
--- /dev/null
@@ -0,0 +1,144 @@
+From: Andreas Gruenbacher <agruen@suse.de>
+Subject: VFS hooks for per-filesystem permission models
+    
+Add may_create and may_delete inode operations that filesystems can
+implement in order to override the vfs provided default behavior.
+This is required for implementing permission models which go beyond
+the traditional UNIX semantics.
+
+If a filesystem does not implement these hooks, the behavior is
+unchanged.
+
+Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
+
+---
+ fs/namei.c         |   48 +++++++++++++++++++++++++++++++++++++-----------
+ include/linux/fs.h |    2 ++
+ 2 files changed, 39 insertions(+), 11 deletions(-)
+
+--- a/fs/namei.c
++++ b/fs/namei.c
+@@ -1402,13 +1402,24 @@ static int may_delete(struct inode *dir,
+       BUG_ON(victim->d_parent->d_inode != dir);
+       audit_inode_child(victim->d_name.name, victim, dir);
+-      error = inode_permission(dir, MAY_WRITE | MAY_EXEC);
++      if (dir->i_op->may_delete) {
++              if (IS_RDONLY(dir))
++                      return -EROFS;
++              if (IS_IMMUTABLE(dir))
++                      return -EACCES;
++              error = dir->i_op->may_delete(dir, victim->d_inode);
++              if (!error)
++                      error = security_inode_permission(dir, MAY_WRITE | MAY_EXEC);
++      } else {
++              error = inode_permission(dir, MAY_WRITE | MAY_EXEC);
++              if (!error && check_sticky(dir, victim->d_inode))
++                      error = -EPERM;
++      }
+       if (error)
+               return error;
+       if (IS_APPEND(dir))
+               return -EPERM;
+-      if (check_sticky(dir, victim->d_inode)||IS_APPEND(victim->d_inode)||
+-          IS_IMMUTABLE(victim->d_inode))
++      if (IS_APPEND(victim->d_inode) || IS_IMMUTABLE(victim->d_inode))
+               return -EPERM;
+       if (isdir) {
+               if (!S_ISDIR(victim->d_inode->i_mode))
+@@ -1432,13 +1443,28 @@ static int may_delete(struct inode *dir,
+  *  3. We should have write and exec permissions on dir
+  *  4. We can't do it if dir is immutable (done in permission())
+  */
+-static inline int may_create(struct inode *dir, struct dentry *child)
++static inline int may_create(struct inode *dir, struct dentry *child,
++                           int isdir)
+ {
++      int error;
++
+       if (child->d_inode)
+               return -EEXIST;
+       if (IS_DEADDIR(dir))
+               return -ENOENT;
+-      return inode_permission(dir, MAY_WRITE | MAY_EXEC);
++
++      if (dir->i_op->may_create) {
++              if (IS_RDONLY(dir))
++                      return -EROFS;
++              if (IS_IMMUTABLE(dir))
++                      return -EACCES;
++              error = dir->i_op->may_create(dir, isdir);
++              if (!error)
++                      error = security_inode_permission(dir, MAY_WRITE | MAY_EXEC);
++      } else
++              error = inode_permission(dir, MAY_WRITE | MAY_EXEC);
++
++      return error;
+ }
+ /* 
+@@ -1504,7 +1530,7 @@ void unlock_rename(struct dentry *p1, st
+ int vfs_create(struct inode *dir, struct dentry *dentry, int mode,
+               struct nameidata *nd)
+ {
+-      int error = may_create(dir, dentry);
++      int error = may_create(dir, dentry, 0);
+       if (error)
+               return error;
+@@ -1948,7 +1974,7 @@ EXPORT_SYMBOL_GPL(lookup_create);
+ int vfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
+ {
+-      int error = may_create(dir, dentry);
++      int error = may_create(dir, dentry, 0);
+       if (error)
+               return error;
+@@ -2049,7 +2075,7 @@ SYSCALL_DEFINE3(mknod, const char __user
+ int vfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
+ {
+-      int error = may_create(dir, dentry);
++      int error = may_create(dir, dentry, 1);
+       if (error)
+               return error;
+@@ -2316,7 +2342,7 @@ SYSCALL_DEFINE1(unlink, const char __use
+ int vfs_symlink(struct inode *dir, struct dentry *dentry, const char *oldname)
+ {
+-      int error = may_create(dir, dentry);
++      int error = may_create(dir, dentry, 0);
+       if (error)
+               return error;
+@@ -2386,7 +2412,7 @@ int vfs_link(struct dentry *old_dentry,
+       if (!inode)
+               return -ENOENT;
+-      error = may_create(dir, new_dentry);
++      error = may_create(dir, new_dentry, S_ISDIR(inode->i_mode));
+       if (error)
+               return error;
+@@ -2594,7 +2620,7 @@ int vfs_rename(struct inode *old_dir, st
+               return error;
+       if (!new_dentry->d_inode)
+-              error = may_create(new_dir, new_dentry);
++              error = may_create(new_dir, new_dentry, is_dir);
+       else
+               error = may_delete(new_dir, new_dentry, is_dir);
+       if (error)
+--- a/include/linux/fs.h
++++ b/include/linux/fs.h
+@@ -1293,6 +1293,8 @@ struct inode_operations {
+       void (*put_link) (struct dentry *, struct nameidata *, void *);
+       void (*truncate) (struct inode *);
+       int (*permission) (struct inode *, int);
++      int (*may_create) (struct inode *, int);
++      int (*may_delete) (struct inode *, struct inode *);
+       int (*setattr) (struct dentry *, struct iattr *);
+       int (*getattr) (struct vfsmount *mnt, struct dentry *, struct kstat *);
+       int (*setxattr) (struct dentry *, const char *,const void *,size_t,int);