]> git.proxmox.com Git - mirror_ubuntu-focal-kernel.git/blob - fs/aufs/xattr.c
UBUNTU: SAUCE: Update aufs to 5.4.3 20200302
[mirror_ubuntu-focal-kernel.git] / fs / aufs / xattr.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * Copyright (C) 2014-2020 Junjiro R. Okajima
4 *
5 * This program, aufs is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 /*
20 * handling xattr functions
21 */
22
23 #include <linux/fs.h>
24 #include <linux/posix_acl_xattr.h>
25 #include <linux/xattr.h>
26 #include "aufs.h"
27
28 static int au_xattr_ignore(int err, char *name, unsigned int ignore_flags)
29 {
30 if (!ignore_flags)
31 goto out;
32 switch (err) {
33 case -ENOMEM:
34 case -EDQUOT:
35 goto out;
36 }
37
38 if ((ignore_flags & AuBrAttr_ICEX) == AuBrAttr_ICEX) {
39 err = 0;
40 goto out;
41 }
42
43 #define cmp(brattr, prefix) do { \
44 if (!strncmp(name, XATTR_##prefix##_PREFIX, \
45 XATTR_##prefix##_PREFIX_LEN)) { \
46 if (ignore_flags & AuBrAttr_ICEX_##brattr) \
47 err = 0; \
48 goto out; \
49 } \
50 } while (0)
51
52 cmp(SEC, SECURITY);
53 cmp(SYS, SYSTEM);
54 cmp(TR, TRUSTED);
55 cmp(USR, USER);
56 #undef cmp
57
58 if (ignore_flags & AuBrAttr_ICEX_OTH)
59 err = 0;
60
61 out:
62 return err;
63 }
64
65 static const int au_xattr_out_of_list = AuBrAttr_ICEX_OTH << 1;
66
67 static int au_do_cpup_xattr(struct dentry *h_dst, struct dentry *h_src,
68 char *name, char **buf, unsigned int ignore_flags,
69 unsigned int verbose)
70 {
71 int err;
72 ssize_t ssz;
73 struct inode *h_idst;
74
75 ssz = vfs_getxattr_alloc(h_src, name, buf, 0, GFP_NOFS);
76 err = ssz;
77 if (unlikely(err <= 0)) {
78 if (err == -ENODATA
79 || (err == -EOPNOTSUPP
80 && ((ignore_flags & au_xattr_out_of_list)
81 || (au_test_nfs_noacl(d_inode(h_src))
82 && (!strcmp(name, XATTR_NAME_POSIX_ACL_ACCESS)
83 || !strcmp(name,
84 XATTR_NAME_POSIX_ACL_DEFAULT))))
85 ))
86 err = 0;
87 if (err && (verbose || au_debug_test()))
88 pr_err("%s, err %d\n", name, err);
89 goto out;
90 }
91
92 /* unlock it temporary */
93 h_idst = d_inode(h_dst);
94 inode_unlock(h_idst);
95 err = vfsub_setxattr(h_dst, name, *buf, ssz, /*flags*/0);
96 inode_lock_nested(h_idst, AuLsc_I_CHILD2);
97 if (unlikely(err)) {
98 if (verbose || au_debug_test())
99 pr_err("%s, err %d\n", name, err);
100 err = au_xattr_ignore(err, name, ignore_flags);
101 }
102
103 out:
104 return err;
105 }
106
107 int au_cpup_xattr(struct dentry *h_dst, struct dentry *h_src, int ignore_flags,
108 unsigned int verbose)
109 {
110 int err, unlocked, acl_access, acl_default;
111 ssize_t ssz;
112 struct inode *h_isrc, *h_idst;
113 char *value, *p, *o, *e;
114
115 /* try stopping to update the source inode while we are referencing */
116 /* there should not be the parent-child relationship between them */
117 h_isrc = d_inode(h_src);
118 h_idst = d_inode(h_dst);
119 inode_unlock(h_idst);
120 inode_lock_shared_nested(h_isrc, AuLsc_I_CHILD);
121 inode_lock_nested(h_idst, AuLsc_I_CHILD2);
122 unlocked = 0;
123
124 /* some filesystems don't list POSIX ACL, for example tmpfs */
125 ssz = vfs_listxattr(h_src, NULL, 0);
126 err = ssz;
127 if (unlikely(err < 0)) {
128 AuTraceErr(err);
129 if (err == -ENODATA
130 || err == -EOPNOTSUPP)
131 err = 0; /* ignore */
132 goto out;
133 }
134
135 err = 0;
136 p = NULL;
137 o = NULL;
138 if (ssz) {
139 err = -ENOMEM;
140 p = kmalloc(ssz, GFP_NOFS);
141 o = p;
142 if (unlikely(!p))
143 goto out;
144 err = vfs_listxattr(h_src, p, ssz);
145 }
146 inode_unlock_shared(h_isrc);
147 unlocked = 1;
148 AuDbg("err %d, ssz %zd\n", err, ssz);
149 if (unlikely(err < 0))
150 goto out_free;
151
152 err = 0;
153 e = p + ssz;
154 value = NULL;
155 acl_access = 0;
156 acl_default = 0;
157 while (!err && p < e) {
158 acl_access |= !strncmp(p, XATTR_NAME_POSIX_ACL_ACCESS,
159 sizeof(XATTR_NAME_POSIX_ACL_ACCESS) - 1);
160 acl_default |= !strncmp(p, XATTR_NAME_POSIX_ACL_DEFAULT,
161 sizeof(XATTR_NAME_POSIX_ACL_DEFAULT)
162 - 1);
163 err = au_do_cpup_xattr(h_dst, h_src, p, &value, ignore_flags,
164 verbose);
165 p += strlen(p) + 1;
166 }
167 AuTraceErr(err);
168 ignore_flags |= au_xattr_out_of_list;
169 if (!err && !acl_access) {
170 err = au_do_cpup_xattr(h_dst, h_src,
171 XATTR_NAME_POSIX_ACL_ACCESS, &value,
172 ignore_flags, verbose);
173 AuTraceErr(err);
174 }
175 if (!err && !acl_default) {
176 err = au_do_cpup_xattr(h_dst, h_src,
177 XATTR_NAME_POSIX_ACL_DEFAULT, &value,
178 ignore_flags, verbose);
179 AuTraceErr(err);
180 }
181
182 au_kfree_try_rcu(value);
183
184 out_free:
185 au_kfree_try_rcu(o);
186 out:
187 if (!unlocked)
188 inode_unlock_shared(h_isrc);
189 AuTraceErr(err);
190 return err;
191 }
192
193 /* ---------------------------------------------------------------------- */
194
195 static int au_smack_reentering(struct super_block *sb)
196 {
197 #if IS_ENABLED(CONFIG_SECURITY_SMACK)
198 /*
199 * as a part of lookup, smack_d_instantiate() is called, and it calls
200 * i_op->getxattr(). ouch.
201 */
202 return si_pid_test(sb);
203 #else
204 return 0;
205 #endif
206 }
207
208 enum {
209 AU_XATTR_LIST,
210 AU_XATTR_GET
211 };
212
213 struct au_lgxattr {
214 int type;
215 union {
216 struct {
217 char *list;
218 size_t size;
219 } list;
220 struct {
221 const char *name;
222 void *value;
223 size_t size;
224 } get;
225 } u;
226 };
227
228 static ssize_t au_lgxattr(struct dentry *dentry, struct au_lgxattr *arg)
229 {
230 ssize_t err;
231 int reenter;
232 struct path h_path;
233 struct super_block *sb;
234
235 sb = dentry->d_sb;
236 reenter = au_smack_reentering(sb);
237 if (!reenter) {
238 err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
239 if (unlikely(err))
240 goto out;
241 }
242 err = au_h_path_getattr(dentry, /*force*/1, &h_path, reenter);
243 if (unlikely(err))
244 goto out_si;
245 if (unlikely(!h_path.dentry))
246 /* illegally overlapped or something */
247 goto out_di; /* pretending success */
248
249 /* always topmost entry only */
250 switch (arg->type) {
251 case AU_XATTR_LIST:
252 err = vfs_listxattr(h_path.dentry,
253 arg->u.list.list, arg->u.list.size);
254 break;
255 case AU_XATTR_GET:
256 AuDebugOn(d_is_negative(h_path.dentry));
257 err = vfs_getxattr(h_path.dentry,
258 arg->u.get.name, arg->u.get.value,
259 arg->u.get.size);
260 break;
261 }
262
263 out_di:
264 if (!reenter)
265 di_read_unlock(dentry, AuLock_IR);
266 out_si:
267 if (!reenter)
268 si_read_unlock(sb);
269 out:
270 AuTraceErr(err);
271 return err;
272 }
273
274 ssize_t aufs_listxattr(struct dentry *dentry, char *list, size_t size)
275 {
276 struct au_lgxattr arg = {
277 .type = AU_XATTR_LIST,
278 .u.list = {
279 .list = list,
280 .size = size
281 },
282 };
283
284 return au_lgxattr(dentry, &arg);
285 }
286
287 static ssize_t au_getxattr(struct dentry *dentry,
288 struct inode *inode __maybe_unused,
289 const char *name, void *value, size_t size)
290 {
291 struct au_lgxattr arg = {
292 .type = AU_XATTR_GET,
293 .u.get = {
294 .name = name,
295 .value = value,
296 .size = size
297 },
298 };
299
300 return au_lgxattr(dentry, &arg);
301 }
302
303 static int au_setxattr(struct dentry *dentry, struct inode *inode,
304 const char *name, const void *value, size_t size,
305 int flags)
306 {
307 struct au_sxattr arg = {
308 .type = AU_XATTR_SET,
309 .u.set = {
310 .name = name,
311 .value = value,
312 .size = size,
313 .flags = flags
314 },
315 };
316
317 return au_sxattr(dentry, inode, &arg);
318 }
319
320 /* ---------------------------------------------------------------------- */
321
322 static int au_xattr_get(const struct xattr_handler *handler,
323 struct dentry *dentry, struct inode *inode,
324 const char *name, void *buffer, size_t size)
325 {
326 return au_getxattr(dentry, inode, name, buffer, size);
327 }
328
329 static int au_xattr_set(const struct xattr_handler *handler,
330 struct dentry *dentry, struct inode *inode,
331 const char *name, const void *value, size_t size,
332 int flags)
333 {
334 return au_setxattr(dentry, inode, name, value, size, flags);
335 }
336
337 static const struct xattr_handler au_xattr_handler = {
338 .name = "",
339 .prefix = "",
340 .get = au_xattr_get,
341 .set = au_xattr_set
342 };
343
344 static const struct xattr_handler *au_xattr_handlers[] = {
345 #ifdef CONFIG_FS_POSIX_ACL
346 &posix_acl_access_xattr_handler,
347 &posix_acl_default_xattr_handler,
348 #endif
349 &au_xattr_handler, /* must be last */
350 NULL
351 };
352
353 void au_xattr_init(struct super_block *sb)
354 {
355 sb->s_xattr = au_xattr_handlers;
356 }