diff options
Diffstat (limited to 'fs/namei.c')
-rw-r--r-- | fs/namei.c | 23 |
1 files changed, 17 insertions, 6 deletions
diff --git a/fs/namei.c b/fs/namei.c index 3b26a240ade9..46af98ed136b 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
@@ -185,6 +185,8 @@ int generic_permission(struct inode *inode, int mask, | |||
185 | { | 185 | { |
186 | umode_t mode = inode->i_mode; | 186 | umode_t mode = inode->i_mode; |
187 | 187 | ||
188 | mask &= MAY_READ | MAY_WRITE | MAY_EXEC; | ||
189 | |||
188 | if (current->fsuid == inode->i_uid) | 190 | if (current->fsuid == inode->i_uid) |
189 | mode >>= 6; | 191 | mode >>= 6; |
190 | else { | 192 | else { |
@@ -203,7 +205,7 @@ int generic_permission(struct inode *inode, int mask, | |||
203 | /* | 205 | /* |
204 | * If the DACs are ok we don't need any capability check. | 206 | * If the DACs are ok we don't need any capability check. |
205 | */ | 207 | */ |
206 | if (((mode & mask & (MAY_READ|MAY_WRITE|MAY_EXEC)) == mask)) | 208 | if ((mask & ~mode) == 0) |
207 | return 0; | 209 | return 0; |
208 | 210 | ||
209 | check_capabilities: | 211 | check_capabilities: |
@@ -228,7 +230,7 @@ int generic_permission(struct inode *inode, int mask, | |||
228 | 230 | ||
229 | int permission(struct inode *inode, int mask, struct nameidata *nd) | 231 | int permission(struct inode *inode, int mask, struct nameidata *nd) |
230 | { | 232 | { |
231 | int retval, submask; | 233 | int retval; |
232 | struct vfsmount *mnt = NULL; | 234 | struct vfsmount *mnt = NULL; |
233 | 235 | ||
234 | if (nd) | 236 | if (nd) |
@@ -261,9 +263,17 @@ int permission(struct inode *inode, int mask, struct nameidata *nd) | |||
261 | } | 263 | } |
262 | 264 | ||
263 | /* Ordinary permission routines do not understand MAY_APPEND. */ | 265 | /* Ordinary permission routines do not understand MAY_APPEND. */ |
264 | submask = mask & ~MAY_APPEND; | ||
265 | if (inode->i_op && inode->i_op->permission) { | 266 | if (inode->i_op && inode->i_op->permission) { |
266 | retval = inode->i_op->permission(inode, submask, nd); | 267 | int extra = 0; |
268 | if (nd) { | ||
269 | if (nd->flags & LOOKUP_ACCESS) | ||
270 | extra |= MAY_ACCESS; | ||
271 | if (nd->flags & LOOKUP_CHDIR) | ||
272 | extra |= MAY_CHDIR; | ||
273 | if (nd->flags & LOOKUP_OPEN) | ||
274 | extra |= MAY_OPEN; | ||
275 | } | ||
276 | retval = inode->i_op->permission(inode, mask | extra); | ||
267 | if (!retval) { | 277 | if (!retval) { |
268 | /* | 278 | /* |
269 | * Exec permission on a regular file is denied if none | 279 | * Exec permission on a regular file is denied if none |
@@ -277,7 +287,7 @@ int permission(struct inode *inode, int mask, struct nameidata *nd) | |||
277 | return -EACCES; | 287 | return -EACCES; |
278 | } | 288 | } |
279 | } else { | 289 | } else { |
280 | retval = generic_permission(inode, submask, NULL); | 290 | retval = generic_permission(inode, mask, NULL); |
281 | } | 291 | } |
282 | if (retval) | 292 | if (retval) |
283 | return retval; | 293 | return retval; |
@@ -286,7 +296,8 @@ int permission(struct inode *inode, int mask, struct nameidata *nd) | |||
286 | if (retval) | 296 | if (retval) |
287 | return retval; | 297 | return retval; |
288 | 298 | ||
289 | return security_inode_permission(inode, mask, nd); | 299 | return security_inode_permission(inode, |
300 | mask & (MAY_READ|MAY_WRITE|MAY_EXEC), nd); | ||
290 | } | 301 | } |
291 | 302 | ||
292 | /** | 303 | /** |