[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