Print this page
NEX-16159 Time spent sharing SMB filesystems could be reduced by optimizing smb_getdataset for default mount points
Reviewed by: Sanjay Nadkarni <sanjay.nadkarni@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Reviewed by: Matt Barden <matt.barden@nexenta.com>
| Split |
Close |
| Expand all |
| Collapse all |
--- old/usr/src/lib/smbsrv/libmlsvc/common/srvsvc_sd.c
+++ new/usr/src/lib/smbsrv/libmlsvc/common/srvsvc_sd.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
|
↓ open down ↓ |
13 lines elided |
↑ open up ↑ |
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
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 (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
24 + * Copyright 2018 Nexenta Systems, Inc. All rights reserved.
24 25 */
25 26
26 27 /*
27 28 * This is a helper file to get/set Windows SD. This is used by
28 29 * SRVSVC service.
29 30 */
30 31 #include <strings.h>
31 32 #include <libzfs.h>
32 33
33 34 #include <smbsrv/libsmb.h>
34 35 #include <smbsrv/libmlsvc.h>
35 36 #include <smbsrv/ndl/srvsvc.ndl>
36 37
37 38 /* Size of offset members in mslm_security_descriptor structure */
38 39 #define SRVSVC_SD_OFFSET_SZ 16
39 40
40 41 #define SRVSVC_ACE_OFFSET 8
41 42 #define SRVSVC_SID_OFFSET 8
42 43
43 44 uint32_t srvsvc_sd_set_relative(smb_sd_t *, uint8_t *);
44 45
45 46 static uint32_t srvsvc_sd_get_autohome(const smb_share_t *, smb_sd_t *);
46 47 static uint32_t srvsvc_sd_status_to_error(uint32_t);
47 48 static uint32_t srvsvc_sd_set_absolute(uint8_t *, smb_sd_t *);
48 49
49 50 /*
50 51 * This method computes ACL on share path from a share name.
51 52 * Return 0 upon success, -1 upon failure.
|
↓ open down ↓ |
18 lines elided |
↑ open up ↑ |
52 53 */
53 54 static int
54 55 srvsvc_shareacl_getpath(smb_share_t *si, char *shr_acl_path)
55 56 {
56 57 char dataset[MAXPATHLEN];
57 58 char mp[ZFS_MAXPROPLEN];
58 59 libzfs_handle_t *libhd;
59 60 zfs_handle_t *zfshd;
60 61 int ret = 0;
61 62
62 - ret = smb_getdataset(si->shr_path, dataset, MAXPATHLEN);
63 - if (ret != 0)
64 - return (ret);
65 -
66 63 if ((libhd = libzfs_init()) == NULL)
67 64 return (-1);
68 65
66 + ret = smb_getdataset(libhd, si->shr_path, dataset, MAXPATHLEN);
67 + if (ret != 0) {
68 + libzfs_fini(libhd);
69 + return (ret);
70 + }
71 +
72 +
69 73 if ((zfshd = zfs_open(libhd, dataset, ZFS_TYPE_DATASET)) == NULL) {
70 74 libzfs_fini(libhd);
71 75 return (-1);
72 76 }
73 77
74 78 if (zfs_prop_get(zfshd, ZFS_PROP_MOUNTPOINT, mp, sizeof (mp), NULL,
75 79 NULL, 0, B_FALSE) != 0) {
76 80 zfs_close(zfshd);
77 81 libzfs_fini(libhd);
78 82 return (-1);
79 83 }
80 84
81 85 zfs_close(zfshd);
82 86 libzfs_fini(libhd);
83 87
84 88 (void) snprintf(shr_acl_path, MAXPATHLEN, "%s/.zfs/shares/%s",
85 89 mp, si->shr_name);
86 90
87 91 return (ret);
88 92 }
89 93
90 94 /*
91 95 * This method sets Security Descriptor on a share path.
92 96 *
93 97 * Returns:
94 98 * ERROR_SUCCESS
95 99 * ERROR_NOT_ENOUGH_MEMORY
96 100 * ERROR_INVALID_ACL
97 101 * ERROR_INVALID_SID
98 102 * ERROR_INVALID_SECURITY_DESCR
99 103 * ERROR_NONE_MAPPED
100 104 * ERROR_INTERNAL_ERROR
101 105 * ERROR_PATH_NOT_FOUND
102 106 */
103 107 uint32_t
104 108 srvsvc_sd_set(smb_share_t *si, uint8_t *sdbuf)
105 109 {
106 110 smb_sd_t sd;
107 111 uint32_t status = ERROR_SUCCESS;
108 112 char path[MAXPATHLEN];
109 113 int ret = 0;
110 114
111 115 ret = srvsvc_shareacl_getpath(si, path);
112 116 if (ret != 0)
113 117 return (ERROR_PATH_NOT_FOUND);
114 118
115 119 smb_sd_init(&sd, 0);
116 120 status = srvsvc_sd_set_absolute(sdbuf, &sd);
117 121 if (status != ERROR_SUCCESS) {
118 122 smb_sd_term(&sd);
119 123 return (status);
120 124 }
121 125
122 126 status = smb_sd_write(path, &sd, SMB_DACL_SECINFO);
123 127 status = srvsvc_sd_status_to_error(status);
124 128 smb_sd_term(&sd);
125 129
126 130 return (status);
127 131 }
128 132
129 133 /*
130 134 * This method returns a Security Descriptor of a share path in self relative
131 135 * format. Call to this function with NULL buffer, returns the size of the
132 136 * security descriptor, which can be used to allocate buffer.
133 137 *
134 138 * Returns:
135 139 * ERROR_SUCCESS
136 140 * ERROR_NOT_ENOUGH_MEMORY
137 141 * ERROR_INVALID_ACL
138 142 * ERROR_INVALID_SID
139 143 * ERROR_INVALID_SECURITY_DESCR
140 144 * ERROR_INVALID_PARAMETER
141 145 * ERROR_NONE_MAPPED
142 146 * ERROR_INTERNAL_ERROR
143 147 * ERROR_PATH_NOT_FOUND
144 148 */
145 149 uint32_t
146 150 srvsvc_sd_get(smb_share_t *si, uint8_t *sdbuf, uint32_t *size)
147 151 {
148 152 smb_sd_t sd;
149 153 uint32_t status = ERROR_SUCCESS;
150 154 char path[MAXPATHLEN];
151 155 int ret = 0;
152 156
153 157 if (sdbuf == NULL && size == NULL)
154 158 return (ERROR_INVALID_PARAMETER);
155 159
156 160 bzero(&sd, sizeof (smb_sd_t));
157 161
158 162 if (si->shr_flags & SMB_SHRF_AUTOHOME) {
159 163 status = srvsvc_sd_get_autohome(si, &sd);
160 164 } else {
161 165 ret = srvsvc_shareacl_getpath(si, path);
162 166 if (ret != 0)
163 167 return (ERROR_PATH_NOT_FOUND);
164 168
165 169 status = smb_sd_read(path, &sd, SMB_ALL_SECINFO);
166 170 status = srvsvc_sd_status_to_error(status);
167 171 }
168 172
169 173 if (status != ERROR_SUCCESS) {
170 174 smb_sd_term(&sd);
171 175 return (status);
172 176 }
173 177
174 178 if (sdbuf == NULL) {
175 179 *size = smb_sd_len(&sd, SMB_ALL_SECINFO);
176 180 smb_sd_term(&sd);
177 181 return (status);
178 182 }
179 183
180 184 status = srvsvc_sd_set_relative(&sd, sdbuf);
181 185
182 186 smb_sd_term(&sd);
183 187 return (status);
184 188 }
185 189
186 190 static uint32_t
187 191 srvsvc_sd_get_autohome(const smb_share_t *si, smb_sd_t *sd)
188 192 {
189 193 smb_fssd_t fs_sd;
190 194 acl_t *acl;
191 195 uint32_t status;
192 196
193 197 if (acl_fromtext("owner@:rwxpdDaARWcCos::allow", &acl) != 0)
194 198 return (ERROR_NOT_ENOUGH_MEMORY);
195 199
196 200 smb_fssd_init(&fs_sd, SMB_ALL_SECINFO, SMB_FSSD_FLAGS_DIR);
197 201 fs_sd.sd_uid = si->shr_uid;
198 202 fs_sd.sd_gid = si->shr_gid;
199 203 fs_sd.sd_zdacl = acl;
200 204 fs_sd.sd_zsacl = NULL;
201 205
202 206 status = smb_sd_fromfs(&fs_sd, sd);
203 207 status = srvsvc_sd_status_to_error(status);
204 208 smb_fssd_term(&fs_sd);
205 209 return (status);
206 210 }
207 211
208 212 /*
209 213 * This method converts an ACE from absolute (pointer) to
210 214 * self relative (flat buffer) format.
211 215 *
212 216 * Returns Win32 error codes.
213 217 */
214 218 static uint32_t
215 219 srvsvc_ace_set_relative(mslm_ace_t *m_ace, struct mslm_sid *m_sid,
216 220 smb_ace_t *ace)
217 221 {
218 222 if ((m_ace == NULL) || (ace == NULL))
219 223 return (ERROR_INVALID_PARAMETER);
220 224
221 225 bcopy(&ace->se_hdr, &m_ace->header, sizeof (mslm_ace_hdr_t));
222 226 m_ace->mask = ace->se_mask;
223 227
224 228 if ((ace->se_sid == NULL) || (m_sid == NULL))
225 229 return (ERROR_INVALID_PARAMETER);
226 230 bcopy(ace->se_sid, m_sid, smb_sid_len(ace->se_sid));
227 231
228 232 return (ERROR_SUCCESS);
229 233 }
230 234
231 235 /*
232 236 * This method converts an ACL from absolute (pointer) to
233 237 * self relative (flat buffer) format.
234 238 *
235 239 * Returns an initialized mslm_acl structure on success.
236 240 * Returns NULL on failure.
237 241 */
238 242 static struct mslm_acl *
239 243 srvsvc_acl_set_relative(uint8_t *sdbuf, smb_acl_t *acl)
240 244 {
241 245 struct mslm_acl *m_acl;
242 246
243 247 if (sdbuf == NULL)
244 248 return (NULL);
245 249
246 250 /*LINTED E_BAD_PTR_CAST_ALIGN*/
247 251 m_acl = (struct mslm_acl *)sdbuf;
248 252 m_acl->revision = acl->sl_revision;
249 253 m_acl->sbz1 = 0;
250 254 m_acl->size = acl->sl_bsize;
251 255 m_acl->sbz2 = 0;
252 256 m_acl->ace_count = acl->sl_acecnt;
253 257
254 258 return (m_acl);
255 259 }
256 260
257 261 /*
258 262 * This method converts Security Descriptor from absolute (pointer) to
259 263 * self relative (flat buffer) format.
260 264 *
261 265 * Returns Win32 error codes.
262 266 */
263 267 uint32_t
264 268 srvsvc_sd_set_relative(smb_sd_t *sd, uint8_t *sdbuf)
265 269 {
266 270 mslm_security_descriptor_t *msd;
267 271 int offset, len, i;
268 272 smb_ace_t *ace;
269 273 mslm_ace_t *m_ace;
270 274 struct mslm_sid *m_sid;
271 275 uint16_t ace_cnt;
272 276 uint32_t status = ERROR_SUCCESS;
273 277
274 278 /*LINTED E_BAD_PTR_CAST_ALIGN*/
275 279 msd = (mslm_security_descriptor_t *)sdbuf;
276 280 if (msd == NULL)
277 281 return (ERROR_INVALID_SECURITY_DESCR);
278 282
279 283 msd->revision = sd->sd_revision;
280 284 msd->sbz1 = 0;
281 285 msd->control = sd->sd_control | SE_SELF_RELATIVE;
282 286
283 287 offset = sizeof (mslm_security_descriptor_t) - SRVSVC_SD_OFFSET_SZ;
284 288 msd->offset_owner = msd->offset_group = 0;
285 289 msd->offset_sacl = msd->offset_dacl = 0;
286 290
287 291 if (sd->sd_owner != NULL) {
288 292 msd->offset_owner = offset;
289 293
290 294 if (sd->sd_owner == NULL)
291 295 return (ERROR_NOT_ENOUGH_MEMORY);
292 296
293 297 len = smb_sid_len(sd->sd_owner);
294 298 bcopy(sd->sd_owner, &sdbuf[offset], len);
295 299 offset += len;
296 300 }
297 301
298 302 if (sd->sd_group != NULL) {
299 303 msd->offset_group = offset;
300 304
301 305 if (sd->sd_group == NULL)
302 306 return (ERROR_NOT_ENOUGH_MEMORY);
303 307
304 308 len = smb_sid_len(sd->sd_group);
305 309 bcopy(sd->sd_group, &sdbuf[offset], len);
306 310 offset += len;
307 311 }
308 312
309 313 if (sd->sd_sacl != NULL) {
310 314 msd->offset_sacl = offset;
311 315 msd->sacl = srvsvc_acl_set_relative(&sdbuf[offset],
312 316 sd->sd_sacl);
313 317 if (msd->sacl == NULL)
314 318 return (ERROR_INVALID_PARAMETER);
315 319
316 320 ace = sd->sd_sacl->sl_aces;
317 321 ace_cnt = msd->sacl->ace_count;
318 322 offset += SRVSVC_ACE_OFFSET;
319 323
320 324 for (i = 0; i < ace_cnt; i++, ace++) {
321 325 /*LINTED E_BAD_PTR_CAST_ALIGN*/
322 326 m_ace = (mslm_ace_t *)&sdbuf[offset];
323 327 offset += SRVSVC_SID_OFFSET;
324 328 /*LINTED E_BAD_PTR_CAST_ALIGN*/
325 329 m_sid = (struct mslm_sid *)&sdbuf[offset];
326 330
327 331 status = srvsvc_ace_set_relative(m_ace, m_sid, ace);
328 332 if (status != ERROR_SUCCESS)
329 333 return (status);
330 334 offset += smb_sid_len(ace->se_sid);
331 335 }
332 336 }
333 337
334 338 if (sd->sd_dacl != NULL) {
335 339 msd->offset_dacl = offset;
336 340 msd->dacl = srvsvc_acl_set_relative(&sdbuf[offset],
337 341 sd->sd_dacl);
338 342 if (msd->dacl == NULL)
339 343 return (ERROR_INVALID_PARAMETER);
340 344
341 345 ace = sd->sd_dacl->sl_aces;
342 346 ace_cnt = msd->dacl->ace_count;
343 347 offset += SRVSVC_ACE_OFFSET;
344 348
345 349 for (i = 0; i < ace_cnt; i++, ace++) {
346 350 /*LINTED E_BAD_PTR_CAST_ALIGN*/
347 351 m_ace = (mslm_ace_t *)&sdbuf[offset];
348 352 offset += SRVSVC_SID_OFFSET;
349 353 /*LINTED E_BAD_PTR_CAST_ALIGN*/
350 354 m_sid = (struct mslm_sid *)&sdbuf[offset];
351 355
352 356 status = srvsvc_ace_set_relative(m_ace, m_sid, ace);
353 357 if (status != ERROR_SUCCESS)
354 358 return (status);
355 359 offset += smb_sid_len(ace->se_sid);
356 360 }
357 361 }
358 362
359 363 return (status);
360 364 }
361 365
362 366 /*
363 367 * This method converts an ACE from self relative (flat buffer) to
364 368 * absolute (pointer) format.
365 369 *
366 370 * Returns Win32 error codes.
367 371 */
368 372 static uint32_t
369 373 srvsvc_ace_set_absolute(mslm_ace_t *m_ace, struct mslm_sid *m_sid,
370 374 smb_ace_t *ace)
371 375 {
372 376 int sid_size = 0;
373 377 if ((m_ace == NULL) || (ace == NULL) || (m_sid == NULL))
374 378 return (ERROR_INVALID_PARAMETER);
375 379
376 380 bzero(ace, sizeof (smb_ace_t));
377 381 bcopy(&m_ace->header, &ace->se_hdr, sizeof (mslm_ace_hdr_t));
378 382 ace->se_mask = m_ace->mask;
379 383
380 384 sid_size = smb_sid_len((smb_sid_t *)m_sid);
381 385 if ((ace->se_sid = malloc(sid_size)) == NULL)
382 386 return (ERROR_NOT_ENOUGH_MEMORY);
383 387 bcopy(m_sid, ace->se_sid, sid_size);
384 388
385 389 return (ERROR_SUCCESS);
386 390 }
387 391
388 392 /*
389 393 * This method converts an ACL from self relative (flat buffer) to
390 394 * absolute (pointer) format.
391 395 *
392 396 * Returns an initialized smb_acl_t structure on success.
393 397 * Returns NULL on failure.
394 398 */
395 399 static smb_acl_t *
396 400 srvsvc_acl_set_absolute(uint8_t *sdbuf, int *offset)
397 401 {
398 402 uint8_t rev;
399 403 uint16_t sz, ace_cnt;
400 404 smb_acl_t *acl;
401 405
402 406 bcopy(&sdbuf[*offset], &rev, sizeof (uint8_t));
403 407 *offset += 2; /* Pad for Sbz1 */
404 408 bcopy(&sdbuf[*offset], &sz, sizeof (uint16_t));
405 409 *offset += 2;
406 410 bcopy(&sdbuf[*offset], &ace_cnt, sizeof (uint16_t));
407 411 *offset += 4; /* Pad for Sbz2 */
408 412
409 413 acl = smb_acl_alloc(rev, sz, ace_cnt);
410 414
411 415 return (acl);
412 416 }
413 417
414 418 /*
415 419 * This method converts Security Descriptor from self relative (flat buffer) to
416 420 * absolute (pointer) format.
417 421 *
418 422 * Returns Win32 error codes.
419 423 */
420 424 static uint32_t
421 425 srvsvc_sd_set_absolute(uint8_t *sdbuf, smb_sd_t *sd)
422 426 {
423 427 mslm_security_descriptor_t *msd;
424 428 mslm_ace_t *m_ace;
425 429 struct mslm_sid *m_sid;
426 430 smb_ace_t *ace;
427 431 uint16_t ace_cnt;
428 432 int offset, i, sid_size;
429 433 uint32_t status = ERROR_SUCCESS;
430 434
431 435 if (sdbuf == NULL)
432 436 return (ERROR_INVALID_SECURITY_DESCR);
433 437
434 438 /*LINTED E_BAD_PTR_CAST_ALIGN*/
435 439 msd = (mslm_security_descriptor_t *)sdbuf;
436 440
437 441 sd->sd_revision = msd->revision;
438 442 sd->sd_control = msd->control & (~SE_SELF_RELATIVE);
439 443
440 444 if (msd->offset_owner != 0) {
441 445 /*LINTED E_BAD_PTR_CAST_ALIGN*/
442 446 m_sid = (struct mslm_sid *)&sdbuf[msd->offset_owner];
443 447 sid_size = smb_sid_len((smb_sid_t *)m_sid);
444 448
445 449 if ((sd->sd_owner = malloc(sid_size)) == NULL)
446 450 return (ERROR_NOT_ENOUGH_MEMORY);
447 451 bcopy(m_sid, sd->sd_owner, sid_size);
448 452 }
449 453
450 454 if (msd->offset_group != 0) {
451 455 /*LINTED E_BAD_PTR_CAST_ALIGN*/
452 456 m_sid = (struct mslm_sid *)&sdbuf[msd->offset_group];
453 457 sid_size = smb_sid_len((smb_sid_t *)m_sid);
454 458
455 459 if ((sd->sd_group = malloc(sid_size)) == NULL)
456 460 return (ERROR_NOT_ENOUGH_MEMORY);
457 461 bcopy(m_sid, sd->sd_group, sid_size);
458 462 }
459 463
460 464 if (msd->offset_sacl != 0) {
461 465 offset = msd->offset_sacl;
462 466 sd->sd_sacl = srvsvc_acl_set_absolute(sdbuf, &offset);
463 467 if (sd->sd_sacl == NULL)
464 468 return (ERROR_NOT_ENOUGH_MEMORY);
465 469
466 470 ace = sd->sd_sacl->sl_aces;
467 471 ace_cnt = sd->sd_sacl->sl_acecnt;
468 472
469 473 for (i = 0; i < ace_cnt; i++, ace++) {
470 474 /*LINTED E_BAD_PTR_CAST_ALIGN*/
471 475 m_ace = (mslm_ace_t *)&sdbuf[offset];
472 476 offset += SRVSVC_SID_OFFSET;
473 477 /*LINTED E_BAD_PTR_CAST_ALIGN*/
474 478 m_sid = (struct mslm_sid *)&sdbuf[offset];
475 479
476 480 status = srvsvc_ace_set_absolute(m_ace, m_sid, ace);
477 481 if (status != ERROR_SUCCESS)
478 482 return (status);
479 483 offset += smb_sid_len(ace->se_sid);
480 484 }
481 485 }
482 486
483 487 if (msd->offset_dacl != 0) {
484 488 offset = msd->offset_dacl;
485 489 sd->sd_dacl = srvsvc_acl_set_absolute(sdbuf, &offset);
486 490 if (sd->sd_dacl == NULL)
487 491 return (ERROR_NOT_ENOUGH_MEMORY);
488 492
489 493 ace = sd->sd_dacl->sl_aces;
490 494 ace_cnt = sd->sd_dacl->sl_acecnt;
491 495
492 496 for (i = 0; i < ace_cnt; i++, ace++) {
493 497 /*LINTED E_BAD_PTR_CAST_ALIGN*/
494 498 m_ace = (mslm_ace_t *)&sdbuf[offset];
495 499 offset += SRVSVC_SID_OFFSET;
496 500 /*LINTED E_BAD_PTR_CAST_ALIGN*/
497 501 m_sid = (struct mslm_sid *)&sdbuf[offset];
498 502
499 503 status = srvsvc_ace_set_absolute(m_ace, m_sid, ace);
500 504 if (status != ERROR_SUCCESS)
501 505 return (status);
502 506 offset += smb_sid_len(ace->se_sid);
503 507 }
504 508 }
505 509
506 510 return (status);
507 511 }
508 512
509 513 /*
510 514 * This method maps NT status codes into Win 32 error codes.
511 515 * This method operates on status codes that are related
512 516 * to processing of Security Descriptor.
513 517 */
514 518 static uint32_t
515 519 srvsvc_sd_status_to_error(uint32_t status)
516 520 {
517 521 int i;
518 522 static struct {
519 523 uint32_t nt_status;
520 524 uint32_t err_code;
521 525 } errmap[] = {
522 526 { NT_STATUS_SUCCESS, ERROR_SUCCESS },
523 527 { NT_STATUS_INVALID_ACL, ERROR_INVALID_ACL },
524 528 { NT_STATUS_INVALID_SID, ERROR_INVALID_SID },
525 529 { NT_STATUS_NONE_MAPPED, ERROR_NONE_MAPPED }
526 530 };
527 531
528 532 for (i = 0; i < (sizeof (errmap) / sizeof (errmap[0])); ++i) {
529 533 if (status == errmap[i].nt_status)
530 534 return (errmap[i].err_code);
531 535 }
532 536
533 537 return (ERROR_INTERNAL_ERROR);
534 538 }
|
↓ open down ↓ |
456 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX