1 /*
2    Unix SMB/CIFS implementation.
3    oplock processing
4    Copyright (C) Andrew Tridgell 1992-1998
5    Copyright (C) Jeremy Allison 1998 - 2001
6    Copyright (C) Volker Lendecke 2005
7 
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 3 of the License, or
11    (at your option) any later version.
12 
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17 
18    You should have received a copy of the GNU General Public License
19    along with this program.  If not, see <http://www.gnu.org/licenses/>.
20 */
21 
22 #define DBGC_CLASS DBGC_LOCKING
23 #include "includes.h"
24 #include "lib/util/server_id.h"
25 #include "smbd/smbd.h"
26 #include "smbd/globals.h"
27 #include "messages.h"
28 #include "locking/leases_db.h"
29 #include "../librpc/gen_ndr/ndr_open_files.h"
30 
31 /*
32  * helper function used by the kernel oplock backends to post the break message
33  */
break_kernel_oplock(struct messaging_context * msg_ctx,files_struct * fsp)34 void break_kernel_oplock(struct messaging_context *msg_ctx, files_struct *fsp)
35 {
36 	uint8_t msg[MSG_SMB_KERNEL_BREAK_SIZE];
37 
38 	/* Put the kernel break info into the message. */
39 	push_file_id_24((char *)msg, &fsp->file_id);
40 	SIVAL(msg,24,fsp->fh->gen_id);
41 
42 	/* Don't need to be root here as we're only ever
43 	   sending to ourselves. */
44 
45 	messaging_send_buf(msg_ctx, messaging_server_id(msg_ctx),
46 			   MSG_SMB_KERNEL_BREAK,
47 			   msg, MSG_SMB_KERNEL_BREAK_SIZE);
48 }
49 
50 /****************************************************************************
51  Attempt to set an oplock on a file. Succeeds if kernel oplocks are
52  disabled (just sets flags).
53 ****************************************************************************/
54 
set_file_oplock(files_struct * fsp)55 NTSTATUS set_file_oplock(files_struct *fsp)
56 {
57 	struct smbd_server_connection *sconn = fsp->conn->sconn;
58 	struct kernel_oplocks *koplocks = sconn->oplocks.kernel_ops;
59 	bool use_kernel = lp_kernel_oplocks(SNUM(fsp->conn)) &&
60 			(koplocks != NULL);
61 	struct file_id_buf buf;
62 
63 	if (fsp->oplock_type == LEVEL_II_OPLOCK && use_kernel) {
64 		DEBUG(10, ("Refusing level2 oplock, kernel oplocks "
65 			   "don't support them\n"));
66 		return NT_STATUS_NOT_SUPPORTED;
67 	}
68 
69 	if ((fsp->oplock_type != NO_OPLOCK) &&
70 	    use_kernel &&
71 	    !koplocks->ops->set_oplock(koplocks, fsp, fsp->oplock_type))
72 	{
73 		return map_nt_error_from_unix(errno);
74 	}
75 
76 	fsp->sent_oplock_break = NO_BREAK_SENT;
77 	if (fsp->oplock_type == LEVEL_II_OPLOCK) {
78 		sconn->oplocks.level_II_open++;
79 	} else if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
80 		sconn->oplocks.exclusive_open++;
81 	}
82 
83 	DBG_INFO("granted oplock on file %s, %s/%"PRIu64", "
84 		 "tv_sec = %x, tv_usec = %x\n",
85 		 fsp_str_dbg(fsp),
86 		 file_id_str_buf(fsp->file_id, &buf),
87 		 fsp->fh->gen_id,
88 		 (int)fsp->open_time.tv_sec,
89 		 (int)fsp->open_time.tv_usec);
90 
91 	return NT_STATUS_OK;
92 }
93 
release_fsp_kernel_oplock(files_struct * fsp)94 static void release_fsp_kernel_oplock(files_struct *fsp)
95 {
96 	struct smbd_server_connection *sconn = fsp->conn->sconn;
97 	struct kernel_oplocks *koplocks = sconn->oplocks.kernel_ops;
98 	bool use_kernel;
99 
100 	if (koplocks == NULL) {
101 		return;
102 	}
103 	use_kernel = lp_kernel_oplocks(SNUM(fsp->conn));
104 	if (!use_kernel) {
105 		return;
106 	}
107 	if (fsp->oplock_type == NO_OPLOCK) {
108 		return;
109 	}
110 	if (fsp->oplock_type == LEASE_OPLOCK) {
111 		/*
112 		 * For leases we don't touch kernel oplocks at all
113 		 */
114 		return;
115 	}
116 
117 	koplocks->ops->release_oplock(koplocks, fsp, NO_OPLOCK);
118 }
119 
120 /****************************************************************************
121  Attempt to release an oplock on a file. Decrements oplock count.
122 ****************************************************************************/
123 
release_file_oplock(files_struct * fsp)124 static void release_file_oplock(files_struct *fsp)
125 {
126 	struct smbd_server_connection *sconn = fsp->conn->sconn;
127 
128 	release_fsp_kernel_oplock(fsp);
129 
130 	if (fsp->oplock_type == LEVEL_II_OPLOCK) {
131 		sconn->oplocks.level_II_open--;
132 	} else if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
133 		sconn->oplocks.exclusive_open--;
134 	}
135 
136 	SMB_ASSERT(sconn->oplocks.exclusive_open>=0);
137 	SMB_ASSERT(sconn->oplocks.level_II_open>=0);
138 
139 	fsp->oplock_type = NO_OPLOCK;
140 	fsp->sent_oplock_break = NO_BREAK_SENT;
141 
142 	TALLOC_FREE(fsp->oplock_timeout);
143 }
144 
145 /****************************************************************************
146  Attempt to downgrade an oplock on a file. Doesn't decrement oplock count.
147 ****************************************************************************/
148 
downgrade_file_oplock(files_struct * fsp)149 static void downgrade_file_oplock(files_struct *fsp)
150 {
151 	struct smbd_server_connection *sconn = fsp->conn->sconn;
152 	struct kernel_oplocks *koplocks = sconn->oplocks.kernel_ops;
153 	bool use_kernel = lp_kernel_oplocks(SNUM(fsp->conn)) &&
154 			(koplocks != NULL);
155 
156 	if (!EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
157 		DEBUG(0, ("trying to downgrade an already-downgraded oplock!\n"));
158 		return;
159 	}
160 
161 	if (use_kernel) {
162 		koplocks->ops->release_oplock(koplocks, fsp, LEVEL_II_OPLOCK);
163 	}
164 	fsp->oplock_type = LEVEL_II_OPLOCK;
165 	sconn->oplocks.exclusive_open--;
166 	sconn->oplocks.level_II_open++;
167 	fsp->sent_oplock_break = NO_BREAK_SENT;
168 
169 	TALLOC_FREE(fsp->oplock_timeout);
170 }
171 
get_lease_type(struct share_mode_entry * e,struct file_id id)172 uint32_t get_lease_type(struct share_mode_entry *e, struct file_id id)
173 {
174 	struct GUID_txt_buf guid_strbuf;
175 	struct file_id_buf file_id_strbuf;
176 	NTSTATUS status;
177 	uint32_t current_state;
178 
179 	if (e->op_type != LEASE_OPLOCK) {
180 		return map_oplock_to_lease_type(e->op_type);
181 	}
182 
183 	status = leases_db_get(&e->client_guid,
184 			       &e->lease_key,
185 			       &id,
186 			       &current_state,
187 			       NULL,	/* breaking */
188 			       NULL,	/* breaking_to_requested */
189 			       NULL,	/* breaking_to_required */
190 			       NULL,	/* lease_version */
191 			       NULL);	/* epoch */
192 	if (NT_STATUS_IS_OK(status)) {
193 		return current_state;
194 	}
195 
196 	if (share_entry_stale_pid(e)) {
197 		return 0;
198 	}
199 	DBG_ERR("leases_db_get for client_guid [%s] "
200 		"lease_key [%"PRIu64"/%"PRIu64"] "
201 		"file_id [%s] failed: %s\n",
202 		GUID_buf_string(&e->client_guid, &guid_strbuf),
203 		e->lease_key.data[0],
204 		e->lease_key.data[1],
205 		file_id_str_buf(id, &file_id_strbuf),
206 		nt_errstr(status));
207 	smb_panic("leases_db_get() failed");
208 }
209 
210 /****************************************************************************
211  Remove a file oplock. Copes with level II and exclusive.
212  Locks then unlocks the share mode lock. Client can decide to go directly
213  to none even if a "break-to-level II" was sent.
214 ****************************************************************************/
215 
remove_oplock(files_struct * fsp)216 bool remove_oplock(files_struct *fsp)
217 {
218 	bool ret;
219 	struct share_mode_lock *lck;
220 
221 	DBG_DEBUG("remove_oplock called for %s\n", fsp_str_dbg(fsp));
222 
223 	/* Remove the oplock flag from the sharemode. */
224 	lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
225 	if (lck == NULL) {
226 		DBG_ERR("failed to lock share entry for "
227 			 "file %s\n", fsp_str_dbg(fsp));
228 		return false;
229 	}
230 
231 	ret = remove_share_oplock(lck, fsp);
232 	if (!ret) {
233 		struct file_id_buf buf;
234 
235 		DBG_ERR("failed to remove share oplock for "
236 			"file %s, %s, %s\n",
237 			fsp_str_dbg(fsp), fsp_fnum_dbg(fsp),
238 			file_id_str_buf(fsp->file_id, &buf));
239 	}
240 	release_file_oplock(fsp);
241 
242 	TALLOC_FREE(lck);
243 	return ret;
244 }
245 
246 /*
247  * Deal with a reply when a break-to-level II was sent.
248  */
downgrade_oplock(files_struct * fsp)249 bool downgrade_oplock(files_struct *fsp)
250 {
251 	bool ret;
252 	struct share_mode_lock *lck;
253 
254 	DEBUG(10, ("downgrade_oplock called for %s\n",
255 		   fsp_str_dbg(fsp)));
256 
257 	lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
258 	if (lck == NULL) {
259 		DEBUG(0,("downgrade_oplock: failed to lock share entry for "
260 			 "file %s\n", fsp_str_dbg(fsp)));
261 		return False;
262 	}
263 	ret = downgrade_share_oplock(lck, fsp);
264 	if (!ret) {
265 		struct file_id_buf idbuf;
266 		DBG_ERR("failed to downgrade share oplock "
267 			"for file %s, %s, file_id %s\n",
268 			fsp_str_dbg(fsp),
269 			fsp_fnum_dbg(fsp),
270 			file_id_str_buf(fsp->file_id, &idbuf));
271 	}
272 	downgrade_file_oplock(fsp);
273 
274 	TALLOC_FREE(lck);
275 	return ret;
276 }
277 
lease_timeout_handler(struct tevent_context * ctx,struct tevent_timer * te,struct timeval now,void * private_data)278 static void lease_timeout_handler(struct tevent_context *ctx,
279 				  struct tevent_timer *te,
280 				  struct timeval now,
281 				  void *private_data)
282 {
283 	struct fsp_lease *lease =
284 		talloc_get_type_abort(private_data,
285 		struct fsp_lease);
286 	struct files_struct *fsp;
287 	struct share_mode_lock *lck;
288 	uint16_t old_epoch = lease->lease.lease_epoch;
289 
290 	fsp = file_find_one_fsp_from_lease_key(lease->sconn,
291 					       &lease->lease.lease_key);
292 	if (fsp == NULL) {
293 		/* race? */
294 		TALLOC_FREE(lease->timeout);
295 		return;
296 	}
297 
298 	/*
299 	 * Paranoia check: There can only be one fsp_lease per lease
300 	 * key
301 	 */
302 	SMB_ASSERT(fsp->lease == lease);
303 
304 	lck = get_existing_share_mode_lock(
305 			talloc_tos(), fsp->file_id);
306 	if (lck == NULL) {
307 		/* race? */
308 		TALLOC_FREE(lease->timeout);
309 		return;
310 	}
311 
312 	fsp_lease_update(fsp);
313 
314 	if (lease->lease.lease_epoch != old_epoch) {
315 		/*
316 		 * If the epoch changed we need to wait for
317 		 * the next timeout to happen.
318 		 */
319 		DEBUG(10, ("lease break timeout race (epoch) for file %s - ignoring\n",
320 			   fsp_str_dbg(fsp)));
321 		TALLOC_FREE(lck);
322 		return;
323 	}
324 
325 	if (!(lease->lease.lease_flags & SMB2_LEASE_FLAG_BREAK_IN_PROGRESS)) {
326 		/*
327 		 * If the epoch changed we need to wait for
328 		 * the next timeout to happen.
329 		 */
330 		DEBUG(10, ("lease break timeout race (flags) for file %s - ignoring\n",
331 			   fsp_str_dbg(fsp)));
332 		TALLOC_FREE(lck);
333 		return;
334 	}
335 
336 	DEBUG(1, ("lease break timed out for file %s -- replying anyway\n",
337 		  fsp_str_dbg(fsp)));
338 	(void)downgrade_lease(lease->sconn->client->connections,
339 			1,
340 			&fsp->file_id,
341 			&lease->lease.lease_key,
342 			SMB2_LEASE_NONE);
343 
344 	TALLOC_FREE(lck);
345 }
346 
fsp_lease_update(struct files_struct * fsp)347 bool fsp_lease_update(struct files_struct *fsp)
348 {
349 	const struct GUID *client_guid = fsp_client_guid(fsp);
350 	struct fsp_lease *lease = fsp->lease;
351 	uint32_t current_state;
352 	bool breaking;
353 	uint16_t lease_version, epoch;
354 	NTSTATUS status;
355 
356 	status = leases_db_get(client_guid,
357 			       &lease->lease.lease_key,
358 			       &fsp->file_id,
359 			       &current_state,
360 			       &breaking,
361 			       NULL, /* breaking_to_requested */
362 			       NULL, /* breaking_to_required */
363 			       &lease_version,
364 			       &epoch);
365 	if (!NT_STATUS_IS_OK(status)) {
366 		DBG_WARNING("Could not find lease entry: %s\n",
367 			    nt_errstr(status));
368 		TALLOC_FREE(lease->timeout);
369 		lease->lease.lease_state = SMB2_LEASE_NONE;
370 		lease->lease.lease_epoch += 1;
371 		lease->lease.lease_flags = 0;
372 		return false;
373 	}
374 
375 	DEBUG(10,("%s: refresh lease state\n", __func__));
376 
377 	/* Ensure we're in sync with current lease state. */
378 	if (lease->lease.lease_epoch != epoch) {
379 		DEBUG(10,("%s: cancel outdated timeout\n", __func__));
380 		TALLOC_FREE(lease->timeout);
381 	}
382 	lease->lease.lease_epoch = epoch;
383 	lease->lease.lease_state = current_state;
384 
385 	if (breaking) {
386 		lease->lease.lease_flags |= SMB2_LEASE_FLAG_BREAK_IN_PROGRESS;
387 
388 		if (lease->timeout == NULL) {
389 			struct timeval t = timeval_current_ofs(OPLOCK_BREAK_TIMEOUT, 0);
390 
391 			DEBUG(10,("%s: setup timeout handler\n", __func__));
392 
393 			lease->timeout = tevent_add_timer(lease->sconn->ev_ctx,
394 							  lease, t,
395 							  lease_timeout_handler,
396 							  lease);
397 			if (lease->timeout == NULL) {
398 				DEBUG(0, ("%s: Could not add lease timeout handler\n",
399 					  __func__));
400 			}
401 		}
402 	} else {
403 		lease->lease.lease_flags &= ~SMB2_LEASE_FLAG_BREAK_IN_PROGRESS;
404 		TALLOC_FREE(lease->timeout);
405 	}
406 
407 	return true;
408 }
409 
410 struct downgrade_lease_additional_state {
411 	struct tevent_immediate *im;
412 	struct smbXsrv_connection *xconn;
413 	uint32_t break_flags;
414 	struct smb2_lease_key lease_key;
415 	uint32_t break_from;
416 	uint32_t break_to;
417 	uint16_t new_epoch;
418 };
419 
downgrade_lease_additional_trigger(struct tevent_context * ev,struct tevent_immediate * im,void * private_data)420 static void downgrade_lease_additional_trigger(struct tevent_context *ev,
421 					       struct tevent_immediate *im,
422 					       void *private_data)
423 {
424 	struct downgrade_lease_additional_state *state =
425 		talloc_get_type_abort(private_data,
426 		struct downgrade_lease_additional_state);
427 	struct smbXsrv_connection *xconn = state->xconn;
428 	NTSTATUS status;
429 
430 	status = smbd_smb2_send_lease_break(xconn,
431 					    state->new_epoch,
432 					    state->break_flags,
433 					    &state->lease_key,
434 					    state->break_from,
435 					    state->break_to);
436 	TALLOC_FREE(state);
437 	if (!NT_STATUS_IS_OK(status)) {
438 		smbd_server_connection_terminate(xconn,
439 						 nt_errstr(status));
440 		return;
441 	}
442 }
443 
444 struct fsps_lease_update_state {
445 	const struct file_id *id;
446 	const struct smb2_lease_key *key;
447 };
448 
fsps_lease_update_fn(struct files_struct * fsp,void * private_data)449 static struct files_struct *fsps_lease_update_fn(
450 	struct files_struct *fsp, void *private_data)
451 {
452 	struct fsps_lease_update_state *state =
453 		(struct fsps_lease_update_state *)private_data;
454 
455 	if (fsp->oplock_type != LEASE_OPLOCK) {
456 		return NULL;
457 	}
458 	if (!smb2_lease_key_equal(&fsp->lease->lease.lease_key, state->key)) {
459 		return NULL;
460 	}
461 	if (!file_id_equal(&fsp->file_id, state->id)) {
462 		return NULL;
463 	}
464 
465 	fsp_lease_update(fsp);
466 
467 	return NULL;
468 }
469 
fsps_lease_update(struct smbd_server_connection * sconn,const struct file_id * id,const struct smb2_lease_key * key)470 static void fsps_lease_update(struct smbd_server_connection *sconn,
471 			      const struct file_id *id,
472 			      const struct smb2_lease_key *key)
473 {
474 	struct fsps_lease_update_state state = { .id = id, .key = key };
475 	files_forall(sconn, fsps_lease_update_fn, &state);
476 }
477 
downgrade_lease(struct smbXsrv_connection * xconn,uint32_t num_file_ids,const struct file_id * ids,const struct smb2_lease_key * key,uint32_t lease_state)478 NTSTATUS downgrade_lease(struct smbXsrv_connection *xconn,
479 			 uint32_t num_file_ids,
480 			 const struct file_id *ids,
481 			 const struct smb2_lease_key *key,
482 			 uint32_t lease_state)
483 {
484 	struct smbd_server_connection *sconn = xconn->client->sconn;
485 	const struct GUID *client_guid = NULL;
486 	struct share_mode_lock *lck;
487 	const struct file_id id = ids[0];
488 	uint32_t current_state, breaking_to_requested, breaking_to_required;
489 	bool breaking;
490 	uint16_t lease_version, epoch;
491 	NTSTATUS status;
492 	uint32_t i;
493 	struct file_id_buf idbuf;
494 
495 	DBG_DEBUG("Downgrading %s to %"PRIu32"\n",
496 		  file_id_str_buf(id, &idbuf),
497 		  lease_state);
498 
499 	lck = get_existing_share_mode_lock(talloc_tos(), id);
500 	if (lck == NULL) {
501 		return NT_STATUS_OBJECT_NAME_NOT_FOUND;
502 	}
503 
504 	client_guid = &sconn->client->connections->smb2.client.guid;
505 
506 	status = leases_db_get(client_guid,
507 			       key,
508 			       &id,
509 			       &current_state,
510 			       &breaking,
511 			       &breaking_to_requested,
512 			       &breaking_to_required,
513 			       &lease_version,
514 			       &epoch);
515 	if (!NT_STATUS_IS_OK(status)) {
516 		DBG_WARNING("leases_db_get returned %s\n",
517 			    nt_errstr(status));
518 		TALLOC_FREE(lck);
519 		return status;
520 	}
521 
522 	if (!breaking) {
523 		DBG_WARNING("Attempt to break from %"PRIu32" to %"PRIu32" - "
524 			    "but we're not in breaking state\n",
525 			    current_state, lease_state);
526 		TALLOC_FREE(lck);
527 		return NT_STATUS_UNSUCCESSFUL;
528 	}
529 
530 	/*
531 	 * Can't upgrade anything: breaking_to_requested (and current_state)
532 	 * must be a strict bitwise superset of new_lease_state
533 	 */
534 	if ((lease_state & breaking_to_requested) != lease_state) {
535 		DBG_WARNING("Attempt to upgrade from %"PRIu32" to %"PRIu32" "
536 			    "- expected %"PRIu32"\n",
537 			    current_state, lease_state,
538 			    breaking_to_requested);
539 		TALLOC_FREE(lck);
540 		return NT_STATUS_REQUEST_NOT_ACCEPTED;
541 	}
542 
543 	if (current_state != lease_state) {
544 		current_state = lease_state;
545 	}
546 
547 	status = NT_STATUS_OK;
548 
549 	if ((lease_state & ~breaking_to_required) != 0) {
550 		struct downgrade_lease_additional_state *state;
551 
552 		DBG_INFO("lease state %"PRIu32" not fully broken from "
553 			 "%"PRIu32" to %"PRIu32"\n",
554 			 lease_state,
555 			 current_state,
556 			 breaking_to_required);
557 
558 		breaking_to_requested = breaking_to_required;
559 
560 		if (current_state & (SMB2_LEASE_WRITE|SMB2_LEASE_HANDLE)) {
561 			/*
562 			 * Here we break in steps, as windows does
563 			 * see the breaking3 and v2_breaking3 tests.
564 			 */
565 			breaking_to_requested |= SMB2_LEASE_READ;
566 		}
567 
568 		state = talloc_zero(xconn,
569 				    struct downgrade_lease_additional_state);
570 		if (state == NULL) {
571 			TALLOC_FREE(lck);
572 			return NT_STATUS_NO_MEMORY;
573 		}
574 
575 		state->im = tevent_create_immediate(state);
576 		if (state->im == NULL) {
577 			TALLOC_FREE(state);
578 			TALLOC_FREE(lck);
579 			return NT_STATUS_NO_MEMORY;
580 		}
581 
582 		state->xconn = xconn;
583 		state->lease_key = *key;
584 		state->break_from = current_state;
585 		state->break_to = breaking_to_requested;
586 		if (lease_version > 1) {
587 			state->new_epoch = epoch;
588 		}
589 
590 		if (current_state & (SMB2_LEASE_WRITE|SMB2_LEASE_HANDLE)) {
591 			state->break_flags =
592 				SMB2_NOTIFY_BREAK_LEASE_FLAG_ACK_REQUIRED;
593 		} else {
594 			/*
595 			 * This is an async break without
596 			 * SMB2_NOTIFY_BREAK_LEASE_FLAG_ACK_REQUIRED
597 			 *
598 			 * we need to store NONE state in the
599 			 * database.
600 			 */
601 			current_state = 0;
602 			breaking_to_requested = 0;
603 			breaking_to_required = 0;
604 			breaking = false;
605 
606 			{
607 				NTSTATUS set_status;
608 
609 				set_status = leases_db_set(
610 					&sconn->client->connections->
611 					smb2.client.guid,
612 					key,
613 					current_state,
614 					breaking,
615 					breaking_to_requested,
616 					breaking_to_required,
617 					lease_version,
618 					epoch);
619 
620 				if (!NT_STATUS_IS_OK(set_status)) {
621 					DBG_DEBUG("leases_db_set failed: %s\n",
622 						  nt_errstr(set_status));
623 					return set_status;
624 				}
625 			}
626 		}
627 
628 		tevent_schedule_immediate(state->im,
629 					  xconn->client->raw_ev_ctx,
630 					  downgrade_lease_additional_trigger,
631 					  state);
632 
633 		status = NT_STATUS_OPLOCK_BREAK_IN_PROGRESS;
634 	} else {
635 		DBG_DEBUG("breaking from %"PRIu32" to %"PRIu32" - "
636 			  "expected %"PRIu32"\n",
637 			  current_state,
638 			  lease_state,
639 			  breaking_to_requested);
640 
641 		breaking_to_requested = 0;
642 		breaking_to_required = 0;
643 		breaking = false;
644 	}
645 
646 	{
647 		NTSTATUS set_status;
648 
649 		set_status = leases_db_set(
650 			client_guid,
651 			key,
652 			current_state,
653 			breaking,
654 			breaking_to_requested,
655 			breaking_to_required,
656 			lease_version,
657 			epoch);
658 
659 		if (!NT_STATUS_IS_OK(set_status)) {
660 			DBG_DEBUG("leases_db_set failed: %s\n",
661 				  nt_errstr(set_status));
662 			TALLOC_FREE(lck);
663 			return set_status;
664 		}
665 	}
666 
667 	DBG_DEBUG("Downgrading %s to %"PRIu32" => %s\n",
668 		  file_id_str_buf(id, &idbuf),
669 		  lease_state,
670 		  nt_errstr(status));
671 
672 	share_mode_wakeup_waiters(id);
673 
674 	fsps_lease_update(sconn, &id, key);
675 
676 	TALLOC_FREE(lck);
677 
678 	DBG_DEBUG("Downgrading %s to %"PRIu32" => %s\n",
679 		  file_id_str_buf(id, &idbuf),
680 		  lease_state,
681 		  nt_errstr(status));
682 
683 	/*
684 	 * Dynamic share case. Ensure other opens are copies.
685 	 * This will only be breaking to NONE.
686 	 */
687 
688 	for (i = 1; i < num_file_ids; i++) {
689 		lck = get_existing_share_mode_lock(talloc_tos(), ids[i]);
690 		if (lck == NULL) {
691 			return NT_STATUS_OBJECT_NAME_NOT_FOUND;
692 		}
693 
694 		fsps_lease_update(sconn, &ids[i], key);
695 
696 		DBG_DEBUG("Downgrading %s to %"PRIu32" => %s\n",
697 			  file_id_str_buf(ids[i], &idbuf),
698 			  lease_state,
699 			  nt_errstr(status));
700 
701 		TALLOC_FREE(lck);
702 	}
703 
704 	return status;
705 }
706 
707 /****************************************************************************
708  Set up an oplock break message.
709 ****************************************************************************/
710 
711 #define SMB1_BREAK_MESSAGE_LENGTH (smb_size + 8*2)
712 
new_break_message_smb1(files_struct * fsp,int cmd,char result[SMB1_BREAK_MESSAGE_LENGTH])713 static void new_break_message_smb1(files_struct *fsp, int cmd,
714 				   char result[SMB1_BREAK_MESSAGE_LENGTH])
715 {
716 	memset(result,'\0',smb_size);
717 	srv_set_message(result,8,0,true);
718 	SCVAL(result,smb_com,SMBlockingX);
719 	SSVAL(result,smb_tid,fsp->conn->cnum);
720 	SSVAL(result,smb_pid,0xFFFF);
721 	SSVAL(result,smb_uid,0);
722 	SSVAL(result,smb_mid,0xFFFF);
723 	SCVAL(result,smb_vwv0,0xFF);
724 	SSVAL(result,smb_vwv2,fsp->fnum);
725 	SCVAL(result,smb_vwv3,LOCKING_ANDX_OPLOCK_RELEASE);
726 	SCVAL(result,smb_vwv3+1,cmd);
727 }
728 
729 /****************************************************************************
730  Function to do the waiting before sending a local break.
731 ****************************************************************************/
732 
wait_before_sending_break(void)733 static void wait_before_sending_break(void)
734 {
735 	long wait_time = (long)lp_oplock_break_wait_time();
736 
737 	if (wait_time) {
738 		smb_msleep(wait_time);
739 	}
740 }
741 
742 /****************************************************************************
743  Ensure that we have a valid oplock.
744 ****************************************************************************/
745 
initial_break_processing(struct smbd_server_connection * sconn,struct file_id id,unsigned long file_id)746 static files_struct *initial_break_processing(
747 	struct smbd_server_connection *sconn, struct file_id id,
748 	unsigned long file_id)
749 {
750 	files_struct *fsp = NULL;
751 	struct file_id_buf idbuf;
752 
753 	DBG_NOTICE("called for %s/%u\n"
754 		   "Current oplocks_open (exclusive = %d, levelII = %d)\n",
755 		   file_id_str_buf(id, &idbuf),
756 		   (int)file_id,
757 		   sconn->oplocks.exclusive_open,
758 		   sconn->oplocks.level_II_open);
759 
760 	/*
761 	 * We need to search the file open table for the
762 	 * entry containing this dev and inode, and ensure
763 	 * we have an oplock on it.
764 	 */
765 
766 	fsp = file_find_dif(sconn, id, file_id);
767 
768 	if(fsp == NULL) {
769 		/* The file could have been closed in the meantime - return success. */
770 		DBG_NOTICE("cannot find open file "
771 			   "with file_id %s gen_id = %lu, allowing break to "
772 			   "succeed.\n",
773 			   file_id_str_buf(id, &idbuf),
774 			   file_id);
775 		return NULL;
776 	}
777 
778 	/* Ensure we have an oplock on the file */
779 
780 	/*
781 	 * There is a potential race condition in that an oplock could
782 	 * have been broken due to another udp request, and yet there are
783 	 * still oplock break messages being sent in the udp message
784 	 * queue for this file. So return true if we don't have an oplock,
785 	 * as we may have just freed it.
786 	 */
787 
788 	if(fsp->oplock_type == NO_OPLOCK) {
789 		DBG_NOTICE("file %s (file_id = %s gen_id = %"PRIu64") "
790 			   "has no oplock. "
791 			   "Allowing break to succeed regardless.\n",
792 			   fsp_str_dbg(fsp),
793 			   file_id_str_buf(id, &idbuf),
794 			   fsp->fh->gen_id);
795 		return NULL;
796 	}
797 
798 	return fsp;
799 }
800 
oplock_timeout_handler(struct tevent_context * ctx,struct tevent_timer * te,struct timeval now,void * private_data)801 static void oplock_timeout_handler(struct tevent_context *ctx,
802 				   struct tevent_timer *te,
803 				   struct timeval now,
804 				   void *private_data)
805 {
806 	files_struct *fsp = (files_struct *)private_data;
807 
808 	SMB_ASSERT(fsp->sent_oplock_break != NO_BREAK_SENT);
809 
810 	/* Remove the timed event handler. */
811 	TALLOC_FREE(fsp->oplock_timeout);
812 	DEBUG(0, ("Oplock break failed for file %s -- replying anyway\n",
813 		  fsp_str_dbg(fsp)));
814 	remove_oplock(fsp);
815 }
816 
817 /*******************************************************************
818  Add a timeout handler waiting for the client reply.
819 *******************************************************************/
820 
add_oplock_timeout_handler(files_struct * fsp)821 static void add_oplock_timeout_handler(files_struct *fsp)
822 {
823 	if (fsp->oplock_timeout != NULL) {
824 		DEBUG(0, ("Logic problem -- have an oplock event hanging "
825 			  "around\n"));
826 	}
827 
828 	fsp->oplock_timeout =
829 		tevent_add_timer(fsp->conn->sconn->ev_ctx, fsp,
830 				 timeval_current_ofs(OPLOCK_BREAK_TIMEOUT, 0),
831 				 oplock_timeout_handler, fsp);
832 
833 	if (fsp->oplock_timeout == NULL) {
834 		DEBUG(0, ("Could not add oplock timeout handler\n"));
835 	}
836 }
837 
send_break_message_smb1(files_struct * fsp,int level)838 static void send_break_message_smb1(files_struct *fsp, int level)
839 {
840 	struct smbXsrv_connection *xconn = NULL;
841 	char break_msg[SMB1_BREAK_MESSAGE_LENGTH];
842 
843 	/*
844 	 * For SMB1 we only have one connection
845 	 */
846 	xconn = fsp->conn->sconn->client->connections;
847 
848 	new_break_message_smb1(fsp, level, break_msg);
849 
850 	show_msg(break_msg);
851 	if (!srv_send_smb(xconn,
852 			break_msg, false, 0,
853 			IS_CONN_ENCRYPTED(fsp->conn),
854 			NULL)) {
855 		exit_server_cleanly("send_break_message_smb1: "
856 			"srv_send_smb failed.");
857 	}
858 }
859 
860 /*******************************************************************
861  This handles the generic oplock break message from another smbd.
862 *******************************************************************/
863 
process_oplock_break_message(struct messaging_context * msg_ctx,void * private_data,uint32_t msg_type,struct server_id src,DATA_BLOB * data)864 static void process_oplock_break_message(struct messaging_context *msg_ctx,
865 					 void *private_data,
866 					 uint32_t msg_type,
867 					 struct server_id src,
868 					 DATA_BLOB *data)
869 {
870 	struct oplock_break_message *msg = NULL;
871 	enum ndr_err_code ndr_err;
872 	files_struct *fsp;
873 	bool use_kernel;
874 	struct smbd_server_connection *sconn =
875 		talloc_get_type_abort(private_data,
876 		struct smbd_server_connection);
877 	struct server_id self = messaging_server_id(sconn->msg_ctx);
878 	struct kernel_oplocks *koplocks = sconn->oplocks.kernel_ops;
879 	uint16_t break_from;
880 	uint16_t break_to;
881 	bool break_needed = true;
882 
883 	msg = talloc(talloc_tos(), struct oplock_break_message);
884 	if (msg == NULL) {
885 		DBG_WARNING("talloc failed\n");
886 		return;
887 	}
888 
889 	ndr_err = ndr_pull_struct_blob_all(
890 		data,
891 		msg,
892 		msg,
893 		(ndr_pull_flags_fn_t)ndr_pull_oplock_break_message);
894 	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
895 		DBG_DEBUG("ndr_pull_oplock_break_message failed: %s\n",
896 			  ndr_errstr(ndr_err));
897 		TALLOC_FREE(msg);
898 		return;
899 	}
900 	if (DEBUGLEVEL >= 10) {
901 		struct server_id_buf buf;
902 		DBG_DEBUG("Got break message from %s\n",
903 			  server_id_str_buf(src, &buf));
904 		NDR_PRINT_DEBUG(oplock_break_message, msg);
905 	}
906 
907 	break_to = msg->break_to;
908 	fsp = initial_break_processing(sconn, msg->id, msg->share_file_id);
909 
910 	TALLOC_FREE(msg);
911 
912 	if (fsp == NULL) {
913 		/* We hit a race here. Break messages are sent, and before we
914 		 * get to process this message, we have closed the file. */
915 		DEBUG(3, ("Did not find fsp\n"));
916 		return;
917 	}
918 
919 	break_from = fsp_lease_type(fsp);
920 
921 	if (fsp->oplock_type != LEASE_OPLOCK) {
922 		if (fsp->sent_oplock_break != NO_BREAK_SENT) {
923 			/*
924 			 * Nothing to do anymore
925 			 */
926 			DEBUG(10, ("fsp->sent_oplock_break = %d\n",
927 				   fsp->sent_oplock_break));
928 			return;
929 		}
930 	}
931 
932 	if (!(global_client_caps & CAP_LEVEL_II_OPLOCKS)) {
933 		DEBUG(10, ("client_caps without level2 oplocks\n"));
934 		break_to &= ~SMB2_LEASE_READ;
935 	}
936 
937 	use_kernel = lp_kernel_oplocks(SNUM(fsp->conn)) &&
938 			(koplocks != NULL);
939 	if (use_kernel) {
940 		DEBUG(10, ("Kernel oplocks don't allow level2\n"));
941 		break_to &= ~SMB2_LEASE_READ;
942 	}
943 
944 	if (!lp_level2_oplocks(SNUM(fsp->conn))) {
945 		DEBUG(10, ("no level2 oplocks by config\n"));
946 		break_to &= ~SMB2_LEASE_READ;
947 	}
948 
949 	if (fsp->oplock_type == LEASE_OPLOCK) {
950 		const struct GUID *client_guid = fsp_client_guid(fsp);
951 		struct share_mode_lock *lck;
952 		uint32_t current_state;
953 		uint32_t breaking_to_requested, breaking_to_required;
954 		bool breaking;
955 		uint16_t lease_version, epoch;
956 		NTSTATUS status;
957 
958 		lck = get_existing_share_mode_lock(
959 			talloc_tos(), fsp->file_id);
960 		if (lck == NULL) {
961 			/*
962 			 * We hit a race here. Break messages are sent, and
963 			 * before we get to process this message, we have closed
964 			 * the file.
965 			 */
966 			DEBUG(3, ("Did not find share_mode\n"));
967 			return;
968 		}
969 
970 		status = leases_db_get(client_guid,
971 				       &fsp->lease->lease.lease_key,
972 				       &fsp->file_id,
973 				       &current_state,
974 				       &breaking,
975 				       &breaking_to_requested,
976 				       &breaking_to_required,
977 				       &lease_version,
978 				       &epoch);
979 		if (!NT_STATUS_IS_OK(status)) {
980 			DBG_WARNING("leases_db_get returned %s\n",
981 				    nt_errstr(status));
982 			TALLOC_FREE(lck);
983 			return;
984 		}
985 
986 		break_from = current_state;
987 		break_to &= current_state;
988 
989 		if (breaking) {
990 			break_to &= breaking_to_required;
991 			if (breaking_to_required != break_to) {
992 				/*
993 				 * Note we don't increment the epoch
994 				 * here, which might be a bug in
995 				 * Windows too...
996 				 */
997 				breaking_to_required = break_to;
998 			}
999 			break_needed = false;
1000 		} else if (current_state == break_to) {
1001 			break_needed = false;
1002 		} else if (current_state == SMB2_LEASE_READ) {
1003 			current_state = SMB2_LEASE_NONE;
1004 			/* Need to increment the epoch */
1005 			epoch += 1;
1006 		} else {
1007 			breaking = true;
1008 			breaking_to_required = break_to;
1009 			breaking_to_requested = break_to;
1010 			/* Need to increment the epoch */
1011 			epoch += 1;
1012 		}
1013 
1014 		{
1015 			NTSTATUS set_status;
1016 
1017 			set_status = leases_db_set(
1018 				client_guid,
1019 				&fsp->lease->lease.lease_key,
1020 				current_state,
1021 				breaking,
1022 				breaking_to_requested,
1023 				breaking_to_required,
1024 				lease_version,
1025 				epoch);
1026 
1027 			if (!NT_STATUS_IS_OK(set_status)) {
1028 				DBG_DEBUG("leases_db_set failed: %s\n",
1029 					  nt_errstr(set_status));
1030 				return;
1031 			}
1032 		}
1033 
1034 		/* Ensure we're in sync with current lease state. */
1035 		fsp_lease_update(fsp);
1036 
1037 		TALLOC_FREE(lck);
1038 	}
1039 
1040 	if (!break_needed) {
1041 		DEBUG(10,("%s: skip break\n", __func__));
1042 		return;
1043 	}
1044 
1045 	if (break_from == SMB2_LEASE_NONE) {
1046 		struct file_id_buf idbuf;
1047 		DBG_NOTICE("Already downgraded oplock to none on %s: %s\n",
1048 			   file_id_str_buf(fsp->file_id, &idbuf),
1049 			   fsp_str_dbg(fsp));
1050 		return;
1051 	}
1052 
1053 	DEBUG(10, ("break_from=%u, break_to=%u\n",
1054 		   (unsigned)break_from, (unsigned)break_to));
1055 
1056 	if (break_from == break_to) {
1057 		struct file_id_buf idbuf;
1058 		DBG_NOTICE("Already downgraded oplock to %u on %s: %s\n",
1059 			   (unsigned)break_to,
1060 			   file_id_str_buf(fsp->file_id, &idbuf),
1061 			   fsp_str_dbg(fsp));
1062 		return;
1063 	}
1064 
1065 	/* Need to wait before sending a break
1066 	   message if we sent ourselves this message. */
1067 	if (server_id_equal(&self, &src)) {
1068 		wait_before_sending_break();
1069 	}
1070 
1071 	if (sconn->using_smb2) {
1072 		send_break_message_smb2(fsp, break_from, break_to);
1073 	} else {
1074 		send_break_message_smb1(fsp, (break_to & SMB2_LEASE_READ) ?
1075 					OPLOCKLEVEL_II : OPLOCKLEVEL_NONE);
1076 	}
1077 
1078 	if ((break_from == SMB2_LEASE_READ) &&
1079 	    (break_to == SMB2_LEASE_NONE)) {
1080 		/*
1081 		 * This is an async break without a reply and thus no timeout
1082 		 *
1083 		 * leases are handled above.
1084 		 */
1085 		if (fsp->oplock_type != LEASE_OPLOCK) {
1086 			remove_oplock(fsp);
1087 		}
1088 		return;
1089 	}
1090 	if (fsp->oplock_type == LEASE_OPLOCK) {
1091 		return;
1092 	}
1093 
1094 	fsp->sent_oplock_break = (break_to & SMB2_LEASE_READ) ?
1095 		LEVEL_II_BREAK_SENT:BREAK_TO_NONE_SENT;
1096 
1097 	add_oplock_timeout_handler(fsp);
1098 }
1099 
1100 /*******************************************************************
1101  This handles the kernel oplock break message.
1102 *******************************************************************/
1103 
process_kernel_oplock_break(struct messaging_context * msg_ctx,void * private_data,uint32_t msg_type,struct server_id src,DATA_BLOB * data)1104 static void process_kernel_oplock_break(struct messaging_context *msg_ctx,
1105 					void *private_data,
1106 					uint32_t msg_type,
1107 					struct server_id src,
1108 					DATA_BLOB *data)
1109 {
1110 	struct file_id id;
1111 	struct file_id_buf idbuf;
1112 	unsigned long file_id;
1113 	files_struct *fsp;
1114 	struct smbd_server_connection *sconn =
1115 		talloc_get_type_abort(private_data,
1116 		struct smbd_server_connection);
1117 	struct server_id_buf tmp;
1118 
1119 	if (data->data == NULL) {
1120 		DEBUG(0, ("Got NULL buffer\n"));
1121 		return;
1122 	}
1123 
1124 	if (data->length != MSG_SMB_KERNEL_BREAK_SIZE) {
1125 		DEBUG(0, ("Got invalid msg len %d\n", (int)data->length));
1126 		return;
1127 	}
1128 
1129 	/* Pull the data from the message. */
1130 	pull_file_id_24((char *)data->data, &id);
1131 	file_id = (unsigned long)IVAL(data->data, 24);
1132 
1133 	DBG_DEBUG("Got kernel oplock break message from pid %s: %s/%u\n",
1134 		  server_id_str_buf(src, &tmp),
1135 		  file_id_str_buf(id, &idbuf),
1136 		  (unsigned int)file_id);
1137 
1138 	fsp = initial_break_processing(sconn, id, file_id);
1139 
1140 	if (fsp == NULL) {
1141 		DEBUG(3, ("Got a kernel oplock break message for a file "
1142 			  "I don't know about\n"));
1143 		return;
1144 	}
1145 
1146 	if (fsp->sent_oplock_break != NO_BREAK_SENT) {
1147 		/* This is ok, kernel oplocks come in completely async */
1148 		DEBUG(3, ("Got a kernel oplock request while waiting for a "
1149 			  "break reply\n"));
1150 		return;
1151 	}
1152 
1153 	if (sconn->using_smb2) {
1154 		send_break_message_smb2(fsp, 0, OPLOCKLEVEL_NONE);
1155 	} else {
1156 		send_break_message_smb1(fsp, OPLOCKLEVEL_NONE);
1157 	}
1158 
1159 	fsp->sent_oplock_break = BREAK_TO_NONE_SENT;
1160 
1161 	add_oplock_timeout_handler(fsp);
1162 }
1163 
send_break_to_none(struct messaging_context * msg_ctx,const struct file_id * id,const struct share_mode_entry * e)1164 static void send_break_to_none(struct messaging_context *msg_ctx,
1165 			       const struct file_id *id,
1166 			       const struct share_mode_entry *e)
1167 {
1168 	NTSTATUS status;
1169 	status = send_break_message(msg_ctx, id, e, OPLOCK_NONE);
1170 	if (!NT_STATUS_IS_OK(status)) {
1171 		DBG_DEBUG("send_break_message failed: %s\n",
1172 			  nt_errstr(status));
1173 	}
1174 }
1175 struct break_to_none_state {
1176 	struct smbd_server_connection *sconn;
1177 	struct file_id id;
1178 	struct smb2_lease_key lease_key;
1179 	struct GUID client_guid;
1180 	size_t num_broken;
1181 };
1182 
do_break_lease_to_none(struct share_mode_entry * e,void * private_data)1183 static bool do_break_lease_to_none(struct share_mode_entry *e,
1184 				   void *private_data)
1185 {
1186 	struct break_to_none_state *state = private_data;
1187 	uint32_t current_state = 0;
1188 	bool our_own;
1189 	NTSTATUS status;
1190 
1191 	DBG_DEBUG("lease_key=%"PRIu64"/%"PRIu64"\n",
1192 		  e->lease_key.data[0],
1193 		  e->lease_key.data[1]);
1194 
1195 	status = leases_db_get(&e->client_guid,
1196 			       &e->lease_key,
1197 			       &state->id,
1198 			       &current_state,
1199 			       NULL, /* breaking */
1200 			       NULL, /* breaking_to_requested */
1201 			       NULL, /* breaking_to_required */
1202 			       NULL, /* lease_version */
1203 			       NULL); /* epoch */
1204 	if (!NT_STATUS_IS_OK(status)) {
1205 		DBG_WARNING("leases_db_get failed: %s\n",
1206 			    nt_errstr(status));
1207 		return false;
1208 	}
1209 
1210 	if ((current_state & SMB2_LEASE_READ) == 0) {
1211 		return false;
1212 	}
1213 
1214 	our_own = smb2_lease_equal(&state->client_guid,
1215 				   &state->lease_key,
1216 				   &e->client_guid,
1217 				   &e->lease_key);
1218 	if (our_own) {
1219 		DEBUG(10, ("Don't break our own lease\n"));
1220 		return false;
1221 	}
1222 
1223 	DBG_DEBUG("Breaking %"PRIu64"/%"PRIu64" to none\n",
1224 		  e->lease_key.data[0],
1225 		  e->lease_key.data[1]);
1226 
1227 	send_break_to_none(state->sconn->msg_ctx, &state->id, e);
1228 
1229 	state->num_broken += 1;
1230 
1231 	return false;
1232 }
1233 
do_break_oplock_to_none(struct share_mode_entry * e,bool * modified,void * private_data)1234 static bool do_break_oplock_to_none(struct share_mode_entry *e,
1235 				    bool *modified,
1236 				    void *private_data)
1237 {
1238 	struct break_to_none_state *state = private_data;
1239 
1240 	if (e->op_type == LEASE_OPLOCK) {
1241 		/*
1242 		 * Already being taken care of
1243 		 */
1244 		return false;
1245 	}
1246 
1247 	/*
1248 	 * As there could have been multiple writes waiting at the
1249 	 * lock_share_entry gate we may not be the first to
1250 	 * enter. Hence the state of the op_types in the share mode
1251 	 * entries may be partly NO_OPLOCK and partly LEVEL_II
1252 	 * oplock. It will do no harm to re-send break messages to
1253 	 * those smbd's that are still waiting their turn to remove
1254 	 * their LEVEL_II state, and also no harm to ignore existing
1255 	 * NO_OPLOCK states. JRA.
1256 	 */
1257 
1258 	DBG_DEBUG("e->op_type == %d\n", e->op_type);
1259 
1260 	if (e->op_type == NO_OPLOCK) {
1261 		return false;
1262 	}
1263 
1264 	/* Paranoia .... */
1265 	SMB_ASSERT(!EXCLUSIVE_OPLOCK_TYPE(e->op_type));
1266 
1267 	send_break_to_none(state->sconn->msg_ctx, &state->id, e);
1268 	state->num_broken += 1;
1269 
1270 	return false;
1271 }
1272 
1273 /****************************************************************************
1274  This function is called on any file modification or lock request. If a file
1275  is level 2 oplocked then it must tell all other level 2 holders to break to
1276  none.
1277 ****************************************************************************/
1278 
contend_level2_oplocks_begin_default(files_struct * fsp,enum level2_contention_type type)1279 static void contend_level2_oplocks_begin_default(files_struct *fsp,
1280 					      enum level2_contention_type type)
1281 {
1282 	struct break_to_none_state state = {
1283 		.sconn = fsp->conn->sconn, .id = fsp->file_id,
1284 	};
1285 	struct share_mode_lock *lck = NULL;
1286 	struct share_mode_data *d = NULL;
1287 	bool ok, has_read_lease;
1288 
1289 	/*
1290 	 * If this file is level II oplocked then we need
1291 	 * to grab the shared memory lock and inform all
1292 	 * other files with a level II lock that they need
1293 	 * to flush their read caches. We keep the lock over
1294 	 * the shared memory area whilst doing this.
1295 	 */
1296 
1297 	if (fsp_lease_type_is_exclusive(fsp)) {
1298 		/*
1299 		 * There can't be any level2 oplocks, we're alone.
1300 		 */
1301 		return;
1302 	}
1303 
1304 	has_read_lease = file_has_read_lease(fsp);
1305 	if (!has_read_lease) {
1306 		DEBUG(10, ("No read oplocks around\n"));
1307 		return;
1308 	}
1309 
1310 	if (fsp->oplock_type == LEASE_OPLOCK) {
1311 		state.client_guid = *fsp_client_guid(fsp);
1312 		state.lease_key = fsp->lease->lease.lease_key;
1313 		DEBUG(10, ("Breaking through lease key %"PRIu64"/%"PRIu64"\n",
1314 			   state.lease_key.data[0],
1315 			   state.lease_key.data[1]));
1316 	}
1317 
1318 	lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
1319 	if (lck == NULL) {
1320 		struct file_id_buf idbuf;
1321 		DBG_WARNING("failed to lock share mode entry for file %s.\n",
1322 			    file_id_str_buf(state.id, &idbuf));
1323 		return;
1324 	}
1325 	d = lck->data;
1326 
1327 	/*
1328 	 * Walk leases and oplocks separately: We have to send one break per
1329 	 * lease. If we have multiple share_mode_entry having a common lease,
1330 	 * we would break the lease twice if we don't walk the leases list
1331 	 * separately.
1332 	 */
1333 
1334 	ok = share_mode_forall_leases(lck, do_break_lease_to_none, &state);
1335 	if (!ok) {
1336 		DBG_WARNING("share_mode_forall_leases failed\n");
1337 	}
1338 
1339 	ok = share_mode_forall_entries(lck, do_break_oplock_to_none, &state);
1340 	if (!ok) {
1341 		DBG_WARNING("share_mode_forall_entries failed\n");
1342 	}
1343 
1344 	if (state.num_broken == 0) {
1345 		/*
1346 		 * Lazy update here. It might be that the read lease
1347 		 * has gone in the meantime.
1348 		 */
1349 		d->flags &= ~SHARE_MODE_LEASE_READ;
1350 		d->modified = true;
1351 	}
1352 
1353 	TALLOC_FREE(lck);
1354 }
1355 
smbd_contend_level2_oplocks_begin(files_struct * fsp,enum level2_contention_type type)1356 void smbd_contend_level2_oplocks_begin(files_struct *fsp,
1357 				  enum level2_contention_type type)
1358 {
1359 	contend_level2_oplocks_begin_default(fsp, type);
1360 }
1361 
smbd_contend_level2_oplocks_end(files_struct * fsp,enum level2_contention_type type)1362 void smbd_contend_level2_oplocks_end(files_struct *fsp,
1363 				enum level2_contention_type type)
1364 {
1365 	return;
1366 }
1367 
1368 /****************************************************************************
1369  Linearize a share mode entry struct to an internal oplock break message.
1370 ****************************************************************************/
1371 
share_mode_entry_to_message(char * msg,const struct file_id * id,const struct share_mode_entry * e)1372 void share_mode_entry_to_message(char *msg, const struct file_id *id,
1373 				 const struct share_mode_entry *e)
1374 {
1375 	SIVAL(msg,OP_BREAK_MSG_PID_OFFSET,(uint32_t)e->pid.pid);
1376 	SBVAL(msg,OP_BREAK_MSG_MID_OFFSET,e->op_mid);
1377 	SSVAL(msg,OP_BREAK_MSG_OP_TYPE_OFFSET,e->op_type);
1378 	SIVAL(msg,OP_BREAK_MSG_ACCESS_MASK_OFFSET,e->access_mask);
1379 	SIVAL(msg,OP_BREAK_MSG_SHARE_ACCESS_OFFSET,e->share_access);
1380 	SIVAL(msg,OP_BREAK_MSG_PRIV_OFFSET,e->private_options);
1381 	SIVAL(msg,OP_BREAK_MSG_TIME_SEC_OFFSET,(uint32_t)e->time.tv_sec);
1382 	SIVAL(msg,OP_BREAK_MSG_TIME_USEC_OFFSET,(uint32_t)e->time.tv_usec);
1383 	/*
1384 	 * "id" used to be part of share_mode_entry, thus the strange
1385 	 * place to put this. Feel free to move somewhere else :-)
1386 	 */
1387 	push_file_id_24(msg+OP_BREAK_MSG_DEV_OFFSET, id);
1388 	SIVAL(msg,OP_BREAK_MSG_FILE_ID_OFFSET,e->share_file_id);
1389 	SIVAL(msg,OP_BREAK_MSG_UID_OFFSET,e->uid);
1390 	SSVAL(msg,OP_BREAK_MSG_FLAGS_OFFSET,e->flags);
1391 	SIVAL(msg,OP_BREAK_MSG_NAME_HASH_OFFSET,e->name_hash);
1392 	SIVAL(msg,OP_BREAK_MSG_VNN_OFFSET,e->pid.vnn);
1393 }
1394 
1395 /****************************************************************************
1396  De-linearize an internal oplock break message to a share mode entry struct.
1397 ****************************************************************************/
1398 
message_to_share_mode_entry(struct file_id * id,struct share_mode_entry * e,const char * msg)1399 void message_to_share_mode_entry(struct file_id *id,
1400 				 struct share_mode_entry *e,
1401 				 const char *msg)
1402 {
1403 	e->pid.pid = (pid_t)IVAL(msg,OP_BREAK_MSG_PID_OFFSET);
1404 	e->op_mid = BVAL(msg,OP_BREAK_MSG_MID_OFFSET);
1405 	e->op_type = SVAL(msg,OP_BREAK_MSG_OP_TYPE_OFFSET);
1406 	e->access_mask = IVAL(msg,OP_BREAK_MSG_ACCESS_MASK_OFFSET);
1407 	e->share_access = IVAL(msg,OP_BREAK_MSG_SHARE_ACCESS_OFFSET);
1408 	e->private_options = IVAL(msg,OP_BREAK_MSG_PRIV_OFFSET);
1409 	e->time.tv_sec = (time_t)IVAL(msg,OP_BREAK_MSG_TIME_SEC_OFFSET);
1410 	e->time.tv_usec = (int)IVAL(msg,OP_BREAK_MSG_TIME_USEC_OFFSET);
1411 	/*
1412 	 * "id" used to be part of share_mode_entry, thus the strange
1413 	 * place to put this. Feel free to move somewhere else :-)
1414 	 */
1415 	pull_file_id_24(msg+OP_BREAK_MSG_DEV_OFFSET, id);
1416 	e->share_file_id = (unsigned long)IVAL(msg,OP_BREAK_MSG_FILE_ID_OFFSET);
1417 	e->uid = (uint32_t)IVAL(msg,OP_BREAK_MSG_UID_OFFSET);
1418 	e->flags = (uint16_t)SVAL(msg,OP_BREAK_MSG_FLAGS_OFFSET);
1419 	e->name_hash = IVAL(msg,OP_BREAK_MSG_NAME_HASH_OFFSET);
1420 	e->pid.vnn = IVAL(msg,OP_BREAK_MSG_VNN_OFFSET);
1421 }
1422 
1423 /****************************************************************************
1424  Setup oplocks for this process.
1425 ****************************************************************************/
1426 
init_oplocks(struct smbd_server_connection * sconn)1427 bool init_oplocks(struct smbd_server_connection *sconn)
1428 {
1429 	DEBUG(3,("init_oplocks: initializing messages.\n"));
1430 
1431 	messaging_register(sconn->msg_ctx, sconn, MSG_SMB_BREAK_REQUEST,
1432 			   process_oplock_break_message);
1433 	messaging_register(sconn->msg_ctx, sconn, MSG_SMB_KERNEL_BREAK,
1434 			   process_kernel_oplock_break);
1435 	return true;
1436 }
1437 
init_kernel_oplocks(struct smbd_server_connection * sconn)1438 void init_kernel_oplocks(struct smbd_server_connection *sconn)
1439 {
1440 	struct kernel_oplocks *koplocks = sconn->oplocks.kernel_ops;
1441 
1442 	/* only initialize once */
1443 	if (koplocks == NULL) {
1444 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
1445 		koplocks = linux_init_kernel_oplocks(sconn);
1446 #endif
1447 		sconn->oplocks.kernel_ops = koplocks;
1448 	}
1449 }
1450