1 // SPDX-License-Identifier: GPL-2.0-only
4 #include <linux/xattr.h>
7 static bool ovl_is_escaped_xattr(struct super_block
*sb
, const char *name
)
9 struct ovl_fs
*ofs
= sb
->s_fs_info
;
11 if (ofs
->config
.userxattr
)
12 return strncmp(name
, OVL_XATTR_ESCAPE_USER_PREFIX
,
13 OVL_XATTR_ESCAPE_USER_PREFIX_LEN
) == 0;
15 return strncmp(name
, OVL_XATTR_ESCAPE_TRUSTED_PREFIX
,
16 OVL_XATTR_ESCAPE_TRUSTED_PREFIX_LEN
- 1) == 0;
19 static bool ovl_is_own_xattr(struct super_block
*sb
, const char *name
)
21 struct ovl_fs
*ofs
= OVL_FS(sb
);
23 if (ofs
->config
.userxattr
)
24 return strncmp(name
, OVL_XATTR_USER_PREFIX
,
25 OVL_XATTR_USER_PREFIX_LEN
) == 0;
27 return strncmp(name
, OVL_XATTR_TRUSTED_PREFIX
,
28 OVL_XATTR_TRUSTED_PREFIX_LEN
) == 0;
31 bool ovl_is_private_xattr(struct super_block
*sb
, const char *name
)
33 return ovl_is_own_xattr(sb
, name
) && !ovl_is_escaped_xattr(sb
, name
);
36 static int ovl_xattr_set(struct dentry
*dentry
, struct inode
*inode
, const char *name
,
37 const void *value
, size_t size
, int flags
)
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
);
44 const struct cred
*old_cred
;
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 ovl_revert_creds(old_cred
);
56 err
= ovl_copy_up(dentry
);
60 realdentry
= ovl_dentry_upper(dentry
);
63 err
= ovl_want_write(dentry
);
67 old_cred
= ovl_override_creds(dentry
->d_sb
);
69 err
= ovl_do_setxattr(ofs
, realdentry
, name
, value
, size
,
72 WARN_ON(flags
!= XATTR_REPLACE
);
73 err
= ovl_do_removexattr(ofs
, realdentry
, name
);
75 ovl_revert_creds(old_cred
);
76 ovl_drop_write(dentry
);
84 static int ovl_xattr_get(struct dentry
*dentry
, struct inode
*inode
, const char *name
,
85 void *value
, size_t size
)
88 const struct cred
*old_cred
;
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 ovl_revert_creds(old_cred
);
98 static bool ovl_can_list(struct super_block
*sb
, const char *s
)
100 /* Never list private (.overlay) */
101 if (ovl_is_private_xattr(sb
, s
))
104 /* List all non-trusted xattrs */
105 if (strncmp(s
, XATTR_TRUSTED_PREFIX
, XATTR_TRUSTED_PREFIX_LEN
) != 0)
108 /* list other trusted for superuser only */
109 return ns_capable_noaudit(&init_user_ns
, CAP_SYS_ADMIN
);
112 ssize_t
ovl_listxattr(struct dentry
*dentry
, char *list
, size_t size
)
114 struct dentry
*realdentry
= ovl_dentry_real(dentry
);
115 struct ovl_fs
*ofs
= OVL_FS(dentry
->d_sb
);
119 const struct cred
*old_cred
;
120 size_t prefix_len
, name_len
;
122 old_cred
= ovl_override_creds(dentry
->d_sb
);
123 res
= vfs_listxattr(realdentry
, list
, size
);
124 ovl_revert_creds(old_cred
);
125 if (res
<= 0 || size
== 0)
128 prefix_len
= ofs
->config
.userxattr
?
129 OVL_XATTR_USER_PREFIX_LEN
: OVL_XATTR_TRUSTED_PREFIX_LEN
;
131 /* filter out private xattrs */
132 for (s
= list
, len
= res
; len
;) {
133 size_t slen
= strnlen(s
, len
) + 1;
135 /* underlying fs providing us with an broken xattr list? */
136 if (WARN_ON(slen
> len
))
140 if (!ovl_can_list(dentry
->d_sb
, s
)) {
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
;
147 memmove(s
, s
+ OVL_XATTR_ESCAPE_PREFIX_LEN
, name_len
+ len
);
157 static char *ovl_xattr_escape_name(const char *prefix
, const char *name
)
159 size_t prefix_len
= strlen(prefix
);
160 size_t name_len
= strlen(name
);
164 escaped_len
= prefix_len
+ OVL_XATTR_ESCAPE_PREFIX_LEN
+ name_len
;
165 if (escaped_len
> XATTR_NAME_MAX
)
166 return ERR_PTR(-EOPNOTSUPP
);
168 escaped
= kmalloc(escaped_len
+ 1, GFP_KERNEL
);
170 return ERR_PTR(-ENOMEM
);
173 memcpy(s
, prefix
, 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);
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
)
189 escaped
= ovl_xattr_escape_name(handler
->prefix
, name
);
191 return PTR_ERR(escaped
);
193 r
= ovl_xattr_get(dentry
, inode
, escaped
, buffer
, size
);
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
)
209 escaped
= ovl_xattr_escape_name(handler
->prefix
, name
);
211 return PTR_ERR(escaped
);
213 r
= ovl_xattr_set(dentry
, inode
, escaped
, value
, size
, flags
);
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
)
224 return ovl_xattr_get(dentry
, inode
, name
, buffer
, size
);
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
)
233 return ovl_xattr_set(dentry
, inode
, name
, value
, size
, flags
);
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
,
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
,
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
,
254 static const struct xattr_handler
* const ovl_trusted_xattr_handlers
[] = {
255 &ovl_own_trusted_xattr_handler
,
256 &ovl_other_xattr_handler
,
260 static const struct xattr_handler
* const ovl_user_xattr_handlers
[] = {
261 &ovl_own_user_xattr_handler
,
262 &ovl_other_xattr_handler
,
266 const struct xattr_handler
* const *ovl_xattr_handlers(struct ovl_fs
*ofs
)
268 return ofs
->config
.userxattr
? ovl_user_xattr_handlers
:
269 ovl_trusted_xattr_handlers
;