Coverage Report

Created: 2026-05-24 06:47

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/samba/source3/locking/locking.c
Line
Count
Source
1
/*
2
   Unix SMB/CIFS implementation.
3
   Locking functions
4
   Copyright (C) Andrew Tridgell 1992-2000
5
   Copyright (C) Jeremy Allison 1992-2006
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
   Revision History:
22
23
   12 aug 96: Erik.Devriendt@te6.siemens.be
24
   added support for shared memory implementation of share mode locking
25
26
   May 1997. Jeremy Allison (jallison@whistle.com). Modified share mode
27
   locking to deal with multiple share modes per open file.
28
29
   September 1997. Jeremy Allison (jallison@whistle.com). Added oplock
30
   support.
31
32
   rewritten completely to use new tdb code. Tridge, Dec '99
33
34
   Added POSIX locking support. Jeremy Allison (jeremy@valinux.com), Apr. 2000.
35
   Added Unix Extensions POSIX locking support. Jeremy Allison Mar 2006.
36
*/
37
38
#include "includes.h"
39
#include "lib/util/time_basic.h"
40
#include "smbd/proto.h"
41
#include "system/filesys.h"
42
#include "lib/util/server_id.h"
43
#include "share_mode_lock.h"
44
#include "share_mode_lock_private.h"
45
#include "locking/proto.h"
46
#include "smbd/globals.h"
47
#include "dbwrap/dbwrap.h"
48
#include "dbwrap/dbwrap_open.h"
49
#include "../libcli/security/security.h"
50
#include "serverid.h"
51
#include "messages.h"
52
#include "util_tdb.h"
53
#include "../librpc/gen_ndr/ndr_open_files.h"
54
#include "librpc/gen_ndr/ndr_file_id.h"
55
#include "librpc/gen_ndr/ndr_leases_db.h"
56
#include "locking/leases_db.h"
57
58
#undef DBGC_CLASS
59
0
#define DBGC_CLASS DBGC_LOCKING
60
61
0
#define NO_LOCKING_COUNT (-1)
62
63
/****************************************************************************
64
 Debugging aids :-).
65
****************************************************************************/
66
67
const char *lock_type_name(enum brl_type lock_type)
68
0
{
69
0
  switch (lock_type) {
70
0
    case READ_LOCK:
71
0
      return "READ";
72
0
    case WRITE_LOCK:
73
0
      return "WRITE";
74
0
    default:
75
0
      return "other";
76
0
  }
77
0
}
78
79
const char *lock_flav_name(enum brl_flavour lock_flav)
80
0
{
81
0
  return (lock_flav == WINDOWS_LOCK) ? "WINDOWS_LOCK" : "POSIX_LOCK";
82
0
}
83
84
/****************************************************************************
85
 Utility function called to see if a file region is locked.
86
 Called in the read/write codepath.
87
****************************************************************************/
88
89
void init_strict_lock_struct(files_struct *fsp,
90
        uint64_t smblctx,
91
        br_off start,
92
        br_off size,
93
        enum brl_type lock_type,
94
        struct lock_struct *plock)
95
0
{
96
0
  SMB_ASSERT(lock_type == READ_LOCK || lock_type == WRITE_LOCK);
97
98
0
  *plock = (struct lock_struct) {
99
0
    .context.smblctx = smblctx,
100
0
    .context.tid = fsp->conn->cnum,
101
0
    .context.pid = messaging_server_id(fsp->conn->sconn->msg_ctx),
102
0
    .start = start,
103
0
    .size = size,
104
0
    .fnum = fsp->fnum,
105
0
    .lock_type = lock_type,
106
0
    .lock_flav = lp_posix_cifsu_locktype(fsp),
107
0
  };
108
0
}
109
110
struct strict_lock_check_state {
111
  bool ret;
112
  files_struct *fsp;
113
  struct lock_struct *plock;
114
};
115
116
static void strict_lock_check_default_fn(struct share_mode_lock *lck,
117
           struct byte_range_lock *br_lck,
118
           void *private_data)
119
0
{
120
0
  struct strict_lock_check_state *state = private_data;
121
122
  /*
123
   * The caller has checked fsp->fsp_flags.can_lock and lp_locking so
124
   * br_lck has to be there!
125
   */
126
0
  SMB_ASSERT(br_lck != NULL);
127
128
0
  state->ret = brl_locktest(br_lck, state->plock, true);
129
0
}
130
131
bool strict_lock_check_default(files_struct *fsp, struct lock_struct *plock)
132
0
{
133
0
  struct byte_range_lock *br_lck;
134
0
  int strict_locking = lp_strict_locking(fsp->conn->params);
135
0
  NTSTATUS status;
136
0
  bool ret = False;
137
138
0
  if (plock->size == 0) {
139
0
    return True;
140
0
  }
141
142
0
  if (!lp_locking(fsp->conn->params) ||
143
0
      !strict_locking ||
144
0
      !fsp->fsp_flags.can_lock)
145
0
  {
146
0
    return True;
147
0
  }
148
149
0
  if (strict_locking == Auto) {
150
0
    uint32_t lease_type = fsp_lease_type(fsp);
151
152
0
    if ((lease_type & SMB2_LEASE_READ) &&
153
0
         (plock->lock_type == READ_LOCK))
154
0
    {
155
0
      DBG_DEBUG("optimisation - read lease on file %s\n",
156
0
          fsp_str_dbg(fsp));
157
0
      return true;
158
0
    }
159
160
0
    if ((lease_type & SMB2_LEASE_WRITE) &&
161
0
         (plock->lock_type == WRITE_LOCK))
162
0
    {
163
0
      DBG_DEBUG("optimisation - write lease on file %s\n",
164
0
          fsp_str_dbg(fsp));
165
0
      return true;
166
0
    }
167
0
  }
168
169
0
  br_lck = brl_get_locks_readonly(fsp);
170
0
  if (!br_lck) {
171
0
    return true;
172
0
  }
173
0
  ret = brl_locktest(br_lck, plock, false);
174
0
  if (!ret) {
175
    /*
176
     * We got a lock conflict. Retry with rw locks to enable
177
     * autocleanup. This is the slow path anyway.
178
     */
179
180
0
    struct strict_lock_check_state state =
181
0
      (struct strict_lock_check_state) {
182
0
      .fsp = fsp,
183
0
      .plock = plock,
184
0
    };
185
186
0
    status = share_mode_do_locked_brl(fsp,
187
0
              strict_lock_check_default_fn,
188
0
              &state);
189
0
    if (!NT_STATUS_IS_OK(status)) {
190
0
      DBG_ERR("share_mode_do_locked_brl [%s] failed: %s\n",
191
0
        fsp_str_dbg(fsp), nt_errstr(status));
192
0
      state.ret = false;
193
0
    }
194
0
    ret = state.ret;
195
0
  }
196
197
0
  DBG_DEBUG("flavour = %s brl start=%" PRIu64 " "
198
0
      "len=%" PRIu64 " %s for fnum %" PRIu64 " file %s\n",
199
0
      lock_flav_name(plock->lock_flav),
200
0
      plock->start,
201
0
      plock->size,
202
0
      ret ? "unlocked" : "locked",
203
0
      plock->fnum,
204
0
      fsp_str_dbg(fsp));
205
206
0
  return ret;
207
0
}
208
209
/****************************************************************************
210
 Find out if a lock could be granted - return who is blocking us if we can't.
211
****************************************************************************/
212
213
NTSTATUS query_lock(files_struct *fsp,
214
      uint64_t *psmblctx,
215
      uint64_t *pcount,
216
      uint64_t *poffset,
217
      enum brl_type *plock_type,
218
      enum brl_flavour lock_flav)
219
0
{
220
0
  struct byte_range_lock *br_lck = NULL;
221
222
0
  if (!fsp->fsp_flags.can_lock) {
223
0
    return fsp->fsp_flags.is_directory ?
224
0
      NT_STATUS_INVALID_DEVICE_REQUEST :
225
0
      NT_STATUS_INVALID_HANDLE;
226
0
  }
227
228
0
  if (!lp_locking(fsp->conn->params)) {
229
0
    return NT_STATUS_OK;
230
0
  }
231
232
0
  br_lck = brl_get_locks_readonly(fsp);
233
0
  if (!br_lck) {
234
0
    return NT_STATUS_NO_MEMORY;
235
0
  }
236
237
0
  return brl_lockquery(br_lck,
238
0
      psmblctx,
239
0
      messaging_server_id(fsp->conn->sconn->msg_ctx),
240
0
      poffset,
241
0
      pcount,
242
0
      plock_type,
243
0
      lock_flav);
244
0
}
245
246
static void increment_current_lock_count(files_struct *fsp,
247
    enum brl_flavour lock_flav)
248
0
{
249
0
  if (lock_flav == WINDOWS_LOCK &&
250
0
      fsp->current_lock_count != NO_LOCKING_COUNT) {
251
    /* blocking ie. pending, locks also count here,
252
     * as this is an efficiency counter to avoid checking
253
     * the lock db. on close. JRA. */
254
255
0
    fsp->current_lock_count++;
256
0
  } else {
257
    /* Notice that this has had a POSIX lock request.
258
     * We can't count locks after this so forget them.
259
     */
260
0
    fsp->current_lock_count = NO_LOCKING_COUNT;
261
0
  }
262
0
}
263
264
static void decrement_current_lock_count(files_struct *fsp,
265
    enum brl_flavour lock_flav)
266
0
{
267
0
  if (lock_flav == WINDOWS_LOCK &&
268
0
      fsp->current_lock_count != NO_LOCKING_COUNT) {
269
0
    SMB_ASSERT(fsp->current_lock_count > 0);
270
0
    fsp->current_lock_count--;
271
0
  }
272
0
}
273
274
/****************************************************************************
275
 Utility function called by locking requests.
276
****************************************************************************/
277
278
NTSTATUS do_lock(struct byte_range_lock *br_lck,
279
     TALLOC_CTX *req_mem_ctx,
280
     const struct GUID *req_guid,
281
     uint64_t smblctx,
282
     uint64_t count,
283
     uint64_t offset,
284
     enum brl_type lock_type,
285
     enum brl_flavour lock_flav,
286
     struct server_id *pblocker_pid,
287
     uint64_t *psmblctx)
288
0
{
289
0
  files_struct *fsp = brl_fsp(br_lck);
290
0
  struct server_id blocker_pid;
291
0
  uint64_t blocker_smblctx;
292
0
  NTSTATUS status;
293
294
0
  SMB_ASSERT(req_mem_ctx != NULL);
295
0
  SMB_ASSERT(req_guid != NULL);
296
297
0
  if (!fsp->fsp_flags.can_lock) {
298
0
    if (fsp->fsp_flags.is_directory) {
299
0
      return NT_STATUS_INVALID_DEVICE_REQUEST;
300
0
    }
301
0
    return NT_STATUS_INVALID_HANDLE;
302
0
  }
303
304
0
  if (!lp_locking(fsp->conn->params)) {
305
0
    return NT_STATUS_OK;
306
0
  }
307
308
  /* NOTE! 0 byte long ranges ARE allowed and should be stored  */
309
310
0
  DBG_DEBUG("lock flavour %s lock type %s start=%"PRIu64" len=%"PRIu64" "
311
0
      "requested for %s file %s\n",
312
0
      lock_flav_name(lock_flav),
313
0
      lock_type_name(lock_type),
314
0
      offset,
315
0
      count,
316
0
      fsp_fnum_dbg(fsp),
317
0
      fsp_str_dbg(fsp));
318
319
0
  brl_req_set(br_lck, req_mem_ctx, req_guid);
320
0
  status = brl_lock(br_lck,
321
0
        smblctx,
322
0
        messaging_server_id(fsp->conn->sconn->msg_ctx),
323
0
        offset,
324
0
        count,
325
0
        lock_type,
326
0
        lock_flav,
327
0
        &blocker_pid,
328
0
        &blocker_smblctx);
329
0
  brl_req_set(br_lck, NULL, NULL);
330
0
        if (!NT_STATUS_IS_OK(status)) {
331
0
    DBG_DEBUG("brl_lock failed: %s\n", nt_errstr(status));
332
0
    if (psmblctx != NULL) {
333
0
      *psmblctx = blocker_smblctx;
334
0
    }
335
0
    if (pblocker_pid != NULL) {
336
0
      *pblocker_pid = blocker_pid;
337
0
    }
338
0
    return status;
339
0
        }
340
341
0
  increment_current_lock_count(fsp, lock_flav);
342
343
0
  return NT_STATUS_OK;
344
0
}
345
346
/****************************************************************************
347
 Utility function called by unlocking requests.
348
****************************************************************************/
349
350
NTSTATUS do_unlock(struct byte_range_lock *br_lck,
351
       uint64_t smblctx,
352
       uint64_t count,
353
       uint64_t offset,
354
       enum brl_flavour lock_flav)
355
0
{
356
0
  files_struct *fsp = brl_fsp(br_lck);
357
0
  bool ok = False;
358
359
0
  if (!fsp->fsp_flags.can_lock) {
360
0
    return fsp->fsp_flags.is_directory ?
361
0
      NT_STATUS_INVALID_DEVICE_REQUEST :
362
0
      NT_STATUS_INVALID_HANDLE;
363
0
  }
364
365
0
  if (!lp_locking(fsp->conn->params)) {
366
0
    return NT_STATUS_OK;
367
0
  }
368
369
0
  DBG_DEBUG("unlock start=%"PRIu64" len=%"PRIu64" requested for %s file "
370
0
      "%s\n",
371
0
      offset,
372
0
      count,
373
0
      fsp_fnum_dbg(fsp),
374
0
      fsp_str_dbg(fsp));
375
376
0
  ok = brl_unlock(br_lck,
377
0
      smblctx,
378
0
      messaging_server_id(fsp->conn->sconn->msg_ctx),
379
0
      offset,
380
0
      count,
381
0
      lock_flav);
382
383
0
  if (!ok) {
384
0
    DEBUG(10,("do_unlock: returning ERRlock.\n" ));
385
0
    return NT_STATUS_RANGE_NOT_LOCKED;
386
0
  }
387
388
0
  decrement_current_lock_count(fsp, lock_flav);
389
0
  return NT_STATUS_OK;
390
0
}
391
392
/****************************************************************************
393
 Remove any locks on this fd. Called from file_close().
394
****************************************************************************/
395
396
void locking_close_file(files_struct *fsp,
397
      enum file_close_type close_type)
398
0
{
399
0
  struct byte_range_lock *br_lck;
400
401
0
  if (!lp_locking(fsp->conn->params)) {
402
0
    return;
403
0
  }
404
405
  /* If we have no outstanding locks or pending
406
   * locks then we don't need to look in the lock db.
407
   */
408
409
0
  if (fsp->current_lock_count == 0) {
410
0
    return;
411
0
  }
412
413
0
  br_lck = brl_get_locks(talloc_tos(),fsp);
414
415
0
  if (br_lck) {
416
    /*
417
     * Unlocks must trigger dbwrap_watch watchers,
418
     * normally in smbd_do_unlocking. Here it's done
419
     * implicitly, we're closing the file and thus remove a
420
     * share mode. This will wake the waiters.
421
     */
422
0
    brl_close_fnum(br_lck);
423
0
    TALLOC_FREE(br_lck);
424
0
  }
425
0
}
426
427
/*******************************************************************
428
 Print out a share mode.
429
********************************************************************/
430
431
char *share_mode_str(TALLOC_CTX *ctx, int num,
432
         const struct file_id *id,
433
         const struct share_mode_entry *e)
434
0
{
435
0
  struct server_id_buf tmp;
436
0
  struct file_id_buf ftmp;
437
438
0
  return talloc_asprintf(ctx, "share_mode_entry[%d]: "
439
0
     "pid = %s, share_access = 0x%x, "
440
0
     "access_mask = 0x%x, mid = 0x%llx, type= 0x%x, gen_id = %llu, "
441
0
     "uid = %u, flags = %u, file_id %s, name_hash = 0x%x",
442
0
     num,
443
0
     server_id_str_buf(e->pid, &tmp),
444
0
     e->share_access,
445
0
     e->access_mask, (unsigned long long)e->op_mid,
446
0
     e->op_type, (unsigned long long)e->share_file_id,
447
0
     (unsigned int)e->uid, (unsigned int)e->flags,
448
0
     file_id_str_buf(*id, &ftmp),
449
0
     (unsigned int)e->name_hash);
450
0
}
451
452
struct rename_share_filename_state {
453
  struct share_mode_data *data;
454
  struct messaging_context *msg_ctx;
455
  struct server_id self;
456
  uint32_t orig_name_hash;
457
  uint32_t new_name_hash;
458
  struct file_rename_message msg;
459
};
460
461
static bool rename_lease_fn(struct share_mode_entry *e,
462
          void *private_data)
463
0
{
464
0
  struct rename_share_filename_state *state = private_data;
465
0
  struct share_mode_data *d = state->data;
466
0
  NTSTATUS status;
467
468
0
  status = leases_db_rename(&e->client_guid,
469
0
          &e->lease_key,
470
0
          &d->id,
471
0
          d->servicepath,
472
0
          d->base_name,
473
0
          d->stream_name);
474
475
0
  if (!NT_STATUS_IS_OK(status)) {
476
    /* Any error recovery possible here ? */
477
0
    DBG_WARNING("Failed to rename lease key for "
478
0
          "renamed file %s:%s. %s\n",
479
0
          d->base_name,
480
0
          d->stream_name,
481
0
          nt_errstr(status));
482
0
  }
483
484
0
  return false;
485
0
}
486
487
/*******************************************************************
488
 Sets the service name and filename for rename.
489
 At this point we emit "file renamed" messages to all
490
 process id's that have this file open.
491
 Based on an initial code idea from SATOH Fumiyasu <fumiya@samba.gr.jp>
492
********************************************************************/
493
494
static bool rename_share_filename_fn(
495
  struct share_mode_entry *e,
496
  bool *modified,
497
  void *private_data)
498
0
{
499
0
  struct rename_share_filename_state *state = private_data;
500
0
  DATA_BLOB blob;
501
0
  enum ndr_err_code ndr_err;
502
0
  bool ok;
503
504
  /*
505
   * If this is a hardlink to the inode with a different name,
506
   * skip this.
507
   */
508
0
  if (e->name_hash != state->orig_name_hash) {
509
0
    return false;
510
0
  }
511
0
  e->name_hash = state->new_name_hash;
512
0
  *modified = true;
513
514
0
  ok = server_id_equal(&e->pid, &state->self);
515
0
  if (ok) {
516
0
    return false;
517
0
  }
518
519
0
  state->msg.share_file_id = e->share_file_id;
520
521
0
  ndr_err = ndr_push_struct_blob(
522
0
    &blob,
523
0
    talloc_tos(),
524
0
    &state->msg,
525
0
    (ndr_push_flags_fn_t)ndr_push_file_rename_message);
526
0
  if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
527
0
    DBG_DEBUG("ndr_push_file_rename_message failed: %s\n",
528
0
        ndr_errstr(ndr_err));
529
0
    return false;
530
0
  }
531
0
  if (DEBUGLEVEL >= 10) {
532
0
    struct server_id_buf tmp;
533
0
    DBG_DEBUG("sending rename message to %s\n",
534
0
        server_id_str_buf(e->pid, &tmp));
535
0
    NDR_PRINT_DEBUG(file_rename_message, &state->msg);
536
0
  }
537
538
0
  messaging_send(state->msg_ctx, e->pid, MSG_SMB_FILE_RENAME, &blob);
539
540
0
  TALLOC_FREE(blob.data);
541
542
0
  return false;
543
0
}
544
545
bool rename_share_filename(struct messaging_context *msg_ctx,
546
      struct share_mode_lock *lck,
547
      struct file_id id,
548
      const char *servicepath,
549
      uint32_t orig_name_hash,
550
      uint32_t new_name_hash,
551
      const struct smb_filename *smb_fname_dst)
552
0
{
553
0
  struct rename_share_filename_state state = {
554
0
    .msg_ctx = msg_ctx,
555
0
    .self = messaging_server_id(msg_ctx),
556
0
    .orig_name_hash = orig_name_hash,
557
0
    .new_name_hash = new_name_hash,
558
0
    .msg.id = id,
559
0
    .msg.servicepath = servicepath,
560
0
    .msg.base_name = smb_fname_dst->base_name,
561
0
    .msg.stream_name = smb_fname_dst->stream_name,
562
0
  };
563
0
  struct share_mode_data *d = NULL;
564
0
  NTSTATUS status;
565
0
  bool ok;
566
567
0
  DBG_DEBUG("servicepath %s newname %s\n",
568
0
      servicepath,
569
0
      smb_fname_dst->base_name);
570
571
0
  status = share_mode_lock_access_private_data(lck, &d);
572
0
  if (!NT_STATUS_IS_OK(status)) {
573
    /* Any error recovery possible here ? */
574
0
    DBG_ERR("share_mode_lock_access_private_data() failed for "
575
0
      "servicepath %s newname %s - %s\n",
576
0
      servicepath, smb_fname_dst->base_name,
577
0
      nt_errstr(status));
578
0
    return false;
579
0
  }
580
0
  state.data = d;
581
582
  /*
583
   * rename_internal_fsp() and rename_internals() add './' to
584
   * head of newname if newname does not contain a '/'.
585
   */
586
587
0
  if (strncmp(state.msg.base_name, "./", 2) == 0) {
588
0
    state.msg.base_name += 2;
589
0
  }
590
591
0
  d->servicepath = talloc_strdup(d, state.msg.servicepath);
592
0
  d->base_name = talloc_strdup(d, state.msg.base_name);
593
0
  d->stream_name = talloc_strdup(d, state.msg.stream_name);
594
0
  if ((d->servicepath == NULL) ||
595
0
      (d->base_name == NULL) ||
596
0
      ((state.msg.stream_name != NULL) && (d->stream_name == NULL))) {
597
0
    DBG_WARNING("talloc failed\n");
598
0
    return false;
599
0
  }
600
0
  d->modified = True;
601
602
0
  ok = share_mode_forall_entries(
603
0
    lck, rename_share_filename_fn, &state);
604
0
  if (!ok) {
605
0
    DBG_WARNING("share_mode_forall_entries failed\n");
606
0
  }
607
608
0
  ok = share_mode_forall_leases(lck, rename_lease_fn, &state);
609
0
  if (!ok) {
610
    /*
611
     * Ignore error here. Not sure what to do..
612
     */
613
0
    DBG_WARNING("share_mode_forall_leases failed\n");
614
0
  }
615
616
0
  return True;
617
0
}
618
619
void get_file_infos(struct file_id id,
620
        uint32_t name_hash,
621
        bool *delete_on_close)
622
0
{
623
0
  struct share_mode_lock *lck;
624
625
0
  if (delete_on_close) {
626
0
    *delete_on_close = false;
627
0
  }
628
629
0
  if (!(lck = fetch_share_mode_unlocked(talloc_tos(), id))) {
630
0
    return;
631
0
  }
632
633
0
  if (delete_on_close) {
634
0
    *delete_on_close = is_delete_on_close_set(lck, name_hash);
635
0
  }
636
637
0
  TALLOC_FREE(lck);
638
0
}
639
640
bool is_valid_share_mode_entry(const struct share_mode_entry *e)
641
0
{
642
0
  int num_props = 0;
643
644
0
  if (e->stale) {
645
0
    return false;
646
0
  }
647
648
0
  num_props += ((e->op_type == NO_OPLOCK) ? 1 : 0);
649
0
  num_props += (EXCLUSIVE_OPLOCK_TYPE(e->op_type) ? 1 : 0);
650
0
  num_props += (LEVEL_II_OPLOCK_TYPE(e->op_type) ? 1 : 0);
651
0
  num_props += (e->op_type == LEASE_OPLOCK);
652
653
0
  if ((num_props > 1) && serverid_exists(&e->pid)) {
654
0
    smb_panic("Invalid share mode entry");
655
0
  }
656
0
  return (num_props != 0);
657
0
}
658
659
struct find_lease_ref_state {
660
  const struct GUID *client_guid;
661
  const struct smb2_lease_key *lease_key;
662
  bool found_same;
663
};
664
665
static bool find_lease_ref_fn(
666
  struct share_mode_entry *e,
667
  bool *modified,
668
  void *private_data)
669
0
{
670
0
  struct find_lease_ref_state *state = private_data;
671
672
0
  if (e->stale) {
673
0
    return false;
674
0
  }
675
0
  if (e->op_type != LEASE_OPLOCK) {
676
0
    return false;
677
0
  }
678
679
0
  state->found_same = smb2_lease_equal(
680
0
    &e->client_guid,
681
0
    &e->lease_key,
682
0
    state->client_guid,
683
0
    state->lease_key);
684
  /*
685
   * If we found a lease reference, look no further (i.e. return true)
686
   */
687
0
  return state->found_same;
688
0
}
689
690
NTSTATUS remove_lease_if_stale(struct share_mode_lock *lck,
691
             const struct GUID *client_guid,
692
             const struct smb2_lease_key *lease_key)
693
0
{
694
0
  struct find_lease_ref_state state = {
695
0
    .client_guid = client_guid, .lease_key = lease_key,
696
0
  };
697
0
  struct file_id id = share_mode_lock_file_id(lck);
698
0
  NTSTATUS status;
699
0
  bool ok;
700
701
0
  ok = share_mode_forall_entries(lck, find_lease_ref_fn, &state);
702
0
  if (!ok) {
703
0
    DBG_ERR("share_mode_forall_entries failed\n");
704
0
    return NT_STATUS_INTERNAL_ERROR;
705
0
  }
706
707
0
  if (state.found_same) {
708
0
    return NT_STATUS_RESOURCE_IN_USE;
709
0
  }
710
711
0
  status = leases_db_del(client_guid, lease_key, &id);
712
0
  if (!NT_STATUS_IS_OK(status)) {
713
0
    int level = DBGLVL_DEBUG;
714
715
0
    if (!NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
716
0
      level = DBGLVL_ERR;
717
0
    }
718
0
    DBG_PREFIX(level, ("leases_db_del failed: %s\n",
719
0
         nt_errstr(status)));
720
0
  }
721
0
  return status;
722
0
}
723
724
bool share_entry_stale_pid(struct share_mode_entry *e)
725
0
{
726
0
  struct server_id_buf buf;
727
0
  bool exists;
728
729
0
  if (e->stale) {
730
0
    return true;
731
0
  }
732
733
0
  exists = serverid_exists(&e->pid);
734
0
  if (exists) {
735
0
    DBG_DEBUG("PID %s still exists\n",
736
0
        server_id_str_buf(e->pid, &buf));
737
0
    return false;
738
0
  }
739
740
0
  DBG_DEBUG("PID %s does not exist anymore\n",
741
0
      server_id_str_buf(e->pid, &buf));
742
743
0
  e->stale = true;
744
745
0
  return true;
746
0
}
747
748
/****************************************************************************
749
 Adds a delete on close token.
750
****************************************************************************/
751
752
static bool add_delete_on_close_token(struct share_mode_data *d,
753
      struct files_struct *fsp,
754
      const struct security_token *nt_tok,
755
      const struct security_unix_token *tok)
756
0
{
757
0
  struct delete_token *tmp, *dtl;
758
0
  const struct smb2_lease *lease = NULL;
759
760
0
  tmp = talloc_realloc(d, d->delete_tokens, struct delete_token,
761
0
           d->num_delete_tokens+1);
762
0
  if (tmp == NULL) {
763
0
    return false;
764
0
  }
765
0
  d->delete_tokens = tmp;
766
0
  dtl = &d->delete_tokens[d->num_delete_tokens];
767
768
0
  dtl->name_hash = fsp->name_hash;
769
770
0
  lease = fsp_get_smb2_lease(fsp);
771
0
  if (lease != NULL) {
772
0
    dtl->parent_lease_key = lease->parent_lease_key;
773
0
  }
774
775
0
  dtl->delete_nt_token = security_token_duplicate(d->delete_tokens, nt_tok);
776
0
  if (dtl->delete_nt_token == NULL) {
777
0
    return false;
778
0
  }
779
0
  dtl->delete_token = copy_unix_token(d->delete_tokens, tok);
780
0
  if (dtl->delete_token == NULL) {
781
0
    return false;
782
0
  }
783
0
  d->num_delete_tokens += 1;
784
0
  d->modified = true;
785
0
  return true;
786
0
}
787
788
void reset_delete_on_close_lck(files_struct *fsp,
789
             struct share_mode_lock *lck)
790
0
{
791
0
  struct share_mode_data *d = NULL;
792
0
  NTSTATUS status;
793
0
  uint32_t i;
794
795
0
  status = share_mode_lock_access_private_data(lck, &d);
796
0
  if (!NT_STATUS_IS_OK(status)) {
797
    /* Any error recovery possible here ? */
798
0
    DBG_ERR("share_mode_lock_access_private_data() failed for "
799
0
      "%s - %s\n", fsp_str_dbg(fsp), nt_errstr(status));
800
0
    smb_panic(__location__);
801
0
    return;
802
0
  }
803
804
0
  for (i=0; i<d->num_delete_tokens; i++) {
805
0
    struct delete_token *dt = &d->delete_tokens[i];
806
807
0
    if (dt->name_hash == fsp->name_hash) {
808
0
      d->modified = true;
809
810
      /* Delete this entry. */
811
0
      TALLOC_FREE(dt->delete_nt_token);
812
0
      TALLOC_FREE(dt->delete_token);
813
0
      *dt = d->delete_tokens[d->num_delete_tokens-1];
814
0
      d->num_delete_tokens -= 1;
815
0
    }
816
0
  }
817
0
}
818
819
struct set_delete_on_close_state {
820
  struct messaging_context *msg_ctx;
821
  DATA_BLOB blob;
822
};
823
824
static bool set_delete_on_close_fn(
825
  struct share_mode_entry *e,
826
  bool *modified,
827
  void *private_data)
828
0
{
829
0
  struct set_delete_on_close_state *state = private_data;
830
0
  NTSTATUS status;
831
832
0
  status = messaging_send(
833
0
    state->msg_ctx,
834
0
    e->pid,
835
0
    MSG_SMB_NOTIFY_CANCEL_DELETED,
836
0
    &state->blob);
837
838
0
  if (!NT_STATUS_IS_OK(status)) {
839
0
    struct server_id_buf tmp;
840
0
    DBG_DEBUG("messaging_send to %s returned %s\n",
841
0
        server_id_str_buf(e->pid, &tmp),
842
0
        nt_errstr(status));
843
0
  }
844
845
0
  return false;
846
0
}
847
848
/****************************************************************************
849
 Sets the delete on close flag over all share modes on this file.
850
 Modify the share mode entry for all files open
851
 on this device and inode to tell other smbds we have
852
 changed the delete on close flag. This will be noticed
853
 in the close code, the last closer will delete the file
854
 if flag is set.
855
 This makes a copy of any struct security_unix_token into the
856
 lck entry. This function is used when the lock is already granted.
857
****************************************************************************/
858
859
void set_delete_on_close_lck(files_struct *fsp,
860
      struct share_mode_lock *lck,
861
      const struct security_token *nt_tok,
862
      const struct security_unix_token *tok)
863
0
{
864
0
  struct share_mode_data *d = NULL;
865
0
  struct set_delete_on_close_state state = {
866
0
    .msg_ctx = fsp->conn->sconn->msg_ctx
867
0
  };
868
0
  uint32_t i;
869
0
  bool ret;
870
0
  enum ndr_err_code ndr_err;
871
0
  NTSTATUS status;
872
873
0
  status = share_mode_lock_access_private_data(lck, &d);
874
0
  if (!NT_STATUS_IS_OK(status)) {
875
    /* Any error recovery possible here ? */
876
0
    DBG_ERR("share_mode_lock_access_private_data() failed for "
877
0
      "%s - %s\n", fsp_str_dbg(fsp), nt_errstr(status));
878
0
    smb_panic(__location__);
879
0
    return;
880
0
  }
881
882
0
  SMB_ASSERT(nt_tok != NULL);
883
0
  SMB_ASSERT(tok != NULL);
884
885
0
  for (i=0; i<d->num_delete_tokens; i++) {
886
0
    struct delete_token *dt = &d->delete_tokens[i];
887
0
    if (dt->name_hash == fsp->name_hash) {
888
0
      const struct smb2_lease *lease = NULL;
889
890
0
      d->modified = true;
891
892
      /* Replace this token with the given tok. */
893
0
      ZERO_STRUCT(dt->parent_lease_key);
894
0
      lease = fsp_get_smb2_lease(fsp);
895
0
      if (lease != NULL) {
896
0
        dt->parent_lease_key = lease->parent_lease_key;
897
0
      }
898
899
0
      TALLOC_FREE(dt->delete_nt_token);
900
0
      dt->delete_nt_token = security_token_duplicate(dt, nt_tok);
901
0
      SMB_ASSERT(dt->delete_nt_token != NULL);
902
0
      TALLOC_FREE(dt->delete_token);
903
0
      dt->delete_token = copy_unix_token(dt, tok);
904
0
      SMB_ASSERT(dt->delete_token != NULL);
905
906
0
      return;
907
0
    }
908
0
  }
909
910
0
  ret = add_delete_on_close_token(d, fsp, nt_tok, tok);
911
0
  SMB_ASSERT(ret);
912
913
0
  ndr_err = ndr_push_struct_blob(
914
0
    &state.blob,
915
0
    talloc_tos(),
916
0
    &fsp->file_id,
917
0
    (ndr_push_flags_fn_t)ndr_push_file_id);
918
0
  if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
919
0
    DBG_ERR("ndr_push_file_id failed: %s\n",
920
0
      ndr_errstr(ndr_err));
921
0
    smb_panic(__location__);
922
0
  }
923
924
0
  ret = share_mode_forall_entries(
925
0
    lck, set_delete_on_close_fn, &state);
926
0
  if (!ret) {
927
0
    DBG_ERR("share_mode_forall_entries failed\n");
928
0
    smb_panic(__location__);
929
0
  }
930
931
0
  TALLOC_FREE(state.blob.data);
932
0
}
933
934
struct set_delete_on_close_locked_state {
935
  struct files_struct *fsp;
936
  bool delete_on_close;
937
  const struct security_token *nt_tok;
938
  const struct security_unix_token *tok;
939
};
940
941
static void set_delete_on_close_locked(struct share_mode_lock *lck,
942
               void *private_data)
943
0
{
944
0
  struct set_delete_on_close_locked_state *state =
945
0
    (struct set_delete_on_close_locked_state *)private_data;
946
947
0
  if (state->delete_on_close) {
948
0
    set_delete_on_close_lck(state->fsp,
949
0
          lck,
950
0
          state->nt_tok,
951
0
          state->tok);
952
0
  } else {
953
0
    reset_delete_on_close_lck(state->fsp, lck);
954
0
  }
955
956
0
  state->fsp->fsp_flags.delete_on_close = state->delete_on_close;
957
0
}
958
959
bool set_delete_on_close(files_struct *fsp, bool delete_on_close,
960
      const struct security_token *nt_tok,
961
      const struct security_unix_token *tok)
962
0
{
963
0
  struct set_delete_on_close_locked_state state = {
964
0
    .fsp = fsp,
965
0
    .delete_on_close = delete_on_close,
966
0
    .nt_tok = nt_tok,
967
0
    .tok = tok,
968
0
  };
969
0
  NTSTATUS status;
970
971
0
  DEBUG(10,("set_delete_on_close: %s delete on close flag for "
972
0
      "%s, file %s\n",
973
0
      delete_on_close ? "Adding" : "Removing", fsp_fnum_dbg(fsp),
974
0
      fsp_str_dbg(fsp)));
975
976
0
  if (fsp->fsp_flags.is_directory) {
977
0
    SMB_ASSERT(!is_ntfs_stream_smb_fname(fsp->fsp_name));
978
0
  }
979
980
0
  status = share_mode_do_locked_vfs_denied(fsp->file_id,
981
0
             set_delete_on_close_locked,
982
0
             &state);
983
0
  if (!NT_STATUS_IS_OK(status)) {
984
0
    return false;
985
0
  }
986
987
0
  return True;
988
0
}
989
990
static struct delete_token *find_delete_on_close_token(
991
  struct share_mode_data *d, uint32_t name_hash)
992
0
{
993
0
  uint32_t i;
994
995
0
  DBG_DEBUG("name_hash = 0x%"PRIx32"\n", name_hash);
996
997
0
  for (i=0; i<d->num_delete_tokens; i++) {
998
0
    struct delete_token *dt = &d->delete_tokens[i];
999
1000
0
    DBG_DEBUG("dt->name_hash = 0x%"PRIx32"\n",
1001
0
        dt->name_hash);
1002
0
    if (dt->name_hash == name_hash) {
1003
0
      return dt;
1004
0
    }
1005
0
  }
1006
0
  return NULL;
1007
0
}
1008
1009
/****************************************************************************
1010
 Return the NT token and UNIX token if there's a match. Return true if
1011
 found, false if not.
1012
****************************************************************************/
1013
1014
bool get_delete_on_close_token(struct share_mode_lock *lck,
1015
          uint32_t name_hash,
1016
          const struct security_token **pp_nt_tok,
1017
          const struct security_unix_token **pp_tok,
1018
          struct smb2_lease_key *parent_lease_key)
1019
0
{
1020
0
  struct share_mode_data *d = NULL;
1021
0
  struct delete_token *dt;
1022
0
  NTSTATUS status;
1023
1024
0
  status = share_mode_lock_access_private_data(lck, &d);
1025
0
  if (!NT_STATUS_IS_OK(status)) {
1026
0
    struct file_id id = share_mode_lock_file_id(lck);
1027
0
    struct file_id_buf id_buf;
1028
    /* Any error recovery possible here ? */
1029
0
    DBG_ERR("share_mode_lock_access_private_data() failed for "
1030
0
      "%s name_hash=%"PRIu32" - %s\n",
1031
0
      file_id_str_buf(id, &id_buf), name_hash,
1032
0
      nt_errstr(status));
1033
0
    return false;
1034
0
  }
1035
1036
0
  dt = find_delete_on_close_token(d, name_hash);
1037
0
  if (dt == NULL) {
1038
0
    return false;
1039
0
  }
1040
0
  *pp_nt_tok = dt->delete_nt_token;
1041
0
  *pp_tok =  dt->delete_token;
1042
0
  *parent_lease_key = dt->parent_lease_key;
1043
0
  return true;
1044
0
}
1045
1046
bool is_delete_on_close_set(struct share_mode_lock *lck, uint32_t name_hash)
1047
0
{
1048
0
  struct share_mode_data *d = NULL;
1049
0
  NTSTATUS status;
1050
1051
0
  status = share_mode_lock_access_private_data(lck, &d);
1052
0
  if (!NT_STATUS_IS_OK(status)) {
1053
0
    struct file_id id = share_mode_lock_file_id(lck);
1054
0
    struct file_id_buf id_buf;
1055
    /* Any error recovery possible here ? */
1056
0
    DBG_ERR("share_mode_lock_access_private_data() failed for "
1057
0
      "%s name_hash=%"PRIu32" - %s\n",
1058
0
      file_id_str_buf(id, &id_buf), name_hash,
1059
0
      nt_errstr(status));
1060
0
    return false;
1061
0
  }
1062
1063
0
  return find_delete_on_close_token(d, name_hash) != NULL;
1064
0
}
1065
1066
struct file_has_open_streams_state {
1067
  bool found_one;
1068
  bool ok;
1069
};
1070
1071
static bool file_has_open_streams_fn(
1072
  struct share_mode_entry *e,
1073
  bool *modified,
1074
  void *private_data)
1075
0
{
1076
0
  struct file_has_open_streams_state *state = private_data;
1077
1078
0
  if (!(e->flags & SHARE_ENTRY_FLAG_STREAM_BASEOPEN)) {
1079
0
    return false;
1080
0
  }
1081
1082
0
  if (share_entry_stale_pid(e)) {
1083
0
    return false;
1084
0
  }
1085
1086
0
  state->found_one = true;
1087
0
  return true;
1088
0
}
1089
1090
static void file_has_open_streams_locked(struct share_mode_lock *lck,
1091
           void *private_data)
1092
0
{
1093
0
  struct file_has_open_streams_state *state = private_data;
1094
1095
0
  state->ok = share_mode_forall_entries(lck,
1096
0
                file_has_open_streams_fn,
1097
0
                private_data);
1098
0
}
1099
1100
bool file_has_open_streams(files_struct *fsp)
1101
0
{
1102
0
  struct file_has_open_streams_state state = { .found_one = false };
1103
0
  NTSTATUS status;
1104
1105
0
  status = share_mode_do_locked_vfs_denied(fsp->file_id,
1106
0
             file_has_open_streams_locked,
1107
0
             &state);
1108
0
  if (!NT_STATUS_IS_OK(status)) {
1109
0
    DBG_DEBUG("share_mode_do_locked_vfs_denied() failed - %s\n",
1110
0
        nt_errstr(status));
1111
0
    return false;
1112
0
  }
1113
1114
0
  if (!state.ok) {
1115
0
    DBG_DEBUG("share_mode_forall_entries failed\n");
1116
0
    return false;
1117
0
  }
1118
1119
0
  return state.found_one;
1120
0
}
1121
1122
/*
1123
 * Walk share mode entries, looking at every lease only once
1124
 */
1125
1126
struct share_mode_forall_leases_state {
1127
  TALLOC_CTX *mem_ctx;
1128
  struct leases_db_key *leases;
1129
  bool (*fn)(struct share_mode_entry *e,
1130
       void *private_data);
1131
  void *private_data;
1132
  NTSTATUS status;
1133
};
1134
1135
static bool share_mode_forall_leases_fn(
1136
  struct share_mode_entry *e,
1137
  bool *modified,
1138
  void *private_data)
1139
0
{
1140
0
  struct share_mode_forall_leases_state *state = private_data;
1141
0
  struct leases_db_key *leases = state->leases;
1142
0
  size_t i, num_leases;
1143
0
  bool stop;
1144
1145
0
  if (e->op_type != LEASE_OPLOCK) {
1146
0
    return false;
1147
0
  }
1148
1149
0
  num_leases = talloc_array_length(leases);
1150
1151
0
  for (i=0; i<num_leases; i++) {
1152
0
    struct leases_db_key *l = &leases[i];
1153
0
    bool same = smb2_lease_equal(
1154
0
      &e->client_guid,
1155
0
      &e->lease_key,
1156
0
      &l->client_guid,
1157
0
      &l->lease_key);
1158
0
    if (same) {
1159
0
      return false;
1160
0
    }
1161
0
  }
1162
1163
0
  leases = talloc_realloc(
1164
0
    state->mem_ctx,
1165
0
    leases,
1166
0
    struct leases_db_key,
1167
0
    num_leases+1);
1168
0
  if (leases == NULL) {
1169
0
    state->status = NT_STATUS_NO_MEMORY;
1170
0
    return true;
1171
0
  }
1172
0
  leases[num_leases] = (struct leases_db_key) {
1173
0
    .client_guid = e->client_guid,
1174
0
    .lease_key = e->lease_key,
1175
0
  };
1176
0
  state->leases = leases;
1177
1178
0
  stop = state->fn(e, state->private_data);
1179
0
  return stop;
1180
0
}
1181
1182
bool share_mode_forall_leases(
1183
  struct share_mode_lock *lck,
1184
  bool (*fn)(struct share_mode_entry *e,
1185
       void *private_data),
1186
  void *private_data)
1187
0
{
1188
0
  struct share_mode_forall_leases_state state = {
1189
0
    .mem_ctx = talloc_tos(),
1190
0
    .fn = fn,
1191
0
    .private_data = private_data
1192
0
  };
1193
0
  bool ok;
1194
1195
0
  ok = share_mode_forall_entries(
1196
0
    lck, share_mode_forall_leases_fn, &state);
1197
0
  TALLOC_FREE(state.leases);
1198
0
  if (!ok) {
1199
0
    DBG_ERR("share_mode_forall_entries failed\n");
1200
0
    return false;
1201
0
  }
1202
1203
0
  if (!NT_STATUS_IS_OK(state.status)) {
1204
0
    DBG_ERR("share_mode_forall_leases_fn returned %s\n",
1205
0
      nt_errstr(state.status));
1206
0
    return false;
1207
0
  }
1208
1209
0
  return true;
1210
0
}