diff options
author | David Howells <dhowells@redhat.com> | 2018-05-16 16:25:46 -0400 |
---|---|---|
committer | David Howells <dhowells@redhat.com> | 2018-05-16 16:35:23 -0400 |
commit | 378831e4daec75fbba6d3612bcf3b4dd00ddbf08 (patch) | |
tree | 66cdf5ae7efa2fe90491caa6cd15c6158791f17e /fs/afs | |
parent | 21b9f1c7e319f654de3b2574fe8d4e4114c9143f (diff) |
afs: Fix directory permissions check
Doing faccessat("/afs/some/directory", 0) triggers a BUG in the permissions
check code.
Fix this by just removing the BUG section. If no permissions are asked
for, just return okay if the file exists.
Also:
(1) Split up the directory check so that it has separate if-statements
rather than if-else-if (e.g. checking for MAY_EXEC shouldn't skip the
check for MAY_READ and MAY_WRITE).
(2) Check for MAY_CHDIR as MAY_EXEC.
Without the main fix, the following BUG may occur:
kernel BUG at fs/afs/security.c:386!
invalid opcode: 0000 [#1] SMP PTI
...
RIP: 0010:afs_permission+0x19d/0x1a0 [kafs]
...
Call Trace:
? inode_permission+0xbe/0x180
? do_faccessat+0xdc/0x270
? do_syscall_64+0x60/0x1f0
? entry_SYSCALL_64_after_hwframe+0x49/0xbe
Fixes: 00d3b7a4533e ("[AFS]: Add security support.")
Reported-by: Jonathan Billings <jsbillings@jsbillings.org>
Signed-off-by: David Howells <dhowells@redhat.com>
Diffstat (limited to 'fs/afs')
-rw-r--r-- | fs/afs/security.c | 10 |
1 files changed, 3 insertions, 7 deletions
diff --git a/fs/afs/security.c b/fs/afs/security.c index 1992b0ffa543..81dfedb7879f 100644 --- a/fs/afs/security.c +++ b/fs/afs/security.c | |||
@@ -372,18 +372,14 @@ int afs_permission(struct inode *inode, int mask) | |||
372 | mask, access, S_ISDIR(inode->i_mode) ? "dir" : "file"); | 372 | mask, access, S_ISDIR(inode->i_mode) ? "dir" : "file"); |
373 | 373 | ||
374 | if (S_ISDIR(inode->i_mode)) { | 374 | if (S_ISDIR(inode->i_mode)) { |
375 | if (mask & MAY_EXEC) { | 375 | if (mask & (MAY_EXEC | MAY_READ | MAY_CHDIR)) { |
376 | if (!(access & AFS_ACE_LOOKUP)) | 376 | if (!(access & AFS_ACE_LOOKUP)) |
377 | goto permission_denied; | 377 | goto permission_denied; |
378 | } else if (mask & MAY_READ) { | 378 | } |
379 | if (!(access & AFS_ACE_LOOKUP)) | 379 | if (mask & MAY_WRITE) { |
380 | goto permission_denied; | ||
381 | } else if (mask & MAY_WRITE) { | ||
382 | if (!(access & (AFS_ACE_DELETE | /* rmdir, unlink, rename from */ | 380 | if (!(access & (AFS_ACE_DELETE | /* rmdir, unlink, rename from */ |
383 | AFS_ACE_INSERT))) /* create, mkdir, symlink, rename to */ | 381 | AFS_ACE_INSERT))) /* create, mkdir, symlink, rename to */ |
384 | goto permission_denied; | 382 | goto permission_denied; |
385 | } else { | ||
386 | BUG(); | ||
387 | } | 383 | } |
388 | } else { | 384 | } else { |
389 | if (!(access & AFS_ACE_LOOKUP)) | 385 | if (!(access & AFS_ACE_LOOKUP)) |