Skip to content

Commit 88083e9

Browse files
committed
Merge branch 'overlayfs-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/vfs
Pull overlayfs fixes from Miklos Szeredi: "This contains a fix for a potential crash/corruption issue and another where the suid/sgid bits weren't cleared on write" * 'overlayfs-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/vfs: ovl: verify upper dentry in ovl_remove_and_whiteout() ovl: Copy up underlying inode's ->i_mode to overlay inode ovl: handle ATTR_KILL*
2 parents b1386ce + cfc9fde commit 88083e9

File tree

3 files changed

+29
-32
lines changed

3 files changed

+29
-32
lines changed

fs/overlayfs/dir.c

Lines changed: 24 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -505,6 +505,7 @@ static int ovl_remove_and_whiteout(struct dentry *dentry, bool is_dir)
505505
struct dentry *upper;
506506
struct dentry *opaquedir = NULL;
507507
int err;
508+
int flags = 0;
508509

509510
if (WARN_ON(!workdir))
510511
return -EROFS;
@@ -534,46 +535,39 @@ static int ovl_remove_and_whiteout(struct dentry *dentry, bool is_dir)
534535
if (err)
535536
goto out_dput;
536537

537-
whiteout = ovl_whiteout(workdir, dentry);
538-
err = PTR_ERR(whiteout);
539-
if (IS_ERR(whiteout))
538+
upper = lookup_one_len(dentry->d_name.name, upperdir,
539+
dentry->d_name.len);
540+
err = PTR_ERR(upper);
541+
if (IS_ERR(upper))
540542
goto out_unlock;
541543

542-
upper = ovl_dentry_upper(dentry);
543-
if (!upper) {
544-
upper = lookup_one_len(dentry->d_name.name, upperdir,
545-
dentry->d_name.len);
546-
err = PTR_ERR(upper);
547-
if (IS_ERR(upper))
548-
goto kill_whiteout;
549-
550-
err = ovl_do_rename(wdir, whiteout, udir, upper, 0);
551-
dput(upper);
552-
if (err)
553-
goto kill_whiteout;
554-
} else {
555-
int flags = 0;
544+
err = -ESTALE;
545+
if ((opaquedir && upper != opaquedir) ||
546+
(!opaquedir && ovl_dentry_upper(dentry) &&
547+
upper != ovl_dentry_upper(dentry))) {
548+
goto out_dput_upper;
549+
}
556550

557-
if (opaquedir)
558-
upper = opaquedir;
559-
err = -ESTALE;
560-
if (upper->d_parent != upperdir)
561-
goto kill_whiteout;
551+
whiteout = ovl_whiteout(workdir, dentry);
552+
err = PTR_ERR(whiteout);
553+
if (IS_ERR(whiteout))
554+
goto out_dput_upper;
562555

563-
if (is_dir)
564-
flags |= RENAME_EXCHANGE;
556+
if (d_is_dir(upper))
557+
flags = RENAME_EXCHANGE;
565558

566-
err = ovl_do_rename(wdir, whiteout, udir, upper, flags);
567-
if (err)
568-
goto kill_whiteout;
559+
err = ovl_do_rename(wdir, whiteout, udir, upper, flags);
560+
if (err)
561+
goto kill_whiteout;
562+
if (flags)
563+
ovl_cleanup(wdir, upper);
569564

570-
if (is_dir)
571-
ovl_cleanup(wdir, upper);
572-
}
573565
ovl_dentry_version_inc(dentry->d_parent);
574566
out_d_drop:
575567
d_drop(dentry);
576568
dput(whiteout);
569+
out_dput_upper:
570+
dput(upper);
577571
out_unlock:
578572
unlock_rename(workdir, upperdir);
579573
out_dput:

fs/overlayfs/inode.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,9 @@ int ovl_setattr(struct dentry *dentry, struct iattr *attr)
8080
goto out_drop_write;
8181
}
8282

83+
if (attr->ia_valid & (ATTR_KILL_SUID|ATTR_KILL_SGID))
84+
attr->ia_valid &= ~ATTR_MODE;
85+
8386
inode_lock(upperdentry->d_inode);
8487
err = notify_change(upperdentry, attr, NULL);
8588
if (!err)
@@ -410,12 +413,11 @@ struct inode *ovl_new_inode(struct super_block *sb, umode_t mode,
410413
if (!inode)
411414
return NULL;
412415

413-
mode &= S_IFMT;
414-
415416
inode->i_ino = get_next_ino();
416417
inode->i_mode = mode;
417418
inode->i_flags |= S_NOATIME | S_NOCMTIME;
418419

420+
mode &= S_IFMT;
419421
switch (mode) {
420422
case S_IFDIR:
421423
inode->i_private = oe;

fs/overlayfs/overlayfs.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,7 @@ static inline void ovl_copyattr(struct inode *from, struct inode *to)
187187
{
188188
to->i_uid = from->i_uid;
189189
to->i_gid = from->i_gid;
190+
to->i_mode = from->i_mode;
190191
}
191192

192193
/* dir.c */

0 commit comments

Comments
 (0)