|
@@ -1273,7 +1273,8 @@ int __user_path_lookup_open(const char __user *name, unsigned int lookup_flags,
|
|
|
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,26 +1346,52 @@ static inline int __lookup_one_len(const char *name, struct qstr *this, struct d
|
|
|
return 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;
|
|
|
struct qstr this;
|
|
|
|
|
|
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,
|