Merge branch 'linus' into x86/boot, to resolve conflict
[linux-2.6-microblaze.git] / fs / overlayfs / xattrs.c
1 // SPDX-License-Identifier: GPL-2.0-only
2
3 #include <linux/fs.h>
4 #include <linux/xattr.h>
5 #include "overlayfs.h"
6
7 static bool ovl_is_escaped_xattr(struct super_block *sb, const char *name)
8 {
9         struct ovl_fs *ofs = sb->s_fs_info;
10
11         if (ofs->config.userxattr)
12                 return strncmp(name, OVL_XATTR_ESCAPE_USER_PREFIX,
13                                OVL_XATTR_ESCAPE_USER_PREFIX_LEN) == 0;
14         else
15                 return strncmp(name, OVL_XATTR_ESCAPE_TRUSTED_PREFIX,
16                                OVL_XATTR_ESCAPE_TRUSTED_PREFIX_LEN - 1) == 0;
17 }
18
19 static bool ovl_is_own_xattr(struct super_block *sb, const char *name)
20 {
21         struct ovl_fs *ofs = OVL_FS(sb);
22
23         if (ofs->config.userxattr)
24                 return strncmp(name, OVL_XATTR_USER_PREFIX,
25                                OVL_XATTR_USER_PREFIX_LEN) == 0;
26         else
27                 return strncmp(name, OVL_XATTR_TRUSTED_PREFIX,
28                                OVL_XATTR_TRUSTED_PREFIX_LEN) == 0;
29 }
30
31 bool ovl_is_private_xattr(struct super_block *sb, const char *name)
32 {
33         return ovl_is_own_xattr(sb, name) && !ovl_is_escaped_xattr(sb, name);
34 }
35
36 static int ovl_xattr_set(struct dentry *dentry, struct inode *inode, const char *name,
37                          const void *value, size_t size, int flags)
38 {
39         int err;
40         struct ovl_fs *ofs = OVL_FS(dentry->d_sb);
41         struct dentry *upperdentry = ovl_i_dentry_upper(inode);
42         struct dentry *realdentry = upperdentry ?: ovl_dentry_lower(dentry);
43         struct path realpath;
44         const struct cred *old_cred;
45
46         if (!value && !upperdentry) {
47                 ovl_path_lower(dentry, &realpath);
48                 old_cred = ovl_override_creds(dentry->d_sb);
49                 err = vfs_getxattr(mnt_idmap(realpath.mnt), realdentry, name, NULL, 0);
50                 revert_creds(old_cred);
51                 if (err < 0)
52                         goto out;
53         }
54
55         if (!upperdentry) {
56                 err = ovl_copy_up(dentry);
57                 if (err)
58                         goto out;
59
60                 realdentry = ovl_dentry_upper(dentry);
61         }
62
63         err = ovl_want_write(dentry);
64         if (err)
65                 goto out;
66
67         old_cred = ovl_override_creds(dentry->d_sb);
68         if (value) {
69                 err = ovl_do_setxattr(ofs, realdentry, name, value, size,
70                                       flags);
71         } else {
72                 WARN_ON(flags != XATTR_REPLACE);
73                 err = ovl_do_removexattr(ofs, realdentry, name);
74         }
75         revert_creds(old_cred);
76         ovl_drop_write(dentry);
77
78         /* copy c/mtime */
79         ovl_copyattr(inode);
80 out:
81         return err;
82 }
83
84 static int ovl_xattr_get(struct dentry *dentry, struct inode *inode, const char *name,
85                          void *value, size_t size)
86 {
87         ssize_t res;
88         const struct cred *old_cred;
89         struct path realpath;
90
91         ovl_i_path_real(inode, &realpath);
92         old_cred = ovl_override_creds(dentry->d_sb);
93         res = vfs_getxattr(mnt_idmap(realpath.mnt), realpath.dentry, name, value, size);
94         revert_creds(old_cred);
95         return res;
96 }
97
98 static bool ovl_can_list(struct super_block *sb, const char *s)
99 {
100         /* Never list private (.overlay) */
101         if (ovl_is_private_xattr(sb, s))
102                 return false;
103
104         /* List all non-trusted xattrs */
105         if (strncmp(s, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN) != 0)
106                 return true;
107
108         /* list other trusted for superuser only */
109         return ns_capable_noaudit(&init_user_ns, CAP_SYS_ADMIN);
110 }
111
112 ssize_t ovl_listxattr(struct dentry *dentry, char *list, size_t size)
113 {
114         struct dentry *realdentry = ovl_dentry_real(dentry);
115         struct ovl_fs *ofs = OVL_FS(dentry->d_sb);
116         ssize_t res;
117         size_t len;
118         char *s;
119         const struct cred *old_cred;
120         size_t prefix_len, name_len;
121
122         old_cred = ovl_override_creds(dentry->d_sb);
123         res = vfs_listxattr(realdentry, list, size);
124         revert_creds(old_cred);
125         if (res <= 0 || size == 0)
126                 return res;
127
128         prefix_len = ofs->config.userxattr ?
129                 OVL_XATTR_USER_PREFIX_LEN : OVL_XATTR_TRUSTED_PREFIX_LEN;
130
131         /* filter out private xattrs */
132         for (s = list, len = res; len;) {
133                 size_t slen = strnlen(s, len) + 1;
134
135                 /* underlying fs providing us with an broken xattr list? */
136                 if (WARN_ON(slen > len))
137                         return -EIO;
138
139                 len -= slen;
140                 if (!ovl_can_list(dentry->d_sb, s)) {
141                         res -= slen;
142                         memmove(s, s + slen, len);
143                 } else if (ovl_is_escaped_xattr(dentry->d_sb, s)) {
144                         res -= OVL_XATTR_ESCAPE_PREFIX_LEN;
145                         name_len = slen - prefix_len - OVL_XATTR_ESCAPE_PREFIX_LEN;
146                         s += prefix_len;
147                         memmove(s, s + OVL_XATTR_ESCAPE_PREFIX_LEN, name_len + len);
148                         s += name_len;
149                 } else {
150                         s += slen;
151                 }
152         }
153
154         return res;
155 }
156
157 static char *ovl_xattr_escape_name(const char *prefix, const char *name)
158 {
159         size_t prefix_len = strlen(prefix);
160         size_t name_len = strlen(name);
161         size_t escaped_len;
162         char *escaped, *s;
163
164         escaped_len = prefix_len + OVL_XATTR_ESCAPE_PREFIX_LEN + name_len;
165         if (escaped_len > XATTR_NAME_MAX)
166                 return ERR_PTR(-EOPNOTSUPP);
167
168         escaped = kmalloc(escaped_len + 1, GFP_KERNEL);
169         if (escaped == NULL)
170                 return ERR_PTR(-ENOMEM);
171
172         s = escaped;
173         memcpy(s, prefix, prefix_len);
174         s += prefix_len;
175         memcpy(s, OVL_XATTR_ESCAPE_PREFIX, OVL_XATTR_ESCAPE_PREFIX_LEN);
176         s += OVL_XATTR_ESCAPE_PREFIX_LEN;
177         memcpy(s, name, name_len + 1);
178
179         return escaped;
180 }
181
182 static int ovl_own_xattr_get(const struct xattr_handler *handler,
183                              struct dentry *dentry, struct inode *inode,
184                              const char *name, void *buffer, size_t size)
185 {
186         char *escaped;
187         int r;
188
189         escaped = ovl_xattr_escape_name(handler->prefix, name);
190         if (IS_ERR(escaped))
191                 return PTR_ERR(escaped);
192
193         r = ovl_xattr_get(dentry, inode, escaped, buffer, size);
194
195         kfree(escaped);
196
197         return r;
198 }
199
200 static int ovl_own_xattr_set(const struct xattr_handler *handler,
201                              struct mnt_idmap *idmap,
202                              struct dentry *dentry, struct inode *inode,
203                              const char *name, const void *value,
204                              size_t size, int flags)
205 {
206         char *escaped;
207         int r;
208
209         escaped = ovl_xattr_escape_name(handler->prefix, name);
210         if (IS_ERR(escaped))
211                 return PTR_ERR(escaped);
212
213         r = ovl_xattr_set(dentry, inode, escaped, value, size, flags);
214
215         kfree(escaped);
216
217         return r;
218 }
219
220 static int ovl_other_xattr_get(const struct xattr_handler *handler,
221                                struct dentry *dentry, struct inode *inode,
222                                const char *name, void *buffer, size_t size)
223 {
224         return ovl_xattr_get(dentry, inode, name, buffer, size);
225 }
226
227 static int ovl_other_xattr_set(const struct xattr_handler *handler,
228                                struct mnt_idmap *idmap,
229                                struct dentry *dentry, struct inode *inode,
230                                const char *name, const void *value,
231                                size_t size, int flags)
232 {
233         return ovl_xattr_set(dentry, inode, name, value, size, flags);
234 }
235
236 static const struct xattr_handler ovl_own_trusted_xattr_handler = {
237         .prefix = OVL_XATTR_TRUSTED_PREFIX,
238         .get = ovl_own_xattr_get,
239         .set = ovl_own_xattr_set,
240 };
241
242 static const struct xattr_handler ovl_own_user_xattr_handler = {
243         .prefix = OVL_XATTR_USER_PREFIX,
244         .get = ovl_own_xattr_get,
245         .set = ovl_own_xattr_set,
246 };
247
248 static const struct xattr_handler ovl_other_xattr_handler = {
249         .prefix = "", /* catch all */
250         .get = ovl_other_xattr_get,
251         .set = ovl_other_xattr_set,
252 };
253
254 static const struct xattr_handler * const ovl_trusted_xattr_handlers[] = {
255         &ovl_own_trusted_xattr_handler,
256         &ovl_other_xattr_handler,
257         NULL
258 };
259
260 static const struct xattr_handler * const ovl_user_xattr_handlers[] = {
261         &ovl_own_user_xattr_handler,
262         &ovl_other_xattr_handler,
263         NULL
264 };
265
266 const struct xattr_handler * const *ovl_xattr_handlers(struct ovl_fs *ofs)
267 {
268         return ofs->config.userxattr ? ovl_user_xattr_handlers :
269                 ovl_trusted_xattr_handlers;
270 }
271