From 62d3818959478dc4b305c22d8e89895f4782568a Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 14 Apr 2015 11:57:35 -0700 Subject: [PATCH] smbd: VFS: Ensure all uses of SMB_VFS_STAT use relative paths. Makes usage consistent for VFS developers. Do a CHDIR followed by a STAT(".") as root in make_connection(), instead of a STAT on an absolute path. Change in behavior is to ensure we chdir("/") on exit of this function, but as we're guarenteed to exit as root, this is the correct thing to do anyway. NB. This doesn't change behavior when re-exporting NFS shares, as the STAT as root would have failed anyway, with the same error as the CHDIR. Fixes bug #11216 - Samba calls SMB_VFS_STAT with an absolute path during TreeConnect processing but a relative path everywhere else. https://bugzilla.samba.org/show_bug.cgi?id=11216 Signed-off-by: Jeremy Allison --- source3/smbd/service.c | 36 ++++++++++++++++++++++++++---------- 1 file changed, 26 insertions(+), 10 deletions(-) diff --git a/source3/smbd/service.c b/source3/smbd/service.c index ada2d07..5b42959 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -773,7 +773,7 @@ static NTSTATUS make_connection_snum(struct smbXsrv_connection *xconn, /* * we've finished with the user stuff - go back to root - * so the SMB_VFS_STAT call will only fail on path errors, + * so the SMB_VFS_CHDIR call will only fail on path errors, * not permission problems. */ change_to_root_user(); @@ -808,22 +808,29 @@ static NTSTATUS make_connection_snum(struct smbXsrv_connection *xconn, set_namearray( &conn->aio_write_behind_list, lp_aio_write_behind(talloc_tos(), snum)); } - smb_fname_cpath = synthetic_smb_fname(talloc_tos(), conn->connectpath, + smb_fname_cpath = synthetic_smb_fname(talloc_tos(), ".", NULL, NULL); if (smb_fname_cpath == NULL) { status = NT_STATUS_NO_MEMORY; goto err_root_exit; } - /* win2000 does not check the permissions on the directory - during the tree connect, instead relying on permission - check during individual operations. To match this behaviour - I have disabled this chdir check (tridge) */ - /* the alternative is just to check the directory exists */ + /* + * We're running as root, so just try and SMB_VFS_CHDIR + * into the directory. This and realpath are the only + * VFS calls that should have to cope with absolute + * paths that might start outside the exported share + * directory. Then do a STAT on "." to get the share dev_t + * value. + */ + + ret = SMB_VFS_CHDIR(conn, conn->connectpath); + if (ret == 0) { + ret = SMB_VFS_STAT(conn, smb_fname_cpath); + } - if ((ret = SMB_VFS_STAT(conn, smb_fname_cpath)) != 0 || - !S_ISDIR(smb_fname_cpath->st.st_ex_mode)) { - if (ret == 0 && !S_ISDIR(smb_fname_cpath->st.st_ex_mode)) { + if (ret != 0) { + if (errno == ENOTDIR) { DEBUG(0,("'%s' is not a directory, when connecting to " "[%s]\n", conn->connectpath, lp_servicename(talloc_tos(), snum))); @@ -868,6 +875,11 @@ static NTSTATUS make_connection_snum(struct smbXsrv_connection *xconn, dbgtext( "(pid %d)\n", (int)getpid() ); } + /* We're exiting as root - ensure we're in / */ + if (chdir("/") != 0) { + smb_panic("Failed to chdir(/)."); + } + return status; err_root_exit: @@ -881,6 +893,10 @@ static NTSTATUS make_connection_snum(struct smbXsrv_connection *xconn, /* Call VFS disconnect hook */ SMB_VFS_DISCONNECT(conn); } + /* We're exiting as root - ensure we're in / */ + if (chdir("/") != 0) { + smb_panic("Failed to chdir(/)."); + } return status; } -- 2.2.0.rc0.207.ga3a616c