All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Aneesh Kumar K.V" <aneesh.kumar@linux.vnet.ibm.com>
To: agruen@kernel.org, bfields@fieldses.org,
	akpm@linux-foundation.org, viro@zeniv.linux.org.uk,
	dhowells@redhat.com
Cc: aneesh.kumar@linux.vnet.ibm.com, linux-fsdevel@vger.kernel.org,
	linux-nfs@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: [PATCH -V1 06/22] vfs: Add delete child and delete self permission flags
Date: Sun, 27 Apr 2014 21:44:37 +0530	[thread overview]
Message-ID: <1398615293-22931-7-git-send-email-aneesh.kumar@linux.vnet.ibm.com> (raw)
In-Reply-To: <1398615293-22931-1-git-send-email-aneesh.kumar@linux.vnet.ibm.com>

From: Andreas Gruenbacher <agruen@kernel.org>

Normally, deleting a file requires write access to the parent directory.
Some permission models use a different permission on the parent
directory to indicate delete access.  In addition, a process can have
per-file delete access even without delete access on the parent
directory.

Introduce two new inode_permission() mask flags and use them in
may_delete()

Signed-off-by: Andreas Gruenbacher <agruen@kernel.org>
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
---
 fs/namei.c         | 45 ++++++++++++++++++++++++++++++++++-----------
 include/linux/fs.h |  2 ++
 2 files changed, 36 insertions(+), 11 deletions(-)

diff --git a/fs/namei.c b/fs/namei.c
index 028bc8bcf77c..56ac7613fbca 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -446,7 +446,7 @@ static int sb_permission(struct super_block *sb, struct inode *inode, int mask)
  * changing the "normal" UIDs which are used for other things.
  *
  * When checking for MAY_APPEND, MAY_CREATE_FILE, MAY_CREATE_DIR,
- * MAY_WRITE must also be set in @mask.
+ * MAY_DELETE_CHILD, MAY_DELETE_SELF, MAY_WRITE must also be set in @mask.
  */
 int inode_permission(struct inode *inode, int mask)
 {
@@ -2366,11 +2366,25 @@ kern_path_mountpoint(int dfd, const char *name, struct path *path,
 }
 EXPORT_SYMBOL(kern_path_mountpoint);
 
+
+/*
+ * We should have exec permission on directory and MAY_DELETE_SELF
+ * on the object being deleted.
+ */
+static int richacl_may_selfdelete(struct inode *dir,
+				  struct inode *inode, int replace_mask)
+{
+	return (IS_RICHACL(inode) &&
+		(inode_permission(dir, MAY_EXEC | replace_mask) == 0) &&
+		(inode_permission(inode, MAY_DELETE_SELF) == 0));
+}
+
 /*
  * It's inline, so penalty for filesystems that don't use sticky bit is
  * minimal.
  */
-static inline int check_sticky(struct inode *dir, struct inode *inode)
+static inline int check_sticky(struct inode *dir,
+			       struct inode *inode, int replace_mask)
 {
 	kuid_t fsuid = current_fsuid();
 
@@ -2380,6 +2394,8 @@ static inline int check_sticky(struct inode *dir, struct inode *inode)
 		return 0;
 	if (uid_eq(dir->i_uid, fsuid))
 		return 0;
+	if (richacl_may_selfdelete(dir, inode, replace_mask))
+		return 0;
 	return !inode_capable(inode, CAP_FOWNER);
 }
 
@@ -2402,10 +2418,11 @@ static inline int check_sticky(struct inode *dir, struct inode *inode)
  * 10. We don't allow removal of NFS sillyrenamed files; it's handled by
  *     nfs_async_unlink().
  */
-static int may_delete(struct inode *dir, struct dentry *victim, bool isdir)
+static int may_delete(struct inode *dir, struct dentry *victim,
+		      bool isdir, bool replace)
 {
 	struct inode *inode = victim->d_inode;
-	int error;
+	int error, mask, replace_mask = 0;
 
 	if (d_is_negative(victim))
 		return -ENOENT;
@@ -2414,13 +2431,19 @@ static int may_delete(struct inode *dir, struct dentry *victim, bool isdir)
 	BUG_ON(victim->d_parent->d_inode != dir);
 	audit_inode_child(dir, victim, AUDIT_TYPE_CHILD_DELETE);
 
-	error = inode_permission(dir, MAY_WRITE | MAY_EXEC);
+	mask = MAY_WRITE | MAY_EXEC | MAY_DELETE_CHILD;
+	if (replace)
+		replace_mask = S_ISDIR(inode->i_mode) ?
+				MAY_CREATE_DIR : MAY_CREATE_FILE;
+	error = inode_permission(dir, mask | replace_mask);
+	if (error && richacl_may_selfdelete(dir, inode, replace_mask))
+		error = 0;
 	if (error)
 		return error;
 	if (IS_APPEND(dir))
 		return -EPERM;
 
-	if (check_sticky(dir, inode) || IS_APPEND(inode) ||
+	if (check_sticky(dir, inode, replace_mask) || IS_APPEND(inode) ||
 	    IS_IMMUTABLE(inode) || IS_SWAPFILE(inode))
 		return -EPERM;
 	if (isdir) {
@@ -3539,7 +3562,7 @@ EXPORT_SYMBOL(dentry_unhash);
 
 int vfs_rmdir(struct inode *dir, struct dentry *dentry)
 {
-	int error = may_delete(dir, dentry, 1);
+	int error = may_delete(dir, dentry, 1, 0);
 
 	if (error)
 		return error;
@@ -3658,7 +3681,7 @@ SYSCALL_DEFINE1(rmdir, const char __user *, pathname)
 int vfs_unlink(struct inode *dir, struct dentry *dentry, struct inode **delegated_inode)
 {
 	struct inode *target = dentry->d_inode;
-	int error = may_delete(dir, dentry, 0);
+	int error = may_delete(dir, dentry, 0, 0);
 
 	if (error)
 		return error;
@@ -4060,7 +4083,7 @@ int vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
 	if (source == target)
 		return 0;
 
-	error = may_delete(old_dir, old_dentry, is_dir);
+	error = may_delete(old_dir, old_dentry, is_dir, 0);
 	if (error)
 		return error;
 
@@ -4070,9 +4093,9 @@ int vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
 		new_is_dir = d_is_dir(new_dentry);
 
 		if (!(flags & RENAME_EXCHANGE))
-			error = may_delete(new_dir, new_dentry, is_dir);
+			error = may_delete(new_dir, new_dentry, is_dir, 1);
 		else
-			error = may_delete(new_dir, new_dentry, new_is_dir);
+			error = may_delete(new_dir, new_dentry, new_is_dir, 1);
 	}
 	if (error)
 		return error;
diff --git a/include/linux/fs.h b/include/linux/fs.h
index da5521de04ab..3f0ad0f2bce8 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -79,6 +79,8 @@ typedef void (dio_iodone_t)(struct kiocb *iocb, loff_t offset,
 #define MAY_NOT_BLOCK		0x00000080
 #define MAY_CREATE_FILE		0x00000100
 #define MAY_CREATE_DIR		0x00000200
+#define MAY_DELETE_CHILD	0x00000400
+#define MAY_DELETE_SELF		0x00000800
 
 /*
  * flags in file.f_mode.  Note that FMODE_READ and FMODE_WRITE must correspond
-- 
1.9.1


  parent reply	other threads:[~2014-04-27 16:16 UTC|newest]

Thread overview: 65+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-04-27 16:14 [PATCH -V1 00/22] New ACL format for better NFSv4 acl interoperability Aneesh Kumar K.V
2014-04-27 16:14 ` [PATCH -V1 01/22] vfs: Add generic IS_ACL() test for acl support Aneesh Kumar K.V
2014-04-27 16:14 ` [PATCH -V1 02/22] vfs: Add IS_RICHACL() test for richacl support Aneesh Kumar K.V
2014-04-27 16:14   ` Aneesh Kumar K.V
2014-04-27 16:14 ` [PATCH -V1 03/22] vfs: Optimize out IS_RICHACL() if CONFIG_FS_RICHACL is not defined Aneesh Kumar K.V
2014-04-27 16:14 ` [PATCH -V1 04/22] vfs: check for directory early Aneesh Kumar K.V
2014-04-27 16:14 ` [PATCH -V1 05/22] vfs: Add new file and directory create permission flags Aneesh Kumar K.V
2014-04-28 11:23   ` Jeff Layton
2014-04-29  0:04     ` Dave Chinner
2014-04-29  0:04       ` Dave Chinner
2014-05-01 15:16       ` Aneesh Kumar K.V
2014-05-01 15:16         ` Aneesh Kumar K.V
2014-04-27 16:14 ` Aneesh Kumar K.V [this message]
2014-04-29  0:07   ` [PATCH -V1 06/22] vfs: Add delete child and delete self " Dave Chinner
2014-05-01 15:18     ` Aneesh Kumar K.V
2014-04-27 16:14 ` [PATCH -V1 07/22] vfs: Make the inode passed to inode_change_ok non-const Aneesh Kumar K.V
2014-04-27 16:14 ` [PATCH -V1 08/22] vfs: Add permission flags for setting file attributes Aneesh Kumar K.V
2014-04-29  0:17   ` Dave Chinner
2014-05-01 15:20     ` Aneesh Kumar K.V
2014-05-01 15:20       ` Aneesh Kumar K.V
2014-04-27 16:14 ` [PATCH -V1 09/22] vfs: Make acl_permission_check() work for richacls Aneesh Kumar K.V
2014-04-29  0:20   ` Dave Chinner
2014-05-01 15:39     ` Aneesh Kumar K.V
2014-05-01 15:39       ` Aneesh Kumar K.V
2014-04-27 16:14 ` [PATCH -V1 10/22] richacl: In-memory representation and helper functions Aneesh Kumar K.V
2014-04-29  0:24   ` Dave Chinner
2014-05-01 15:42     ` Aneesh Kumar K.V
2014-05-06  9:35   ` Kinglong Mee
2014-05-06  9:35     ` Kinglong Mee
2014-04-27 16:14 ` [PATCH -V1 11/22] richacl: Permission mapping functions Aneesh Kumar K.V
2014-04-27 16:14 ` [PATCH -V1 12/22] richacl: Compute maximum file masks from an acl Aneesh Kumar K.V
2014-04-27 16:14 ` [PATCH -V1 13/22] richacl: Update the file masks in chmod() Aneesh Kumar K.V
2014-04-27 16:14   ` Aneesh Kumar K.V
2014-04-27 16:14 ` [PATCH -V1 14/22] richacl: Permission check algorithm Aneesh Kumar K.V
2014-04-27 16:14 ` [PATCH -V1 15/22] richacl: Create-time inheritance Aneesh Kumar K.V
2014-04-27 16:14 ` [PATCH -V1 16/22] richacl: Check if an acl is equivalent to a file mode Aneesh Kumar K.V
2014-04-27 16:14 ` [PATCH -V1 17/22] richacl: Automatic Inheritance Aneesh Kumar K.V
2014-04-27 16:14 ` [PATCH -V1 18/22] richacl: xattr mapping functions Aneesh Kumar K.V
2014-04-27 16:14 ` [PATCH -V1 19/22] vfs: Cache richacl in struct inode Aneesh Kumar K.V
2014-04-27 16:14   ` Aneesh Kumar K.V
2014-04-29  0:52   ` Dave Chinner
2014-04-29  0:52     ` Dave Chinner
2014-04-29 12:16     ` Matthew Wilcox
2014-05-01 15:45     ` Aneesh Kumar K.V
2014-04-27 16:14 ` [PATCH -V1 20/22] vfs: Add richacl permission check Aneesh Kumar K.V
2014-04-27 16:14 ` [PATCH -V1 21/22] ext4: Implement rich acl for ext4 Aneesh Kumar K.V
2014-04-27 16:14 ` [PATCH -V1 22/22] ext4: Add Ext4 compat richacl feature flag Aneesh Kumar K.V
2014-04-28 21:31   ` Andreas Dilger
2014-04-28 21:31     ` Andreas Dilger
2014-05-01 15:48     ` Aneesh Kumar K.V
2014-05-01 15:48       ` Aneesh Kumar K.V
2014-05-01 17:52       ` Andreas Dilger
2014-04-27 22:20 ` [PATCH -V1 00/22] New ACL format for better NFSv4 acl interoperability Dave Chinner
2014-04-27 22:20   ` Dave Chinner
2014-04-28  5:24   ` Aneesh Kumar K.V
2014-04-28  5:24     ` Aneesh Kumar K.V
2014-04-28 23:58     ` Dave Chinner
2014-05-01 15:49       ` Aneesh Kumar K.V
2014-05-01 15:49         ` Aneesh Kumar K.V
2014-04-28  4:39 ` Christoph Hellwig
2014-04-28  5:54   ` Aneesh Kumar K.V
2014-04-28  5:54     ` Aneesh Kumar K.V
2014-04-28  9:03     ` Christoph Hellwig
2014-04-28  9:03       ` Christoph Hellwig
2014-05-06 20:15 ` J. Bruce Fields

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1398615293-22931-7-git-send-email-aneesh.kumar@linux.vnet.ibm.com \
    --to=aneesh.kumar@linux.vnet.ibm.com \
    --cc=agruen@kernel.org \
    --cc=akpm@linux-foundation.org \
    --cc=bfields@fieldses.org \
    --cc=dhowells@redhat.com \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-nfs@vger.kernel.org \
    --cc=viro@zeniv.linux.org.uk \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.