| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | File: fs/xattr.c |
|---|
| 3 | 4 | |
|---|
| .. | .. |
|---|
| 130 | 131 | return -EPERM; |
|---|
| 131 | 132 | } |
|---|
| 132 | 133 | |
|---|
| 133 | | - return inode_permission2(ERR_PTR(-EOPNOTSUPP), inode, mask); |
|---|
| 134 | + return inode_permission(inode, mask); |
|---|
| 134 | 135 | } |
|---|
| 136 | + |
|---|
| 137 | +/* |
|---|
| 138 | + * Look for any handler that deals with the specified namespace. |
|---|
| 139 | + */ |
|---|
| 140 | +int |
|---|
| 141 | +xattr_supported_namespace(struct inode *inode, const char *prefix) |
|---|
| 142 | +{ |
|---|
| 143 | + const struct xattr_handler **handlers = inode->i_sb->s_xattr; |
|---|
| 144 | + const struct xattr_handler *handler; |
|---|
| 145 | + size_t preflen; |
|---|
| 146 | + |
|---|
| 147 | + if (!(inode->i_opflags & IOP_XATTR)) { |
|---|
| 148 | + if (unlikely(is_bad_inode(inode))) |
|---|
| 149 | + return -EIO; |
|---|
| 150 | + return -EOPNOTSUPP; |
|---|
| 151 | + } |
|---|
| 152 | + |
|---|
| 153 | + preflen = strlen(prefix); |
|---|
| 154 | + |
|---|
| 155 | + for_each_xattr_handler(handlers, handler) { |
|---|
| 156 | + if (!strncmp(xattr_prefix(handler), prefix, preflen)) |
|---|
| 157 | + return 0; |
|---|
| 158 | + } |
|---|
| 159 | + |
|---|
| 160 | + return -EOPNOTSUPP; |
|---|
| 161 | +} |
|---|
| 162 | +EXPORT_SYMBOL(xattr_supported_namespace); |
|---|
| 135 | 163 | |
|---|
| 136 | 164 | int |
|---|
| 137 | 165 | __vfs_setxattr(struct dentry *dentry, struct inode *inode, const char *name, |
|---|
| .. | .. |
|---|
| 204 | 232 | } |
|---|
| 205 | 233 | |
|---|
| 206 | 234 | /** |
|---|
| 207 | | - * __vfs_setxattr_locked: set an extended attribute while holding the inode |
|---|
| 235 | + * __vfs_setxattr_locked - set an extended attribute while holding the inode |
|---|
| 208 | 236 | * lock |
|---|
| 209 | 237 | * |
|---|
| 210 | | - * @dentry - object to perform setxattr on |
|---|
| 211 | | - * @name - xattr name to set |
|---|
| 212 | | - * @value - value to set @name to |
|---|
| 213 | | - * @size - size of @value |
|---|
| 214 | | - * @flags - flags to pass into filesystem operations |
|---|
| 215 | | - * @delegated_inode - on return, will contain an inode pointer that |
|---|
| 238 | + * @dentry: object to perform setxattr on |
|---|
| 239 | + * @name: xattr name to set |
|---|
| 240 | + * @value: value to set @name to |
|---|
| 241 | + * @size: size of @value |
|---|
| 242 | + * @flags: flags to pass into filesystem operations |
|---|
| 243 | + * @delegated_inode: on return, will contain an inode pointer that |
|---|
| 216 | 244 | * a delegation was broken on, NULL if none. |
|---|
| 217 | 245 | */ |
|---|
| 218 | 246 | int |
|---|
| .. | .. |
|---|
| 263 | 291 | } |
|---|
| 264 | 292 | return error; |
|---|
| 265 | 293 | } |
|---|
| 266 | | -EXPORT_SYMBOL_GPL(vfs_setxattr); |
|---|
| 294 | +EXPORT_SYMBOL_NS_GPL(vfs_setxattr, ANDROID_GKI_VFS_EXPORT_ONLY); |
|---|
| 267 | 295 | |
|---|
| 268 | 296 | static ssize_t |
|---|
| 269 | 297 | xattr_getsecurity(struct inode *inode, const char *name, void *value, |
|---|
| .. | .. |
|---|
| 317 | 345 | return PTR_ERR(handler); |
|---|
| 318 | 346 | if (!handler->get) |
|---|
| 319 | 347 | return -EOPNOTSUPP; |
|---|
| 320 | | - error = handler->get(handler, dentry, inode, name, NULL, 0); |
|---|
| 348 | + error = handler->get(handler, dentry, inode, name, NULL, 0, 0); |
|---|
| 321 | 349 | if (error < 0) |
|---|
| 322 | 350 | return error; |
|---|
| 323 | 351 | |
|---|
| .. | .. |
|---|
| 328 | 356 | memset(value, 0, error + 1); |
|---|
| 329 | 357 | } |
|---|
| 330 | 358 | |
|---|
| 331 | | - error = handler->get(handler, dentry, inode, name, value, error); |
|---|
| 359 | + error = handler->get(handler, dentry, inode, name, value, error, 0); |
|---|
| 332 | 360 | *xattr_value = value; |
|---|
| 333 | 361 | return error; |
|---|
| 334 | 362 | } |
|---|
| 335 | 363 | |
|---|
| 336 | 364 | ssize_t |
|---|
| 337 | 365 | __vfs_getxattr(struct dentry *dentry, struct inode *inode, const char *name, |
|---|
| 338 | | - void *value, size_t size) |
|---|
| 366 | + void *value, size_t size, int flags) |
|---|
| 339 | 367 | { |
|---|
| 340 | 368 | const struct xattr_handler *handler; |
|---|
| 341 | | - |
|---|
| 342 | | - handler = xattr_resolve_name(inode, &name); |
|---|
| 343 | | - if (IS_ERR(handler)) |
|---|
| 344 | | - return PTR_ERR(handler); |
|---|
| 345 | | - if (unlikely(handler->__get)) |
|---|
| 346 | | - return handler->__get(handler, dentry, inode, name, value, |
|---|
| 347 | | - size); |
|---|
| 348 | | - if (!handler->get) |
|---|
| 349 | | - return -EOPNOTSUPP; |
|---|
| 350 | | - return handler->get(handler, dentry, inode, name, value, size); |
|---|
| 351 | | -} |
|---|
| 352 | | -EXPORT_SYMBOL(__vfs_getxattr); |
|---|
| 353 | | - |
|---|
| 354 | | -ssize_t |
|---|
| 355 | | -vfs_getxattr(struct dentry *dentry, const char *name, void *value, size_t size) |
|---|
| 356 | | -{ |
|---|
| 357 | | - struct inode *inode = dentry->d_inode; |
|---|
| 358 | 369 | int error; |
|---|
| 359 | | - const struct xattr_handler *handler; |
|---|
| 360 | 370 | |
|---|
| 371 | + if (flags & XATTR_NOSECURITY) |
|---|
| 372 | + goto nolsm; |
|---|
| 361 | 373 | error = xattr_permission(inode, name, MAY_READ); |
|---|
| 362 | 374 | if (error) |
|---|
| 363 | 375 | return error; |
|---|
| .. | .. |
|---|
| 384 | 396 | return PTR_ERR(handler); |
|---|
| 385 | 397 | if (!handler->get) |
|---|
| 386 | 398 | return -EOPNOTSUPP; |
|---|
| 387 | | - return handler->get(handler, dentry, inode, name, value, size); |
|---|
| 399 | + return handler->get(handler, dentry, inode, name, value, size, flags); |
|---|
| 388 | 400 | } |
|---|
| 389 | | -EXPORT_SYMBOL_GPL(vfs_getxattr); |
|---|
| 401 | +EXPORT_SYMBOL(__vfs_getxattr); |
|---|
| 402 | + |
|---|
| 403 | +ssize_t |
|---|
| 404 | +vfs_getxattr(struct dentry *dentry, const char *name, void *value, size_t size) |
|---|
| 405 | +{ |
|---|
| 406 | + return __vfs_getxattr(dentry, dentry->d_inode, name, value, size, 0); |
|---|
| 407 | +} |
|---|
| 408 | +EXPORT_SYMBOL_NS_GPL(vfs_getxattr, ANDROID_GKI_VFS_EXPORT_ONLY); |
|---|
| 390 | 409 | |
|---|
| 391 | 410 | ssize_t |
|---|
| 392 | 411 | vfs_listxattr(struct dentry *dentry, char *list, size_t size) |
|---|
| .. | .. |
|---|
| 406 | 425 | } |
|---|
| 407 | 426 | return error; |
|---|
| 408 | 427 | } |
|---|
| 409 | | -EXPORT_SYMBOL_GPL(vfs_listxattr); |
|---|
| 428 | +EXPORT_SYMBOL_NS_GPL(vfs_listxattr, ANDROID_GKI_VFS_EXPORT_ONLY); |
|---|
| 410 | 429 | |
|---|
| 411 | 430 | int |
|---|
| 412 | 431 | __vfs_removexattr(struct dentry *dentry, const char *name) |
|---|
| .. | .. |
|---|
| 424 | 443 | EXPORT_SYMBOL(__vfs_removexattr); |
|---|
| 425 | 444 | |
|---|
| 426 | 445 | /** |
|---|
| 427 | | - * __vfs_removexattr_locked: set an extended attribute while holding the inode |
|---|
| 446 | + * __vfs_removexattr_locked - set an extended attribute while holding the inode |
|---|
| 428 | 447 | * lock |
|---|
| 429 | 448 | * |
|---|
| 430 | | - * @dentry - object to perform setxattr on |
|---|
| 431 | | - * @name - name of xattr to remove |
|---|
| 432 | | - * @delegated_inode - on return, will contain an inode pointer that |
|---|
| 449 | + * @dentry: object to perform setxattr on |
|---|
| 450 | + * @name: name of xattr to remove |
|---|
| 451 | + * @delegated_inode: on return, will contain an inode pointer that |
|---|
| 433 | 452 | * a delegation was broken on, NULL if none. |
|---|
| 434 | 453 | */ |
|---|
| 435 | 454 | int |
|---|
| .. | .. |
|---|
| 895 | 914 | if (len < sizeof(*new_xattr)) |
|---|
| 896 | 915 | return NULL; |
|---|
| 897 | 916 | |
|---|
| 898 | | - new_xattr = kmalloc(len, GFP_KERNEL); |
|---|
| 917 | + new_xattr = kvmalloc(len, GFP_KERNEL); |
|---|
| 899 | 918 | if (!new_xattr) |
|---|
| 900 | 919 | return NULL; |
|---|
| 901 | 920 | |
|---|
| .. | .. |
|---|
| 938 | 957 | * @value: value of the xattr. If %NULL, will remove the attribute. |
|---|
| 939 | 958 | * @size: size of the new xattr |
|---|
| 940 | 959 | * @flags: %XATTR_{CREATE|REPLACE} |
|---|
| 960 | + * @removed_size: returns size of the removed xattr, -1 if none removed |
|---|
| 941 | 961 | * |
|---|
| 942 | 962 | * %XATTR_CREATE is set, the xattr shouldn't exist already; otherwise fails |
|---|
| 943 | 963 | * with -EEXIST. If %XATTR_REPLACE is set, the xattr should exist; |
|---|
| .. | .. |
|---|
| 946 | 966 | * Returns 0 on success, -errno on failure. |
|---|
| 947 | 967 | */ |
|---|
| 948 | 968 | int simple_xattr_set(struct simple_xattrs *xattrs, const char *name, |
|---|
| 949 | | - const void *value, size_t size, int flags) |
|---|
| 969 | + const void *value, size_t size, int flags, |
|---|
| 970 | + ssize_t *removed_size) |
|---|
| 950 | 971 | { |
|---|
| 951 | 972 | struct simple_xattr *xattr; |
|---|
| 952 | 973 | struct simple_xattr *new_xattr = NULL; |
|---|
| 953 | 974 | int err = 0; |
|---|
| 975 | + |
|---|
| 976 | + if (removed_size) |
|---|
| 977 | + *removed_size = -1; |
|---|
| 954 | 978 | |
|---|
| 955 | 979 | /* value == NULL means remove */ |
|---|
| 956 | 980 | if (value) { |
|---|
| .. | .. |
|---|
| 960 | 984 | |
|---|
| 961 | 985 | new_xattr->name = kstrdup(name, GFP_KERNEL); |
|---|
| 962 | 986 | if (!new_xattr->name) { |
|---|
| 963 | | - kfree(new_xattr); |
|---|
| 987 | + kvfree(new_xattr); |
|---|
| 964 | 988 | return -ENOMEM; |
|---|
| 965 | 989 | } |
|---|
| 966 | 990 | } |
|---|
| .. | .. |
|---|
| 973 | 997 | err = -EEXIST; |
|---|
| 974 | 998 | } else if (new_xattr) { |
|---|
| 975 | 999 | list_replace(&xattr->list, &new_xattr->list); |
|---|
| 1000 | + if (removed_size) |
|---|
| 1001 | + *removed_size = xattr->size; |
|---|
| 976 | 1002 | } else { |
|---|
| 977 | 1003 | list_del(&xattr->list); |
|---|
| 1004 | + if (removed_size) |
|---|
| 1005 | + *removed_size = xattr->size; |
|---|
| 978 | 1006 | } |
|---|
| 979 | 1007 | goto out; |
|---|
| 980 | 1008 | } |
|---|
| .. | .. |
|---|
| 990 | 1018 | spin_unlock(&xattrs->lock); |
|---|
| 991 | 1019 | if (xattr) { |
|---|
| 992 | 1020 | kfree(xattr->name); |
|---|
| 993 | | - kfree(xattr); |
|---|
| 1021 | + kvfree(xattr); |
|---|
| 994 | 1022 | } |
|---|
| 995 | 1023 | return err; |
|---|
| 996 | 1024 | |
|---|
| .. | .. |
|---|
| 1021 | 1049 | ssize_t simple_xattr_list(struct inode *inode, struct simple_xattrs *xattrs, |
|---|
| 1022 | 1050 | char *buffer, size_t size) |
|---|
| 1023 | 1051 | { |
|---|
| 1024 | | - bool trusted = capable(CAP_SYS_ADMIN); |
|---|
| 1052 | + bool trusted = ns_capable_noaudit(&init_user_ns, CAP_SYS_ADMIN); |
|---|
| 1025 | 1053 | struct simple_xattr *xattr; |
|---|
| 1026 | 1054 | ssize_t remaining_size = size; |
|---|
| 1027 | 1055 | int err = 0; |
|---|