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 272
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.