xref: /openbmc/linux/fs/cachefiles/namei.c (revision 32759f7d)
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /* CacheFiles path walking and related routines
3  *
4  * Copyright (C) 2021 Red Hat, Inc. All Rights Reserved.
5  * Written by David Howells (dhowells@redhat.com)
6  */
7 
8 #include <linux/fs.h>
9 #include <linux/namei.h>
10 #include "internal.h"
11 
12 /*
13  * Mark the backing file as being a cache file if it's not already in use.  The
14  * mark tells the culling request command that it's not allowed to cull the
15  * file or directory.  The caller must hold the inode lock.
16  */
17 static bool __cachefiles_mark_inode_in_use(struct cachefiles_object *object,
18 					   struct dentry *dentry)
19 {
20 	struct inode *inode = d_backing_inode(dentry);
21 	bool can_use = false;
22 
23 	if (!(inode->i_flags & S_KERNEL_FILE)) {
24 		inode->i_flags |= S_KERNEL_FILE;
25 		trace_cachefiles_mark_active(object, inode);
26 		can_use = true;
27 	} else {
28 		pr_notice("cachefiles: Inode already in use: %pd\n", dentry);
29 	}
30 
31 	return can_use;
32 }
33 
34 /*
35  * Unmark a backing inode.  The caller must hold the inode lock.
36  */
37 static void __cachefiles_unmark_inode_in_use(struct cachefiles_object *object,
38 					     struct dentry *dentry)
39 {
40 	struct inode *inode = d_backing_inode(dentry);
41 
42 	inode->i_flags &= ~S_KERNEL_FILE;
43 	trace_cachefiles_mark_inactive(object, inode);
44 }
45 
46 /*
47  * get a subdirectory
48  */
49 struct dentry *cachefiles_get_directory(struct cachefiles_cache *cache,
50 					struct dentry *dir,
51 					const char *dirname,
52 					bool *_is_new)
53 {
54 	struct dentry *subdir;
55 	struct path path;
56 	int ret;
57 
58 	_enter(",,%s", dirname);
59 
60 	/* search the current directory for the element name */
61 	inode_lock_nested(d_inode(dir), I_MUTEX_PARENT);
62 
63 retry:
64 	ret = cachefiles_inject_read_error();
65 	if (ret == 0)
66 		subdir = lookup_one_len(dirname, dir, strlen(dirname));
67 	else
68 		subdir = ERR_PTR(ret);
69 	if (IS_ERR(subdir)) {
70 		trace_cachefiles_vfs_error(NULL, d_backing_inode(dir),
71 					   PTR_ERR(subdir),
72 					   cachefiles_trace_lookup_error);
73 		if (PTR_ERR(subdir) == -ENOMEM)
74 			goto nomem_d_alloc;
75 		goto lookup_error;
76 	}
77 
78 	_debug("subdir -> %pd %s",
79 	       subdir, d_backing_inode(subdir) ? "positive" : "negative");
80 
81 	/* we need to create the subdir if it doesn't exist yet */
82 	if (d_is_negative(subdir)) {
83 		ret = cachefiles_has_space(cache, 1, 0);
84 		if (ret < 0)
85 			goto mkdir_error;
86 
87 		_debug("attempt mkdir");
88 
89 		path.mnt = cache->mnt;
90 		path.dentry = dir;
91 		ret = security_path_mkdir(&path, subdir, 0700);
92 		if (ret < 0)
93 			goto mkdir_error;
94 		ret = cachefiles_inject_write_error();
95 		if (ret == 0)
96 			ret = vfs_mkdir(&init_user_ns, d_inode(dir), subdir, 0700);
97 		if (ret < 0) {
98 			trace_cachefiles_vfs_error(NULL, d_inode(dir), ret,
99 						   cachefiles_trace_mkdir_error);
100 			goto mkdir_error;
101 		}
102 
103 		if (unlikely(d_unhashed(subdir))) {
104 			cachefiles_put_directory(subdir);
105 			goto retry;
106 		}
107 		ASSERT(d_backing_inode(subdir));
108 
109 		_debug("mkdir -> %pd{ino=%lu}",
110 		       subdir, d_backing_inode(subdir)->i_ino);
111 		if (_is_new)
112 			*_is_new = true;
113 	}
114 
115 	/* Tell rmdir() it's not allowed to delete the subdir */
116 	inode_lock(d_inode(subdir));
117 	inode_unlock(d_inode(dir));
118 
119 	if (!__cachefiles_mark_inode_in_use(NULL, subdir))
120 		goto mark_error;
121 
122 	inode_unlock(d_inode(subdir));
123 
124 	/* we need to make sure the subdir is a directory */
125 	ASSERT(d_backing_inode(subdir));
126 
127 	if (!d_can_lookup(subdir)) {
128 		pr_err("%s is not a directory\n", dirname);
129 		ret = -EIO;
130 		goto check_error;
131 	}
132 
133 	ret = -EPERM;
134 	if (!(d_backing_inode(subdir)->i_opflags & IOP_XATTR) ||
135 	    !d_backing_inode(subdir)->i_op->lookup ||
136 	    !d_backing_inode(subdir)->i_op->mkdir ||
137 	    !d_backing_inode(subdir)->i_op->rename ||
138 	    !d_backing_inode(subdir)->i_op->rmdir ||
139 	    !d_backing_inode(subdir)->i_op->unlink)
140 		goto check_error;
141 
142 	_leave(" = [%lu]", d_backing_inode(subdir)->i_ino);
143 	return subdir;
144 
145 check_error:
146 	cachefiles_put_directory(subdir);
147 	_leave(" = %d [check]", ret);
148 	return ERR_PTR(ret);
149 
150 mark_error:
151 	inode_unlock(d_inode(subdir));
152 	dput(subdir);
153 	return ERR_PTR(-EBUSY);
154 
155 mkdir_error:
156 	inode_unlock(d_inode(dir));
157 	dput(subdir);
158 	pr_err("mkdir %s failed with error %d\n", dirname, ret);
159 	return ERR_PTR(ret);
160 
161 lookup_error:
162 	inode_unlock(d_inode(dir));
163 	ret = PTR_ERR(subdir);
164 	pr_err("Lookup %s failed with error %d\n", dirname, ret);
165 	return ERR_PTR(ret);
166 
167 nomem_d_alloc:
168 	inode_unlock(d_inode(dir));
169 	_leave(" = -ENOMEM");
170 	return ERR_PTR(-ENOMEM);
171 }
172 
173 /*
174  * Put a subdirectory.
175  */
176 void cachefiles_put_directory(struct dentry *dir)
177 {
178 	if (dir) {
179 		inode_lock(dir->d_inode);
180 		__cachefiles_unmark_inode_in_use(NULL, dir);
181 		inode_unlock(dir->d_inode);
182 		dput(dir);
183 	}
184 }
185