fs/overlayfs/namei.c

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

File Facts

System
Linux kernel
Corpus path
fs/overlayfs/namei.c
Extension
.c
Size
36799 bytes
Lines
1484
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

struct ovl_lookup_data {
	struct super_block *sb;
	struct dentry *dentry;
	const struct ovl_layer *layer;
	struct qstr name;
	bool is_dir;
	bool opaque;
	bool xwhiteouts;
	bool stop;
	bool last;
	char *redirect;
	char *upperredirect;
	int metacopy;
	/* Referring to last redirect xattr */
	bool absolute_redirect;
};

static int ovl_check_redirect(const struct path *path, struct ovl_lookup_data *d,
			      size_t prelen, const char *post)
{
	int res;
	char *buf;
	struct ovl_fs *ofs = OVL_FS(d->sb);

	d->absolute_redirect = false;
	buf = ovl_get_redirect_xattr(ofs, path, prelen + strlen(post));
	if (IS_ERR_OR_NULL(buf))
		return PTR_ERR(buf);

	if (buf[0] == '/') {
		d->absolute_redirect = true;
		/*
		 * One of the ancestor path elements in an absolute path
		 * lookup in ovl_lookup_layer() could have been opaque and
		 * that will stop further lookup in lower layers (d->stop=true)
		 * But we have found an absolute redirect in descendant path
		 * element and that should force continue lookup in lower
		 * layers (reset d->stop).
		 */
		d->stop = false;
	} else {
		res = strlen(buf) + 1;
		memmove(buf + prelen, buf, res);
		memcpy(buf, d->name.name, prelen);
	}

	strcat(buf, post);
	kfree(d->redirect);
	d->redirect = buf;
	d->name.name = d->redirect;
	d->name.len = strlen(d->redirect);

	return 0;
}

static int ovl_acceptable(void *ctx, struct dentry *dentry)
{
	/*
	 * A non-dir origin may be disconnected, which is fine, because
	 * we only need it for its unique inode number.
	 */
	if (!d_is_dir(dentry))
		return 1;

	/* Don't decode a deleted empty directory */
	if (d_unhashed(dentry))
		return 0;

	/* Check if directory belongs to the layer we are decoding from */
	return is_subdir(dentry, ((struct vfsmount *)ctx)->mnt_root);
}

/*
 * Check validity of an overlay file handle buffer.
 *
 * Return 0 for a valid file handle.
 * Return -ENODATA for "origin unknown".
 * Return <0 for an invalid file handle.
 */
int ovl_check_fb_len(struct ovl_fb *fb, int fb_len)
{
	if (fb_len < sizeof(struct ovl_fb) || fb_len < fb->len)
		return -EINVAL;

	if (fb->magic != OVL_FH_MAGIC)
		return -EINVAL;

	/* Treat larger version and unknown flags as "origin unknown" */
	if (fb->version > OVL_FH_VERSION || fb->flags & ~OVL_FH_FLAG_ALL)
		return -ENODATA;

Annotation

Implementation Notes