[XFRM] SAD info TLV aggregationx
[cascardo/linux.git] / fs / namei.c
index 28d49b3..880052c 100644 (file)
@@ -249,9 +249,11 @@ int permission(struct inode *inode, int mask, struct nameidata *nd)
 
        /*
         * MAY_EXEC on regular files requires special handling: We override
-        * filesystem execute permissions if the mode bits aren't set.
+        * filesystem execute permissions if the mode bits aren't set or
+        * the fs is mounted with the "noexec" flag.
         */
-       if ((mask & MAY_EXEC) && S_ISREG(mode) && !(mode & S_IXUGO))
+       if ((mask & MAY_EXEC) && S_ISREG(mode) && (!(mode & S_IXUGO) ||
+                       (nd && nd->mnt && (nd->mnt->mnt_flags & MNT_NOEXEC))))
                return -EACCES;
 
        /* Ordinary permission routines do not understand MAY_APPEND. */
@@ -295,7 +297,7 @@ int vfs_permission(struct nameidata *nd, int mask)
  */
 int file_permission(struct file *file, int mask)
 {
-       return permission(file->f_dentry->d_inode, mask, NULL);
+       return permission(file->f_path.dentry->d_inode, mask, NULL);
 }
 
 /*
@@ -331,7 +333,7 @@ int get_write_access(struct inode * inode)
 
 int deny_write_access(struct file * file)
 {
-       struct inode *inode = file->f_dentry->d_inode;
+       struct inode *inode = file->f_path.dentry->d_inode;
 
        spin_lock(&inode->i_lock);
        if (atomic_read(&inode->i_writecount) > 0) {
@@ -366,7 +368,7 @@ void path_release_on_umount(struct nameidata *nd)
  */
 void release_open_intent(struct nameidata *nd)
 {
-       if (nd->intent.open.file->f_dentry == NULL)
+       if (nd->intent.open.file->f_path.dentry == NULL)
                put_filp(nd->intent.open.file);
        else
                fput(nd->intent.open.file);
@@ -570,11 +572,6 @@ fail:
        return PTR_ERR(link);
 }
 
-struct path {
-       struct vfsmount *mnt;
-       struct dentry *dentry;
-};
-
 static inline void dput_path(struct path *path, struct nameidata *nd)
 {
        dput(path->dentry);
@@ -1141,7 +1138,7 @@ static int fastcall do_path_lookup(int dfd, const char *name,
                if (!file)
                        goto out_fail;
 
-               dentry = file->f_dentry;
+               dentry = file->f_path.dentry;
 
                retval = -ENOTDIR;
                if (!S_ISDIR(dentry->d_inode->i_mode))
@@ -1151,7 +1148,7 @@ static int fastcall do_path_lookup(int dfd, const char *name,
                if (retval)
                        goto fput_fail;
 
-               nd->mnt = mntget(file->f_vfsmnt);
+               nd->mnt = mntget(file->f_path.mnt);
                nd->dentry = dget(dentry);
 
                fput_light(file, fput_needed);
@@ -1246,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
@@ -1290,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);
 }
 
 /*
@@ -1996,8 +2025,7 @@ asmlinkage long sys_mkdir(const char __user *pathname, int mode)
 void dentry_unhash(struct dentry *dentry)
 {
        dget(dentry);
-       if (atomic_read(&dentry->d_count))
-               shrink_dcache_parent(dentry);
+       shrink_dcache_parent(dentry);
        spin_lock(&dcache_lock);
        spin_lock(&dentry->d_lock);
        if (atomic_read(&dentry->d_count) == 2)
@@ -2692,10 +2720,11 @@ int __page_symlink(struct inode *inode, const char *symname, int len,
 {
        struct address_space *mapping = inode->i_mapping;
        struct page *page;
-       int err = -ENOMEM;
+       int err;
        char *kaddr;
 
 retry:
+       err = -ENOMEM;
        page = find_or_create_page(mapping, 0, gfp_mask);
        if (!page)
                goto fail;
@@ -2748,7 +2777,7 @@ int page_symlink(struct inode *inode, const char *symname, int len)
                        mapping_gfp_mask(inode->i_mapping));
 }
 
-struct inode_operations page_symlink_inode_operations = {
+const struct inode_operations page_symlink_inode_operations = {
        .readlink       = generic_readlink,
        .follow_link    = page_follow_link_light,
        .put_link       = page_put_link,