diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2011-06-20 19:55:42 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2011-07-20 01:43:30 -0400 |
commit | d594e7ec4da6c1a527dea4965eee37cd785792b8 (patch) | |
tree | b1c50c217309934a25449052625747927cbe4b45 | |
parent | eecdd358b467405a084d400d5ec571bbdbfe97a3 (diff) |
massage generic_permission() to treat directories on a separate path
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
-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) | |||
235 | if (ret != -EACCES) | 235 | if (ret != -EACCES) |
236 | return ret; | 236 | return ret; |
237 | 237 | ||
238 | if (S_ISDIR(inode->i_mode)) { | ||
239 | /* DACs are overridable for directories */ | ||
240 | if (ns_capable(inode_userns(inode), CAP_DAC_OVERRIDE)) | ||
241 | return 0; | ||
242 | if (!(mask & MAY_WRITE)) | ||
243 | if (ns_capable(inode_userns(inode), CAP_DAC_READ_SEARCH)) | ||
244 | return 0; | ||
245 | return -EACCES; | ||
246 | } | ||
238 | /* | 247 | /* |
239 | * Read/write DACs are always overridable. | 248 | * Read/write DACs are always overridable. |
240 | * Executable DACs are overridable for all directories and | 249 | * Executable DACs are overridable when there is |
241 | * for non-directories that have least one exec bit set. | 250 | * at least one exec bit set. |
242 | */ | 251 | */ |
243 | if (!(mask & MAY_EXEC) || execute_ok(inode)) | 252 | if (!(mask & MAY_EXEC) || (inode->i_mode & S_IXUGO)) |
244 | if (ns_capable(inode_userns(inode), CAP_DAC_OVERRIDE)) | 253 | if (ns_capable(inode_userns(inode), CAP_DAC_OVERRIDE)) |
245 | return 0; | 254 | return 0; |
246 | 255 | ||
@@ -248,7 +257,7 @@ int generic_permission(struct inode *inode, int mask) | |||
248 | * Searching includes executable on directories, else just read. | 257 | * Searching includes executable on directories, else just read. |
249 | */ | 258 | */ |
250 | mask &= MAY_READ | MAY_WRITE | MAY_EXEC; | 259 | mask &= MAY_READ | MAY_WRITE | MAY_EXEC; |
251 | if (mask == MAY_READ || (S_ISDIR(inode->i_mode) && !(mask & MAY_WRITE))) | 260 | if (mask == MAY_READ) |
252 | if (ns_capable(inode_userns(inode), CAP_DAC_READ_SEARCH)) | 261 | if (ns_capable(inode_userns(inode), CAP_DAC_READ_SEARCH)) |
253 | return 0; | 262 | return 0; |
254 | 263 | ||