@@ -3539,23 +3539,20 @@ int smb2_open(struct ksmbd_work *work)
35393539 KSMBD_SHARE_FLAG_ACL_XATTR )) {
35403540 struct smb_fattr fattr ;
35413541 struct smb_ntsd * pntsd ;
3542- int pntsd_size , ace_num = 0 ;
3542+ int pntsd_size ;
3543+ size_t scratch_len ;
35433544
35443545#if LINUX_VERSION_CODE >= KERNEL_VERSION (6 , 3 , 0 )
35453546 ksmbd_acls_fattr (& fattr , idmap , inode );
35463547#else
35473548 ksmbd_acls_fattr (& fattr , user_ns , inode );
35483549#endif
3549- if (fattr .cf_acls )
3550- ace_num = fattr .cf_acls -> a_count ;
3551- if (fattr .cf_dacls )
3552- ace_num += fattr .cf_dacls -> a_count ;
3553-
3554- pntsd = kmalloc (sizeof (struct smb_ntsd ) +
3555- sizeof (struct smb_sid ) * 3 +
3556- sizeof (struct smb_acl ) +
3557- sizeof (struct smb_ace ) * ace_num * 2 ,
3558- KSMBD_DEFAULT_GFP );
3550+ scratch_len = smb_acl_sec_desc_scratch_len (& fattr ,
3551+ NULL , 0 ,
3552+ OWNER_SECINFO | GROUP_SECINFO |
3553+ DACL_SECINFO );
3554+
3555+ pntsd = kvmalloc (scratch_len , KSMBD_DEFAULT_GFP );
35593556 if (!pntsd ) {
35603557 posix_acl_release (fattr .cf_acls );
35613558 posix_acl_release (fattr .cf_dacls );
@@ -3575,7 +3572,7 @@ int smb2_open(struct ksmbd_work *work)
35753572 posix_acl_release (fattr .cf_acls );
35763573 posix_acl_release (fattr .cf_dacls );
35773574 if (rc ) {
3578- kfree (pntsd );
3575+ kvfree (pntsd );
35793576 goto err_out ;
35803577 }
35813578
@@ -3589,7 +3586,7 @@ int smb2_open(struct ksmbd_work *work)
35893586 pntsd ,
35903587 pntsd_size ,
35913588 false);
3592- kfree (pntsd );
3589+ kvfree (pntsd );
35933590 if (rc )
35943591 pr_err ("failed to store ntacl in xattr : %d\n" ,
35953592 rc );
@@ -5638,8 +5635,9 @@ static int smb2_get_info_file(struct ksmbd_work *work,
56385635 if (test_share_config_flag (work -> tcon -> share_conf ,
56395636 KSMBD_SHARE_FLAG_PIPE )) {
56405637 /* smb2 info file called for pipe */
5641- return smb2_get_info_file_pipe (work -> sess , req , rsp ,
5638+ rc = smb2_get_info_file_pipe (work -> sess , req , rsp ,
56425639 work -> response_buf );
5640+ goto iov_pin_out ;
56435641 }
56445642
56455643 if (work -> next_smb2_rcv_hdr_off ) {
@@ -5739,6 +5737,12 @@ static int smb2_get_info_file(struct ksmbd_work *work,
57395737 rc = buffer_check_err (le32_to_cpu (req -> OutputBufferLength ),
57405738 rsp , work -> response_buf );
57415739 ksmbd_fd_put (work , fp );
5740+
5741+ iov_pin_out :
5742+ if (!rc )
5743+ rc = ksmbd_iov_pin_rsp (work , (void * )rsp ,
5744+ offsetof(struct smb2_query_info_rsp , Buffer ) +
5745+ le32_to_cpu (rsp -> OutputBufferLength ));
57425746 return rc ;
57435747}
57445748
@@ -5958,6 +5962,11 @@ static int smb2_get_info_filesystem(struct ksmbd_work *work,
59585962 rc = buffer_check_err (le32_to_cpu (req -> OutputBufferLength ),
59595963 rsp , work -> response_buf );
59605964 path_put (& path );
5965+
5966+ if (!rc )
5967+ rc = ksmbd_iov_pin_rsp (work , (void * )rsp ,
5968+ offsetof(struct smb2_query_info_rsp , Buffer ) +
5969+ le32_to_cpu (rsp -> OutputBufferLength ));
59615970 return rc ;
59625971}
59635972
@@ -5971,20 +5980,29 @@ static int smb2_get_info_sec(struct ksmbd_work *work,
59715980#else
59725981 struct user_namespace * user_ns ;
59735982#endif
5974- struct smb_ntsd * pntsd = ( struct smb_ntsd * ) rsp -> Buffer , * ppntsd = NULL ;
5983+ struct smb_ntsd * pntsd = NULL , * ppntsd = NULL ;
59755984 struct smb_fattr fattr = {{0 }};
59765985 struct inode * inode ;
59775986 __u32 secdesclen = 0 ;
59785987 unsigned int id = KSMBD_NO_FID , pid = KSMBD_NO_FID ;
59795988 int addition_info = le32_to_cpu (req -> AdditionalInformation );
5980- int rc = 0 , ppntsd_size = 0 ;
5989+ int rc = 0 , ppntsd_size = 0 , max_len ;
5990+ size_t scratch_len ;
59815991
59825992 if (addition_info & ~(OWNER_SECINFO | GROUP_SECINFO | DACL_SECINFO |
59835993 PROTECTED_DACL_SECINFO |
59845994 UNPROTECTED_DACL_SECINFO )) {
59855995 ksmbd_debug (SMB , "Unsupported addition info: 0x%x)\n" ,
59865996 addition_info );
59875997
5998+ #if LINUX_VERSION_CODE >= KERNEL_VERSION (6 , 3 , 0 )
5999+ pntsd = kmalloc_obj (struct smb_ntsd , KSMBD_DEFAULT_GFP );
6000+ #else
6001+ pntsd = kmalloc (sizeof (struct smb_ntsd ), KSMBD_DEFAULT_GFP );
6002+ #endif
6003+ if (!pntsd )
6004+ return - ENOMEM ;
6005+
59886006 pntsd -> revision = cpu_to_le16 (1 );
59896007 pntsd -> type = cpu_to_le16 (SELF_RELATIVE | DACL_PROTECTED );
59906008 pntsd -> osidoffset = 0 ;
@@ -5993,9 +6011,7 @@ static int smb2_get_info_sec(struct ksmbd_work *work,
59936011 pntsd -> dacloffset = 0 ;
59946012
59956013 secdesclen = sizeof (struct smb_ntsd );
5996- rsp -> OutputBufferLength = cpu_to_le32 (secdesclen );
5997-
5998- return 0 ;
6014+ goto iov_pin ;
59996015 }
60006016
60016017 if (work -> next_smb2_rcv_hdr_off ) {
@@ -6038,23 +6054,59 @@ static int smb2_get_info_sec(struct ksmbd_work *work,
60386054 fp -> filp -> f_path .dentry ,
60396055 & ppntsd );
60406056
6057+ max_len = smb2_calc_max_out_buf_len (work ,
6058+ offsetof(struct smb2_query_info_rsp , Buffer ),
6059+ le32_to_cpu (req -> OutputBufferLength ));
6060+ if (max_len < 0 ) {
6061+ rc = - EINVAL ;
6062+ goto out ;
6063+ }
6064+
6065+ scratch_len = smb_acl_sec_desc_scratch_len (& fattr , ppntsd ,
6066+ ppntsd_size , addition_info );
6067+ pntsd = kvzalloc (scratch_len , KSMBD_DEFAULT_GFP );
6068+ if (!pntsd ) {
6069+ rc = - ENOMEM ;
6070+ goto out ;
6071+ }
6072+
60416073 /* Check if sd buffer size exceeds response buffer size */
6042- if (smb2_resp_buf_len (work , 8 ) > ppntsd_size )
60436074#if LINUX_VERSION_CODE >= KERNEL_VERSION (6 , 3 , 0 )
6044- rc = build_sec_desc (idmap , pntsd , ppntsd , ppntsd_size ,
6075+ rc = build_sec_desc (idmap , pntsd , ppntsd , ppntsd_size ,
6076+ addition_info , & secdesclen , & fattr );
60456077#else
6046- rc = build_sec_desc (user_ns , pntsd , ppntsd , ppntsd_size ,
6078+ rc = build_sec_desc (user_ns , pntsd , ppntsd , ppntsd_size ,
6079+ addition_info , & secdesclen , & fattr );
60476080#endif
6048- addition_info , & secdesclen , & fattr );
6081+
6082+ out :
60496083 posix_acl_release (fattr .cf_acls );
60506084 posix_acl_release (fattr .cf_dacls );
60516085 kfree (ppntsd );
60526086 ksmbd_fd_put (work , fp );
6053- if (rc )
6087+ if (rc ) {
6088+ kvfree (pntsd );
60546089 return rc ;
6090+ }
60556091
6092+ iov_pin :
60566093 rsp -> OutputBufferLength = cpu_to_le32 (secdesclen );
6057- return 0 ;
6094+ rc = buffer_check_err (le32_to_cpu (req -> OutputBufferLength ),
6095+ rsp , work -> response_buf );
6096+ if (rc ) {
6097+ kvfree (pntsd );
6098+ return rc ;
6099+ }
6100+
6101+ rc = ksmbd_iov_pin_rsp_read (work , (void * )rsp ,
6102+ offsetof(struct smb2_query_info_rsp , Buffer ),
6103+ pntsd , secdesclen );
6104+ if (rc ) {
6105+ rsp -> OutputBufferLength = 0 ;
6106+ kvfree (pntsd );
6107+ }
6108+
6109+ return rc ;
60586110}
60596111
60606112/**
@@ -6078,6 +6130,9 @@ int smb2_query_info(struct ksmbd_work *work)
60786130 goto err_out ;
60796131 }
60806132
6133+ rsp -> StructureSize = cpu_to_le16 (9 );
6134+ rsp -> OutputBufferOffset = cpu_to_le16 (72 );
6135+
60816136 switch (req -> InfoType ) {
60826137 case SMB2_O_INFO_FILE :
60836138 ksmbd_debug (SMB , "GOT SMB2_O_INFO_FILE\n" );
@@ -6098,14 +6153,6 @@ int smb2_query_info(struct ksmbd_work *work)
60986153 }
60996154 ksmbd_revert_fsids (work );
61006155
6101- if (!rc ) {
6102- rsp -> StructureSize = cpu_to_le16 (9 );
6103- rsp -> OutputBufferOffset = cpu_to_le16 (72 );
6104- rc = ksmbd_iov_pin_rsp (work , (void * )rsp ,
6105- offsetof(struct smb2_query_info_rsp , Buffer ) +
6106- le32_to_cpu (rsp -> OutputBufferLength ));
6107- }
6108-
61096156err_out :
61106157 if (rc < 0 ) {
61116158 if (rc == - EACCES )
@@ -6116,6 +6163,8 @@ int smb2_query_info(struct ksmbd_work *work)
61166163 rsp -> hdr .Status = STATUS_UNEXPECTED_IO_ERROR ;
61176164 else if (rc == - ENOMEM )
61186165 rsp -> hdr .Status = STATUS_INSUFFICIENT_RESOURCES ;
6166+ else if (rc == - EINVAL && rsp -> hdr .Status == 0 )
6167+ rsp -> hdr .Status = STATUS_INVALID_PARAMETER ;
61196168 else if (rc == - EOPNOTSUPP || rsp -> hdr .Status == 0 )
61206169 rsp -> hdr .Status = STATUS_INVALID_INFO_CLASS ;
61216170 smb2_set_err_rsp (work );
0 commit comments