fs/xattr.c

Source file repositories/reference/linux-study-clean/fs/xattr.c

File Facts

System
Linux kernel
Corpus path
fs/xattr.c
Extension
.c
Size
46690 bytes
Lines
1762
Domain
Core OS
Bucket
VFS And Filesystem Core
Inferred role
Core OS: syscall or user/kernel boundary
Status
core implementation candidate

Why This File Exists

Core operating-system implementation surface: boot, tasks, memory, VFS, syscall-facing interfaces, synchronization, credentials, and isolation.

Dependency Surface

Detected Declarations

Annotated Snippet

SYSCALL_DEFINE6(setxattrat, int, dfd, const char __user *, pathname, unsigned int, at_flags,
		const char __user *, name, const struct xattr_args __user *, uargs,
		size_t, usize)
{
	struct xattr_args args = {};
	int error;

	BUILD_BUG_ON(sizeof(struct xattr_args) < XATTR_ARGS_SIZE_VER0);
	BUILD_BUG_ON(sizeof(struct xattr_args) != XATTR_ARGS_SIZE_LATEST);

	if (unlikely(usize < XATTR_ARGS_SIZE_VER0))
		return -EINVAL;
	if (usize > PAGE_SIZE)
		return -E2BIG;

	error = copy_struct_from_user(&args, sizeof(args), uargs, usize);
	if (error)
		return error;

	return path_setxattrat(dfd, pathname, at_flags, name,
			       u64_to_user_ptr(args.value), args.size,
			       args.flags);
}

SYSCALL_DEFINE5(setxattr, const char __user *, pathname,
		const char __user *, name, const void __user *, value,
		size_t, size, int, flags)
{
	return path_setxattrat(AT_FDCWD, pathname, 0, name, value, size, flags);
}

SYSCALL_DEFINE5(lsetxattr, const char __user *, pathname,
		const char __user *, name, const void __user *, value,
		size_t, size, int, flags)
{
	return path_setxattrat(AT_FDCWD, pathname, AT_SYMLINK_NOFOLLOW, name,
			       value, size, flags);
}

SYSCALL_DEFINE5(fsetxattr, int, fd, const char __user *, name,
		const void __user *,value, size_t, size, int, flags)
{
	return path_setxattrat(fd, NULL, AT_EMPTY_PATH, name,
			       value, size, flags);
}

/*
 * Extended attribute GET operations
 */
static ssize_t
do_getxattr(struct mnt_idmap *idmap, struct dentry *d,
	struct kernel_xattr_ctx *ctx)
{
	ssize_t error;
	char *kname = ctx->kname->name;
	void *kvalue = NULL;

	if (ctx->size) {
		if (ctx->size > XATTR_SIZE_MAX)
			ctx->size = XATTR_SIZE_MAX;
		kvalue = kvzalloc(ctx->size, GFP_KERNEL);
		if (!kvalue)
			return -ENOMEM;
	}

	if (is_posix_acl_xattr(kname))
		error = do_get_acl(idmap, d, kname, kvalue, ctx->size);
	else
		error = vfs_getxattr(idmap, d, kname, kvalue, ctx->size);
	if (error > 0) {
		if (ctx->size && copy_to_user(ctx->value, kvalue, error))
			error = -EFAULT;
	} else if (error == -ERANGE && ctx->size >= XATTR_SIZE_MAX) {
		/* The file system tried to returned a value bigger
		   than XATTR_SIZE_MAX bytes. Not possible. */
		error = -E2BIG;
	}

	kvfree(kvalue);
	return error;
}

ssize_t file_getxattr(struct file *f, struct kernel_xattr_ctx *ctx)
{
	audit_file(f);
	return do_getxattr(file_mnt_idmap(f), f->f_path.dentry, ctx);
}

ssize_t filename_getxattr(int dfd, struct filename *filename,
			  unsigned int lookup_flags, struct kernel_xattr_ctx *ctx)

Annotation

Implementation Notes