4837 Total CVEs
26 Years
GitHub
README.md
Rendering markdown...
POC / diff.patch PATCH
15c15,16
< static int ovl_copy_up_truncate(struct dentry *dentry)
---
> static int ovl_copy_up_last(struct dentry *dentry, struct iattr *attr,
> 			    bool no_data)
32,33c33,36
< 	stat.size = 0;
< 	err = ovl_copy_up_one(parent, dentry, &lowerpath, &stat);
---
> 	if (no_data)
> 		stat.size = 0;
> 
> 	err = ovl_copy_up_one(parent, dentry, &lowerpath, &stat, attr);
45,57d47
< 	/*
< 	 * 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;
< 
62,66c52,54
< 	err = ovl_copy_up(dentry);
< 	if (!err) {
< 		upperdentry = ovl_dentry_upper(dentry);
< 
< 		inode_lock(upperdentry->d_inode);
---
> 	upperdentry = ovl_dentry_upper(dentry);
> 	if (upperdentry) {
> 		mutex_lock(&upperdentry->d_inode->i_mutex);
68,70c56,58
< 		if (!err)
< 			ovl_copyattr(upperdentry->d_inode, dentry->d_inode);
< 		inode_unlock(upperdentry->d_inode);
---
> 		mutex_unlock(&upperdentry->d_inode->i_mutex);
> 	} else {
> 		err = ovl_copy_up_last(dentry, attr, false);
113,135d100
< 	if (ovl_is_default_permissions(inode)) {
< 		struct kstat stat;
< 		struct path realpath = { .dentry = realdentry };
< 
< 		if (mask & MAY_NOT_BLOCK)
< 			return -ECHILD;
< 
< 		realpath.mnt = ovl_entry_mnt_real(oe, inode, is_upper);
< 
< 		err = vfs_getattr(&realpath, &stat);
< 		if (err)
< 			return err;
< 
< 		if ((stat.mode ^ inode->i_mode) & S_IFMT)
< 			return -ESTALE;
< 
< 		inode->i_mode = stat.mode;
< 		inode->i_uid = stat.uid;
< 		inode->i_gid = stat.gid;
< 
< 		return generic_permission(inode, mask);
< 	}
< 
172,174c137,143
< static const char *ovl_get_link(struct dentry *dentry,
< 				struct inode *inode,
< 				struct delayed_call *done)
---
> 
> struct ovl_link_data {
> 	struct dentry *realdentry;
> 	void *cookie;
> };
> 
> static void *ovl_follow_link(struct dentry *dentry, struct nameidata *nd)
175a145
> 	void *ret;
179,181d148
< 	if (!dentry)
< 		return ERR_PTR(-ECHILD);
< 
185c152
< 	if (WARN_ON(!realinode->i_op->get_link))
---
> 	if (WARN_ON(!realinode->i_op->follow_link))
188c155,186
< 	return realinode->i_op->get_link(realdentry, realinode, done);
---
> 	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;
> 	}
> }
> 
> static void ovl_put_link(struct dentry *dentry, struct nameidata *nd, void *c)
> {
> 	struct inode *realinode;
> 	struct ovl_link_data *data = c;
> 
> 	if (!data)
> 		return;
> 
> 	realinode = data->realdentry->d_inode;
> 	realinode->i_op->put_link(data->realdentry, nd, data->cookie);
> 	kfree(data);
210c208
< 	return strncmp(name, OVL_XATTR_PRE_NAME, OVL_XATTR_PRE_LEN) == 0;
---
> 	return strncmp(name, "trusted.overlay.", 14) == 0;
243,246c241
< 	if ((type & (__OVL_PATH_PURE | __OVL_PATH_UPPER)) == __OVL_PATH_UPPER)
< 		return S_ISDIR(dentry->d_inode->i_mode);
< 	else
< 		return false;
---
> 	return type == OVL_PATH_UPPER && S_ISDIR(dentry->d_inode->i_mode);
307c302
< 	if (!OVL_TYPE_UPPER(type)) {
---
> 	if (type == OVL_PATH_LOWER) {
329c324
< 	if (OVL_TYPE_UPPER(type))
---
> 	if (type != OVL_PATH_LOWER)
341c336,337
< struct inode *ovl_d_select_inode(struct dentry *dentry, unsigned file_flags)
---
> static int ovl_dentry_open(struct dentry *dentry, struct file *file,
> 		    const struct cred *cred)
346,348c342
< 
< 	if (d_is_dir(dentry))
< 		return d_backing_inode(dentry);
---
> 	bool want_write = false;
351c345,346
< 	if (ovl_open_need_copy_up(file_flags, type, realpath.dentry)) {
---
> 	if (ovl_open_need_copy_up(file->f_flags, type, realpath.dentry)) {
> 		want_write = true;
354c349
< 			return ERR_PTR(err);
---
> 			goto out;
356,357c351,352
< 		if (file_flags & O_TRUNC)
< 			err = ovl_copy_up_truncate(dentry);
---
> 		if (file->f_flags & O_TRUNC)
> 			err = ovl_copy_up_last(dentry, NULL, true);
360d354
< 		ovl_drop_write(dentry);
362c356
< 			return ERR_PTR(err);
---
> 			goto out_drop_write;
367,370c361,366
< 	if (realpath.dentry->d_flags & DCACHE_OP_SELECT_INODE)
< 		return realpath.dentry->d_op->d_select_inode(realpath.dentry, file_flags);
< 
< 	return d_backing_inode(realpath.dentry);
---
> 	err = vfs_open(&realpath, file, cred);
> out_drop_write:
> 	if (want_write)
> 		ovl_drop_write(dentry);
> out:
> 	return err;
380a377
> 	.dentry_open	= ovl_dentry_open,
385c382,383
< 	.get_link	= ovl_get_link,
---
> 	.follow_link	= ovl_follow_link,
> 	.put_link	= ovl_put_link,
434a433
>