Coverage Report

Created: 2025-11-16 06:57

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/samba/source3/smbd/smb2_oplock.c
Line
Count
Source
1
/* 
2
   Unix SMB/CIFS implementation.
3
   oplock processing
4
   Copyright (C) Andrew Tridgell 1992-1998
5
   Copyright (C) Jeremy Allison 1998 - 2001
6
   Copyright (C) Volker Lendecke 2005
7
8
   This program is free software; you can redistribute it and/or modify
9
   it under the terms of the GNU General Public License as published by
10
   the Free Software Foundation; either version 3 of the License, or
11
   (at your option) any later version.
12
13
   This program is distributed in the hope that it will be useful,
14
   but WITHOUT ANY WARRANTY; without even the implied warranty of
15
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
   GNU General Public License for more details.
17
18
   You should have received a copy of the GNU General Public License
19
   along with this program.  If not, see <http://www.gnu.org/licenses/>.
20
*/
21
22
0
#define DBGC_CLASS DBGC_LOCKING
23
#include "includes.h"
24
#include "lib/util/server_id.h"
25
#include "locking/share_mode_lock.h"
26
#include "smbd/smbd.h"
27
#include "smbd/globals.h"
28
#include "messages.h"
29
#include "locking/leases_db.h"
30
#include "../librpc/gen_ndr/ndr_open_files.h"
31
#include "lib/util/tevent_ntstatus.h"
32
#include "source3/smbd/dir.h"
33
34
/*
35
 * helper function used by the kernel oplock backends to post the break message
36
 */
37
void break_kernel_oplock(struct messaging_context *msg_ctx, files_struct *fsp)
38
0
{
39
0
  struct oplock_break_message msg = {
40
0
    .id = fsp->file_id,
41
0
    .share_file_id = fh_get_gen_id(fsp->fh),
42
0
  };
43
0
  enum ndr_err_code ndr_err;
44
0
  uint8_t msgbuf[33];
45
0
  DATA_BLOB blob = {.data = msgbuf, .length = sizeof(msgbuf)};
46
47
  /* Don't need to be root here as we're only ever
48
     sending to ourselves. */
49
50
0
  ndr_err = ndr_push_struct_into_fixed_blob(
51
0
    &blob,
52
0
    &msg,
53
0
    (ndr_push_flags_fn_t)ndr_push_oplock_break_message);
54
0
  if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
55
0
    DBG_WARNING("ndr_push_oplock_break_message failed: %s\n",
56
0
          ndr_errstr(ndr_err));
57
0
    return;
58
0
  }
59
60
0
  messaging_send(msg_ctx,
61
0
           messaging_server_id(msg_ctx),
62
0
           MSG_SMB_KERNEL_BREAK,
63
0
           &blob);
64
0
}
65
66
/****************************************************************************
67
 Attempt to set an oplock on a file. Succeeds if kernel oplocks are
68
 disabled (just sets flags).
69
****************************************************************************/
70
71
NTSTATUS set_file_oplock(files_struct *fsp)
72
0
{
73
0
  struct smbd_server_connection *sconn = fsp->conn->sconn;
74
0
  struct kernel_oplocks *koplocks = sconn->oplocks.kernel_ops;
75
0
  bool use_kernel = lp_kernel_oplocks(SNUM(fsp->conn)) &&
76
0
      (koplocks != NULL);
77
0
  struct file_id_buf buf;
78
79
0
  smb_vfs_assert_allowed();
80
81
0
  if (fsp->oplock_type == LEVEL_II_OPLOCK && use_kernel) {
82
0
    DEBUG(10, ("Refusing level2 oplock, kernel oplocks "
83
0
         "don't support them\n"));
84
0
    return NT_STATUS_NOT_SUPPORTED;
85
0
  }
86
87
0
  if ((fsp->oplock_type != NO_OPLOCK) &&
88
0
      use_kernel &&
89
0
      !koplocks->ops->set_oplock(koplocks, fsp, fsp->oplock_type))
90
0
  {
91
0
    return map_nt_error_from_unix(errno);
92
0
  }
93
94
0
  fsp->sent_oplock_break = NO_BREAK_SENT;
95
0
  if (fsp->oplock_type == LEVEL_II_OPLOCK) {
96
0
    sconn->oplocks.level_II_open++;
97
0
  } else if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
98
0
    sconn->oplocks.exclusive_open++;
99
0
  }
100
101
0
  DBG_INFO("granted oplock on file %s, %s/%"PRIu64", "
102
0
     "tv_sec = %x, tv_usec = %x\n",
103
0
     fsp_str_dbg(fsp),
104
0
     file_id_str_buf(fsp->file_id, &buf),
105
0
     fh_get_gen_id(fsp->fh),
106
0
     (int)fsp->open_time.tv_sec,
107
0
     (int)fsp->open_time.tv_usec);
108
109
0
  return NT_STATUS_OK;
110
0
}
111
112
static void release_fsp_kernel_oplock(files_struct *fsp)
113
0
{
114
0
  struct smbd_server_connection *sconn = fsp->conn->sconn;
115
0
  struct kernel_oplocks *koplocks = sconn->oplocks.kernel_ops;
116
0
  bool use_kernel;
117
118
0
  smb_vfs_assert_allowed();
119
120
0
  if (koplocks == NULL) {
121
0
    return;
122
0
  }
123
0
  use_kernel = lp_kernel_oplocks(SNUM(fsp->conn));
124
0
  if (!use_kernel) {
125
0
    return;
126
0
  }
127
0
  if (fsp->oplock_type == NO_OPLOCK) {
128
0
    return;
129
0
  }
130
0
  if (fsp->oplock_type == LEASE_OPLOCK) {
131
    /*
132
     * For leases we don't touch kernel oplocks at all
133
     */
134
0
    return;
135
0
  }
136
137
0
  koplocks->ops->release_oplock(koplocks, fsp, NO_OPLOCK);
138
0
}
139
140
/****************************************************************************
141
 Attempt to release an oplock on a file. Decrements oplock count.
142
****************************************************************************/
143
144
void release_file_oplock(files_struct *fsp)
145
0
{
146
0
  struct smbd_server_connection *sconn = fsp->conn->sconn;
147
148
0
  release_fsp_kernel_oplock(fsp);
149
150
0
  if (fsp->oplock_type == LEVEL_II_OPLOCK) {
151
0
    sconn->oplocks.level_II_open--;
152
0
  } else if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
153
0
    sconn->oplocks.exclusive_open--;
154
0
  }
155
156
0
  SMB_ASSERT(sconn->oplocks.exclusive_open>=0);
157
0
  SMB_ASSERT(sconn->oplocks.level_II_open>=0);
158
159
0
  fsp->oplock_type = NO_OPLOCK;
160
0
  fsp->sent_oplock_break = NO_BREAK_SENT;
161
162
0
  TALLOC_FREE(fsp->oplock_timeout);
163
0
}
164
165
/****************************************************************************
166
 Attempt to downgrade an oplock on a file. Doesn't decrement oplock count.
167
****************************************************************************/
168
169
static void downgrade_file_oplock(files_struct *fsp)
170
0
{
171
0
  struct smbd_server_connection *sconn = fsp->conn->sconn;
172
0
  struct kernel_oplocks *koplocks = sconn->oplocks.kernel_ops;
173
0
  bool use_kernel = lp_kernel_oplocks(SNUM(fsp->conn)) &&
174
0
      (koplocks != NULL);
175
176
0
  smb_vfs_assert_allowed();
177
178
0
  if (!EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
179
0
    DEBUG(0, ("trying to downgrade an already-downgraded oplock!\n"));
180
0
    return;
181
0
  }
182
183
0
  if (use_kernel) {
184
0
    koplocks->ops->release_oplock(koplocks, fsp, LEVEL_II_OPLOCK);
185
0
  }
186
0
  fsp->oplock_type = LEVEL_II_OPLOCK;
187
0
  sconn->oplocks.exclusive_open--;
188
0
  sconn->oplocks.level_II_open++;
189
0
  fsp->sent_oplock_break = NO_BREAK_SENT;
190
191
0
  TALLOC_FREE(fsp->oplock_timeout);
192
0
}
193
194
uint32_t get_lease_type(struct share_mode_entry *e, struct file_id id)
195
0
{
196
0
  struct GUID_txt_buf guid_strbuf;
197
0
  struct file_id_buf file_id_strbuf;
198
0
  NTSTATUS status;
199
0
  uint32_t current_state;
200
201
0
  if (e->op_type != LEASE_OPLOCK) {
202
0
    return map_oplock_to_lease_type(e->op_type);
203
0
  }
204
205
0
  status = leases_db_get(&e->client_guid,
206
0
             &e->lease_key,
207
0
             &id,
208
0
             &current_state,
209
0
             NULL, /* breaking */
210
0
             NULL, /* breaking_to_requested */
211
0
             NULL, /* breaking_to_required */
212
0
             NULL, /* lease_version */
213
0
             NULL);  /* epoch */
214
0
  if (NT_STATUS_IS_OK(status)) {
215
0
    return current_state;
216
0
  }
217
218
0
  if (share_entry_stale_pid(e)) {
219
0
    return 0;
220
0
  }
221
0
  DBG_ERR("leases_db_get for client_guid [%s] "
222
0
    "lease_key [%"PRIx64"/%"PRIx64"] "
223
0
    "file_id [%s] failed: %s\n",
224
0
    GUID_buf_string(&e->client_guid, &guid_strbuf),
225
0
    e->lease_key.data[0],
226
0
    e->lease_key.data[1],
227
0
    file_id_str_buf(id, &file_id_strbuf),
228
0
    nt_errstr(status));
229
0
  smb_panic("leases_db_get() failed");
230
0
}
231
232
/****************************************************************************
233
 Remove a file oplock. Copes with level II and exclusive.
234
 Locks then unlocks the share mode lock. Client can decide to go directly
235
 to none even if a "break-to-level II" was sent.
236
****************************************************************************/
237
238
bool remove_oplock(files_struct *fsp)
239
0
{
240
0
  bool ret;
241
0
  struct share_mode_lock *lck;
242
243
0
  DBG_DEBUG("remove_oplock called for %s\n", fsp_str_dbg(fsp));
244
245
  /* Remove the oplock flag from the sharemode. */
246
0
  lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
247
0
  if (lck == NULL) {
248
0
    DBG_ERR("failed to lock share entry for "
249
0
       "file %s\n", fsp_str_dbg(fsp));
250
0
    return false;
251
0
  }
252
253
0
  ret = remove_share_oplock(lck, fsp);
254
0
  if (!ret) {
255
0
    struct file_id_buf buf;
256
257
0
    DBG_ERR("failed to remove share oplock for "
258
0
      "file %s, %s, %s\n",
259
0
      fsp_str_dbg(fsp), fsp_fnum_dbg(fsp),
260
0
      file_id_str_buf(fsp->file_id, &buf));
261
0
  }
262
0
  release_file_oplock(fsp);
263
264
0
  TALLOC_FREE(lck);
265
0
  return ret;
266
0
}
267
268
/*
269
 * Deal with a reply when a break-to-level II was sent.
270
 */
271
bool downgrade_oplock(files_struct *fsp)
272
0
{
273
0
  bool ret;
274
0
  struct share_mode_lock *lck;
275
276
0
  DEBUG(10, ("downgrade_oplock called for %s\n",
277
0
       fsp_str_dbg(fsp)));
278
279
0
  lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
280
0
  if (lck == NULL) {
281
0
    DEBUG(0,("downgrade_oplock: failed to lock share entry for "
282
0
       "file %s\n", fsp_str_dbg(fsp)));
283
0
    return False;
284
0
  }
285
0
  ret = downgrade_share_oplock(lck, fsp);
286
0
  if (!ret) {
287
0
    struct file_id_buf idbuf;
288
0
    DBG_ERR("failed to downgrade share oplock "
289
0
      "for file %s, %s, file_id %s\n",
290
0
      fsp_str_dbg(fsp),
291
0
      fsp_fnum_dbg(fsp),
292
0
      file_id_str_buf(fsp->file_id, &idbuf));
293
0
  }
294
0
  downgrade_file_oplock(fsp);
295
296
0
  TALLOC_FREE(lck);
297
0
  return ret;
298
0
}
299
300
static void lease_timeout_handler(struct tevent_context *ctx,
301
          struct tevent_timer *te,
302
          struct timeval now,
303
          void *private_data)
304
0
{
305
0
  struct fsp_lease *lease =
306
0
    talloc_get_type_abort(private_data,
307
0
    struct fsp_lease);
308
0
  struct files_struct *fsp;
309
0
  struct share_mode_lock *lck;
310
0
  uint16_t old_epoch = lease->lease.lease_epoch;
311
312
0
  fsp = file_find_one_fsp_from_lease_key(lease->sconn,
313
0
                 &lease->lease.lease_key);
314
0
  if (fsp == NULL) {
315
    /* race? */
316
0
    TALLOC_FREE(lease->timeout);
317
0
    return;
318
0
  }
319
320
  /*
321
   * Paranoia check: There can only be one fsp_lease per lease
322
   * key
323
   */
324
0
  SMB_ASSERT(fsp->lease == lease);
325
326
0
  lck = get_existing_share_mode_lock(
327
0
      talloc_tos(), fsp->file_id);
328
0
  if (lck == NULL) {
329
    /* race? */
330
0
    TALLOC_FREE(lease->timeout);
331
0
    return;
332
0
  }
333
334
0
  fsp_lease_update(fsp);
335
336
0
  if (lease->lease.lease_epoch != old_epoch) {
337
    /*
338
     * If the epoch changed we need to wait for
339
     * the next timeout to happen.
340
     */
341
0
    DEBUG(10, ("lease break timeout race (epoch) for file %s - ignoring\n",
342
0
         fsp_str_dbg(fsp)));
343
0
    TALLOC_FREE(lck);
344
0
    return;
345
0
  }
346
347
0
  if (!(lease->lease.lease_flags & SMB2_LEASE_FLAG_BREAK_IN_PROGRESS)) {
348
    /*
349
     * If the epoch changed we need to wait for
350
     * the next timeout to happen.
351
     */
352
0
    DEBUG(10, ("lease break timeout race (flags) for file %s - ignoring\n",
353
0
         fsp_str_dbg(fsp)));
354
0
    TALLOC_FREE(lck);
355
0
    return;
356
0
  }
357
358
0
  DEBUG(1, ("lease break timed out for file %s -- replying anyway\n",
359
0
      fsp_str_dbg(fsp)));
360
0
  (void)downgrade_lease(lease->sconn->client,
361
0
      1,
362
0
      &fsp->file_id,
363
0
      &lease->lease.lease_key,
364
0
      SMB2_LEASE_NONE);
365
366
0
  TALLOC_FREE(lck);
367
0
}
368
369
bool fsp_lease_update(struct files_struct *fsp)
370
0
{
371
0
  const struct GUID *client_guid = fsp_client_guid(fsp);
372
0
  struct fsp_lease *lease = fsp->lease;
373
0
  uint32_t current_state;
374
0
  bool breaking;
375
0
  uint16_t lease_version, epoch;
376
0
  NTSTATUS status;
377
378
0
  status = leases_db_get(client_guid,
379
0
             &lease->lease.lease_key,
380
0
             &fsp->file_id,
381
0
             &current_state,
382
0
             &breaking,
383
0
             NULL, /* breaking_to_requested */
384
0
             NULL, /* breaking_to_required */
385
0
             &lease_version,
386
0
             &epoch);
387
0
  if (!NT_STATUS_IS_OK(status)) {
388
0
    DBG_WARNING("Could not find lease entry: %s\n",
389
0
          nt_errstr(status));
390
0
    TALLOC_FREE(lease->timeout);
391
0
    lease->lease.lease_state = SMB2_LEASE_NONE;
392
0
    lease->lease.lease_epoch += 1;
393
0
    lease->lease.lease_flags = 0;
394
0
    return false;
395
0
  }
396
397
0
  DEBUG(10,("%s: refresh lease state\n", __func__));
398
399
  /* Ensure we're in sync with current lease state. */
400
0
  if (lease->lease.lease_epoch != epoch) {
401
0
    DEBUG(10,("%s: cancel outdated timeout\n", __func__));
402
0
    TALLOC_FREE(lease->timeout);
403
0
  }
404
0
  lease->lease.lease_epoch = epoch;
405
0
  lease->lease.lease_state = current_state;
406
407
0
  if (breaking) {
408
0
    lease->lease.lease_flags |= SMB2_LEASE_FLAG_BREAK_IN_PROGRESS;
409
410
0
    if (lease->timeout == NULL) {
411
0
      struct timeval t = timeval_current_ofs(OPLOCK_BREAK_TIMEOUT, 0);
412
413
0
      DEBUG(10,("%s: setup timeout handler\n", __func__));
414
415
0
      lease->timeout = tevent_add_timer(lease->sconn->ev_ctx,
416
0
                lease, t,
417
0
                lease_timeout_handler,
418
0
                lease);
419
0
      if (lease->timeout == NULL) {
420
0
        DEBUG(0, ("%s: Could not add lease timeout handler\n",
421
0
            __func__));
422
0
      }
423
0
    }
424
0
  } else {
425
0
    lease->lease.lease_flags &= ~SMB2_LEASE_FLAG_BREAK_IN_PROGRESS;
426
0
    TALLOC_FREE(lease->timeout);
427
0
  }
428
429
0
  return true;
430
0
}
431
432
struct downgrade_lease_additional_state {
433
  struct tevent_immediate *im;
434
  struct smbXsrv_client *client;
435
  uint32_t break_flags;
436
  struct smb2_lease_key lease_key;
437
  uint32_t break_from;
438
  uint32_t break_to;
439
  uint16_t new_epoch;
440
};
441
442
static void downgrade_lease_additional_trigger(struct tevent_context *ev,
443
                 struct tevent_immediate *im,
444
                 void *private_data)
445
0
{
446
0
  struct downgrade_lease_additional_state *state =
447
0
    talloc_get_type_abort(private_data,
448
0
    struct downgrade_lease_additional_state);
449
0
  NTSTATUS status;
450
451
0
  status = smbd_smb2_send_lease_break(state->client,
452
0
              state->new_epoch,
453
0
              state->break_flags,
454
0
              &state->lease_key,
455
0
              state->break_from,
456
0
              state->break_to);
457
0
  if (!NT_STATUS_IS_OK(status)) {
458
0
    smbd_server_disconnect_client(state->client,
459
0
                nt_errstr(status));
460
0
  }
461
0
  TALLOC_FREE(state);
462
0
}
463
464
struct fsps_lease_update_state {
465
  const struct file_id *id;
466
  const struct smb2_lease_key *key;
467
};
468
469
static struct files_struct *fsps_lease_update_fn(
470
  struct files_struct *fsp, void *private_data)
471
0
{
472
0
  struct fsps_lease_update_state *state =
473
0
    (struct fsps_lease_update_state *)private_data;
474
475
0
  if (fsp->oplock_type != LEASE_OPLOCK) {
476
0
    return NULL;
477
0
  }
478
0
  if (!smb2_lease_key_equal(&fsp->lease->lease.lease_key, state->key)) {
479
0
    return NULL;
480
0
  }
481
0
  if (!file_id_equal(&fsp->file_id, state->id)) {
482
0
    return NULL;
483
0
  }
484
485
0
  fsp_lease_update(fsp);
486
487
0
  return NULL;
488
0
}
489
490
static void fsps_lease_update(struct smbd_server_connection *sconn,
491
            const struct file_id *id,
492
            const struct smb2_lease_key *key)
493
0
{
494
0
  struct fsps_lease_update_state state = { .id = id, .key = key };
495
0
  files_forall(sconn, fsps_lease_update_fn, &state);
496
0
}
497
498
NTSTATUS downgrade_lease(struct smbXsrv_client *client,
499
       uint32_t num_file_ids,
500
       const struct file_id *ids,
501
       const struct smb2_lease_key *key,
502
       uint32_t lease_state)
503
0
{
504
0
  struct smbd_server_connection *sconn = client->sconn;
505
0
  const struct GUID *client_guid = NULL;
506
0
  struct share_mode_lock *lck;
507
0
  const struct file_id id = ids[0];
508
0
  uint32_t current_state, breaking_to_requested, breaking_to_required;
509
0
  bool breaking;
510
0
  uint16_t lease_version, epoch;
511
0
  NTSTATUS status;
512
0
  uint32_t i;
513
0
  struct file_id_buf idbuf;
514
515
0
  DBG_DEBUG("Downgrading %s to %"PRIu32"\n",
516
0
      file_id_str_buf(id, &idbuf),
517
0
      lease_state);
518
519
0
  lck = get_existing_share_mode_lock(talloc_tos(), id);
520
0
  if (lck == NULL) {
521
0
    return NT_STATUS_OBJECT_NAME_NOT_FOUND;
522
0
  }
523
524
0
  client_guid = &sconn->client->global->client_guid;
525
526
0
  status = leases_db_get(client_guid,
527
0
             key,
528
0
             &id,
529
0
             &current_state,
530
0
             &breaking,
531
0
             &breaking_to_requested,
532
0
             &breaking_to_required,
533
0
             &lease_version,
534
0
             &epoch);
535
0
  if (!NT_STATUS_IS_OK(status)) {
536
0
    DBG_WARNING("leases_db_get returned %s\n",
537
0
          nt_errstr(status));
538
0
    TALLOC_FREE(lck);
539
0
    return status;
540
0
  }
541
542
0
  if (!breaking) {
543
0
    DBG_WARNING("Attempt to break from %"PRIu32" to %"PRIu32" - "
544
0
          "but we're not in breaking state\n",
545
0
          current_state, lease_state);
546
0
    TALLOC_FREE(lck);
547
0
    return NT_STATUS_UNSUCCESSFUL;
548
0
  }
549
550
  /*
551
   * Can't upgrade anything: breaking_to_requested (and current_state)
552
   * must be a strict bitwise superset of new_lease_state
553
   */
554
0
  if ((lease_state & breaking_to_requested) != lease_state) {
555
0
    DBG_WARNING("Attempt to upgrade from %"PRIu32" to %"PRIu32" "
556
0
          "- expected %"PRIu32"\n",
557
0
          current_state, lease_state,
558
0
          breaking_to_requested);
559
0
    TALLOC_FREE(lck);
560
0
    return NT_STATUS_REQUEST_NOT_ACCEPTED;
561
0
  }
562
563
0
  if (current_state != lease_state) {
564
0
    current_state = lease_state;
565
0
  }
566
567
0
  status = NT_STATUS_OK;
568
569
0
  if ((lease_state & ~breaking_to_required) != 0) {
570
0
    struct downgrade_lease_additional_state *state;
571
572
0
    DBG_INFO("lease state %"PRIu32" not fully broken from "
573
0
       "%"PRIu32" to %"PRIu32"\n",
574
0
       lease_state,
575
0
       current_state,
576
0
       breaking_to_required);
577
578
0
    breaking_to_requested = breaking_to_required;
579
580
0
    if (current_state & (SMB2_LEASE_WRITE|SMB2_LEASE_HANDLE)) {
581
      /*
582
       * Here we break in steps, as windows does
583
       * see the breaking3 and v2_breaking3 tests.
584
       */
585
0
      breaking_to_requested |= SMB2_LEASE_READ;
586
0
    }
587
588
0
    state = talloc_zero(client,
589
0
            struct downgrade_lease_additional_state);
590
0
    if (state == NULL) {
591
0
      TALLOC_FREE(lck);
592
0
      return NT_STATUS_NO_MEMORY;
593
0
    }
594
595
0
    state->im = tevent_create_immediate(state);
596
0
    if (state->im == NULL) {
597
0
      TALLOC_FREE(state);
598
0
      TALLOC_FREE(lck);
599
0
      return NT_STATUS_NO_MEMORY;
600
0
    }
601
602
0
    state->client = client;
603
0
    state->lease_key = *key;
604
0
    state->break_from = current_state;
605
0
    state->break_to = breaking_to_requested;
606
0
    if (lease_version > 1) {
607
0
      state->new_epoch = epoch;
608
0
    }
609
610
0
    if (current_state & (SMB2_LEASE_WRITE|SMB2_LEASE_HANDLE)) {
611
0
      state->break_flags =
612
0
        SMB2_NOTIFY_BREAK_LEASE_FLAG_ACK_REQUIRED;
613
0
    } else {
614
      /*
615
       * This is an async break without
616
       * SMB2_NOTIFY_BREAK_LEASE_FLAG_ACK_REQUIRED
617
       *
618
       * we need to store NONE state in the
619
       * database.
620
       */
621
0
      current_state = 0;
622
0
      breaking_to_requested = 0;
623
0
      breaking_to_required = 0;
624
0
      breaking = false;
625
626
0
      {
627
0
        NTSTATUS set_status;
628
629
0
        set_status = leases_db_set(
630
0
          &sconn->client->global->client_guid,
631
0
          key,
632
0
          current_state,
633
0
          breaking,
634
0
          breaking_to_requested,
635
0
          breaking_to_required,
636
0
          lease_version,
637
0
          epoch);
638
639
0
        if (!NT_STATUS_IS_OK(set_status)) {
640
0
          DBG_DEBUG("leases_db_set failed: %s\n",
641
0
              nt_errstr(set_status));
642
0
          return set_status;
643
0
        }
644
0
      }
645
0
    }
646
647
0
    tevent_schedule_immediate(state->im,
648
0
            client->raw_ev_ctx,
649
0
            downgrade_lease_additional_trigger,
650
0
            state);
651
652
0
    status = NT_STATUS_OPLOCK_BREAK_IN_PROGRESS;
653
0
  } else {
654
0
    DBG_DEBUG("breaking from %"PRIu32" to %"PRIu32" - "
655
0
        "expected %"PRIu32"\n",
656
0
        current_state,
657
0
        lease_state,
658
0
        breaking_to_requested);
659
660
0
    breaking_to_requested = 0;
661
0
    breaking_to_required = 0;
662
0
    breaking = false;
663
0
  }
664
665
0
  {
666
0
    NTSTATUS set_status;
667
668
0
    set_status = leases_db_set(
669
0
      client_guid,
670
0
      key,
671
0
      current_state,
672
0
      breaking,
673
0
      breaking_to_requested,
674
0
      breaking_to_required,
675
0
      lease_version,
676
0
      epoch);
677
678
0
    if (!NT_STATUS_IS_OK(set_status)) {
679
0
      DBG_DEBUG("leases_db_set failed: %s\n",
680
0
          nt_errstr(set_status));
681
0
      TALLOC_FREE(lck);
682
0
      return set_status;
683
0
    }
684
0
  }
685
686
0
  DBG_DEBUG("Downgrading %s to %"PRIu32" => %s\n",
687
0
      file_id_str_buf(id, &idbuf),
688
0
      lease_state,
689
0
      nt_errstr(status));
690
691
0
  share_mode_wakeup_waiters(id);
692
693
0
  fsps_lease_update(sconn, &id, key);
694
695
0
  TALLOC_FREE(lck);
696
697
0
  DBG_DEBUG("Downgrading %s to %"PRIu32" => %s\n",
698
0
      file_id_str_buf(id, &idbuf),
699
0
      lease_state,
700
0
      nt_errstr(status));
701
702
  /*
703
   * Dynamic share case. Ensure other opens are copies.
704
   * This will only be breaking to NONE.
705
   */
706
707
0
  for (i = 1; i < num_file_ids; i++) {
708
0
    lck = get_existing_share_mode_lock(talloc_tos(), ids[i]);
709
0
    if (lck == NULL) {
710
0
      return NT_STATUS_OBJECT_NAME_NOT_FOUND;
711
0
    }
712
713
0
    fsps_lease_update(sconn, &ids[i], key);
714
715
0
    DBG_DEBUG("Downgrading %s to %"PRIu32" => %s\n",
716
0
        file_id_str_buf(ids[i], &idbuf),
717
0
        lease_state,
718
0
        nt_errstr(status));
719
720
0
    TALLOC_FREE(lck);
721
0
  }
722
723
0
  return status;
724
0
}
725
726
#define SMB1_BREAK_MESSAGE_LENGTH (smb_size + 8*2)
727
728
/****************************************************************************
729
 Function to do the waiting before sending a local break.
730
****************************************************************************/
731
732
static void wait_before_sending_break(void)
733
0
{
734
0
  long wait_time = (long)lp_oplock_break_wait_time();
735
736
0
  if (wait_time) {
737
0
    smb_msleep(wait_time);
738
0
  }
739
0
}
740
741
/****************************************************************************
742
 Ensure that we have a valid oplock.
743
****************************************************************************/
744
745
static files_struct *initial_break_processing(
746
  struct smbd_server_connection *sconn, struct file_id id,
747
  unsigned long file_id)
748
0
{
749
0
  files_struct *fsp = NULL;
750
0
  struct file_id_buf idbuf;
751
752
0
  DBG_NOTICE("called for %s/%u\n"
753
0
       "Current oplocks_open (exclusive = %d, levelII = %d)\n",
754
0
       file_id_str_buf(id, &idbuf),
755
0
       (int)file_id,
756
0
       sconn->oplocks.exclusive_open,
757
0
       sconn->oplocks.level_II_open);
758
759
  /*
760
   * We need to search the file open table for the
761
   * entry containing this dev and inode, and ensure
762
   * we have an oplock on it.
763
   */
764
765
0
  fsp = file_find_dif(sconn, id, file_id);
766
767
0
  if(fsp == NULL) {
768
    /* The file could have been closed in the meantime - return success. */
769
0
    DBG_NOTICE("cannot find open file "
770
0
         "with file_id %s gen_id = %lu, allowing break to "
771
0
         "succeed.\n",
772
0
         file_id_str_buf(id, &idbuf),
773
0
         file_id);
774
0
    return NULL;
775
0
  }
776
777
  /* Ensure we have an oplock on the file */
778
779
  /*
780
   * There is a potential race condition in that an oplock could
781
   * have been broken due to another udp request, and yet there are
782
   * still oplock break messages being sent in the udp message
783
   * queue for this file. So return true if we don't have an oplock,
784
   * as we may have just freed it.
785
   */
786
787
0
  if(fsp->oplock_type == NO_OPLOCK) {
788
0
    DBG_NOTICE("file %s (file_id = %s gen_id = %"PRIu64") "
789
0
         "has no oplock. "
790
0
         "Allowing break to succeed regardless.\n",
791
0
         fsp_str_dbg(fsp),
792
0
         file_id_str_buf(id, &idbuf),
793
0
         fh_get_gen_id(fsp->fh));
794
0
    return NULL;
795
0
  }
796
797
0
  return fsp;
798
0
}
799
800
static void oplock_timeout_handler(struct tevent_context *ctx,
801
           struct tevent_timer *te,
802
           struct timeval now,
803
           void *private_data)
804
0
{
805
0
  files_struct *fsp = (files_struct *)private_data;
806
807
0
  SMB_ASSERT(fsp->sent_oplock_break != NO_BREAK_SENT);
808
809
  /* Remove the timed event handler. */
810
0
  TALLOC_FREE(fsp->oplock_timeout);
811
0
  DEBUG(0, ("Oplock break failed for file %s -- replying anyway\n",
812
0
      fsp_str_dbg(fsp)));
813
0
  remove_oplock(fsp);
814
0
}
815
816
/*******************************************************************
817
 Add a timeout handler waiting for the client reply.
818
*******************************************************************/
819
820
static void add_oplock_timeout_handler(files_struct *fsp)
821
0
{
822
0
  if (fsp->oplock_timeout != NULL) {
823
0
    DEBUG(0, ("Logic problem -- have an oplock event hanging "
824
0
        "around\n"));
825
0
  }
826
827
0
  fsp->oplock_timeout =
828
0
    tevent_add_timer(fsp->conn->sconn->ev_ctx, fsp,
829
0
         timeval_current_ofs(OPLOCK_BREAK_TIMEOUT, 0),
830
0
         oplock_timeout_handler, fsp);
831
832
0
  if (fsp->oplock_timeout == NULL) {
833
0
    DEBUG(0, ("Could not add oplock timeout handler\n"));
834
0
  }
835
0
}
836
837
/*******************************************************************
838
 This handles the generic oplock break message from another smbd.
839
*******************************************************************/
840
841
static void process_oplock_break_message(struct messaging_context *msg_ctx,
842
           void *private_data,
843
           uint32_t msg_type,
844
           struct server_id src,
845
           DATA_BLOB *data)
846
0
{
847
0
  struct oplock_break_message msg;
848
0
  enum ndr_err_code ndr_err;
849
0
  files_struct *fsp;
850
0
  bool use_kernel;
851
0
  struct smbd_server_connection *sconn =
852
0
    talloc_get_type_abort(private_data,
853
0
    struct smbd_server_connection);
854
0
  struct server_id self = messaging_server_id(sconn->msg_ctx);
855
0
  struct kernel_oplocks *koplocks = sconn->oplocks.kernel_ops;
856
0
  uint16_t break_from;
857
0
  uint16_t break_to;
858
0
  bool break_needed = true;
859
860
0
  smb_vfs_assert_allowed();
861
862
0
  ndr_err = ndr_pull_struct_blob_all_noalloc(
863
0
    data, &msg, (ndr_pull_flags_fn_t)ndr_pull_oplock_break_message);
864
0
  if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
865
0
    DBG_DEBUG("ndr_pull_oplock_break_message failed: %s\n",
866
0
        ndr_errstr(ndr_err));
867
0
    return;
868
0
  }
869
0
  if (DEBUGLEVEL >= 10) {
870
0
    struct server_id_buf buf;
871
0
    DBG_DEBUG("Got break message from %s\n",
872
0
        server_id_str_buf(src, &buf));
873
0
    NDR_PRINT_DEBUG(oplock_break_message, &msg);
874
0
  }
875
876
0
  break_to = msg.break_to;
877
0
  fsp = initial_break_processing(sconn, msg.id, msg.share_file_id);
878
879
0
  if (fsp == NULL) {
880
    /* We hit a race here. Break messages are sent, and before we
881
     * get to process this message, we have closed the file. */
882
0
    DEBUG(3, ("Did not find fsp\n"));
883
0
    return;
884
0
  }
885
886
0
  break_from = fsp_lease_type(fsp);
887
888
0
  if (fsp->oplock_type != LEASE_OPLOCK) {
889
0
    if (fsp->sent_oplock_break != NO_BREAK_SENT) {
890
      /*
891
       * Nothing to do anymore
892
       */
893
0
      DEBUG(10, ("fsp->sent_oplock_break = %d\n",
894
0
           fsp->sent_oplock_break));
895
0
      return;
896
0
    }
897
0
  }
898
899
0
  if (!(global_client_caps & CAP_LEVEL_II_OPLOCKS)) {
900
0
    DEBUG(10, ("client_caps without level2 oplocks\n"));
901
0
    break_to &= ~SMB2_LEASE_READ;
902
0
  }
903
904
0
  use_kernel = lp_kernel_oplocks(SNUM(fsp->conn)) &&
905
0
      (koplocks != NULL);
906
0
  if (use_kernel) {
907
0
    DEBUG(10, ("Kernel oplocks don't allow level2\n"));
908
0
    break_to &= ~SMB2_LEASE_READ;
909
0
  }
910
911
0
  if (!lp_level2_oplocks(SNUM(fsp->conn))) {
912
0
    DEBUG(10, ("no level2 oplocks by config\n"));
913
0
    break_to &= ~SMB2_LEASE_READ;
914
0
  }
915
916
0
  if (fsp->oplock_type == LEASE_OPLOCK) {
917
0
    const struct GUID *client_guid = fsp_client_guid(fsp);
918
0
    struct share_mode_lock *lck;
919
0
    uint32_t current_state;
920
0
    uint32_t breaking_to_requested, breaking_to_required;
921
0
    bool breaking;
922
0
    uint16_t lease_version, epoch;
923
0
    NTSTATUS status;
924
925
0
    lck = get_existing_share_mode_lock(
926
0
      talloc_tos(), fsp->file_id);
927
0
    if (lck == NULL) {
928
      /*
929
       * We hit a race here. Break messages are sent, and
930
       * before we get to process this message, we have closed
931
       * the file.
932
       */
933
0
      DEBUG(3, ("Did not find share_mode\n"));
934
0
      return;
935
0
    }
936
937
0
    status = leases_db_get(client_guid,
938
0
               &fsp->lease->lease.lease_key,
939
0
               &fsp->file_id,
940
0
               &current_state,
941
0
               &breaking,
942
0
               &breaking_to_requested,
943
0
               &breaking_to_required,
944
0
               &lease_version,
945
0
               &epoch);
946
0
    if (!NT_STATUS_IS_OK(status)) {
947
0
      DBG_WARNING("leases_db_get returned %s\n",
948
0
            nt_errstr(status));
949
0
      TALLOC_FREE(lck);
950
0
      return;
951
0
    }
952
953
0
    break_from = current_state;
954
0
    break_to &= current_state;
955
956
0
    if (breaking) {
957
0
      break_to &= breaking_to_required;
958
0
      if (breaking_to_required != break_to) {
959
        /*
960
         * Note we don't increment the epoch
961
         * here, which might be a bug in
962
         * Windows too...
963
         */
964
0
        breaking_to_required = break_to;
965
0
      }
966
0
      break_needed = false;
967
0
    } else if (current_state == break_to) {
968
0
      break_needed = false;
969
0
    } else if (current_state == SMB2_LEASE_READ) {
970
0
      current_state = SMB2_LEASE_NONE;
971
      /* Need to increment the epoch */
972
0
      epoch += 1;
973
0
    } else {
974
0
      breaking = true;
975
0
      breaking_to_required = break_to;
976
0
      breaking_to_requested = break_to;
977
      /* Need to increment the epoch */
978
0
      epoch += 1;
979
0
    }
980
981
0
    {
982
0
      NTSTATUS set_status;
983
984
0
      set_status = leases_db_set(
985
0
        client_guid,
986
0
        &fsp->lease->lease.lease_key,
987
0
        current_state,
988
0
        breaking,
989
0
        breaking_to_requested,
990
0
        breaking_to_required,
991
0
        lease_version,
992
0
        epoch);
993
994
0
      if (!NT_STATUS_IS_OK(set_status)) {
995
0
        DBG_DEBUG("leases_db_set failed: %s\n",
996
0
            nt_errstr(set_status));
997
0
        return;
998
0
      }
999
0
    }
1000
1001
    /* Ensure we're in sync with current lease state. */
1002
0
    fsp_lease_update(fsp);
1003
1004
0
    TALLOC_FREE(lck);
1005
0
  }
1006
1007
0
  if (!break_needed) {
1008
0
    DEBUG(10,("%s: skip break\n", __func__));
1009
0
    return;
1010
0
  }
1011
1012
0
  if (break_from == SMB2_LEASE_NONE) {
1013
0
    struct file_id_buf idbuf;
1014
0
    DBG_NOTICE("Already downgraded oplock to none on %s: %s\n",
1015
0
         file_id_str_buf(fsp->file_id, &idbuf),
1016
0
         fsp_str_dbg(fsp));
1017
0
    return;
1018
0
  }
1019
1020
0
  DEBUG(10, ("break_from=%u, break_to=%u\n",
1021
0
       (unsigned)break_from, (unsigned)break_to));
1022
1023
0
  if (break_from == break_to) {
1024
0
    struct file_id_buf idbuf;
1025
0
    DBG_NOTICE("Already downgraded oplock to %u on %s: %s\n",
1026
0
         (unsigned)break_to,
1027
0
         file_id_str_buf(fsp->file_id, &idbuf),
1028
0
         fsp_str_dbg(fsp));
1029
0
    return;
1030
0
  }
1031
1032
  /* Need to wait before sending a break
1033
     message if we sent ourselves this message. */
1034
0
  if (server_id_equal(&self, &src)) {
1035
0
    wait_before_sending_break();
1036
0
  }
1037
1038
0
#if defined(WITH_SMB1SERVER)
1039
0
  if (conn_using_smb2(sconn)) {
1040
0
#endif
1041
0
    send_break_message_smb2(fsp, break_from, break_to);
1042
0
#if defined(WITH_SMB1SERVER)
1043
0
  } else {
1044
0
    send_break_message_smb1(fsp, (break_to & SMB2_LEASE_READ) ?
1045
0
          OPLOCKLEVEL_II : OPLOCKLEVEL_NONE);
1046
0
  }
1047
0
#endif
1048
1049
0
  if ((break_from == SMB2_LEASE_READ) &&
1050
0
      (break_to == SMB2_LEASE_NONE)) {
1051
    /*
1052
     * This is an async break without a reply and thus no timeout
1053
     *
1054
     * leases are handled above.
1055
     */
1056
0
    if (fsp->oplock_type != LEASE_OPLOCK) {
1057
0
      remove_oplock(fsp);
1058
0
    }
1059
0
    return;
1060
0
  }
1061
0
  if (fsp->oplock_type == LEASE_OPLOCK) {
1062
0
    return;
1063
0
  }
1064
1065
0
  fsp->sent_oplock_break = (break_to & SMB2_LEASE_READ) ?
1066
0
    LEVEL_II_BREAK_SENT:BREAK_TO_NONE_SENT;
1067
1068
0
  add_oplock_timeout_handler(fsp);
1069
0
}
1070
1071
/*******************************************************************
1072
 This handles the kernel oplock break message.
1073
*******************************************************************/
1074
1075
static void process_kernel_oplock_break(struct messaging_context *msg_ctx,
1076
          void *private_data,
1077
          uint32_t msg_type,
1078
          struct server_id src,
1079
          DATA_BLOB *data)
1080
0
{
1081
0
  struct oplock_break_message msg;
1082
0
  enum ndr_err_code ndr_err;
1083
0
  struct file_id_buf idbuf;
1084
0
  files_struct *fsp;
1085
0
  struct smbd_server_connection *sconn =
1086
0
    talloc_get_type_abort(private_data,
1087
0
    struct smbd_server_connection);
1088
0
  struct server_id_buf tmp;
1089
1090
0
  ndr_err = ndr_pull_struct_blob_all_noalloc(
1091
0
    data,
1092
0
    &msg,
1093
0
    (ndr_pull_flags_fn_t)ndr_pull_oplock_break_message);
1094
0
  if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1095
0
    DBG_DEBUG("ndr_pull_oplock_break_message failed: %s\n",
1096
0
        ndr_errstr(ndr_err));
1097
0
    return;
1098
0
  }
1099
1100
0
  DBG_DEBUG("Got kernel oplock break message from pid %s: %s/%u\n",
1101
0
      server_id_str_buf(src, &tmp),
1102
0
      file_id_str_buf(msg.id, &idbuf),
1103
0
      (unsigned int)msg.share_file_id);
1104
1105
0
  fsp = initial_break_processing(sconn, msg.id, msg.share_file_id);
1106
1107
0
  if (fsp == NULL) {
1108
0
    DEBUG(3, ("Got a kernel oplock break message for a file "
1109
0
        "I don't know about\n"));
1110
0
    return;
1111
0
  }
1112
1113
0
  if (fsp->sent_oplock_break != NO_BREAK_SENT) {
1114
    /* This is ok, kernel oplocks come in completely async */
1115
0
    DEBUG(3, ("Got a kernel oplock request while waiting for a "
1116
0
        "break reply\n"));
1117
0
    return;
1118
0
  }
1119
1120
0
#if defined(WITH_SMB1SERVER)
1121
0
  if (conn_using_smb2(sconn)) {
1122
0
#endif
1123
0
    send_break_message_smb2(fsp, 0, OPLOCKLEVEL_NONE);
1124
0
#if defined(WITH_SMB1SERVER)
1125
0
  } else {
1126
0
    send_break_message_smb1(fsp, OPLOCKLEVEL_NONE);
1127
0
  }
1128
0
#endif
1129
1130
0
  fsp->sent_oplock_break = BREAK_TO_NONE_SENT;
1131
1132
0
  add_oplock_timeout_handler(fsp);
1133
0
}
1134
1135
static void send_break_to_none(struct messaging_context *msg_ctx,
1136
             const struct file_id *id,
1137
             const struct share_mode_entry *e)
1138
0
{
1139
0
  NTSTATUS status;
1140
0
  status = send_break_message(msg_ctx, id, e, OPLOCK_NONE);
1141
0
  if (!NT_STATUS_IS_OK(status)) {
1142
0
    DBG_DEBUG("send_break_message failed: %s\n",
1143
0
        nt_errstr(status));
1144
0
  }
1145
0
}
1146
struct break_to_none_state {
1147
  struct smbd_server_connection *sconn;
1148
  struct file_id id;
1149
  struct smb2_lease_key lease_key;
1150
  struct GUID client_guid;
1151
  size_t num_read_leases;
1152
  uint32_t total_lease_types;
1153
};
1154
1155
static bool do_break_lease_to_none(struct share_mode_entry *e,
1156
           void *private_data)
1157
0
{
1158
0
  struct break_to_none_state *state = private_data;
1159
0
  uint32_t current_state = 0;
1160
0
  bool our_own;
1161
0
  NTSTATUS status;
1162
1163
0
  DBG_DEBUG("lease_key=%"PRIu64"/%"PRIu64"\n",
1164
0
      e->lease_key.data[0],
1165
0
      e->lease_key.data[1]);
1166
1167
0
  status = leases_db_get(&e->client_guid,
1168
0
             &e->lease_key,
1169
0
             &state->id,
1170
0
             &current_state,
1171
0
             NULL, /* breaking */
1172
0
             NULL, /* breaking_to_requested */
1173
0
             NULL, /* breaking_to_required */
1174
0
             NULL, /* lease_version */
1175
0
             NULL); /* epoch */
1176
0
  if (!NT_STATUS_IS_OK(status)) {
1177
0
    DBG_WARNING("leases_db_get failed: %s\n",
1178
0
          nt_errstr(status));
1179
0
    return false;
1180
0
  }
1181
1182
0
  state->total_lease_types |= current_state;
1183
1184
0
  if ((current_state & SMB2_LEASE_READ) == 0) {
1185
0
    return false;
1186
0
  }
1187
1188
0
  state->num_read_leases += 1;
1189
1190
0
  our_own = smb2_lease_equal(&state->client_guid,
1191
0
           &state->lease_key,
1192
0
           &e->client_guid,
1193
0
           &e->lease_key);
1194
0
  if (our_own) {
1195
0
    DEBUG(10, ("Don't break our own lease\n"));
1196
0
    return false;
1197
0
  }
1198
1199
0
  DBG_DEBUG("Breaking %"PRIu64"/%"PRIu64" to none\n",
1200
0
      e->lease_key.data[0],
1201
0
      e->lease_key.data[1]);
1202
1203
0
  send_break_to_none(state->sconn->msg_ctx, &state->id, e);
1204
1205
0
  return false;
1206
0
}
1207
1208
static bool do_break_oplock_to_none(struct share_mode_entry *e,
1209
            bool *modified,
1210
            void *private_data)
1211
0
{
1212
0
  struct break_to_none_state *state = private_data;
1213
1214
0
  if (e->op_type == LEASE_OPLOCK) {
1215
    /*
1216
     * Already being taken care of
1217
     */
1218
0
    return false;
1219
0
  }
1220
1221
  /*
1222
   * As there could have been multiple writes waiting at the
1223
   * lock_share_entry gate we may not be the first to
1224
   * enter. Hence the state of the op_types in the share mode
1225
   * entries may be partly NO_OPLOCK and partly LEVEL_II
1226
   * oplock. It will do no harm to re-send break messages to
1227
   * those smbd's that are still waiting their turn to remove
1228
   * their LEVEL_II state, and also no harm to ignore existing
1229
   * NO_OPLOCK states. JRA.
1230
   */
1231
1232
0
  DBG_DEBUG("e->op_type == %d\n", e->op_type);
1233
1234
0
  state->total_lease_types |= map_oplock_to_lease_type(e->op_type);
1235
1236
0
  if (e->op_type == NO_OPLOCK) {
1237
0
    return false;
1238
0
  }
1239
1240
0
  state->num_read_leases += 1;
1241
1242
  /* Paranoia .... */
1243
0
  SMB_ASSERT(!EXCLUSIVE_OPLOCK_TYPE(e->op_type));
1244
1245
0
  send_break_to_none(state->sconn->msg_ctx, &state->id, e);
1246
1247
0
  return false;
1248
0
}
1249
1250
struct dirlease_break_state {
1251
  struct smbd_server_connection *sconn;
1252
  struct file_id file_id;
1253
  struct smb2_lease_key parent_lease_key;
1254
  uint32_t total_lease_types;
1255
};
1256
1257
static bool do_dirlease_break_to_none(struct share_mode_entry *e,
1258
              void *private_data)
1259
0
{
1260
0
  struct dirlease_break_state *state = private_data;
1261
0
  uint32_t current_state = 0;
1262
0
  NTSTATUS status;
1263
1264
0
  DBG_DEBUG("lease_key=%"PRIu64"/%"PRIu64"\n",
1265
0
      e->lease_key.data[0],
1266
0
      e->lease_key.data[1]);
1267
1268
0
  status = leases_db_get(&e->client_guid,
1269
0
             &e->lease_key,
1270
0
             &state->file_id,
1271
0
             &current_state,
1272
0
             NULL, /* breaking */
1273
0
             NULL, /* breaking_to_requested */
1274
0
             NULL, /* breaking_to_required */
1275
0
             NULL, /* lease_version */
1276
0
             NULL); /* epoch */
1277
0
  if (!NT_STATUS_IS_OK(status)) {
1278
0
    DBG_WARNING("leases_db_get failed: %s\n",
1279
0
          nt_errstr(status));
1280
0
    return false;
1281
0
  }
1282
1283
0
  if (share_entry_stale_pid(e)) {
1284
0
    return false;
1285
0
  }
1286
1287
0
  state->total_lease_types |= current_state;
1288
1289
0
  if (smb2_lease_key_equal(&state->parent_lease_key, &e->lease_key)) {
1290
0
    return false;
1291
0
  }
1292
1293
0
  if ((current_state & (SMB2_LEASE_READ | SMB2_LEASE_HANDLE)) == 0) {
1294
0
    return false;
1295
0
  }
1296
1297
0
  DBG_DEBUG("Breaking %"PRIu64"/%"PRIu64" to none\n",
1298
0
      e->lease_key.data[0],
1299
0
      e->lease_key.data[1]);
1300
1301
0
  send_break_to_none(state->sconn->msg_ctx, &state->file_id, e);
1302
0
  return false;
1303
0
}
1304
1305
void contend_dirleases(struct connection_struct *conn,
1306
           const struct smb_filename *smb_fname,
1307
           const struct smb2_lease *lease)
1308
0
{
1309
0
  struct dirlease_break_state state = {
1310
0
    .sconn = conn->sconn,
1311
0
  };
1312
0
  struct share_mode_lock *lck = NULL;
1313
0
  struct smb_filename *parent_fname = NULL;
1314
0
  uint32_t access_mask, share_mode;
1315
0
  NTSTATUS status;
1316
0
  int ret;
1317
0
  bool ok;
1318
1319
0
  if (lease != NULL) {
1320
0
    DBG_DEBUG("Parent leasekey %"PRIx64"/%"PRIx64"\n",
1321
0
        lease->parent_lease_key.data[0],
1322
0
        lease->parent_lease_key.data[1]);
1323
0
    state.parent_lease_key = lease->parent_lease_key;
1324
0
  }
1325
1326
0
  status = SMB_VFS_PARENT_PATHNAME(conn,
1327
0
           talloc_tos(),
1328
0
           smb_fname,
1329
0
           &parent_fname,
1330
0
           NULL);
1331
0
  if (!NT_STATUS_IS_OK(status)) {
1332
0
    DBG_ERR("parent_smb_fname() for [%s] failed: %s\n",
1333
0
      smb_fname_str_dbg(smb_fname), strerror(errno));
1334
0
    return;
1335
0
  }
1336
1337
0
  ret = SMB_VFS_STAT(conn, parent_fname);
1338
0
  if (ret != 0) {
1339
0
    struct smb_filename *cwd = SMB_VFS_GETWD(conn, talloc_tos());
1340
1341
0
    DBG_ERR("Trigger [conn: %s] [smb_fname: %s] cwd [%s], "
1342
0
      "failed to stat parent [%s]: %s\n",
1343
0
      conn->connectpath,
1344
0
      smb_fname_str_dbg(smb_fname),
1345
0
      (cwd != NULL) ? cwd->base_name : "",
1346
0
      smb_fname_str_dbg(parent_fname),
1347
0
      strerror(errno));
1348
0
    TALLOC_FREE(parent_fname);
1349
0
    TALLOC_FREE(cwd);
1350
0
    return;
1351
0
  }
1352
1353
0
  state.file_id = vfs_file_id_from_sbuf(conn, &parent_fname->st);
1354
0
  TALLOC_FREE(parent_fname);
1355
1356
0
  lck = get_existing_share_mode_lock(talloc_tos(), state.file_id);
1357
0
  if (lck == NULL) {
1358
    /*
1359
     * No sharemode db entry -> no leases.
1360
     */
1361
0
    return;
1362
0
  }
1363
1364
0
  ok = share_mode_forall_leases(lck, do_dirlease_break_to_none, &state);
1365
0
  if (!ok) {
1366
0
    DBG_WARNING("share_mode_forall_leases failed\n");
1367
0
  }
1368
1369
  /*
1370
   * While we're at it, update lease type.
1371
   */
1372
0
  share_mode_flags_get(lck,
1373
0
           &access_mask,
1374
0
           &share_mode,
1375
0
           NULL);
1376
0
  share_mode_flags_set(lck,
1377
0
           access_mask,
1378
0
           share_mode,
1379
0
           state.total_lease_types,
1380
0
           NULL);
1381
1382
0
  TALLOC_FREE(lck);
1383
0
}
1384
1385
/****************************************************************************
1386
 This function is called on any file modification or lock request. If a file
1387
 is level 2 oplocked then it must tell all other level 2 holders to break to
1388
 none.
1389
****************************************************************************/
1390
1391
static void contend_level2_oplocks_begin_default(files_struct *fsp,
1392
                enum level2_contention_type type)
1393
0
{
1394
0
  struct break_to_none_state state = {
1395
0
    .sconn = fsp->conn->sconn, .id = fsp->file_id,
1396
0
  };
1397
0
  struct share_mode_lock *lck = NULL;
1398
0
  uint32_t fsp_lease = fsp_lease_type(fsp);
1399
0
  bool ok, has_read_lease;
1400
1401
  /*
1402
   * If this file is level II oplocked then we need
1403
   * to grab the shared memory lock and inform all
1404
   * other files with a level II lock that they need
1405
   * to flush their read caches. We keep the lock over
1406
   * the shared memory area whilst doing this.
1407
   */
1408
1409
0
  if (fsp_lease & SMB2_LEASE_WRITE) {
1410
    /*
1411
     * There can't be any level2 oplocks, we're alone.
1412
     */
1413
0
    return;
1414
0
  }
1415
1416
0
  has_read_lease = file_has_read_lease(fsp);
1417
0
  if (!has_read_lease) {
1418
0
    DEBUG(10, ("No read oplocks around\n"));
1419
0
    return;
1420
0
  }
1421
1422
0
  if (fsp->oplock_type == LEASE_OPLOCK) {
1423
0
    state.client_guid = *fsp_client_guid(fsp);
1424
0
    state.lease_key = fsp->lease->lease.lease_key;
1425
0
    DEBUG(10, ("Breaking through lease key %"PRIu64"/%"PRIu64"\n",
1426
0
         state.lease_key.data[0],
1427
0
         state.lease_key.data[1]));
1428
0
  }
1429
1430
0
  lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
1431
0
  if (lck == NULL) {
1432
0
    struct file_id_buf idbuf;
1433
0
    DBG_WARNING("failed to lock share mode entry for file %s.\n",
1434
0
          file_id_str_buf(state.id, &idbuf));
1435
0
    return;
1436
0
  }
1437
1438
  /*
1439
   * Walk leases and oplocks separately: We have to send one break per
1440
   * lease. If we have multiple share_mode_entry having a common lease,
1441
   * we would break the lease twice if we don't walk the leases list
1442
   * separately.
1443
   */
1444
1445
0
  ok = share_mode_forall_leases(lck, do_break_lease_to_none, &state);
1446
0
  if (!ok) {
1447
0
    DBG_WARNING("share_mode_forall_leases failed\n");
1448
0
  }
1449
1450
0
  ok = share_mode_forall_entries(lck, do_break_oplock_to_none, &state);
1451
0
  if (!ok) {
1452
0
    DBG_WARNING("share_mode_forall_entries failed\n");
1453
0
  }
1454
1455
0
  {
1456
    /*
1457
     * Lazy update here. It might be that all leases
1458
     * have gone in the meantime.
1459
     */
1460
0
    uint32_t acc, sh, ls;
1461
0
    share_mode_flags_get(lck, &acc, &sh, &ls);
1462
0
    ls = state.total_lease_types;
1463
0
    share_mode_flags_set(lck, acc, sh, ls, NULL);
1464
0
  }
1465
1466
0
  TALLOC_FREE(lck);
1467
0
}
1468
1469
void smbd_contend_level2_oplocks_begin(files_struct *fsp,
1470
          enum level2_contention_type type)
1471
0
{
1472
0
  contend_level2_oplocks_begin_default(fsp, type);
1473
0
}
1474
1475
void smbd_contend_level2_oplocks_end(files_struct *fsp,
1476
        enum level2_contention_type type)
1477
0
{
1478
0
  return;
1479
0
}
1480
1481
/****************************************************************************
1482
 Setup oplocks for this process.
1483
****************************************************************************/
1484
1485
bool init_oplocks(struct smbd_server_connection *sconn)
1486
0
{
1487
0
  DEBUG(3,("init_oplocks: initializing messages.\n"));
1488
1489
0
  messaging_register(sconn->msg_ctx, sconn, MSG_SMB_BREAK_REQUEST,
1490
0
         process_oplock_break_message);
1491
0
  messaging_register(sconn->msg_ctx, sconn, MSG_SMB_KERNEL_BREAK,
1492
0
         process_kernel_oplock_break);
1493
0
  return true;
1494
0
}
1495
1496
void init_kernel_oplocks(struct smbd_server_connection *sconn)
1497
0
{
1498
0
  struct kernel_oplocks *koplocks = sconn->oplocks.kernel_ops;
1499
1500
  /* only initialize once */
1501
0
  if (koplocks == NULL) {
1502
0
#ifdef HAVE_KERNEL_OPLOCKS_LINUX
1503
0
    koplocks = linux_init_kernel_oplocks(sconn);
1504
0
#endif
1505
0
    sconn->oplocks.kernel_ops = koplocks;
1506
0
  }
1507
0
}
1508
1509
struct pending_hlease_break {
1510
  struct pending_hlease_break *prev;
1511
  struct pending_hlease_break *next;
1512
  struct server_id pid;
1513
  struct file_id id;
1514
  uint64_t share_file_id;
1515
  uint16_t break_to;
1516
};
1517
1518
struct delay_for_handle_lease_break_state {
1519
  TALLOC_CTX *mem_ctx;
1520
  struct tevent_context *ev;
1521
  struct timeval timeout;
1522
  uint32_t access_mask;
1523
  bool recursive;
1524
  bool recursive_h_leases_break;
1525
  struct files_struct *fsp;
1526
  struct share_mode_lock *lck;
1527
  bool delay;
1528
  struct pending_hlease_break *breaks;
1529
  struct file_id break_id;
1530
  bool found_open;
1531
  uint32_t num_watches;
1532
};
1533
1534
static void delay_for_handle_lease_break_cleanup(struct tevent_req *req,
1535
             enum tevent_req_state req_state)
1536
0
{
1537
0
  struct delay_for_handle_lease_break_state *state =
1538
0
    tevent_req_data(req, struct delay_for_handle_lease_break_state);
1539
1540
0
  if (req_state == TEVENT_REQ_DONE) {
1541
0
    return;
1542
0
  }
1543
0
  TALLOC_FREE(state->lck);
1544
0
}
1545
1546
static void delay_for_handle_lease_break_check(struct tevent_req *req);
1547
1548
struct tevent_req *delay_for_handle_lease_break_send(
1549
  TALLOC_CTX *mem_ctx,
1550
  struct tevent_context *ev,
1551
  struct timeval timeout,
1552
  struct files_struct *fsp,
1553
  uint32_t access_mask,
1554
  bool recursive,
1555
  struct share_mode_lock **lck)
1556
0
{
1557
0
  struct tevent_req *req = NULL;
1558
0
  struct delay_for_handle_lease_break_state *state = NULL;
1559
1560
0
  req = tevent_req_create(
1561
0
    mem_ctx, &state, struct delay_for_handle_lease_break_state);
1562
0
  if (req == NULL) {
1563
0
    return NULL;
1564
0
  }
1565
1566
0
  tevent_req_set_cleanup_fn(req, delay_for_handle_lease_break_cleanup);
1567
1568
0
  *state = (struct delay_for_handle_lease_break_state) {
1569
0
    .mem_ctx = mem_ctx,
1570
0
    .ev = ev,
1571
0
    .timeout = timeout,
1572
0
    .access_mask = access_mask,
1573
0
    .recursive = recursive,
1574
0
    .recursive_h_leases_break = recursive,
1575
0
    .fsp = fsp,
1576
0
    .lck = talloc_move(state, lck),
1577
0
  };
1578
1579
0
  delay_for_handle_lease_break_check(req);
1580
0
  if (!tevent_req_is_in_progress(req)) {
1581
0
    return tevent_req_post(req, ev);
1582
0
  }
1583
1584
  /* Ensure we can't be closed in flight. */
1585
0
  if (!aio_add_req_to_fsp(fsp, req)) {
1586
0
    tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1587
0
    return tevent_req_post(req, ev);
1588
0
  }
1589
1590
0
  return req;
1591
0
}
1592
1593
static bool delay_for_handle_lease_break_fn(struct share_mode_entry *e,
1594
              void *private_data)
1595
0
{
1596
0
  struct delay_for_handle_lease_break_state *state = talloc_get_type_abort(
1597
0
    private_data, struct delay_for_handle_lease_break_state);
1598
0
  struct files_struct *fsp = state->fsp;
1599
0
  struct server_id_buf buf;
1600
0
  uint32_t lease_type;
1601
0
  bool ours, stale;
1602
1603
0
  if (fsp->lease != NULL) {
1604
0
    ours = smb2_lease_equal(fsp_client_guid(fsp),
1605
0
          &fsp->lease->lease.lease_key,
1606
0
          &e->client_guid,
1607
0
          &e->lease_key);
1608
0
    if (ours) {
1609
0
      return false;
1610
0
    }
1611
0
  }
1612
1613
0
  if ((state->access_mask & e->access_mask) == 0) {
1614
0
    return false;
1615
0
  }
1616
1617
0
  lease_type = get_lease_type(e, fsp->file_id);
1618
0
  if ((lease_type & SMB2_LEASE_HANDLE) == 0) {
1619
0
    return false;
1620
0
  }
1621
1622
0
  stale = share_entry_stale_pid(e);
1623
0
  if (stale) {
1624
0
    return false;
1625
0
  }
1626
1627
0
  state->delay = true;
1628
1629
0
  DBG_DEBUG("Breaking h-lease on [%s] pid [%s]\n",
1630
0
      fsp_str_dbg(fsp),
1631
0
      server_id_str_buf(e->pid, &buf));
1632
1633
0
  send_break_message(fsp->conn->sconn->msg_ctx,
1634
0
         &fsp->file_id,
1635
0
         e,
1636
0
         lease_type & ~SMB2_LEASE_HANDLE);
1637
1638
0
  return false;
1639
0
}
1640
1641
static void delay_for_handle_lease_break_fsp_done(struct tevent_req *subreq);
1642
1643
static void delay_for_handle_lease_break_fsp_check(struct tevent_req *req)
1644
0
{
1645
0
  struct delay_for_handle_lease_break_state *state = tevent_req_data(
1646
0
    req, struct delay_for_handle_lease_break_state);
1647
0
  struct tevent_req *subreq = NULL;
1648
0
  bool ok;
1649
1650
0
  DBG_DEBUG("fsp [%s]\n", fsp_str_dbg(state->fsp));
1651
1652
0
  if (state->lck == NULL) {
1653
0
    DBG_DEBUG("fsp [%s] all opens are gone\n",
1654
0
        fsp_str_dbg(state->fsp));
1655
0
    return;
1656
0
  }
1657
1658
0
  ok = share_mode_forall_leases(state->lck,
1659
0
              delay_for_handle_lease_break_fn,
1660
0
              state);
1661
0
  if (!ok) {
1662
0
    tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1663
0
    return;
1664
0
  }
1665
0
  if (state->delay) {
1666
0
    DBG_DEBUG("Delaying fsp [%s]\n", fsp_str_dbg(state->fsp));
1667
1668
0
    subreq = share_mode_watch_send(state,
1669
0
                 state->ev,
1670
0
                 &state->fsp->file_id,
1671
0
                 (struct server_id){0});
1672
0
    if (tevent_req_nomem(subreq, req)) {
1673
0
      return;
1674
0
    }
1675
1676
0
    tevent_req_set_callback(subreq,
1677
0
          delay_for_handle_lease_break_fsp_done,
1678
0
          req);
1679
1680
0
    if (!tevent_req_set_endtime(subreq, state->ev, state->timeout)) {
1681
0
      tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1682
0
      return;
1683
0
    }
1684
0
    return;
1685
0
  }
1686
0
}
1687
1688
static void delay_for_handle_lease_break_fsp_done(struct tevent_req *subreq)
1689
0
{
1690
0
  struct tevent_req *req = tevent_req_callback_data(
1691
0
    subreq, struct tevent_req);
1692
0
  struct delay_for_handle_lease_break_state *state = tevent_req_data(
1693
0
    req, struct delay_for_handle_lease_break_state);
1694
0
  NTSTATUS status;
1695
1696
0
  DBG_DEBUG("Watch returned for fsp [%s]\n", fsp_str_dbg(state->fsp));
1697
1698
0
  status = share_mode_watch_recv(subreq, NULL, NULL);
1699
0
  TALLOC_FREE(subreq);
1700
0
  if (!NT_STATUS_IS_OK(status)) {
1701
0
    DBG_ERR("share_mode_watch_recv returned %s\n",
1702
0
      nt_errstr(status));
1703
0
    if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
1704
      /*
1705
       * The sharemode-watch timer fired because a client
1706
       * didn't respond to the lease break.
1707
       */
1708
0
      status = NT_STATUS_ACCESS_DENIED;
1709
0
    }
1710
0
    tevent_req_nterror(req, status);
1711
0
    return;
1712
0
  }
1713
1714
0
  state->lck = get_existing_share_mode_lock(state, state->fsp->file_id);
1715
  /*
1716
   * This could potentially end up looping for some if a client
1717
   * aggressively reaquires H-leases on the file, but we have a
1718
   * timeout on the tevent req as upper bound.
1719
   */
1720
0
  delay_for_handle_lease_break_check(req);
1721
0
}
1722
1723
static int delay_for_handle_lease_break_below_fn(struct share_mode_data *d,
1724
             struct share_mode_entry *e,
1725
             void *private_data)
1726
0
{
1727
0
  struct tevent_req *req = talloc_get_type_abort(
1728
0
    private_data, struct tevent_req);
1729
0
  struct delay_for_handle_lease_break_state *state = tevent_req_data(
1730
0
    req, struct delay_for_handle_lease_break_state);
1731
0
  struct pending_hlease_break *b = NULL;
1732
0
  struct file_id_buf fid_buf;
1733
0
  const char *fid_bufp = NULL;
1734
0
  struct server_id_buf sid_buf;
1735
0
  uint32_t lease = 0;
1736
0
  bool stale;
1737
1738
0
  if (DEBUGLVL(DBGLVL_DEBUG)) {
1739
0
    fid_bufp = file_id_str_buf(d->id, &fid_buf);
1740
0
  }
1741
1742
0
  DBG_DEBUG("Breaking [%s] file-id [%s]\n",
1743
0
      state->recursive_h_leases_break ? "yes" : "no",
1744
0
      fid_bufp);
1745
1746
0
  stale = share_entry_stale_pid(e);
1747
0
  if (stale) {
1748
0
    return 0;
1749
0
  }
1750
1751
0
  if (state->recursive_h_leases_break) {
1752
0
    lease = get_lease_type(e, d->id);
1753
0
  }
1754
1755
0
  if ((lease & SMB2_LEASE_HANDLE) == 0) {
1756
0
    if (e->flags & SHARE_ENTRY_FLAG_POSIX_OPEN) {
1757
0
      DBG_DEBUG("POSIX open file-id [%s]\n", fid_bufp);
1758
      /* Ignore POSIX opens. */
1759
0
      return 0;
1760
0
    }
1761
0
    state->found_open = true;
1762
0
    DBG_DEBUG("Unbreakable open [%s]\n", fid_bufp);
1763
0
    if (!state->recursive_h_leases_break) {
1764
      /* Second round, stop */
1765
0
      DBG_DEBUG("Stopping\n");
1766
0
      return -1;
1767
0
    }
1768
0
    return 0;
1769
0
  }
1770
0
  lease &= ~SMB2_LEASE_HANDLE;
1771
1772
0
  b = talloc_zero(state, struct pending_hlease_break);
1773
0
  if (b == NULL) {
1774
0
    DBG_ERR("talloc_zero failed\n");
1775
0
    return -1;
1776
0
  }
1777
0
  b->id = d->id;
1778
0
  b->break_to = lease;
1779
0
  b->pid = e->pid;
1780
0
  b->share_file_id = e->share_file_id;
1781
1782
0
  DLIST_ADD_END(state->breaks, b);
1783
1784
0
  DBG_DEBUG("Queued h-lease break on file-id [%s] pid [%s]\n",
1785
0
      fid_bufp,
1786
0
      server_id_str_buf(b->pid, &sid_buf));
1787
1788
0
  state->delay = true;
1789
0
  return 0;
1790
0
}
1791
1792
static void delay_for_handle_lease_break_below_send_breaks(
1793
  struct tevent_req *req);
1794
1795
static void delay_for_handle_lease_break_below_check(struct tevent_req *req)
1796
0
{
1797
0
  struct delay_for_handle_lease_break_state *state = tevent_req_data(
1798
0
    req, struct delay_for_handle_lease_break_state);
1799
0
  int ret;
1800
1801
0
  DBG_DEBUG("fsp [%s]\n", fsp_str_dbg(state->fsp));
1802
1803
0
  if (!state->recursive) {
1804
0
    return;
1805
0
  }
1806
0
  if (!S_ISDIR(state->fsp->fsp_name->st.st_ex_mode)) {
1807
0
    return;
1808
0
  }
1809
0
  if (!lp_strict_rename(SNUM(state->fsp->conn))) {
1810
    /*
1811
     * This will also not do h-lease breaks
1812
     */
1813
0
    state->found_open = file_find_subpath(state->fsp);
1814
0
    return;
1815
0
  }
1816
1817
0
  ret = opens_below_forall(state->fsp->conn,
1818
0
         state->fsp->fsp_name,
1819
0
         delay_for_handle_lease_break_below_fn,
1820
0
         req);
1821
0
  if (ret == -1) {
1822
0
    tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1823
0
    return;
1824
0
  }
1825
0
  if (!state->delay) {
1826
0
    DBG_DEBUG("No delay for [%s]\n", fsp_str_dbg(state->fsp));
1827
0
    return;
1828
0
  }
1829
  /*
1830
   * Ignore any opens without h-lease in the first round of listing opens
1831
   */
1832
0
  state->found_open = false;
1833
0
  delay_for_handle_lease_break_below_send_breaks(req);
1834
0
  return;
1835
0
}
1836
1837
static void delay_for_handle_lease_break_below_done(struct tevent_req *subreq);
1838
1839
static void delay_for_handle_lease_break_below_send_breaks(
1840
  struct tevent_req *req)
1841
0
{
1842
0
  struct delay_for_handle_lease_break_state *state = tevent_req_data(
1843
0
    req, struct delay_for_handle_lease_break_state);
1844
0
  struct messaging_context *msg_ctx = state->fsp->conn->sconn->msg_ctx;
1845
0
  struct pending_hlease_break *b = NULL;
1846
0
  struct file_id last_file_id;
1847
0
  struct tevent_req *subreq = NULL;
1848
0
  NTSTATUS status;
1849
1850
0
  DBG_DEBUG("Sending breaks\n");
1851
1852
0
  if (state->breaks == NULL) {
1853
0
    return;
1854
0
  }
1855
1856
0
  for (b = state->breaks, last_file_id = b->id; b != NULL; b = b->next) {
1857
0
    struct share_mode_entry e;
1858
0
    struct file_id_buf fid_buf;
1859
0
    struct server_id_buf sid_buf;
1860
1861
0
    if (!file_id_equal(&b->id, &last_file_id)) {
1862
0
      break;
1863
0
    }
1864
1865
0
    e = (struct share_mode_entry) {
1866
0
      .share_file_id = b->share_file_id,
1867
0
      .pid = b->pid,
1868
0
    };
1869
1870
0
    status = send_break_message(msg_ctx,
1871
0
              &b->id,
1872
0
              &e,
1873
0
              b->break_to);
1874
0
    if (tevent_req_nterror(req, status)) {
1875
0
      DBG_ERR("send_break_message failed\n");
1876
0
      return;
1877
0
    }
1878
1879
0
    DLIST_REMOVE(state->breaks, b);
1880
1881
0
    DBG_DEBUG("Sent h-lease break on file-id [%s] pid [%s]\n",
1882
0
        file_id_str_buf(b->id, &fid_buf),
1883
0
        server_id_str_buf(b->pid, &sid_buf));
1884
1885
0
    subreq = share_mode_watch_send(state,
1886
0
                 state->ev,
1887
0
                 &b->id,
1888
0
                 (struct server_id){0});
1889
0
    if (tevent_req_nomem(subreq, req)) {
1890
0
      return;
1891
0
    }
1892
0
    tevent_req_set_callback(subreq,
1893
0
          delay_for_handle_lease_break_below_done,
1894
0
          req);
1895
0
    if (!tevent_req_set_endtime(subreq, state->ev, state->timeout)) {
1896
0
      tevent_req_oom(req);
1897
0
      return;
1898
0
    }
1899
0
    state->num_watches++;
1900
0
  }
1901
1902
0
  state->break_id = last_file_id;
1903
0
  DBG_DEBUG("Stopped sending breaks\n");
1904
0
}
1905
1906
static void delay_for_handle_lease_break_below_done(struct tevent_req *subreq)
1907
0
{
1908
0
  struct tevent_req *req = tevent_req_callback_data(
1909
0
    subreq, struct tevent_req);
1910
0
  struct delay_for_handle_lease_break_state *state = tevent_req_data(
1911
0
    req, struct delay_for_handle_lease_break_state);
1912
0
  struct share_mode_lock *lck = NULL;
1913
0
  struct file_id_buf fid_buf;
1914
0
  const char *fid_bufp = NULL;
1915
0
  NTSTATUS status;
1916
1917
0
  if (DEBUGLVL(DBGLVL_DEBUG)) {
1918
0
    fid_bufp = file_id_str_buf(state->break_id, &fid_buf);
1919
0
  }
1920
1921
0
  DBG_DEBUG("Watch finished for file-id [%s]\n", fid_bufp);
1922
1923
0
  status = share_mode_watch_recv(subreq, NULL, NULL);
1924
0
  TALLOC_FREE(subreq);
1925
0
  if (!NT_STATUS_IS_OK(status)) {
1926
0
    DBG_ERR("share_mode_watch_recv returned %s\n",
1927
0
      nt_errstr(status));
1928
0
    if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
1929
      /*
1930
       * The sharemode-watch timer fired because a client
1931
       * didn't respond to the lease break.
1932
       */
1933
0
      status = NT_STATUS_ACCESS_DENIED;
1934
0
    }
1935
0
    tevent_req_nterror(req, status);
1936
0
    return;
1937
0
  }
1938
1939
0
  state->num_watches--;
1940
0
  if (state->num_watches > 0) {
1941
0
    return;
1942
0
  }
1943
1944
  /*
1945
   * If the client just sends a break ACK, but doesn't close the file,
1946
   * Windows server directly returns NT_STATUS_ACCESS_DENIED.
1947
   */
1948
1949
0
  DBG_DEBUG("Checking for remaining opens on [%s]\n", fid_bufp);
1950
1951
0
  lck = fetch_share_mode_unlocked(state, state->break_id);
1952
0
  if (lck != NULL) {
1953
0
    bool has_nonposix_open;
1954
1955
0
    has_nonposix_open = has_nonposix_opens(lck);
1956
0
    TALLOC_FREE(lck);
1957
0
    if (has_nonposix_open) {
1958
0
      DBG_DEBUG("Found open\n");
1959
0
      tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1960
0
      return;
1961
0
    }
1962
0
  }
1963
1964
0
  if (state->breaks != NULL) {
1965
0
    delay_for_handle_lease_break_below_send_breaks(req);
1966
0
    return;
1967
0
  }
1968
1969
  /*
1970
   * We've sent lease breaks recursively once, don't do that again. So we
1971
   * do a recursive scan a second time to check for new opens and if there
1972
   * are any, with or without h-leases, just fail with
1973
   * NT_STATUS_ACCESS_DENIED.
1974
   */
1975
0
  state->recursive_h_leases_break = false;
1976
1977
0
  state->lck = get_existing_share_mode_lock(state, state->fsp->file_id);
1978
0
  delay_for_handle_lease_break_check(req);
1979
0
}
1980
1981
static void delay_for_handle_lease_break_check(struct tevent_req *req)
1982
0
{
1983
0
  struct delay_for_handle_lease_break_state *state = tevent_req_data(
1984
0
    req, struct delay_for_handle_lease_break_state);
1985
1986
0
  state->delay = false;
1987
1988
0
  DBG_DEBUG("fsp [%s]\n", fsp_str_dbg(state->fsp));
1989
1990
0
  delay_for_handle_lease_break_fsp_check(req);
1991
0
  if (!tevent_req_is_in_progress(req)) {
1992
0
    return;
1993
0
  }
1994
0
  if (state->delay) {
1995
0
    DBG_DEBUG("Delaying fsp [%s]\n", fsp_str_dbg(state->fsp));
1996
0
    TALLOC_FREE(state->lck);
1997
0
    return;
1998
0
  }
1999
2000
0
  delay_for_handle_lease_break_below_check(req);
2001
0
  if (!tevent_req_is_in_progress(req)) {
2002
0
    return;
2003
0
  }
2004
0
  if (state->found_open) {
2005
0
    tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2006
0
    return;
2007
0
  }
2008
0
  if (state->delay) {
2009
0
    TALLOC_FREE(state->lck);
2010
0
    return;
2011
0
  }
2012
2013
0
  tevent_req_done(req);
2014
0
}
2015
2016
NTSTATUS delay_for_handle_lease_break_recv(struct tevent_req *req,
2017
             TALLOC_CTX *mem_ctx,
2018
             struct share_mode_lock **lck)
2019
0
{
2020
0
  NTSTATUS status;
2021
2022
0
  struct delay_for_handle_lease_break_state *state =
2023
0
    tevent_req_data(req, struct delay_for_handle_lease_break_state);
2024
2025
0
  if (tevent_req_is_nterror(req, &status)) {
2026
0
    tevent_req_received(req);
2027
0
    return status;
2028
0
  }
2029
2030
0
  *lck = talloc_move(mem_ctx, &state->lck);
2031
0
  tevent_req_received(req);
2032
0
  return NT_STATUS_OK;
2033
0
}
2034
2035
const struct smb2_lease *fsp_get_smb2_lease(const struct files_struct *fsp)
2036
0
{
2037
0
  if (fsp == NULL) {
2038
0
    return NULL;
2039
0
  }
2040
0
  if (fsp->lease == NULL) {
2041
0
    return NULL;
2042
0
  }
2043
0
  return &fsp->lease->lease;
2044
0
}