Ignore:
Timestamp:
Nov 27, 2012, 4:43:17 PM (13 years ago)
Author:
Silvan Scherrer
Message:

Samba Server: updated trunk to 3.6.0

Location:
trunk/server
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/server

  • trunk/server/source3/smbd/smb2_read.c

    r414 r745  
    2020
    2121#include "includes.h"
     22#include "system/filesys.h"
     23#include "smbd/smbd.h"
    2224#include "smbd/globals.h"
    2325#include "../libcli/smb/smb_common.h"
     26#include "libcli/security/security.h"
     27#include "../lib/util/tevent_ntstatus.h"
     28#include "rpc_server/srv_pipe_hnd.h"
    2429
    2530static struct tevent_req *smbd_smb2_read_send(TALLOC_CTX *mem_ctx,
     
    7681
    7782        /* check the max read size */
    78         if (in_length > 0x00010000) {
     83        if (in_length > lp_smb2_max_read()) {
    7984                DEBUG(0,("here:%s: 0x%08X: 0x%08X\n",
    80                         __location__, in_length, 0x00010000));
     85                        __location__, in_length, lp_smb2_max_read()));
    8186                return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
    8287        }
     
    8489        if (req->compat_chain_fsp) {
    8590                /* skip check */
    86         } else if (in_file_id_persistent != 0) {
     91        } else if (in_file_id_persistent != in_file_id_volatile) {
    8792                return smbd_smb2_request_error(req, NT_STATUS_FILE_CLOSED);
    8893        }
     
    171176struct smbd_smb2_read_state {
    172177        struct smbd_smb2_request *smb2req;
     178        files_struct *fsp;
     179        uint64_t in_file_id_volatile;
     180        uint32_t in_length;
     181        uint64_t in_offset;
     182        uint32_t in_minimum;
    173183        DATA_BLOB out_data;
    174184        uint32_t out_remaining;
    175185};
    176186
     187/* struct smbd_smb2_read_state destructor. Send the SMB2_READ data. */
     188static int smb2_sendfile_send_data(struct smbd_smb2_read_state *state)
     189{
     190        struct lock_struct lock;
     191        uint32_t in_length = state->in_length;
     192        uint64_t in_offset = state->in_offset;
     193        files_struct *fsp = state->fsp;
     194        ssize_t nread;
     195
     196        nread = SMB_VFS_SENDFILE(fsp->conn->sconn->sock,
     197                                        fsp,
     198                                        NULL,
     199                                        in_offset,
     200                                        in_length);
     201        DEBUG(10,("smb2_sendfile_send_data: SMB_VFS_SENDFILE returned %d on file %s\n",
     202                (int)nread,
     203                fsp_str_dbg(fsp) ));
     204
     205        if (nread == -1) {
     206                if (errno == ENOSYS || errno == EINTR) {
     207                        /*
     208                         * Special hack for broken systems with no working
     209                         * sendfile. Fake this up by doing read/write calls.
     210                        */
     211                        set_use_sendfile(SNUM(fsp->conn), false);
     212                        nread = fake_sendfile(fsp, in_offset, in_length);
     213                        if (nread == -1) {
     214                                DEBUG(0,("smb2_sendfile_send_data: "
     215                                        "fake_sendfile failed for "
     216                                        "file %s (%s).\n",
     217                                        fsp_str_dbg(fsp),
     218                                        strerror(errno)));
     219                                exit_server_cleanly("smb2_sendfile_send_data: "
     220                                        "fake_sendfile failed");
     221                        }
     222                        goto out;
     223                }
     224
     225                DEBUG(0,("smb2_sendfile_send_data: sendfile failed for file "
     226                        "%s (%s). Terminating\n",
     227                        fsp_str_dbg(fsp),
     228                        strerror(errno)));
     229                exit_server_cleanly("smb2_sendfile_send_data: sendfile failed");
     230        } else if (nread == 0) {
     231                /*
     232                 * Some sendfile implementations return 0 to indicate
     233                 * that there was a short read, but nothing was
     234                 * actually written to the socket.  In this case,
     235                 * fallback to the normal read path so the header gets
     236                 * the correct byte count.
     237                 */
     238                DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
     239                        "falling back to the normal read: %s\n",
     240                        fsp_str_dbg(fsp)));
     241
     242                nread = fake_sendfile(fsp, in_offset, in_length);
     243                if (nread == -1) {
     244                        DEBUG(0,("smb2_sendfile_send_data: "
     245                                "fake_sendfile failed for file "
     246                                "%s (%s). Terminating\n",
     247                                fsp_str_dbg(fsp),
     248                                strerror(errno)));
     249                        exit_server_cleanly("smb2_sendfile_send_data: "
     250                                "fake_sendfile failed");
     251                }
     252        }
     253
     254  out:
     255
     256        if (nread < in_length) {
     257                sendfile_short_send(fsp, nread, 0, in_length);
     258        }
     259
     260        init_strict_lock_struct(fsp,
     261                                state->in_file_id_volatile,
     262                                in_offset,
     263                                in_length,
     264                                READ_LOCK,
     265                                &lock);
     266
     267        SMB_VFS_STRICT_UNLOCK(fsp->conn, fsp, &lock);
     268        return 0;
     269}
     270
     271static NTSTATUS schedule_smb2_sendfile_read(struct smbd_smb2_request *smb2req,
     272                                        struct smbd_smb2_read_state *state)
     273{
     274        struct smbd_smb2_read_state *state_copy = NULL;
     275        files_struct *fsp = state->fsp;
     276
     277        /*
     278         * We cannot use sendfile if...
     279         * We were not configured to do so OR
     280         * Signing is active OR
     281         * This is a compound SMB2 operation OR
     282         * fsp is a STREAM file OR
     283         * We're using a write cache OR
     284         * It's not a regular file OR
     285         * Requested offset is greater than file size OR
     286         * there's not enough data in the file.
     287         * Phew :-). Luckily this means most
     288         * reads on most normal files. JRA.
     289        */
     290
     291        if (!_lp_use_sendfile(SNUM(fsp->conn)) ||
     292                        smb2req->do_signing ||
     293                        smb2req->in.vector_count != 4 ||
     294                        (fsp->base_fsp != NULL) ||
     295                        (fsp->wcp != NULL) ||
     296                        (!S_ISREG(fsp->fsp_name->st.st_ex_mode)) ||
     297                        (state->in_offset >= fsp->fsp_name->st.st_ex_size) ||
     298                        (fsp->fsp_name->st.st_ex_size < state->in_offset +
     299                                state->in_length)) {
     300                return NT_STATUS_RETRY;
     301        }
     302
     303        /* We've already checked there's this amount of data
     304           to read. */
     305        state->out_data.length = state->in_length;
     306        state->out_remaining = 0;
     307
     308        /* Make a copy of state attached to the smb2req. Attach
     309           the destructor here as this will trigger the sendfile
     310           call when the request is destroyed. */
     311        state_copy = TALLOC_P(smb2req, struct smbd_smb2_read_state);
     312        if (!state_copy) {
     313                return NT_STATUS_NO_MEMORY;
     314        }
     315        *state_copy = *state;
     316        talloc_set_destructor(state_copy, smb2_sendfile_send_data);
     317        return NT_STATUS_OK;
     318}
     319
    177320static void smbd_smb2_read_pipe_done(struct tevent_req *subreq);
     321
     322/*******************************************************************
     323 Common read complete processing function for both synchronous and
     324 asynchronous reads.
     325*******************************************************************/
     326
     327NTSTATUS smb2_read_complete(struct tevent_req *req, ssize_t nread, int err)
     328{
     329        struct smbd_smb2_read_state *state = tevent_req_data(req,
     330                                        struct smbd_smb2_read_state);
     331        files_struct *fsp = state->fsp;
     332
     333        if (nread < 0) {
     334                NTSTATUS status = map_nt_error_from_unix(err);
     335
     336                DEBUG( 3,( "smb2_read_complete: file %s nread = %d. "
     337                        "Error = %s (NTSTATUS %s)\n",
     338                        fsp_str_dbg(fsp),
     339                        (int)nread,
     340                        strerror(err),
     341                        nt_errstr(status)));
     342
     343                return status;
     344        }
     345        if (nread == 0 && state->in_length != 0) {
     346                DEBUG(5,("smb2_read_complete: read_file[%s] end of file\n",
     347                        fsp_str_dbg(fsp)));
     348                return NT_STATUS_END_OF_FILE;
     349        }
     350
     351        if (nread < state->in_minimum) {
     352                DEBUG(5,("smb2_read_complete: read_file[%s] read less %d than "
     353                        "minimum requested %u. Returning end of file\n",
     354                        fsp_str_dbg(fsp),
     355                        (int)nread,
     356                        (unsigned int)state->in_minimum));
     357                return NT_STATUS_END_OF_FILE;
     358        }
     359
     360        DEBUG(3,("smbd_smb2_read: fnum=[%d/%s] length=%lu offset=%lu read=%lu\n",
     361                fsp->fnum,
     362                fsp_str_dbg(fsp),
     363                (unsigned long)state->in_length,
     364                (unsigned long)state->in_offset,
     365                (unsigned long)nread));
     366
     367        state->out_data.length = nread;
     368        state->out_remaining = 0;
     369
     370        return NT_STATUS_OK;
     371}
    178372
    179373static struct tevent_req *smbd_smb2_read_send(TALLOC_CTX *mem_ctx,
     
    187381                                              uint32_t in_remaining)
    188382{
    189         struct tevent_req *req;
    190         struct smbd_smb2_read_state *state;
    191         struct smb_request *smbreq;
     383        NTSTATUS status;
     384        struct tevent_req *req = NULL;
     385        struct smbd_smb2_read_state *state = NULL;
     386        struct smb_request *smbreq = NULL;
    192387        connection_struct *conn = smb2req->tcon->compat_conn;
    193         files_struct *fsp;
     388        files_struct *fsp = NULL;
    194389        ssize_t nread = -1;
    195390        struct lock_struct lock;
     391        int saved_errno;
    196392
    197393        req = tevent_req_create(mem_ctx, &state,
     
    201397        }
    202398        state->smb2req = smb2req;
     399        state->in_length = in_length;
     400        state->in_offset = in_offset;
     401        state->in_minimum = in_minimum;
    203402        state->out_data = data_blob_null;
    204403        state->out_remaining = 0;
     
    225424                return tevent_req_post(req, ev);
    226425        }
    227 
    228         state->out_data = data_blob_talloc(state, NULL, in_length);
    229         if (in_length > 0 && tevent_req_nomem(state->out_data.data, req)) {
    230                 return tevent_req_post(req, ev);
    231         }
     426        if (fsp->is_directory) {
     427                tevent_req_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
     428                return tevent_req_post(req, ev);
     429        }
     430
     431        state->fsp = fsp;
     432        state->in_file_id_volatile = in_file_id_volatile;
    232433
    233434        if (IS_IPC(smbreq->conn)) {
    234                 struct tevent_req *subreq;
     435                struct tevent_req *subreq = NULL;
     436
     437                state->out_data = data_blob_talloc(state, NULL, in_length);
     438                if (in_length > 0 && tevent_req_nomem(state->out_data.data, req)) {
     439                        return tevent_req_post(req, ev);
     440                }
    235441
    236442                if (!fsp_is_np(fsp)) {
     
    257463        }
    258464
     465        status = schedule_smb2_aio_read(fsp->conn,
     466                                smbreq,
     467                                fsp,
     468                                state,
     469                                &state->out_data,
     470                                (SMB_OFF_T)in_offset,
     471                                (size_t)in_length);
     472
     473        if (NT_STATUS_IS_OK(status)) {
     474                /*
     475                 * Doing an async read. Don't
     476                 * send a "gone async" message
     477                 * as we expect this to be less
     478                 * than the client timeout period.
     479                 * JRA. FIXME for offline files..
     480                 * FIXME. Add cancel code..
     481                 */
     482                smb2req->async = true;
     483                return req;
     484        }
     485
     486        if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
     487                /* Real error in setting up aio. Fail. */
     488                tevent_req_nterror(req, NT_STATUS_FILE_CLOSED);
     489                return tevent_req_post(req, ev);
     490        }
     491
     492        /* Fallback to synchronous. */
     493
    259494        init_strict_lock_struct(fsp,
    260                                 in_smbpid,
     495                                in_file_id_volatile,
    261496                                in_offset,
    262497                                in_length,
     
    269504        }
    270505
     506        /* Try sendfile in preference. */
     507        status = schedule_smb2_sendfile_read(smb2req, state);
     508        if (NT_STATUS_IS_OK(status)) {
     509                tevent_req_done(req);
     510                return tevent_req_post(req, ev);
     511        } else {
     512                if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
     513                        SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
     514                        tevent_req_nterror(req, status);
     515                        return tevent_req_post(req, ev);
     516                }
     517        }
     518
     519        /* Ok, read into memory. Allocate the out buffer. */
     520        state->out_data = data_blob_talloc(state, NULL, in_length);
     521        if (in_length > 0 && tevent_req_nomem(state->out_data.data, req)) {
     522                SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
     523                return tevent_req_post(req, ev);
     524        }
     525
    271526        nread = read_file(fsp,
    272527                          (char *)state->out_data.data,
     
    274529                          in_length);
    275530
     531        saved_errno = errno;
     532
    276533        SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
    277534
    278         if (nread < 0) {
    279                 DEBUG(5,("smbd_smb2_read: read_file[%s] nread[%lld]\n",
    280                          fsp_str_dbg(fsp), (long long)nread));
    281                 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
    282                 return tevent_req_post(req, ev);
    283         }
    284         if (nread == 0 && in_length != 0) {
    285                 DEBUG(5,("smbd_smb2_read: read_file[%s] end of file\n",
    286                          fsp_str_dbg(fsp)));
    287                 tevent_req_nterror(req, NT_STATUS_END_OF_FILE);
    288                 return tevent_req_post(req, ev);
    289         }
    290 
    291         state->out_data.length = nread;
    292         state->out_remaining = 0;
    293         tevent_req_done(req);
     535        DEBUG(10,("smbd_smb2_read: file %s handle [0x%016llX] offset=%llu "
     536                "len=%llu returned %lld\n",
     537                fsp_str_dbg(fsp),
     538                (unsigned long long)in_file_id_volatile,
     539                (unsigned long long)in_offset,
     540                (unsigned long long)in_length,
     541                (long long)nread));
     542
     543        status = smb2_read_complete(req, nread, saved_errno);
     544        if (!NT_STATUS_IS_OK(status)) {
     545                tevent_req_nterror(req, status);
     546        } else {
     547                /* Success. */
     548                tevent_req_done(req);
     549        }
    294550        return tevent_req_post(req, ev);
    295551}
     
    320576        state->out_remaining = 0;
    321577
     578        /*
     579         * TODO: add STATUS_BUFFER_OVERFLOW handling, once we also
     580         * handle it in SMB1 pipe_read_andx_done().
     581         */
     582
    322583        tevent_req_done(req);
    323584}
Note: See TracChangeset for help on using the changeset viewer.