1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
23 * Copyright 2018 Nexenta Systems, Inc. All rights reserved.
24 */
25 /*
26 * SMB Node State Machine
27 * ----------------------
28 *
29 *
30 * +----------- Creation/Allocation
31 * |
32 * | T0
33 * |
34 * v
35 * +----------------------------+
36 * | SMB_NODE_STATE_AVAILABLE |
37 * +----------------------------+
38 * |
39 * | T1
40 * |
41 * v
42 * +-----------------------------+
43 * | SMB_NODE_STATE_DESTROYING |
44 * +-----------------------------+
45 * |
46 * |
47 * | T2
48 * |
49 * +----------> Deletion/Free
50 *
51 * Transition T0
52 *
53 * This transition occurs in smb_node_lookup(). If the node looked for is
54 * not found in the has table a new node is created. The reference count is
55 * initialized to 1 and the state initialized to SMB_NODE_STATE_AVAILABLE.
56 *
57 * Transition T1
58 *
59 * This transition occurs in smb_node_release(). If the reference count
60 * drops to zero the state is moved to SMB_NODE_STATE_DESTROYING and no more
61 * reference count will be given out for that node.
62 *
63 * Transition T2
64 *
65 * This transition occurs in smb_node_release(). The structure is deleted.
66 *
67 * Comments
68 * --------
69 *
70 * The reason the smb node has 2 states is the following synchronization
71 * rule:
72 *
73 * There's a mutex embedded in the node used to protect its fields and
74 * there's a lock embedded in the bucket of the hash table the node belongs
75 * to. To increment or to decrement the reference count the mutex must be
76 * entered. To insert the node into the bucket and to remove it from the
77 * bucket the lock must be entered in RW_WRITER mode. When both (mutex and
78 * lock) have to be entered, the lock has always to be entered first then
79 * the mutex. This prevents a deadlock between smb_node_lookup() and
80 * smb_node_release() from occurring. However, in smb_node_release() when the
81 * reference count drops to zero and triggers the deletion of the node, the
82 * mutex has to be released before entering the lock of the bucket (to
83 * remove the node). This creates a window during which the node that is
84 * about to be freed could be given out by smb_node_lookup(). To close that
85 * window the node is moved to the state SMB_NODE_STATE_DESTROYING before
86 * releasing the mutex. That way, even if smb_node_lookup() finds it, the
87 * state will indicate that the node should be treated as non existent (of
88 * course the state of the node should be tested/updated under the
89 * protection of the mutex).
90 */
91 #include <smbsrv/smb2_kproto.h>
92 #include <smbsrv/smb_fsops.h>
93 #include <smbsrv/smb_kstat.h>
94 #include <sys/ddi.h>
95 #include <sys/extdirent.h>
96 #include <sys/pathname.h>
97 #include <sys/sdt.h>
98 #include <sys/nbmlock.h>
99 #include <fs/fs_reparse.h>
100
101 uint32_t smb_is_executable(char *);
102 static void smb_node_create_audit_buf(smb_node_t *, int);
103 static void smb_node_destroy_audit_buf(smb_node_t *);
104 static void smb_node_audit(smb_node_t *);
105 static smb_node_t *smb_node_alloc(char *, vnode_t *, smb_llist_t *, uint32_t);
106 static void smb_node_free(smb_node_t *);
107 static int smb_node_constructor(void *, void *, int);
108 static void smb_node_destructor(void *, void *);
109 static smb_llist_t *smb_node_get_hash(fsid_t *, smb_attr_t *, uint32_t *);
110
111 static void smb_node_init_reparse(smb_node_t *, smb_attr_t *);
112 static void smb_node_init_system(smb_node_t *);
113
114 #define VALIDATE_DIR_NODE(_dir_, _node_) \
115 ASSERT((_dir_)->n_magic == SMB_NODE_MAGIC); \
116 ASSERT(((_dir_)->vp->v_xattrdir) || ((_dir_)->vp->v_type == VDIR)); \
117 ASSERT((_dir_)->n_dnode != (_node_));
118
119 /* round sz to DEV_BSIZE block */
120 #define SMB_ALLOCSZ(sz) (((sz) + DEV_BSIZE-1) & ~(DEV_BSIZE-1))
121
122 static kmem_cache_t *smb_node_cache = NULL;
123 static smb_llist_t smb_node_hash_table[SMBND_HASH_MASK+1];
124 static smb_node_t *smb_root_node;
125
126 /*
127 * smb_node_init
128 *
129 * Initialization of the SMB node layer.
130 *
131 * This function is not multi-thread safe. The caller must make sure only one
132 * thread makes the call.
133 */
134 void
135 smb_node_init(void)
136 {
137 smb_attr_t attr;
138 smb_llist_t *node_hdr;
139 smb_node_t *node;
140 uint32_t hashkey;
141 int i;
142
143 if (smb_node_cache != NULL)
144 return;
145
146 smb_node_cache = kmem_cache_create(SMBSRV_KSTAT_NODE_CACHE,
147 sizeof (smb_node_t), 8, smb_node_constructor, smb_node_destructor,
148 NULL, NULL, NULL, 0);
149
150 for (i = 0; i <= SMBND_HASH_MASK; i++) {
151 smb_llist_constructor(&smb_node_hash_table[i],
152 sizeof (smb_node_t), offsetof(smb_node_t, n_lnd));
153 }
154
155 /*
156 * The node cache is shared by all zones, so the smb_root_node
157 * must represent the real (global zone) rootdir.
158 * Note intentional use of kcred here.
159 */
160 attr.sa_mask = SMB_AT_ALL;
161 VERIFY0(smb_vop_getattr(rootdir, NULL, &attr, 0, kcred));
162 node_hdr = smb_node_get_hash(&rootdir->v_vfsp->vfs_fsid, &attr,
163 &hashkey);
164 node = smb_node_alloc("/", rootdir, node_hdr, hashkey);
165 smb_llist_enter(node_hdr, RW_WRITER);
166 smb_llist_insert_head(node_hdr, node);
167 smb_llist_exit(node_hdr);
168 smb_root_node = node; /* smb_node_release in smb_node_fini */
169 }
170
171 /*
172 * smb_node_fini
173 *
174 * This function is not multi-thread safe. The caller must make sure only one
175 * thread makes the call.
176 */
177 void
178 smb_node_fini(void)
179 {
180 int i;
181
182 if (smb_root_node != NULL) {
183 smb_node_release(smb_root_node);
184 smb_root_node = NULL;
185 }
186
187 if (smb_node_cache == NULL)
188 return;
189
190 #ifdef DEBUG
191 for (i = 0; i <= SMBND_HASH_MASK; i++) {
192 smb_llist_t *bucket;
193 smb_node_t *node;
194
195 /*
196 * The following sequence is just intended for sanity check.
197 * This will have to be modified when the code goes into
198 * production.
199 *
200 * The SMB node hash table should be emtpy at this point. If the
201 * hash table is not empty a panic will be triggered.
202 *
203 * The reason why SMB nodes are still remaining in the hash
204 * table is problably due to a mismatch between calls to
205 * smb_node_lookup() and smb_node_release(). You must track that
206 * down.
207 */
208 bucket = &smb_node_hash_table[i];
209 node = smb_llist_head(bucket);
210 while (node != NULL) {
211 cmn_err(CE_NOTE, "leaked node: 0x%p %s",
212 (void *)node, node->od_name);
213 node = smb_llist_next(bucket, node);
214 }
215 }
216 #endif
217
218 for (i = 0; i <= SMBND_HASH_MASK; i++) {
219 smb_llist_destructor(&smb_node_hash_table[i]);
220 }
221 kmem_cache_destroy(smb_node_cache);
222 smb_node_cache = NULL;
223 }
224
225 /*
226 * smb_node_lookup()
227 *
228 * NOTE: This routine should only be called by the file system interface layer,
229 * and not by SMB.
230 *
231 * smb_node_lookup() is called upon successful lookup, mkdir, and create
232 * (for both non-streams and streams). In each of these cases, a held vnode is
233 * passed into this routine. If a new smb_node is created it will take its
234 * own hold on the vnode. The caller's hold therefore still belongs to, and
235 * should be released by, the caller.
236 *
237 * A reference is taken on the smb_node whether found in the hash table
238 * or newly created.
239 *
240 * If an smb_node needs to be created, a reference is also taken on the
241 * dnode (if passed in).
242 *
243 * See smb_node_release() for details on the release of these references.
244 */
245
246 /*ARGSUSED*/
247 smb_node_t *
248 smb_node_lookup(
249 struct smb_request *sr,
250 struct open_param *op,
251 cred_t *cred,
252 vnode_t *vp,
253 char *od_name,
254 smb_node_t *dnode,
255 smb_node_t *unode)
256 {
257 smb_llist_t *node_hdr;
258 smb_node_t *node;
259 smb_attr_t attr;
260 uint32_t hashkey = 0;
261 fsid_t fsid;
262 int error;
263 krw_t lock_mode;
264 vnode_t *unnamed_vp = NULL;
265
266 /*
267 * smb_vop_getattr() is called here instead of smb_fsop_getattr(),
268 * because the node may not yet exist. We also do not want to call
269 * it with the list lock held.
270 */
271
272 if (unode)
273 unnamed_vp = unode->vp;
274
275 /*
276 * This getattr is performed on behalf of the server
277 * that's why kcred is used not the user's cred
278 */
279 attr.sa_mask = SMB_AT_ALL;
280 error = smb_vop_getattr(vp, unnamed_vp, &attr, 0, zone_kcred());
281 if (error)
282 return (NULL);
283
284 if (sr && sr->tid_tree) {
285 /*
286 * The fsid for a file is that of the tree, even
287 * if the file resides in a different mountpoint
288 * under the share.
289 */
290 fsid = SMB_TREE_FSID(sr->tid_tree);
291 } else {
292 /*
293 * This should be getting executed only for the
294 * tree root smb_node.
295 */
296 fsid = vp->v_vfsp->vfs_fsid;
297 }
298
299 node_hdr = smb_node_get_hash(&fsid, &attr, &hashkey);
300 lock_mode = RW_READER;
301
302 smb_llist_enter(node_hdr, lock_mode);
303 for (;;) {
304 node = list_head(&node_hdr->ll_list);
305 while (node) {
306 ASSERT(node->n_magic == SMB_NODE_MAGIC);
307 ASSERT(node->n_hash_bucket == node_hdr);
308 if ((node->n_hashkey == hashkey) && (node->vp == vp)) {
309 mutex_enter(&node->n_mutex);
310 DTRACE_PROBE1(smb_node_lookup_hit,
311 smb_node_t *, node);
312 switch (node->n_state) {
313 case SMB_NODE_STATE_AVAILABLE:
314 /* The node was found. */
315 node->n_refcnt++;
316 if ((node->n_dnode == NULL) &&
317 (dnode != NULL) &&
318 (node != dnode) &&
319 (strcmp(od_name, "..") != 0) &&
320 (strcmp(od_name, ".") != 0)) {
321 VALIDATE_DIR_NODE(dnode, node);
322 node->n_dnode = dnode;
323 smb_node_ref(dnode);
324 }
325
326 smb_node_audit(node);
327 mutex_exit(&node->n_mutex);
328 smb_llist_exit(node_hdr);
329 return (node);
330
331 case SMB_NODE_STATE_DESTROYING:
332 /*
333 * Although the node exists it is about
334 * to be destroyed. We act as it hasn't
335 * been found.
336 */
337 mutex_exit(&node->n_mutex);
338 break;
339 default:
340 /*
341 * Although the node exists it is in an
342 * unknown state. We act as it hasn't
343 * been found.
344 */
345 ASSERT(0);
346 mutex_exit(&node->n_mutex);
347 break;
348 }
349 }
350 node = smb_llist_next(node_hdr, node);
351 }
352 if ((lock_mode == RW_READER) && smb_llist_upgrade(node_hdr)) {
353 lock_mode = RW_WRITER;
354 continue;
355 }
356 break;
357 }
358 node = smb_node_alloc(od_name, vp, node_hdr, hashkey);
359 smb_node_init_reparse(node, &attr);
360
361 if (op)
362 node->flags |= smb_is_executable(op->fqi.fq_last_comp);
363
364 if (dnode) {
365 smb_node_ref(dnode);
366 node->n_dnode = dnode;
367 ASSERT(dnode->n_dnode != node);
368 ASSERT((dnode->vp->v_xattrdir) ||
369 (dnode->vp->v_type == VDIR));
370 }
371
372 if (unode) {
373 smb_node_ref(unode);
374 node->n_unode = unode;
375 }
376
377 smb_node_init_system(node);
378
379 DTRACE_PROBE1(smb_node_lookup_miss, smb_node_t *, node);
380 smb_node_audit(node);
381 smb_llist_insert_head(node_hdr, node);
382 smb_llist_exit(node_hdr);
383 return (node);
384 }
385
386 /*
387 * smb_stream_node_lookup()
388 *
389 * Note: stream_name (the name that will be stored in the "od_name" field
390 * of a stream's smb_node) is the same as the on-disk name for the stream
391 * except that it does not have SMB_STREAM_PREFIX prepended.
392 */
393
394 smb_node_t *
395 smb_stream_node_lookup(smb_request_t *sr, cred_t *cr, smb_node_t *fnode,
396 vnode_t *xattrdirvp, vnode_t *vp, char *stream_name)
397 {
398 smb_node_t *xattrdir_node;
399 smb_node_t *snode;
400
401 xattrdir_node = smb_node_lookup(sr, NULL, cr, xattrdirvp, XATTR_DIR,
402 fnode, NULL);
403
404 if (xattrdir_node == NULL)
405 return (NULL);
406
407 snode = smb_node_lookup(sr, NULL, cr, vp, stream_name, xattrdir_node,
408 fnode);
409
410 (void) smb_node_release(xattrdir_node);
411 return (snode);
412 }
413
414
415 /*
416 * This function should be called whenever a reference is needed on an
417 * smb_node pointer. The copy of an smb_node pointer from one non-local
418 * data structure to another requires a reference to be taken on the smb_node
419 * (unless the usage is localized). Each data structure deallocation routine
420 * will call smb_node_release() on its smb_node pointers.
421 *
422 * In general, an smb_node pointer residing in a structure should never be
423 * stale. A node pointer may be NULL, however, and care should be taken
424 * prior to calling smb_node_ref(), which ASSERTs that the pointer is valid.
425 * Care also needs to be taken with respect to racing deallocations of a
426 * structure.
427 */
428 void
429 smb_node_ref(smb_node_t *node)
430 {
431 SMB_NODE_VALID(node);
432
433 mutex_enter(&node->n_mutex);
434 switch (node->n_state) {
435 case SMB_NODE_STATE_AVAILABLE:
436 node->n_refcnt++;
437 ASSERT(node->n_refcnt);
438 DTRACE_PROBE1(smb_node_ref_exit, smb_node_t *, node);
439 smb_node_audit(node);
440 break;
441 default:
442 SMB_PANIC();
443 }
444 mutex_exit(&node->n_mutex);
445 }
446
447 /*
448 * smb_node_lookup() takes a hold on an smb_node, whether found in the
449 * hash table or newly created. This hold is expected to be released
450 * in the following manner.
451 *
452 * smb_node_lookup() takes an address of an smb_node pointer. This should
453 * be getting passed down via a lookup (whether path name or component), mkdir,
454 * create. If the original smb_node pointer resides in a data structure, then
455 * the deallocation routine for the data structure is responsible for calling
456 * smb_node_release() on the smb_node pointer. Alternatively,
457 * smb_node_release() can be called as soon as the smb_node pointer is no longer
458 * needed. In this case, callers are responsible for setting an embedded
459 * pointer to NULL if it is known that the last reference is being released.
460 *
461 * If the passed-in address of the smb_node pointer belongs to a local variable,
462 * then the caller with the local variable should call smb_node_release()
463 * directly.
464 *
465 * smb_node_release() itself will call smb_node_release() on a node's n_dnode,
466 * as smb_node_lookup() takes a hold on dnode.
467 */
468 void
469 smb_node_release(smb_node_t *node)
470 {
471 SMB_NODE_VALID(node);
472
473 mutex_enter(&node->n_mutex);
474 ASSERT(node->n_refcnt);
475 DTRACE_PROBE1(smb_node_release, smb_node_t *, node);
476 if (--node->n_refcnt == 0) {
477 switch (node->n_state) {
478
479 case SMB_NODE_STATE_AVAILABLE:
480 node->n_state = SMB_NODE_STATE_DESTROYING;
481 mutex_exit(&node->n_mutex);
482
483 smb_llist_enter(node->n_hash_bucket, RW_WRITER);
484 smb_llist_remove(node->n_hash_bucket, node);
485 smb_llist_exit(node->n_hash_bucket);
486
487 /*
488 * Check if the file was deleted
489 */
490 if (node->flags & NODE_FLAGS_DELETE_ON_CLOSE) {
491 smb_node_delete_on_close(node);
492 }
493
494 if (node->n_dnode) {
495 ASSERT(node->n_dnode->n_magic ==
496 SMB_NODE_MAGIC);
497 smb_node_release(node->n_dnode);
498 }
499
500 if (node->n_unode) {
501 ASSERT(node->n_unode->n_magic ==
502 SMB_NODE_MAGIC);
503 smb_node_release(node->n_unode);
504 }
505
506 smb_node_free(node);
507 return;
508
509 default:
510 SMB_PANIC();
511 }
512 }
513 smb_node_audit(node);
514 mutex_exit(&node->n_mutex);
515 }
516
517 void
518 smb_node_delete_on_close(smb_node_t *node)
519 {
520 smb_node_t *d_snode;
521 int rc = 0;
522 uint32_t flags = 0;
523
524 d_snode = node->n_dnode;
525
526 ASSERT((node->flags & NODE_FLAGS_DELETE_ON_CLOSE) != 0);
527
528 node->flags &= ~NODE_FLAGS_DELETE_ON_CLOSE;
529 node->flags |= NODE_FLAGS_DELETE_COMMITTED;
530 flags = node->n_delete_on_close_flags;
531 ASSERT(node->od_name != NULL);
532
533 if (smb_node_is_dir(node))
534 rc = smb_fsop_rmdir(0, node->delete_on_close_cred,
535 d_snode, node->od_name, flags);
536 else
537 rc = smb_fsop_remove(0, node->delete_on_close_cred,
538 d_snode, node->od_name, flags);
539 crfree(node->delete_on_close_cred);
540 node->delete_on_close_cred = NULL;
541
542 if (rc != 0)
543 cmn_err(CE_WARN, "File %s could not be removed, rc=%d\n",
544 node->od_name, rc);
545 DTRACE_PROBE2(smb_node_delete_on_close, int, rc, smb_node_t *, node);
546 }
547
548 /*
549 * smb_node_rename()
550 *
551 */
552 void
553 smb_node_rename(
554 smb_node_t *from_dnode,
555 smb_node_t *ret_node,
556 smb_node_t *to_dnode,
557 char *to_name)
558 {
559 SMB_NODE_VALID(from_dnode);
560 SMB_NODE_VALID(to_dnode);
561 SMB_NODE_VALID(ret_node);
562
563 smb_node_ref(to_dnode);
564 mutex_enter(&ret_node->n_mutex);
565 switch (ret_node->n_state) {
566 case SMB_NODE_STATE_AVAILABLE:
567 ret_node->n_dnode = to_dnode;
568 mutex_exit(&ret_node->n_mutex);
569 ASSERT(to_dnode->n_dnode != ret_node);
570 ASSERT((to_dnode->vp->v_xattrdir) ||
571 (to_dnode->vp->v_type == VDIR));
572 smb_node_release(from_dnode);
573 (void) strcpy(ret_node->od_name, to_name);
574 /*
575 * XXX Need to update attributes?
576 */
577 break;
578 default:
579 SMB_PANIC();
580 }
581 }
582
583 /*
584 * Find/create an SMB node for the root of this zone and store it
585 * in *svrootp. Also create nodes leading to this directory.
586 */
587 int
588 smb_node_root_init(smb_server_t *sv, smb_node_t **svrootp)
589 {
590 zone_t *zone = curzone;
591 int error;
592
593 ASSERT(zone->zone_id == sv->sv_zid);
594 if (smb_root_node == NULL)
595 return (ENOENT);
596
597 /*
598 * We're getting smb nodes below the zone root here,
599 * so need to use kcred, not zone_kcred().
600 */
601 error = smb_pathname(NULL, zone->zone_rootpath, 0,
602 smb_root_node, smb_root_node, NULL, svrootp, kcred, NULL);
603
604 return (error);
605 }
606
607 /*
608 * Helper function for smb_node_set_delete_on_close(). Assumes node is a dir.
609 * Return 0 if this is an empty dir. Otherwise return a NT_STATUS code.
610 * Unfortunately, to find out if a directory is empty, we have to read it
611 * and check for anything other than "." or ".." in the readdir buf.
612 */
613 static uint32_t
614 smb_rmdir_possible(smb_node_t *n)
615 {
616 ASSERT(n->vp->v_type == VDIR);
617 char *buf;
618 char *bufptr;
619 struct dirent64 *dp;
620 uint32_t status = NT_STATUS_SUCCESS;
621 int bsize = SMB_ODIR_BUFSIZE;
622 int eof = 0;
623
624 buf = kmem_alloc(SMB_ODIR_BUFSIZE, KM_SLEEP);
625
626 /* Flags zero: no edirent, no ABE wanted here */
627 if (smb_vop_readdir(n->vp, 0, buf, &bsize, &eof, 0, zone_kcred())) {
628 status = NT_STATUS_INTERNAL_ERROR;
629 goto out;
630 }
631
632 bufptr = buf;
633 while (bsize > 0) {
634 /* LINTED pointer alignment */
635 dp = (struct dirent64 *)bufptr;
636
637 bufptr += dp->d_reclen;
638 bsize -= dp->d_reclen;
639 if (bsize < 0) {
640 /* partial record */
641 status = NT_STATUS_DIRECTORY_NOT_EMPTY;
642 break;
643 }
644
645 if (strcmp(dp->d_name, ".") != 0 &&
646 strcmp(dp->d_name, "..") != 0) {
647 status = NT_STATUS_DIRECTORY_NOT_EMPTY;
648 break;
649 }
650 }
651
652 out:
653 kmem_free(buf, SMB_ODIR_BUFSIZE);
654 return (status);
655 }
656
657 /*
658 * When DeleteOnClose is set on an smb_node, the common open code will
659 * reject subsequent open requests for the file. Observation of Windows
660 * 2000 indicates that subsequent opens should be allowed (assuming
661 * there would be no sharing violation) until the file is closed using
662 * the fid on which the DeleteOnClose was requested.
663 *
664 * If there are multiple opens with delete-on-close create options,
665 * whichever the first file handle is closed will trigger the node to be
666 * marked as delete-on-close. The credentials of that ofile will be used
667 * as the delete-on-close credentials of the node.
668 *
669 * Note that "read-only" tests have already happened before this call.
670 */
671 uint32_t
672 smb_node_set_delete_on_close(smb_node_t *node, cred_t *cr, uint32_t flags)
673 {
674 uint32_t status;
675
676 /*
677 * If the directory is not empty we should fail setting del-on-close
678 * with STATUS_DIRECTORY_NOT_EMPTY. see MS's
679 * "File System Behavior Overview" doc section 4.3.2
680 */
681 if (smb_node_is_dir(node)) {
682 status = smb_rmdir_possible(node);
683 if (status != 0) {
684 return (status);
685 }
686 }
687
688 mutex_enter(&node->n_mutex);
689 if (node->flags & NODE_FLAGS_DELETE_ON_CLOSE) {
690 /* It was already marked. We're done. */
691 mutex_exit(&node->n_mutex);
692 return (NT_STATUS_SUCCESS);
693 }
694
695 crhold(cr);
696 node->delete_on_close_cred = cr;
697 node->n_delete_on_close_flags = flags;
698 node->flags |= NODE_FLAGS_DELETE_ON_CLOSE;
699 mutex_exit(&node->n_mutex);
700
701 /*
702 * Tell any change notify calls to close their handles
703 * and get out of the way. FILE_ACTION_DELETE_PENDING
704 * is a special, internal-only action for this purpose.
705 */
706 smb_node_notify_change(node, FILE_ACTION_DELETE_PENDING, NULL);
707
708 return (NT_STATUS_SUCCESS);
709 }
710
711 void
712 smb_node_reset_delete_on_close(smb_node_t *node)
713 {
714 mutex_enter(&node->n_mutex);
715 if (node->flags & NODE_FLAGS_DELETE_ON_CLOSE) {
716 node->flags &= ~NODE_FLAGS_DELETE_ON_CLOSE;
717 crfree(node->delete_on_close_cred);
718 node->delete_on_close_cred = NULL;
719 node->n_delete_on_close_flags = 0;
720 }
721 mutex_exit(&node->n_mutex);
722 }
723
724 /*
725 * smb_node_open_check
726 *
727 * check file sharing rules for current open request
728 * against all existing opens for a file.
729 *
730 * Returns NT_STATUS_SHARING_VIOLATION if there is any
731 * sharing conflict, otherwise returns NT_STATUS_SUCCESS.
732 */
733 uint32_t
734 smb_node_open_check(smb_node_t *node, uint32_t desired_access,
735 uint32_t share_access)
736 {
737 smb_ofile_t *of;
738 uint32_t status;
739
740 SMB_NODE_VALID(node);
741
742 smb_llist_enter(&node->n_ofile_list, RW_READER);
743 of = smb_llist_head(&node->n_ofile_list);
744 while (of) {
745 status = smb_ofile_open_check(of, desired_access, share_access);
746
747 switch (status) {
748 case NT_STATUS_INVALID_HANDLE:
749 case NT_STATUS_SUCCESS:
750 of = smb_llist_next(&node->n_ofile_list, of);
751 break;
752 default:
753 ASSERT(status == NT_STATUS_SHARING_VIOLATION);
754 DTRACE_PROBE3(conflict3,
755 smb_ofile_t, of,
756 uint32_t, desired_access,
757 uint32_t, share_access);
758 smb_llist_exit(&node->n_ofile_list);
759 return (status);
760 }
761 }
762
763 smb_llist_exit(&node->n_ofile_list);
764 return (NT_STATUS_SUCCESS);
765 }
766
767 uint32_t
768 smb_node_rename_check(smb_node_t *node)
769 {
770 smb_ofile_t *of;
771 uint32_t status;
772
773 SMB_NODE_VALID(node);
774
775 /*
776 * Intra-CIFS check
777 */
778 smb_llist_enter(&node->n_ofile_list, RW_READER);
779 of = smb_llist_head(&node->n_ofile_list);
780 while (of) {
781 status = smb_ofile_rename_check(of);
782
783 switch (status) {
784 case NT_STATUS_INVALID_HANDLE:
785 case NT_STATUS_SUCCESS:
786 of = smb_llist_next(&node->n_ofile_list, of);
787 break;
788 default:
789 ASSERT(status == NT_STATUS_SHARING_VIOLATION);
790 DTRACE_PROBE1(conflict1, smb_ofile_t, of);
791 smb_llist_exit(&node->n_ofile_list);
792 return (status);
793 }
794 }
795 smb_llist_exit(&node->n_ofile_list);
796 return (NT_STATUS_SUCCESS);
797 }
798
799 uint32_t
800 smb_node_delete_check(smb_node_t *node)
801 {
802 smb_ofile_t *of;
803 uint32_t status;
804
805 SMB_NODE_VALID(node);
806
807 if (smb_node_is_dir(node))
808 return (NT_STATUS_SUCCESS);
809
810 if (smb_node_is_reparse(node))
811 return (NT_STATUS_ACCESS_DENIED);
812
813 /*
814 * intra-CIFS check
815 */
816 smb_llist_enter(&node->n_ofile_list, RW_READER);
817 of = smb_llist_head(&node->n_ofile_list);
818 while (of) {
819 status = smb_ofile_delete_check(of);
820
821 switch (status) {
822 case NT_STATUS_INVALID_HANDLE:
823 case NT_STATUS_SUCCESS:
824 of = smb_llist_next(&node->n_ofile_list, of);
825 break;
826 default:
827 ASSERT(status == NT_STATUS_SHARING_VIOLATION);
828 DTRACE_PROBE1(conflict1, smb_ofile_t, of);
829 smb_llist_exit(&node->n_ofile_list);
830 return (status);
831 }
832 }
833 smb_llist_exit(&node->n_ofile_list);
834 return (NT_STATUS_SUCCESS);
835 }
836
837 /*
838 * smb_node_share_check
839 *
840 * Returns: TRUE - ofiles have non-zero share access
841 * B_FALSE - ofile with share access NONE.
842 */
843 boolean_t
844 smb_node_share_check(smb_node_t *node)
845 {
846 smb_ofile_t *of;
847 boolean_t status = B_TRUE;
848
849 SMB_NODE_VALID(node);
850
851 smb_llist_enter(&node->n_ofile_list, RW_READER);
852 of = smb_llist_head(&node->n_ofile_list);
853 if (of)
854 status = smb_ofile_share_check(of);
855 smb_llist_exit(&node->n_ofile_list);
856
857 return (status);
858 }
859
860 /*
861 * SMB Change Notification
862 */
863
864 void
865 smb_node_fcn_subscribe(smb_node_t *node)
866 {
867
868 mutex_enter(&node->n_mutex);
869 if (node->n_fcn_count == 0)
870 (void) smb_fem_fcn_install(node);
871 node->n_fcn_count++;
872 mutex_exit(&node->n_mutex);
873 }
874
875 void
876 smb_node_fcn_unsubscribe(smb_node_t *node)
877 {
878
879 mutex_enter(&node->n_mutex);
880 node->n_fcn_count--;
881 if (node->n_fcn_count == 0)
882 smb_fem_fcn_uninstall(node);
883 mutex_exit(&node->n_mutex);
884 }
885
886 void
887 smb_node_notify_change(smb_node_t *node, uint_t action, const char *name)
888 {
889 smb_ofile_t *of;
890
891 SMB_NODE_VALID(node);
892
893 smb_llist_enter(&node->n_ofile_list, RW_READER);
894 of = smb_llist_head(&node->n_ofile_list);
895 while (of) {
896 /*
897 * We'd rather deliver events only to ofiles that have
898 * subscribed. There's no explicit synchronization with
899 * where this flag is set, but other actions cause this
900 * value to reach visibility soon enough for events to
901 * start arriving by the time we need them to start.
902 * Once nc_subscribed is set, it stays set for the
903 * life of the ofile.
904 */
905 if (of->f_notify.nc_subscribed)
906 smb_notify_ofile(of, action, name);
907 of = smb_llist_next(&node->n_ofile_list, of);
908 }
909 smb_llist_exit(&node->n_ofile_list);
910
911 /*
912 * After changes that add or remove a name,
913 * we know the directory attributes changed,
914 * and we can tell the immediate parent.
915 */
916 switch (action) {
917 case FILE_ACTION_ADDED:
918 case FILE_ACTION_REMOVED:
919 case FILE_ACTION_RENAMED_NEW_NAME:
920 /*
921 * Note: FILE_ACTION_RENAMED_OLD_NAME is intentionally
922 * omitted, because it's always followed by another
923 * event with FILE_ACTION_RENAMED_NEW_NAME posted to
924 * the same directory, and we only need/want one.
925 */
926 if (node->n_dnode != NULL) {
927 smb_node_notify_change(node->n_dnode,
928 FILE_ACTION_MODIFIED, node->od_name);
929 }
930 break;
931 }
932
933 /*
934 * If we wanted to support recursive notify events
935 * (where a notify call on some directory receives
936 * events from all objects below that directory),
937 * we might deliver _SUBDIR_CHANGED to all our
938 * parents, grandparents etc, here. However, we
939 * don't currently subscribe to changes on all the
940 * child (and grandchild) objects that would be
941 * needed to make that work. It's prohibitively
942 * expensive to do that, and support for recursive
943 * notify is optional anyway, so don't bother.
944 */
945 }
946
947 /*
948 * smb_node_start_crit()
949 *
950 * Enter critical region for share reservations.
951 * See comments above smb_fsop_shrlock().
952 */
953 void
954 smb_node_start_crit(smb_node_t *node, krw_t mode)
955 {
956 rw_enter(&node->n_lock, mode);
957 nbl_start_crit(node->vp, mode);
958 }
959
960 /*
961 * smb_node_end_crit()
962 *
963 * Exit critical region for share reservations.
964 */
965 void
966 smb_node_end_crit(smb_node_t *node)
967 {
968 nbl_end_crit(node->vp);
969 rw_exit(&node->n_lock);
970 }
971
972 int
973 smb_node_in_crit(smb_node_t *node)
974 {
975 return (nbl_in_crit(node->vp) && RW_LOCK_HELD(&node->n_lock));
976 }
977
978 void
979 smb_node_rdlock(smb_node_t *node)
980 {
981 rw_enter(&node->n_lock, RW_READER);
982 }
983
984 void
985 smb_node_wrlock(smb_node_t *node)
986 {
987 rw_enter(&node->n_lock, RW_WRITER);
988 }
989
990 void
991 smb_node_unlock(smb_node_t *node)
992 {
993 rw_exit(&node->n_lock);
994 }
995
996 void
997 smb_node_add_ofile(smb_node_t *node, smb_ofile_t *of)
998 {
999 SMB_NODE_VALID(node);
1000
1001 smb_llist_enter(&node->n_ofile_list, RW_WRITER);
1002 smb_llist_insert_tail(&node->n_ofile_list, of);
1003 smb_llist_exit(&node->n_ofile_list);
1004 }
1005
1006 void
1007 smb_node_rem_ofile(smb_node_t *node, smb_ofile_t *of)
1008 {
1009 SMB_NODE_VALID(node);
1010
1011 smb_llist_enter(&node->n_ofile_list, RW_WRITER);
1012 smb_llist_remove(&node->n_ofile_list, of);
1013 smb_llist_exit(&node->n_ofile_list);
1014 }
1015
1016 /*
1017 * smb_node_inc_open_ofiles
1018 */
1019 void
1020 smb_node_inc_open_ofiles(smb_node_t *node)
1021 {
1022 SMB_NODE_VALID(node);
1023 atomic_inc_32(&node->n_open_count);
1024 }
1025
1026 /*
1027 * smb_node_dec_open_ofiles
1028 * returns new value
1029 */
1030 uint32_t
1031 smb_node_dec_open_ofiles(smb_node_t *node)
1032 {
1033 SMB_NODE_VALID(node);
1034 return (atomic_dec_32_nv(&node->n_open_count));
1035 }
1036
1037 /*
1038 * smb_node_inc_opening_count
1039 */
1040 void
1041 smb_node_inc_opening_count(smb_node_t *node)
1042 {
1043 SMB_NODE_VALID(node);
1044 atomic_inc_32(&node->n_opening_count);
1045 }
1046
1047 /*
1048 * smb_node_dec_opening_count
1049 */
1050 void
1051 smb_node_dec_opening_count(smb_node_t *node)
1052 {
1053 SMB_NODE_VALID(node);
1054 atomic_dec_32(&node->n_opening_count);
1055 }
1056
1057 /*
1058 * smb_node_getmntpath
1059 */
1060 int
1061 smb_node_getmntpath(smb_node_t *node, char *buf, uint32_t buflen)
1062 {
1063 vnode_t *vp, *root_vp;
1064 vfs_t *vfsp;
1065 int err;
1066
1067 ASSERT(node);
1068 ASSERT(node->vp);
1069 ASSERT(node->vp->v_vfsp);
1070
1071 vp = node->vp;
1072 vfsp = vp->v_vfsp;
1073
1074 if (VFS_ROOT(vfsp, &root_vp))
1075 return (ENOENT);
1076
1077 VN_HOLD(vp);
1078
1079 /* NULL is passed in as we want to start at "/" */
1080 err = vnodetopath(NULL, root_vp, buf, buflen, zone_kcred());
1081
1082 VN_RELE(vp);
1083 VN_RELE(root_vp);
1084 return (err);
1085 }
1086
1087 /*
1088 * smb_node_getshrpath
1089 *
1090 * Determine the absolute pathname of 'node' within the share (tree).
1091 * For example if the node represents file "test1.txt" in directory
1092 * "dir1" the pathname would be: \dir1\test1.txt
1093 */
1094 int
1095 smb_node_getshrpath(smb_node_t *node, smb_tree_t *tree,
1096 char *buf, uint32_t buflen)
1097 {
1098 int rc;
1099
1100 ASSERT(node);
1101 ASSERT(tree);
1102 ASSERT(tree->t_snode);
1103
1104 rc = smb_node_getpath(node, tree->t_snode->vp, buf, buflen);
1105 (void) strsubst(buf, '/', '\\');
1106 return (rc);
1107 }
1108
1109 /*
1110 * smb_node_getpath
1111 *
1112 * Determine the absolute pathname of 'node' from 'rootvp'.
1113 *
1114 * Using vnodetopath is only reliable for directory nodes (due to
1115 * its reliance on the DNLC for non-directory nodes). Thus, if node
1116 * represents a file, construct the pathname for the parent dnode
1117 * and append filename.
1118 * If node represents a named stream, construct the pathname for the
1119 * associated unnamed stream and append the stream name.
1120 *
1121 * The pathname returned in buf will be '/' separated.
1122 */
1123 int
1124 smb_node_getpath(smb_node_t *node, vnode_t *rootvp, char *buf, uint32_t buflen)
1125 {
1126 int rc;
1127 vnode_t *vp;
1128 smb_node_t *unode, *dnode;
1129 cred_t *kcr = zone_kcred();
1130
1131 unode = (SMB_IS_STREAM(node)) ? node->n_unode : node;
1132 dnode = (smb_node_is_dir(unode)) ? unode : unode->n_dnode;
1133
1134 /* find path to directory node */
1135 vp = dnode->vp;
1136 VN_HOLD(vp);
1137 if (rootvp) {
1138 VN_HOLD(rootvp);
1139 rc = vnodetopath(rootvp, vp, buf, buflen, kcr);
1140 VN_RELE(rootvp);
1141 } else {
1142 rc = vnodetopath(NULL, vp, buf, buflen, kcr);
1143 }
1144 VN_RELE(vp);
1145
1146 if (rc != 0)
1147 return (rc);
1148
1149 /* append filename if necessary */
1150 if (!smb_node_is_dir(unode)) {
1151 if (buf[strlen(buf) - 1] != '/')
1152 (void) strlcat(buf, "/", buflen);
1153 (void) strlcat(buf, unode->od_name, buflen);
1154 }
1155
1156 /* append named stream name if necessary */
1157 if (SMB_IS_STREAM(node))
1158 (void) strlcat(buf, node->od_name, buflen);
1159
1160 return (rc);
1161 }
1162
1163 /*
1164 * smb_node_getpath_nofail
1165 *
1166 * Same as smb_node_getpath, but try to reconstruct on failure,
1167 * and truncate from the beginning if we can't.
1168 */
1169 void
1170 smb_node_getpath_nofail(smb_node_t *node, vnode_t *rootvp, char *buf,
1171 uint32_t buflen)
1172 {
1173 int rc, len, addlen;
1174 vnode_t *vp;
1175 smb_node_t *unode, *dnode;
1176 cred_t *kcr = zone_kcred();
1177 boolean_t is_dir, is_stream;
1178
1179 is_stream = (SMB_IS_STREAM(node) != NULL);
1180 unode = (is_stream) ? node->n_unode : node;
1181 is_dir = smb_node_is_dir(unode);
1182 dnode = (is_dir) ? unode : unode->n_dnode;
1183
1184 /* find path to directory node */
1185 vp = dnode->vp;
1186 VN_HOLD(vp);
1187 if (rootvp) {
1188 VN_HOLD(rootvp);
1189 rc = vnodetopath(rootvp, vp, buf, buflen, kcr);
1190 VN_RELE(rootvp);
1191 } else {
1192 rc = vnodetopath(NULL, vp, buf, buflen, kcr);
1193 }
1194 VN_RELE(vp);
1195
1196 /* On failure, reconstruct the path from the node_t's */
1197 if (rc != 0) {
1198 smb_node_t *nodep = unode;
1199 char *p = buf + buflen;
1200
1201 /* append named stream name if necessary */
1202 if (is_stream) {
1203 len = strlen(node->od_name) + 1;
1204 ASSERT3U(buflen, >=, len);
1205 p -= len;
1206 (void) strcpy(p, node->od_name);
1207 }
1208
1209 len = strlen(nodep->od_name) + 1;
1210 p -= len;
1211 while (nodep->n_dnode != NULL && nodep->vp != rootvp &&
1212 p >= buf) {
1213 (void) strcpy(p, nodep->od_name);
1214 p[len - 1] = '/';
1215 nodep = nodep->n_dnode;
1216 len = strlen(nodep->od_name) + 1;
1217 p -= len;
1218 }
1219 if (nodep->n_dnode != NULL && nodep->vp != rootvp) {
1220 /* something went horribly wrong... */
1221 #ifdef DEBUG
1222 cmn_err(CE_WARN,
1223 "smb_node_getpath_nofail: buffer too small: "
1224 "size %d", buflen);
1225 #else
1226 cmn_err(CE_WARN,
1227 "smb_node_getpath_nofail: couldn't get full path");
1228 #endif
1229 p = buf;
1230 *p = '*';
1231 } else {
1232 p += len - 1;
1233 if (p >= buf)
1234 *p = '/';
1235 }
1236
1237 buf[buflen - 1] = '\0';
1238 (void) memmove(buf, p, strlen(p) + 1);
1239 cmn_err(CE_NOTE,
1240 "smb_node_getpath_nofail: vnodetopath failed, rc=%d", rc);
1241 return;
1242 }
1243
1244 len = strlen(buf) + 1;
1245
1246 /* append filename if necessary */
1247 if (!is_dir) {
1248 if (buf[len - 2] != '/' && strlcat(buf, "/", buflen) >= buflen)
1249 goto trunc;
1250 if (strlcat(buf, unode->od_name, buflen) >= buflen)
1251 goto trunc;
1252 }
1253
1254 /* append named stream name if necessary */
1255 if (!is_stream || strlcat(buf, node->od_name, buflen) < buflen)
1256 return;
1257
1258 trunc:
1259 buf[len - 1] = '\0';
1260 addlen = 0;
1261 /* append filename if necessary */
1262 if (!is_dir) {
1263 if (buf[len - 2] != '/')
1264 addlen++;
1265 addlen += strlen(unode->od_name);
1266 }
1267
1268 /* append named stream name if necessary */
1269 if (is_stream)
1270 addlen += strlen(node->od_name);
1271
1272 if ((buflen - len) < addlen) {
1273 #ifdef DEBUG
1274 cmn_err(CE_WARN,
1275 "smb_node_getpath_nofail: vnodetopath succeeded, "
1276 "but buffer too small for filename");
1277 #else
1278 cmn_err(CE_WARN,
1279 "smb_node_getpath_nofail: couldn't get full path");
1280 #endif
1281 addlen = addlen - (buflen - len);
1282 (void) memmove(buf, buf + addlen, len - addlen);
1283 buf[0] = '*';
1284 }
1285
1286 /* append filename if necessary */
1287 if (!is_dir) {
1288 if (buf[len - 2] != '/')
1289 (void) strlcat(buf, "/", buflen);
1290 (void) strlcat(buf, unode->od_name, buflen);
1291 }
1292
1293 /* append named stream name if necessary */
1294 if (is_stream)
1295 (void) strlcat(buf, node->od_name, buflen);
1296 }
1297
1298 /*
1299 * smb_node_alloc
1300 */
1301 static smb_node_t *
1302 smb_node_alloc(
1303 char *od_name,
1304 vnode_t *vp,
1305 smb_llist_t *bucket,
1306 uint32_t hashkey)
1307 {
1308 smb_node_t *node;
1309 vnode_t *root_vp;
1310
1311 node = kmem_cache_alloc(smb_node_cache, KM_SLEEP);
1312
1313 if (node->n_audit_buf != NULL)
1314 node->n_audit_buf->anb_index = 0;
1315
1316 node->flags = 0;
1317 VN_HOLD(vp);
1318 node->vp = vp;
1319 node->n_refcnt = 1;
1320 node->n_hash_bucket = bucket;
1321 node->n_hashkey = hashkey;
1322 node->n_open_count = 0;
1323 node->n_allocsz = 0;
1324 node->n_dnode = NULL;
1325 node->n_unode = NULL;
1326 node->delete_on_close_cred = NULL;
1327 node->n_delete_on_close_flags = 0;
1328 node->n_oplock.ol_fem = B_FALSE;
1329
1330 (void) strlcpy(node->od_name, od_name, sizeof (node->od_name));
1331 if (strcmp(od_name, XATTR_DIR) == 0)
1332 node->flags |= NODE_XATTR_DIR;
1333
1334 if (VFS_ROOT(vp->v_vfsp, &root_vp) == 0) {
1335 if (vp == root_vp)
1336 node->flags |= NODE_FLAGS_VFSROOT;
1337 VN_RELE(root_vp);
1338 }
1339
1340 node->n_state = SMB_NODE_STATE_AVAILABLE;
1341 node->n_magic = SMB_NODE_MAGIC;
1342
1343 return (node);
1344 }
1345
1346 /*
1347 * smb_node_free
1348 */
1349 static void
1350 smb_node_free(smb_node_t *node)
1351 {
1352 SMB_NODE_VALID(node);
1353
1354 node->n_magic = 0;
1355 VERIFY(!list_link_active(&node->n_lnd));
1356 VERIFY(node->n_lock_list.ll_count == 0);
1357 VERIFY(node->n_wlock_list.ll_count == 0);
1358 VERIFY(node->n_ofile_list.ll_count == 0);
1359 VERIFY(node->n_oplock.ol_fem == B_FALSE);
1360 VERIFY(MUTEX_NOT_HELD(&node->n_mutex));
1361 VERIFY(!RW_LOCK_HELD(&node->n_lock));
1362 VN_RELE(node->vp);
1363 kmem_cache_free(smb_node_cache, node);
1364 }
1365
1366 /*
1367 * smb_node_constructor
1368 */
1369 static int
1370 smb_node_constructor(void *buf, void *un, int kmflags)
1371 {
1372 _NOTE(ARGUNUSED(kmflags, un))
1373
1374 smb_node_t *node = (smb_node_t *)buf;
1375
1376 bzero(node, sizeof (smb_node_t));
1377
1378 smb_llist_constructor(&node->n_ofile_list, sizeof (smb_ofile_t),
1379 offsetof(smb_ofile_t, f_node_lnd));
1380 smb_llist_constructor(&node->n_lock_list, sizeof (smb_lock_t),
1381 offsetof(smb_lock_t, l_lnd));
1382 smb_llist_constructor(&node->n_wlock_list, sizeof (smb_lock_t),
1383 offsetof(smb_lock_t, l_lnd));
1384 mutex_init(&node->n_oplock.ol_mutex, NULL, MUTEX_DEFAULT, NULL);
1385 cv_init(&node->n_oplock.WaitingOpenCV, NULL, CV_DEFAULT, NULL);
1386 rw_init(&node->n_lock, NULL, RW_DEFAULT, NULL);
1387 mutex_init(&node->n_mutex, NULL, MUTEX_DEFAULT, NULL);
1388 smb_node_create_audit_buf(node, kmflags);
1389 return (0);
1390 }
1391
1392 /*
1393 * smb_node_destructor
1394 */
1395 static void
1396 smb_node_destructor(void *buf, void *un)
1397 {
1398 _NOTE(ARGUNUSED(un))
1399
1400 smb_node_t *node = (smb_node_t *)buf;
1401
1402 smb_node_destroy_audit_buf(node);
1403 mutex_destroy(&node->n_mutex);
1404 rw_destroy(&node->n_lock);
1405 cv_destroy(&node->n_oplock.WaitingOpenCV);
1406 mutex_destroy(&node->n_oplock.ol_mutex);
1407 smb_llist_destructor(&node->n_lock_list);
1408 smb_llist_destructor(&node->n_wlock_list);
1409 smb_llist_destructor(&node->n_ofile_list);
1410 }
1411
1412 /*
1413 * smb_node_create_audit_buf
1414 */
1415 static void
1416 smb_node_create_audit_buf(smb_node_t *node, int kmflags)
1417 {
1418 smb_audit_buf_node_t *abn;
1419
1420 if (smb_audit_flags & SMB_AUDIT_NODE) {
1421 abn = kmem_zalloc(sizeof (smb_audit_buf_node_t), kmflags);
1422 abn->anb_max_index = SMB_AUDIT_BUF_MAX_REC - 1;
1423 node->n_audit_buf = abn;
1424 }
1425 }
1426
1427 /*
1428 * smb_node_destroy_audit_buf
1429 */
1430 static void
1431 smb_node_destroy_audit_buf(smb_node_t *node)
1432 {
1433 if (node->n_audit_buf != NULL) {
1434 kmem_free(node->n_audit_buf, sizeof (smb_audit_buf_node_t));
1435 node->n_audit_buf = NULL;
1436 }
1437 }
1438
1439 /*
1440 * smb_node_audit
1441 *
1442 * This function saves the calling stack in the audit buffer of the node passed
1443 * in.
1444 */
1445 static void
1446 smb_node_audit(smb_node_t *node)
1447 {
1448 #ifdef _KERNEL
1449 smb_audit_buf_node_t *abn;
1450 smb_audit_record_node_t *anr;
1451
1452 if (node->n_audit_buf) {
1453 abn = node->n_audit_buf;
1454 anr = abn->anb_records;
1455 anr += abn->anb_index;
1456 abn->anb_index++;
1457 abn->anb_index &= abn->anb_max_index;
1458 anr->anr_refcnt = node->n_refcnt;
1459 anr->anr_depth = getpcstack(anr->anr_stack,
1460 SMB_AUDIT_STACK_DEPTH);
1461 }
1462 #else /* _KERNEL */
1463 _NOTE(ARGUNUSED(node))
1464 #endif /* _KERNEL */
1465 }
1466
1467 static smb_llist_t *
1468 smb_node_get_hash(fsid_t *fsid, smb_attr_t *attr, uint32_t *phashkey)
1469 {
1470 uint32_t hashkey;
1471
1472 hashkey = fsid->val[0] + attr->sa_vattr.va_nodeid;
1473 hashkey += (hashkey >> 24) + (hashkey >> 16) + (hashkey >> 8);
1474 *phashkey = hashkey;
1475 return (&smb_node_hash_table[(hashkey & SMBND_HASH_MASK)]);
1476 }
1477
1478 boolean_t
1479 smb_node_is_file(smb_node_t *node)
1480 {
1481 SMB_NODE_VALID(node);
1482 return (node->vp->v_type == VREG);
1483 }
1484
1485 boolean_t
1486 smb_node_is_dir(smb_node_t *node)
1487 {
1488 SMB_NODE_VALID(node);
1489 return ((node->vp->v_type == VDIR) ||
1490 (node->flags & NODE_FLAGS_DFSLINK));
1491 }
1492
1493 boolean_t
1494 smb_node_is_symlink(smb_node_t *node)
1495 {
1496 SMB_NODE_VALID(node);
1497 return ((node->vp->v_type == VLNK) &&
1498 ((node->flags & NODE_FLAGS_REPARSE) == 0));
1499 }
1500
1501 boolean_t
1502 smb_node_is_dfslink(smb_node_t *node)
1503 {
1504 SMB_NODE_VALID(node);
1505 return ((node->vp->v_type == VLNK) &&
1506 (node->flags & NODE_FLAGS_DFSLINK));
1507 }
1508
1509 boolean_t
1510 smb_node_is_reparse(smb_node_t *node)
1511 {
1512 SMB_NODE_VALID(node);
1513 return ((node->vp->v_type == VLNK) &&
1514 (node->flags & NODE_FLAGS_REPARSE));
1515 }
1516
1517 boolean_t
1518 smb_node_is_vfsroot(smb_node_t *node)
1519 {
1520 SMB_NODE_VALID(node);
1521 return ((node->flags & NODE_FLAGS_VFSROOT) == NODE_FLAGS_VFSROOT);
1522 }
1523
1524 boolean_t
1525 smb_node_is_system(smb_node_t *node)
1526 {
1527 SMB_NODE_VALID(node);
1528 return ((node->flags & NODE_FLAGS_SYSTEM) == NODE_FLAGS_SYSTEM);
1529 }
1530
1531 /*
1532 * smb_node_file_is_readonly
1533 *
1534 * Checks if the file (which node represents) is marked readonly
1535 * in the filesystem. Note that there may be handles open with
1536 * modify rights, and those continue to allow access even after
1537 * the DOS read-only flag has been set in the file system.
1538 */
1539 boolean_t
1540 smb_node_file_is_readonly(smb_node_t *node)
1541 {
1542 smb_attr_t attr;
1543
1544 if (node == NULL)
1545 return (B_FALSE); /* pipes */
1546
1547 bzero(&attr, sizeof (smb_attr_t));
1548 attr.sa_mask = SMB_AT_DOSATTR;
1549 (void) smb_fsop_getattr(NULL, zone_kcred(), node, &attr);
1550 return ((attr.sa_dosattr & FILE_ATTRIBUTE_READONLY) != 0);
1551 }
1552
1553 /*
1554 * smb_node_setattr
1555 *
1556 * The sr may be NULL, for example when closing an ofile.
1557 * The ofile may be NULL, for example when a client request
1558 * specifies the file by pathname.
1559 *
1560 * Returns: errno
1561 *
1562 * Timestamps
1563 *
1564 * Windows and Unix have different models for timestamp updates.
1565 * [MS-FSA 2.1.5.14 Server Requests Setting of File Information]
1566 *
1567 * An open "handle" in Windows can control whether and when
1568 * any timestamp updates happen for that handle. For example,
1569 * timestamps set via some handle are no longer updated by I/O
1570 * operations on that handle. In Unix we don't really have any
1571 * way to avoid the timestamp updates that the file system does.
1572 * Therefore, we need to make some compromises, and simulate the
1573 * more important parts of the Windows file system semantics.
1574 *
1575 * For example, when an SMB client sets file times, set those
1576 * times in the file system (so the change will be visible to
1577 * other clients, at least until they change again) but we also
1578 * make those times "sticky" in our open handle, and reapply
1579 * those times when the handle is closed. That reapply on close
1580 * simulates the Windows behavior where the timestamp updates
1581 * would be discontinued after they were set. These "sticky"
1582 * attributes are returned in any query on the handle where
1583 * they are stored.
1584 *
1585 * Other than the above, the file system layer takes care of the
1586 * normal time stamp updates, such as updating the mtime after a
1587 * write, and ctime after an attribute change.
1588 *
1589 * Dos Attributes are stored persistently, but with a twist:
1590 * In Windows, when you set the "read-only" bit on some file,
1591 * existing writable handles to that file continue to have
1592 * write access. (because access check happens at open)
1593 * If we were to set the read-only bit directly, we would
1594 * cause errors in subsequent writes on any of our open
1595 * (and writable) file handles. So here too, we have to
1596 * simulate the Windows behavior. We keep the read-only
1597 * bit "pending" in the smb_node (so it will be visible in
1598 * any new opens of the file) and apply it on close.
1599 *
1600 * File allocation size is also simulated, and not persistent.
1601 * When the file allocation size is set it is first rounded up
1602 * to block size. If the file size is smaller than the allocation
1603 * size the file is truncated by setting the filesize to allocsz.
1604 */
1605 int
1606 smb_node_setattr(smb_request_t *sr, smb_node_t *node,
1607 cred_t *cr, smb_ofile_t *of, smb_attr_t *attr)
1608 {
1609 int rc;
1610 uint_t times_mask;
1611 smb_attr_t tmp_attr;
1612 smb_node_t *unnamed_node;
1613
1614 SMB_NODE_VALID(node);
1615
1616 /* set attributes specified in attr */
1617 if (attr->sa_mask == 0)
1618 return (0); /* nothing to do (caller bug?) */
1619
1620 /*
1621 * Allocation size and EOF position interact.
1622 * We don't persistently store the allocation size
1623 * but make it look like we do while there are opens.
1624 * Note: We update the caller's attr in the cases
1625 * where they're setting only one of allocsz|size.
1626 */
1627 switch (attr->sa_mask & (SMB_AT_ALLOCSZ | SMB_AT_SIZE)) {
1628
1629 case SMB_AT_ALLOCSZ:
1630 /*
1631 * Setting the allocation size but not EOF position.
1632 * Get the current EOF in tmp_attr and (if necessary)
1633 * truncate to the (rounded up) allocation size.
1634 * Using kcred here because if we don't have access,
1635 * we want to fail at setattr below and not here.
1636 */
1637 bzero(&tmp_attr, sizeof (smb_attr_t));
1638 tmp_attr.sa_mask = SMB_AT_SIZE;
1639 rc = smb_fsop_getattr(NULL, zone_kcred(), node, &tmp_attr);
1640 if (rc != 0)
1641 return (rc);
1642 attr->sa_allocsz = SMB_ALLOCSZ(attr->sa_allocsz);
1643 if (tmp_attr.sa_vattr.va_size > attr->sa_allocsz) {
1644 /* truncate the file to allocsz */
1645 attr->sa_vattr.va_size = attr->sa_allocsz;
1646 attr->sa_mask |= SMB_AT_SIZE;
1647 }
1648 break;
1649
1650 case SMB_AT_SIZE:
1651 /*
1652 * Setting the EOF position but not allocation size.
1653 * If the new EOF position would be greater than
1654 * the allocation size, increase the latter.
1655 */
1656 if (node->n_allocsz < attr->sa_vattr.va_size) {
1657 attr->sa_mask |= SMB_AT_ALLOCSZ;
1658 attr->sa_allocsz =
1659 SMB_ALLOCSZ(attr->sa_vattr.va_size);
1660 }
1661 break;
1662
1663 case SMB_AT_ALLOCSZ | SMB_AT_SIZE:
1664 /*
1665 * Setting both. Increase alloc size if needed.
1666 */
1667 if (attr->sa_allocsz < attr->sa_vattr.va_size)
1668 attr->sa_allocsz =
1669 SMB_ALLOCSZ(attr->sa_vattr.va_size);
1670 break;
1671
1672 default:
1673 break;
1674 }
1675
1676 /*
1677 * If we have an open file, and we set the size,
1678 * then set the "written" flag so that at close,
1679 * we can force an mtime update.
1680 */
1681 if (of != NULL && (attr->sa_mask & SMB_AT_SIZE) != 0)
1682 of->f_written = B_TRUE;
1683
1684 /*
1685 * When operating on an open file, some settable attributes
1686 * become "sticky" in the open file object until close.
1687 * (see above re. timestamps)
1688 */
1689 times_mask = attr->sa_mask & SMB_AT_TIMES;
1690 if (of != NULL && times_mask != 0) {
1691 smb_attr_t *pa;
1692
1693 SMB_OFILE_VALID(of);
1694 mutex_enter(&of->f_mutex);
1695 pa = &of->f_pending_attr;
1696
1697 pa->sa_mask |= times_mask;
1698
1699 if (times_mask & SMB_AT_ATIME)
1700 pa->sa_vattr.va_atime =
1701 attr->sa_vattr.va_atime;
1702 if (times_mask & SMB_AT_MTIME)
1703 pa->sa_vattr.va_mtime =
1704 attr->sa_vattr.va_mtime;
1705 if (times_mask & SMB_AT_CTIME)
1706 pa->sa_vattr.va_ctime =
1707 attr->sa_vattr.va_ctime;
1708 if (times_mask & SMB_AT_CRTIME)
1709 pa->sa_crtime =
1710 attr->sa_crtime;
1711
1712 mutex_exit(&of->f_mutex);
1713
1714 /*
1715 * The f_pending_attr times are reapplied in
1716 * smb_ofile_close().
1717 */
1718
1719 /*
1720 * If this change is comming directly from a client
1721 * (sr != NULL) and it's a persistent handle, save
1722 * the "sticky times" in the handle.
1723 */
1724 if (sr != NULL && of->dh_persist) {
1725 smb2_dh_update_times(sr, of, attr);
1726 }
1727 }
1728
1729 if ((attr->sa_mask & SMB_AT_ALLOCSZ) != 0) {
1730 mutex_enter(&node->n_mutex);
1731 /*
1732 * Simulate n_allocsz persistence only while
1733 * there are opens. See smb_node_getattr
1734 */
1735 if (node->n_open_count != 0)
1736 node->n_allocsz = attr->sa_allocsz;
1737 mutex_exit(&node->n_mutex);
1738 }
1739
1740 rc = smb_fsop_setattr(sr, cr, node, attr);
1741 if (rc != 0)
1742 return (rc);
1743
1744 if (node->n_dnode != NULL) {
1745 smb_node_notify_change(node->n_dnode,
1746 FILE_ACTION_MODIFIED, node->od_name);
1747 }
1748
1749 if ((unnamed_node = SMB_IS_STREAM(node)) != NULL) {
1750 ASSERT(unnamed_node->n_magic == SMB_NODE_MAGIC);
1751 ASSERT(unnamed_node->n_state != SMB_NODE_STATE_DESTROYING);
1752 smb_node_notify_change(node->n_dnode,
1753 FILE_ACTION_MODIFIED_STREAM, node->od_name);
1754 }
1755
1756 return (0);
1757 }
1758
1759 /*
1760 * smb_node_getattr
1761 *
1762 * Get attributes from the file system and apply any smb-specific
1763 * overrides for size, dos attributes and timestamps
1764 *
1765 * When node->n_pending_readonly is set on a node, pretend that
1766 * we've already set this node readonly at the filesystem level.
1767 * We can't actually do that until all writable handles are closed
1768 * or those writable handles would suddenly loose their access.
1769 *
1770 * Returns: errno
1771 */
1772 int
1773 smb_node_getattr(smb_request_t *sr, smb_node_t *node, cred_t *cr,
1774 smb_ofile_t *of, smb_attr_t *attr)
1775 {
1776 int rc;
1777 uint_t want_mask, pend_mask;
1778 boolean_t isdir;
1779
1780 SMB_NODE_VALID(node);
1781
1782 /* Deal with some interdependencies */
1783 if (attr->sa_mask & SMB_AT_ALLOCSZ)
1784 attr->sa_mask |= SMB_AT_SIZE;
1785 if (attr->sa_mask & SMB_AT_DOSATTR)
1786 attr->sa_mask |= SMB_AT_TYPE;
1787
1788 rc = smb_fsop_getattr(sr, cr, node, attr);
1789 if (rc != 0)
1790 return (rc);
1791
1792 isdir = smb_node_is_dir(node);
1793
1794 mutex_enter(&node->n_mutex);
1795
1796 if (attr->sa_mask & SMB_AT_DOSATTR) {
1797 if (attr->sa_dosattr == 0) {
1798 attr->sa_dosattr = (isdir) ?
1799 FILE_ATTRIBUTE_DIRECTORY:
1800 FILE_ATTRIBUTE_NORMAL;
1801 }
1802 }
1803
1804 /*
1805 * Also fix-up sa_allocsz, which is not persistent.
1806 * When there are no open files, allocsz is faked.
1807 * While there are open files, we pretend we have a
1808 * persistent allocation size in n_allocsz, and
1809 * keep that up-to-date here, increasing it when
1810 * we see the file size grow past it.
1811 */
1812 if (attr->sa_mask & SMB_AT_ALLOCSZ) {
1813 if (isdir) {
1814 attr->sa_allocsz = 0;
1815 } else if (node->n_open_count == 0) {
1816 attr->sa_allocsz =
1817 SMB_ALLOCSZ(attr->sa_vattr.va_size);
1818 } else {
1819 if (node->n_allocsz < attr->sa_vattr.va_size)
1820 node->n_allocsz =
1821 SMB_ALLOCSZ(attr->sa_vattr.va_size);
1822 attr->sa_allocsz = node->n_allocsz;
1823 }
1824 }
1825
1826 mutex_exit(&node->n_mutex);
1827
1828 if (isdir) {
1829 attr->sa_vattr.va_size = 0;
1830 attr->sa_vattr.va_nlink = 1;
1831 }
1832
1833 /*
1834 * getattr with an ofile gets any "pending" times that
1835 * might have been previously set via this ofile.
1836 * This is what makes these times "sticky".
1837 */
1838 want_mask = attr->sa_mask & SMB_AT_TIMES;
1839 if (of != NULL && want_mask != 0) {
1840 smb_attr_t *pa;
1841
1842 SMB_OFILE_VALID(of);
1843 mutex_enter(&of->f_mutex);
1844 pa = &of->f_pending_attr;
1845
1846 pend_mask = pa->sa_mask;
1847
1848 if (want_mask & pend_mask & SMB_AT_ATIME)
1849 attr->sa_vattr.va_atime =
1850 pa->sa_vattr.va_atime;
1851 if (want_mask & pend_mask & SMB_AT_MTIME)
1852 attr->sa_vattr.va_mtime =
1853 pa->sa_vattr.va_mtime;
1854 if (want_mask & pend_mask & SMB_AT_CTIME)
1855 attr->sa_vattr.va_ctime =
1856 pa->sa_vattr.va_ctime;
1857 if (want_mask & pend_mask & SMB_AT_CRTIME)
1858 attr->sa_crtime =
1859 pa->sa_crtime;
1860
1861 mutex_exit(&of->f_mutex);
1862 }
1863
1864
1865 return (0);
1866 }
1867
1868
1869 #ifndef _KERNEL
1870 extern int reparse_vnode_parse(vnode_t *vp, nvlist_t *nvl);
1871 #endif /* _KERNEL */
1872
1873 /*
1874 * Check to see if the node represents a reparse point.
1875 * If yes, whether the reparse point contains a DFS link.
1876 */
1877 static void
1878 smb_node_init_reparse(smb_node_t *node, smb_attr_t *attr)
1879 {
1880 nvlist_t *nvl;
1881 nvpair_t *rec;
1882 char *rec_type;
1883
1884 if ((attr->sa_dosattr & FILE_ATTRIBUTE_REPARSE_POINT) == 0)
1885 return;
1886
1887 if ((nvl = reparse_init()) == NULL)
1888 return;
1889
1890 if (reparse_vnode_parse(node->vp, nvl) != 0) {
1891 reparse_free(nvl);
1892 return;
1893 }
1894
1895 node->flags |= NODE_FLAGS_REPARSE;
1896
1897 rec = nvlist_next_nvpair(nvl, NULL);
1898 while (rec != NULL) {
1899 rec_type = nvpair_name(rec);
1900 if ((rec_type != NULL) &&
1901 (strcasecmp(rec_type, DFS_REPARSE_SVCTYPE) == 0)) {
1902 node->flags |= NODE_FLAGS_DFSLINK;
1903 break;
1904 }
1905 rec = nvlist_next_nvpair(nvl, rec);
1906 }
1907
1908 reparse_free(nvl);
1909 }
1910
1911 /*
1912 * smb_node_init_system
1913 *
1914 * If the node represents a special system file set NODE_FLAG_SYSTEM.
1915 * System files:
1916 * - any node whose parent dnode has NODE_FLAG_SYSTEM set
1917 * - any node whose associated unnamed stream node (unode) has
1918 * NODE_FLAG_SYSTEM set
1919 * - .$EXTEND at root of share (quota management)
1920 */
1921 static void
1922 smb_node_init_system(smb_node_t *node)
1923 {
1924 smb_node_t *dnode = node->n_dnode;
1925 smb_node_t *unode = node->n_unode;
1926
1927 if ((dnode) && (dnode->flags & NODE_FLAGS_SYSTEM)) {
1928 node->flags |= NODE_FLAGS_SYSTEM;
1929 return;
1930 }
1931
1932 if ((unode) && (unode->flags & NODE_FLAGS_SYSTEM)) {
1933 node->flags |= NODE_FLAGS_SYSTEM;
1934 return;
1935 }
1936
1937 if ((dnode) && (smb_node_is_vfsroot(node->n_dnode) &&
1938 (strcasecmp(node->od_name, ".$EXTEND") == 0))) {
1939 node->flags |= NODE_FLAGS_SYSTEM;
1940 }
1941 }