|
@@ -1243,22 +1243,13 @@ int __user_path_lookup_open(const char __user *name, unsigned int lookup_flags,
|
|
|
return err;
|
|
|
}
|
|
|
|
|
|
-/*
|
|
|
- * Restricted form of lookup. Doesn't follow links, single-component only,
|
|
|
- * needs parent already locked. Doesn't follow mounts.
|
|
|
- * SMP-safe.
|
|
|
- */
|
|
|
-static struct dentry * __lookup_hash(struct qstr *name, struct dentry * base, struct nameidata *nd)
|
|
|
+static inline struct dentry *__lookup_hash_kern(struct qstr *name, struct dentry *base, struct nameidata *nd)
|
|
|
{
|
|
|
- struct dentry * dentry;
|
|
|
+ struct dentry *dentry;
|
|
|
struct inode *inode;
|
|
|
int err;
|
|
|
|
|
|
inode = base->d_inode;
|
|
|
- err = permission(inode, MAY_EXEC, nd);
|
|
|
- dentry = ERR_PTR(err);
|
|
|
- if (err)
|
|
|
- goto out;
|
|
|
|
|
|
/*
|
|
|
* See if the low-level filesystem might want
|
|
@@ -1287,35 +1278,76 @@ out:
|
|
|
return dentry;
|
|
|
}
|
|
|
|
|
|
+/*
|
|
|
+ * Restricted form of lookup. Doesn't follow links, single-component only,
|
|
|
+ * 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)
|
|
|
+{
|
|
|
+ struct dentry *dentry;
|
|
|
+ struct inode *inode;
|
|
|
+ int err;
|
|
|
+
|
|
|
+ inode = base->d_inode;
|
|
|
+
|
|
|
+ err = permission(inode, MAY_EXEC, nd);
|
|
|
+ dentry = ERR_PTR(err);
|
|
|
+ if (err)
|
|
|
+ goto out;
|
|
|
+
|
|
|
+ dentry = __lookup_hash_kern(name, base, nd);
|
|
|
+out:
|
|
|
+ return dentry;
|
|
|
+}
|
|
|
+
|
|
|
static struct dentry *lookup_hash(struct nameidata *nd)
|
|
|
{
|
|
|
return __lookup_hash(&nd->last, nd->dentry, nd);
|
|
|
}
|
|
|
|
|
|
/* SMP-safe */
|
|
|
-struct dentry * lookup_one_len(const char * name, struct dentry * base, int len)
|
|
|
+static inline int __lookup_one_len(const char *name, struct qstr *this, struct dentry *base, int len)
|
|
|
{
|
|
|
unsigned long hash;
|
|
|
- struct qstr this;
|
|
|
unsigned int c;
|
|
|
|
|
|
- this.name = name;
|
|
|
- this.len = len;
|
|
|
+ this->name = name;
|
|
|
+ this->len = len;
|
|
|
if (!len)
|
|
|
- goto access;
|
|
|
+ return -EACCES;
|
|
|
|
|
|
hash = init_name_hash();
|
|
|
while (len--) {
|
|
|
c = *(const unsigned char *)name++;
|
|
|
if (c == '/' || c == '\0')
|
|
|
- goto access;
|
|
|
+ return -EACCES;
|
|
|
hash = partial_name_hash(c, hash);
|
|
|
}
|
|
|
- this.hash = end_name_hash(hash);
|
|
|
+ this->hash = end_name_hash(hash);
|
|
|
+ return 0;
|
|
|
+}
|
|
|
|
|
|
+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);
|
|
|
return __lookup_hash(&this, base, NULL);
|
|
|
-access:
|
|
|
- return ERR_PTR(-EACCES);
|
|
|
+}
|
|
|
+
|
|
|
+struct dentry *lookup_one_len_kern(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);
|
|
|
+ return __lookup_hash_kern(&this, base, NULL);
|
|
|
}
|
|
|
|
|
|
/*
|