mirror of
https://github.com/freebsd/freebsd-src
synced 2024-10-15 04:43:53 +00:00
o Make the credential used by socreate() an explicit argument to
socreate(), rather than getting it implicitly from the thread argument. o Make NFS cache the credential provided at mount-time, and use the cached credential (nfsmount->nm_cred) when making calls to socreate() on initially connecting, or reconnecting the socket. This fixes bugs involving NFS over TCP and ipfw uid/gid rules, as well as bugs involving NFS and mandatory access control implementations. Reviewed by: freebsd-arch
This commit is contained in:
parent
536550c3f2
commit
9c4d63da6d
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=88739
|
@ -264,7 +264,8 @@ streamsopen(dev_t dev, int oflags, int devtype, struct thread *td)
|
|||
if ((error = falloc(td, &fp, &fd)) != 0)
|
||||
return error;
|
||||
|
||||
if ((error = socreate(family, &so, type, protocol, td)) != 0) {
|
||||
if ((error = socreate(family, &so, type, protocol,
|
||||
td->td_proc->p_ucred, td)) != 0) {
|
||||
p->p_fd->fd_ofiles[fd] = 0;
|
||||
ffree(fp);
|
||||
return error;
|
||||
|
|
|
@ -174,14 +174,16 @@ fifo_open(ap)
|
|||
if ((fip = vp->v_fifoinfo) == NULL) {
|
||||
MALLOC(fip, struct fifoinfo *, sizeof(*fip), M_VNODE, M_WAITOK);
|
||||
vp->v_fifoinfo = fip;
|
||||
error = socreate(AF_LOCAL, &rso, SOCK_STREAM, 0, ap->a_td);
|
||||
error = socreate(AF_LOCAL, &rso, SOCK_STREAM, 0,
|
||||
ap->a_td->td_proc->p_ucred, ap->a_td);
|
||||
if (error) {
|
||||
free(fip, M_VNODE);
|
||||
vp->v_fifoinfo = NULL;
|
||||
return (error);
|
||||
}
|
||||
fip->fi_readsock = rso;
|
||||
error = socreate(AF_LOCAL, &wso, SOCK_STREAM, 0, ap->a_td);
|
||||
error = socreate(AF_LOCAL, &wso, SOCK_STREAM, 0,
|
||||
ap->a_td->td_proc->p_ucred, ap->a_td);
|
||||
if (error) {
|
||||
(void)soclose(rso);
|
||||
free(fip, M_VNODE);
|
||||
|
|
|
@ -246,7 +246,8 @@ portal_open(ap)
|
|||
/*
|
||||
* Create a new socket.
|
||||
*/
|
||||
error = socreate(AF_UNIX, &so, SOCK_STREAM, 0, ap->a_td);
|
||||
error = socreate(AF_UNIX, &so, SOCK_STREAM, 0,
|
||||
ap->a_td->td_proc->p_ucred, ap->a_td);
|
||||
if (error)
|
||||
goto bad;
|
||||
|
||||
|
|
|
@ -137,11 +137,12 @@ soalloc(waitok)
|
|||
* closed with soclose().
|
||||
*/
|
||||
int
|
||||
socreate(dom, aso, type, proto, td)
|
||||
socreate(dom, aso, type, proto, cred, td)
|
||||
int dom;
|
||||
struct socket **aso;
|
||||
register int type;
|
||||
int proto;
|
||||
struct ucred *cred;
|
||||
struct thread *td;
|
||||
{
|
||||
register struct protosw *prp;
|
||||
|
@ -172,7 +173,7 @@ socreate(dom, aso, type, proto, td)
|
|||
TAILQ_INIT(&so->so_incomp);
|
||||
TAILQ_INIT(&so->so_comp);
|
||||
so->so_type = type;
|
||||
so->so_cred = crhold(td->td_proc->p_ucred);
|
||||
so->so_cred = crhold(cred);
|
||||
so->so_proto = prp;
|
||||
soref(so);
|
||||
error = (*prp->pr_usrreqs->pru_attach)(so, proto, td);
|
||||
|
|
|
@ -132,7 +132,8 @@ socket(td, uap)
|
|||
if (error)
|
||||
goto done2;
|
||||
fhold(fp);
|
||||
error = socreate(uap->domain, &so, uap->type, uap->protocol, td);
|
||||
error = socreate(uap->domain, &so, uap->type, uap->protocol,
|
||||
td->td_proc->p_ucred, td);
|
||||
if (error) {
|
||||
if (fdp->fd_ofiles[fd] == fp) {
|
||||
fdp->fd_ofiles[fd] = NULL;
|
||||
|
@ -478,10 +479,12 @@ socketpair(td, uap)
|
|||
int fd, error, sv[2];
|
||||
|
||||
mtx_lock(&Giant);
|
||||
error = socreate(uap->domain, &so1, uap->type, uap->protocol, td);
|
||||
error = socreate(uap->domain, &so1, uap->type, uap->protocol,
|
||||
td->td_proc->p_ucred, td);
|
||||
if (error)
|
||||
goto done2;
|
||||
error = socreate(uap->domain, &so2, uap->type, uap->protocol, td);
|
||||
error = socreate(uap->domain, &so2, uap->type, uap->protocol,
|
||||
td->td_proc->p_ucred, td);
|
||||
if (error)
|
||||
goto free1;
|
||||
error = falloc(td, &fp1, &fd);
|
||||
|
|
|
@ -586,7 +586,8 @@ ng_ksocket_newhook(node_p node, hook_p hook, const char *name0)
|
|||
return (EINVAL);
|
||||
|
||||
/* Create the socket */
|
||||
error = socreate(family, &priv->so, type, protocol, td);
|
||||
error = socreate(family, &priv->so, type, protocol,
|
||||
td->td_proc->p_ucred, td);
|
||||
if (error != 0)
|
||||
return (error);
|
||||
|
||||
|
|
|
@ -226,7 +226,8 @@ nb_connect_in(struct nbpcb *nbp, struct sockaddr_in *to, struct thread *td)
|
|||
struct socket *so;
|
||||
int error, s;
|
||||
|
||||
error = socreate(AF_INET, &so, SOCK_STREAM, IPPROTO_TCP, td);
|
||||
error = socreate(AF_INET, &so, SOCK_STREAM, IPPROTO_TCP,
|
||||
td->td_proc->p_ucred, td);
|
||||
if (error)
|
||||
return error;
|
||||
nbp->nbp_tso = so;
|
||||
|
|
|
@ -586,7 +586,8 @@ bootpc_call(struct bootpc_globalcontext *gctx, struct thread *td)
|
|||
/*
|
||||
* Create socket and set its recieve timeout.
|
||||
*/
|
||||
error = socreate(AF_INET, &so, SOCK_DGRAM, 0, td);
|
||||
error = socreate(AF_INET, &so, SOCK_DGRAM, 0, td->td_proc->p_ucred,
|
||||
td);
|
||||
if (error != 0)
|
||||
goto out;
|
||||
|
||||
|
@ -971,7 +972,8 @@ bootpc_fakeup_interface(struct bootpc_ifcontext *ifctx,
|
|||
struct ifaddr *ifa;
|
||||
struct sockaddr_dl *sdl;
|
||||
|
||||
error = socreate(AF_INET, &ifctx->so, SOCK_DGRAM, 0, td);
|
||||
error = socreate(AF_INET, &ifctx->so, SOCK_DGRAM, 0,
|
||||
td->td_proc->p_ucred, td);
|
||||
if (error != 0)
|
||||
panic("nfs_boot: socreate, error=%d", error);
|
||||
|
||||
|
|
|
@ -215,7 +215,8 @@ krpc_call(struct sockaddr_in *sa, u_int prog, u_int vers, u_int func,
|
|||
/*
|
||||
* Create socket and set its recieve timeout.
|
||||
*/
|
||||
if ((error = socreate(AF_INET, &so, SOCK_DGRAM, 0, td)))
|
||||
if ((error = socreate(AF_INET, &so, SOCK_DGRAM, 0,
|
||||
td->td_proc->p_ucred, td)))
|
||||
goto out;
|
||||
|
||||
tv.tv_sec = 1;
|
||||
|
|
|
@ -163,7 +163,7 @@ nfs_connect(struct nfsmount *nmp, struct nfsreq *rep)
|
|||
nmp->nm_so = (struct socket *)0;
|
||||
saddr = nmp->nm_nam;
|
||||
error = socreate(saddr->sa_family, &nmp->nm_so, nmp->nm_sotype,
|
||||
nmp->nm_soproto, td);
|
||||
nmp->nm_soproto, nmp->nm_cred, td);
|
||||
if (error)
|
||||
goto bad;
|
||||
so = nmp->nm_so;
|
||||
|
|
|
@ -92,7 +92,8 @@ SYSCTL_INT(_vfs_nfs, OID_AUTO, debug, CTLFLAG_RW, &nfs_debug, 0, "");
|
|||
static int nfs_iosize(struct nfsmount *nmp);
|
||||
static void nfs_decode_args(struct nfsmount *nmp, struct nfs_args *argp);
|
||||
static int mountnfs(struct nfs_args *, struct mount *,
|
||||
struct sockaddr *, char *, char *, struct vnode **);
|
||||
struct sockaddr *, char *, char *, struct vnode **,
|
||||
struct ucred *cred);
|
||||
static int nfs_mount(struct mount *mp, char *path, caddr_t data,
|
||||
struct nameidata *ndp, struct thread *td);
|
||||
static int nfs_unmount(struct mount *mp, int mntflags, struct thread *td);
|
||||
|
@ -377,6 +378,7 @@ int
|
|||
nfs_mountroot(struct mount *mp)
|
||||
{
|
||||
struct mount *swap_mp;
|
||||
struct nfsmount *nmp = VFSTONFS(mp);
|
||||
struct nfsv3_diskless *nd = &nfsv3_diskless;
|
||||
struct socket *so;
|
||||
struct vnode *vp;
|
||||
|
@ -419,7 +421,8 @@ nfs_mountroot(struct mount *mp)
|
|||
* Do enough of ifconfig(8) so that the critical net interface can
|
||||
* talk to the server.
|
||||
*/
|
||||
error = socreate(nd->myif.ifra_addr.sa_family, &so, SOCK_DGRAM, 0, td);
|
||||
error = socreate(nd->myif.ifra_addr.sa_family, &so, SOCK_DGRAM, 0,
|
||||
nmp->nm_cred, td);
|
||||
if (error)
|
||||
panic("nfs_mountroot: socreate(%04x): %d",
|
||||
nd->myif.ifra_addr.sa_family, error);
|
||||
|
@ -557,7 +560,8 @@ nfs_mountdiskless(char *path, char *which, int mountflag,
|
|||
mp->mnt_kern_flag = 0;
|
||||
mp->mnt_flag = mountflag;
|
||||
nam = dup_sockaddr((struct sockaddr *)sin, 1);
|
||||
if ((error = mountnfs(args, mp, nam, which, path, vpp)) != 0) {
|
||||
if ((error = mountnfs(args, mp, nam, which, path, vpp, td->td_ucred))
|
||||
!= 0) {
|
||||
printf("nfs_mountroot: mount %s on %s: %d", path, which, error);
|
||||
mp->mnt_vfc->vfc_refcount--;
|
||||
vfs_unbusy(mp, td);
|
||||
|
@ -785,7 +789,7 @@ nfs_mount(struct mount *mp, char *path, caddr_t data, struct nameidata *ndp,
|
|||
if (error)
|
||||
return (error);
|
||||
args.fh = nfh;
|
||||
error = mountnfs(&args, mp, nam, path, hst, &vp);
|
||||
error = mountnfs(&args, mp, nam, path, hst, &vp, td->td_ucred);
|
||||
return (error);
|
||||
}
|
||||
|
||||
|
@ -794,7 +798,7 @@ nfs_mount(struct mount *mp, char *path, caddr_t data, struct nameidata *ndp,
|
|||
*/
|
||||
static int
|
||||
mountnfs(struct nfs_args *argp, struct mount *mp, struct sockaddr *nam,
|
||||
char *pth, char *hst, struct vnode **vpp)
|
||||
char *pth, char *hst, struct vnode **vpp, struct ucred *cred)
|
||||
{
|
||||
struct nfsmount *nmp;
|
||||
struct nfsnode *np;
|
||||
|
@ -814,6 +818,7 @@ mountnfs(struct nfs_args *argp, struct mount *mp, struct sockaddr *nam,
|
|||
}
|
||||
vfs_getnewfsid(mp);
|
||||
nmp->nm_mountp = mp;
|
||||
nmp->nm_cred = crhold(cred);
|
||||
|
||||
/*
|
||||
* V2 can only handle 32 bit filesizes. A 4GB-1 limit may be too
|
||||
|
@ -891,6 +896,7 @@ mountnfs(struct nfs_args *argp, struct mount *mp, struct sockaddr *nam,
|
|||
return (0);
|
||||
bad:
|
||||
nfs_disconnect(nmp);
|
||||
crfree(nmp->nm_cred);
|
||||
zfree(nfsmount_zone, nmp);
|
||||
FREE(nam, M_SONAME);
|
||||
return (error);
|
||||
|
@ -925,6 +931,7 @@ nfs_unmount(struct mount *mp, int mntflags, struct thread *td)
|
|||
nfs_disconnect(nmp);
|
||||
FREE(nmp->nm_nam, M_SONAME);
|
||||
|
||||
crfree(nmp->nm_cred);
|
||||
zfree(nfsmount_zone, nmp);
|
||||
return (0);
|
||||
}
|
||||
|
|
|
@ -53,6 +53,7 @@ struct nfsmount {
|
|||
u_char nm_fh[NFSX_V3FHMAX]; /* File handle of root dir */
|
||||
int nm_fhsize; /* Size of root file handle */
|
||||
struct socket *nm_so; /* Rpc socket */
|
||||
struct ucred *nm_cred; /* Cached mount-time credential */
|
||||
int nm_sotype; /* Type of socket */
|
||||
int nm_soproto; /* and protocol */
|
||||
int nm_soflags; /* pr_flags for socket protocol */
|
||||
|
|
|
@ -383,7 +383,7 @@ int soclose __P((struct socket *so));
|
|||
int soconnect __P((struct socket *so, struct sockaddr *nam, struct thread *td));
|
||||
int soconnect2 __P((struct socket *so1, struct socket *so2));
|
||||
int socreate __P((int dom, struct socket **aso, int type, int proto,
|
||||
struct thread *td));
|
||||
struct ucred *cred, struct thread *td));
|
||||
int sodisconnect __P((struct socket *so));
|
||||
void sofree __P((struct socket *so));
|
||||
int sogetopt __P((struct socket *so, struct sockopt *sopt));
|
||||
|
|
Loading…
Reference in a new issue