xref: /linux/fs/overlayfs/xattrs.c (revision fab183d632628381b466a41479489541ac0e29a0)
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) == 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 
45 	if (!value && !upperdentry) {
46 		ovl_path_lower(dentry, &realpath);
47 		with_ovl_creds(dentry->d_sb)
48 			err = vfs_getxattr(mnt_idmap(realpath.mnt), realdentry, name, NULL, 0);
49 		if (err < 0)
50 			goto out;
51 	}
52 
53 	if (!upperdentry) {
54 		err = ovl_copy_up(dentry);
55 		if (err)
56 			goto out;
57 
58 		realdentry = ovl_dentry_upper(dentry);
59 	}
60 
61 	err = ovl_want_write(dentry);
62 	if (err)
63 		goto out;
64 
65 	with_ovl_creds(dentry->d_sb) {
66 		if (value) {
67 			err = ovl_do_setxattr(ofs, realdentry, name, value, size, flags);
68 		} else {
69 			WARN_ON(flags != XATTR_REPLACE);
70 			err = ovl_do_removexattr(ofs, realdentry, name);
71 		}
72 	}
73 	ovl_drop_write(dentry);
74 
75 	/* copy c/mtime */
76 	ovl_copyattr(inode);
77 out:
78 	return err;
79 }
80 
ovl_xattr_get(struct dentry * dentry,struct inode * inode,const char * name,void * value,size_t size)81 static int ovl_xattr_get(struct dentry *dentry, struct inode *inode, const char *name,
82 			 void *value, size_t size)
83 {
84 	struct path realpath;
85 
86 	ovl_i_path_real(inode, &realpath);
87 	/* Use vfs_getxattr(), not __vfs_getxattr(): it idmaps the security.capability rootid. */
88 	with_ovl_creds(dentry->d_sb)
89 		return vfs_getxattr(mnt_idmap(realpath.mnt), realpath.dentry, name, value, size);
90 }
91 
ovl_can_list(struct super_block * sb,const char * s)92 static bool ovl_can_list(struct super_block *sb, const char *s)
93 {
94 	/* Never list private (.overlay) */
95 	if (ovl_is_private_xattr(sb, s))
96 		return false;
97 
98 	/* List all non-trusted xattrs */
99 	if (strncmp(s, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN) != 0)
100 		return true;
101 
102 	/* list other trusted for superuser only */
103 	return ns_capable_noaudit(&init_user_ns, CAP_SYS_ADMIN);
104 }
105 
ovl_listxattr(struct dentry * dentry,char * list,size_t size)106 ssize_t ovl_listxattr(struct dentry *dentry, char *list, size_t size)
107 {
108 	struct dentry *realdentry = ovl_dentry_real(dentry);
109 	struct ovl_fs *ofs = OVL_FS(dentry->d_sb);
110 	ssize_t res;
111 	size_t len;
112 	char *s;
113 	size_t prefix_len, name_len;
114 
115 	with_ovl_creds(dentry->d_sb)
116 		res = vfs_listxattr(realdentry, list, size);
117 	if (res <= 0 || size == 0)
118 		return res;
119 
120 	prefix_len = ofs->config.userxattr ?
121 		OVL_XATTR_USER_PREFIX_LEN : OVL_XATTR_TRUSTED_PREFIX_LEN;
122 
123 	/* filter out private xattrs */
124 	for (s = list, len = res; len;) {
125 		size_t slen = strnlen(s, len) + 1;
126 
127 		/* underlying fs providing us with an broken xattr list? */
128 		if (WARN_ON(slen > len))
129 			return -EIO;
130 
131 		len -= slen;
132 		if (!ovl_can_list(dentry->d_sb, s)) {
133 			res -= slen;
134 			memmove(s, s + slen, len);
135 		} else if (ovl_is_escaped_xattr(dentry->d_sb, s)) {
136 			res -= OVL_XATTR_ESCAPE_PREFIX_LEN;
137 			name_len = slen - prefix_len - OVL_XATTR_ESCAPE_PREFIX_LEN;
138 			s += prefix_len;
139 			memmove(s, s + OVL_XATTR_ESCAPE_PREFIX_LEN, name_len + len);
140 			s += name_len;
141 		} else {
142 			s += slen;
143 		}
144 	}
145 
146 	return res;
147 }
148 
ovl_xattr_escape_name(const char * prefix,const char * name)149 static char *ovl_xattr_escape_name(const char *prefix, const char *name)
150 {
151 	size_t prefix_len = strlen(prefix);
152 	size_t name_len = strlen(name);
153 	size_t escaped_len;
154 	char *escaped, *s;
155 
156 	escaped_len = prefix_len + OVL_XATTR_ESCAPE_PREFIX_LEN + name_len;
157 	if (escaped_len > XATTR_NAME_MAX)
158 		return ERR_PTR(-EOPNOTSUPP);
159 
160 	escaped = kmalloc(escaped_len + 1, GFP_KERNEL);
161 	if (escaped == NULL)
162 		return ERR_PTR(-ENOMEM);
163 
164 	s = escaped;
165 	memcpy(s, prefix, prefix_len);
166 	s += prefix_len;
167 	memcpy(s, OVL_XATTR_ESCAPE_PREFIX, OVL_XATTR_ESCAPE_PREFIX_LEN);
168 	s += OVL_XATTR_ESCAPE_PREFIX_LEN;
169 	memcpy(s, name, name_len + 1);
170 
171 	return escaped;
172 }
173 
ovl_own_xattr_get(const struct xattr_handler * handler,struct dentry * dentry,struct inode * inode,const char * name,void * buffer,size_t size)174 static int ovl_own_xattr_get(const struct xattr_handler *handler,
175 			     struct dentry *dentry, struct inode *inode,
176 			     const char *name, void *buffer, size_t size)
177 {
178 	char *escaped;
179 	int r;
180 
181 	escaped = ovl_xattr_escape_name(handler->prefix, name);
182 	if (IS_ERR(escaped))
183 		return PTR_ERR(escaped);
184 
185 	r = ovl_xattr_get(dentry, inode, escaped, buffer, size);
186 
187 	kfree(escaped);
188 
189 	return r;
190 }
191 
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)192 static int ovl_own_xattr_set(const struct xattr_handler *handler,
193 			     struct mnt_idmap *idmap,
194 			     struct dentry *dentry, struct inode *inode,
195 			     const char *name, const void *value,
196 			     size_t size, int flags)
197 {
198 	char *escaped;
199 	int r;
200 
201 	escaped = ovl_xattr_escape_name(handler->prefix, name);
202 	if (IS_ERR(escaped))
203 		return PTR_ERR(escaped);
204 
205 	r = ovl_xattr_set(dentry, inode, escaped, value, size, flags);
206 
207 	kfree(escaped);
208 
209 	return r;
210 }
211 
ovl_other_xattr_get(const struct xattr_handler * handler,struct dentry * dentry,struct inode * inode,const char * name,void * buffer,size_t size)212 static int ovl_other_xattr_get(const struct xattr_handler *handler,
213 			       struct dentry *dentry, struct inode *inode,
214 			       const char *name, void *buffer, size_t size)
215 {
216 	return ovl_xattr_get(dentry, inode, name, buffer, size);
217 }
218 
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)219 static int ovl_other_xattr_set(const struct xattr_handler *handler,
220 			       struct mnt_idmap *idmap,
221 			       struct dentry *dentry, struct inode *inode,
222 			       const char *name, const void *value,
223 			       size_t size, int flags)
224 {
225 	return ovl_xattr_set(dentry, inode, name, value, size, flags);
226 }
227 
228 static const struct xattr_handler ovl_own_trusted_xattr_handler = {
229 	.prefix	= OVL_XATTR_TRUSTED_PREFIX,
230 	.get = ovl_own_xattr_get,
231 	.set = ovl_own_xattr_set,
232 };
233 
234 static const struct xattr_handler ovl_own_user_xattr_handler = {
235 	.prefix	= OVL_XATTR_USER_PREFIX,
236 	.get = ovl_own_xattr_get,
237 	.set = ovl_own_xattr_set,
238 };
239 
240 static const struct xattr_handler ovl_other_xattr_handler = {
241 	.prefix	= "", /* catch all */
242 	.get = ovl_other_xattr_get,
243 	.set = ovl_other_xattr_set,
244 };
245 
246 static const struct xattr_handler * const ovl_trusted_xattr_handlers[] = {
247 	&ovl_own_trusted_xattr_handler,
248 	&ovl_other_xattr_handler,
249 	NULL
250 };
251 
252 static const struct xattr_handler * const ovl_user_xattr_handlers[] = {
253 	&ovl_own_user_xattr_handler,
254 	&ovl_other_xattr_handler,
255 	NULL
256 };
257 
ovl_xattr_handlers(struct ovl_fs * ofs)258 const struct xattr_handler * const *ovl_xattr_handlers(struct ovl_fs *ofs)
259 {
260 	return ofs->config.userxattr ? ovl_user_xattr_handlers :
261 		ovl_trusted_xattr_handlers;
262 }
263