@@ -1001,7 +1001,8 @@ static int may_linkat(struct path *link)
10011001 * may_create_in_sticky - Check whether an O_CREAT open in a sticky directory
10021002 * should be allowed, or not, on files that already
10031003 * exist.
1004- * @dir: the sticky parent directory
1004+ * @dir_mode: mode bits of directory
1005+ * @dir_uid: owner of directory
10051006 * @inode: the inode of the file to open
10061007 *
10071008 * Block an O_CREAT open of a FIFO (or a regular file) when:
@@ -1017,18 +1018,18 @@ static int may_linkat(struct path *link)
10171018 *
10181019 * Returns 0 if the open is allowed, -ve on error.
10191020 */
1020- static int may_create_in_sticky (struct dentry * const dir ,
1021+ static int may_create_in_sticky (umode_t dir_mode , kuid_t dir_uid ,
10211022 struct inode * const inode )
10221023{
10231024 if ((!sysctl_protected_fifos && S_ISFIFO (inode -> i_mode )) ||
10241025 (!sysctl_protected_regular && S_ISREG (inode -> i_mode )) ||
1025- likely (!(dir -> d_inode -> i_mode & S_ISVTX )) ||
1026- uid_eq (inode -> i_uid , dir -> d_inode -> i_uid ) ||
1026+ likely (!(dir_mode & S_ISVTX )) ||
1027+ uid_eq (inode -> i_uid , dir_uid ) ||
10271028 uid_eq (current_fsuid (), inode -> i_uid ))
10281029 return 0 ;
10291030
1030- if (likely (dir -> d_inode -> i_mode & 0002 ) ||
1031- (dir -> d_inode -> i_mode & 0020 &&
1031+ if (likely (dir_mode & 0002 ) ||
1032+ (dir_mode & 0020 &&
10321033 ((sysctl_protected_fifos >= 2 && S_ISFIFO (inode -> i_mode )) ||
10331034 (sysctl_protected_regular >= 2 && S_ISREG (inode -> i_mode ))))) {
10341035 const char * operation = S_ISFIFO (inode -> i_mode ) ?
@@ -3201,6 +3202,8 @@ static int do_last(struct nameidata *nd,
32013202 struct file * file , const struct open_flags * op )
32023203{
32033204 struct dentry * dir = nd -> path .dentry ;
3205+ kuid_t dir_uid = dir -> d_inode -> i_uid ;
3206+ umode_t dir_mode = dir -> d_inode -> i_mode ;
32043207 int open_flag = op -> open_flag ;
32053208 bool will_truncate = (open_flag & O_TRUNC ) != 0 ;
32063209 bool got_write = false;
@@ -3331,7 +3334,7 @@ static int do_last(struct nameidata *nd,
33313334 error = - EISDIR ;
33323335 if (d_is_dir (nd -> path .dentry ))
33333336 goto out ;
3334- error = may_create_in_sticky (dir ,
3337+ error = may_create_in_sticky (dir_mode , dir_uid ,
33353338 d_backing_inode (nd -> path .dentry ));
33363339 if (unlikely (error ))
33373340 goto out ;
0 commit comments