1 /* 2 * This file and its contents are supplied under the terms of the 3 * Common Development and Distribution License ("CDDL"), version 1.0. 4 * You may only use this file in accordance with the terms of version 5 * 1.0 of the CDDL. 6 * 7 * A full copy of the text of the CDDL should have accompanied this 8 * source. A copy of the CDDL is also available via the Internet at 9 * http://www.illumos.org/license/CDDL. 10 */ 11 12 /* 13 * Copyright 2020 Tintri by DDN, Inc. All rights reserved. 14 * Copyright 2022 RackTop Systems, Inc. 15 */ 16 17 /* 18 * Dispatch function for SMB2_OPLOCK_BREAK 19 */ 20 21 #include <smbsrv/smb2_kproto.h> 22 #include <smbsrv/smb_oplock.h> 23 24 #define BATCH_OR_EXCL (OPLOCK_LEVEL_BATCH | OPLOCK_LEVEL_ONE) 25 26 /* StructSize for the two "break" message formats. */ 27 #define SSZ_OPLOCK 24 28 #define SSZ_LEASE 36 29 30 /* 31 * SMB2 Oplock Break Acknowledgement 32 * [MS-SMB2] 3.3.5.22.1 Processing an Oplock Acknowledgment 33 * Called via smb2_disp_table[] 34 * This is an "Ack" from the client. 35 */ 36 smb_sdrc_t 37 smb2_oplock_break_ack(smb_request_t *sr) 38 { 39 smb_arg_olbrk_t *olbrk = &sr->arg.olbrk; 40 smb_node_t *node; 41 smb_ofile_t *ofile; 42 smb_oplock_grant_t *og; 43 smb2fid_t smb2fid; 44 uint32_t status; 45 uint32_t NewLevel; 46 uint8_t smbOplockLevel; 47 int rc = 0; 48 uint16_t StructSize; 49 50 /* 51 * Decode the SMB2 Oplock Break Ack (24 bytes) or 52 * Lease Break Ack (36 bytes), starting with just 53 * the StructSize, which tells us what this is. 54 */ 55 rc = smb_mbc_decodef(&sr->smb_data, "w", &StructSize); 56 if (rc != 0) 57 return (SDRC_ERROR); 58 59 if (StructSize == SSZ_LEASE) { 60 /* See smb2_lease.c */ 61 return (smb2_lease_break_ack(sr)); 62 } 63 if (StructSize != SSZ_OPLOCK) 64 return (SDRC_ERROR); 65 66 /* 67 * Decode an SMB2 Oplock Break Ack. 68 * [MS-SMB2] 2.2.24.1 69 * Note: Struct size decoded above. 70 */ 71 rc = smb_mbc_decodef( 72 &sr->smb_data, "b5.qq", 73 &smbOplockLevel, /* b */ 74 /* reserved 5. */ 75 &smb2fid.persistent, /* q */ 76 &smb2fid.temporal); /* q */ 77 if (rc != 0) 78 return (SDRC_ERROR); 79 80 /* 81 * Convert SMB oplock level to internal form. 82 */ 83 switch (smbOplockLevel) { 84 case SMB2_OPLOCK_LEVEL_NONE: /* 0x00 */ 85 NewLevel = OPLOCK_LEVEL_NONE; 86 break; 87 case SMB2_OPLOCK_LEVEL_II: /* 0x01 */ 88 NewLevel = OPLOCK_LEVEL_TWO; 89 break; 90 case SMB2_OPLOCK_LEVEL_EXCLUSIVE: /* 0x08 */ 91 NewLevel = OPLOCK_LEVEL_ONE; 92 break; 93 case SMB2_OPLOCK_LEVEL_BATCH: /* 0x09 */ 94 NewLevel = OPLOCK_LEVEL_BATCH; 95 break; 96 97 /* Note: _LEVEL_LEASE is not valid here. */ 98 case SMB2_OPLOCK_LEVEL_LEASE: /* 0xFF */ 99 default: 100 /* 101 * Impossible NewLevel here, will cause 102 * NT_STATUS_INVALID_PARAMETER below. 103 */ 104 NewLevel = OPLOCK_LEVEL_GRANULAR; 105 break; 106 } 107 108 /* for dtrace */ 109 olbrk->NewLevel = NewLevel; 110 111 /* Find the ofile */ 112 status = smb2sr_lookup_fid(sr, &smb2fid); 113 /* Success or NT_STATUS_FILE_CLOSED */ 114 115 DTRACE_SMB2_START(op__OplockBreak, smb_request_t *, sr); 116 117 if (status != 0) { 118 /* lookup fid failed */ 119 goto errout; 120 } 121 122 if (NewLevel == OPLOCK_LEVEL_GRANULAR) { 123 /* Switch above got invalid smbOplockLevel */ 124 status = NT_STATUS_INVALID_PARAMETER; 125 goto errout; 126 } 127 128 /* Success, so have sr->fid_ofile */ 129 ofile = sr->fid_ofile; 130 og = &ofile->f_oplock; 131 node = ofile->f_node; 132 133 smb_llist_enter(&node->n_ofile_list, RW_READER); 134 mutex_enter(&node->n_oplock.ol_mutex); 135 136 if (og->og_breaking == 0) { 137 /* 138 * This is an unsolicited Ack. (There is no 139 * outstanding oplock break in progress now.) 140 * There are WPTS tests that care which error 141 * is returned. See [MS-SMB2] 3.3.5.22.1 142 */ 143 if (NewLevel >= (og->og_state & OPLOCK_LEVEL_TYPE_MASK)) { 144 status = NT_STATUS_INVALID_OPLOCK_PROTOCOL; 145 goto unlock_out; 146 } 147 status = NT_STATUS_INVALID_DEVICE_STATE; 148 goto unlock_out; 149 } 150 151 /* 152 * Process the oplock break ack. 153 * 154 * Clear breaking flags before we ack, 155 * because ack might set those. 156 */ 157 ofile->f_oplock.og_breaking = 0; 158 cv_broadcast(&ofile->f_oplock.og_ack_cv); 159 160 status = smb_oplock_ack_break(sr, ofile, &NewLevel); 161 162 ofile->f_oplock.og_state = NewLevel; 163 if (ofile->dh_persist) 164 smb2_dh_update_oplock(sr, ofile); 165 166 unlock_out: 167 mutex_exit(&node->n_oplock.ol_mutex); 168 smb_llist_exit(&node->n_ofile_list); 169 170 errout: 171 sr->smb2_status = status; 172 DTRACE_SMB2_DONE(op__OplockBreak, smb_request_t *, sr); 173 if (status) { 174 smb2sr_put_error(sr, status); 175 return (SDRC_SUCCESS); 176 } 177 178 /* 179 * Convert internal oplock state back to SMB form. 180 */ 181 switch (NewLevel & OPLOCK_LEVEL_TYPE_MASK) { 182 case OPLOCK_LEVEL_NONE: 183 smbOplockLevel = SMB2_OPLOCK_LEVEL_NONE; 184 break; 185 case OPLOCK_LEVEL_TWO: 186 smbOplockLevel = SMB2_OPLOCK_LEVEL_II; 187 break; 188 case OPLOCK_LEVEL_ONE: 189 smbOplockLevel = SMB2_OPLOCK_LEVEL_EXCLUSIVE; 190 break; 191 case OPLOCK_LEVEL_BATCH: 192 smbOplockLevel = SMB2_OPLOCK_LEVEL_BATCH; 193 break; 194 case OPLOCK_LEVEL_GRANULAR: 195 default: 196 smbOplockLevel = SMB2_OPLOCK_LEVEL_NONE; 197 break; 198 } 199 200 /* 201 * Encode an SMB2 Oplock Break Ack response 202 * [MS-SMB2] 2.2.25.1 203 */ 204 (void) smb_mbc_encodef( 205 &sr->reply, "wb5.qq", 206 SSZ_OPLOCK, /* w */ 207 smbOplockLevel, /* b */ 208 /* reserved 5. */ 209 smb2fid.persistent, /* q */ 210 smb2fid.temporal); /* q */ 211 212 return (SDRC_SUCCESS); 213 } 214 215 /* 216 * Compose an SMB2 Oplock Break Notification packet, including 217 * the SMB2 header and everything, in sr->reply. 218 * The caller will send it and free the request. 219 */ 220 static void 221 smb2_oplock_break_notification(smb_request_t *sr, uint32_t NewLevel) 222 { 223 smb_ofile_t *ofile = sr->fid_ofile; 224 smb2fid_t smb2fid; 225 uint16_t StructSize; 226 uint8_t OplockLevel; 227 228 /* 229 * Convert internal level to SMB2 230 */ 231 switch (NewLevel) { 232 default: 233 ASSERT(0); 234 /* FALLTHROUGH */ 235 case OPLOCK_LEVEL_NONE: 236 OplockLevel = SMB2_OPLOCK_LEVEL_NONE; 237 break; 238 case OPLOCK_LEVEL_TWO: 239 OplockLevel = SMB2_OPLOCK_LEVEL_II; 240 break; 241 } 242 243 /* 244 * SMB2 Header 245 */ 246 sr->smb2_cmd_code = SMB2_OPLOCK_BREAK; 247 sr->smb2_hdr_flags = SMB2_FLAGS_SERVER_TO_REDIR; 248 sr->smb_tid = 0; 249 sr->smb_pid = 0; 250 sr->smb2_ssnid = 0; 251 sr->smb2_messageid = UINT64_MAX; 252 (void) smb2_encode_header(sr, B_FALSE); 253 254 /* 255 * SMB2 Oplock Break, variable part 256 */ 257 StructSize = 24; 258 smb2fid.persistent = ofile->f_persistid; 259 smb2fid.temporal = ofile->f_fid; 260 (void) smb_mbc_encodef( 261 &sr->reply, "wb5.qq", 262 StructSize, /* w */ 263 OplockLevel, /* b */ 264 /* reserved 5. */ 265 smb2fid.persistent, /* q */ 266 smb2fid.temporal); /* q */ 267 } 268 269 /* 270 * Send an oplock break over the wire, or if we can't, 271 * then process the oplock break locally. 272 * 273 * [MS-SMB2] 3.3.4.6 Object Store Indicates an Oplock Break 274 * 275 * Note: When "AckRequired" is set, and we're for any reason 276 * unable to communicate with the client so that they do an 277 * "oplock break ACK", then we absolutely MUST do a local ACK 278 * for this break indication (or close the ofile). 279 * 280 * The file-system level oplock code (smb_cmn_oplock.c) 281 * requires these ACK calls to clear "breaking" flags. 282 * 283 * This is called either from smb_oplock_async_break via a 284 * taskq job scheduled in smb_oplock_ind_break, or from the 285 * smb2sr_append_postwork() mechanism when we're doing a 286 * "break in ack", via smb_oplock_ind_break_in_ack. 287 * 288 * This runs much like other smb_request_t handlers, in the 289 * context of a worker task that calls with no locks held. 290 * 291 * Note that we have sr->fid_ofile here but all the other 292 * normal sr members may be NULL: uid_user, tid_tree. 293 * Also sr->session may or may not be the same session as 294 * the ofile came from (ofile->f_session) depending on 295 * whether this is a "live" open or an orphaned DH, 296 * where ofile->f_session will be NULL. 297 */ 298 void 299 smb2_oplock_send_break(smb_request_t *sr) 300 { 301 smb_ofile_t *ofile = sr->fid_ofile; 302 smb_node_t *node = ofile->f_node; 303 uint32_t NewLevel = sr->arg.olbrk.NewLevel; 304 boolean_t AckReq = sr->arg.olbrk.AckRequired; 305 uint32_t status; 306 int rc; 307 308 /* 309 * Build the break message in sr->reply. 310 * It's free'd in smb_request_free(). 311 * Always SMB2 oplock here (no lease) 312 */ 313 sr->reply.max_bytes = MLEN; 314 smb2_oplock_break_notification(sr, NewLevel); 315 316 /* 317 * Try to send the break message to the client. 318 * If connected, this IF body will be true. 319 */ 320 if (sr->session == ofile->f_session) 321 rc = smb_session_send(sr->session, 0, &sr->reply); 322 else 323 rc = ENOTCONN; 324 325 if (rc != 0) { 326 /* 327 * We were unable to send the oplock break request, 328 * presumably because the connection is gone. 329 * 330 * [MS-SMB2] 3.3.4.6 Object Store Indicates an Oplock Break 331 * If no connection is available, Open.IsResilient is FALSE, 332 * Open.IsDurable is FALSE, and Open.IsPersistent is FALSE, 333 * the server SHOULD close the Open as specified in... 334 */ 335 if (ofile->dh_persist == B_FALSE && 336 ofile->dh_vers != SMB2_RESILIENT && 337 (ofile->dh_vers == SMB2_NOT_DURABLE || 338 (NewLevel & OPLOCK_LEVEL_BATCH) == 0)) { 339 smb_ofile_close(ofile, 0); 340 return; 341 } 342 /* Keep this (durable) open. */ 343 if (!AckReq) 344 return; 345 /* Do local Ack below. */ 346 } else { 347 /* 348 * OK, we were able to send the break message. 349 * If no ack. required, we're done. 350 */ 351 if (!AckReq) 352 return; 353 354 /* 355 * We're expecting an ACK. Wait in this thread 356 * so we can log clients that don't respond. 357 */ 358 status = smb_oplock_wait_ack(sr); 359 if (status == 0) 360 return; 361 362 cmn_err(CE_NOTE, "clnt %s oplock break timeout", 363 sr->session->ip_addr_str); 364 DTRACE_PROBE1(ack_timeout, smb_request_t *, sr); 365 366 /* 367 * Will do local ack below. Note, after timeout, 368 * do a break to none or "no caching" regardless 369 * of what the passed in cache level was. 370 */ 371 NewLevel = OPLOCK_LEVEL_NONE; 372 } 373 374 /* 375 * Do the ack locally. 376 */ 377 smb_llist_enter(&node->n_ofile_list, RW_READER); 378 mutex_enter(&node->n_oplock.ol_mutex); 379 380 ofile->f_oplock.og_breaking = 0; 381 cv_broadcast(&ofile->f_oplock.og_ack_cv); 382 383 status = smb_oplock_ack_break(sr, ofile, &NewLevel); 384 385 ofile->f_oplock.og_state = NewLevel; 386 if (ofile->dh_persist) 387 smb2_dh_update_oplock(sr, ofile); 388 389 mutex_exit(&node->n_oplock.ol_mutex); 390 smb_llist_exit(&node->n_ofile_list); 391 392 #ifdef DEBUG 393 if (status != 0) { 394 cmn_err(CE_NOTE, "clnt %s local oplock ack, status=0x%x", 395 sr->session->ip_addr_str, status); 396 } 397 #endif 398 } 399 400 /* 401 * Client has an open handle and requests an oplock. 402 * Convert SMB2 oplock request info in to internal form, 403 * call common oplock code, convert result to SMB2. 404 * 405 * If necessary, "go async" here. 406 */ 407 void 408 smb2_oplock_acquire(smb_request_t *sr) 409 { 410 smb_arg_open_t *op = &sr->arg.open; 411 smb_ofile_t *ofile = sr->fid_ofile; 412 uint32_t status; 413 414 /* Only disk trees get oplocks. */ 415 ASSERT((sr->tid_tree->t_res_type & STYPE_MASK) == STYPE_DISKTREE); 416 417 /* Only plain files... */ 418 if (!smb_node_is_file(ofile->f_node)) { 419 op->op_oplock_level = SMB2_OPLOCK_LEVEL_NONE; 420 return; 421 } 422 423 if (!smb_tree_has_feature(sr->tid_tree, SMB_TREE_OPLOCKS)) { 424 op->op_oplock_level = SMB2_OPLOCK_LEVEL_NONE; 425 return; 426 } 427 428 /* 429 * SMB2: Convert to internal form. 430 */ 431 switch (op->op_oplock_level) { 432 case SMB2_OPLOCK_LEVEL_BATCH: 433 op->op_oplock_state = OPLOCK_LEVEL_BATCH; 434 break; 435 case SMB2_OPLOCK_LEVEL_EXCLUSIVE: 436 op->op_oplock_state = OPLOCK_LEVEL_ONE; 437 break; 438 case SMB2_OPLOCK_LEVEL_II: 439 op->op_oplock_state = OPLOCK_LEVEL_TWO; 440 break; 441 case SMB2_OPLOCK_LEVEL_LEASE: 442 ASSERT(0); /* Handled elsewhere */ 443 /* FALLTHROUGH */ 444 case SMB2_OPLOCK_LEVEL_NONE: 445 default: 446 op->op_oplock_level = SMB2_OPLOCK_LEVEL_NONE; 447 return; 448 } 449 450 /* 451 * Tree options may force shared oplocks, 452 * in which case we reduce the request. 453 * Can't get here with LEVEL_NONE, so 454 * this can only decrease the level. 455 */ 456 if (smb_tree_has_feature(sr->tid_tree, SMB_TREE_FORCE_L2_OPLOCK)) { 457 op->op_oplock_state = OPLOCK_LEVEL_TWO; 458 } 459 460 /* 461 * Try exclusive first, if requested 462 */ 463 if ((op->op_oplock_state & BATCH_OR_EXCL) != 0) { 464 status = smb_oplock_request(sr, ofile, 465 &op->op_oplock_state); 466 } else { 467 status = NT_STATUS_OPLOCK_NOT_GRANTED; 468 } 469 470 /* 471 * If exclusive failed (or the tree forced shared oplocks) 472 * try for a shared oplock (Level II) 473 */ 474 if (status == NT_STATUS_OPLOCK_NOT_GRANTED) { 475 op->op_oplock_state = OPLOCK_LEVEL_TWO; 476 status = smb_oplock_request(sr, ofile, 477 &op->op_oplock_state); 478 } 479 480 /* 481 * Keep track of what we got (ofile->f_oplock.og_state etc) 482 * so we'll know what we had when sending a break later. 483 * The og_dialect here is the oplock dialect, not the 484 * SMB dialect. No lease here, so SMB 2.0. 485 */ 486 switch (status) { 487 case NT_STATUS_SUCCESS: 488 case NT_STATUS_OPLOCK_BREAK_IN_PROGRESS: 489 ofile->f_oplock.og_dialect = SMB_VERS_2_002; 490 ofile->f_oplock.og_state = op->op_oplock_state; 491 ofile->f_oplock.og_breaking = 0; 492 if (ofile->dh_persist) { 493 smb2_dh_update_oplock(sr, ofile); 494 } 495 break; 496 497 case NT_STATUS_OPLOCK_NOT_GRANTED: 498 op->op_oplock_level = SMB2_OPLOCK_LEVEL_NONE; 499 return; 500 501 default: 502 /* Caller did not check args sufficiently? */ 503 cmn_err(CE_NOTE, "clnt %s oplock req. err 0x%x", 504 sr->session->ip_addr_str, status); 505 DTRACE_PROBE2(other__error, smb_request_t *, sr, 506 uint32_t, status); 507 op->op_oplock_level = SMB2_OPLOCK_LEVEL_NONE; 508 return; 509 } 510 511 /* 512 * Only success cases get here 513 * Convert internal oplock state to SMB2 514 */ 515 if (op->op_oplock_state & OPLOCK_LEVEL_GRANULAR) { 516 ASSERT(0); 517 op->op_oplock_level = SMB2_OPLOCK_LEVEL_NONE; 518 } else if (op->op_oplock_state & OPLOCK_LEVEL_BATCH) { 519 op->op_oplock_level = SMB2_OPLOCK_LEVEL_BATCH; 520 } else if (op->op_oplock_state & OPLOCK_LEVEL_ONE) { 521 op->op_oplock_level = SMB2_OPLOCK_LEVEL_EXCLUSIVE; 522 } else if (op->op_oplock_state & OPLOCK_LEVEL_TWO) { 523 op->op_oplock_level = SMB2_OPLOCK_LEVEL_II; 524 } else { 525 op->op_oplock_level = SMB2_OPLOCK_LEVEL_NONE; 526 } 527 528 /* 529 * An smb_oplock_reqest call may have returned the 530 * status code that says we should wait. 531 */ 532 if (status == NT_STATUS_OPLOCK_BREAK_IN_PROGRESS) { 533 (void) smb2sr_go_async(sr); 534 (void) smb_oplock_wait_break(sr, ofile->f_node, 0); 535 } 536 } 537 538 /* 539 * smb2_oplock_reconnect() Helper for smb2_dh_reconnect 540 * Get oplock state into op->op_oplock_level etc. 541 * 542 * Similar to the end of smb2_lease_acquire (for leases) or 543 * the end of smb2_oplock_acquire (for old-style oplocks). 544 */ 545 void 546 smb2_oplock_reconnect(smb_request_t *sr) 547 { 548 smb_arg_open_t *op = &sr->arg.open; 549 smb_ofile_t *ofile = sr->fid_ofile; 550 551 op->op_oplock_state = ofile->f_oplock.og_state; 552 if (ofile->f_lease != NULL) { 553 smb_lease_t *ls = ofile->f_lease; 554 555 op->op_oplock_level = SMB2_OPLOCK_LEVEL_LEASE; 556 op->lease_state = ls->ls_state & 557 OPLOCK_LEVEL_CACHE_MASK; 558 op->lease_flags = (ls->ls_breaking != 0) ? 559 SMB2_LEASE_FLAG_BREAK_IN_PROGRESS : 0; 560 op->lease_epoch = ls->ls_epoch; 561 op->lease_version = ls->ls_version; 562 } else { 563 switch (op->op_oplock_state & OPLOCK_LEVEL_TYPE_MASK) { 564 default: 565 case OPLOCK_LEVEL_NONE: 566 op->op_oplock_level = SMB2_OPLOCK_LEVEL_NONE; 567 break; 568 case OPLOCK_LEVEL_TWO: 569 op->op_oplock_level = SMB2_OPLOCK_LEVEL_II; 570 break; 571 case OPLOCK_LEVEL_ONE: 572 op->op_oplock_level = SMB2_OPLOCK_LEVEL_EXCLUSIVE; 573 break; 574 case OPLOCK_LEVEL_BATCH: 575 op->op_oplock_level = SMB2_OPLOCK_LEVEL_BATCH; 576 break; 577 } 578 } 579 } 580