diff options
Diffstat (limited to 'fs/namei.c')
-rw-r--r-- | fs/namei.c | 66 |
1 files changed, 50 insertions, 16 deletions
diff --git a/fs/namei.c b/fs/namei.c index b3f8a1966c9c..6dbbd42d8b95 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
@@ -256,6 +256,38 @@ int permission(struct inode *inode, int mask, struct nameidata *nd) | |||
256 | return security_inode_permission(inode, mask, nd); | 256 | return security_inode_permission(inode, mask, nd); |
257 | } | 257 | } |
258 | 258 | ||
259 | /** | ||
260 | * vfs_permission - check for access rights to a given path | ||
261 | * @nd: lookup result that describes the path | ||
262 | * @mask: right to check for (%MAY_READ, %MAY_WRITE, %MAY_EXEC) | ||
263 | * | ||
264 | * Used to check for read/write/execute permissions on a path. | ||
265 | * We use "fsuid" for this, letting us set arbitrary permissions | ||
266 | * for filesystem access without changing the "normal" uids which | ||
267 | * are used for other things. | ||
268 | */ | ||
269 | int vfs_permission(struct nameidata *nd, int mask) | ||
270 | { | ||
271 | return permission(nd->dentry->d_inode, mask, nd); | ||
272 | } | ||
273 | |||
274 | /** | ||
275 | * file_permission - check for additional access rights to a given file | ||
276 | * @file: file to check access rights for | ||
277 | * @mask: right to check for (%MAY_READ, %MAY_WRITE, %MAY_EXEC) | ||
278 | * | ||
279 | * Used to check for read/write/execute permissions on an already opened | ||
280 | * file. | ||
281 | * | ||
282 | * Note: | ||
283 | * Do not use this function in new code. All access checks should | ||
284 | * be done using vfs_permission(). | ||
285 | */ | ||
286 | int file_permission(struct file *file, int mask) | ||
287 | { | ||
288 | return permission(file->f_dentry->d_inode, mask, NULL); | ||
289 | } | ||
290 | |||
259 | /* | 291 | /* |
260 | * get_write_access() gets write permission for a file. | 292 | * get_write_access() gets write permission for a file. |
261 | * put_write_access() releases this write permission. | 293 | * put_write_access() releases this write permission. |
@@ -765,9 +797,8 @@ static fastcall int __link_path_walk(const char * name, struct nameidata *nd) | |||
765 | 797 | ||
766 | nd->flags |= LOOKUP_CONTINUE; | 798 | nd->flags |= LOOKUP_CONTINUE; |
767 | err = exec_permission_lite(inode, nd); | 799 | err = exec_permission_lite(inode, nd); |
768 | if (err == -EAGAIN) { | 800 | if (err == -EAGAIN) |
769 | err = permission(inode, MAY_EXEC, nd); | 801 | err = vfs_permission(nd, MAY_EXEC); |
770 | } | ||
771 | if (err) | 802 | if (err) |
772 | break; | 803 | break; |
773 | 804 | ||
@@ -1109,8 +1140,9 @@ int path_lookup_open(const char *name, unsigned int lookup_flags, | |||
1109 | * @open_flags: open intent flags | 1140 | * @open_flags: open intent flags |
1110 | * @create_mode: create intent flags | 1141 | * @create_mode: create intent flags |
1111 | */ | 1142 | */ |
1112 | int path_lookup_create(const char *name, unsigned int lookup_flags, | 1143 | static int path_lookup_create(const char *name, unsigned int lookup_flags, |
1113 | struct nameidata *nd, int open_flags, int create_mode) | 1144 | struct nameidata *nd, int open_flags, |
1145 | int create_mode) | ||
1114 | { | 1146 | { |
1115 | return __path_lookup_intent_open(name, lookup_flags|LOOKUP_CREATE, nd, | 1147 | return __path_lookup_intent_open(name, lookup_flags|LOOKUP_CREATE, nd, |
1116 | open_flags, create_mode); | 1148 | open_flags, create_mode); |
@@ -1173,9 +1205,9 @@ out: | |||
1173 | return dentry; | 1205 | return dentry; |
1174 | } | 1206 | } |
1175 | 1207 | ||
1176 | struct dentry * lookup_hash(struct qstr *name, struct dentry * base) | 1208 | struct dentry * lookup_hash(struct nameidata *nd) |
1177 | { | 1209 | { |
1178 | return __lookup_hash(name, base, NULL); | 1210 | return __lookup_hash(&nd->last, nd->dentry, nd); |
1179 | } | 1211 | } |
1180 | 1212 | ||
1181 | /* SMP-safe */ | 1213 | /* SMP-safe */ |
@@ -1199,7 +1231,7 @@ struct dentry * lookup_one_len(const char * name, struct dentry * base, int len) | |||
1199 | } | 1231 | } |
1200 | this.hash = end_name_hash(hash); | 1232 | this.hash = end_name_hash(hash); |
1201 | 1233 | ||
1202 | return lookup_hash(&this, base); | 1234 | return __lookup_hash(&this, base, NULL); |
1203 | access: | 1235 | access: |
1204 | return ERR_PTR(-EACCES); | 1236 | return ERR_PTR(-EACCES); |
1205 | } | 1237 | } |
@@ -1407,7 +1439,7 @@ int may_open(struct nameidata *nd, int acc_mode, int flag) | |||
1407 | if (S_ISDIR(inode->i_mode) && (flag & FMODE_WRITE)) | 1439 | if (S_ISDIR(inode->i_mode) && (flag & FMODE_WRITE)) |
1408 | return -EISDIR; | 1440 | return -EISDIR; |
1409 | 1441 | ||
1410 | error = permission(inode, acc_mode, nd); | 1442 | error = vfs_permission(nd, acc_mode); |
1411 | if (error) | 1443 | if (error) |
1412 | return error; | 1444 | return error; |
1413 | 1445 | ||
@@ -1532,7 +1564,7 @@ int open_namei(const char * pathname, int flag, int mode, struct nameidata *nd) | |||
1532 | dir = nd->dentry; | 1564 | dir = nd->dentry; |
1533 | nd->flags &= ~LOOKUP_PARENT; | 1565 | nd->flags &= ~LOOKUP_PARENT; |
1534 | down(&dir->d_inode->i_sem); | 1566 | down(&dir->d_inode->i_sem); |
1535 | path.dentry = __lookup_hash(&nd->last, nd->dentry, nd); | 1567 | path.dentry = lookup_hash(nd); |
1536 | path.mnt = nd->mnt; | 1568 | path.mnt = nd->mnt; |
1537 | 1569 | ||
1538 | do_last: | 1570 | do_last: |
@@ -1634,7 +1666,7 @@ do_link: | |||
1634 | } | 1666 | } |
1635 | dir = nd->dentry; | 1667 | dir = nd->dentry; |
1636 | down(&dir->d_inode->i_sem); | 1668 | down(&dir->d_inode->i_sem); |
1637 | path.dentry = __lookup_hash(&nd->last, nd->dentry, nd); | 1669 | path.dentry = lookup_hash(nd); |
1638 | path.mnt = nd->mnt; | 1670 | path.mnt = nd->mnt; |
1639 | __putname(nd->last.name); | 1671 | __putname(nd->last.name); |
1640 | goto do_last; | 1672 | goto do_last; |
@@ -1666,7 +1698,7 @@ struct dentry *lookup_create(struct nameidata *nd, int is_dir) | |||
1666 | /* | 1698 | /* |
1667 | * Do the final lookup. | 1699 | * Do the final lookup. |
1668 | */ | 1700 | */ |
1669 | dentry = lookup_hash(&nd->last, nd->dentry); | 1701 | dentry = lookup_hash(nd); |
1670 | if (IS_ERR(dentry)) | 1702 | if (IS_ERR(dentry)) |
1671 | goto fail; | 1703 | goto fail; |
1672 | 1704 | ||
@@ -1901,7 +1933,7 @@ asmlinkage long sys_rmdir(const char __user * pathname) | |||
1901 | goto exit1; | 1933 | goto exit1; |
1902 | } | 1934 | } |
1903 | down(&nd.dentry->d_inode->i_sem); | 1935 | down(&nd.dentry->d_inode->i_sem); |
1904 | dentry = lookup_hash(&nd.last, nd.dentry); | 1936 | dentry = lookup_hash(&nd); |
1905 | error = PTR_ERR(dentry); | 1937 | error = PTR_ERR(dentry); |
1906 | if (!IS_ERR(dentry)) { | 1938 | if (!IS_ERR(dentry)) { |
1907 | error = vfs_rmdir(nd.dentry->d_inode, dentry); | 1939 | error = vfs_rmdir(nd.dentry->d_inode, dentry); |
@@ -1970,7 +2002,7 @@ asmlinkage long sys_unlink(const char __user * pathname) | |||
1970 | if (nd.last_type != LAST_NORM) | 2002 | if (nd.last_type != LAST_NORM) |
1971 | goto exit1; | 2003 | goto exit1; |
1972 | down(&nd.dentry->d_inode->i_sem); | 2004 | down(&nd.dentry->d_inode->i_sem); |
1973 | dentry = lookup_hash(&nd.last, nd.dentry); | 2005 | dentry = lookup_hash(&nd); |
1974 | error = PTR_ERR(dentry); | 2006 | error = PTR_ERR(dentry); |
1975 | if (!IS_ERR(dentry)) { | 2007 | if (!IS_ERR(dentry)) { |
1976 | /* Why not before? Because we want correct error value */ | 2008 | /* Why not before? Because we want correct error value */ |
@@ -2313,7 +2345,7 @@ static inline int do_rename(const char * oldname, const char * newname) | |||
2313 | 2345 | ||
2314 | trap = lock_rename(new_dir, old_dir); | 2346 | trap = lock_rename(new_dir, old_dir); |
2315 | 2347 | ||
2316 | old_dentry = lookup_hash(&oldnd.last, old_dir); | 2348 | old_dentry = lookup_hash(&oldnd); |
2317 | error = PTR_ERR(old_dentry); | 2349 | error = PTR_ERR(old_dentry); |
2318 | if (IS_ERR(old_dentry)) | 2350 | if (IS_ERR(old_dentry)) |
2319 | goto exit3; | 2351 | goto exit3; |
@@ -2333,7 +2365,7 @@ static inline int do_rename(const char * oldname, const char * newname) | |||
2333 | error = -EINVAL; | 2365 | error = -EINVAL; |
2334 | if (old_dentry == trap) | 2366 | if (old_dentry == trap) |
2335 | goto exit4; | 2367 | goto exit4; |
2336 | new_dentry = lookup_hash(&newnd.last, new_dir); | 2368 | new_dentry = lookup_hash(&newnd); |
2337 | error = PTR_ERR(new_dentry); | 2369 | error = PTR_ERR(new_dentry); |
2338 | if (IS_ERR(new_dentry)) | 2370 | if (IS_ERR(new_dentry)) |
2339 | goto exit4; | 2371 | goto exit4; |
@@ -2536,6 +2568,8 @@ EXPORT_SYMBOL(path_lookup); | |||
2536 | EXPORT_SYMBOL(path_release); | 2568 | EXPORT_SYMBOL(path_release); |
2537 | EXPORT_SYMBOL(path_walk); | 2569 | EXPORT_SYMBOL(path_walk); |
2538 | EXPORT_SYMBOL(permission); | 2570 | EXPORT_SYMBOL(permission); |
2571 | EXPORT_SYMBOL(vfs_permission); | ||
2572 | EXPORT_SYMBOL(file_permission); | ||
2539 | EXPORT_SYMBOL(unlock_rename); | 2573 | EXPORT_SYMBOL(unlock_rename); |
2540 | EXPORT_SYMBOL(vfs_create); | 2574 | EXPORT_SYMBOL(vfs_create); |
2541 | EXPORT_SYMBOL(vfs_follow_link); | 2575 | EXPORT_SYMBOL(vfs_follow_link); |