Print this page
NEX-17589 Get "too high" smbd error when copy big file to cifs share
Reviewed by: Joyce McIntosh <joyce.mcintosh@nexenta.com>
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Matt Barden <matt.barden@nexenta.com>
NEX-17795 SMB logon should tolerate idmap problems
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Joyce McIntosh <joyce.mcintosh@nexenta.com>
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
NEX-9190 Files with owners not in /etc/passwd and not having inherited ACL's are prevented from seeing ownership/permissions via SMB
Reviewed by: Gordon Ross <gordon.ross@nexenta.com>
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
NEX-4083 Upstream changes from illumos 5917 and 5995
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Kevin Crowe <kevin.crowe@nexenta.com>
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
SMB-50 User-mode SMB server
 Includes work by these authors:
 Thomas Keiser <thomas.keiser@nexenta.com>
 Albert Lee <trisk@nexenta.com>
        
*** 18,45 ****
   *
   * CDDL HEADER END
   */
  /*
   * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
!  * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
   */
  
  /*
   * SMB server interface to idmap
   * (smb_idmap_get..., smb_idmap_batch_...)
   *
!  * There are three implementations of this interface:
!  *      uts/common/fs/smbsrv/smb_idmap.c (smbsrv kmod)
!  *      lib/smbsrv/libfksmbsrv/common/fksmb_idmap.c (libfksmbsrv)
!  *      lib/smbsrv/libsmb/common/smb_idmap.c (libsmb)
   *
   * There are enough differences (relative to the code size)
   * that it's more trouble than it's worth to merge them.
   *
   * This one differs from the others in that it:
   *      calls kernel (kidmap_...) interfaces
!  *      domain SIDs are shared, not strdup'ed
   */
  
  /*
   * SMB ID mapping
   *
--- 18,45 ----
   *
   * CDDL HEADER END
   */
  /*
   * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
!  * Copyright 2018 Nexenta Systems, Inc.  All rights reserved.
   */
  
  /*
   * SMB server interface to idmap
   * (smb_idmap_get..., smb_idmap_batch_...)
   *
!  * There are three implementations of this interface.
!  * This is the kernel version of these routines.  See also:
!  * $SRC/lib/smbsrv/libfksmbsrv/common/fksmb_idmap.c
!  * $SRC/lib/smbsrv/libsmb/common/smb_idmap.c
   *
   * There are enough differences (relative to the code size)
   * that it's more trouble than it's worth to merge them.
   *
   * This one differs from the others in that it:
   *      calls kernel (kidmap_...) interfaces
!  *      returned domain SIDs are shared, not strdup'ed
   */
  
  /*
   * SMB ID mapping
   *
*** 102,111 ****
--- 102,119 ----
          default:
                  ASSERT(0);
                  return (IDMAP_ERR_ARG);
          }
  
+         /*
+          * IDMAP_ERR_NOTFOUND is an advisory error
+          * and idmap will generate a local sid.
+          */
+         if (sim.sim_stat == IDMAP_ERR_NOTFOUND &&
+             sim.sim_domsid != NULL)
+                 sim.sim_stat = IDMAP_SUCCESS;
+ 
          if (sim.sim_stat != IDMAP_SUCCESS)
                  return (sim.sim_stat);
  
          if (sim.sim_domsid == NULL)
                  return (IDMAP_ERR_NOMAPPING);
*** 172,182 ****
   * Creates and initializes the context for batch ID mapping.
   */
  idmap_stat
  smb_idmap_batch_create(smb_idmap_batch_t *sib, uint16_t nmap, int flags)
  {
!         ASSERT(sib);
  
          bzero(sib, sizeof (smb_idmap_batch_t));
  
          sib->sib_idmaph = kidmap_get_create(global_zone);
  
--- 180,190 ----
   * Creates and initializes the context for batch ID mapping.
   */
  idmap_stat
  smb_idmap_batch_create(smb_idmap_batch_t *sib, uint16_t nmap, int flags)
  {
!         ASSERT(sib != NULL);
  
          bzero(sib, sizeof (smb_idmap_batch_t));
  
          sib->sib_idmaph = kidmap_get_create(global_zone);
  
*** 199,213 ****
  smb_idmap_batch_destroy(smb_idmap_batch_t *sib)
  {
          char *domsid;
          int i;
  
!         ASSERT(sib);
!         ASSERT(sib->sib_maps);
  
!         if (sib->sib_idmaph)
                  kidmap_get_destroy(sib->sib_idmaph);
  
          if (sib->sib_flags & SMB_IDMAP_ID2SID) {
                  /*
                   * SIDs are allocated only when mapping
                   * UID/GID to SIDs
--- 207,223 ----
  smb_idmap_batch_destroy(smb_idmap_batch_t *sib)
  {
          char *domsid;
          int i;
  
!         ASSERT(sib != NULL);
!         ASSERT(sib->sib_maps != NULL);
  
!         if (sib->sib_idmaph) {
                  kidmap_get_destroy(sib->sib_idmaph);
+                 sib->sib_idmaph = NULL;
+         }
  
          if (sib->sib_flags & SMB_IDMAP_ID2SID) {
                  /*
                   * SIDs are allocated only when mapping
                   * UID/GID to SIDs
*** 224,235 ****
                          if (domsid)
                                  smb_mem_free(domsid);
                  }
          }
  
!         if (sib->sib_size && sib->sib_maps)
                  kmem_free(sib->sib_maps, sib->sib_size);
  }
  
  /*
   * smb_idmap_batch_getid
   *
--- 234,247 ----
                          if (domsid)
                                  smb_mem_free(domsid);
                  }
          }
  
!         if (sib->sib_size && sib->sib_maps) {
                  kmem_free(sib->sib_maps, sib->sib_size);
+                 sib->sib_maps = NULL;
+         }
  }
  
  /*
   * smb_idmap_batch_getid
   *
*** 247,264 ****
      smb_sid_t *sid, int idtype)
  {
          char strsid[SMB_SID_STRSZ];
          idmap_stat idm_stat;
  
!         ASSERT(idmaph);
!         ASSERT(sim);
!         ASSERT(sid);
  
          smb_sid_tostr(sid, strsid);
          if (smb_sid_splitstr(strsid, &sim->sim_rid) != 0)
                  return (IDMAP_ERR_SID);
          sim->sim_domsid = smb_mem_strdup(strsid);
  
          switch (idtype) {
          case SMB_IDMAP_USER:
                  idm_stat = kidmap_batch_getuidbysid(idmaph, sim->sim_domsid,
                      sim->sim_rid, sim->sim_id, &sim->sim_stat);
--- 259,278 ----
      smb_sid_t *sid, int idtype)
  {
          char strsid[SMB_SID_STRSZ];
          idmap_stat idm_stat;
  
!         ASSERT(idmaph != NULL);
!         ASSERT(sim != NULL);
!         ASSERT(sid != NULL);
  
          smb_sid_tostr(sid, strsid);
          if (smb_sid_splitstr(strsid, &sim->sim_rid) != 0)
                  return (IDMAP_ERR_SID);
+         /* Note: Free sim_domsid in smb_idmap_batch_destroy */
          sim->sim_domsid = smb_mem_strdup(strsid);
+         sim->sim_idtype = idtype;
  
          switch (idtype) {
          case SMB_IDMAP_USER:
                  idm_stat = kidmap_batch_getuidbysid(idmaph, sim->sim_domsid,
                      sim->sim_rid, sim->sim_id, &sim->sim_stat);
*** 288,304 ****
--- 302,320 ----
   *
   * Queue a request to map the given UID/GID to a SID.
   *
   * sim->sim_domsid and sim->sim_rid will contain the mapping
   * result upon successful process of the batched request.
+  * Stash the type for error reporting (caller saves the ID).
   */
  idmap_stat
  smb_idmap_batch_getsid(idmap_get_handle_t *idmaph, smb_idmap_t *sim,
      uid_t id, int idtype)
  {
          idmap_stat idm_stat;
  
+         sim->sim_idtype = idtype;
          switch (idtype) {
          case SMB_IDMAP_USER:
                  idm_stat = kidmap_batch_getsidbyuid(idmaph, id,
                      (const char **)&sim->sim_domsid, &sim->sim_rid,
                      &sim->sim_stat);
*** 340,349 ****
--- 356,387 ----
          }
  
          return (idm_stat);
  }
  
+ static void
+ smb_idmap_bgm_report(smb_idmap_batch_t *sib, smb_idmap_t *sim)
+ {
+ 
+         if ((sib->sib_flags & SMB_IDMAP_ID2SID) != 0) {
+                 /*
+                  * Note: The ID and type we asked idmap to map
+                  * were saved in *sim_id and sim_idtype.
+                  */
+                 uint_t id = (sim->sim_id == NULL) ?
+                     0 : (uint_t)*sim->sim_id;
+                 cmn_err(CE_WARN, "Can't get SID for "
+                     "ID=%u type=%d, status=%d",
+                     id, sim->sim_idtype, sim->sim_stat);
+         }
+ 
+         if ((sib->sib_flags & SMB_IDMAP_SID2ID) != 0) {
+                 cmn_err(CE_WARN, "Can't get ID for SID %s-%u, status=%d",
+                     sim->sim_domsid, sim->sim_rid, sim->sim_stat);
+         }
+ }
+ 
  /*
   * smb_idmap_batch_getmappings
   *
   * trigger ID mapping service to get the mappings for queued
   * requests.
*** 354,376 ****
   */
  idmap_stat
  smb_idmap_batch_getmappings(smb_idmap_batch_t *sib)
  {
          idmap_stat idm_stat = IDMAP_SUCCESS;
          int i;
  
          idm_stat = kidmap_get_mappings(sib->sib_idmaph);
          if (idm_stat != IDMAP_SUCCESS)
                  return (idm_stat);
  
          /*
           * Check the status for all the queued requests
           */
!         for (i = 0; i < sib->sib_nmap; i++) {
!                 if (sib->sib_maps[i].sim_stat != IDMAP_SUCCESS)
!                         return (sib->sib_maps[i].sim_stat);
          }
  
          if (smb_idmap_batch_binsid(sib) != 0)
                  idm_stat = IDMAP_ERR_OTHER;
  
          return (idm_stat);
--- 392,419 ----
   */
  idmap_stat
  smb_idmap_batch_getmappings(smb_idmap_batch_t *sib)
  {
          idmap_stat idm_stat = IDMAP_SUCCESS;
+         smb_idmap_t *sim;
          int i;
  
          idm_stat = kidmap_get_mappings(sib->sib_idmaph);
          if (idm_stat != IDMAP_SUCCESS)
                  return (idm_stat);
  
          /*
           * Check the status for all the queued requests
           */
!         for (i = 0, sim = sib->sib_maps; i < sib->sib_nmap; i++, sim++) {
!                 if (sim->sim_stat != IDMAP_SUCCESS) {
!                         smb_idmap_bgm_report(sib, sim);
!                         if ((sib->sib_flags & SMB_IDMAP_SKIP_ERRS) == 0) {
!                                 return (sim->sim_stat);
                          }
+                 }
+         }
  
          if (smb_idmap_batch_binsid(sib) != 0)
                  idm_stat = IDMAP_ERR_OTHER;
  
          return (idm_stat);
*** 394,404 ****
                  /* This operation is not required */
                  return (0);
  
          sim = sib->sib_maps;
          for (i = 0; i < sib->sib_nmap; sim++, i++) {
!                 ASSERT(sim->sim_domsid);
                  if (sim->sim_domsid == NULL)
                          return (1);
  
                  if ((sid = smb_sid_fromstr(sim->sim_domsid)) == NULL)
                          return (1);
--- 437,447 ----
                  /* This operation is not required */
                  return (0);
  
          sim = sib->sib_maps;
          for (i = 0; i < sib->sib_nmap; sim++, i++) {
!                 ASSERT(sim->sim_domsid != NULL);
                  if (sim->sim_domsid == NULL)
                          return (1);
  
                  if ((sid = smb_sid_fromstr(sim->sim_domsid)) == NULL)
                          return (1);