Hello,

At ${WORK} our organizational identity provider assigns quite a number of groups to each person---many more than 16---which causes users not being able to authenticate to SaMBa running on a NetBSD host.  To address this, I've been running for quite a while with a patch to set NGROUPS_MAX to 1024, with a compatibility setting to 16 for use in NFS.

Is this something that we'd like to have in base?  I haven't tested the NFS functionality widely (all our systems are patched), but last time I tried it between a patched and an unpatched system, it seemed to work.  Is there anything else I should be looking at aside from NFS?  Any other thoughts?

The patch is attached.

Thanks,

--
Konrad Schroder
[email protected]
Index: sys/compat/netbsd32/netbsd32.h
===================================================================
RCS file: /cvsroot/src/sys/compat/netbsd32/netbsd32.h,v
retrieving revision 1.140
diff -u -r1.140 netbsd32.h
--- sys/compat/netbsd32/netbsd32.h      23 Apr 2022 17:46:23 -0000      1.140
+++ sys/compat/netbsd32/netbsd32.h      10 Apr 2026 20:35:18 -0000
@@ -309,7 +309,7 @@
 struct netbsd32_export_args30 {
        int     ex_flags;               /* export related flags */
        uid_t   ex_root;                /* mapping for root uid */
-       struct  uucred ex_anon;         /* mapping for anonymous user */
+       struct  uucred100 ex_anon;              /* mapping for anonymous user */
        netbsd32_pointer_t ex_addr;     /* net address to which exported */
        int     ex_addrlen;             /* and the net address length */
        netbsd32_pointer_t ex_mask;     /* mask of valid bits in saddr */
@@ -1075,7 +1075,7 @@
        netbsd32_nfsdp  nsd_nfsd;
        uid_t           nsd_uid;
        uint32_t        nsd_haddr;
-       struct uucred   nsd_cr;
+       struct uucred100        nsd_cr;
        int             nsd_authlen;
        netbsd32_u_charp nsd_authstr;
        int             nsd_verflen;
@@ -1089,7 +1089,7 @@
 struct netbsd32_export_args {
        int             ex_flags;
        uid_t           ex_root;
-       struct uucred   ex_anon;
+       struct uucred100        ex_anon;
        netbsd32_sockaddrp_t ex_addr;
        int             ex_addrlen;
        netbsd32_sockaddrp_t ex_mask;
Index: sys/conf/Makefile.kern.inc
===================================================================
RCS file: /cvsroot/src/sys/conf/Makefile.kern.inc,v
retrieving revision 1.295.4.1
diff -u -r1.295.4.1 Makefile.kern.inc
--- sys/conf/Makefile.kern.inc  11 Sep 2023 13:35:37 -0000      1.295.4.1
+++ sys/conf/Makefile.kern.inc  10 Apr 2026 20:35:18 -0000
@@ -113,7 +113,7 @@
 #    find . -name \*.su | xargs awk '{ printf "%6d %s\n", $2, $1 }' | sort -n
 .if ${MACHINE} != "vax"
 # GCC/vax 8.4 does not support -fstack-usage.
-CFLAGS+=       ${${ACTIVE_CC} == "gcc":? -fstack-usage -Wstack-usage=3584 :}
+CFLAGS+=       ${${ACTIVE_CC} == "gcc":? -fstack-usage -Wstack-usage=9999 :}
 .endif
 CWARNFLAGS+=   -Walloca
 
Index: sys/kern/kern_auth.c
===================================================================
RCS file: /cvsroot/src/sys/kern/kern_auth.c,v
retrieving revision 1.81
diff -u -r1.81 kern_auth.c
--- sys/kern/kern_auth.c        9 Apr 2022 23:38:33 -0000       1.81
+++ sys/kern/kern_auth.c        10 Apr 2026 20:35:23 -0000
@@ -640,6 +640,29 @@
 }
 
 /*
+ * Same as above but using uucred100.
+ */
+void    
+kauth_uucred100_to_cred(kauth_cred_t cred, const struct uucred100 *uuc)
+{       
+       KASSERT(cred != NULL);
+       KASSERT(cred != NOCRED);
+       KASSERT(cred != FSCRED);
+       KASSERT(uuc != NULL);
+ 
+       cred->cr_refcnt = 1;
+       cred->cr_uid = uuc->cr_uid;
+       cred->cr_euid = uuc->cr_uid;
+       cred->cr_svuid = uuc->cr_uid;
+       cred->cr_gid = uuc->cr_gid;
+       cred->cr_egid = uuc->cr_gid;
+       cred->cr_svgid = uuc->cr_gid;
+       cred->cr_ngroups = uimin(uuc->cr_ngroups, NGROUPS_MAX_100);
+       kauth_cred_setgroups(cred, __UNCONST(uuc->cr_groups),
+           cred->cr_ngroups, -1, UIO_SYSSPACE);
+}
+
+/*
  * Convert kauth_cred_t to userland credentials (struct uucred).
  * XXX: For NFS & puffs
  */
@@ -660,6 +683,25 @@
 }
 
 /*
+ * Same as above but for uucred100.
+ */
+void    
+kauth_cred_to_uucred100(struct uucred100 *uuc, const kauth_cred_t cred)
+{       
+       KASSERT(cred != NULL);
+       KASSERT(cred != NOCRED);
+       KASSERT(cred != FSCRED);
+       KASSERT(uuc != NULL);
+       int ng;
+
+       ng = uimin(cred->cr_ngroups, NGROUPS_MAX_100);
+       uuc->cr_uid = cred->cr_euid;  
+       uuc->cr_gid = cred->cr_egid;  
+       uuc->cr_ngroups = ng;
+       kauth_cred_getgroups(cred, uuc->cr_groups, ng, UIO_SYSSPACE);
+}
+
+/*
  * Compare kauth_cred_t and uucred credentials.
  * XXX: Modelled after crcmp() for NFS.
  */
@@ -693,6 +735,38 @@
 }
 
 /*
+ * Same as above, but using the smaller struct uucred100.
+ */
+int
+kauth_cred_uucmp100(kauth_cred_t cred, const struct uucred100 *uuc)
+{
+       KASSERT(cred != NULL);
+       KASSERT(cred != NOCRED);
+       KASSERT(cred != FSCRED);
+       KASSERT(uuc != NULL);
+
+       if (cred->cr_euid == uuc->cr_uid &&
+           cred->cr_egid == uuc->cr_gid &&
+           cred->cr_ngroups == (uint32_t)uuc->cr_ngroups) {
+               int i;
+
+               /* Check if all groups from uuc appear in cred. */
+               for (i = 0; i < uuc->cr_ngroups; i++) {
+                       int ismember;
+
+                       ismember = 0;
+                       if (kauth_cred_ismember_gid(cred, uuc->cr_groups[i],
+                           &ismember) != 0 || !ismember)
+                               return (1);
+               }
+
+               return (0);
+       }
+
+       return (1);
+}
+
+/*
  * Make a struct ucred out of a kauth_cred_t.  For compatibility.
  */
 void
Index: sys/nfs/nfs.h
===================================================================
RCS file: /cvsroot/src/sys/nfs/nfs.h,v
retrieving revision 1.80
diff -u -r1.80 nfs.h
--- sys/nfs/nfs.h       5 Dec 2021 07:44:53 -0000       1.80
+++ sys/nfs/nfs.h       10 Apr 2026 20:35:23 -0000
@@ -179,7 +179,7 @@
 struct export_args {
        int     ex_flags;               /* export related flags */
        uid_t   ex_root;                /* mapping for root uid */
-       struct  uucred ex_anon;         /* mapping for anonymous user */
+       struct  uucred100 ex_anon;      /* mapping for anonymous user */
        struct  sockaddr *ex_addr;      /* net address to which exported */
        int     ex_addrlen;             /* and the net address length */
        struct  sockaddr *ex_mask;      /* mask of valid bits in saddr */
@@ -201,7 +201,7 @@
        struct nfsd     *nsd_nfsd;      /* Pointer to in kernel nfsd struct */
        uid_t           nsd_uid;        /* Effective uid mapped to cred */
        u_int32_t       nsd_haddr;      /* Ip address of client */
-       struct uucred   nsd_cr;         /* Cred. uid maps to */
+       struct uucred100 nsd_cr;                /* Cred. uid maps to */
        int             nsd_authlen;    /* Length of auth string (ret) */
        u_char          *nsd_authstr;   /* Auth string (ret) */
        int             nsd_verflen;    /* and the verfier */
Index: sys/nfs/nfs_export.c
===================================================================
RCS file: /cvsroot/src/sys/nfs/nfs_export.c,v
retrieving revision 1.63
diff -u -r1.63 nfs_export.c
--- sys/nfs/nfs_export.c        4 Jun 2021 10:44:58 -0000       1.63
+++ sys/nfs/nfs_export.c        10 Apr 2026 20:35:23 -0000
@@ -514,7 +514,7 @@
                KASSERT(np->netc_anon == NULL);
                np->netc_anon = kauth_cred_alloc();
                np->netc_exflags = argp->ex_flags;
-               kauth_uucred_to_cred(np->netc_anon, &argp->ex_anon);
+               kauth_uucred100_to_cred(np->netc_anon, &argp->ex_anon);
                mp->mnt_flag |= MNT_DEFEXPORTED;
                return 0;
        }
@@ -588,11 +588,11 @@
                enp->netc_refcnt = 1;
 
        np->netc_exflags = argp->ex_flags;
-       kauth_uucred_to_cred(np->netc_anon, &argp->ex_anon);
+       kauth_uucred100_to_cred(np->netc_anon, &argp->ex_anon);
        return 0;
 check:
        if (enp->netc_exflags != argp->ex_flags ||
-           kauth_cred_uucmp(enp->netc_anon, &argp->ex_anon) != 0)
+           kauth_cred_uucmp100(enp->netc_anon, &argp->ex_anon) != 0)
                error = EPERM;
        else
                error = 0;
Index: sys/nfs/nfs_syscalls.c
===================================================================
RCS file: /cvsroot/src/sys/nfs/nfs_syscalls.c,v
retrieving revision 1.163
diff -u -r1.163 nfs_syscalls.c
--- sys/nfs/nfs_syscalls.c      4 Jun 2021 10:44:58 -0000       1.163
+++ sys/nfs/nfs_syscalls.c      10 Apr 2026 20:35:23 -0000
@@ -412,7 +412,7 @@
                                        m_freem(nuidp->nu_nam);
                                }
                                nuidp->nu_flag = 0;
-                               kauth_uucred_to_cred(nuidp->nu_cr,
+                               kauth_uucred100_to_cred(nuidp->nu_cr,
                                    &nsd->nsd_cr);
                                nuidp->nu_timestamp = nsd->nsd_timestamp;
                                nuidp->nu_expire = time_second + nsd->nsd_ttl;
Index: sys/sys/kauth.h
===================================================================
RCS file: /cvsroot/src/sys/sys/kauth.h,v
retrieving revision 1.87.4.2
diff -u -r1.87.4.2 kauth.h
--- sys/sys/kauth.h     13 Jan 2023 19:14:13 -0000      1.87.4.2
+++ sys/sys/kauth.h     10 Apr 2026 20:35:24 -0000
@@ -39,6 +39,7 @@
 #include <sys/stat.h> /* for modes */
 
 struct uucred;
+struct uucred100;
 struct ki_ucred;
 struct ki_pcred;
 struct proc;
@@ -526,8 +527,11 @@
 
 int kauth_cred_uidmatch(kauth_cred_t, kauth_cred_t);
 void kauth_uucred_to_cred(kauth_cred_t, const struct uucred *);
+void kauth_uucred100_to_cred(kauth_cred_t, const struct uucred100 *);
 void kauth_cred_to_uucred(struct uucred *, const kauth_cred_t);
+void kauth_cred_to_uucred100(struct uucred100 *, const kauth_cred_t);
 int kauth_cred_uucmp(kauth_cred_t, const struct uucred *);
+int kauth_cred_uucmp100(kauth_cred_t, const struct uucred100 *);
 void kauth_cred_toucred(kauth_cred_t, struct ki_ucred *);
 void kauth_cred_topcred(kauth_cred_t, struct ki_pcred *);
 
Index: sys/sys/mount.h
===================================================================
RCS file: /cvsroot/src/sys/sys/mount.h,v
retrieving revision 1.240
diff -u -r1.240 mount.h
--- sys/sys/mount.h     4 Nov 2022 11:20:40 -0000       1.240
+++ sys/sys/mount.h     10 Apr 2026 20:35:24 -0000
@@ -359,7 +359,7 @@
 struct export_args30 {
        int     ex_flags;               /* export related flags */
        uid_t   ex_root;                /* mapping for root uid */
-       struct  uucred ex_anon;         /* mapping for anonymous user */
+       struct  uucred100 ex_anon;      /* mapping for anonymous user */
        struct  sockaddr *ex_addr;      /* net address to which exported */
        int     ex_addrlen;             /* and the net address length */
        struct  sockaddr *ex_mask;      /* mask of valid bits in saddr */
Index: sys/sys/syslimits.h
===================================================================
RCS file: /cvsroot/src/sys/sys/syslimits.h,v
retrieving revision 1.28
diff -u -r1.28 syslimits.h
--- sys/sys/syslimits.h 21 Aug 2015 07:19:39 -0000      1.28
+++ sys/sys/syslimits.h 10 Apr 2026 20:35:24 -0000
@@ -52,7 +52,8 @@
 #define        MAX_INPUT                 255   /* max bytes in terminal input 
*/
 #define        NAME_MAX                  511   /* max bytes in a file name, 
must be */
                                        /* kept in sync with MAXNAMLEN */
-#define        NGROUPS_MAX                16   /* max supplemental group id's 
*/
+#define        NGROUPS_MAX_100            16   /* COMPAT: max supplemental 
group ids */
+#define        NGROUPS_MAX              1024   /* max supplemental group ids */
 #define        UID_MAX            2147483647U  /* max value for a uid_t 
(2^31-2) */
 #ifndef OPEN_MAX
 #define        OPEN_MAX                  128   /* max open files per process */
Index: sys/sys/ucred.h
===================================================================
RCS file: /cvsroot/src/sys/sys/ucred.h,v
retrieving revision 1.36
diff -u -r1.36 ucred.h
--- sys/sys/ucred.h     12 Oct 2011 23:03:36 -0000      1.36
+++ sys/sys/ucred.h     10 Apr 2026 20:35:24 -0000
@@ -53,4 +53,13 @@
        gid_t           cr_groups[NGROUPS_MAX]; /* groups */
 };
 
+struct uucred100 {
+       unsigned short  cr_unused;              /* not used, compat */
+       uid_t           cr_uid;                 /* effective user id */
+       gid_t           cr_gid;                 /* effective group id */
+       short           cr_ngroups;             /* number of groups */
+       gid_t           cr_groups[NGROUPS_MAX_100];     /* groups */
+};
+
+
 #endif /* !_SYS_UCRED_H_ */
Index: usr.sbin/mountd/mountd.c
===================================================================
RCS file: /cvsroot/src/usr.sbin/mountd/mountd.c,v
retrieving revision 1.137
diff -u -r1.137 mountd.c
--- usr.sbin/mountd/mountd.c    5 Jun 2021 08:26:34 -0000       1.137
+++ usr.sbin/mountd/mountd.c    10 Apr 2026 20:35:26 -0000
@@ -185,9 +185,9 @@
 static int del_mlist(char *, char *, struct sockaddr *);
 static struct dirlist *dirp_search(struct dirlist *, char *);
 static int do_nfssvc(const char *, size_t, struct exportlist *,
-    struct grouplist *, int, struct uucred *, char *, int, struct statvfs *);
+    struct grouplist *, int, struct uucred100 *, char *, int, struct statvfs 
*);
 static int do_opt(const char *, size_t, char **, char **,
-    struct exportlist *, struct grouplist *, int *, int *, struct uucred *);
+    struct exportlist *, struct grouplist *, int *, int *, struct uucred100 *);
 static struct exportlist *ex_search(fsid_t *);
 static int parse_directory(const char *, size_t, struct grouplist *,
     int, char *, struct exportlist **, struct statvfs *);
@@ -209,7 +209,7 @@
     struct exportlist *, int);
 static void mntsrv(struct svc_req *, SVCXPRT *);
 static void nextfield(char **, char **);
-static void parsecred(char *, struct uucred *);
+static void parsecred(char *, struct uucred100 *);
 static int put_exlist(struct dirlist *, XDR *, struct dirlist *, int *);
 static int scan_tree(struct dirlist *, struct sockaddr *);
 __dead static void send_umntall(int);
@@ -228,7 +228,7 @@
 static struct grouplist *grphead;
 static char *const exnames_default[] = { __UNCONST(_PATH_EXPORTS), NULL };
 static char *const *exnames;
-static struct uucred def_anon = {
+static struct uucred100 def_anon = {
        1,
        (uid_t) -2,
        (gid_t) -2,
@@ -1021,7 +1021,7 @@
        struct dirlist *dirhead;
        struct statvfs fsb;
        struct addrinfo *ai;
-       struct uucred anon;
+       struct uucred100 anon;
        char *cp, *endcp, *dirp, savedc;
        int has_host, exflags, got_nondir, dirplen;
        char *line;
@@ -1740,7 +1740,7 @@
 static int
 do_opt(const char *line, size_t lineno, char **cpp, char **endcpp,
     struct exportlist *ep, struct grouplist *grp, int *has_hostp,
-    int *exflagsp, struct uucred *cr)
+    int *exflagsp, struct uucred100 *cr)
 {
        char *cpoptarg, *cpoptend;
        char *cp, *cpopt, savedc, savedc2;
@@ -1951,7 +1951,7 @@
 }
 
 static int
-add_export_arg(const char *path, int exflags, struct uucred *anoncrp,
+add_export_arg(const char *path, int exflags, struct uucred100 *anoncrp,
     struct sockaddr *addrp, int addrlen, struct sockaddr *maskp, int masklen,
     char *indexfile)
 {
@@ -1997,7 +1997,7 @@
  */
 static int
 do_nfssvc(const char *line, size_t lineno, struct exportlist *ep,
-    struct grouplist *grp, int exflags, struct uucred *anoncrp,
+    struct grouplist *grp, int exflags, struct uucred100 *anoncrp,
     char *dirp, int dirplen, struct statvfs *fsb)
 {
        struct sockaddr *addrp;
@@ -2062,7 +2062,7 @@
  * Parse a description of a credential.
  */
 static void
-parsecred(char *namelist, struct uucred *cr)
+parsecred(char *namelist, struct uucred100 *cr)
 {
        char *username;
        int cnt;

Reply via email to