Merge branches 'pm-cpufreq' and 'pm-cpuidle'
[linux-2.6-microblaze.git] / fs / overlayfs / namei.c
index a6162c4..3fe05fb 100644 (file)
@@ -150,17 +150,22 @@ invalid:
        goto out;
 }
 
-struct dentry *ovl_decode_real_fh(struct ovl_fh *fh, struct vfsmount *mnt,
-                                 bool connected)
+struct dentry *ovl_decode_real_fh(struct ovl_fs *ofs, struct ovl_fh *fh,
+                                 struct vfsmount *mnt, bool connected)
 {
        struct dentry *real;
        int bytes;
 
+       if (!capable(CAP_DAC_READ_SEARCH))
+               return NULL;
+
        /*
         * Make sure that the stored uuid matches the uuid of the lower
         * layer where file handle will be decoded.
+        * In case of uuid=off option just make sure that stored uuid is null.
         */
-       if (!uuid_equal(&fh->fb.uuid, &mnt->mnt_sb->s_uuid))
+       if (ofs->config.uuid ? !uuid_equal(&fh->fb.uuid, &mnt->mnt_sb->s_uuid) :
+                             !uuid_is_null(&fh->fb.uuid))
                return NULL;
 
        bytes = (fh->fb.len - offsetof(struct ovl_fb, fid));
@@ -354,7 +359,7 @@ int ovl_check_origin_fh(struct ovl_fs *ofs, struct ovl_fh *fh, bool connected,
                    ofs->layers[i].fs->bad_uuid)
                        continue;
 
-               origin = ovl_decode_real_fh(fh, ofs->layers[i].mnt,
+               origin = ovl_decode_real_fh(ofs, fh, ofs->layers[i].mnt,
                                            connected);
                if (origin)
                        break;
@@ -450,7 +455,7 @@ int ovl_verify_set_fh(struct ovl_fs *ofs, struct dentry *dentry,
        struct ovl_fh *fh;
        int err;
 
-       fh = ovl_encode_real_fh(real, is_upper);
+       fh = ovl_encode_real_fh(ofs, real, is_upper);
        err = PTR_ERR(fh);
        if (IS_ERR(fh)) {
                fh = NULL;
@@ -488,7 +493,7 @@ struct dentry *ovl_index_upper(struct ovl_fs *ofs, struct dentry *index)
        if (IS_ERR_OR_NULL(fh))
                return ERR_CAST(fh);
 
-       upper = ovl_decode_real_fh(fh, ovl_upper_mnt(ofs), true);
+       upper = ovl_decode_real_fh(ofs, fh, ovl_upper_mnt(ofs), true);
        kfree(fh);
 
        if (IS_ERR_OR_NULL(upper))
@@ -640,12 +645,13 @@ static int ovl_get_index_name_fh(struct ovl_fh *fh, struct qstr *name)
  * index dir was cleared. Either way, that index cannot be used to indentify
  * the overlay inode.
  */
-int ovl_get_index_name(struct dentry *origin, struct qstr *name)
+int ovl_get_index_name(struct ovl_fs *ofs, struct dentry *origin,
+                      struct qstr *name)
 {
        struct ovl_fh *fh;
        int err;
 
-       fh = ovl_encode_real_fh(origin, false);
+       fh = ovl_encode_real_fh(ofs, origin, false);
        if (IS_ERR(fh))
                return PTR_ERR(fh);
 
@@ -694,7 +700,7 @@ struct dentry *ovl_lookup_index(struct ovl_fs *ofs, struct dentry *upper,
        bool is_dir = d_is_dir(origin);
        int err;
 
-       err = ovl_get_index_name(origin, &name);
+       err = ovl_get_index_name(ofs, origin, &name);
        if (err)
                return ERR_PTR(err);
 
@@ -805,7 +811,7 @@ static int ovl_fix_origin(struct ovl_fs *ofs, struct dentry *dentry,
        if (err)
                return err;
 
-       err = ovl_set_origin(dentry, lower, upper);
+       err = ovl_set_origin(ofs, dentry, lower, upper);
        if (!err)
                err = ovl_set_impure(dentry->d_parent, upper->d_parent);
 
@@ -1003,6 +1009,8 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry,
         * Just make sure a corresponding data dentry has been found.
         */
        if (d.metacopy || (uppermetacopy && !ctr)) {
+               pr_warn_ratelimited("metacopy with no lower data found - abort lookup (%pd2)\n",
+                                   dentry);
                err = -EIO;
                goto out_put;
        } else if (!d.is_dir && upperdentry && !ctr && origin_path) {