diff options
author | Christoph Hellwig <hch@lst.de> | 2007-10-17 02:25:38 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-10-17 11:42:44 -0400 |
commit | eead19115329c5615ba03cbaf1c3fe24c14858a3 (patch) | |
tree | 4b8aeeea5060fca595f2c5e8290d742cdb14a08f | |
parent | ebb3e820b83e426ee331bae6d8fb0e54f472a25d (diff) |
partially fix up the lookup_one_noperm mess
Try to fix the mess created by sysfs braindamage.
- refactor code internal to fs/namei.c a little to avoid too much
duplication:
o __lookup_hash_kern is renamed back to __lookup_hash
o the old __lookup_hash goes away, permission checks moves to
the two callers
o useless inline qualifiers on above functions go away
- lookup_one_len_kern loses it's last argument and is renamed to
lookup_one_noperm to make it's useage a little more clear
- added kerneldoc comments to describe lookup_one_len aswell as
lookup_one_noperm and make it very clear that no one should use
the latter ever.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Cc: Josef 'Jeff' Sipek <jsipek@cs.sunysb.edu>
Cc: Miklos Szeredi <miklos@szeredi.hu>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r-- | fs/namei.c | 58 | ||||
-rw-r--r-- | fs/sysfs/dir.c | 3 | ||||
-rw-r--r-- | include/linux/namei.h | 4 |
3 files changed, 39 insertions, 26 deletions
diff --git a/fs/namei.c b/fs/namei.c index b40b8084eefc..bab0d19a2e36 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
@@ -1273,7 +1273,8 @@ int __user_path_lookup_open(const char __user *name, unsigned int lookup_flags, | |||
1273 | return err; | 1273 | return err; |
1274 | } | 1274 | } |
1275 | 1275 | ||
1276 | static inline struct dentry *__lookup_hash_kern(struct qstr *name, struct dentry *base, struct nameidata *nd) | 1276 | static struct dentry *__lookup_hash(struct qstr *name, |
1277 | struct dentry *base, struct nameidata *nd) | ||
1277 | { | 1278 | { |
1278 | struct dentry *dentry; | 1279 | struct dentry *dentry; |
1279 | struct inode *inode; | 1280 | struct inode *inode; |
@@ -1313,31 +1314,18 @@ out: | |||
1313 | * needs parent already locked. Doesn't follow mounts. | 1314 | * needs parent already locked. Doesn't follow mounts. |
1314 | * SMP-safe. | 1315 | * SMP-safe. |
1315 | */ | 1316 | */ |
1316 | static inline struct dentry * __lookup_hash(struct qstr *name, struct dentry *base, struct nameidata *nd) | 1317 | static struct dentry *lookup_hash(struct nameidata *nd) |
1317 | { | 1318 | { |
1318 | struct dentry *dentry; | ||
1319 | struct inode *inode; | ||
1320 | int err; | 1319 | int err; |
1321 | 1320 | ||
1322 | inode = base->d_inode; | 1321 | err = permission(nd->dentry->d_inode, MAY_EXEC, nd); |
1323 | |||
1324 | err = permission(inode, MAY_EXEC, nd); | ||
1325 | dentry = ERR_PTR(err); | ||
1326 | if (err) | 1322 | if (err) |
1327 | goto out; | 1323 | return ERR_PTR(err); |
1328 | |||
1329 | dentry = __lookup_hash_kern(name, base, nd); | ||
1330 | out: | ||
1331 | return dentry; | ||
1332 | } | ||
1333 | |||
1334 | static struct dentry *lookup_hash(struct nameidata *nd) | ||
1335 | { | ||
1336 | return __lookup_hash(&nd->last, nd->dentry, nd); | 1324 | return __lookup_hash(&nd->last, nd->dentry, nd); |
1337 | } | 1325 | } |
1338 | 1326 | ||
1339 | /* SMP-safe */ | 1327 | static int __lookup_one_len(const char *name, struct qstr *this, |
1340 | static inline int __lookup_one_len(const char *name, struct qstr *this, struct dentry *base, int len) | 1328 | struct dentry *base, int len) |
1341 | { | 1329 | { |
1342 | unsigned long hash; | 1330 | unsigned long hash; |
1343 | unsigned int c; | 1331 | unsigned int c; |
@@ -1358,6 +1346,17 @@ static inline int __lookup_one_len(const char *name, struct qstr *this, struct d | |||
1358 | return 0; | 1346 | return 0; |
1359 | } | 1347 | } |
1360 | 1348 | ||
1349 | /** | ||
1350 | * lookup_one_len: filesystem helper to lookup single pathname component | ||
1351 | * @name: pathname component to lookup | ||
1352 | * @base: base directory to lookup from | ||
1353 | * @len: maximum length @len should be interpreted to | ||
1354 | * | ||
1355 | * Note that this routine is purely a helper for filesystem useage and should | ||
1356 | * not be called by generic code. Also note that by using this function to | ||
1357 | * nameidata argument is passed to the filesystem methods and a filesystem | ||
1358 | * using this helper needs to be prepared for that. | ||
1359 | */ | ||
1361 | struct dentry *lookup_one_len(const char *name, struct dentry *base, int len) | 1360 | struct dentry *lookup_one_len(const char *name, struct dentry *base, int len) |
1362 | { | 1361 | { |
1363 | int err; | 1362 | int err; |
@@ -1366,18 +1365,33 @@ struct dentry *lookup_one_len(const char *name, struct dentry *base, int len) | |||
1366 | err = __lookup_one_len(name, &this, base, len); | 1365 | err = __lookup_one_len(name, &this, base, len); |
1367 | if (err) | 1366 | if (err) |
1368 | return ERR_PTR(err); | 1367 | return ERR_PTR(err); |
1368 | |||
1369 | err = permission(base->d_inode, MAY_EXEC, NULL); | ||
1370 | if (err) | ||
1371 | return ERR_PTR(err); | ||
1369 | return __lookup_hash(&this, base, NULL); | 1372 | return __lookup_hash(&this, base, NULL); |
1370 | } | 1373 | } |
1371 | 1374 | ||
1372 | struct dentry *lookup_one_len_kern(const char *name, struct dentry *base, int len) | 1375 | /** |
1376 | * lookup_one_noperm - bad hack for sysfs | ||
1377 | * @name: pathname component to lookup | ||
1378 | * @base: base directory to lookup from | ||
1379 | * | ||
1380 | * This is a variant of lookup_one_len that doesn't perform any permission | ||
1381 | * checks. It's a horrible hack to work around the braindead sysfs | ||
1382 | * architecture and should not be used anywhere else. | ||
1383 | * | ||
1384 | * DON'T USE THIS FUNCTION EVER, thanks. | ||
1385 | */ | ||
1386 | struct dentry *lookup_one_noperm(const char *name, struct dentry *base) | ||
1373 | { | 1387 | { |
1374 | int err; | 1388 | int err; |
1375 | struct qstr this; | 1389 | struct qstr this; |
1376 | 1390 | ||
1377 | err = __lookup_one_len(name, &this, base, len); | 1391 | err = __lookup_one_len(name, &this, base, strlen(name)); |
1378 | if (err) | 1392 | if (err) |
1379 | return ERR_PTR(err); | 1393 | return ERR_PTR(err); |
1380 | return __lookup_hash_kern(&this, base, NULL); | 1394 | return __lookup_hash(&this, base, NULL); |
1381 | } | 1395 | } |
1382 | 1396 | ||
1383 | int fastcall __user_walk_fd(int dfd, const char __user *name, unsigned flags, | 1397 | int fastcall __user_walk_fd(int dfd, const char __user *name, unsigned flags, |
diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c index 9161db4d6b5c..d3118d482935 100644 --- a/fs/sysfs/dir.c +++ b/fs/sysfs/dir.c | |||
@@ -112,8 +112,7 @@ struct dentry *sysfs_get_dentry(struct sysfs_dirent *sd) | |||
112 | /* look it up */ | 112 | /* look it up */ |
113 | parent = dentry; | 113 | parent = dentry; |
114 | mutex_lock(&parent->d_inode->i_mutex); | 114 | mutex_lock(&parent->d_inode->i_mutex); |
115 | dentry = lookup_one_len_kern(cur->s_name, parent, | 115 | dentry = lookup_one_noperm(cur->s_name, parent); |
116 | strlen(cur->s_name)); | ||
117 | mutex_unlock(&parent->d_inode->i_mutex); | 116 | mutex_unlock(&parent->d_inode->i_mutex); |
118 | dput(parent); | 117 | dput(parent); |
119 | 118 | ||
diff --git a/include/linux/namei.h b/include/linux/namei.h index 6c38efbd810f..4cb4f8d2f78d 100644 --- a/include/linux/namei.h +++ b/include/linux/namei.h | |||
@@ -81,8 +81,8 @@ extern struct file *lookup_instantiate_filp(struct nameidata *nd, struct dentry | |||
81 | extern struct file *nameidata_to_filp(struct nameidata *nd, int flags); | 81 | extern struct file *nameidata_to_filp(struct nameidata *nd, int flags); |
82 | extern void release_open_intent(struct nameidata *); | 82 | extern void release_open_intent(struct nameidata *); |
83 | 83 | ||
84 | extern struct dentry * lookup_one_len(const char *, struct dentry *, int); | 84 | extern struct dentry *lookup_one_len(const char *, struct dentry *, int); |
85 | extern struct dentry *lookup_one_len_kern(const char *, struct dentry *, int); | 85 | extern struct dentry *lookup_one_noperm(const char *, struct dentry *); |
86 | 86 | ||
87 | extern int follow_down(struct vfsmount **, struct dentry **); | 87 | extern int follow_down(struct vfsmount **, struct dentry **); |
88 | extern int follow_up(struct vfsmount **, struct dentry **); | 88 | extern int follow_up(struct vfsmount **, struct dentry **); |