Esempio n. 1
0
ssize_t ovl_listxattr(struct dentry *dentry, char *list, size_t size)
{
	ssize_t res;
	int off;

	res = vfs_listxattr(ovl_dentry_real(dentry), list, size);
	if (res <= 0 || size == 0)
		return res;

	if (ovl_path_type(dentry->d_parent) != OVL_PATH_MERGE)
		return res;

	/* filter out private xattrs */
	for (off = 0; off < res;) {
		char *s = list + off;
		size_t slen = strlen(s) + 1;

		BUG_ON(off + slen > res);

		if (ovl_is_private_xattr(s)) {
			res -= slen;
			memmove(s, s + slen, res - off);
		} else {
			off += slen;
		}
	}

	return res;
}
Esempio n. 2
0
static void *ovl_follow_link(struct dentry *dentry, struct nameidata *nd)
{
	void *ret;
	struct dentry *realdentry;
	struct inode *realinode;

	realdentry = ovl_dentry_real(dentry);
	realinode = realdentry->d_inode;

	if (WARN_ON(!realinode->i_op->follow_link))
		return ERR_PTR(-EPERM);

	ret = realinode->i_op->follow_link(realdentry, nd);
	if (IS_ERR(ret))
		return ret;

	if (realinode->i_op->put_link) {
		struct ovl_link_data *data;

		data = kmalloc(sizeof(struct ovl_link_data), GFP_KERNEL);
		if (!data) {
			realinode->i_op->put_link(realdentry, nd, ret);
			return ERR_PTR(-ENOMEM);
		}
		data->realdentry = realdentry;
		data->cookie = ret;

		return data;
	} else {
		return NULL;
	}
}
Esempio n. 3
0
ssize_t ovl_listxattr(struct dentry *dentry, char *list, size_t size)
{
	struct dentry *realdentry = ovl_dentry_real(dentry);
	ssize_t res;
	size_t len;
	char *s;
	const struct cred *old_cred;

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

	/* 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(s)) {
			res -= slen;
			memmove(s, s + slen, len);
		} else {
			s += slen;
		}
	}

	return res;
}
Esempio n. 4
0
static const char *ovl_follow_link(struct dentry *dentry, void **cookie)
{
	struct dentry *realdentry;
	struct inode *realinode;
	struct ovl_link_data *data = NULL;
	const char *ret;

	realdentry = ovl_dentry_real(dentry);
	realinode = realdentry->d_inode;

	if (WARN_ON(!realinode->i_op->follow_link))
		return ERR_PTR(-EPERM);

	if (realinode->i_op->put_link) {
		data = kmalloc(sizeof(struct ovl_link_data), GFP_KERNEL);
		if (!data)
			return ERR_PTR(-ENOMEM);
		data->realdentry = realdentry;
	}

	ret = realinode->i_op->follow_link(realdentry, cookie);
	if (IS_ERR_OR_NULL(ret)) {
		kfree(data);
		return ret;
	}

	if (data)
		data->cookie = *cookie;

	*cookie = data;

	return ret;
}
Esempio n. 5
0
ssize_t ovl_getxattr(struct dentry *dentry, const char *name,
		     void *value, size_t size)
{
	if (ovl_path_type(dentry->d_parent) == OVL_PATH_MERGE &&
	    ovl_is_private_xattr(name))
		return -ENODATA;

	return vfs_getxattr(ovl_dentry_real(dentry), name, value, size);
}
Esempio n. 6
0
int ovl_setattr(struct dentry *dentry, struct iattr *attr)
{
	int err;
	struct dentry *upperdentry;

	/*
	 * Check for permissions before trying to copy-up.  This is redundant
	 * since it will be rechecked later by ->setattr() on upper dentry.  But
	 * without this, copy-up can be triggered by just about anybody.
	 *
	 * We don't initialize inode->size, which just means that
	 * inode_newsize_ok() will always check against MAX_LFS_FILESIZE and not
	 * check for a swapfile (which this won't be anyway).
	 */
	err = inode_change_ok(dentry->d_inode, attr);
	if (err)
		return err;

	err = ovl_want_write(dentry);
	if (err)
		goto out;

	if (attr->ia_valid & ATTR_SIZE) {
		struct inode *realinode = d_inode(ovl_dentry_real(dentry));

		err = -ETXTBSY;
		if (atomic_read(&realinode->i_writecount) < 0)
			goto out_drop_write;
	}

	err = ovl_copy_up(dentry);
	if (!err) {
		struct inode *winode = NULL;

		upperdentry = ovl_dentry_upper(dentry);

		if (attr->ia_valid & ATTR_SIZE) {
			winode = d_inode(upperdentry);
			err = get_write_access(winode);
			if (err)
				goto out_drop_write;
		}

		inode_lock(upperdentry->d_inode);
		err = notify_change(upperdentry, attr, NULL);
		if (!err)
			ovl_copyattr(upperdentry->d_inode, dentry->d_inode);
		inode_unlock(upperdentry->d_inode);

		if (winode)
			put_write_access(winode);
	}
out_drop_write:
	ovl_drop_write(dentry);
out:
	return err;
}
Esempio n. 7
0
ssize_t ovl_getxattr(struct dentry *dentry, struct inode *inode,
		     const char *name, void *value, size_t size)
{
	struct dentry *realdentry = ovl_dentry_real(dentry);

	if (ovl_is_private_xattr(name))
		return -ENODATA;

	return vfs_getxattr(realdentry, name, value, size);
}
Esempio n. 8
0
int ovl_xattr_get(struct dentry *dentry, const char *name,
		  void *value, size_t size)
{
	struct dentry *realdentry = ovl_dentry_real(dentry);
	ssize_t res;
	const struct cred *old_cred;

	old_cred = ovl_override_creds(dentry->d_sb);
	res = vfs_getxattr(realdentry, name, value, size);
	revert_creds(old_cred);
	return res;
}
Esempio n. 9
0
static const char *ovl_get_link(struct dentry *dentry,
				struct inode *inode,
				struct delayed_call *done)
{
	const struct cred *old_cred;
	const char *p;

	if (!dentry)
		return ERR_PTR(-ECHILD);

	old_cred = ovl_override_creds(dentry->d_sb);
	p = vfs_get_link(ovl_dentry_real(dentry), done);
	revert_creds(old_cred);
	return p;
}
Esempio n. 10
0
static const char *ovl_get_link(struct dentry *dentry,
				struct inode *inode,
				struct delayed_call *done)
{
	struct dentry *realdentry;
	struct inode *realinode;

	if (!dentry)
		return ERR_PTR(-ECHILD);

	realdentry = ovl_dentry_real(dentry);
	realinode = realdentry->d_inode;

	if (WARN_ON(!realinode->i_op->get_link))
		return ERR_PTR(-EPERM);

	return realinode->i_op->get_link(realdentry, realinode, done);
}