Line data Source code
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 "system/filesys.h"
40 : #include "lib/util/server_id.h"
41 : #include "share_mode_lock.h"
42 : #include "share_mode_lock_private.h"
43 : #include "locking/proto.h"
44 : #include "smbd/globals.h"
45 : #include "dbwrap/dbwrap.h"
46 : #include "dbwrap/dbwrap_open.h"
47 : #include "dbwrap/dbwrap_private.h"
48 : #include "../libcli/security/security.h"
49 : #include "serverid.h"
50 : #include "messages.h"
51 : #include "util_tdb.h"
52 : #include "../librpc/gen_ndr/ndr_open_files.h"
53 : #include "source3/lib/dbwrap/dbwrap_watch.h"
54 : #include "locking/leases_db.h"
55 : #include "../lib/util/memcache.h"
56 : #include "lib/util/tevent_ntstatus.h"
57 : #include "g_lock.h"
58 : #include "smbd/fd_handle.h"
59 : #include "lib/global_contexts.h"
60 :
61 : #undef DBGC_CLASS
62 : #define DBGC_CLASS DBGC_LOCKING
63 :
64 : #define NO_LOCKING_COUNT (-1)
65 :
66 : /* the locking database handle */
67 : static struct g_lock_ctx *lock_ctx;
68 :
69 73 : static bool locking_init_internal(bool read_only)
70 : {
71 : struct db_context *backend;
72 : char *db_path;
73 :
74 73 : brl_init(read_only);
75 :
76 73 : if (lock_ctx != NULL) {
77 0 : return True;
78 : }
79 :
80 73 : db_path = lock_path(talloc_tos(), "locking.tdb");
81 73 : if (db_path == NULL) {
82 0 : return false;
83 : }
84 :
85 73 : backend = db_open(NULL, db_path,
86 : SMB_OPEN_DATABASE_TDB_HASH_SIZE,
87 : TDB_DEFAULT|
88 : TDB_VOLATILE|
89 : TDB_CLEAR_IF_FIRST|
90 : TDB_INCOMPATIBLE_HASH|
91 : TDB_SEQNUM,
92 : read_only?O_RDONLY:O_RDWR|O_CREAT, 0644,
93 : DBWRAP_LOCK_ORDER_NONE,
94 : DBWRAP_FLAG_NONE);
95 73 : TALLOC_FREE(db_path);
96 73 : if (!backend) {
97 0 : DEBUG(0,("ERROR: Failed to initialise locking database\n"));
98 0 : return False;
99 : }
100 :
101 73 : lock_ctx = g_lock_ctx_init_backend(
102 : NULL, global_messaging_context(), &backend);
103 73 : if (lock_ctx == NULL) {
104 0 : TALLOC_FREE(backend);
105 0 : return false;
106 : }
107 73 : g_lock_set_lock_order(lock_ctx, DBWRAP_LOCK_ORDER_1);
108 :
109 73 : if (!posix_locking_init(read_only)) {
110 0 : TALLOC_FREE(lock_ctx);
111 0 : return False;
112 : }
113 :
114 73 : return True;
115 : }
116 :
117 73 : bool locking_init(void)
118 : {
119 73 : return locking_init_internal(false);
120 : }
121 :
122 0 : bool locking_init_readonly(void)
123 : {
124 0 : return locking_init_internal(true);
125 : }
126 :
127 : /*******************************************************************
128 : Deinitialize the share_mode management.
129 : ******************************************************************/
130 :
131 5270 : bool locking_end(void)
132 : {
133 5270 : brl_shutdown();
134 5270 : TALLOC_FREE(lock_ctx);
135 5270 : return true;
136 : }
137 :
138 : /*******************************************************************
139 : Form a static locking key for a dev/inode pair.
140 : ******************************************************************/
141 :
142 89133 : static TDB_DATA locking_key(const struct file_id *id)
143 : {
144 89133 : return make_tdb_data((const uint8_t *)id, sizeof(*id));
145 : }
146 :
147 : /*******************************************************************
148 : Share mode cache utility functions that store/delete/retrieve
149 : entries from memcache.
150 :
151 : For now share the statcache (global cache) memory space. If
152 : a lock record gets orphaned (which shouldn't happen as we're
153 : using the same locking_key data as lookup) it will eventually
154 : fall out of the cache via the normal LRU trim mechanism. If
155 : necessary we can always make this a separate (smaller) cache.
156 : ******************************************************************/
157 :
158 27731 : static DATA_BLOB memcache_key(const struct file_id *id)
159 : {
160 27731 : return data_blob_const((const void *)id, sizeof(*id));
161 : }
162 :
163 10161 : static void share_mode_memcache_store(struct share_mode_data *d)
164 : {
165 10161 : const DATA_BLOB key = memcache_key(&d->id);
166 : struct file_id_buf idbuf;
167 :
168 10161 : DBG_DEBUG("stored entry for file %s epoch %"PRIx64" key %s\n",
169 : d->base_name,
170 : d->unique_content_epoch,
171 : file_id_str_buf(d->id, &idbuf));
172 :
173 : /* Ensure everything stored in the cache is pristine. */
174 10161 : d->modified = false;
175 10161 : d->fresh = false;
176 :
177 : /*
178 : * Ensure the memory going into the cache
179 : * doesn't have a destructor so it can be
180 : * cleanly evicted by the memcache LRU
181 : * mechanism.
182 : */
183 10161 : talloc_set_destructor(d, NULL);
184 :
185 : /* Cache will own d after this call. */
186 10161 : memcache_add_talloc(NULL,
187 : SHARE_MODE_LOCK_CACHE,
188 : key,
189 : &d);
190 10161 : }
191 :
192 : /*
193 : * NB. We use ndr_pull_hyper on a stack-created
194 : * struct ndr_pull with no talloc allowed, as we
195 : * need this to be really fast as an ndr-peek into
196 : * the first 10 bytes of the blob.
197 : */
198 :
199 10627 : static enum ndr_err_code get_share_mode_blob_header(
200 : const uint8_t *buf, size_t buflen, uint64_t *pepoch, uint16_t *pflags)
201 : {
202 10627 : struct ndr_pull ndr = {
203 : .data = discard_const_p(uint8_t, buf),
204 : .data_size = buflen,
205 : };
206 10627 : NDR_CHECK(ndr_pull_hyper(&ndr, NDR_SCALARS, pepoch));
207 10627 : NDR_CHECK(ndr_pull_uint16(&ndr, NDR_SCALARS, pflags));
208 10627 : return NDR_ERR_SUCCESS;
209 : }
210 :
211 : struct fsp_update_share_mode_flags_state {
212 : enum ndr_err_code ndr_err;
213 : uint16_t share_mode_flags;
214 : };
215 :
216 467 : static void fsp_update_share_mode_flags_fn(
217 : const uint8_t *buf,
218 : size_t buflen,
219 : bool *modified_dependent,
220 : void *private_data)
221 : {
222 467 : struct fsp_update_share_mode_flags_state *state = private_data;
223 : uint64_t seq;
224 :
225 467 : state->ndr_err = get_share_mode_blob_header(
226 : buf, buflen, &seq, &state->share_mode_flags);
227 467 : }
228 :
229 467 : static NTSTATUS fsp_update_share_mode_flags(struct files_struct *fsp)
230 : {
231 467 : struct fsp_update_share_mode_flags_state state = {0};
232 467 : int seqnum = g_lock_seqnum(lock_ctx);
233 : NTSTATUS status;
234 :
235 467 : if (seqnum == fsp->share_mode_flags_seqnum) {
236 0 : return NT_STATUS_OK;
237 : }
238 :
239 467 : status = share_mode_do_locked(
240 : fsp->file_id, fsp_update_share_mode_flags_fn, &state);
241 467 : if (!NT_STATUS_IS_OK(status)) {
242 0 : DBG_DEBUG("share_mode_do_locked returned %s\n",
243 : nt_errstr(status));
244 0 : return status;
245 : }
246 :
247 467 : if (!NDR_ERR_CODE_IS_SUCCESS(state.ndr_err)) {
248 0 : DBG_DEBUG("get_share_mode_blob_header returned %s\n",
249 : ndr_errstr(state.ndr_err));
250 0 : return ndr_map_error2ntstatus(state.ndr_err);
251 : }
252 :
253 467 : fsp->share_mode_flags_seqnum = seqnum;
254 467 : fsp->share_mode_flags = state.share_mode_flags;
255 :
256 467 : return NT_STATUS_OK;
257 : }
258 :
259 467 : bool file_has_read_lease(struct files_struct *fsp)
260 : {
261 : NTSTATUS status;
262 :
263 467 : status = fsp_update_share_mode_flags(fsp);
264 467 : if (!NT_STATUS_IS_OK(status)) {
265 : /* Safe default for leases */
266 0 : return true;
267 : }
268 :
269 467 : return (fsp->share_mode_flags & SHARE_MODE_LEASE_READ) != 0;
270 : }
271 :
272 10159 : static int share_mode_data_nofree_destructor(struct share_mode_data *d)
273 : {
274 10159 : return -1;
275 : }
276 :
277 17570 : static struct share_mode_data *share_mode_memcache_fetch(
278 : TALLOC_CTX *mem_ctx,
279 : struct file_id id,
280 : const uint8_t *buf,
281 : size_t buflen)
282 : {
283 17570 : const DATA_BLOB key = memcache_key(&id);
284 : enum ndr_err_code ndr_err;
285 : struct share_mode_data *d;
286 : uint64_t unique_content_epoch;
287 : uint16_t flags;
288 : void *ptr;
289 : struct file_id_buf idbuf;
290 :
291 17570 : ptr = memcache_lookup_talloc(NULL,
292 : SHARE_MODE_LOCK_CACHE,
293 : key);
294 17570 : if (ptr == NULL) {
295 7410 : DBG_DEBUG("failed to find entry for key %s\n",
296 : file_id_str_buf(id, &idbuf));
297 7410 : return NULL;
298 : }
299 : /* sequence number key is at start of blob. */
300 10160 : ndr_err = get_share_mode_blob_header(
301 : buf, buflen, &unique_content_epoch, &flags);
302 10160 : if (ndr_err != NDR_ERR_SUCCESS) {
303 : /* Bad blob. Remove entry. */
304 0 : DBG_DEBUG("bad blob %u key %s\n",
305 : (unsigned int)ndr_err,
306 : file_id_str_buf(id, &idbuf));
307 0 : memcache_delete(NULL,
308 : SHARE_MODE_LOCK_CACHE,
309 : key);
310 0 : return NULL;
311 : }
312 :
313 10160 : d = (struct share_mode_data *)ptr;
314 10160 : if (d->unique_content_epoch != unique_content_epoch) {
315 1 : DBG_DEBUG("epoch changed (cached %"PRIx64") (new %"PRIx64") "
316 : "for key %s\n",
317 : d->unique_content_epoch,
318 : unique_content_epoch,
319 : file_id_str_buf(id, &idbuf));
320 : /* Cache out of date. Remove entry. */
321 1 : memcache_delete(NULL,
322 : SHARE_MODE_LOCK_CACHE,
323 : key);
324 1 : return NULL;
325 : }
326 :
327 : /* Move onto mem_ctx. */
328 10159 : d = talloc_move(mem_ctx, &ptr);
329 :
330 : /*
331 : * Now we own d, prevent the cache from freeing it
332 : * when we delete the entry.
333 : */
334 10159 : talloc_set_destructor(d, share_mode_data_nofree_destructor);
335 :
336 : /* Remove from the cache. We own it now. */
337 10159 : memcache_delete(NULL,
338 : SHARE_MODE_LOCK_CACHE,
339 : key);
340 :
341 : /* And reset the destructor to none. */
342 10159 : talloc_set_destructor(d, NULL);
343 :
344 10159 : DBG_DEBUG("fetched entry for file %s epoch %"PRIx64" key %s\n",
345 : d->base_name,
346 : d->unique_content_epoch,
347 : file_id_str_buf(id, &idbuf));
348 :
349 10159 : return d;
350 : }
351 :
352 : /*
353 : * 132 is the sizeof an ndr-encoded struct share_mode_entry_buf.
354 : * Reading/writing entries will immediately error out if this
355 : * size differs (push/pull is done without allocs).
356 : */
357 :
358 : struct share_mode_entry_buf {
359 : uint8_t buf[132];
360 : };
361 : #define SHARE_MODE_ENTRY_SIZE (sizeof(struct share_mode_entry_buf))
362 :
363 12190 : static bool share_mode_entry_put(
364 : const struct share_mode_entry *e,
365 : struct share_mode_entry_buf *dst)
366 : {
367 12190 : DATA_BLOB blob = { .data = dst->buf, .length = sizeof(dst->buf) };
368 : enum ndr_err_code ndr_err;
369 :
370 12190 : if (DEBUGLEVEL>=10) {
371 0 : DBG_DEBUG("share_mode_entry:\n");
372 0 : NDR_PRINT_DEBUG(share_mode_entry, discard_const_p(void, e));
373 : }
374 :
375 12190 : ndr_err = ndr_push_struct_into_fixed_blob(
376 : &blob,
377 : e,
378 : (ndr_push_flags_fn_t)ndr_push_share_mode_entry);
379 12190 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
380 0 : DBG_WARNING("ndr_push_share_mode_entry failed: %s\n",
381 : ndr_errstr(ndr_err));
382 0 : return false;
383 : }
384 :
385 12190 : return true;
386 : }
387 :
388 18499 : static bool share_mode_entry_get(
389 : const uint8_t ptr[SHARE_MODE_ENTRY_SIZE], struct share_mode_entry *e)
390 : {
391 18499 : enum ndr_err_code ndr_err = NDR_ERR_SUCCESS;
392 18499 : DATA_BLOB blob = {
393 : .data = discard_const_p(uint8_t, ptr),
394 : .length = SHARE_MODE_ENTRY_SIZE,
395 : };
396 :
397 18499 : ndr_err = ndr_pull_struct_blob_all_noalloc(
398 : &blob, e, (ndr_pull_flags_fn_t)ndr_pull_share_mode_entry);
399 18499 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
400 0 : DBG_WARNING("ndr_pull_share_mode_entry failed\n");
401 0 : return false;
402 : }
403 18499 : return true;
404 : }
405 :
406 : /*
407 : * locking.tdb records consist of
408 : *
409 : * uint32_t share_mode_data_len
410 : * uint8_t [share_mode_data] This is struct share_mode_data in NDR
411 : *
412 : * 0 [SHARE_MODE_ENTRY_SIZE] Sorted array of share modes,
413 : * 1 [SHARE_MODE_ENTRY_SIZE] filling up the rest of the data in the
414 : * 2 [SHARE_MODE_ENTRY_SIZE] g_lock.c maintained record in locking.tdb
415 : */
416 :
417 : struct locking_tdb_data {
418 : const uint8_t *share_mode_data_buf;
419 : size_t share_mode_data_len;
420 : const uint8_t *share_entries;
421 : size_t num_share_entries;
422 : };
423 :
424 55470 : static bool locking_tdb_data_get(
425 : struct locking_tdb_data *data, const uint8_t *buf, size_t buflen)
426 : {
427 : uint32_t share_mode_data_len, share_entries_len;
428 :
429 55470 : if (buflen == 0) {
430 0 : *data = (struct locking_tdb_data) { 0 };
431 0 : return true;
432 : }
433 55470 : if (buflen < sizeof(uint32_t)) {
434 0 : return false;
435 : }
436 :
437 55470 : share_mode_data_len = PULL_LE_U32(buf, 0);
438 :
439 55470 : buf += sizeof(uint32_t);
440 55470 : buflen -= sizeof(uint32_t);
441 :
442 55470 : if (buflen < share_mode_data_len) {
443 0 : return false;
444 : }
445 :
446 55470 : share_entries_len = buflen - share_mode_data_len;
447 :
448 55470 : if ((share_entries_len % SHARE_MODE_ENTRY_SIZE) != 0) {
449 0 : return false;
450 : }
451 :
452 105193 : *data = (struct locking_tdb_data) {
453 : .share_mode_data_buf = buf,
454 : .share_mode_data_len = share_mode_data_len,
455 55470 : .share_entries = buf + share_mode_data_len,
456 55470 : .num_share_entries = share_entries_len / SHARE_MODE_ENTRY_SIZE,
457 : };
458 :
459 55470 : return true;
460 : }
461 :
462 : struct locking_tdb_data_fetch_state {
463 : TALLOC_CTX *mem_ctx;
464 : uint8_t *data;
465 : size_t datalen;
466 : };
467 :
468 54738 : static void locking_tdb_data_fetch_fn(
469 : struct server_id exclusive,
470 : size_t num_shared,
471 : const struct server_id *shared,
472 : const uint8_t *data,
473 : size_t datalen,
474 : void *private_data)
475 : {
476 54738 : struct locking_tdb_data_fetch_state *state = private_data;
477 54738 : state->datalen = datalen;
478 54738 : state->data = talloc_memdup(state->mem_ctx, data, datalen);
479 54738 : }
480 :
481 54738 : static NTSTATUS locking_tdb_data_fetch(
482 : TDB_DATA key, TALLOC_CTX *mem_ctx, struct locking_tdb_data **ltdb)
483 : {
484 54738 : struct locking_tdb_data_fetch_state state = { 0 };
485 54738 : struct locking_tdb_data *result = NULL;
486 : NTSTATUS status;
487 : bool ok;
488 :
489 54738 : result = talloc_zero(mem_ctx, struct locking_tdb_data);
490 54738 : if (result == NULL) {
491 0 : return NT_STATUS_NO_MEMORY;
492 : }
493 54738 : state.mem_ctx = result;
494 :
495 54738 : status = g_lock_dump(lock_ctx, key, locking_tdb_data_fetch_fn, &state);
496 :
497 54738 : if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
498 : /*
499 : * Just return an empty record
500 : */
501 0 : goto done;
502 : }
503 54738 : if (!NT_STATUS_IS_OK(status)) {
504 0 : DBG_DEBUG("g_lock_dump failed: %s\n", nt_errstr(status));
505 0 : return status;
506 : }
507 54738 : if (state.datalen == 0) {
508 17442 : goto done;
509 : }
510 :
511 37296 : ok = locking_tdb_data_get(result, state.data, state.datalen);
512 37296 : if (!ok) {
513 0 : DBG_DEBUG("locking_tdb_data_get failed for %zu bytes\n",
514 : state.datalen);
515 0 : TALLOC_FREE(result);
516 0 : return NT_STATUS_INTERNAL_DB_CORRUPTION;
517 : }
518 :
519 37296 : done:
520 54738 : *ltdb = result;
521 54738 : return NT_STATUS_OK;
522 : }
523 :
524 43336 : static NTSTATUS locking_tdb_data_store(
525 : TDB_DATA key,
526 : const struct locking_tdb_data *ltdb,
527 : const TDB_DATA *share_mode_dbufs,
528 : size_t num_share_mode_dbufs)
529 43336 : {
530 : uint8_t share_mode_data_len_buf[4];
531 43336 : TDB_DATA dbufs[num_share_mode_dbufs+3];
532 : NTSTATUS status;
533 :
534 58762 : if ((ltdb->share_mode_data_len == 0) &&
535 33224 : (ltdb->num_share_entries == 0) &&
536 : (num_share_mode_dbufs == 0)) {
537 : /*
538 : * Nothing to write
539 : */
540 8899 : status = g_lock_write_data(lock_ctx, key, NULL, 0);
541 8899 : if (!NT_STATUS_IS_OK(status)) {
542 0 : DBG_DEBUG("g_lock_writev_data() failed: %s\n",
543 : nt_errstr(status));
544 : }
545 8899 : return status;
546 : }
547 :
548 34437 : PUSH_LE_U32(share_mode_data_len_buf, 0, ltdb->share_mode_data_len);
549 :
550 34437 : dbufs[0] = (TDB_DATA) {
551 : .dptr = share_mode_data_len_buf,
552 : .dsize = sizeof(share_mode_data_len_buf),
553 : };
554 34437 : dbufs[1] = (TDB_DATA) {
555 34437 : .dptr = discard_const_p(uint8_t, ltdb->share_mode_data_buf),
556 34437 : .dsize = ltdb->share_mode_data_len,
557 : };
558 :
559 34437 : if (ltdb->num_share_entries > SIZE_MAX/SHARE_MODE_ENTRY_SIZE) {
560 : /* overflow */
561 0 : return NT_STATUS_BUFFER_OVERFLOW;
562 : }
563 34437 : dbufs[2] = (TDB_DATA) {
564 34437 : .dptr = discard_const_p(uint8_t, ltdb->share_entries),
565 34437 : .dsize = ltdb->num_share_entries * SHARE_MODE_ENTRY_SIZE,
566 : };
567 :
568 34437 : if (num_share_mode_dbufs != 0) {
569 12066 : memcpy(&dbufs[3],
570 : share_mode_dbufs,
571 : num_share_mode_dbufs * sizeof(TDB_DATA));
572 : }
573 :
574 34437 : status = g_lock_writev_data(lock_ctx, key, dbufs, ARRAY_SIZE(dbufs));
575 34437 : if (!NT_STATUS_IS_OK(status)) {
576 0 : DBG_DEBUG("g_lock_writev_data() failed: %s\n",
577 : nt_errstr(status));
578 : }
579 34437 : return status;
580 : }
581 :
582 : /*******************************************************************
583 : Get all share mode entries for a dev/inode pair.
584 : ********************************************************************/
585 :
586 17570 : static struct share_mode_data *parse_share_modes(
587 : TALLOC_CTX *mem_ctx,
588 : struct file_id id,
589 : const uint8_t *buf,
590 : size_t buflen)
591 : {
592 : struct share_mode_data *d;
593 : enum ndr_err_code ndr_err;
594 : DATA_BLOB blob;
595 :
596 : /* See if we already have a cached copy of this key. */
597 17570 : d = share_mode_memcache_fetch(mem_ctx, id, buf, buflen);
598 17570 : if (d != NULL) {
599 10159 : return d;
600 : }
601 :
602 7411 : d = talloc(mem_ctx, struct share_mode_data);
603 7411 : if (d == NULL) {
604 0 : DEBUG(0, ("talloc failed\n"));
605 0 : goto fail;
606 : }
607 :
608 7411 : blob = (DATA_BLOB) {
609 : .data = discard_const_p(uint8_t, buf),
610 : .length = buflen,
611 : };
612 7411 : ndr_err = ndr_pull_struct_blob_all(
613 : &blob, d, d, (ndr_pull_flags_fn_t)ndr_pull_share_mode_data);
614 7411 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
615 10 : DBG_WARNING("ndr_pull_share_mode_data failed: %s\n",
616 : ndr_errstr(ndr_err));
617 10 : goto fail;
618 : }
619 :
620 7401 : if (DEBUGLEVEL >= 10) {
621 0 : DEBUG(10, ("parse_share_modes:\n"));
622 0 : NDR_PRINT_DEBUG(share_mode_data, d);
623 : }
624 :
625 7401 : return d;
626 10 : fail:
627 10 : TALLOC_FREE(d);
628 10 : return NULL;
629 : }
630 :
631 : /*******************************************************************
632 : If modified, store the share_mode_data back into the database.
633 : ********************************************************************/
634 :
635 25411 : static NTSTATUS share_mode_data_store(
636 : struct share_mode_data *d, bool *have_share_entries)
637 : {
638 25411 : TDB_DATA key = locking_key(&d->id);
639 25411 : struct locking_tdb_data *ltdb = NULL;
640 25411 : DATA_BLOB blob = { 0 };
641 : NTSTATUS status;
642 :
643 25411 : if (!d->modified) {
644 6351 : DBG_DEBUG("not modified\n");
645 6351 : return NT_STATUS_OK;
646 : }
647 :
648 19060 : if (DEBUGLEVEL >= 10) {
649 0 : DBG_DEBUG("\n");
650 0 : NDR_PRINT_DEBUG(share_mode_data, d);
651 : }
652 :
653 19060 : d->unique_content_epoch = generate_unique_u64(d->unique_content_epoch);
654 :
655 19060 : status = locking_tdb_data_fetch(key, d, <db);
656 19060 : if (!NT_STATUS_IS_OK(status)) {
657 0 : return status;
658 : }
659 :
660 19060 : if (ltdb->num_share_entries != 0) {
661 : enum ndr_err_code ndr_err;
662 :
663 10161 : ndr_err = ndr_push_struct_blob(
664 : &blob,
665 : ltdb,
666 : d,
667 : (ndr_push_flags_fn_t)ndr_push_share_mode_data);
668 10161 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
669 0 : DBG_DEBUG("ndr_push_share_mode_data failed: %s\n",
670 : ndr_errstr(ndr_err));
671 0 : TALLOC_FREE(ltdb);
672 0 : return ndr_map_error2ntstatus(ndr_err);
673 : }
674 :
675 10161 : *have_share_entries = true;
676 : }
677 :
678 19060 : ltdb->share_mode_data_buf = blob.data;
679 19060 : ltdb->share_mode_data_len = blob.length;
680 :
681 19060 : status = locking_tdb_data_store(key, ltdb, NULL, 0);
682 19060 : TALLOC_FREE(ltdb);
683 19060 : return status;
684 : }
685 :
686 : /*******************************************************************
687 : Allocate a new share_mode_data struct, mark it unmodified.
688 : fresh is set to note that currently there is no database entry.
689 : ********************************************************************/
690 :
691 8899 : static struct share_mode_data *fresh_share_mode_lock(
692 : TALLOC_CTX *mem_ctx, const char *servicepath,
693 : const struct smb_filename *smb_fname,
694 : const struct timespec *old_write_time)
695 : {
696 : struct share_mode_data *d;
697 :
698 8899 : if ((servicepath == NULL) || (smb_fname == NULL) ||
699 : (old_write_time == NULL)) {
700 0 : return NULL;
701 : }
702 :
703 8899 : d = talloc_zero(mem_ctx, struct share_mode_data);
704 8899 : if (d == NULL) {
705 0 : goto fail;
706 : }
707 8899 : d->unique_content_epoch = generate_unique_u64(0);
708 :
709 8899 : d->base_name = talloc_strdup(d, smb_fname->base_name);
710 8899 : if (d->base_name == NULL) {
711 0 : goto fail;
712 : }
713 8899 : if (smb_fname->stream_name != NULL) {
714 64 : d->stream_name = talloc_strdup(d, smb_fname->stream_name);
715 64 : if (d->stream_name == NULL) {
716 0 : goto fail;
717 : }
718 : }
719 8899 : d->servicepath = talloc_strdup(d, servicepath);
720 8899 : if (d->servicepath == NULL) {
721 0 : goto fail;
722 : }
723 8899 : d->old_write_time = full_timespec_to_nt_time(old_write_time);
724 8899 : d->flags = SHARE_MODE_SHARE_DELETE |
725 : SHARE_MODE_SHARE_WRITE |
726 : SHARE_MODE_SHARE_READ;
727 8899 : d->modified = false;
728 8899 : d->fresh = true;
729 8899 : return d;
730 0 : fail:
731 0 : DEBUG(0, ("talloc failed\n"));
732 0 : TALLOC_FREE(d);
733 0 : return NULL;
734 : }
735 :
736 : /*
737 : * Key that's locked with g_lock
738 : */
739 : static uint8_t share_mode_lock_key_data[sizeof(struct file_id)];
740 : static TDB_DATA share_mode_lock_key = {
741 : .dptr = share_mode_lock_key_data,
742 : .dsize = sizeof(share_mode_lock_key_data),
743 : };
744 : static size_t share_mode_lock_key_refcount = 0;
745 :
746 : /*
747 : * We can only ever have one share mode locked. Use a static
748 : * share_mode_data pointer that is shared by multiple nested
749 : * share_mode_lock structures, explicitly refcounted.
750 : */
751 : static struct share_mode_data *static_share_mode_data = NULL;
752 : static size_t static_share_mode_data_refcount = 0;
753 :
754 : /*******************************************************************
755 : Either fetch a share mode from the database, or allocate a fresh
756 : one if the record doesn't exist.
757 : ********************************************************************/
758 :
759 : struct get_static_share_mode_data_state {
760 : TALLOC_CTX *mem_ctx;
761 : struct file_id id;
762 : const char *servicepath;
763 : const struct smb_filename *smb_fname;
764 : const struct timespec *old_write_time;
765 : NTSTATUS status;
766 : };
767 :
768 25412 : static void get_static_share_mode_data_fn(
769 : struct server_id exclusive,
770 : size_t num_shared,
771 : const struct server_id *shared,
772 : const uint8_t *data,
773 : size_t datalen,
774 : void *private_data)
775 : {
776 25412 : struct get_static_share_mode_data_state *state = private_data;
777 25412 : struct share_mode_data *d = NULL;
778 25412 : struct locking_tdb_data ltdb = { 0 };
779 :
780 25412 : if (datalen != 0) {
781 : bool ok;
782 :
783 16512 : ok = locking_tdb_data_get(<db, data, datalen);
784 16512 : if (!ok) {
785 0 : DBG_DEBUG("locking_tdb_data_get failed\n");
786 0 : state->status = NT_STATUS_INTERNAL_DB_CORRUPTION;
787 1 : return;
788 : }
789 : }
790 :
791 25412 : if (ltdb.share_mode_data_len == 0) {
792 8900 : if (state->smb_fname == NULL) {
793 1 : state->status = NT_STATUS_NOT_FOUND;
794 1 : return;
795 : }
796 8899 : d = fresh_share_mode_lock(
797 : state->mem_ctx,
798 : state->servicepath,
799 : state->smb_fname,
800 : state->old_write_time);
801 8899 : if (d == NULL) {
802 0 : state->status = NT_STATUS_NO_MEMORY;
803 0 : return;
804 : }
805 : } else {
806 16512 : d = parse_share_modes(
807 : lock_ctx,
808 : state->id,
809 : ltdb.share_mode_data_buf,
810 : ltdb.share_mode_data_len);
811 16512 : if (d == NULL) {
812 0 : state->status = NT_STATUS_INTERNAL_DB_CORRUPTION;
813 0 : return;
814 : }
815 : }
816 :
817 25411 : d->id = state->id;
818 25411 : static_share_mode_data = d;
819 : }
820 :
821 25412 : static NTSTATUS get_static_share_mode_data(
822 : struct file_id id,
823 : const char *servicepath,
824 : const struct smb_filename *smb_fname,
825 : const struct timespec *old_write_time)
826 : {
827 25412 : struct get_static_share_mode_data_state state = {
828 : .mem_ctx = lock_ctx,
829 : .id = id,
830 : .servicepath = servicepath,
831 : .smb_fname = smb_fname,
832 : .old_write_time = old_write_time,
833 : };
834 : NTSTATUS status;
835 :
836 25412 : SMB_ASSERT(static_share_mode_data == NULL);
837 :
838 25412 : status = g_lock_dump(
839 : lock_ctx,
840 : share_mode_lock_key,
841 : get_static_share_mode_data_fn,
842 : &state);
843 25412 : if (!NT_STATUS_IS_OK(status)) {
844 0 : DBG_DEBUG("g_lock_dump failed: %s\n",
845 : nt_errstr(status));
846 0 : return status;
847 : }
848 25412 : if (!NT_STATUS_IS_OK(state.status)) {
849 1 : DBG_DEBUG("get_static_share_mode_data_fn failed: %s\n",
850 : nt_errstr(state.status));
851 1 : return state.status;
852 : }
853 :
854 25411 : return NT_STATUS_OK;
855 : }
856 :
857 : /*******************************************************************
858 : Get a share_mode_lock, Reference counted to allow nested calls.
859 : ********************************************************************/
860 :
861 : static int share_mode_lock_destructor(struct share_mode_lock *lck);
862 :
863 25577 : struct share_mode_lock *get_share_mode_lock(
864 : TALLOC_CTX *mem_ctx,
865 : struct file_id id,
866 : const char *servicepath,
867 : const struct smb_filename *smb_fname,
868 : const struct timespec *old_write_time)
869 : {
870 25577 : TDB_DATA key = locking_key(&id);
871 25577 : struct share_mode_lock *lck = NULL;
872 : NTSTATUS status;
873 : int cmp;
874 :
875 25577 : lck = talloc(mem_ctx, struct share_mode_lock);
876 25577 : if (lck == NULL) {
877 0 : DEBUG(1, ("talloc failed\n"));
878 0 : return NULL;
879 : }
880 :
881 25577 : if (static_share_mode_data != NULL) {
882 165 : if (!file_id_equal(&static_share_mode_data->id, &id)) {
883 : struct file_id_buf existing;
884 : struct file_id_buf requested;
885 :
886 0 : DBG_ERR("Can not lock two share modes "
887 : "simultaneously: existing %s requested %s\n",
888 : file_id_str_buf(static_share_mode_data->id, &existing),
889 : file_id_str_buf(id, &requested));
890 :
891 0 : smb_panic(__location__);
892 : goto fail;
893 : }
894 165 : goto done;
895 : }
896 :
897 25412 : if (share_mode_lock_key_refcount == 0) {
898 25412 : status = g_lock_lock(
899 : lock_ctx,
900 : key,
901 : G_LOCK_WRITE,
902 25412 : (struct timeval) { .tv_sec = 3600 });
903 25412 : if (!NT_STATUS_IS_OK(status)) {
904 0 : DBG_DEBUG("g_lock_lock failed: %s\n",
905 : nt_errstr(status));
906 0 : goto fail;
907 : }
908 25412 : memcpy(share_mode_lock_key_data, key.dptr, key.dsize);
909 : }
910 :
911 25412 : cmp = tdb_data_cmp(share_mode_lock_key, key);
912 25412 : if (cmp != 0) {
913 0 : DBG_WARNING("Can not lock two share modes simultaneously\n");
914 0 : smb_panic(__location__);
915 : goto fail;
916 : }
917 :
918 25412 : SMB_ASSERT(share_mode_lock_key_refcount < SIZE_MAX);
919 25412 : share_mode_lock_key_refcount += 1;
920 :
921 25412 : SMB_ASSERT(static_share_mode_data_refcount == 0);
922 :
923 25412 : status = get_static_share_mode_data(
924 : id,
925 : servicepath,
926 : smb_fname,
927 : old_write_time);
928 25412 : if (!NT_STATUS_IS_OK(status)) {
929 1 : DBG_DEBUG("get_static_share_mode_data failed: %s\n",
930 : nt_errstr(status));
931 1 : share_mode_lock_key_refcount -= 1;
932 1 : goto fail;
933 : }
934 25411 : done:
935 25576 : static_share_mode_data_refcount += 1;
936 25576 : lck->data = static_share_mode_data;
937 :
938 25576 : talloc_set_destructor(lck, share_mode_lock_destructor);
939 :
940 25576 : if (CHECK_DEBUGLVL(DBGLVL_DEBUG)) {
941 : struct file_id_buf returned;
942 :
943 0 : DBG_DEBUG("Returning %s (data_refcount=%zu key_refcount=%zu)\n",
944 : file_id_str_buf(id, &returned),
945 : static_share_mode_data_refcount,
946 : share_mode_lock_key_refcount);
947 : }
948 :
949 25576 : return lck;
950 1 : fail:
951 1 : TALLOC_FREE(lck);
952 1 : if (share_mode_lock_key_refcount == 0) {
953 1 : status = g_lock_unlock(lock_ctx, share_mode_lock_key);
954 1 : if (!NT_STATUS_IS_OK(status)) {
955 0 : DBG_ERR("g_lock_unlock failed: %s\n",
956 : nt_errstr(status));
957 : }
958 : }
959 1 : return NULL;
960 : }
961 :
962 25576 : static int share_mode_lock_destructor(struct share_mode_lock *lck)
963 : {
964 25576 : bool have_share_entries = false;
965 : NTSTATUS status;
966 :
967 25576 : SMB_ASSERT(static_share_mode_data_refcount > 0);
968 25576 : static_share_mode_data_refcount -= 1;
969 :
970 25576 : if (static_share_mode_data_refcount > 0) {
971 165 : return 0;
972 : }
973 :
974 25411 : status = share_mode_data_store(
975 : static_share_mode_data, &have_share_entries);
976 25411 : if (!NT_STATUS_IS_OK(status)) {
977 0 : DBG_ERR("share_mode_data_store failed: %s\n",
978 : nt_errstr(status));
979 0 : smb_panic("Could not store share mode data\n");
980 : }
981 :
982 25411 : SMB_ASSERT(share_mode_lock_key_refcount > 0);
983 25411 : share_mode_lock_key_refcount -= 1;
984 :
985 25411 : if (share_mode_lock_key_refcount == 0) {
986 25411 : status = g_lock_unlock(lock_ctx, share_mode_lock_key);
987 25411 : if (!NT_STATUS_IS_OK(status)) {
988 0 : DBG_ERR("g_lock_unlock failed: %s\n",
989 : nt_errstr(status));
990 0 : smb_panic("Could not unlock share mode\n");
991 : }
992 : }
993 :
994 25411 : if (have_share_entries) {
995 : /*
996 : * This is worth keeping. Without share modes,
997 : * share_mode_data_store above has left nothing in the
998 : * database.
999 : */
1000 10161 : share_mode_memcache_store(static_share_mode_data);
1001 10161 : static_share_mode_data = NULL;
1002 : }
1003 :
1004 25411 : TALLOC_FREE(static_share_mode_data);
1005 25411 : return 0;
1006 : }
1007 :
1008 : /*******************************************************************
1009 : Fetch a share mode where we know one MUST exist. This call reference
1010 : counts it internally to allow for nested lock fetches.
1011 : ********************************************************************/
1012 :
1013 13497 : struct share_mode_lock *get_existing_share_mode_lock(TALLOC_CTX *mem_ctx,
1014 : const struct file_id id)
1015 : {
1016 13497 : return get_share_mode_lock(mem_ctx, id, NULL, NULL, NULL);
1017 : }
1018 :
1019 : struct share_mode_do_locked_state {
1020 : TDB_DATA key;
1021 : void (*fn)(const uint8_t *buf,
1022 : size_t buflen,
1023 : bool *modified_dependent,
1024 : void *private_data);
1025 : void *private_data;
1026 : };
1027 :
1028 604 : static void share_mode_do_locked_fn(
1029 : struct server_id exclusive,
1030 : size_t num_shared,
1031 : const struct server_id *shared,
1032 : const uint8_t *data,
1033 : size_t datalen,
1034 : void *private_data)
1035 : {
1036 604 : struct share_mode_do_locked_state *state = private_data;
1037 604 : bool modified_dependent = false;
1038 604 : struct locking_tdb_data ltdb = { 0 };
1039 : bool ok;
1040 :
1041 604 : ok = locking_tdb_data_get(
1042 : <db, discard_const_p(uint8_t, data), datalen);
1043 604 : if (!ok) {
1044 0 : DBG_WARNING("locking_tdb_data_get failed\n");
1045 0 : return;
1046 : }
1047 :
1048 604 : state->fn(ltdb.share_mode_data_buf,
1049 : ltdb.share_mode_data_len,
1050 : &modified_dependent,
1051 : state->private_data);
1052 :
1053 604 : if (modified_dependent) {
1054 128 : g_lock_wake_watchers(lock_ctx, state->key);
1055 : }
1056 : }
1057 :
1058 604 : NTSTATUS share_mode_do_locked(
1059 : struct file_id id,
1060 : void (*fn)(const uint8_t *buf,
1061 : size_t buflen,
1062 : bool *modified_dependent,
1063 : void *private_data),
1064 : void *private_data)
1065 : {
1066 604 : TDB_DATA key = locking_key(&id);
1067 : size_t data_refcount, key_refcount;
1068 604 : struct share_mode_do_locked_state state = {
1069 : .key = key, .fn = fn, .private_data = private_data,
1070 : };
1071 : NTSTATUS status;
1072 :
1073 604 : if (share_mode_lock_key_refcount == 0) {
1074 474 : status = g_lock_lock(
1075 : lock_ctx,
1076 : key,
1077 : G_LOCK_WRITE,
1078 474 : (struct timeval) { .tv_sec = 3600 });
1079 474 : if (!NT_STATUS_IS_OK(status)) {
1080 0 : DBG_DEBUG("g_lock_lock failed: %s\n",
1081 : nt_errstr(status));
1082 0 : return status;
1083 : }
1084 474 : memcpy(share_mode_lock_key_data, key.dptr, key.dsize);
1085 : }
1086 :
1087 604 : SMB_ASSERT(share_mode_lock_key_refcount < SIZE_MAX);
1088 604 : share_mode_lock_key_refcount += 1;
1089 :
1090 604 : key_refcount = share_mode_lock_key_refcount;
1091 604 : data_refcount = static_share_mode_data_refcount;
1092 :
1093 604 : status = g_lock_dump(
1094 : lock_ctx, key, share_mode_do_locked_fn, &state);
1095 604 : if (!NT_STATUS_IS_OK(status)) {
1096 0 : DBG_DEBUG("g_lock_dump failed: %s\n",
1097 : nt_errstr(status));
1098 : }
1099 :
1100 604 : SMB_ASSERT(data_refcount == static_share_mode_data_refcount);
1101 604 : SMB_ASSERT(key_refcount == share_mode_lock_key_refcount);
1102 604 : share_mode_lock_key_refcount -= 1;
1103 :
1104 604 : if (share_mode_lock_key_refcount == 0) {
1105 474 : status = g_lock_unlock(lock_ctx, key);
1106 474 : if (!NT_STATUS_IS_OK(status)) {
1107 0 : DBG_DEBUG("g_lock_unlock failed: %s\n",
1108 : nt_errstr(status));
1109 : }
1110 : }
1111 :
1112 604 : return status;
1113 : }
1114 :
1115 124 : static void share_mode_wakeup_waiters_fn(
1116 : const uint8_t *buf,
1117 : size_t buflen,
1118 : bool *modified_dependent,
1119 : void *private_data)
1120 : {
1121 124 : *modified_dependent = true;
1122 124 : }
1123 :
1124 124 : NTSTATUS share_mode_wakeup_waiters(struct file_id id)
1125 : {
1126 124 : return share_mode_do_locked(id, share_mode_wakeup_waiters_fn, NULL);
1127 : }
1128 :
1129 1 : NTTIME share_mode_changed_write_time(struct share_mode_lock *lck)
1130 : {
1131 1 : return lck->data->changed_write_time;
1132 : }
1133 :
1134 0 : const char *share_mode_servicepath(struct share_mode_lock *lck)
1135 : {
1136 0 : return lck->data->servicepath;
1137 : }
1138 :
1139 0 : char *share_mode_filename(TALLOC_CTX *mem_ctx, struct share_mode_lock *lck)
1140 : {
1141 0 : struct share_mode_data *d = lck->data;
1142 0 : bool has_stream = (d->stream_name != NULL);
1143 0 : char *fname = NULL;
1144 :
1145 0 : fname = talloc_asprintf(
1146 : mem_ctx,
1147 : "%s%s%s",
1148 : d->base_name,
1149 : has_stream ? ":" : "",
1150 : has_stream ? d->stream_name : "");
1151 0 : return fname;
1152 : }
1153 :
1154 0 : char *share_mode_data_dump(
1155 : TALLOC_CTX *mem_ctx, struct share_mode_lock *lck)
1156 : {
1157 0 : struct ndr_print *p = talloc(mem_ctx, struct ndr_print);
1158 0 : char *ret = NULL;
1159 :
1160 0 : if (p == NULL) {
1161 0 : return NULL;
1162 : }
1163 :
1164 0 : *p = (struct ndr_print) {
1165 : .print = ndr_print_string_helper,
1166 : .depth = 1,
1167 0 : .private_data = talloc_strdup(mem_ctx, ""),
1168 : };
1169 :
1170 0 : if (p->private_data == NULL) {
1171 0 : TALLOC_FREE(p);
1172 0 : return NULL;
1173 : }
1174 :
1175 0 : ndr_print_share_mode_data(p, "SHARE_MODE_DATA", lck->data);
1176 :
1177 0 : ret = p->private_data;
1178 :
1179 0 : TALLOC_FREE(p);
1180 :
1181 0 : return ret;
1182 : }
1183 :
1184 17309 : void share_mode_flags_get(
1185 : struct share_mode_lock *lck,
1186 : uint32_t *access_mask,
1187 : uint32_t *share_mode,
1188 : uint32_t *lease_type)
1189 : {
1190 17309 : uint16_t flags = lck->data->flags;
1191 :
1192 17309 : if (access_mask != NULL) {
1193 17309 : *access_mask =
1194 : ((flags & SHARE_MODE_ACCESS_READ) ?
1195 17309 : FILE_READ_DATA : 0) |
1196 : ((flags & SHARE_MODE_ACCESS_WRITE) ?
1197 17309 : FILE_WRITE_DATA : 0) |
1198 : ((flags & SHARE_MODE_ACCESS_DELETE) ?
1199 17309 : DELETE_ACCESS : 0);
1200 : }
1201 17309 : if (share_mode != NULL) {
1202 17309 : *share_mode =
1203 : ((flags & SHARE_MODE_SHARE_READ) ?
1204 17309 : FILE_SHARE_READ : 0) |
1205 : ((flags & SHARE_MODE_SHARE_WRITE) ?
1206 17309 : FILE_SHARE_WRITE : 0) |
1207 : ((flags & SHARE_MODE_SHARE_DELETE) ?
1208 : FILE_SHARE_DELETE : 0);
1209 : }
1210 17309 : if (lease_type != NULL) {
1211 12190 : *lease_type =
1212 : ((flags & SHARE_MODE_LEASE_READ) ?
1213 23130 : SMB2_LEASE_READ : 0) |
1214 : ((flags & SHARE_MODE_LEASE_WRITE) ?
1215 23130 : SMB2_LEASE_WRITE : 0) |
1216 : ((flags & SHARE_MODE_LEASE_HANDLE) ?
1217 12190 : SMB2_LEASE_HANDLE : 0);
1218 : }
1219 17309 : }
1220 :
1221 12204 : void share_mode_flags_set(
1222 : struct share_mode_lock *lck,
1223 : uint32_t access_mask,
1224 : uint32_t share_mode,
1225 : uint32_t lease_type,
1226 : bool *modified)
1227 : {
1228 12204 : struct share_mode_data *d = lck->data;
1229 12204 : uint16_t flags = 0;
1230 :
1231 12204 : flags |= (access_mask & (FILE_READ_DATA | FILE_EXECUTE)) ?
1232 : SHARE_MODE_ACCESS_READ : 0;
1233 12204 : flags |= (access_mask & (FILE_WRITE_DATA | FILE_APPEND_DATA)) ?
1234 : SHARE_MODE_ACCESS_WRITE : 0;
1235 12204 : flags |= (access_mask & (DELETE_ACCESS)) ?
1236 12204 : SHARE_MODE_ACCESS_DELETE : 0;
1237 :
1238 12204 : flags |= (share_mode & FILE_SHARE_READ) ?
1239 12204 : SHARE_MODE_SHARE_READ : 0;
1240 12204 : flags |= (share_mode & FILE_SHARE_WRITE) ?
1241 12204 : SHARE_MODE_SHARE_WRITE : 0;
1242 12204 : flags |= (share_mode & FILE_SHARE_DELETE) ?
1243 12204 : SHARE_MODE_SHARE_DELETE : 0;
1244 :
1245 12204 : flags |= (lease_type & SMB2_LEASE_READ) ?
1246 12204 : SHARE_MODE_LEASE_READ : 0;
1247 12204 : flags |= (lease_type & SMB2_LEASE_WRITE) ?
1248 12204 : SHARE_MODE_LEASE_WRITE : 0;
1249 12204 : flags |= (lease_type & SMB2_LEASE_HANDLE) ?
1250 12204 : SHARE_MODE_LEASE_HANDLE : 0;
1251 :
1252 12204 : if (d->flags == flags) {
1253 7470 : return;
1254 : }
1255 :
1256 4734 : if (modified != NULL) {
1257 0 : *modified = true;
1258 : }
1259 4734 : d->flags = flags;
1260 4734 : d->modified = true;
1261 : }
1262 :
1263 : struct share_mode_watch_state {
1264 : bool blockerdead;
1265 : struct server_id blocker;
1266 : };
1267 :
1268 : static void share_mode_watch_done(struct tevent_req *subreq);
1269 :
1270 0 : struct tevent_req *share_mode_watch_send(
1271 : TALLOC_CTX *mem_ctx,
1272 : struct tevent_context *ev,
1273 : struct share_mode_lock *lck,
1274 : struct server_id blocker)
1275 : {
1276 0 : TDB_DATA key = locking_key(&lck->data->id);
1277 0 : struct tevent_req *req = NULL, *subreq = NULL;
1278 0 : struct share_mode_watch_state *state = NULL;
1279 :
1280 0 : req = tevent_req_create(
1281 : mem_ctx, &state, struct share_mode_watch_state);
1282 0 : if (req == NULL) {
1283 0 : return NULL;
1284 : }
1285 :
1286 0 : subreq = g_lock_watch_data_send(state, ev, lock_ctx, key, blocker);
1287 0 : if (tevent_req_nomem(subreq, req)) {
1288 0 : return tevent_req_post(req, ev);
1289 : }
1290 0 : tevent_req_set_callback(subreq, share_mode_watch_done, req);
1291 0 : return req;
1292 : }
1293 :
1294 0 : static void share_mode_watch_done(struct tevent_req *subreq)
1295 : {
1296 0 : struct tevent_req *req = tevent_req_callback_data(
1297 : subreq, struct tevent_req);
1298 0 : struct share_mode_watch_state *state = tevent_req_data(
1299 : req, struct share_mode_watch_state);
1300 : NTSTATUS status;
1301 :
1302 0 : status = g_lock_watch_data_recv(
1303 : subreq, &state->blockerdead, &state->blocker);
1304 0 : if (tevent_req_nterror(req, status)) {
1305 0 : return;
1306 : }
1307 0 : tevent_req_done(req);
1308 : }
1309 :
1310 0 : NTSTATUS share_mode_watch_recv(
1311 : struct tevent_req *req, bool *blockerdead, struct server_id *blocker)
1312 : {
1313 0 : struct share_mode_watch_state *state = tevent_req_data(
1314 : req, struct share_mode_watch_state);
1315 : NTSTATUS status;
1316 :
1317 0 : if (tevent_req_is_nterror(req, &status)) {
1318 0 : return status;
1319 : }
1320 0 : if (blockerdead != NULL) {
1321 0 : *blockerdead = state->blockerdead;
1322 : }
1323 0 : if (blocker != NULL) {
1324 0 : *blocker = state->blocker;
1325 : }
1326 0 : return NT_STATUS_OK;
1327 : }
1328 :
1329 : struct fetch_share_mode_unlocked_state {
1330 : TALLOC_CTX *mem_ctx;
1331 : struct file_id id;
1332 : struct share_mode_lock *lck;
1333 : };
1334 :
1335 926 : static void fetch_share_mode_unlocked_parser(
1336 : struct server_id exclusive,
1337 : size_t num_shared,
1338 : const struct server_id *shared,
1339 : const uint8_t *data,
1340 : size_t datalen,
1341 : void *private_data)
1342 : {
1343 926 : struct fetch_share_mode_unlocked_state *state = private_data;
1344 926 : struct locking_tdb_data ltdb = { 0 };
1345 :
1346 926 : if (datalen != 0) {
1347 926 : bool ok = locking_tdb_data_get(<db, data, datalen);
1348 926 : if (!ok) {
1349 0 : DBG_DEBUG("locking_tdb_data_get failed\n");
1350 0 : return;
1351 : }
1352 : }
1353 :
1354 926 : if (ltdb.share_mode_data_len == 0) {
1355 : /* Likely a ctdb tombstone record, ignore it */
1356 0 : return;
1357 : }
1358 :
1359 926 : state->lck = talloc(state->mem_ctx, struct share_mode_lock);
1360 926 : if (state->lck == NULL) {
1361 0 : DEBUG(0, ("talloc failed\n"));
1362 0 : return;
1363 : }
1364 :
1365 1852 : state->lck->data = parse_share_modes(
1366 926 : state->lck,
1367 : state->id,
1368 : ltdb.share_mode_data_buf,
1369 : ltdb.share_mode_data_len);
1370 926 : if (state->lck->data == NULL) {
1371 0 : DBG_DEBUG("parse_share_modes failed\n");
1372 0 : TALLOC_FREE(state->lck);
1373 : }
1374 : }
1375 :
1376 : /*******************************************************************
1377 : Get a share_mode_lock without locking the database or reference
1378 : counting. Used by smbstatus to display existing share modes.
1379 : ********************************************************************/
1380 :
1381 1863 : struct share_mode_lock *fetch_share_mode_unlocked(TALLOC_CTX *mem_ctx,
1382 : struct file_id id)
1383 : {
1384 1863 : struct fetch_share_mode_unlocked_state state = {
1385 : .mem_ctx = mem_ctx,
1386 : .id = id,
1387 : };
1388 1863 : TDB_DATA key = locking_key(&id);
1389 : NTSTATUS status;
1390 :
1391 1863 : status = g_lock_dump(
1392 : lock_ctx, key, fetch_share_mode_unlocked_parser, &state);
1393 1863 : if (!NT_STATUS_IS_OK(status)) {
1394 937 : DBG_DEBUG("g_lock_dump failed: %s\n", nt_errstr(status));
1395 937 : return NULL;
1396 : }
1397 926 : return state.lck;
1398 : }
1399 :
1400 : struct fetch_share_mode_state {
1401 : struct file_id id;
1402 : struct share_mode_lock *lck;
1403 : NTSTATUS status;
1404 : };
1405 :
1406 : static void fetch_share_mode_fn(
1407 : struct server_id exclusive,
1408 : size_t num_shared,
1409 : const struct server_id *shared,
1410 : const uint8_t *data,
1411 : size_t datalen,
1412 : void *private_data);
1413 : static void fetch_share_mode_done(struct tevent_req *subreq);
1414 :
1415 : /**
1416 : * @brief Get a share_mode_lock without locking or refcounting
1417 : *
1418 : * This can be used in a clustered Samba environment where the async dbwrap
1419 : * request is sent over a socket to the local ctdbd. If the send queue is full
1420 : * and the caller was issuing multiple async dbwrap requests in a loop, the
1421 : * caller knows it's probably time to stop sending requests for now and try
1422 : * again later.
1423 : *
1424 : * @param[in] mem_ctx The talloc memory context to use.
1425 : *
1426 : * @param[in] ev The event context to work on.
1427 : *
1428 : * @param[in] id The file id for the locking.tdb key
1429 : *
1430 : * @param[out] queued This boolean out parameter tells the caller whether the
1431 : * async request is blocked in a full send queue:
1432 : *
1433 : * false := request is dispatched
1434 : *
1435 : * true := send queue is full, request waiting to be
1436 : * dispatched
1437 : *
1438 : * @return The new async request, NULL on error.
1439 : **/
1440 0 : struct tevent_req *fetch_share_mode_send(TALLOC_CTX *mem_ctx,
1441 : struct tevent_context *ev,
1442 : struct file_id id,
1443 : bool *queued)
1444 : {
1445 0 : struct tevent_req *req = NULL, *subreq = NULL;
1446 0 : struct fetch_share_mode_state *state = NULL;
1447 :
1448 0 : *queued = false;
1449 :
1450 0 : req = tevent_req_create(mem_ctx, &state,
1451 : struct fetch_share_mode_state);
1452 0 : if (req == NULL) {
1453 0 : return NULL;
1454 : }
1455 0 : state->id = id;
1456 :
1457 0 : subreq = g_lock_dump_send(
1458 : state,
1459 : ev,
1460 : lock_ctx,
1461 : locking_key(&id),
1462 : fetch_share_mode_fn,
1463 : state);
1464 0 : if (tevent_req_nomem(subreq, req)) {
1465 0 : return tevent_req_post(req, ev);
1466 : }
1467 0 : tevent_req_set_callback(subreq, fetch_share_mode_done, req);
1468 0 : return req;
1469 : }
1470 :
1471 0 : static void fetch_share_mode_fn(
1472 : struct server_id exclusive,
1473 : size_t num_shared,
1474 : const struct server_id *shared,
1475 : const uint8_t *data,
1476 : size_t datalen,
1477 : void *private_data)
1478 : {
1479 0 : struct fetch_share_mode_state *state = talloc_get_type_abort(
1480 : private_data, struct fetch_share_mode_state);
1481 0 : struct locking_tdb_data ltdb = { 0 };
1482 :
1483 0 : if (datalen != 0) {
1484 0 : bool ok = locking_tdb_data_get(<db, data, datalen);
1485 0 : if (!ok) {
1486 0 : DBG_DEBUG("locking_tdb_data_get failed\n");
1487 0 : return;
1488 : }
1489 : }
1490 :
1491 0 : if (ltdb.share_mode_data_len == 0) {
1492 : /* Likely a ctdb tombstone record, ignore it */
1493 0 : return;
1494 : }
1495 :
1496 0 : state->lck = talloc(state, struct share_mode_lock);
1497 0 : if (state->lck == NULL) {
1498 0 : DBG_WARNING("talloc failed\n");
1499 0 : state->status = NT_STATUS_NO_MEMORY;
1500 0 : return;
1501 : }
1502 :
1503 0 : state->lck->data = parse_share_modes(
1504 0 : state->lck,
1505 : state->id,
1506 : ltdb.share_mode_data_buf,
1507 : ltdb.share_mode_data_len);
1508 0 : if (state->lck->data == NULL) {
1509 0 : DBG_DEBUG("parse_share_modes failed\n");
1510 0 : state->status = NT_STATUS_INTERNAL_DB_CORRUPTION;
1511 0 : TALLOC_FREE(state->lck);
1512 0 : return;
1513 : }
1514 : }
1515 :
1516 0 : static void fetch_share_mode_done(struct tevent_req *subreq)
1517 : {
1518 0 : struct tevent_req *req = tevent_req_callback_data(
1519 : subreq, struct tevent_req);
1520 0 : struct fetch_share_mode_state *state = tevent_req_data(
1521 : req, struct fetch_share_mode_state);
1522 : NTSTATUS status;
1523 :
1524 0 : status = g_lock_dump_recv(subreq);
1525 0 : TALLOC_FREE(subreq);
1526 0 : if (tevent_req_nterror(req, status)) {
1527 0 : return;
1528 : }
1529 0 : if (tevent_req_nterror(req, state->status)) {
1530 0 : return;
1531 : }
1532 0 : tevent_req_done(req);
1533 : }
1534 :
1535 0 : NTSTATUS fetch_share_mode_recv(struct tevent_req *req,
1536 : TALLOC_CTX *mem_ctx,
1537 : struct share_mode_lock **_lck)
1538 : {
1539 0 : struct fetch_share_mode_state *state = tevent_req_data(
1540 : req, struct fetch_share_mode_state);
1541 0 : struct share_mode_lock *lck = NULL;
1542 :
1543 : NTSTATUS status;
1544 :
1545 0 : if (tevent_req_is_nterror(req, &status)) {
1546 0 : tevent_req_received(req);
1547 0 : return status;
1548 : }
1549 :
1550 0 : if (state->lck == NULL) {
1551 0 : tevent_req_received(req);
1552 0 : return NT_STATUS_NOT_FOUND;
1553 : }
1554 :
1555 0 : lck = talloc_move(mem_ctx, &state->lck);
1556 :
1557 0 : if (DEBUGLEVEL >= 10) {
1558 0 : DBG_DEBUG("share_mode_data:\n");
1559 0 : NDR_PRINT_DEBUG(share_mode_data, lck->data);
1560 : }
1561 :
1562 0 : *_lck = lck;
1563 0 : tevent_req_received(req);
1564 0 : return NT_STATUS_OK;
1565 : }
1566 :
1567 : struct share_mode_forall_state {
1568 : TDB_DATA key;
1569 : int (*fn)(struct file_id fid,
1570 : const struct share_mode_data *data,
1571 : void *private_data);
1572 : void *private_data;
1573 : };
1574 :
1575 132 : static void share_mode_forall_dump_fn(
1576 : struct server_id exclusive,
1577 : size_t num_shared,
1578 : const struct server_id *shared,
1579 : const uint8_t *data,
1580 : size_t datalen,
1581 : void *private_data)
1582 : {
1583 132 : struct share_mode_forall_state *state = private_data;
1584 : struct file_id fid;
1585 132 : struct locking_tdb_data ltdb = { 0 };
1586 : bool ok;
1587 : struct share_mode_data *d;
1588 :
1589 132 : if (state->key.dsize != sizeof(fid)) {
1590 0 : DBG_DEBUG("Got invalid key length %zu\n", state->key.dsize);
1591 10 : return;
1592 : }
1593 132 : memcpy(&fid, state->key.dptr, sizeof(fid));
1594 :
1595 132 : ok = locking_tdb_data_get(<db, data, datalen);
1596 132 : if (!ok) {
1597 0 : DBG_DEBUG("locking_tdb_data_get() failed\n");
1598 0 : return;
1599 : }
1600 :
1601 132 : d = parse_share_modes(
1602 : talloc_tos(),
1603 : fid,
1604 : ltdb.share_mode_data_buf,
1605 : ltdb.share_mode_data_len);
1606 132 : if (d == NULL) {
1607 10 : DBG_DEBUG("parse_share_modes() failed\n");
1608 10 : return;
1609 : }
1610 :
1611 122 : state->fn(fid, d, state->private_data);
1612 122 : TALLOC_FREE(d);
1613 : }
1614 :
1615 132 : static int share_mode_forall_fn(TDB_DATA key, void *private_data)
1616 : {
1617 132 : struct share_mode_forall_state *state = private_data;
1618 : NTSTATUS status;
1619 :
1620 132 : state->key = key;
1621 :
1622 132 : status = g_lock_dump(
1623 : lock_ctx, key, share_mode_forall_dump_fn, private_data);
1624 132 : if (!NT_STATUS_IS_OK(status)) {
1625 0 : DBG_DEBUG("g_lock_dump failed: %s\n",
1626 : nt_errstr(status));
1627 : }
1628 132 : return 0;
1629 : }
1630 :
1631 116 : int share_mode_forall(int (*fn)(struct file_id fid,
1632 : const struct share_mode_data *data,
1633 : void *private_data),
1634 : void *private_data)
1635 : {
1636 116 : struct share_mode_forall_state state = {
1637 : .fn = fn,
1638 : .private_data = private_data
1639 : };
1640 : int ret;
1641 :
1642 116 : if (lock_ctx == NULL) {
1643 0 : return 0;
1644 : }
1645 :
1646 116 : ret = g_lock_locks(
1647 : lock_ctx, share_mode_forall_fn, &state);
1648 116 : if (ret < 0) {
1649 0 : DBG_DEBUG("g_lock_locks failed\n");
1650 : }
1651 116 : return ret;
1652 : }
1653 :
1654 : struct share_entry_forall_state {
1655 : struct file_id fid;
1656 : const struct share_mode_data *data;
1657 : int (*fn)(struct file_id fid,
1658 : const struct share_mode_data *data,
1659 : const struct share_mode_entry *entry,
1660 : void *private_data);
1661 : void *private_data;
1662 : int ret;
1663 : };
1664 :
1665 0 : static bool share_entry_traverse_walker(
1666 : struct share_mode_entry *e,
1667 : bool *modified,
1668 : void *private_data)
1669 : {
1670 0 : struct share_entry_forall_state *state = private_data;
1671 :
1672 0 : state->ret = state->fn(
1673 : state->fid, state->data, e, state->private_data);
1674 0 : return (state->ret != 0);
1675 : }
1676 :
1677 0 : static int share_entry_traverse_fn(struct file_id fid,
1678 : const struct share_mode_data *data,
1679 : void *private_data)
1680 : {
1681 0 : struct share_entry_forall_state *state = private_data;
1682 0 : struct share_mode_lock lck = {
1683 : .data = discard_const_p(struct share_mode_data, data)
1684 : };
1685 : bool ok;
1686 :
1687 0 : state->fid = fid;
1688 0 : state->data = data;
1689 :
1690 0 : ok = share_mode_forall_entries(
1691 : &lck, share_entry_traverse_walker, state);
1692 0 : if (!ok) {
1693 0 : DBG_DEBUG("share_mode_forall_entries failed\n");
1694 0 : return false;
1695 : }
1696 :
1697 0 : return state->ret;
1698 : }
1699 :
1700 : /*******************************************************************
1701 : Call the specified function on each entry under management by the
1702 : share mode system.
1703 : ********************************************************************/
1704 :
1705 12 : int share_entry_forall(int (*fn)(struct file_id fid,
1706 : const struct share_mode_data *data,
1707 : const struct share_mode_entry *entry,
1708 : void *private_data),
1709 : void *private_data)
1710 : {
1711 12 : struct share_entry_forall_state state = {
1712 : .fn = fn, .private_data = private_data };
1713 :
1714 12 : return share_mode_forall(share_entry_traverse_fn, &state);
1715 : }
1716 :
1717 18499 : static int share_mode_entry_cmp(
1718 : struct server_id pid1,
1719 : uint64_t share_file_id1,
1720 : struct server_id pid2,
1721 : uint64_t share_file_id2)
1722 : {
1723 : int cmp;
1724 :
1725 18499 : cmp = server_id_cmp(&pid1, &pid2);
1726 18499 : if (cmp != 0) {
1727 6301 : return cmp;
1728 : }
1729 12198 : if (share_file_id1 != share_file_id2) {
1730 8 : return (share_file_id1 < share_file_id2) ? -1 : 1;
1731 : }
1732 12190 : return 0;
1733 : }
1734 :
1735 24256 : static size_t share_mode_entry_find(
1736 : const uint8_t *data,
1737 : size_t num_share_modes,
1738 : struct server_id pid,
1739 : uint64_t share_file_id,
1740 : struct share_mode_entry *e,
1741 : bool *match)
1742 : {
1743 : ssize_t left, right, middle;
1744 :
1745 24256 : *match = false;
1746 :
1747 24256 : if (num_share_modes == 0) {
1748 8899 : return 0;
1749 : }
1750 :
1751 15357 : left = 0;
1752 15357 : right = (num_share_modes-1);
1753 :
1754 35771 : while (left <= right) {
1755 18499 : const uint8_t *middle_ptr = NULL;
1756 : int cmp;
1757 : bool ok;
1758 :
1759 18499 : middle = left + ((right - left) / 2);
1760 18499 : middle_ptr = data + middle * SHARE_MODE_ENTRY_SIZE;
1761 :
1762 18499 : DBG_DEBUG("left=%zu, right=%zu, middle=%zu, middle_ptr=%p\n",
1763 : left,
1764 : right,
1765 : middle,
1766 : middle_ptr);
1767 :
1768 18499 : ok = share_mode_entry_get(middle_ptr, e);
1769 18499 : if (!ok) {
1770 0 : DBG_DEBUG("share_mode_entry_get failed\n");
1771 0 : return 0;
1772 : }
1773 :
1774 18499 : cmp = share_mode_entry_cmp(
1775 : e->pid, e->share_file_id, pid, share_file_id);
1776 18499 : if (cmp == 0) {
1777 12190 : *match = true;
1778 12190 : return middle;
1779 : }
1780 :
1781 6309 : if (cmp < 0) {
1782 2462 : right = middle-1;
1783 : } else {
1784 3847 : left = middle+1;
1785 : }
1786 : }
1787 :
1788 3167 : return left;
1789 : }
1790 :
1791 12066 : bool set_share_mode(struct share_mode_lock *lck,
1792 : struct files_struct *fsp,
1793 : uid_t uid,
1794 : uint64_t mid,
1795 : uint16_t op_type,
1796 : const struct smb2_lease_key *lease_key,
1797 : uint32_t share_access,
1798 : uint32_t access_mask)
1799 : {
1800 12066 : struct share_mode_data *d = lck->data;
1801 12066 : TDB_DATA key = locking_key(&d->id);
1802 12066 : struct server_id my_pid = messaging_server_id(
1803 12066 : fsp->conn->sconn->msg_ctx);
1804 12066 : struct locking_tdb_data *ltdb = NULL;
1805 : size_t idx;
1806 12066 : struct share_mode_entry e = { .pid.pid = 0 };
1807 : struct share_mode_entry_buf e_buf;
1808 : NTSTATUS status;
1809 : bool ok, found;
1810 :
1811 : TDB_DATA dbufs[3];
1812 12066 : size_t num_dbufs = 0;
1813 :
1814 12066 : status = locking_tdb_data_fetch(key, talloc_tos(), <db);
1815 12066 : if (!NT_STATUS_IS_OK(status)) {
1816 0 : DBG_DEBUG("locking_tdb_data_fetch failed: %s\n",
1817 : nt_errstr(status));
1818 0 : return false;
1819 : }
1820 12066 : DBG_DEBUG("num_share_modes=%zu\n", ltdb->num_share_entries);
1821 :
1822 33822 : idx = share_mode_entry_find(
1823 12066 : ltdb->share_entries,
1824 12066 : ltdb->num_share_entries,
1825 : my_pid,
1826 : fh_get_gen_id(fsp->fh),
1827 : &e,
1828 : &found);
1829 12066 : if (found) {
1830 0 : DBG_WARNING("Found duplicate share mode\n");
1831 0 : status = NT_STATUS_INTERNAL_DB_CORRUPTION;
1832 0 : goto done;
1833 : }
1834 :
1835 12066 : e = (struct share_mode_entry) {
1836 : .pid = my_pid,
1837 : .share_access = share_access,
1838 12066 : .private_options = fh_get_private_options(fsp->fh),
1839 : .access_mask = access_mask,
1840 : .op_mid = mid,
1841 : .op_type = op_type,
1842 12066 : .time.tv_sec = fsp->open_time.tv_sec,
1843 12066 : .time.tv_usec = fsp->open_time.tv_usec,
1844 12066 : .share_file_id = fh_get_gen_id(fsp->fh),
1845 : .uid = (uint32_t)uid,
1846 : .flags = (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN) ?
1847 12066 : SHARE_MODE_FLAG_POSIX_OPEN : 0,
1848 12066 : .name_hash = fsp->name_hash,
1849 : };
1850 :
1851 12066 : if (op_type == LEASE_OPLOCK) {
1852 0 : const struct GUID *client_guid = fsp_client_guid(fsp);
1853 0 : e.client_guid = *client_guid;
1854 0 : e.lease_key = *lease_key;
1855 : }
1856 :
1857 12066 : ok = share_mode_entry_put(&e, &e_buf);
1858 12066 : if (!ok) {
1859 0 : DBG_DEBUG("share_mode_entry_put failed\n");
1860 0 : status = NT_STATUS_INTERNAL_ERROR;
1861 0 : goto done;
1862 : }
1863 :
1864 12066 : DBG_DEBUG("idx=%zu, found=%d\n", idx, (int)found);
1865 :
1866 12066 : if (idx > 0) {
1867 1908 : dbufs[num_dbufs] = (TDB_DATA) {
1868 1908 : .dptr = discard_const_p(uint8_t, ltdb->share_entries),
1869 1908 : .dsize = idx * SHARE_MODE_ENTRY_SIZE,
1870 : };
1871 1908 : num_dbufs += 1;
1872 : }
1873 :
1874 12066 : dbufs[num_dbufs] = (TDB_DATA) {
1875 : .dptr = e_buf.buf, .dsize = SHARE_MODE_ENTRY_SIZE,
1876 : };
1877 12066 : num_dbufs += 1;
1878 :
1879 12066 : if (idx < ltdb->num_share_entries) {
1880 1875 : size_t num_after_idx = (ltdb->num_share_entries-idx);
1881 1875 : dbufs[num_dbufs] = (TDB_DATA) {
1882 3748 : .dptr = discard_const_p(uint8_t, ltdb->share_entries) +
1883 1875 : idx * SHARE_MODE_ENTRY_SIZE,
1884 1875 : .dsize = num_after_idx * SHARE_MODE_ENTRY_SIZE,
1885 : };
1886 1875 : num_dbufs += 1;
1887 : }
1888 :
1889 : {
1890 : size_t i;
1891 27915 : for (i=0; i<num_dbufs; i++) {
1892 15849 : DBG_DEBUG("dbufs[%zu]=(%p, %zu)\n",
1893 : i,
1894 : dbufs[i].dptr,
1895 : dbufs[i].dsize);
1896 : }
1897 : }
1898 :
1899 12066 : if (num_dbufs == 1) {
1900 : /*
1901 : * Storing a fresh record with just one share entry
1902 : */
1903 8899 : d->modified = true;
1904 : }
1905 :
1906 : /*
1907 : * If there was any existing data in
1908 : * ltdb->share_entries, it's now been
1909 : * moved and we've split it into:
1910 : *
1911 : * num_dbufs = 3
1912 : * dbufs[0] -> old sorted data less than new_entry
1913 : * dbufs[1] -> new_share_mode_entry
1914 : * dbufs[2] -> old sorted_data greater than new entry.
1915 : *
1916 : * So the old data inside ltdb->share_entries is
1917 : * no longer valid.
1918 : *
1919 : * If we're storing a brand new entry the
1920 : * dbufs look like:
1921 : *
1922 : * num_dbufs = 1
1923 : * dbufs[0] -> new_share_mode_entry
1924 : *
1925 : * Either way we must set ltdb->share_entries = NULL
1926 : * and ltdb->num_share_entries = 0 so that
1927 : * locking_tdb_data_store() doesn't use it to
1928 : * store any data. It's no longer there.
1929 : */
1930 :
1931 12066 : ltdb->share_entries = NULL;
1932 12066 : ltdb->num_share_entries = 0;
1933 :
1934 12066 : status = locking_tdb_data_store(key, ltdb, dbufs, num_dbufs);
1935 12066 : if (!NT_STATUS_IS_OK(status)) {
1936 0 : DBG_DEBUG("locking_tdb_data_store failed: %s\n",
1937 : nt_errstr(status));
1938 : }
1939 22944 : done:
1940 12066 : TALLOC_FREE(ltdb);
1941 12066 : return NT_STATUS_IS_OK(status);
1942 : }
1943 :
1944 2882 : static bool share_mode_for_one_entry(
1945 : bool (*fn)(struct share_mode_entry *e,
1946 : bool *modified,
1947 : void *private_data),
1948 : void *private_data,
1949 : size_t *i,
1950 : uint8_t *data,
1951 : size_t *num_share_modes,
1952 : bool *writeback)
1953 : {
1954 2882 : DATA_BLOB blob = {
1955 2882 : .data = data + (*i) * SHARE_MODE_ENTRY_SIZE,
1956 : .length = SHARE_MODE_ENTRY_SIZE,
1957 : };
1958 2882 : struct share_mode_entry e = {.pid.pid=0};
1959 2882 : enum ndr_err_code ndr_err = NDR_ERR_SUCCESS;
1960 2882 : bool modified = false;
1961 2882 : bool stop = false;
1962 : struct server_id e_pid;
1963 : uint64_t e_share_file_id;
1964 :
1965 2882 : ndr_err = ndr_pull_struct_blob_all_noalloc(
1966 : &blob,
1967 : &e,
1968 : (ndr_pull_flags_fn_t)ndr_pull_share_mode_entry);
1969 2882 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1970 0 : DBG_WARNING("ndr_pull_share_mode_entry failed\n");
1971 0 : *i += 1;
1972 0 : return false;
1973 : }
1974 2882 : if (DEBUGLEVEL >= 10) {
1975 0 : DBG_DEBUG("entry[%zu]:\n", *i);
1976 0 : NDR_PRINT_DEBUG(share_mode_entry, &e);
1977 : }
1978 :
1979 2882 : e_pid = e.pid;
1980 2882 : e_share_file_id = e.share_file_id;
1981 :
1982 2882 : stop = fn(&e, &modified, private_data);
1983 :
1984 2882 : DBG_DEBUG("entry[%zu]: modified=%d, e.stale=%d\n",
1985 : *i,
1986 : (int)modified,
1987 : (int)e.stale);
1988 :
1989 2882 : if (e.stale) {
1990 0 : if (DEBUGLEVEL>=10) {
1991 0 : DBG_DEBUG("share_mode_entry:\n");
1992 0 : NDR_PRINT_DEBUG(share_mode_entry, &e);
1993 : }
1994 :
1995 0 : if (*i < *num_share_modes) {
1996 0 : memmove(blob.data,
1997 0 : blob.data + SHARE_MODE_ENTRY_SIZE,
1998 0 : (*num_share_modes - *i - 1) *
1999 : SHARE_MODE_ENTRY_SIZE);
2000 : }
2001 0 : *num_share_modes -= 1;
2002 0 : *writeback = true;
2003 0 : return stop;
2004 : }
2005 :
2006 2882 : if (modified) {
2007 20 : if (DEBUGLEVEL>=10) {
2008 0 : DBG_DEBUG("share_mode_entry:\n");
2009 0 : NDR_PRINT_DEBUG(share_mode_entry, &e);
2010 : }
2011 :
2012 : /*
2013 : * Make sure sorting order is kept intact
2014 : */
2015 20 : SMB_ASSERT(server_id_equal(&e_pid, &e.pid));
2016 20 : SMB_ASSERT(e_share_file_id == e.share_file_id);
2017 :
2018 20 : ndr_err = ndr_push_struct_into_fixed_blob(
2019 : &blob,
2020 : &e,
2021 : (ndr_push_flags_fn_t)
2022 : ndr_push_share_mode_entry);
2023 20 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2024 0 : DBG_WARNING("ndr_push_share_mode_entry "
2025 : "failed: %s\n",
2026 : ndr_errstr(ndr_err));
2027 : /*
2028 : * Not much we can do, just ignore it
2029 : */
2030 : }
2031 20 : *i += 1;
2032 20 : *writeback = true;
2033 20 : return stop;
2034 : }
2035 :
2036 2862 : if (stop) {
2037 1 : return true;
2038 : }
2039 :
2040 2861 : *i += 1;
2041 2861 : return false;
2042 : }
2043 :
2044 11422 : bool share_mode_forall_entries(
2045 : struct share_mode_lock *lck,
2046 : bool (*fn)(struct share_mode_entry *e,
2047 : bool *modified,
2048 : void *private_data),
2049 : void *private_data)
2050 : {
2051 11422 : struct share_mode_data *d = lck->data;
2052 11422 : TDB_DATA key = locking_key(&d->id);
2053 11422 : struct locking_tdb_data *ltdb = NULL;
2054 11422 : uint8_t *share_entries = NULL;
2055 : size_t num_share_entries;
2056 11422 : bool writeback = false;
2057 : NTSTATUS status;
2058 11422 : bool stop = false;
2059 : size_t i;
2060 :
2061 11422 : status = locking_tdb_data_fetch(key, talloc_tos(), <db);
2062 11422 : if (!NT_STATUS_IS_OK(status)) {
2063 0 : DBG_DEBUG("locking_tdb_data_fetch failed: %s\n",
2064 : nt_errstr(status));
2065 0 : return false;
2066 : }
2067 11422 : DBG_DEBUG("num_share_modes=%zu\n", ltdb->num_share_entries);
2068 :
2069 11422 : num_share_entries = ltdb->num_share_entries;
2070 11422 : share_entries = discard_const_p(uint8_t, ltdb->share_entries);
2071 :
2072 11422 : i = 0;
2073 24180 : while (i<num_share_entries) {
2074 2882 : stop = share_mode_for_one_entry(
2075 : fn,
2076 : private_data,
2077 : &i,
2078 : share_entries,
2079 : &num_share_entries,
2080 : &writeback);
2081 2882 : if (stop) {
2082 1 : break;
2083 : }
2084 : }
2085 :
2086 11422 : DBG_DEBUG("num_share_entries=%zu, writeback=%d\n",
2087 : num_share_entries,
2088 : (int)writeback);
2089 :
2090 11422 : if (!writeback) {
2091 11402 : return true;
2092 : }
2093 :
2094 20 : if ((ltdb->num_share_entries != 0 ) && (num_share_entries == 0)) {
2095 : /*
2096 : * This routine wiped all share entries, let
2097 : * share_mode_data_store() delete the record
2098 : */
2099 0 : d->modified = true;
2100 : }
2101 :
2102 20 : ltdb->num_share_entries = num_share_entries;
2103 20 : ltdb->share_entries = share_entries;
2104 :
2105 20 : status = locking_tdb_data_store(key, ltdb, NULL, 0);
2106 20 : if (!NT_STATUS_IS_OK(status)) {
2107 0 : DBG_DEBUG("locking_tdb_data_store failed: %s\n",
2108 : nt_errstr(status));
2109 0 : return false;
2110 : }
2111 :
2112 20 : return true;
2113 : }
2114 :
2115 : struct share_mode_count_entries_state {
2116 : size_t num_share_modes;
2117 : NTSTATUS status;
2118 : };
2119 :
2120 0 : static void share_mode_count_entries_fn(
2121 : struct server_id exclusive,
2122 : size_t num_shared,
2123 : const struct server_id *shared,
2124 : const uint8_t *data,
2125 : size_t datalen,
2126 : void *private_data)
2127 : {
2128 0 : struct share_mode_count_entries_state *state = private_data;
2129 0 : struct locking_tdb_data ltdb = { 0 };
2130 : bool ok;
2131 :
2132 0 : ok = locking_tdb_data_get(<db, data, datalen);
2133 0 : if (!ok) {
2134 0 : DBG_WARNING("locking_tdb_data_get failed for %zu\n", datalen);
2135 0 : state->status = NT_STATUS_INTERNAL_DB_CORRUPTION;
2136 0 : return;
2137 : }
2138 0 : state->num_share_modes = ltdb.num_share_entries;
2139 0 : state->status = NT_STATUS_OK;
2140 : }
2141 :
2142 0 : NTSTATUS share_mode_count_entries(struct file_id fid, size_t *num_share_modes)
2143 : {
2144 0 : struct share_mode_count_entries_state state = {
2145 : .status = NT_STATUS_NOT_FOUND,
2146 : };
2147 : NTSTATUS status;
2148 :
2149 0 : status = g_lock_dump(
2150 : lock_ctx,
2151 : locking_key(&fid),
2152 : share_mode_count_entries_fn,
2153 : &state);
2154 0 : if (!NT_STATUS_IS_OK(status)) {
2155 0 : DBG_DEBUG("g_lock_dump failed: %s\n",
2156 : nt_errstr(status));
2157 0 : return status;
2158 : }
2159 0 : if (!NT_STATUS_IS_OK(state.status)) {
2160 0 : DBG_DEBUG("share_mode_count_entries_fn failed: %s\n",
2161 : nt_errstr(state.status));
2162 0 : return state.status;
2163 : }
2164 :
2165 0 : *num_share_modes = state.num_share_modes;
2166 0 : return NT_STATUS_OK;
2167 : }
2168 :
2169 12190 : static bool share_mode_entry_do(
2170 : struct share_mode_lock *lck,
2171 : struct server_id pid,
2172 : uint64_t share_file_id,
2173 : void (*fn)(struct share_mode_entry *e,
2174 : size_t num_share_modes,
2175 : bool *modified,
2176 : void *private_data),
2177 : void *private_data)
2178 : {
2179 12190 : struct share_mode_data *d = lck->data;
2180 12190 : TDB_DATA key = locking_key(&d->id);
2181 12190 : struct locking_tdb_data *ltdb = NULL;
2182 : size_t idx;
2183 12190 : bool found = false;
2184 12190 : bool modified = false;
2185 : struct share_mode_entry e;
2186 12190 : uint8_t *e_ptr = NULL;
2187 : NTSTATUS status;
2188 12190 : bool ret = false;
2189 :
2190 12190 : status = locking_tdb_data_fetch(key, talloc_tos(), <db);
2191 12190 : if (!NT_STATUS_IS_OK(status)) {
2192 0 : DBG_DEBUG("locking_tdb_data_fetch failed: %s\n",
2193 : nt_errstr(status));
2194 0 : return false;
2195 : }
2196 12190 : DBG_DEBUG("num_share_modes=%zu\n", ltdb->num_share_entries);
2197 :
2198 23130 : idx = share_mode_entry_find(
2199 12190 : ltdb->share_entries,
2200 12190 : ltdb->num_share_entries,
2201 : pid,
2202 : share_file_id,
2203 : &e,
2204 : &found);
2205 12190 : if (!found) {
2206 0 : DBG_WARNING("Did not find share mode entry for %"PRIu64"\n",
2207 : share_file_id);
2208 0 : goto done;
2209 : }
2210 :
2211 12190 : if (DEBUGLEVEL>=10) {
2212 0 : DBG_DEBUG("entry[%zu]:\n", idx);
2213 0 : NDR_PRINT_DEBUG(share_mode_entry, &e);
2214 : }
2215 :
2216 12190 : fn(&e, ltdb->num_share_entries, &modified, private_data);
2217 :
2218 12190 : DBG_DEBUG("entry[%zu]: modified=%d, e.stale=%d\n",
2219 : idx,
2220 : (int)modified,
2221 : (int)e.stale);
2222 :
2223 12190 : if (!e.stale && !modified) {
2224 0 : ret = true;
2225 0 : goto done;
2226 : }
2227 :
2228 23130 : e_ptr = discard_const_p(uint8_t, ltdb->share_entries) +
2229 12190 : idx * SHARE_MODE_ENTRY_SIZE;
2230 :
2231 12190 : if (e.stale) {
2232 : /*
2233 : * Move the rest down one entry
2234 : */
2235 12066 : size_t behind = ltdb->num_share_entries - idx - 1;
2236 12066 : if (behind != 0) {
2237 3822 : memmove(e_ptr,
2238 1912 : e_ptr + SHARE_MODE_ENTRY_SIZE,
2239 : behind * SHARE_MODE_ENTRY_SIZE);
2240 : }
2241 12066 : ltdb->num_share_entries -= 1;
2242 :
2243 12066 : if (ltdb->num_share_entries == 0) {
2244 : /*
2245 : * Tell share_mode_lock_destructor() to delete
2246 : * the whole record
2247 : */
2248 8899 : d->modified = true;
2249 : }
2250 :
2251 12066 : if (DEBUGLEVEL>=10) {
2252 0 : DBG_DEBUG("share_mode_entry:\n");
2253 0 : NDR_PRINT_DEBUG(share_mode_entry, &e);
2254 : }
2255 : } else {
2256 : struct share_mode_entry_buf buf;
2257 : bool ok;
2258 :
2259 124 : if (ltdb->num_share_entries != 1) {
2260 : /*
2261 : * Make sure the sorting order stays intact
2262 : */
2263 0 : SMB_ASSERT(server_id_equal(&e.pid, &pid));
2264 0 : SMB_ASSERT(e.share_file_id == share_file_id);
2265 : }
2266 :
2267 124 : ok = share_mode_entry_put(&e, &buf);
2268 124 : if (!ok) {
2269 0 : DBG_DEBUG("share_mode_entry_put failed\n");
2270 0 : goto done;
2271 : }
2272 124 : memcpy(e_ptr, buf.buf, SHARE_MODE_ENTRY_SIZE);
2273 : }
2274 :
2275 12190 : status = locking_tdb_data_store(key, ltdb, NULL, 0);
2276 12190 : if (!NT_STATUS_IS_OK(status)) {
2277 0 : DBG_DEBUG("locking_tdb_data_store failed: %s\n",
2278 : nt_errstr(status));
2279 0 : goto done;
2280 : }
2281 :
2282 12190 : ret = true;
2283 12190 : done:
2284 12190 : TALLOC_FREE(ltdb);
2285 12190 : return ret;
2286 : }
2287 :
2288 : struct del_share_mode_state {
2289 : bool ok;
2290 : };
2291 :
2292 12066 : static void del_share_mode_fn(
2293 : struct share_mode_entry *e,
2294 : size_t num_share_modes,
2295 : bool *modified,
2296 : void *private_data)
2297 : {
2298 12066 : struct del_share_mode_state *state = private_data;
2299 12066 : e->stale = true;
2300 12066 : state->ok = true;
2301 12066 : }
2302 :
2303 12066 : bool del_share_mode(struct share_mode_lock *lck, files_struct *fsp)
2304 : {
2305 12066 : struct del_share_mode_state state = { .ok = false };
2306 : bool ok;
2307 :
2308 24132 : ok = share_mode_entry_do(
2309 : lck,
2310 12066 : messaging_server_id(fsp->conn->sconn->msg_ctx),
2311 : fh_get_gen_id(fsp->fh),
2312 : del_share_mode_fn,
2313 : &state);
2314 12066 : if (!ok) {
2315 0 : DBG_DEBUG("share_mode_entry_do failed\n");
2316 0 : return false;
2317 : }
2318 12066 : if (!state.ok) {
2319 0 : DBG_DEBUG("del_share_mode_fn failed\n");
2320 0 : return false;
2321 : }
2322 12066 : return true;
2323 : }
2324 :
2325 : struct remove_share_oplock_state {
2326 : bool ok;
2327 : };
2328 :
2329 124 : static void remove_share_oplock_fn(
2330 : struct share_mode_entry *e,
2331 : size_t num_share_modes,
2332 : bool *modified,
2333 : void *private_data)
2334 : {
2335 124 : struct remove_share_oplock_state *state = private_data;
2336 :
2337 124 : e->op_type = NO_OPLOCK;
2338 124 : *modified = true;
2339 124 : state->ok = true;
2340 124 : }
2341 :
2342 124 : bool remove_share_oplock(struct share_mode_lock *lck, files_struct *fsp)
2343 : {
2344 124 : struct remove_share_oplock_state state = { .ok = false };
2345 : bool ok;
2346 :
2347 248 : ok = share_mode_entry_do(
2348 : lck,
2349 124 : messaging_server_id(fsp->conn->sconn->msg_ctx),
2350 : fh_get_gen_id(fsp->fh),
2351 : remove_share_oplock_fn,
2352 : &state);
2353 124 : if (!ok) {
2354 0 : DBG_DEBUG("share_mode_entry_do failed\n");
2355 0 : return false;
2356 : }
2357 124 : if (!state.ok) {
2358 0 : DBG_DEBUG("remove_share_oplock_fn failed\n");
2359 0 : return false;
2360 : }
2361 :
2362 124 : if (fsp->oplock_type == LEASE_OPLOCK) {
2363 0 : remove_lease_if_stale(
2364 : lck,
2365 : fsp_client_guid(fsp),
2366 0 : &fsp->lease->lease.lease_key);
2367 : }
2368 :
2369 124 : share_mode_wakeup_waiters(fsp->file_id);
2370 :
2371 124 : return true;
2372 : }
2373 :
2374 : struct downgrade_share_oplock_state {
2375 : bool ok;
2376 : };
2377 :
2378 0 : static void downgrade_share_oplock_fn(
2379 : struct share_mode_entry *e,
2380 : size_t num_share_modes,
2381 : bool *modified,
2382 : void *private_data)
2383 : {
2384 0 : struct downgrade_share_oplock_state *state = private_data;
2385 :
2386 0 : e->op_type = LEVEL_II_OPLOCK;
2387 0 : *modified = true;
2388 0 : state->ok = true;
2389 0 : }
2390 :
2391 0 : bool downgrade_share_oplock(struct share_mode_lock *lck, files_struct *fsp)
2392 : {
2393 0 : struct downgrade_share_oplock_state state = { .ok = false };
2394 : bool ok;
2395 :
2396 0 : ok = share_mode_entry_do(
2397 : lck,
2398 0 : messaging_server_id(fsp->conn->sconn->msg_ctx),
2399 : fh_get_gen_id(fsp->fh),
2400 : downgrade_share_oplock_fn,
2401 : &state);
2402 0 : if (!ok) {
2403 0 : DBG_DEBUG("share_mode_entry_do failed\n");
2404 0 : return false;
2405 : }
2406 0 : if (!state.ok) {
2407 0 : DBG_DEBUG("downgrade_share_oplock_fn failed\n");
2408 0 : return false;
2409 : }
2410 :
2411 0 : lck->data->flags |= SHARE_MODE_LEASE_READ;
2412 0 : lck->data->modified = true;
2413 :
2414 0 : return true;
2415 : }
2416 :
2417 0 : bool mark_share_mode_disconnected(struct share_mode_lock *lck,
2418 : struct files_struct *fsp)
2419 : {
2420 0 : struct server_id disconnected_pid = { .pid = 0 };
2421 : bool ok;
2422 :
2423 0 : if (fsp->op == NULL) {
2424 0 : return false;
2425 : }
2426 0 : if (!fsp->op->global->durable) {
2427 0 : return false;
2428 : }
2429 :
2430 0 : server_id_set_disconnected(&disconnected_pid);
2431 :
2432 0 : ok = reset_share_mode_entry(
2433 : lck,
2434 0 : messaging_server_id(fsp->conn->sconn->msg_ctx),
2435 : fh_get_gen_id(fsp->fh),
2436 : disconnected_pid,
2437 : UINT64_MAX,
2438 0 : fsp->op->global->open_persistent_id);
2439 :
2440 0 : return ok;
2441 : }
2442 :
2443 0 : bool reset_share_mode_entry(
2444 : struct share_mode_lock *lck,
2445 : struct server_id old_pid,
2446 : uint64_t old_share_file_id,
2447 : struct server_id new_pid,
2448 : uint64_t new_mid,
2449 : uint64_t new_share_file_id)
2450 : {
2451 0 : struct share_mode_data *d = lck->data;
2452 0 : TDB_DATA key = locking_key(&d->id);
2453 0 : struct locking_tdb_data *ltdb = NULL;
2454 : struct share_mode_entry e;
2455 : struct share_mode_entry_buf e_buf;
2456 : NTSTATUS status;
2457 0 : bool ret = false;
2458 : bool ok;
2459 :
2460 0 : status = locking_tdb_data_fetch(key, talloc_tos(), <db);
2461 0 : if (!NT_STATUS_IS_OK(status)) {
2462 0 : DBG_DEBUG("locking_tdb_data_fetch failed: %s\n",
2463 : nt_errstr(status));
2464 0 : return false;
2465 : }
2466 :
2467 0 : if (ltdb->num_share_entries != 1) {
2468 0 : DBG_DEBUG("num_share_modes=%zu\n", ltdb->num_share_entries);
2469 0 : goto done;
2470 : }
2471 :
2472 0 : ok = share_mode_entry_get(ltdb->share_entries, &e);
2473 0 : if (!ok) {
2474 0 : DBG_WARNING("share_mode_entry_get failed\n");
2475 0 : goto done;
2476 : }
2477 :
2478 0 : ret = share_mode_entry_cmp(
2479 : old_pid, old_share_file_id, e.pid, e.share_file_id);
2480 0 : if (ret != 0) {
2481 : struct server_id_buf tmp1, tmp2;
2482 0 : DBG_WARNING("Expected pid=%s, file_id=%"PRIu64", "
2483 : "got pid=%s, file_id=%"PRIu64"\n",
2484 : server_id_str_buf(old_pid, &tmp1),
2485 : old_share_file_id,
2486 : server_id_str_buf(e.pid, &tmp2),
2487 : e.share_file_id);
2488 0 : goto done;
2489 : }
2490 :
2491 0 : e.pid = new_pid;
2492 0 : if (new_mid != UINT64_MAX) {
2493 0 : e.op_mid = new_mid;
2494 : }
2495 0 : e.share_file_id = new_share_file_id;
2496 :
2497 0 : ok = share_mode_entry_put(&e, &e_buf);
2498 0 : if (!ok) {
2499 0 : DBG_WARNING("share_mode_entry_put failed\n");
2500 0 : goto done;
2501 : }
2502 :
2503 0 : ltdb->share_entries = e_buf.buf;
2504 :
2505 0 : status = locking_tdb_data_store(key, ltdb, NULL, 0);
2506 0 : if (!NT_STATUS_IS_OK(status)) {
2507 0 : DBG_DEBUG("locking_tdb_data_store failed: %s\n",
2508 : nt_errstr(status));
2509 0 : goto done;
2510 : }
2511 :
2512 0 : d->modified = true;
2513 0 : ret = true;
2514 0 : done:
2515 0 : TALLOC_FREE(ltdb);
2516 0 : return true;
2517 : }
|