When mapping a directory, we want the MAY_WRITE permissions to reflect whether or not we have permission to modify, add and delete the directory entries. MAY_EXEC must map to lookup permissions. On the other hand, for files, we want MAY_WRITE to reflect a permission to modify and extend the file.
Unified · Split
| @@ -2379,21 +2379,30 @@ EXPORT_SYMBOL_GPL(nfs_access_add_cache); · 2378 unmodified lines | ||
| 2379 | 2379 | #define NFS_MAY_WRITE (NFS4_ACCESS_MODIFY | \ |
| 2380 | 2380 | NFS4_ACCESS_EXTEND | \ |
| 2381 | 2381 | NFS4_ACCESS_DELETE) |
| 2382 | +#define NFS_FILE_MAY_WRITE (NFS4_ACCESS_MODIFY | \ | |
| 2383 | + NFS4_ACCESS_EXTEND) | |
| 2384 | +#define NFS_DIR_MAY_WRITE NFS_MAY_WRITE | |
| 2382 | 2385 | #define NFS_MAY_LOOKUP (NFS4_ACCESS_LOOKUP) |
| 2383 | 2386 | #define NFS_MAY_EXECUTE (NFS4_ACCESS_EXECUTE) |
| 2384 | 2387 | static int |
| 2385 | −nfs_access_calc_mask(u32 access_result) | |
| 2388 | +nfs_access_calc_mask(u32 access_result, umode_t umode) | |
| 2386 | 2389 | { |
| 2387 | 2390 | int mask = 0; |
| 2388 | 2391 | |
| 2389 | 2392 | if (access_result & NFS_MAY_READ) |
| 2390 | 2393 | mask |= MAY_READ; |
| 2391 | − if (access_result & NFS_MAY_WRITE) | |
| 2392 | − mask |= MAY_WRITE; | |
| 2393 | − if (access_result & NFS_MAY_LOOKUP) | |
| 2394 | − mask |= MAY_EXEC; | |
| 2395 | − if (access_result & NFS_MAY_EXECUTE) | |
| 2396 | − mask |= MAY_EXEC; | |
| 2394 | + if (S_ISDIR(umode)) { | |
| 2395 | + if ((access_result & NFS_DIR_MAY_WRITE) == NFS_DIR_MAY_WRITE) | |
| 2396 | + mask |= MAY_WRITE; | |
| 2397 | + if ((access_result & NFS_MAY_LOOKUP) == NFS_MAY_LOOKUP) | |
| 2398 | + mask |= MAY_EXEC; | |
| 2399 | + } else if (S_ISREG(umode)) { | |
| 2400 | + if ((access_result & NFS_FILE_MAY_WRITE) == NFS_FILE_MAY_WRITE) | |
| 2401 | + mask |= MAY_WRITE; | |
| 2402 | + if ((access_result & NFS_MAY_EXECUTE) == NFS_MAY_EXECUTE) | |
| 2403 | + mask |= MAY_EXEC; | |
| 2404 | + } else if (access_result & NFS_MAY_WRITE) | |
| 2405 | + mask |= MAY_WRITE; | |
| 2397 | 2406 | return mask; |
| 2398 | 2407 | } |
| 2399 | 2408 | |
| @@ -2438,7 +2447,7 @@ static int nfs_do_access(struct inode *inode, struct rpc_cred *cred, int mask) · 38 unmodified lines | ||
| 2438 | 2447 | } |
| 2439 | 2448 | nfs_access_add_cache(inode, &cache); |
| 2440 | 2449 | out_cached: |
| 2441 | − cache_mask = nfs_access_calc_mask(cache.mask); | |
| 2450 | + cache_mask = nfs_access_calc_mask(cache.mask, inode->i_mode); | |
| 2442 | 2451 | if ((mask & ~cache_mask & (MAY_READ | MAY_WRITE | MAY_EXEC)) != 0) |
| 2443 | 2452 | status = -EACCES; |
| 2444 | 2453 | out: |