From: Christoph Hellwig Currently it's up to the filesystem ->permission method to check whether the filesystem is readonly or the file marked immutable. But this is really a VFS decision, and the distintion becomes more important when moving to per-mountpoint read only flags. For most filesystems that have been using generic_permission this is not change in behaviour. For those that we're missing the check (cifs without CIFS_MOUNT_NO_PERM and coda [1]) this is a bugfix. Both reiserfs and xfs have this check still in their ->permission routine because they call it from other places aswell. I'll try switching them over to generic_permission and will take care of this one. [1] coda_ioctl_permission always returns 0, aka always grants access, which looks more than fishy to me. Signed-off-by: Andrew Morton --- 25-akpm/fs/namei.c | 39 ++++++++++++++++++++------------------- 25-akpm/fs/nfs/dir.c | 18 ------------------ 2 files changed, 20 insertions(+), 37 deletions(-) diff -puN fs/namei.c~move-read-only-and-immutable-checks-into-permission fs/namei.c --- 25/fs/namei.c~move-read-only-and-immutable-checks-into-permission Thu Jan 13 15:53:59 2005 +++ 25-akpm/fs/namei.c Thu Jan 13 15:53:59 2005 @@ -169,21 +169,6 @@ int generic_permission(struct inode *ino { umode_t mode = inode->i_mode; - if (mask & MAY_WRITE) { - /* - * Nobody gets write access to a read-only fs. - */ - if (IS_RDONLY(inode) && - (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode))) - return -EROFS; - - /* - * Nobody gets write access to an immutable file. - */ - if (IS_IMMUTABLE(inode)) - return -EACCES; - } - if (current->fsuid == inode->i_uid) mode >>= 6; else { @@ -225,14 +210,30 @@ int generic_permission(struct inode *ino return -EACCES; } -int permission(struct inode * inode,int mask, struct nameidata *nd) +int permission(struct inode *inode, int mask, struct nameidata *nd) { - int retval; - int submask; + int retval, submask; + + if (mask & MAY_WRITE) { + umode_t mode = inode->i_mode; + + /* + * Nobody gets write access to a read-only fs. + */ + if (IS_RDONLY(inode) && + (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode))) + return -EROFS; + + /* + * Nobody gets write access to an immutable file. + */ + if (IS_IMMUTABLE(inode)) + return -EACCES; + } + /* Ordinary permission routines do not understand MAY_APPEND. */ submask = mask & ~MAY_APPEND; - if (inode->i_op && inode->i_op->permission) retval = inode->i_op->permission(inode, submask, nd); else diff -puN fs/nfs/dir.c~move-read-only-and-immutable-checks-into-permission fs/nfs/dir.c --- 25/fs/nfs/dir.c~move-read-only-and-immutable-checks-into-permission Thu Jan 13 15:53:59 2005 +++ 25-akpm/fs/nfs/dir.c Thu Jan 13 15:53:59 2005 @@ -1498,29 +1498,11 @@ out: int nfs_permission(struct inode *inode, int mask, struct nameidata *nd) { struct rpc_cred *cred; - int mode = inode->i_mode; int res; if (mask == 0) return 0; - if (mask & MAY_WRITE) { - /* - * - * Nobody gets write access to a read-only fs. - * - */ - if (IS_RDONLY(inode) && - (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode))) - return -EROFS; - /* - * - * Nobody gets write access to an immutable file. - * - */ - if (IS_IMMUTABLE(inode)) - return -EACCES; - } /* Are we checking permissions on anything other than lookup/execute? */ if ((mask & MAY_EXEC) == 0) { /* We only need to check permissions on file open() and access() */ _