Skip to content

Commit 0e22bed

Browse files
committed
Merge tag 'ovl-update-6.10' of git://git.kernel.org/pub/scm/linux/kernel/git/overlayfs/vfs
Pull overlayfs updates from Miklos Szeredi: - Add tmpfile support - Clean up include * tag 'ovl-update-6.10' of git://git.kernel.org/pub/scm/linux/kernel/git/overlayfs/vfs: ovl: remove duplicate included header ovl: remove upper umask handling from ovl_create_upper() ovl: implement tmpfile
2 parents 4f2d34b + e9229c1 commit 0e22bed

File tree

8 files changed

+165
-29
lines changed

8 files changed

+165
-29
lines changed

fs/backing-file.c

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,29 @@ struct file *backing_file_open(const struct path *user_path, int flags,
5252
}
5353
EXPORT_SYMBOL_GPL(backing_file_open);
5454

55+
struct file *backing_tmpfile_open(const struct path *user_path, int flags,
56+
const struct path *real_parentpath,
57+
umode_t mode, const struct cred *cred)
58+
{
59+
struct mnt_idmap *real_idmap = mnt_idmap(real_parentpath->mnt);
60+
struct file *f;
61+
int error;
62+
63+
f = alloc_empty_backing_file(flags, cred);
64+
if (IS_ERR(f))
65+
return f;
66+
67+
path_get(user_path);
68+
*backing_file_user_path(f) = *user_path;
69+
error = vfs_tmpfile(real_idmap, real_parentpath, f, mode);
70+
if (error) {
71+
fput(f);
72+
f = ERR_PTR(error);
73+
}
74+
return f;
75+
}
76+
EXPORT_SYMBOL(backing_tmpfile_open);
77+
5578
struct backing_aio {
5679
struct kiocb iocb;
5780
refcount_t ref;

fs/internal.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,9 @@ int do_mkdirat(int dfd, struct filename *name, umode_t mode);
6262
int do_symlinkat(struct filename *from, int newdfd, struct filename *to);
6363
int do_linkat(int olddfd, struct filename *old, int newdfd,
6464
struct filename *new, int flags);
65+
int vfs_tmpfile(struct mnt_idmap *idmap,
66+
const struct path *parentpath,
67+
struct file *file, umode_t mode);
6568

6669
/*
6770
* namespace.c

fs/namei.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3676,9 +3676,9 @@ static int do_open(struct nameidata *nd,
36763676
* On non-idmapped mounts or if permission checking is to be performed on the
36773677
* raw inode simply pass @nop_mnt_idmap.
36783678
*/
3679-
static int vfs_tmpfile(struct mnt_idmap *idmap,
3680-
const struct path *parentpath,
3681-
struct file *file, umode_t mode)
3679+
int vfs_tmpfile(struct mnt_idmap *idmap,
3680+
const struct path *parentpath,
3681+
struct file *file, umode_t mode)
36823682
{
36833683
struct dentry *child;
36843684
struct inode *dir = d_inode(parentpath->dentry);

fs/overlayfs/dir.c

Lines changed: 130 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include <linux/posix_acl_xattr.h>
1515
#include <linux/atomic.h>
1616
#include <linux/ratelimit.h>
17+
#include <linux/backing-file.h>
1718
#include "overlayfs.h"
1819

1920
static unsigned short ovl_redirect_max = 256;
@@ -260,14 +261,13 @@ static int ovl_set_opaque(struct dentry *dentry, struct dentry *upperdentry)
260261
* may not use to instantiate the new dentry.
261262
*/
262263
static int ovl_instantiate(struct dentry *dentry, struct inode *inode,
263-
struct dentry *newdentry, bool hardlink)
264+
struct dentry *newdentry, bool hardlink, struct file *tmpfile)
264265
{
265266
struct ovl_inode_params oip = {
266267
.upperdentry = newdentry,
267268
.newinode = inode,
268269
};
269270

270-
ovl_dir_modified(dentry->d_parent, false);
271271
ovl_dentry_set_upper_alias(dentry);
272272
ovl_dentry_init_reval(dentry, newdentry, NULL);
273273

@@ -295,6 +295,9 @@ static int ovl_instantiate(struct dentry *dentry, struct inode *inode,
295295
inc_nlink(inode);
296296
}
297297

298+
if (tmpfile)
299+
d_mark_tmpfile(tmpfile, inode);
300+
298301
d_instantiate(dentry, inode);
299302
if (inode != oip.newinode) {
300303
pr_warn_ratelimited("newly created inode found in cache (%pd2)\n",
@@ -327,9 +330,6 @@ static int ovl_create_upper(struct dentry *dentry, struct inode *inode,
327330
struct dentry *newdentry;
328331
int err;
329332

330-
if (!attr->hardlink && !IS_POSIXACL(udir))
331-
attr->mode &= ~current_umask();
332-
333333
inode_lock_nested(udir, I_MUTEX_PARENT);
334334
newdentry = ovl_create_real(ofs, udir,
335335
ovl_lookup_upper(ofs, dentry->d_name.name,
@@ -345,7 +345,8 @@ static int ovl_create_upper(struct dentry *dentry, struct inode *inode,
345345
ovl_set_opaque(dentry, newdentry);
346346
}
347347

348-
err = ovl_instantiate(dentry, inode, newdentry, !!attr->hardlink);
348+
ovl_dir_modified(dentry->d_parent, false);
349+
err = ovl_instantiate(dentry, inode, newdentry, !!attr->hardlink, NULL);
349350
if (err)
350351
goto out_cleanup;
351352
out_unlock:
@@ -529,7 +530,8 @@ static int ovl_create_over_whiteout(struct dentry *dentry, struct inode *inode,
529530
if (err)
530531
goto out_cleanup;
531532
}
532-
err = ovl_instantiate(dentry, inode, newdentry, hardlink);
533+
ovl_dir_modified(dentry->d_parent, false);
534+
err = ovl_instantiate(dentry, inode, newdentry, hardlink, NULL);
533535
if (err) {
534536
ovl_cleanup(ofs, udir, newdentry);
535537
dput(newdentry);
@@ -551,12 +553,35 @@ static int ovl_create_over_whiteout(struct dentry *dentry, struct inode *inode,
551553
goto out_dput;
552554
}
553555

556+
static int ovl_setup_cred_for_create(struct dentry *dentry, struct inode *inode,
557+
umode_t mode, const struct cred *old_cred)
558+
{
559+
int err;
560+
struct cred *override_cred;
561+
562+
override_cred = prepare_creds();
563+
if (!override_cred)
564+
return -ENOMEM;
565+
566+
override_cred->fsuid = inode->i_uid;
567+
override_cred->fsgid = inode->i_gid;
568+
err = security_dentry_create_files_as(dentry, mode, &dentry->d_name,
569+
old_cred, override_cred);
570+
if (err) {
571+
put_cred(override_cred);
572+
return err;
573+
}
574+
put_cred(override_creds(override_cred));
575+
put_cred(override_cred);
576+
577+
return 0;
578+
}
579+
554580
static int ovl_create_or_link(struct dentry *dentry, struct inode *inode,
555581
struct ovl_cattr *attr, bool origin)
556582
{
557583
int err;
558584
const struct cred *old_cred;
559-
struct cred *override_cred;
560585
struct dentry *parent = dentry->d_parent;
561586

562587
old_cred = ovl_override_creds(dentry->d_sb);
@@ -572,10 +597,6 @@ static int ovl_create_or_link(struct dentry *dentry, struct inode *inode,
572597
}
573598

574599
if (!attr->hardlink) {
575-
err = -ENOMEM;
576-
override_cred = prepare_creds();
577-
if (!override_cred)
578-
goto out_revert_creds;
579600
/*
580601
* In the creation cases(create, mkdir, mknod, symlink),
581602
* ovl should transfer current's fs{u,g}id to underlying
@@ -589,17 +610,9 @@ static int ovl_create_or_link(struct dentry *dentry, struct inode *inode,
589610
* create a new inode, so just use the ovl mounter's
590611
* fs{u,g}id.
591612
*/
592-
override_cred->fsuid = inode->i_uid;
593-
override_cred->fsgid = inode->i_gid;
594-
err = security_dentry_create_files_as(dentry,
595-
attr->mode, &dentry->d_name, old_cred,
596-
override_cred);
597-
if (err) {
598-
put_cred(override_cred);
613+
err = ovl_setup_cred_for_create(dentry, inode, attr->mode, old_cred);
614+
if (err)
599615
goto out_revert_creds;
600-
}
601-
put_cred(override_creds(override_cred));
602-
put_cred(override_cred);
603616
}
604617

605618
if (!ovl_dentry_is_whiteout(dentry))
@@ -1290,6 +1303,100 @@ static int ovl_rename(struct mnt_idmap *idmap, struct inode *olddir,
12901303
return err;
12911304
}
12921305

1306+
static int ovl_create_tmpfile(struct file *file, struct dentry *dentry,
1307+
struct inode *inode, umode_t mode)
1308+
{
1309+
const struct cred *old_cred;
1310+
struct path realparentpath;
1311+
struct file *realfile;
1312+
struct dentry *newdentry;
1313+
/* It's okay to set O_NOATIME, since the owner will be current fsuid */
1314+
int flags = file->f_flags | OVL_OPEN_FLAGS;
1315+
int err;
1316+
1317+
err = ovl_copy_up(dentry->d_parent);
1318+
if (err)
1319+
return err;
1320+
1321+
old_cred = ovl_override_creds(dentry->d_sb);
1322+
err = ovl_setup_cred_for_create(dentry, inode, mode, old_cred);
1323+
if (err)
1324+
goto out_revert_creds;
1325+
1326+
ovl_path_upper(dentry->d_parent, &realparentpath);
1327+
realfile = backing_tmpfile_open(&file->f_path, flags, &realparentpath,
1328+
mode, current_cred());
1329+
err = PTR_ERR_OR_ZERO(realfile);
1330+
pr_debug("tmpfile/open(%pd2, 0%o) = %i\n", realparentpath.dentry, mode, err);
1331+
if (err)
1332+
goto out_revert_creds;
1333+
1334+
/* ovl_instantiate() consumes the newdentry reference on success */
1335+
newdentry = dget(realfile->f_path.dentry);
1336+
err = ovl_instantiate(dentry, inode, newdentry, false, file);
1337+
if (!err) {
1338+
file->private_data = realfile;
1339+
} else {
1340+
dput(newdentry);
1341+
fput(realfile);
1342+
}
1343+
out_revert_creds:
1344+
revert_creds(old_cred);
1345+
return err;
1346+
}
1347+
1348+
static int ovl_dummy_open(struct inode *inode, struct file *file)
1349+
{
1350+
return 0;
1351+
}
1352+
1353+
static int ovl_tmpfile(struct mnt_idmap *idmap, struct inode *dir,
1354+
struct file *file, umode_t mode)
1355+
{
1356+
int err;
1357+
struct dentry *dentry = file->f_path.dentry;
1358+
struct inode *inode;
1359+
1360+
if (!OVL_FS(dentry->d_sb)->tmpfile)
1361+
return -EOPNOTSUPP;
1362+
1363+
err = ovl_want_write(dentry);
1364+
if (err)
1365+
return err;
1366+
1367+
err = -ENOMEM;
1368+
inode = ovl_new_inode(dentry->d_sb, mode, 0);
1369+
if (!inode)
1370+
goto drop_write;
1371+
1372+
inode_init_owner(&nop_mnt_idmap, inode, dir, mode);
1373+
err = ovl_create_tmpfile(file, dentry, inode, inode->i_mode);
1374+
if (err)
1375+
goto put_inode;
1376+
1377+
/*
1378+
* Check if the preallocated inode was actually used. Having something
1379+
* else assigned to the dentry shouldn't happen as that would indicate
1380+
* that the backing tmpfile "leaked" out of overlayfs.
1381+
*/
1382+
err = -EIO;
1383+
if (WARN_ON(inode != d_inode(dentry)))
1384+
goto put_realfile;
1385+
1386+
/* inode reference was transferred to dentry */
1387+
inode = NULL;
1388+
err = finish_open(file, dentry, ovl_dummy_open);
1389+
put_realfile:
1390+
/* Without FMODE_OPENED ->release() won't be called on @file */
1391+
if (!(file->f_mode & FMODE_OPENED))
1392+
fput(file->private_data);
1393+
put_inode:
1394+
iput(inode);
1395+
drop_write:
1396+
ovl_drop_write(dentry);
1397+
return err;
1398+
}
1399+
12931400
const struct inode_operations ovl_dir_inode_operations = {
12941401
.lookup = ovl_lookup,
12951402
.mkdir = ovl_mkdir,
@@ -1310,4 +1417,5 @@ const struct inode_operations ovl_dir_inode_operations = {
13101417
.update_time = ovl_update_time,
13111418
.fileattr_get = ovl_fileattr_get,
13121419
.fileattr_set = ovl_fileattr_set,
1420+
.tmpfile = ovl_tmpfile,
13131421
};

fs/overlayfs/file.c

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,6 @@ static char ovl_whatisit(struct inode *inode, struct inode *realinode)
2424
return 'm';
2525
}
2626

27-
/* No atime modification on underlying */
28-
#define OVL_OPEN_FLAGS (O_NOATIME)
29-
3027
static struct file *ovl_open_realfile(const struct file *file,
3128
const struct path *realpath)
3229
{

fs/overlayfs/inode.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
#include <linux/slab.h>
99
#include <linux/cred.h>
1010
#include <linux/xattr.h>
11-
#include <linux/posix_acl.h>
1211
#include <linux/ratelimit.h>
1312
#include <linux/fiemap.h>
1413
#include <linux/fileattr.h>

fs/overlayfs/overlayfs.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,9 @@ static inline int ovl_metadata_digest_size(const struct ovl_metacopy *metacopy)
175175
return (int)metacopy->len - OVL_METACOPY_MIN_SIZE;
176176
}
177177

178+
/* No atime modification on underlying */
179+
#define OVL_OPEN_FLAGS (O_NOATIME)
180+
178181
extern const char *const ovl_xattr_table[][2];
179182
static inline const char *ovl_xattr(struct ovl_fs *ofs, enum ovl_xattr ox)
180183
{

include/linux/backing-file.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@ struct backing_file_ctx {
2222
struct file *backing_file_open(const struct path *user_path, int flags,
2323
const struct path *real_path,
2424
const struct cred *cred);
25+
struct file *backing_tmpfile_open(const struct path *user_path, int flags,
26+
const struct path *real_parentpath,
27+
umode_t mode, const struct cred *cred);
2528
ssize_t backing_file_read_iter(struct file *file, struct iov_iter *iter,
2629
struct kiocb *iocb, int flags,
2730
struct backing_file_ctx *ctx);

0 commit comments

Comments
 (0)