Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 22 Jan 2001 22:58:56 -0500
From:      "Brian F. Feldman" <green@FreeBSD.org>
To:        arch@FreeBSD.org
Cc:        alfred@FreeBSD.org
Subject:   struct ucred is evil and must be contained
Message-ID:  <200101230358.f0N3wvW01298@green.dyndns.org>

next in thread | raw e-mail | index | archive | help
Okay, maybe the subject is a bit sensationalistic, but the fact remains that 
ucred has grown into a monster, in the same manner of struct proc, that 
needs to be carefully contained.  In this vain, I've created a struct xucred 
and replaced uses of ucred outside of the kernel with it where possible.

This will also happen to fix the bug that if you screw up your interfaces 
(change the size of ucred, for example), mountd and nfsd will not panic the 
kernel because of it.  This is a very good thing!  Comments?

Index: sbin/mountd/mountd.c
===================================================================
RCS file: /usr2/ncvs/src/sbin/mountd/mountd.c,v
retrieving revision 1.39
diff -u -r1.39 mountd.c
--- sbin/mountd/mountd.c	1999/12/03 20:23:53	1.39
+++ sbin/mountd/mountd.c	2001/01/23 00:24:24
@@ -161,9 +161,9 @@
 void	del_mlist __P((char *, char *));
 struct dirlist *dirp_search __P((struct dirlist *, char *));
 int	do_mount __P((struct exportlist *, struct grouplist *, int,
-		struct ucred *, char *, int, struct statfs *));
+		struct xucred *, char *, int, struct statfs *));
 int	do_opt __P((char **, char **, struct exportlist *, struct grouplist *,
-				int *, int *, struct ucred *));
+				int *, int *, struct xucred *));
 struct	exportlist *ex_search __P((fsid_t *));
 struct	exportlist *get_exp __P((void));
 void	free_dir __P((struct dirlist *));
@@ -184,7 +184,7 @@
 void	mntsrv __P((struct svc_req *, SVCXPRT *));
 void	nextfield __P((char **, char **));
 void	out_of_mem __P((void));
-void	parsecred __P((char *, struct ucred *));
+void	parsecred __P((char *, struct xucred *));
 int	put_exlist __P((struct dirlist *, XDR *, struct dirlist *, int *));
 int	scan_tree __P((struct dirlist *, u_int32_t));
 static void usage __P((void));
@@ -202,8 +202,7 @@
 struct mountlist *mlhead;
 struct grouplist *grphead;
 char exname[MAXPATHLEN];
-struct ucred def_anon = {
-	1,
+struct xucred def_anon = {
 	(uid_t) -2,
 	1,
 	{ (gid_t) -2 }
@@ -732,7 +731,7 @@
 	struct dirlist *dirhead;
 	struct statfs fsb, *fsp;
 	struct hostent *hpe;
-	struct ucred anon;
+	struct xucred anon;
 	char *cp, *endcp, *dirp, *hst, *usr, *dom, savedc;
 	int len, has_host, exflags, got_nondir, dirplen, num, i, netgrp;
 
@@ -1332,7 +1331,7 @@
 	struct grouplist *grp;
 	int *has_hostp;
 	int *exflagsp;
-	struct ucred *cr;
+	struct xucred *cr;
 {
 	char *cpoptarg, *cpoptend;
 	char *cp, *endcp, *cpopt, savedc, savedc2;
@@ -1591,7 +1590,7 @@
 	struct exportlist *ep;
 	struct grouplist *grp;
 	int exflags;
-	struct ucred *anoncrp;
+	struct xucred *anoncrp;
 	char *dirp;
 	int dirplen;
 	struct statfs *fsb;
@@ -1842,7 +1841,7 @@
 void
 parsecred(namelist, cr)
 	char *namelist;
-	struct ucred *cr;
+	struct xucred *cr;
 {
 	char *name;
 	int cnt;
@@ -1854,7 +1853,6 @@
 	/*
 	 * Set up the unprivileged user.
 	 */
-	cr->cr_ref = 1;
 	cr->cr_uid = -2;
 	cr->cr_groups[0] = -2;
 	cr->cr_ngroups = 1;
Index: sys/kern/vfs_subr.c
===================================================================
RCS file: /usr2/ncvs/src/sys/kern/vfs_subr.c,v
retrieving revision 1.298
diff -u -r1.298 vfs_subr.c
--- sys/kern/vfs_subr.c	2000/12/15 20:08:19	1.298
+++ sys/kern/vfs_subr.c	2001/01/23 00:52:35
@@ -2314,7 +2314,11 @@
 			return (EPERM);
 		np = &nep->ne_defexported;
 		np->netc_exflags = argp->ex_flags;
-		np->netc_anon = argp->ex_anon;
+		bzero(&np->netc_anon, sizeof(np->netc_anon));
+		np->netc_anon.cr_uid = argp->ex_anon.cr_uid;
+		np->netc_anon.cr_ngroups = argp->ex_anon.cr_ngroups;
+		bcopy(argp->ex_anon.cr_groups, np->netc_anon.cr_groups,
+		    sizeof(np->netc_anon.cr_groups));
 		np->netc_anon.cr_ref = 1;
 		mp->mnt_flag |= MNT_DEFEXPORTED;
 		return (0);
@@ -2358,7 +2362,11 @@
 		goto out;
 	}
 	np->netc_exflags = argp->ex_flags;
-	np->netc_anon = argp->ex_anon;
+	bzero(&np->netc_anon, sizeof(np->netc_anon));
+	np->netc_anon.cr_uid = argp->ex_anon.cr_uid;
+	np->netc_anon.cr_ngroups = argp->ex_anon.cr_ngroups;
+	bcopy(argp->ex_anon.cr_groups, np->netc_anon.cr_groups,
+	    sizeof(np->netc_anon.cr_groups));
 	np->netc_anon.cr_ref = 1;
 	return (0);
 out:
Index: sys/netinet/tcp_subr.c
===================================================================
RCS file: /usr2/ncvs/src/sys/netinet/tcp_subr.c,v
retrieving revision 1.86
diff -u -r1.86 tcp_subr.c
--- sys/netinet/tcp_subr.c	2000/12/24 10:57:21	1.86
+++ sys/netinet/tcp_subr.c	2001/01/23 00:13:00
@@ -893,6 +893,7 @@
 static int
 tcp_getcred(SYSCTL_HANDLER_ARGS)
 {
+	struct xucred xuc;
 	struct sockaddr_in addrs[2];
 	struct inpcb *inp;
 	int error, s;
@@ -910,19 +911,25 @@
 		error = ENOENT;
 		goto out;
 	}
-	error = SYSCTL_OUT(req, inp->inp_socket->so_cred, sizeof(struct ucred));
+
+	xuc.cr_uid = inp->inp_socket->so_cred->cr_uid;
+	xuc.cr_ngroups = inp->inp_socket->so_cred->cr_ngroups;
+	bcopy(inp->inp_socket->so_cred->cr_groups, xuc.cr_groups,
+	    sizeof(xuc.cr_groups));
+	error = SYSCTL_OUT(req, &xuc, sizeof(struct xucred));
 out:
 	splx(s);
 	return (error);
 }
 
 SYSCTL_PROC(_net_inet_tcp, OID_AUTO, getcred, CTLTYPE_OPAQUE|CTLFLAG_RW,
-    0, 0, tcp_getcred, "S,ucred", "Get the ucred of a TCP connection");
+    0, 0, tcp_getcred, "S,xucred", "Get the xucred of a TCP connection");
 
 #ifdef INET6
 static int
 tcp6_getcred(SYSCTL_HANDLER_ARGS)
 {
+	struct xucred xuc;
 	struct sockaddr_in6 addrs[2];
 	struct inpcb *inp;
 	int error, s, mapped = 0;
@@ -956,8 +963,12 @@
 		error = ENOENT;
 		goto out;
 	}
-	error = SYSCTL_OUT(req, inp->inp_socket->so_cred, 
-			   sizeof(struct ucred));
+	
+	xuc.cr_uid = inp->inp_socket->so_cred->cr_uid;
+	xuc.cr_ngroups = inp->inp_socket->so_cred->cr_ngroups;
+	bcopy(inp->inp_socket->so_cred->cr_groups, xuc.cr_groups,
+	    sizeof(xuc.cr_groups));
+	error = SYSCTL_OUT(req, &xuc, sizeof(struct xucred));
 out:
 	splx(s);
 	return (error);
@@ -965,7 +976,7 @@
 
 SYSCTL_PROC(_net_inet6_tcp6, OID_AUTO, getcred, CTLTYPE_OPAQUE|CTLFLAG_RW,
 	    0, 0,
-	    tcp6_getcred, "S,ucred", "Get the ucred of a TCP6 connection");
+	    tcp6_getcred, "S,xucred", "Get the xucred of a TCP6 connection");
 #endif
 
 
Index: sys/netinet/udp_usrreq.c
===================================================================
RCS file: /usr2/ncvs/src/sys/netinet/udp_usrreq.c,v
retrieving revision 1.80
diff -u -r1.80 udp_usrreq.c
--- sys/netinet/udp_usrreq.c	2000/12/24 10:57:21	1.80
+++ sys/netinet/udp_usrreq.c	2001/01/23 00:13:50
@@ -606,6 +606,7 @@
 static int
 udp_getcred(SYSCTL_HANDLER_ARGS)
 {
+	struct xucred xuc;
 	struct sockaddr_in addrs[2];
 	struct inpcb *inp;
 	int error, s;
@@ -623,14 +624,19 @@
 		error = ENOENT;
 		goto out;
 	}
-	error = SYSCTL_OUT(req, inp->inp_socket->so_cred, sizeof(struct ucred));
+
+	xuc.cr_uid = inp->inp_socket->so_cred->cr_uid;
+	xuc.cr_ngroups = inp->inp_socket->so_cred->cr_ngroups;
+	bcopy(inp->inp_socket->so_cred->cr_groups, xuc.cr_groups,
+	    sizeof(xuc.cr_groups));
+	error = SYSCTL_OUT(req, &xuc, sizeof(struct xucred));
 out:
 	splx(s);
 	return (error);
 }
 
 SYSCTL_PROC(_net_inet_udp, OID_AUTO, getcred, CTLTYPE_OPAQUE|CTLFLAG_RW,
-    0, 0, udp_getcred, "S,ucred", "Get the ucred of a UDP connection");
+    0, 0, udp_getcred, "S,xucred", "Get the xucred of a UDP connection");
 
 static int
 udp_output(inp, m, addr, control, p)
Index: sys/netinet6/udp6_usrreq.c
===================================================================
RCS file: /usr2/ncvs/src/sys/netinet6/udp6_usrreq.c,v
retrieving revision 1.13
diff -u -r1.13 udp6_usrreq.c
--- sys/netinet6/udp6_usrreq.c	2000/10/23 07:11:01	1.13
+++ sys/netinet6/udp6_usrreq.c	2001/01/23 00:15:16
@@ -474,6 +474,7 @@
 static int
 udp6_getcred(SYSCTL_HANDLER_ARGS)
 {
+	struct xucred xuc;
 	struct sockaddr_in6 addrs[2];
 	struct inpcb *inp;
 	int error, s;
@@ -484,7 +485,7 @@
 
 	if (req->newlen != sizeof(addrs))
 		return (EINVAL);
-	if (req->oldlen != sizeof(struct ucred))
+	if (req->oldlen != sizeof(struct xucred))
 		return (EINVAL);
 	error = SYSCTL_IN(req, addrs, sizeof(addrs));
 	if (error)
@@ -498,9 +499,12 @@
 		error = ENOENT;
 		goto out;
 	}
-	error = SYSCTL_OUT(req, inp->inp_socket->so_cred,
-			   sizeof(struct ucred));
 
+	xuc.cr_uid = inp->inp_socket->so_cred->cr_uid;
+	xuc.cr_ngroups = inp->inp_socket->so_cred->cr_ngroups;
+	bcopy(inp->inp_socket->so_cred->cr_groups, xuc.cr_groups,
+	    sizeof(xuc.cr_groups));
+	error = SYSCTL_OUT(req, &xuc, sizeof(struct xucred));
 out:
 	splx(s);
 	return (error);
@@ -508,7 +512,7 @@
 
 SYSCTL_PROC(_net_inet6_udp6, OID_AUTO, getcred, CTLTYPE_OPAQUE|CTLFLAG_RW,
 	    0, 0,
-	    udp6_getcred, "S,ucred", "Get the ucred of a UDP6 connection");
+	    udp6_getcred, "S,xucred", "Get the xucred of a UDP6 connection");
 
 static int
 udp6_abort(struct socket *so)
Index: sys/nfs/nfs.h
===================================================================
RCS file: /usr2/ncvs/src/sys/nfs/nfs.h,v
retrieving revision 1.56
diff -u -r1.56 nfs.h
--- sys/nfs/nfs.h	2000/10/24 10:13:36	1.56
+++ sys/nfs/nfs.h	2001/01/23 00:28:27
@@ -197,7 +197,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 ucred	nsd_cr;		/* Cred. uid maps to */
+	struct xucred	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_syscalls.c
===================================================================
RCS file: /usr2/ncvs/src/sys/nfs/nfs_syscalls.c,v
retrieving revision 1.64
diff -u -r1.64 nfs_syscalls.c
--- sys/nfs/nfs_syscalls.c	2000/12/21 21:44:24	1.64
+++ sys/nfs/nfs_syscalls.c	2001/01/23 00:48:56
@@ -244,7 +244,7 @@
 				slp->ns_numuids++;
 				nuidp = (struct nfsuid *)
 				   malloc(sizeof (struct nfsuid), M_NFSUID,
-					M_WAITOK);
+					M_WAITOK | M_ZERO);
 			    } else
 				nuidp = (struct nfsuid *)0;
 			    if ((slp->ns_flag & SLP_VALID) == 0) {
@@ -260,7 +260,12 @@
 					FREE(nuidp->nu_nam, M_SONAME);
 			        }
 				nuidp->nu_flag = 0;
-				nuidp->nu_cr = nsd->nsd_cr;
+				nuidp->nu_cr.cr_uid = nsd->nsd_cr.cr_uid;
+				nuidp->nu_cr.cr_ngroups =
+				  nsd->nsd_cr.cr_ngroups;
+				bcopy(nsd->nsd_cr.cr_groups,
+				  nuidp->nu_cr.cr_groups,
+				  sizeof(nuidp->nu_cr.cr_groups));
 				if (nuidp->nu_cr.cr_ngroups > NGROUPS)
 				    nuidp->nu_cr.cr_ngroups = NGROUPS;
 				nuidp->nu_cr.cr_ref = 1;
Index: sys/sys/mount.h
===================================================================
RCS file: /usr2/ncvs/src/sys/sys/mount.h,v
retrieving revision 1.99
diff -u -r1.99 mount.h
--- sys/sys/mount.h	2000/12/04 09:21:05	1.99
+++ sys/sys/mount.h	2001/01/23 00:32:10
@@ -245,11 +245,11 @@
 struct export_args {
 	int	ex_flags;		/* export related flags */
 	uid_t	ex_root;		/* mapping for root uid */
-	struct	ucred ex_anon;		/* mapping for anonymous user */
+	struct	xucred ex_anon;		/* mapping for anonymous user */
 	struct	sockaddr *ex_addr;	/* net address to which exported */
-	int	ex_addrlen;		/* and the net address length */
+	u_char	ex_addrlen;		/* and the net address length */
 	struct	sockaddr *ex_mask;	/* mask of valid bits in saddr */
-	int	ex_masklen;		/* and the smask length */
+	u_char	ex_masklen;		/* and the smask length */
 	char	*ex_indexfile;		/* index file for WebNFS URLs */
 };
 
Index: sys/sys/ucred.h
===================================================================
RCS file: /usr2/ncvs/src/sys/sys/ucred.h,v
retrieving revision 1.19
diff -u -r1.19 ucred.h
--- sys/sys/ucred.h	2000/11/30 19:09:47	1.19
+++ sys/sys/ucred.h	2001/01/23 00:25:53
@@ -37,6 +37,7 @@
 #ifndef _SYS_UCRED_H_
 #define	_SYS_UCRED_H_
 
+#ifdef _KERNEL
 #include <sys/mutex.h>
 
 /*
@@ -53,9 +54,19 @@
 	struct	uidinfo *cr_uidinfo;	/* per uid resource consumption */
 	struct	mtx cr_mtx;		/* protect refcount */
 };
-#define cr_gid cr_groups[0]
 #define NOCRED ((struct ucred *)0)	/* no credential available */
 #define FSCRED ((struct ucred *)-1)	/* filesystem credential */
+#endif
+
+/*
+ * This is the external representation of struct ucred which "won't change".
+ */
+struct xucred {
+	uid_t	cr_uid;			/* effective user id */
+	short	cr_ngroups;		/* number of groups */
+	gid_t	cr_groups[NGROUPS];	/* groups */
+};
+#define cr_gid cr_groups[0]
 
 #ifdef _KERNEL
 
Index: usr.sbin/inetd/builtins.c
===================================================================
RCS file: /usr2/ncvs/src/usr.sbin/inetd/builtins.c,v
retrieving revision 1.29
diff -u -r1.29 builtins.c
--- usr.sbin/inetd/builtins.c	2000/12/05 13:56:01	1.29
+++ usr.sbin/inetd/builtins.c	2001/01/22 23:54:26
@@ -338,7 +338,7 @@
 	struct sockaddr_in6 sin6[2];
 #endif
 	struct sockaddr_storage ss[2];
-	struct ucred uc;
+	struct xucred uc;
 	struct timeval tv = {
 		10,
 		0
Index: usr.sbin/pstat/pstat.c
===================================================================
RCS file: /usr2/ncvs/src/usr.sbin/pstat/pstat.c,v
retrieving revision 1.52
diff -u -r1.52 pstat.c
--- usr.sbin/pstat/pstat.c	2000/12/30 15:41:40	1.52
+++ usr.sbin/pstat/pstat.c	2001/01/23 00:32:34
@@ -48,8 +48,8 @@
 #include <sys/param.h>
 #include <sys/time.h>
 #include <sys/vnode.h>
-#include <sys/ucred.h>
 #define _KERNEL
+#include <sys/ucred.h>
 #include <sys/file.h>
 #include <ufs/ufs/quota.h>
 #include <ufs/ufs/inode.h>


-- 
 Brian Fundakowski Feldman           \  FreeBSD: The Power to Serve!  /
 green@FreeBSD.org                    `------------------------------'




To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-arch" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200101230358.f0N3wvW01298>