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,28 +18,28 @@
  *
  * CDDL HEADER END
  */
 /*
  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2013 Nexenta Systems, Inc.  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:
- *      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 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
- *      domain SIDs are shared, not strdup'ed
+ *      returned domain SIDs are shared, not strdup'ed
  */
 
 /*
  * SMB ID mapping
  *

@@ -102,10 +102,18 @@
         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,11 +180,11 @@
  * 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);
+        ASSERT(sib != NULL);
 
         bzero(sib, sizeof (smb_idmap_batch_t));
 
         sib->sib_idmaph = kidmap_get_create(global_zone);
 

@@ -199,15 +207,17 @@
 smb_idmap_batch_destroy(smb_idmap_batch_t *sib)
 {
         char *domsid;
         int i;
 
-        ASSERT(sib);
-        ASSERT(sib->sib_maps);
+        ASSERT(sib != NULL);
+        ASSERT(sib->sib_maps != NULL);
 
-        if (sib->sib_idmaph)
+        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,12 +234,14 @@
                         if (domsid)
                                 smb_mem_free(domsid);
                 }
         }
 
-        if (sib->sib_size && sib->sib_maps)
+        if (sib->sib_size && sib->sib_maps) {
                 kmem_free(sib->sib_maps, sib->sib_size);
+                sib->sib_maps = NULL;
+        }
 }
 
 /*
  * smb_idmap_batch_getid
  *

@@ -247,18 +259,20 @@
     smb_sid_t *sid, int idtype)
 {
         char strsid[SMB_SID_STRSZ];
         idmap_stat idm_stat;
 
-        ASSERT(idmaph);
-        ASSERT(sim);
-        ASSERT(sid);
+        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,17 +302,19 @@
  *
  * 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,10 +356,32 @@
         }
 
         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,23 +392,28 @@
  */
 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; i < sib->sib_nmap; i++) {
-                if (sib->sib_maps[i].sim_stat != IDMAP_SUCCESS)
-                        return (sib->sib_maps[i].sim_stat);
+        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,11 +437,11 @@
                 /* This operation is not required */
                 return (0);
 
         sim = sib->sib_maps;
         for (i = 0; i < sib->sib_nmap; sim++, i++) {
-                ASSERT(sim->sim_domsid);
+                ASSERT(sim->sim_domsid != NULL);
                 if (sim->sim_domsid == NULL)
                         return (1);
 
                 if ((sid = smb_sid_fromstr(sim->sim_domsid)) == NULL)
                         return (1);