xref: /linux/fs/overlayfs/xattrs.c (revision dad02fad)
1 // SPDX-License-Identifier: GPL-2.0-only
2 
3 #include <linux/fs.h>
4 #include <linux/xattr.h>
5 #include "overlayfs.h"
6 
ovl_is_escaped_xattr(struct super_block * sb,const char * name)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 
ovl_is_own_xattr(struct super_block * sb,const char * name)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 
ovl_is_private_xattr(struct super_block * sb,const char * name)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 
ovl_xattr_set(struct dentry * dentry,struct inode * inode,const char * name,const void * value,size_t size,int flags)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 
ovl_xattr_get(struct dentry * dentry,struct inode * inode,const char * name,void * value,size_t size)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 
ovl_can_list(struct super_block * sb,const char * s)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 
ovl_listxattr(struct dentry * dentry,char * list,size_t size)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 
ovl_xattr_escape_name(const char * prefix,const char * name)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 
ovl_own_xattr_get(const struct xattr_handler * handler,struct dentry * dentry,struct inode * inode,const char * name,void * buffer,size_t size)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 
ovl_own_xattr_set(const struct xattr_handler * handler,struct mnt_idmap * idmap,struct dentry * dentry,struct inode * inode,const char * name,const void * value,size_t size,int flags)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 
ovl_other_xattr_get(const struct xattr_handler * handler,struct dentry * dentry,struct inode * inode,const char * name,void * buffer,size_t size)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 
ovl_other_xattr_set(const struct xattr_handler * handler,struct mnt_idmap * idmap,struct dentry * dentry,struct inode * inode,const char * name,const void * value,size_t size,int flags)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 
ovl_xattr_handlers(struct ovl_fs * ofs)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 
272