fs/overlayfs/xattrs.c

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

File Facts

System
Linux kernel
Corpus path
fs/overlayfs/xattrs.c
Extension
.c
Size
6707 bytes
Lines
262
Domain
Core OS
Bucket
VFS And Filesystem Core
Inferred role
Core OS: implementation source
Status
source 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

if (value) {
			err = ovl_do_setxattr(ofs, realdentry, name, value, size, flags);
		} else {
			WARN_ON(flags != XATTR_REPLACE);
			err = ovl_do_removexattr(ofs, realdentry, name);
		}
	}
	ovl_drop_write(dentry);

	/* copy c/mtime */
	ovl_copyattr(inode);
out:
	return err;
}

static int ovl_xattr_get(struct dentry *dentry, struct inode *inode, const char *name,
			 void *value, size_t size)
{
	struct path realpath;

	ovl_i_path_real(inode, &realpath);
	with_ovl_creds(dentry->d_sb)
		return vfs_getxattr(mnt_idmap(realpath.mnt), realpath.dentry, name, value, size);
}

static bool ovl_can_list(struct super_block *sb, const char *s)
{
	/* Never list private (.overlay) */
	if (ovl_is_private_xattr(sb, s))
		return false;

	/* List all non-trusted xattrs */
	if (strncmp(s, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN) != 0)
		return true;

	/* list other trusted for superuser only */
	return ns_capable_noaudit(&init_user_ns, CAP_SYS_ADMIN);
}

ssize_t ovl_listxattr(struct dentry *dentry, char *list, size_t size)
{
	struct dentry *realdentry = ovl_dentry_real(dentry);
	struct ovl_fs *ofs = OVL_FS(dentry->d_sb);
	ssize_t res;
	size_t len;
	char *s;
	size_t prefix_len, name_len;

	with_ovl_creds(dentry->d_sb)
		res = vfs_listxattr(realdentry, list, size);
	if (res <= 0 || size == 0)
		return res;

	prefix_len = ofs->config.userxattr ?
		OVL_XATTR_USER_PREFIX_LEN : OVL_XATTR_TRUSTED_PREFIX_LEN;

	/* filter out private xattrs */
	for (s = list, len = res; len;) {
		size_t slen = strnlen(s, len) + 1;

		/* underlying fs providing us with an broken xattr list? */
		if (WARN_ON(slen > len))
			return -EIO;

		len -= slen;
		if (!ovl_can_list(dentry->d_sb, s)) {
			res -= slen;
			memmove(s, s + slen, len);
		} else if (ovl_is_escaped_xattr(dentry->d_sb, s)) {
			res -= OVL_XATTR_ESCAPE_PREFIX_LEN;
			name_len = slen - prefix_len - OVL_XATTR_ESCAPE_PREFIX_LEN;
			s += prefix_len;
			memmove(s, s + OVL_XATTR_ESCAPE_PREFIX_LEN, name_len + len);
			s += name_len;
		} else {
			s += slen;
		}
	}

	return res;
}

static char *ovl_xattr_escape_name(const char *prefix, const char *name)
{
	size_t prefix_len = strlen(prefix);
	size_t name_len = strlen(name);
	size_t escaped_len;
	char *escaped, *s;

	escaped_len = prefix_len + OVL_XATTR_ESCAPE_PREFIX_LEN + name_len;

Annotation

Implementation Notes