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