Print this page
NEX-14666 Need to provide SMB 2.1 Client
NEX-17187 panic in smbfs_acl_store
NEX-17231 smbfs create xattr files finds wrong file
NEX-17224 smbfs lookup EINVAL should be ENOENT
NEX-17260 SMB1 client fails to list directory after NEX-14666
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Rick McNeal <rick.mcneal@nexenta.com>
Reviewed by: Saso Kiselkov <saso.kiselkov@nexenta.com>
Reviewed by: Joyce McIntosh <joyce.mcintosh@nexenta.com>
and: (cleanup)
| Split |
Close |
| Expand all |
| Collapse all |
--- old/usr/src/uts/common/fs/smbclnt/smbfs/smbfs_acl.c
+++ new/usr/src/uts/common/fs/smbclnt/smbfs/smbfs_acl.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
↓ open down ↓ |
14 lines elided |
↑ open up ↑ |
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21
22 22 /*
23 23 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
24 24 * Use is subject to license terms.
25 + *
26 + * Copyright 2018 Nexenta Systems, Inc. All rights reserved.
25 27 */
26 28
27 29 /*
28 30 * ACL support for smbfs
29 31 */
30 32
31 33 #include <sys/systm.h> /* bcopy, ... */
32 34 #include <sys/errno.h>
33 35 #include <sys/cred.h>
34 36 #include <sys/cmn_err.h>
35 37 #include <sys/kmem.h>
36 38 #include <sys/sunddi.h>
37 39 #include <sys/acl.h>
38 40 #include <sys/vnode.h>
39 41 #include <sys/vfs.h>
40 42 #include <sys/byteorder.h>
41 43
42 44 #include <netsmb/mchain.h>
43 45 #include <netsmb/smb.h>
44 46 #include <netsmb/smb_conn.h>
45 47 #include <netsmb/smb_osdep.h>
46 48 #include <netsmb/smb_subr.h>
47 49
48 50 #include <smbfs/smbfs.h>
49 51 #include <smbfs/smbfs_node.h>
50 52 #include <smbfs/smbfs_subr.h>
51 53
52 54 #include <sys/fs/smbfs_ioctl.h>
53 55 #include <fs/fs_subr.h>
54 56 #include "smbfs_ntacl.h"
55 57
56 58 /* Sanity check SD sizes */
57 59 #define MAX_RAW_SD_SIZE 32768
58 60 #define SMALL_SD_SIZE 1024
59 61
60 62 /*
61 63 * smbfs_getsd() is a common function used by both
|
↓ open down ↓ |
27 lines elided |
↑ open up ↑ |
62 64 * smbfs_ioctl SMBFSIO_GETSD and VOP_GETSECATTR.
63 65 * Handles required rights, tmpopen/tmpclose.
64 66 *
65 67 * Note: smbfs_getsd allocates and returns an mblk chain,
66 68 * which the caller must free.
67 69 */
68 70 static int
69 71 smbfs_getsd(vnode_t *vp, uint32_t selector, mblk_t **mp, cred_t *cr)
70 72 {
71 73 struct smb_cred scred;
72 - int error, cerror;
73 74 smbmntinfo_t *smi;
74 75 smbnode_t *np;
75 - u_int16_t fid = SMB_FID_UNUSED;
76 + smb_fh_t *fid = NULL;
76 77 uint32_t sdlen = SMALL_SD_SIZE;
77 78 uint32_t rights = STD_RIGHT_READ_CONTROL_ACCESS;
79 + int error;
78 80
79 81 if (selector & SACL_SECURITY_INFORMATION)
80 82 rights |= SEC_RIGHT_SYSTEM_SECURITY;
81 83
82 84 np = VTOSMB(vp);
83 85 smi = VTOSMI(vp);
84 86
85 - /* Shared lock for (possible) n_fid use. */
86 - if (smbfs_rw_enter_sig(&np->r_lkserlock, RW_READER, SMBINTR(vp)))
87 - return (EINTR);
88 87 smb_credinit(&scred, cr);
89 88
90 89 error = smbfs_smb_tmpopen(np, rights, &scred, &fid);
91 90 if (error)
92 91 goto out;
93 92
94 93 again:
95 94 /*
96 95 * This does the OTW Get
97 96 */
98 - error = smbfs_smb_getsec_m(smi->smi_share, fid,
99 - &scred, selector, mp, &sdlen);
97 + error = smbfs_smb_getsec(smi->smi_share, fid,
98 + selector, mp, &sdlen, &scred);
100 99 /*
101 100 * Server may give us an error indicating that we
102 101 * need a larger data buffer to receive the SD,
103 102 * and the size we'll need. Use the given size,
104 103 * but only after a sanity check.
105 104 *
106 105 * Let's check for specific error values here.
107 106 * The NT error is: STATUS_BUFFER_TOO_SMALL,
108 107 * or with old error codes, one of these:
109 108 * ERRSRV/ERRnoroom, ERRDOS/122, ERRDOS/111
110 109 * Those are mapped to: EMOREDATA, which is
111 110 * later converted to E2BIG.
112 111 */
113 112 if (error == E2BIG &&
114 113 sdlen > SMALL_SD_SIZE &&
115 114 sdlen <= MAX_RAW_SD_SIZE)
116 115 goto again;
117 116
118 - cerror = smbfs_smb_tmpclose(np, fid, &scred);
119 - if (cerror)
120 - SMBVDEBUG("error %d closing file %s\n",
121 - cerror, np->n_rpath);
117 + smbfs_smb_tmpclose(np, fid);
122 118
123 119 out:
124 120 smb_credrele(&scred);
125 - smbfs_rw_exit(&np->r_lkserlock);
126 121
127 122 return (error);
128 123 }
129 124
130 125 /*
131 126 * smbfs_setsd() is a common function used by both
132 127 * smbfs_ioctl SMBFSIO_SETSD and VOP_SETSECATTR.
133 128 * Handles required rights, tmpopen/tmpclose.
134 129 *
135 130 * Note: smbfs_setsd _consumes_ the passed *mp and
136 131 * clears the pointer (so the caller won't free it)
137 132 */
138 133 static int
139 134 smbfs_setsd(vnode_t *vp, uint32_t selector, mblk_t **mp, cred_t *cr)
140 135 {
141 136 struct smb_cred scred;
142 - int error, cerror;
143 137 smbmntinfo_t *smi;
144 138 smbnode_t *np;
145 139 uint32_t rights;
146 - u_int16_t fid = SMB_FID_UNUSED;
140 + smb_fh_t *fid = NULL;
141 + int error;
147 142
148 143 np = VTOSMB(vp);
149 144 smi = VTOSMI(vp);
150 145
151 146 /*
152 147 * Which parts of the SD are we setting?
153 148 * What rights do we need for that?
154 149 */
155 150 if (selector == 0)
156 151 return (0);
157 152
158 153 rights = 0;
159 154 if (selector & (OWNER_SECURITY_INFORMATION |
160 155 GROUP_SECURITY_INFORMATION))
161 156 rights |= STD_RIGHT_WRITE_OWNER_ACCESS;
162 157 if (selector & DACL_SECURITY_INFORMATION)
163 158 rights |= STD_RIGHT_WRITE_DAC_ACCESS;
164 159 if (selector & SACL_SECURITY_INFORMATION)
165 160 rights |= SEC_RIGHT_SYSTEM_SECURITY;
166 161
167 - /* Shared lock for (possible) n_fid use. */
168 - if (smbfs_rw_enter_sig(&np->r_lkserlock, RW_READER, SMBINTR(vp)))
169 - return (EINTR);
170 162 smb_credinit(&scred, cr);
171 163
172 164 error = smbfs_smb_tmpopen(np, rights, &scred, &fid);
173 165 if (error)
174 166 goto out;
175 167
176 168 /*
177 169 * We're setting the remote ACL now, so
178 170 * invalidate our cached ACL just in case
179 171 * the server doesn't do exactly as we ask.
180 172 */
181 173 mutex_enter(&np->r_statelock);
182 174 np->r_sectime = gethrtime();
183 175 mutex_exit(&np->r_statelock);
184 176
185 177 /*
186 178 * This does the OTW Set
187 179 */
188 - error = smbfs_smb_setsec_m(smi->smi_share, fid,
189 - &scred, selector, mp);
180 + error = smbfs_smb_setsec(smi->smi_share, fid,
181 + selector, mp, &scred);
190 182
191 - cerror = smbfs_smb_tmpclose(np, fid, &scred);
192 - if (cerror)
193 - SMBVDEBUG("error %d closing file %s\n",
194 - cerror, np->n_rpath);
183 + smbfs_smb_tmpclose(np, fid);
195 184
196 185 out:
197 186 smb_credrele(&scred);
198 - smbfs_rw_exit(&np->r_lkserlock);
199 187
200 188 return (error);
201 189 }
202 190
203 191 /*
204 192 * Helper for VOP_IOCTL: SMBFSIO_GETSD
205 193 */
206 194 int
207 195 smbfs_acl_iocget(vnode_t *vp, intptr_t arg, int flag, cred_t *cr)
208 196 {
209 197 ioc_sdbuf_t iocb;
210 198 mdchain_t *mdp, md_store;
211 199 mblk_t *m;
212 200 void *ubuf;
213 201 int error;
214 202
215 203 /*
216 204 * Get the buffer information
217 205 */
218 206 if (ddi_copyin((void *)arg, &iocb, sizeof (iocb), flag))
219 207 return (EFAULT);
220 208
221 209 /*
222 210 * This does the OTW Get (and maybe open, close)
223 211 * Allocates and returns an mblk in &m.
224 212 */
225 213 error = smbfs_getsd(vp, iocb.selector, &m, cr);
226 214 if (error)
227 215 return (error);
228 216
229 217 /*
230 218 * Have m. Must free it before return.
231 219 */
232 220 mdp = &md_store;
233 221 md_initm(mdp, m);
234 222 iocb.used = m_fixhdr(m);
235 223
236 224 /*
237 225 * Always copyout the buffer information,
238 226 * so the user can realloc and try again
239 227 * after an EOVERFLOW return.
240 228 */
241 229 if (ddi_copyout(&iocb, (void *)arg, sizeof (iocb), flag)) {
242 230 error = EFAULT;
243 231 goto out;
244 232 }
245 233
246 234 if (iocb.used > iocb.alloc) {
247 235 error = EOVERFLOW;
248 236 goto out;
249 237 }
250 238
251 239 /*
252 240 * Copyout the buffer contents (SD)
253 241 */
254 242 ubuf = (void *)(uintptr_t)iocb.addr;
255 243 error = md_get_mem(mdp, ubuf, iocb.used, MB_MUSER);
256 244
257 245 out:
258 246 /* Note: m_freem(m) is done by... */
259 247 md_done(mdp);
260 248
261 249 return (error);
262 250 }
263 251
264 252 /*
265 253 * Helper for VOP_IOCTL: SMBFSIO_SETSD
266 254 */
267 255 int
268 256 smbfs_acl_iocset(vnode_t *vp, intptr_t arg, int flag, cred_t *cr)
269 257 {
270 258 ioc_sdbuf_t iocb;
271 259 mbchain_t *mbp, mb_store;
272 260 void *ubuf;
273 261 int error;
274 262
275 263 /*
276 264 * Get the buffer information
277 265 */
278 266 if (ddi_copyin((void *)arg, &iocb, sizeof (iocb), flag))
279 267 return (EFAULT);
280 268
281 269 if (iocb.used < sizeof (ntsecdesc_t) ||
282 270 iocb.used >= MAX_RAW_SD_SIZE)
283 271 return (EINVAL);
284 272
285 273 /*
286 274 * Get the buffer contents (security descriptor data)
287 275 */
288 276 mbp = &mb_store;
289 277 (void) mb_init(mbp);
290 278 ubuf = (void *)(uintptr_t)iocb.addr;
291 279 error = mb_put_mem(mbp, ubuf, iocb.used, MB_MUSER);
292 280 if (error)
293 281 goto out;
294 282
295 283 /*
296 284 * This does the OTW Set (and maybe open, close)
297 285 * It clears mb_top when consuming the message.
298 286 */
299 287 error = smbfs_setsd(vp, iocb.selector, &mbp->mb_top, cr);
300 288
301 289 out:
302 290 mb_done(mbp);
303 291 return (error);
304 292
305 293 }
306 294
307 295 /*
308 296 * Refresh our cached copy of the security attributes
309 297 */
310 298 static int
311 299 smbfs_acl_refresh(vnode_t *vp, cred_t *cr)
312 300 {
313 301 smbnode_t *np;
314 302 smbmntinfo_t *smi;
315 303 mdchain_t *mdp, md_store;
316 304 mblk_t *m = NULL;
317 305 i_ntsd_t *sd = NULL;
318 306 vsecattr_t vsa, ovsa;
319 307 uint32_t selector;
320 308 uid_t uid;
321 309 gid_t gid;
322 310 int error;
323 311
324 312 np = VTOSMB(vp);
325 313 smi = VTOSMI(vp);
326 314
327 315 bzero(&md_store, sizeof (md_store));
328 316 mdp = &md_store;
329 317
330 318 /*
331 319 * Which parts of the SD we request.
332 320 * Not getting the SACL for now.
333 321 */
334 322 selector = DACL_SECURITY_INFORMATION |
335 323 OWNER_SECURITY_INFORMATION |
336 324 GROUP_SECURITY_INFORMATION;
337 325
338 326 /*
339 327 * This does the OTW Get (and maybe open, close)
340 328 * Allocates and returns an mblk in &m.
341 329 */
342 330 error = smbfs_getsd(vp, selector, &m, cr);
343 331 if (error)
344 332 goto out;
345 333 /* Note: allocated *m */
346 334 md_initm(mdp, m);
347 335
348 336 /*
349 337 * Parse the OtW security descriptor,
350 338 * storing in our internal form.
351 339 */
352 340 error = md_get_ntsd(mdp, &sd);
353 341 if (error)
354 342 goto out;
355 343
356 344 /*
357 345 * Convert the Windows security descriptor to a
358 346 * ZFS ACL (and owner ID, primary group ID).
359 347 */
360 348 bzero(&vsa, sizeof (vsa));
361 349 vsa.vsa_mask = VSA_ACE | VSA_ACECNT;
362 350 error = smbfs_acl_sd2zfs(sd, &vsa, &uid, &gid);
363 351 if (error)
364 352 goto out;
365 353
366 354 ASSERT(vsa.vsa_aclentp != NULL);
367 355 SMBVDEBUG("uid=%u, gid=%u", uid, gid);
368 356
369 357 /*
370 358 * Store the results in r_secattr, n_uid, n_gid
371 359 */
372 360 mutex_enter(&np->r_statelock);
373 361 ovsa = np->r_secattr;
374 362 np->r_secattr = vsa;
375 363 np->n_uid = uid;
376 364 np->n_gid = gid;
377 365 /*
378 366 * ACLs don't change frequently, so cache these
379 367 * for a relatively long time (ac dir max).
380 368 */
381 369 np->r_sectime = gethrtime() + smi->smi_acdirmax;
382 370 mutex_exit(&np->r_statelock);
383 371
384 372 /* Allocated in: smbfs_acl_sd2zfs */
385 373 if (ovsa.vsa_aclentp != NULL)
386 374 kmem_free(ovsa.vsa_aclentp, ovsa.vsa_aclentsz);
387 375
388 376 out:
389 377 if (sd != NULL)
390 378 smbfs_acl_free_sd(sd);
391 379 /* Note: m_freem(m) is done by... */
392 380 md_done(mdp);
393 381
394 382 return (error);
395 383 }
396 384
397 385 /*
398 386 * Helper for smbfsgetattr()
399 387 *
400 388 * Just refresh the ACL cache if needed,
401 389 * which updates n_uid/n_gid
402 390 */
403 391 int
404 392 smbfs_acl_getids(vnode_t *vp, cred_t *cr)
405 393 {
406 394 smbnode_t *np;
407 395 int error;
408 396
409 397 np = VTOSMB(vp);
410 398
411 399 /*
412 400 * NB: extended attribute files and directories
413 401 * do not have ACLs separate from the parent.
414 402 * Let the caller do ACL fabrication.
415 403 */
416 404 if (np->n_flag & N_XATTR)
417 405 return (ENOSYS);
418 406
419 407 mutex_enter(&np->r_statelock);
420 408 if (gethrtime() >= np->r_sectime) {
421 409 /* Need to update r_secattr */
422 410 mutex_exit(&np->r_statelock);
423 411 error = smbfs_acl_refresh(vp, cr);
424 412 return (error);
425 413 }
426 414 mutex_exit(&np->r_statelock);
427 415
428 416 return (0);
429 417 }
430 418
431 419 /*
432 420 * Helper for VOP_GETSECATTR
433 421 *
434 422 * Refresh the ACL cache if needed, then
435 423 * duplicate the requested parts of the vsecattr.
436 424 */
437 425 /* ARGSUSED */
438 426 int
439 427 smbfs_acl_getvsa(vnode_t *vp, vsecattr_t *vsa,
440 428 int flag, cred_t *cr)
441 429 {
442 430 smbnode_t *np;
443 431 int error;
444 432
445 433 np = VTOSMB(vp);
446 434
447 435 /*
448 436 * NB: extended attribute files and directories
449 437 * do not have ACLs separate from the parent.
450 438 * Let the caller do ACL fabrication.
451 439 */
452 440 if (np->n_flag & N_XATTR)
453 441 return (ENOSYS);
454 442
455 443 mutex_enter(&np->r_statelock);
456 444
457 445 if (np->r_secattr.vsa_aclentp == NULL ||
458 446 gethrtime() >= np->r_sectime) {
459 447 /* Need to update r_secattr */
460 448 mutex_exit(&np->r_statelock);
461 449
462 450 error = smbfs_acl_refresh(vp, cr);
463 451 if (error)
464 452 return (error);
465 453
466 454 mutex_enter(&np->r_statelock);
467 455 }
468 456 ASSERT(np->r_secattr.vsa_aclentp != NULL);
469 457
470 458 /*
471 459 * Duplicate requested parts of r_secattr
472 460 */
473 461
474 462 if (vsa->vsa_mask & VSA_ACECNT)
475 463 vsa->vsa_aclcnt = np->r_secattr.vsa_aclcnt;
476 464
477 465 if (vsa->vsa_mask & VSA_ACE) {
478 466 vsa->vsa_aclentsz = np->r_secattr.vsa_aclentsz;
479 467 vsa->vsa_aclentp = kmem_alloc(vsa->vsa_aclentsz, KM_SLEEP);
480 468 bcopy(np->r_secattr.vsa_aclentp, vsa->vsa_aclentp,
481 469 vsa->vsa_aclentsz);
482 470 }
483 471
484 472 mutex_exit(&np->r_statelock);
485 473 return (0);
486 474 }
487 475
488 476 /*
489 477 * Helper for smbfs_acl_setids, smbfs_acl_setvsa
490 478 */
491 479 static int
492 480 smbfs_acl_store(vnode_t *vp, vsecattr_t *vsa, uid_t uid, gid_t gid,
493 481 uint32_t selector, cred_t *cr)
494 482 {
495 483 mbchain_t *mbp, mb_store;
496 484 i_ntsd_t *sd;
497 485 int error;
498 486
499 487 ASSERT(selector != 0);
500 488
501 489 sd = NULL;
502 490 bzero(&mb_store, sizeof (mb_store));
503 491 mbp = &mb_store;
504 492
505 493 /*
506 494 * Convert a ZFS ACL (and owner ID, group ID)
507 495 * into an NT SD, internal form.
508 496 */
509 497 error = smbfs_acl_zfs2sd(vsa, uid, gid, selector, &sd);
510 498 if (error)
511 499 goto out;
512 500
513 501 /*
514 502 * Marshall the internal form SD into an
515 503 * OtW security descriptor.
516 504 */
517 505 (void) mb_init(mbp);
518 506 error = mb_put_ntsd(mbp, sd);
519 507 if (error)
520 508 goto out;
521 509
522 510 /*
523 511 * This does the OTW Set (and maybe open, close)
524 512 * It clears mb_top when consuming the message.
525 513 */
526 514 error = smbfs_setsd(vp, selector, &mbp->mb_top, cr);
527 515
528 516 out:
529 517 if (sd != NULL)
530 518 smbfs_acl_free_sd(sd);
531 519 mb_done(mbp);
532 520 return (error);
533 521 }
534 522
535 523 /*
536 524 * Helper for smbfs_setattr()
537 525 *
538 526 * Set the passed UID/GID as indicated by va_mask.
539 527 */
540 528 int
541 529 smbfs_acl_setids(vnode_t *vp, vattr_t *vap, cred_t *cr)
542 530 {
543 531 uid_t uid = (uid_t)-1;
544 532 gid_t gid = (uid_t)-1;
545 533 uint32_t selector = 0;
546 534 int error;
547 535
548 536 if (vap->va_mask & AT_UID) {
549 537 selector |= OWNER_SECURITY_INFORMATION;
550 538 uid = vap->va_uid;
551 539 }
552 540
553 541 if (vap->va_mask & AT_GID) {
554 542 selector |= GROUP_SECURITY_INFORMATION;
555 543 gid = vap->va_gid;
556 544 }
557 545
558 546 if (selector == 0)
559 547 return (0);
560 548
561 549 error = smbfs_acl_store(vp, NULL, uid, gid, selector, cr);
562 550 return (error);
563 551 }
564 552
565 553 /*
566 554 * Helper for VOP_SETSECATTR
567 555 * Convert ZFS to NT form, call smbfs_setsd.
568 556 */
569 557 /* ARGSUSED */
570 558 int
571 559 smbfs_acl_setvsa(vnode_t *vp, vsecattr_t *vsa,
572 560 int flag, cred_t *cr)
573 561 {
574 562 uint32_t selector = DACL_SECURITY_INFORMATION;
575 563 smbnode_t *np = VTOSMB(vp);
576 564 int error;
577 565
578 566 /*
579 567 * NB: extended attribute files and directories
580 568 * do not have ACLs separate from the parent.
581 569 */
582 570 if (np->n_flag & N_XATTR)
583 571 return (ENOSYS);
584 572
585 573 /*
586 574 * When handling ACE_OWNER or ACE_GROUP entries,
587 575 * we need the current owner and group.
588 576 */
589 577 error = smbfs_acl_getids(vp, cr);
590 578 if (error)
591 579 return (error);
592 580
593 581 error = smbfs_acl_store(vp, vsa, np->n_uid, np->n_gid, selector, cr);
594 582 return (error);
595 583 }
|
↓ open down ↓ |
387 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX