@@ -878,6 +878,10 @@ static int ntfs_resident_writepage(struct folio *folio,
878878 struct ntfs_inode * ni = ntfs_i (inode );
879879 int ret ;
880880
881+ /* Avoid any operation if inode is bad. */
882+ if (unlikely (is_bad_ni (ni )))
883+ return - EINVAL ;
884+
881885 if (unlikely (ntfs3_forced_shutdown (inode -> i_sb )))
882886 return - EIO ;
883887
@@ -896,6 +900,10 @@ static int ntfs_writepages(struct address_space *mapping,
896900{
897901 struct inode * inode = mapping -> host ;
898902
903+ /* Avoid any operation if inode is bad. */
904+ if (unlikely (is_bad_ni (ntfs_i (inode ))))
905+ return - EINVAL ;
906+
899907 if (unlikely (ntfs3_forced_shutdown (inode -> i_sb )))
900908 return - EIO ;
901909
@@ -919,6 +927,10 @@ int ntfs_write_begin(struct file *file, struct address_space *mapping,
919927 struct inode * inode = mapping -> host ;
920928 struct ntfs_inode * ni = ntfs_i (inode );
921929
930+ /* Avoid any operation if inode is bad. */
931+ if (unlikely (is_bad_ni (ni )))
932+ return - EINVAL ;
933+
922934 if (unlikely (ntfs3_forced_shutdown (inode -> i_sb )))
923935 return - EIO ;
924936
@@ -1062,10 +1074,10 @@ int inode_read_data(struct inode *inode, void *data, size_t bytes)
10621074 * Number of bytes for REPARSE_DATA_BUFFER(IO_REPARSE_TAG_SYMLINK)
10631075 * for unicode string of @uni_len length.
10641076 */
1065- static inline u32 ntfs_reparse_bytes (u32 uni_len )
1077+ static inline u32 ntfs_reparse_bytes (u32 uni_len , bool is_absolute )
10661078{
10671079 /* Header + unicode string + decorated unicode string. */
1068- return sizeof (short ) * (2 * uni_len + 4 ) +
1080+ return sizeof (short ) * (2 * uni_len + ( is_absolute ? 4 : 0 ) ) +
10691081 offsetof(struct REPARSE_DATA_BUFFER ,
10701082 SymbolicLinkReparseBuffer .PathBuffer );
10711083}
@@ -1078,8 +1090,11 @@ ntfs_create_reparse_buffer(struct ntfs_sb_info *sbi, const char *symname,
10781090 struct REPARSE_DATA_BUFFER * rp ;
10791091 __le16 * rp_name ;
10801092 typeof (rp -> SymbolicLinkReparseBuffer ) * rs ;
1093+ bool is_absolute ;
10811094
1082- rp = kzalloc (ntfs_reparse_bytes (2 * size + 2 ), GFP_NOFS );
1095+ is_absolute = (strlen (symname ) > 1 && symname [1 ] == ':' );
1096+
1097+ rp = kzalloc (ntfs_reparse_bytes (2 * size + 2 , is_absolute ), GFP_NOFS );
10831098 if (!rp )
10841099 return ERR_PTR (- ENOMEM );
10851100
@@ -1094,7 +1109,7 @@ ntfs_create_reparse_buffer(struct ntfs_sb_info *sbi, const char *symname,
10941109 goto out ;
10951110
10961111 /* err = the length of unicode name of symlink. */
1097- * nsize = ntfs_reparse_bytes (err );
1112+ * nsize = ntfs_reparse_bytes (err , is_absolute );
10981113
10991114 if (* nsize > sbi -> reparse .max_size ) {
11001115 err = - EFBIG ;
@@ -1114,24 +1129,26 @@ ntfs_create_reparse_buffer(struct ntfs_sb_info *sbi, const char *symname,
11141129
11151130 /* PrintName + SubstituteName. */
11161131 rs -> SubstituteNameOffset = cpu_to_le16 (sizeof (short ) * err );
1117- rs -> SubstituteNameLength = cpu_to_le16 (sizeof (short ) * err + 8 );
1132+ rs -> SubstituteNameLength = cpu_to_le16 (sizeof (short ) * err + ( is_absolute ? 8 : 0 ) );
11181133 rs -> PrintNameLength = rs -> SubstituteNameOffset ;
11191134
11201135 /*
11211136 * TODO: Use relative path if possible to allow Windows to
11221137 * parse this path.
11231138 * 0-absolute path 1- relative path (SYMLINK_FLAG_RELATIVE).
11241139 */
1125- rs -> Flags = 0 ;
1140+ rs -> Flags = cpu_to_le32 ( is_absolute ? 0 : SYMLINK_FLAG_RELATIVE ) ;
11261141
1127- memmove (rp_name + err + 4 , rp_name , sizeof (short ) * err );
1142+ memmove (rp_name + err + ( is_absolute ? 4 : 0 ) , rp_name , sizeof (short ) * err );
11281143
1129- /* Decorate SubstituteName. */
1130- rp_name += err ;
1131- rp_name [0 ] = cpu_to_le16 ('\\' );
1132- rp_name [1 ] = cpu_to_le16 ('?' );
1133- rp_name [2 ] = cpu_to_le16 ('?' );
1134- rp_name [3 ] = cpu_to_le16 ('\\' );
1144+ if (is_absolute ) {
1145+ /* Decorate SubstituteName. */
1146+ rp_name += err ;
1147+ rp_name [0 ] = cpu_to_le16 ('\\' );
1148+ rp_name [1 ] = cpu_to_le16 ('?' );
1149+ rp_name [2 ] = cpu_to_le16 ('?' );
1150+ rp_name [3 ] = cpu_to_le16 ('\\' );
1151+ }
11351152
11361153 return rp ;
11371154out :
@@ -1260,6 +1277,12 @@ int ntfs_create_inode(struct mnt_idmap *idmap, struct inode *dir,
12601277 goto out1 ;
12611278 }
12621279
1280+ /* Avoid any operation if inode is bad. */
1281+ if (unlikely (is_bad_ni (dir_ni ))) {
1282+ err = - EINVAL ;
1283+ goto out2 ;
1284+ }
1285+
12631286 if (unlikely (ntfs3_forced_shutdown (sb ))) {
12641287 err = - EIO ;
12651288 goto out2 ;
@@ -1350,7 +1373,7 @@ int ntfs_create_inode(struct mnt_idmap *idmap, struct inode *dir,
13501373 fname -> dup .a_time = std5 -> cr_time ;
13511374 fname -> dup .alloc_size = fname -> dup .data_size = 0 ;
13521375 fname -> dup .fa = std5 -> fa ;
1353- fname -> dup .ea_size = fname -> dup . reparse = 0 ;
1376+ fname -> dup .extend_data = S_ISLNK ( mode ) ? IO_REPARSE_TAG_SYMLINK : 0 ;
13541377
13551378 dsize = le16_to_cpu (new_de -> key_size );
13561379 asize = ALIGN (SIZEOF_RESIDENT + dsize , 8 );
@@ -1590,27 +1613,29 @@ int ntfs_create_inode(struct mnt_idmap *idmap, struct inode *dir,
15901613 inode -> i_flags |= S_NOSEC ;
15911614 }
15921615
1593- /*
1594- * ntfs_init_acl and ntfs_save_wsl_perm update extended attribute.
1595- * The packed size of extended attribute is stored in direntry too.
1596- * 'fname' here points to inside new_de.
1597- */
1598- err = ntfs_save_wsl_perm (inode , & fname -> dup .ea_size );
1599- if (err )
1600- goto out6 ;
1616+ if (!S_ISLNK (mode )) {
1617+ /*
1618+ * ntfs_init_acl and ntfs_save_wsl_perm update extended attribute.
1619+ * The packed size of extended attribute is stored in direntry too.
1620+ * 'fname' here points to inside new_de.
1621+ */
1622+ err = ntfs_save_wsl_perm (inode , & fname -> dup .extend_data );
1623+ if (err )
1624+ goto out6 ;
16011625
1602- /*
1603- * update ea_size in file_name attribute too.
1604- * Use ni_find_attr cause layout of MFT record may be changed
1605- * in ntfs_init_acl and ntfs_save_wsl_perm.
1606- */
1607- attr = ni_find_attr (ni , NULL , NULL , ATTR_NAME , NULL , 0 , NULL , NULL );
1608- if (attr ) {
1609- struct ATTR_FILE_NAME * fn ;
1626+ /*
1627+ * update ea_size in file_name attribute too.
1628+ * Use ni_find_attr cause layout of MFT record may be changed
1629+ * in ntfs_init_acl and ntfs_save_wsl_perm.
1630+ */
1631+ attr = ni_find_attr (ni , NULL , NULL , ATTR_NAME , NULL , 0 , NULL , NULL );
1632+ if (attr ) {
1633+ struct ATTR_FILE_NAME * fn ;
16101634
1611- fn = resident_data_ex (attr , SIZEOF_ATTRIBUTE_FILENAME );
1612- if (fn )
1613- fn -> dup .ea_size = fname -> dup .ea_size ;
1635+ fn = resident_data_ex (attr , SIZEOF_ATTRIBUTE_FILENAME );
1636+ if (fn )
1637+ fn -> dup .extend_data = fname -> dup .extend_data ;
1638+ }
16141639 }
16151640
16161641 /* We do not need to update parent directory later */
0 commit comments