@@ -505,6 +505,8 @@ struct nameidata {
505
505
struct nameidata * saved ;
506
506
unsigned root_seq ;
507
507
int dfd ;
508
+ kuid_t dir_uid ;
509
+ umode_t dir_mode ;
508
510
} __randomize_layout ;
509
511
510
512
static void set_nameidata (struct nameidata * p , int dfd , struct filename * name )
@@ -938,9 +940,6 @@ int sysctl_protected_regular __read_mostly;
938
940
*/
939
941
static inline int may_follow_link (struct nameidata * nd , const struct inode * inode )
940
942
{
941
- const struct inode * parent ;
942
- kuid_t puid ;
943
-
944
943
if (!sysctl_protected_symlinks )
945
944
return 0 ;
946
945
@@ -949,13 +948,11 @@ static inline int may_follow_link(struct nameidata *nd, const struct inode *inod
949
948
return 0 ;
950
949
951
950
/* Allowed if parent directory not sticky and world-writable. */
952
- parent = nd -> inode ;
953
- if ((parent -> i_mode & (S_ISVTX |S_IWOTH )) != (S_ISVTX |S_IWOTH ))
951
+ if ((nd -> dir_mode & (S_ISVTX |S_IWOTH )) != (S_ISVTX |S_IWOTH ))
954
952
return 0 ;
955
953
956
954
/* Allowed if parent directory and link owner match. */
957
- puid = parent -> i_uid ;
958
- if (uid_valid (puid ) && uid_eq (puid , inode -> i_uid ))
955
+ if (uid_valid (nd -> dir_uid ) && uid_eq (nd -> dir_uid , inode -> i_uid ))
959
956
return 0 ;
960
957
961
958
if (nd -> flags & LOOKUP_RCU )
@@ -2159,6 +2156,8 @@ static int link_path_walk(const char *name, struct nameidata *nd)
2159
2156
OK :
2160
2157
/* pathname or trailing symlink, done */
2161
2158
if (!depth ) {
2159
+ nd -> dir_uid = nd -> inode -> i_uid ;
2160
+ nd -> dir_mode = nd -> inode -> i_mode ;
2162
2161
nd -> flags &= ~LOOKUP_PARENT ;
2163
2162
return 0 ;
2164
2163
}
@@ -3224,8 +3223,6 @@ static const char *open_last_lookups(struct nameidata *nd,
3224
3223
static const char * do_last (struct nameidata * nd ,
3225
3224
struct file * file , const struct open_flags * op )
3226
3225
{
3227
- kuid_t dir_uid = nd -> inode -> i_uid ;
3228
- umode_t dir_mode = nd -> inode -> i_mode ;
3229
3226
int open_flag = op -> open_flag ;
3230
3227
bool do_truncate ;
3231
3228
int acc_mode ;
@@ -3241,7 +3238,7 @@ static const char *do_last(struct nameidata *nd,
3241
3238
if (open_flag & O_CREAT ) {
3242
3239
if (d_is_dir (nd -> path .dentry ))
3243
3240
return ERR_PTR (- EISDIR );
3244
- error = may_create_in_sticky (dir_mode , dir_uid ,
3241
+ error = may_create_in_sticky (nd -> dir_mode , nd -> dir_uid ,
3245
3242
d_backing_inode (nd -> path .dentry ));
3246
3243
if (unlikely (error ))
3247
3244
return ERR_PTR (error );
0 commit comments