@@ -3583,44 +3583,44 @@ static int do_open(struct nameidata *nd,
3583
3583
* On non-idmapped mounts or if permission checking is to be performed on the
3584
3584
* raw inode simply passs init_user_ns.
3585
3585
*/
3586
- static struct dentry * vfs_tmpfile (struct user_namespace * mnt_userns ,
3587
- struct dentry * dentry , umode_t mode , int open_flag )
3586
+ static int vfs_tmpfile (struct user_namespace * mnt_userns ,
3587
+ const struct path * parentpath ,
3588
+ struct file * file , umode_t mode )
3588
3589
{
3589
- struct dentry * child = NULL ;
3590
- struct inode * dir = dentry -> d_inode ;
3590
+ struct dentry * child ;
3591
+ struct inode * dir = d_inode ( parentpath -> dentry ) ;
3591
3592
struct inode * inode ;
3592
3593
int error ;
3593
3594
3594
3595
/* we want directory to be writable */
3595
3596
error = inode_permission (mnt_userns , dir , MAY_WRITE | MAY_EXEC );
3596
3597
if (error )
3597
- goto out_err ;
3598
- error = - EOPNOTSUPP ;
3598
+ return error ;
3599
3599
if (!dir -> i_op -> tmpfile )
3600
- goto out_err ;
3601
- error = - ENOMEM ;
3602
- child = d_alloc (dentry , & slash_name );
3600
+ return - EOPNOTSUPP ;
3601
+ child = d_alloc (parentpath -> dentry , & slash_name );
3603
3602
if (unlikely (!child ))
3604
- goto out_err ;
3603
+ return - ENOMEM ;
3604
+ file -> f_path .mnt = parentpath -> mnt ;
3605
+ file -> f_path .dentry = child ;
3605
3606
mode = vfs_prepare_mode (mnt_userns , dir , mode , mode , mode );
3606
3607
error = dir -> i_op -> tmpfile (mnt_userns , dir , child , mode );
3608
+ error = finish_open_simple (file , error );
3609
+ dput (child );
3607
3610
if (error )
3608
- goto out_err ;
3609
- error = - ENOENT ;
3610
- inode = child -> d_inode ;
3611
- if (unlikely (!inode ))
3612
- goto out_err ;
3613
- if (!(open_flag & O_EXCL )) {
3611
+ return error ;
3612
+ /* Don't check for other permissions, the inode was just created */
3613
+ error = may_open (mnt_userns , & file -> f_path , 0 , file -> f_flags );
3614
+ if (error )
3615
+ return error ;
3616
+ inode = file_inode (file );
3617
+ if (!(file -> f_flags & O_EXCL )) {
3614
3618
spin_lock (& inode -> i_lock );
3615
3619
inode -> i_state |= I_LINKABLE ;
3616
3620
spin_unlock (& inode -> i_lock );
3617
3621
}
3618
3622
ima_post_create_tmpfile (mnt_userns , inode );
3619
- return child ;
3620
-
3621
- out_err :
3622
- dput (child );
3623
- return ERR_PTR (error );
3623
+ return 0 ;
3624
3624
}
3625
3625
3626
3626
/**
@@ -3641,25 +3641,15 @@ struct file *vfs_tmpfile_open(struct user_namespace *mnt_userns,
3641
3641
{
3642
3642
struct file * file ;
3643
3643
int error ;
3644
- struct path path = { .mnt = parentpath -> mnt };
3645
-
3646
- path .dentry = vfs_tmpfile (mnt_userns , parentpath -> dentry , mode , open_flag );
3647
- if (IS_ERR (path .dentry ))
3648
- return ERR_CAST (path .dentry );
3649
-
3650
- error = may_open (mnt_userns , & path , 0 , open_flag );
3651
- file = ERR_PTR (error );
3652
- if (error )
3653
- goto out_dput ;
3654
-
3655
- /*
3656
- * This relies on the "noaccount" property of fake open, otherwise
3657
- * equivalent to dentry_open().
3658
- */
3659
- file = open_with_fake_path (& path , open_flag , d_inode (path .dentry ), cred );
3660
- out_dput :
3661
- dput (path .dentry );
3662
3644
3645
+ file = alloc_empty_file_noaccount (open_flag , cred );
3646
+ if (!IS_ERR (file )) {
3647
+ error = vfs_tmpfile (mnt_userns , parentpath , file , mode );
3648
+ if (error ) {
3649
+ fput (file );
3650
+ file = ERR_PTR (error );
3651
+ }
3652
+ }
3663
3653
return file ;
3664
3654
}
3665
3655
EXPORT_SYMBOL (vfs_tmpfile_open );
@@ -3669,26 +3659,19 @@ static int do_tmpfile(struct nameidata *nd, unsigned flags,
3669
3659
struct file * file )
3670
3660
{
3671
3661
struct user_namespace * mnt_userns ;
3672
- struct dentry * child ;
3673
3662
struct path path ;
3674
3663
int error = path_lookupat (nd , flags | LOOKUP_DIRECTORY , & path );
3664
+
3675
3665
if (unlikely (error ))
3676
3666
return error ;
3677
3667
error = mnt_want_write (path .mnt );
3678
3668
if (unlikely (error ))
3679
3669
goto out ;
3680
3670
mnt_userns = mnt_user_ns (path .mnt );
3681
- child = vfs_tmpfile (mnt_userns , path .dentry , op -> mode , op -> open_flag );
3682
- error = PTR_ERR (child );
3683
- if (IS_ERR (child ))
3671
+ error = vfs_tmpfile (mnt_userns , & path , file , op -> mode );
3672
+ if (error )
3684
3673
goto out2 ;
3685
- dput (path .dentry );
3686
- path .dentry = child ;
3687
- audit_inode (nd -> name , child , 0 );
3688
- /* Don't check for other permissions, the inode was just created */
3689
- error = may_open (mnt_userns , & path , 0 , op -> open_flag );
3690
- if (!error )
3691
- error = vfs_open (& path , file );
3674
+ audit_inode (nd -> name , file -> f_path .dentry , 0 );
3692
3675
out2 :
3693
3676
mnt_drop_write (path .mnt );
3694
3677
out :
0 commit comments