@@ -81,7 +81,7 @@ int cachefiles_daemon_bind(struct cachefiles_cache *cache, char *args)
static int cachefiles_daemon_add_cache(struct cachefiles_cache *cache)
{
struct cachefiles_object *fsdef;
- struct path path;
+ struct path path, cache_path;
struct kstatfs stats;
struct dentry *graveyard, *cachedir, *root;
const struct cred *saved_cred;
@@ -115,16 +115,23 @@ static int cachefiles_daemon_add_cache(struct cachefiles_cache *cache)
if (ret < 0)
goto error_open_root;
- cache->mnt = path.mnt;
- root = path.dentry;
-
- ret = -EINVAL;
if (mnt_user_ns(path.mnt) != &init_user_ns) {
+ ret = -EINVAL;
+ cache->mnt = NULL;
pr_warn("File cache on idmapped mounts not supported");
goto error_unsupported;
}
+ cache->mnt = clone_private_mount(&path);
+ if (IS_ERR(cache->mnt)) {
+ ret = PTR_ERR(cache->mnt);
+ cache->mnt = NULL;
+ pr_warn("Failed to create private mount for file cache\n");
+ goto error_unsupported;
+ }
+
/* check parameters */
+ root = path.dentry;
ret = -EOPNOTSUPP;
if (d_is_negative(root) ||
!d_backing_inode(root)->i_op->lookup ||
@@ -144,8 +151,10 @@ static int cachefiles_daemon_add_cache(struct cachefiles_cache *cache)
if (ret < 0)
goto error_unsupported;
+ cache_path.dentry = path.dentry;
+ cache_path.mnt = cache->mnt;
/* get the cache size and blocksize */
- ret = vfs_statfs(&path, &stats);
+ ret = vfs_statfs(&cache_path, &stats);
if (ret < 0)
goto error_unsupported;
@@ -229,7 +238,12 @@ static int cachefiles_daemon_add_cache(struct cachefiles_cache *cache)
/* done */
set_bit(CACHEFILES_READY, &cache->flags);
- dput(root);
+
+ /*
+ * We've created a private mount and we've stashed our "cache" and
+ * "graveyard" dentries so we don't need the path anymore.
+ */
+ path_put(&path);
pr_info("File cache on %s registered\n", cache->cache.identifier);
@@ -242,11 +256,11 @@ static int cachefiles_daemon_add_cache(struct cachefiles_cache *cache)
dput(cache->graveyard);
cache->graveyard = NULL;
error_unsupported:
- mntput(cache->mnt);
+ path_put(&path);
+ kern_unmount(cache->mnt);
cache->mnt = NULL;
dput(fsdef->dentry);
fsdef->dentry = NULL;
- dput(root);
error_open_root:
kmem_cache_free(cachefiles_object_jar, fsdef);
error_root_object:
@@ -270,7 +284,7 @@ void cachefiles_daemon_unbind(struct cachefiles_cache *cache)
}
dput(cache->graveyard);
- mntput(cache->mnt);
+ kern_unmount(cache->mnt);
kfree(cache->rootdirname);
kfree(cache->secctx);