diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2011-06-21 01:55:42 +0200 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2011-07-20 07:43:30 +0200 |
commit | d594e7ec4da6c1a527dea4965eee37cd785792b8 (patch) | |
tree | b1c50c217309934a25449052625747927cbe4b45 /fs/namei.c | |
parent | ->permission() sanitizing: don't pass flags to exec_permission() (diff) | |
download | linux-d594e7ec4da6c1a527dea4965eee37cd785792b8.tar.xz linux-d594e7ec4da6c1a527dea4965eee37cd785792b8.zip |
massage generic_permission() to treat directories on a separate path
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/namei.c')
-rw-r--r-- | fs/namei.c | 17 |
1 files changed, 13 insertions, 4 deletions
diff --git a/fs/namei.c b/fs/namei.c index 21eba95368f2..758bae739305 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -235,12 +235,21 @@ int generic_permission(struct inode *inode, int mask) if (ret != -EACCES) return ret; + if (S_ISDIR(inode->i_mode)) { + /* DACs are overridable for directories */ + if (ns_capable(inode_userns(inode), CAP_DAC_OVERRIDE)) + return 0; + if (!(mask & MAY_WRITE)) + if (ns_capable(inode_userns(inode), CAP_DAC_READ_SEARCH)) + return 0; + return -EACCES; + } /* * Read/write DACs are always overridable. - * Executable DACs are overridable for all directories and - * for non-directories that have least one exec bit set. + * Executable DACs are overridable when there is + * at least one exec bit set. */ - if (!(mask & MAY_EXEC) || execute_ok(inode)) + if (!(mask & MAY_EXEC) || (inode->i_mode & S_IXUGO)) if (ns_capable(inode_userns(inode), CAP_DAC_OVERRIDE)) return 0; @@ -248,7 +257,7 @@ int generic_permission(struct inode *inode, int mask) * Searching includes executable on directories, else just read. */ mask &= MAY_READ | MAY_WRITE | MAY_EXEC; - if (mask == MAY_READ || (S_ISDIR(inode->i_mode) && !(mask & MAY_WRITE))) + if (mask == MAY_READ) if (ns_capable(inode_userns(inode), CAP_DAC_READ_SEARCH)) return 0; |