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 == B_FALSE) { 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 = B_FALSE; 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 * Note: this can also fail for other reasons 358 * such as client disconnect or server shutdown. 359 */ 360 status = smb_oplock_wait_ack(sr, NewLevel); 361 if (status == 0) 362 return; 363 364 DTRACE_PROBE2(wait__ack__failed, smb_request_t *, sr, 365 uint32_t, status); 366 367 /* 368 * Will do local ack below. Note, after timeout, 369 * do a break to none or "no caching" regardless 370 * of what the passed in cache level was. 371 */ 372 NewLevel = OPLOCK_LEVEL_NONE; 373 } 374 375 /* 376 * Do the ack locally. 377 */ 378 smb_llist_enter(&node->n_ofile_list, RW_READER); 379 mutex_enter(&node->n_oplock.ol_mutex); 380 381 ofile->f_oplock.og_breaking = B_FALSE; 382 cv_broadcast(&ofile->f_oplock.og_ack_cv); 383 384 status = smb_oplock_ack_break(sr, ofile, &NewLevel); 385 386 ofile->f_oplock.og_state = NewLevel; 387 if (ofile->dh_persist) 388 smb2_dh_update_oplock(sr, ofile); 389 390 mutex_exit(&node->n_oplock.ol_mutex); 391 smb_llist_exit(&node->n_ofile_list); 392 393 #ifdef DEBUG 394 if (status != 0) { 395 cmn_err(CE_NOTE, "clnt %s local oplock ack, status=0x%x", 396 sr->session->ip_addr_str, status); 397 } 398 #endif 399 } 400 401 /* 402 * Client has an open handle and requests an oplock. 403 * Convert SMB2 oplock request info in to internal form, 404 * call common oplock code, convert result to SMB2. 405 * 406 * If necessary, "go async" here. 407 */ 408 void 409 smb2_oplock_acquire(smb_request_t *sr) 410 { 411 smb_arg_open_t *op = &sr->arg.open; 412 smb_ofile_t *ofile = sr->fid_ofile; 413 uint32_t status; 414 415 /* Only disk trees get oplocks. */ 416 ASSERT((sr->tid_tree->t_res_type & STYPE_MASK) == STYPE_DISKTREE); 417 418 /* Only plain files... */ 419 if (!smb_node_is_file(ofile->f_node)) { 420 op->op_oplock_level = SMB2_OPLOCK_LEVEL_NONE; 421 return; 422 } 423 424 if (!smb_tree_has_feature(sr->tid_tree, SMB_TREE_OPLOCKS)) { 425 op->op_oplock_level = SMB2_OPLOCK_LEVEL_NONE; 426 return; 427 } 428 429 /* 430 * SMB2: Convert to internal form. 431 */ 432 switch (op->op_oplock_level) { 433 case SMB2_OPLOCK_LEVEL_BATCH: 434 op->op_oplock_state = OPLOCK_LEVEL_BATCH; 435 break; 436 case SMB2_OPLOCK_LEVEL_EXCLUSIVE: 437 op->op_oplock_state = OPLOCK_LEVEL_ONE; 438 break; 439 case SMB2_OPLOCK_LEVEL_II: 440 op->op_oplock_state = OPLOCK_LEVEL_TWO; 441 break; 442 case SMB2_OPLOCK_LEVEL_LEASE: 443 ASSERT(0); /* Handled elsewhere */ 444 /* FALLTHROUGH */ 445 case SMB2_OPLOCK_LEVEL_NONE: 446 default: 447 op->op_oplock_level = SMB2_OPLOCK_LEVEL_NONE; 448 return; 449 } 450 451 /* 452 * Tree options may force shared oplocks, 453 * in which case we reduce the request. 454 * Can't get here with LEVEL_NONE, so 455 * this can only decrease the level. 456 */ 457 if (smb_tree_has_feature(sr->tid_tree, SMB_TREE_FORCE_L2_OPLOCK)) { 458 op->op_oplock_state = OPLOCK_LEVEL_TWO; 459 } 460 461 /* 462 * Try exclusive first, if requested 463 */ 464 if ((op->op_oplock_state & BATCH_OR_EXCL) != 0) { 465 status = smb_oplock_request(sr, ofile, 466 &op->op_oplock_state); 467 } else { 468 status = NT_STATUS_OPLOCK_NOT_GRANTED; 469 } 470 471 /* 472 * If exclusive failed (or the tree forced shared oplocks) 473 * try for a shared oplock (Level II) 474 */ 475 if (status == NT_STATUS_OPLOCK_NOT_GRANTED) { 476 op->op_oplock_state = OPLOCK_LEVEL_TWO; 477 status = smb_oplock_request(sr, ofile, 478 &op->op_oplock_state); 479 } 480 481 /* 482 * Keep track of what we got (ofile->f_oplock.og_state etc) 483 * so we'll know what we had when sending a break later. 484 * The og_dialect here is the oplock dialect, not the 485 * SMB dialect. No lease here, so SMB 2.0. 486 */ 487 switch (status) { 488 case NT_STATUS_SUCCESS: 489 case NT_STATUS_OPLOCK_BREAK_IN_PROGRESS: 490 ofile->f_oplock.og_dialect = SMB_VERS_2_002; 491 ofile->f_oplock.og_state = op->op_oplock_state; 492 ofile->f_oplock.og_breakto = op->op_oplock_state; 493 ofile->f_oplock.og_breaking = B_FALSE; 494 if (ofile->dh_persist) { 495 smb2_dh_update_oplock(sr, ofile); 496 } 497 break; 498 499 case NT_STATUS_OPLOCK_NOT_GRANTED: 500 op->op_oplock_level = SMB2_OPLOCK_LEVEL_NONE; 501 return; 502 503 default: 504 /* Caller did not check args sufficiently? */ 505 cmn_err(CE_NOTE, "clnt %s oplock req. err 0x%x", 506 sr->session->ip_addr_str, status); 507 DTRACE_PROBE2(other__error, smb_request_t *, sr, 508 uint32_t, status); 509 op->op_oplock_level = SMB2_OPLOCK_LEVEL_NONE; 510 return; 511 } 512 513 /* 514 * Only success cases get here 515 * Convert internal oplock state to SMB2 516 */ 517 if (op->op_oplock_state & OPLOCK_LEVEL_GRANULAR) { 518 ASSERT(0); 519 op->op_oplock_level = SMB2_OPLOCK_LEVEL_NONE; 520 } else if (op->op_oplock_state & OPLOCK_LEVEL_BATCH) { 521 op->op_oplock_level = SMB2_OPLOCK_LEVEL_BATCH; 522 } else if (op->op_oplock_state & OPLOCK_LEVEL_ONE) { 523 op->op_oplock_level = SMB2_OPLOCK_LEVEL_EXCLUSIVE; 524 } else if (op->op_oplock_state & OPLOCK_LEVEL_TWO) { 525 op->op_oplock_level = SMB2_OPLOCK_LEVEL_II; 526 } else { 527 op->op_oplock_level = SMB2_OPLOCK_LEVEL_NONE; 528 } 529 530 /* 531 * An smb_oplock_reqest call may have returned the 532 * status code that says we should wait. 533 */ 534 if (status == NT_STATUS_OPLOCK_BREAK_IN_PROGRESS) { 535 (void) smb2sr_go_async(sr); 536 (void) smb_oplock_wait_break(sr, ofile->f_node, 0); 537 } 538 } 539 540 /* 541 * smb2_oplock_reconnect() Helper for smb2_dh_reconnect 542 * Get oplock state into op->op_oplock_level etc. 543 * 544 * Similar to the end of smb2_lease_acquire (for leases) or 545 * the end of smb2_oplock_acquire (for old-style oplocks). 546 */ 547 void 548 smb2_oplock_reconnect(smb_request_t *sr) 549 { 550 smb_arg_open_t *op = &sr->arg.open; 551 smb_ofile_t *ofile = sr->fid_ofile; 552 553 op->op_oplock_state = ofile->f_oplock.og_state; 554 if (ofile->f_lease != NULL) { 555 smb_lease_t *ls = ofile->f_lease; 556 557 op->op_oplock_level = SMB2_OPLOCK_LEVEL_LEASE; 558 op->lease_state = ls->ls_state & 559 OPLOCK_LEVEL_CACHE_MASK; 560 op->lease_flags = (ls->ls_breaking != 0) ? 561 SMB2_LEASE_FLAG_BREAK_IN_PROGRESS : 0; 562 op->lease_epoch = ls->ls_epoch; 563 op->lease_version = ls->ls_version; 564 } else { 565 switch (op->op_oplock_state & OPLOCK_LEVEL_TYPE_MASK) { 566 default: 567 case OPLOCK_LEVEL_NONE: 568 op->op_oplock_level = SMB2_OPLOCK_LEVEL_NONE; 569 break; 570 case OPLOCK_LEVEL_TWO: 571 op->op_oplock_level = SMB2_OPLOCK_LEVEL_II; 572 break; 573 case OPLOCK_LEVEL_ONE: 574 op->op_oplock_level = SMB2_OPLOCK_LEVEL_EXCLUSIVE; 575 break; 576 case OPLOCK_LEVEL_BATCH: 577 op->op_oplock_level = SMB2_OPLOCK_LEVEL_BATCH; 578 break; 579 } 580 } 581 } 582