aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs/cifsacl.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/cifs/cifsacl.c')
-rw-r--r--fs/cifs/cifsacl.c535
1 files changed, 94 insertions, 441 deletions
diff --git a/fs/cifs/cifsacl.c b/fs/cifs/cifsacl.c
index 42b3fe981a0..f4508ee4e80 100644
--- a/fs/cifs/cifsacl.c
+++ b/fs/cifs/cifsacl.c
@@ -44,128 +44,6 @@ static const struct cifs_sid sid_user = {1, 2 , {0, 0, 0, 0, 0, 5}, {} };
44 44
45static const struct cred *root_cred; 45static const struct cred *root_cred;
46 46
47static void
48shrink_idmap_tree(struct rb_root *root, int nr_to_scan, int *nr_rem,
49 int *nr_del)
50{
51 struct rb_node *node;
52 struct rb_node *tmp;
53 struct cifs_sid_id *psidid;
54
55 node = rb_first(root);
56 while (node) {
57 tmp = node;
58 node = rb_next(tmp);
59 psidid = rb_entry(tmp, struct cifs_sid_id, rbnode);
60 if (nr_to_scan == 0 || *nr_del == nr_to_scan)
61 ++(*nr_rem);
62 else {
63 if (time_after(jiffies, psidid->time + SID_MAP_EXPIRE)
64 && psidid->refcount == 0) {
65 rb_erase(tmp, root);
66 ++(*nr_del);
67 } else
68 ++(*nr_rem);
69 }
70 }
71}
72
73/*
74 * Run idmap cache shrinker.
75 */
76static int
77cifs_idmap_shrinker(struct shrinker *shrink, struct shrink_control *sc)
78{
79 int nr_to_scan = sc->nr_to_scan;
80 int nr_del = 0;
81 int nr_rem = 0;
82 struct rb_root *root;
83
84 root = &uidtree;
85 spin_lock(&siduidlock);
86 shrink_idmap_tree(root, nr_to_scan, &nr_rem, &nr_del);
87 spin_unlock(&siduidlock);
88
89 root = &gidtree;
90 spin_lock(&sidgidlock);
91 shrink_idmap_tree(root, nr_to_scan, &nr_rem, &nr_del);
92 spin_unlock(&sidgidlock);
93
94 root = &siduidtree;
95 spin_lock(&uidsidlock);
96 shrink_idmap_tree(root, nr_to_scan, &nr_rem, &nr_del);
97 spin_unlock(&uidsidlock);
98
99 root = &sidgidtree;
100 spin_lock(&gidsidlock);
101 shrink_idmap_tree(root, nr_to_scan, &nr_rem, &nr_del);
102 spin_unlock(&gidsidlock);
103
104 return nr_rem;
105}
106
107static void
108sid_rb_insert(struct rb_root *root, unsigned long cid,
109 struct cifs_sid_id **psidid, char *typestr)
110{
111 char *strptr;
112 struct rb_node *node = root->rb_node;
113 struct rb_node *parent = NULL;
114 struct rb_node **linkto = &(root->rb_node);
115 struct cifs_sid_id *lsidid;
116
117 while (node) {
118 lsidid = rb_entry(node, struct cifs_sid_id, rbnode);
119 parent = node;
120 if (cid > lsidid->id) {
121 linkto = &(node->rb_left);
122 node = node->rb_left;
123 }
124 if (cid < lsidid->id) {
125 linkto = &(node->rb_right);
126 node = node->rb_right;
127 }
128 }
129
130 (*psidid)->id = cid;
131 (*psidid)->time = jiffies - (SID_MAP_RETRY + 1);
132 (*psidid)->refcount = 0;
133
134 sprintf((*psidid)->sidstr, "%s", typestr);
135 strptr = (*psidid)->sidstr + strlen((*psidid)->sidstr);
136 sprintf(strptr, "%ld", cid);
137
138 clear_bit(SID_ID_PENDING, &(*psidid)->state);
139 clear_bit(SID_ID_MAPPED, &(*psidid)->state);
140
141 rb_link_node(&(*psidid)->rbnode, parent, linkto);
142 rb_insert_color(&(*psidid)->rbnode, root);
143}
144
145static struct cifs_sid_id *
146sid_rb_search(struct rb_root *root, unsigned long cid)
147{
148 struct rb_node *node = root->rb_node;
149 struct cifs_sid_id *lsidid;
150
151 while (node) {
152 lsidid = rb_entry(node, struct cifs_sid_id, rbnode);
153 if (cid > lsidid->id)
154 node = node->rb_left;
155 else if (cid < lsidid->id)
156 node = node->rb_right;
157 else /* node found */
158 return lsidid;
159 }
160
161 return NULL;
162}
163
164static struct shrinker cifs_shrinker = {
165 .shrink = cifs_idmap_shrinker,
166 .seeks = DEFAULT_SEEKS,
167};
168
169static int 47static int
170cifs_idmap_key_instantiate(struct key *key, struct key_preparsed_payload *prep) 48cifs_idmap_key_instantiate(struct key *key, struct key_preparsed_payload *prep)
171{ 49{
@@ -195,30 +73,39 @@ static struct key_type cifs_idmap_key_type = {
195 .match = user_match, 73 .match = user_match,
196}; 74};
197 75
198static void 76static char *
199sid_to_str(struct cifs_sid *sidptr, char *sidstr) 77sid_to_key_str(struct cifs_sid *sidptr, unsigned int type)
200{ 78{
201 int i; 79 int i, len;
202 unsigned int saval; 80 unsigned int saval;
203 char *strptr; 81 char *sidstr, *strptr;
204 82
205 strptr = sidstr; 83 /* 3 bytes for prefix */
84 sidstr = kmalloc(3 + SID_STRING_BASE_SIZE +
85 (SID_STRING_SUBAUTH_SIZE * sidptr->num_subauth),
86 GFP_KERNEL);
87 if (!sidstr)
88 return sidstr;
206 89
207 sprintf(strptr, "S-%hhu", sidptr->revision); 90 strptr = sidstr;
208 strptr = sidstr + strlen(sidstr); 91 len = sprintf(strptr, "%cs:S-%hhu", type == SIDOWNER ? 'o' : 'g',
92 sidptr->revision);
93 strptr += len;
209 94
210 for (i = 0; i < NUM_AUTHS; ++i) { 95 for (i = 0; i < NUM_AUTHS; ++i) {
211 if (sidptr->authority[i]) { 96 if (sidptr->authority[i]) {
212 sprintf(strptr, "-%hhu", sidptr->authority[i]); 97 len = sprintf(strptr, "-%hhu", sidptr->authority[i]);
213 strptr = sidstr + strlen(sidstr); 98 strptr += len;
214 } 99 }
215 } 100 }
216 101
217 for (i = 0; i < sidptr->num_subauth; ++i) { 102 for (i = 0; i < sidptr->num_subauth; ++i) {
218 saval = le32_to_cpu(sidptr->sub_auth[i]); 103 saval = le32_to_cpu(sidptr->sub_auth[i]);
219 sprintf(strptr, "-%u", saval); 104 len = sprintf(strptr, "-%u", saval);
220 strptr = sidstr + strlen(sidstr); 105 strptr += len;
221 } 106 }
107
108 return sidstr;
222} 109}
223 110
224/* 111/*
@@ -284,184 +171,38 @@ cifs_copy_sid(struct cifs_sid *dst, const struct cifs_sid *src)
284 dst->sub_auth[i] = src->sub_auth[i]; 171 dst->sub_auth[i] = src->sub_auth[i];
285} 172}
286 173
287static void
288id_rb_insert(struct rb_root *root, struct cifs_sid *sidptr,
289 struct cifs_sid_id **psidid, char *typestr)
290{
291 int rc;
292 char *strptr;
293 struct rb_node *node = root->rb_node;
294 struct rb_node *parent = NULL;
295 struct rb_node **linkto = &(root->rb_node);
296 struct cifs_sid_id *lsidid;
297
298 while (node) {
299 lsidid = rb_entry(node, struct cifs_sid_id, rbnode);
300 parent = node;
301 rc = compare_sids(sidptr, &((lsidid)->sid));
302 if (rc > 0) {
303 linkto = &(node->rb_left);
304 node = node->rb_left;
305 } else if (rc < 0) {
306 linkto = &(node->rb_right);
307 node = node->rb_right;
308 }
309 }
310
311 cifs_copy_sid(&(*psidid)->sid, sidptr);
312 (*psidid)->time = jiffies - (SID_MAP_RETRY + 1);
313 (*psidid)->refcount = 0;
314
315 sprintf((*psidid)->sidstr, "%s", typestr);
316 strptr = (*psidid)->sidstr + strlen((*psidid)->sidstr);
317 sid_to_str(&(*psidid)->sid, strptr);
318
319 clear_bit(SID_ID_PENDING, &(*psidid)->state);
320 clear_bit(SID_ID_MAPPED, &(*psidid)->state);
321
322 rb_link_node(&(*psidid)->rbnode, parent, linkto);
323 rb_insert_color(&(*psidid)->rbnode, root);
324}
325
326static struct cifs_sid_id *
327id_rb_search(struct rb_root *root, struct cifs_sid *sidptr)
328{
329 int rc;
330 struct rb_node *node = root->rb_node;
331 struct cifs_sid_id *lsidid;
332
333 while (node) {
334 lsidid = rb_entry(node, struct cifs_sid_id, rbnode);
335 rc = compare_sids(sidptr, &((lsidid)->sid));
336 if (rc > 0) {
337 node = node->rb_left;
338 } else if (rc < 0) {
339 node = node->rb_right;
340 } else /* node found */
341 return lsidid;
342 }
343
344 return NULL;
345}
346
347static int
348sidid_pending_wait(void *unused)
349{
350 schedule();
351 return signal_pending(current) ? -ERESTARTSYS : 0;
352}
353
354static int 174static int
355id_to_sid(unsigned long cid, uint sidtype, struct cifs_sid *ssid) 175id_to_sid(unsigned int cid, uint sidtype, struct cifs_sid *ssid)
356{ 176{
357 int rc = 0; 177 int rc;
358 struct key *sidkey; 178 struct key *sidkey;
179 char desc[3 + 10 + 1]; /* 3 byte prefix + 10 bytes for value + NULL */
359 const struct cred *saved_cred; 180 const struct cred *saved_cred;
360 struct cifs_sid *lsid;
361 struct cifs_sid_id *psidid, *npsidid;
362 struct rb_root *cidtree;
363 spinlock_t *cidlock;
364
365 if (sidtype == SIDOWNER) {
366 cidlock = &siduidlock;
367 cidtree = &uidtree;
368 } else if (sidtype == SIDGROUP) {
369 cidlock = &sidgidlock;
370 cidtree = &gidtree;
371 } else
372 return -EINVAL;
373
374 spin_lock(cidlock);
375 psidid = sid_rb_search(cidtree, cid);
376
377 if (!psidid) { /* node does not exist, allocate one & attempt adding */
378 spin_unlock(cidlock);
379 npsidid = kzalloc(sizeof(struct cifs_sid_id), GFP_KERNEL);
380 if (!npsidid)
381 return -ENOMEM;
382
383 npsidid->sidstr = kmalloc(SID_STRING_MAX, GFP_KERNEL);
384 if (!npsidid->sidstr) {
385 kfree(npsidid);
386 return -ENOMEM;
387 }
388
389 spin_lock(cidlock);
390 psidid = sid_rb_search(cidtree, cid);
391 if (psidid) { /* node happened to get inserted meanwhile */
392 ++psidid->refcount;
393 spin_unlock(cidlock);
394 kfree(npsidid->sidstr);
395 kfree(npsidid);
396 } else {
397 psidid = npsidid;
398 sid_rb_insert(cidtree, cid, &psidid,
399 sidtype == SIDOWNER ? "oi:" : "gi:");
400 ++psidid->refcount;
401 spin_unlock(cidlock);
402 }
403 } else {
404 ++psidid->refcount;
405 spin_unlock(cidlock);
406 }
407 181
408 /* 182 rc = snprintf(desc, sizeof(desc), "%ci:%u",
409 * If we are here, it is safe to access psidid and its fields 183 sidtype == SIDOWNER ? 'o' : 'g', cid);
410 * since a reference was taken earlier while holding the spinlock. 184 if (rc >= sizeof(desc))
411 * A reference on the node is put without holding the spinlock 185 return -EINVAL;
412 * and it is OK to do so in this case, shrinker will not erase
413 * this node until all references are put and we do not access
414 * any fields of the node after a reference is put .
415 */
416 if (test_bit(SID_ID_MAPPED, &psidid->state)) {
417 cifs_copy_sid(ssid, &psidid->sid);
418 psidid->time = jiffies; /* update ts for accessing */
419 goto id_sid_out;
420 }
421 186
422 if (time_after(psidid->time + SID_MAP_RETRY, jiffies)) { 187 rc = 0;
188 saved_cred = override_creds(root_cred);
189 sidkey = request_key(&cifs_idmap_key_type, desc, "");
190 if (IS_ERR(sidkey)) {
423 rc = -EINVAL; 191 rc = -EINVAL;
424 goto id_sid_out; 192 cFYI(1, "%s: Can't map %cid %u to a SID", __func__,
425 } 193 sidtype == SIDOWNER ? 'u' : 'g', cid);
426 194 goto out_revert_creds;
427 if (!test_and_set_bit(SID_ID_PENDING, &psidid->state)) { 195 } else if (sidkey->datalen < CIFS_SID_BASE_SIZE) {
428 saved_cred = override_creds(root_cred); 196 rc = -EIO;
429 sidkey = request_key(&cifs_idmap_key_type, psidid->sidstr, ""); 197 cFYI(1, "%s: Downcall contained malformed key "
430 if (IS_ERR(sidkey)) { 198 "(datalen=%hu)", __func__, sidkey->datalen);
431 rc = -EINVAL; 199 goto out_key_put;
432 cFYI(1, "%s: Can't map and id to a SID", __func__); 200 }
433 } else if (sidkey->datalen < CIFS_SID_BASE_SIZE) { 201 cifs_copy_sid(ssid, (struct cifs_sid *)sidkey->payload.data);
434 rc = -EIO; 202out_key_put:
435 cFYI(1, "%s: Downcall contained malformed key " 203 key_put(sidkey);
436 "(datalen=%hu)", __func__, sidkey->datalen); 204out_revert_creds:
437 } else { 205 revert_creds(saved_cred);
438 lsid = (struct cifs_sid *)sidkey->payload.data;
439 cifs_copy_sid(&psidid->sid, lsid);
440 cifs_copy_sid(ssid, &psidid->sid);
441 set_bit(SID_ID_MAPPED, &psidid->state);
442 key_put(sidkey);
443 kfree(psidid->sidstr);
444 }
445 psidid->time = jiffies; /* update ts for accessing */
446 revert_creds(saved_cred);
447 clear_bit(SID_ID_PENDING, &psidid->state);
448 wake_up_bit(&psidid->state, SID_ID_PENDING);
449 } else {
450 rc = wait_on_bit(&psidid->state, SID_ID_PENDING,
451 sidid_pending_wait, TASK_INTERRUPTIBLE);
452 if (rc) {
453 cFYI(1, "%s: sidid_pending_wait interrupted %d",
454 __func__, rc);
455 --psidid->refcount;
456 return rc;
457 }
458 if (test_bit(SID_ID_MAPPED, &psidid->state))
459 cifs_copy_sid(ssid, &psidid->sid);
460 else
461 rc = -EINVAL;
462 }
463id_sid_out:
464 --psidid->refcount;
465 return rc; 206 return rc;
466} 207}
467 208
@@ -470,111 +211,66 @@ sid_to_id(struct cifs_sb_info *cifs_sb, struct cifs_sid *psid,
470 struct cifs_fattr *fattr, uint sidtype) 211 struct cifs_fattr *fattr, uint sidtype)
471{ 212{
472 int rc; 213 int rc;
473 unsigned long cid; 214 struct key *sidkey;
474 struct key *idkey; 215 char *sidstr;
475 const struct cred *saved_cred; 216 const struct cred *saved_cred;
476 struct cifs_sid_id *psidid, *npsidid; 217 uid_t fuid = cifs_sb->mnt_uid;
477 struct rb_root *cidtree; 218 gid_t fgid = cifs_sb->mnt_gid;
478 spinlock_t *cidlock;
479
480 if (sidtype == SIDOWNER) {
481 cid = cifs_sb->mnt_uid; /* default uid, in case upcall fails */
482 cidlock = &siduidlock;
483 cidtree = &uidtree;
484 } else if (sidtype == SIDGROUP) {
485 cid = cifs_sb->mnt_gid; /* default gid, in case upcall fails */
486 cidlock = &sidgidlock;
487 cidtree = &gidtree;
488 } else
489 return -ENOENT;
490
491 spin_lock(cidlock);
492 psidid = id_rb_search(cidtree, psid);
493
494 if (!psidid) { /* node does not exist, allocate one & attempt adding */
495 spin_unlock(cidlock);
496 npsidid = kzalloc(sizeof(struct cifs_sid_id), GFP_KERNEL);
497 if (!npsidid)
498 return -ENOMEM;
499
500 npsidid->sidstr = kmalloc(SID_STRING_MAX, GFP_KERNEL);
501 if (!npsidid->sidstr) {
502 kfree(npsidid);
503 return -ENOMEM;
504 }
505
506 spin_lock(cidlock);
507 psidid = id_rb_search(cidtree, psid);
508 if (psidid) { /* node happened to get inserted meanwhile */
509 ++psidid->refcount;
510 spin_unlock(cidlock);
511 kfree(npsidid->sidstr);
512 kfree(npsidid);
513 } else {
514 psidid = npsidid;
515 id_rb_insert(cidtree, psid, &psidid,
516 sidtype == SIDOWNER ? "os:" : "gs:");
517 ++psidid->refcount;
518 spin_unlock(cidlock);
519 }
520 } else {
521 ++psidid->refcount;
522 spin_unlock(cidlock);
523 }
524 219
525 /* 220 /*
526 * If we are here, it is safe to access psidid and its fields 221 * If we have too many subauthorities, then something is really wrong.
527 * since a reference was taken earlier while holding the spinlock. 222 * Just return an error.
528 * A reference on the node is put without holding the spinlock
529 * and it is OK to do so in this case, shrinker will not erase
530 * this node until all references are put and we do not access
531 * any fields of the node after a reference is put .
532 */ 223 */
533 if (test_bit(SID_ID_MAPPED, &psidid->state)) { 224 if (unlikely(psid->num_subauth > SID_MAX_SUB_AUTHORITIES)) {
534 cid = psidid->id; 225 cFYI(1, "%s: %u subauthorities is too many!", __func__,
535 psidid->time = jiffies; /* update ts for accessing */ 226 psid->num_subauth);
536 goto sid_to_id_out; 227 return -EIO;
537 } 228 }
538 229
539 if (time_after(psidid->time + SID_MAP_RETRY, jiffies)) 230 sidstr = sid_to_key_str(psid, sidtype);
540 goto sid_to_id_out; 231 if (!sidstr)
541 232 return -ENOMEM;
542 if (!test_and_set_bit(SID_ID_PENDING, &psidid->state)) { 233
543 saved_cred = override_creds(root_cred); 234 saved_cred = override_creds(root_cred);
544 idkey = request_key(&cifs_idmap_key_type, psidid->sidstr, ""); 235 sidkey = request_key(&cifs_idmap_key_type, sidstr, "");
545 if (IS_ERR(idkey)) 236 if (IS_ERR(sidkey)) {
546 cFYI(1, "%s: Can't map SID to an id", __func__); 237 rc = -EINVAL;
547 else { 238 cFYI(1, "%s: Can't map SID %s to a %cid", __func__, sidstr,
548 cid = *(unsigned long *)idkey->payload.value; 239 sidtype == SIDOWNER ? 'u' : 'g');
549 psidid->id = cid; 240 goto out_revert_creds;
550 set_bit(SID_ID_MAPPED, &psidid->state); 241 }
551 key_put(idkey); 242
552 kfree(psidid->sidstr); 243 /*
553 } 244 * FIXME: Here we assume that uid_t and gid_t are same size. It's
554 revert_creds(saved_cred); 245 * probably a safe assumption but might be better to check based on
555 psidid->time = jiffies; /* update ts for accessing */ 246 * sidtype.
556 clear_bit(SID_ID_PENDING, &psidid->state); 247 */
557 wake_up_bit(&psidid->state, SID_ID_PENDING); 248 if (sidkey->datalen < sizeof(uid_t)) {
558 } else { 249 rc = -EIO;
559 rc = wait_on_bit(&psidid->state, SID_ID_PENDING, 250 cFYI(1, "%s: Downcall contained malformed key "
560 sidid_pending_wait, TASK_INTERRUPTIBLE); 251 "(datalen=%hu)", __func__, sidkey->datalen);
561 if (rc) { 252 goto out_key_put;
562 cFYI(1, "%s: sidid_pending_wait interrupted %d",
563 __func__, rc);
564 --psidid->refcount; /* decremented without spinlock */
565 return rc;
566 }
567 if (test_bit(SID_ID_MAPPED, &psidid->state))
568 cid = psidid->id;
569 } 253 }
570 254
571sid_to_id_out:
572 --psidid->refcount; /* decremented without spinlock */
573 if (sidtype == SIDOWNER) 255 if (sidtype == SIDOWNER)
574 fattr->cf_uid = cid; 256 fuid = *(uid_t *)sidkey->payload.value;
575 else 257 else
576 fattr->cf_gid = cid; 258 fgid = *(gid_t *)sidkey->payload.value;
577 259
260out_key_put:
261 key_put(sidkey);
262out_revert_creds:
263 revert_creds(saved_cred);
264 kfree(sidstr);
265
266 /*
267 * Note that we return 0 here unconditionally. If the mapping
268 * fails then we just fall back to using the mnt_uid/mnt_gid.
269 */
270 if (sidtype == SIDOWNER)
271 fattr->cf_uid = fuid;
272 else
273 fattr->cf_gid = fgid;
578 return 0; 274 return 0;
579} 275}
580 276
@@ -621,17 +317,6 @@ init_cifs_idmap(void)
621 cred->jit_keyring = KEY_REQKEY_DEFL_THREAD_KEYRING; 317 cred->jit_keyring = KEY_REQKEY_DEFL_THREAD_KEYRING;
622 root_cred = cred; 318 root_cred = cred;
623 319
624 spin_lock_init(&siduidlock);
625 uidtree = RB_ROOT;
626 spin_lock_init(&sidgidlock);
627 gidtree = RB_ROOT;
628
629 spin_lock_init(&uidsidlock);
630 siduidtree = RB_ROOT;
631 spin_lock_init(&gidsidlock);
632 sidgidtree = RB_ROOT;
633 register_shrinker(&cifs_shrinker);
634
635 cFYI(1, "cifs idmap keyring: %d", key_serial(keyring)); 320 cFYI(1, "cifs idmap keyring: %d", key_serial(keyring));
636 return 0; 321 return 0;
637 322
@@ -648,41 +333,9 @@ exit_cifs_idmap(void)
648 key_revoke(root_cred->thread_keyring); 333 key_revoke(root_cred->thread_keyring);
649 unregister_key_type(&cifs_idmap_key_type); 334 unregister_key_type(&cifs_idmap_key_type);
650 put_cred(root_cred); 335 put_cred(root_cred);
651 unregister_shrinker(&cifs_shrinker);
652 cFYI(1, "Unregistered %s key type", cifs_idmap_key_type.name); 336 cFYI(1, "Unregistered %s key type", cifs_idmap_key_type.name);
653} 337}
654 338
655void
656cifs_destroy_idmaptrees(void)
657{
658 struct rb_root *root;
659 struct rb_node *node;
660
661 root = &uidtree;
662 spin_lock(&siduidlock);
663 while ((node = rb_first(root)))
664 rb_erase(node, root);
665 spin_unlock(&siduidlock);
666
667 root = &gidtree;
668 spin_lock(&sidgidlock);
669 while ((node = rb_first(root)))
670 rb_erase(node, root);
671 spin_unlock(&sidgidlock);
672
673 root = &siduidtree;
674 spin_lock(&uidsidlock);
675 while ((node = rb_first(root)))
676 rb_erase(node, root);
677 spin_unlock(&uidsidlock);
678
679 root = &sidgidtree;
680 spin_lock(&gidsidlock);
681 while ((node = rb_first(root)))
682 rb_erase(node, root);
683 spin_unlock(&gidsidlock);
684}
685
686/* copy ntsd, owner sid, and group sid from a security descriptor to another */ 339/* copy ntsd, owner sid, and group sid from a security descriptor to another */
687static void copy_sec_desc(const struct cifs_ntsd *pntsd, 340static void copy_sec_desc(const struct cifs_ntsd *pntsd,
688 struct cifs_ntsd *pnntsd, __u32 sidsoffset) 341 struct cifs_ntsd *pnntsd, __u32 sidsoffset)