From owner-freebsd-arch Mon Jan 22 19:59:36 2001 Delivered-To: freebsd-arch@freebsd.org Received: from green.dyndns.org (localhost [127.0.0.1]) by hub.freebsd.org (Postfix) with ESMTP id 41BCC37B400; Mon, 22 Jan 2001 19:59:07 -0800 (PST) Received: from localhost (green@localhost [127.0.0.1]) by green.dyndns.org (8.11.1/8.11.1) with ESMTP id f0N3wvW01298; Mon, 22 Jan 2001 22:58:59 -0500 (EST) (envelope-from green@FreeBSD.org) Message-Id: <200101230358.f0N3wvW01298@green.dyndns.org> X-Mailer: exmh version 2.2 06/23/2000 with nmh-1.0.4 To: arch@FreeBSD.org Cc: alfred@FreeBSD.org Subject: struct ucred is evil and must be contained From: "Brian F. Feldman" Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Date: Mon, 22 Jan 2001 22:58:56 -0500 Sender: owner-freebsd-arch@FreeBSD.ORG Precedence: bulk X-Loop: FreeBSD.ORG 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 /* @@ -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 #include #include -#include #define _KERNEL +#include #include #include #include -- 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