lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:	Mon,  1 Feb 2010 11:04:43 +0530
From:	"Aneesh Kumar K.V" <aneesh.kumar@...ux.vnet.ibm.com>
To:	sfrench@...ibm.com, ffilz@...ibm.com, agruen@...e.de,
	adilger@....com, sandeen@...hat.com, tytso@....edu,
	staubach@...hat.com, bfields@...i.umich.edu, jlayton@...hat.com
Cc:	aneesh.kumar@...ux.vnet.ibm.com, linux-fsdevel@...r.kernel.org,
	nfsv4@...ux-nfs.org, linux-ext4@...r.kernel.org
Subject: [PATCH 01/23] vfs: VFS hooks for per-filesystem permission models

From: Andreas Gruenbacher <agruen@...e.de>

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@...e.de>
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@...ux.vnet.ibm.com>
---
 fs/namei.c         |   50 ++++++++++++++++++++++++++++++++++++++------------
 include/linux/fs.h |    4 ++++
 2 files changed, 42 insertions(+), 12 deletions(-)

diff --git a/fs/namei.c b/fs/namei.c
index b55440b..3e842ac 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -1337,14 +1337,26 @@ static int may_delete(struct inode *dir,struct dentry *victim,int isdir)
 
 	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) || IS_SWAPFILE(victim->d_inode))
+	if (IS_APPEND(victim->d_inode) || IS_IMMUTABLE(victim->d_inode) ||
+		IS_SWAPFILE(victim->d_inode))
 		return -EPERM;
 	if (isdir) {
 		if (!S_ISDIR(victim->d_inode->i_mode))
@@ -1368,13 +1380,27 @@ static int may_delete(struct inode *dir,struct dentry *victim,int isdir)
  *  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;
 }
 
 /* 
@@ -1438,7 +1464,7 @@ void unlock_rename(struct dentry *p1, struct dentry *p2)
 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;
@@ -1970,7 +1996,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;
@@ -2075,7 +2101,7 @@ SYSCALL_DEFINE3(mknod, const char __user *, filename, int, mode, unsigned, dev)
 
 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;
@@ -2360,7 +2386,7 @@ SYSCALL_DEFINE1(unlink, const char __user *, pathname)
 
 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;
@@ -2434,7 +2460,7 @@ int vfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_de
 	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;
 
@@ -2646,7 +2672,7 @@ int vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
 		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)
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 9147ca8..2191464 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1534,6 +1534,10 @@ struct inode_operations {
 			  loff_t len);
 	int (*fiemap)(struct inode *, struct fiemap_extent_info *, u64 start,
 		      u64 len);
+	int (*may_create) (struct inode *, int);
+	int (*may_delete) (struct inode *, struct inode *);
+
+
 };
 
 struct seq_file;
-- 
1.7.0.rc0.48.gdace5

--
To unsubscribe from this list: send the line "unsubscribe linux-ext4" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ