[Unionfs] notify_change in inode.c:unionfs_create()

hooanon05 at yahoo.co.jp hooanon05 at yahoo.co.jp
Sun Mar 12 19:41:07 EST 2006


Josef Sipek:
> Hmm..I shouldn't need any fsuid/fsgid change since we are passing
> ATTR_FORCE which bypasses all the permission checks. So, I'm tempted to
> blame nfs.

Actually, linux nfs client doesn't change fsuid before sending the
request to nfs server. It might be a bug as you wrote, but I am not
sure.
Here is a patch for unionfs.

Junjiro Okajima


diff -rup unionfs-20060308-2131.orig/copyup.c unionfs-20060308-2131/copyup.c
--- unionfs-20060308-2131.orig/copyup.c	2006-03-09 11:31:58.000000000 +0900
+++ unionfs-20060308-2131/copyup.c	2006-03-13 07:20:49.000000000 +0900
@@ -143,7 +143,7 @@ static int copyup_permissions(struct sup
 						      i_mode & ~S_IALLUGO);
 	}
 
-	err = notify_change(new_hidden_dentry, &newattrs);
+	err = unionfs_notify_change(new_hidden_dentry, &newattrs);
 
 	print_exit_status(err);
 	return err;
diff -rup unionfs-20060308-2131.orig/inode.c unionfs-20060308-2131/inode.c
--- unionfs-20060308-2131.orig/inode.c	2006-03-09 11:31:58.000000000 +0900
+++ unionfs-20060308-2131/inode.c	2006-03-13 07:20:49.000000000 +0900
@@ -95,7 +95,7 @@ static int unionfs_create(struct inode *
 			newattrs.ia_size = 0;
 		}
 
-		err = notify_change(whiteout_dentry, &newattrs);
+		err = unionfs_notify_change(whiteout_dentry, &newattrs);
 
 		mutex_unlock(&whiteout_dentry->d_inode->i_mutex);
 
@@ -969,7 +969,7 @@ static int unionfs_setattr(struct dentry
 			}
 
 		}
-		err = notify_change(hidden_dentry, ia);
+		err = unionfs_notify_change(hidden_dentry, ia);
 		if (err)
 			goto out;
 		break;
diff -rup unionfs-20060308-2131.orig/subr.c unionfs-20060308-2131/subr.c
--- unionfs-20060308-2131.orig/subr.c	2006-03-09 11:31:58.000000000 +0900
+++ unionfs-20060308-2131/subr.c	2006-03-13 07:26:44.000000000 +0900
@@ -323,6 +323,28 @@ void superio_revert(struct superio *sio)
 	write_unlock(&tasklist_lock);
 }
 
+int unionfs_notify_change(struct dentry *hidden_dentry, struct iattr *attr)
+{
+	int err;
+	struct inode *inode;
+	struct superio sio;
+
+	inode = hidden_dentry->d_inode;
+	//BUG_ON(!mutex_is_locked(&inode->i_mutex)); // should be locked before this function
+	if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) // is i_flags maintenanced in unionfs?
+		return -EPERM;
+
+	if (!current->fsuid
+	    || !(attr->ia_valid & ATTR_FORCE)
+	    || !is_branch_nfs(hidden_dentry))
+		return notify_change(hidden_dentry, attr);
+
+	superio_store(&sio);
+	err = notify_change(hidden_dentry, attr);
+	superio_revert(&sio);
+	return err;
+}
+
 /*
  *
  * vim:shiftwidth=8
diff -rup unionfs-20060308-2131.orig/unionfs.h unionfs-20060308-2131/unionfs.h
--- unionfs-20060308-2131.orig/unionfs.h	2006-03-09 11:31:58.000000000 +0900
+++ unionfs-20060308-2131/unionfs.h	2006-03-13 07:20:49.000000000 +0900
@@ -795,6 +795,11 @@ struct superio {
 };
 extern void superio_store(struct superio *sio);
 extern void superio_revert(struct superio *sio);
+extern int unionfs_notify_change(struct dentry *hidden_dentry, struct iattr *attr);
+static inline int is_branch_nfs(struct dentry *dentry)
+{
+	return !strcmp(sbt(dentry->d_sb), "nfs");
+}
 
 #endif				/* __KERNEL__ */
 



More information about the unionfs mailing list