From: Jeremy Allison Date: Tue, 14 Dec 2021 00:48:14 +0000 (-0800) Subject: s3: smbd: Inside call_trans2setfilepathinfo(), for the TRANSACT2_SETPATHINFO case... X-Git-Tag: tdb-1.4.6~271 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=d508dff634509eb9c3a69ef628f618eeeda34d9b;p=thirdparty%2Fsamba.git s3: smbd: Inside call_trans2setfilepathinfo(), for the TRANSACT2_SETPATHINFO case, ensure we have a VALID_STAT return from filename_convert(). Remember, filename_convert() can return NT_STATUS_OK with !VALID_STAT() if the last component doesn't exist, as this may be an object create. For call_trans2setfilepathinfo(), there are only 4 info levels for the TRANSACT2_SETPATHINFO (pathname) case that don't require an existing filesystem object (i.e. a VALID_STAT()) in the return from filename_convert() as they can create an object in the filesystem. If we don't get a VALID_STAT() and the info level isn't one of those 4, error out. Signed-off-by: Jeremy Allison Reviewed-by: Noel Power --- diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 8b97aa64d28..73a3bbae7cd 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -9339,6 +9339,7 @@ static void call_trans2setfilepathinfo(connection_struct *conn, } else { char *fname = NULL; uint32_t ucf_flags = ucf_flags_from_smb_request(req); + bool require_existing_object = true; /* set path info */ if (total_params < 7) { @@ -9406,6 +9407,32 @@ static void call_trans2setfilepathinfo(connection_struct *conn, */ fsp = smb_fname->fsp; + /* + * There are 4 info levels which can + * create a new object in the filesystem. + * They are: + * SMB_SET_FILE_UNIX_LINK -> creates POSIX symlink. + * SMB_POSIX_PATH_OPEN -> creates POSIX file or directory. + * SMB_SET_FILE_UNIX_BASIC: + * SMB_SET_FILE_UNIX_INFO2: can create a POSIX special file. + * + * These info levels do not require an existing object. + */ + switch (info_level) { + case SMB_SET_FILE_UNIX_LINK: + case SMB_POSIX_PATH_OPEN: + case SMB_SET_FILE_UNIX_BASIC: + case SMB_SET_FILE_UNIX_INFO2: + require_existing_object = false; + break; + default: + break; + } + + if (!VALID_STAT(smb_fname->st) && require_existing_object) { + reply_nterror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND); + } + if (INFO_LEVEL_IS_UNIX(info_level)) { /* * For CIFS UNIX extensions the target name may not exist.