partially fix up the lookup_one_noperm mess
Subsystems (2)
PATCH 1/1 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 <[email protected]>
fs/namei.c +36 -22
@@ -1273,7 +1273,8 @@ int __user_path_lookup_open(const char _return err; } -static inline struct dentry *__lookup_hash_kern (struct qstr *name,struct dentry *base,struct nameidata *nd) +static struct dentry *__lookup_hash (struct qstr *name, +struct dentry *base,struct nameidata *nd) {struct dentry *dentry;struct inode *inode;
@@ -1313,31 +1314,18 @@ out:* needs parent already locked. Doesn't follow mounts. * SMP-safe. */ -static inline struct dentry *__lookup_hash (struct qstr *name,struct dentry *base,struct nameidata *nd) +static struct dentry *lookup_hash (struct nameidata *nd) { -struct dentry *dentry; -struct inode *inode;int err; - inode = base->d_inode; - - err =permission (inode,MAY_EXEC , nd); - dentry =ERR_PTR (err); + err =permission (nd->dentry->d_inode,MAY_EXEC , nd);if (err) - goto out; - - dentry =__lookup_hash_kern (name, base, nd); -out: -return dentry; -} - -static struct dentry *lookup_hash (struct nameidata *nd) -{ +return ERR_PTR (err);return __lookup_hash (&nd->last, nd->dentry, nd); } -/* SMP-safe */ -static inline int __lookup_one_len (const char *name,struct qstr *this,struct dentry *base,int len) +static int __lookup_one_len (const char *name,struct qstr *this, +struct dentry *base,int len) {unsigned long hash;unsigned int c;
@@ -1358,6 +1346,17 @@ static inline int __lookup_one_len(constreturn 0 ; } +/** +* lookup_one_len: filesystem helper to lookup single pathname component +* @name: pathname component to lookup +* @base: base directory to lookup from +* @len: maximum length @len should be interpreted to +* +* Note that this routine is purely a helper for filesystem useage and should +* not be called by generic code. Also note that by using this function to +* nameidata argument is passed to the filesystem methods and a filesystem +* using this helper needs to be prepared for that. +*/ struct dentry *lookup_one_len (const char *name,struct dentry *base,int len) {int err;
@@ -1366,18 +1365,33 @@ struct dentry *lookup_one_len(const char err =__lookup_one_len (name, &this, base, len);if (err)return ERR_PTR (err); + + err =permission (base->d_inode,MAY_EXEC ,NULL ); +if (err) +return ERR_PTR (err);return __lookup_hash (&this, base,NULL ); } -struct dentry *lookup_one_len_kern (const char *name,struct dentry *base,int len) +/** +* lookup_one_noperm - bad hack for sysfs +* @name: pathname component to lookup +* @base: base directory to lookup from +* +* This is a variant of lookup_one_len that doesn't perform any permission +* checks. It's a horrible hack to work around the braindead sysfs +* architecture and should not be used anywhere else. +* +* DON'T USE THIS FUNCTION EVER, thanks. +*/ +struct dentry *lookup_one_noperm (const char *name,struct dentry *base) {int err;struct qstr this; - err =__lookup_one_len (name, &this, base, len); + err =__lookup_one_len (name, &this, base,strlen (name));if (err)return ERR_PTR (err); -return __lookup_hash_kern (&this, base,NULL ); +return __lookup_hash (&this, base,NULL ); } int fastcall __user_walk_fd(int dfd, const char __user *name, unsigned flags,
fs/sysfs/dir.c +1 -2
@@ -130,8 +130,7 @@ struct dentry *sysfs_get_dentry(struct s/* look it up */ parent_dentry = dentry; - dentry =lookup_one_len_kern (cur->s_name, parent_dentry, -strlen (cur->s_name)); + dentry =lookup_one_noperm (cur->s_name, parent_dentry);dput (parent_dentry);if (IS_ERR (dentry)) {
include/linux/namei.h +2 -2
@@ -81,8 +81,8 @@ extern struct file *lookup_instantiate_fextern struct file *nameidata_to_filp (struct nameidata *nd,int flags);extern void release_open_intent (struct nameidata *); -extern struct dentry *lookup_one_len (const char *,struct dentry *,int ); -extern struct dentry *lookup_one_len_kern (const char *,struct dentry *,int ); +extern struct dentry *lookup_one_len (const char *,struct dentry *,int ); +extern struct dentry *lookup_one_noperm (const char *,struct dentry *);extern int follow_down (struct vfsmount **,struct dentry **);extern int follow_up (struct vfsmount **,struct dentry **);