Add fdallocn function and use it when passing fds over unix socket.
This gets rid of "unp_externalize fdalloc failed" panic. Reviewed by: pjd MFC after: 1 week
This commit is contained in:
parent
fb69d3e351
commit
db8f33fd32
@ -1581,6 +1581,34 @@ fdalloc(struct thread *td, int minfd, int *result)
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate n file descriptors for the process.
|
||||
*/
|
||||
int
|
||||
fdallocn(struct thread *td, int minfd, int *fds, int n)
|
||||
{
|
||||
struct proc *p = td->td_proc;
|
||||
struct filedesc *fdp = p->p_fd;
|
||||
int i;
|
||||
|
||||
FILEDESC_XLOCK_ASSERT(fdp);
|
||||
|
||||
if (!fdavail(td, n))
|
||||
return (EMFILE);
|
||||
|
||||
for (i = 0; i < n; i++)
|
||||
if (fdalloc(td, 0, &fds[i]) != 0)
|
||||
break;
|
||||
|
||||
if (i < n) {
|
||||
for (i--; i >= 0; i--)
|
||||
fdunused(fdp, fds[i]);
|
||||
return (EMFILE);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Check to see whether n user file descriptors are available to the process
|
||||
* p.
|
||||
|
@ -1706,7 +1706,6 @@ unp_externalize(struct mbuf *control, struct mbuf **controlp, int flags)
|
||||
void *data;
|
||||
socklen_t clen = control->m_len, datalen;
|
||||
int error, newfds;
|
||||
int f;
|
||||
u_int newlen;
|
||||
|
||||
UNP_LINK_UNLOCK_ASSERT();
|
||||
@ -1732,13 +1731,6 @@ unp_externalize(struct mbuf *control, struct mbuf **controlp, int flags)
|
||||
goto next;
|
||||
}
|
||||
FILEDESC_XLOCK(fdesc);
|
||||
/* if the new FD's will not fit free them. */
|
||||
if (!fdavail(td, newfds)) {
|
||||
FILEDESC_XUNLOCK(fdesc);
|
||||
error = EMSGSIZE;
|
||||
unp_freerights(fdep, newfds);
|
||||
goto next;
|
||||
}
|
||||
|
||||
/*
|
||||
* Now change each pointer to an fd in the global
|
||||
@ -1758,17 +1750,22 @@ unp_externalize(struct mbuf *control, struct mbuf **controlp, int flags)
|
||||
|
||||
fdp = (int *)
|
||||
CMSG_DATA(mtod(*controlp, struct cmsghdr *));
|
||||
if (fdallocn(td, 0, fdp, newfds) != 0) {
|
||||
FILEDESC_XUNLOCK(td->td_proc->p_fd);
|
||||
error = EMSGSIZE;
|
||||
unp_freerights(fdep, newfds);
|
||||
m_freem(*controlp);
|
||||
*controlp = NULL;
|
||||
goto next;
|
||||
}
|
||||
for (i = 0; i < newfds; i++, fdp++) {
|
||||
if (fdalloc(td, 0, &f))
|
||||
panic("unp_externalize fdalloc failed");
|
||||
fde = &fdesc->fd_ofiles[f];
|
||||
fde = &fdesc->fd_ofiles[*fdp];
|
||||
fde->fde_file = fdep[0]->fde_file;
|
||||
filecaps_move(&fdep[0]->fde_caps,
|
||||
&fde->fde_caps);
|
||||
if ((flags & MSG_CMSG_CLOEXEC) != 0)
|
||||
fde->fde_flags |= UF_EXCLOSE;
|
||||
unp_externalize_fp(fde->fde_file);
|
||||
*fdp = f;
|
||||
}
|
||||
FILEDESC_XUNLOCK(fdesc);
|
||||
free(fdep[0], M_FILECAPS);
|
||||
|
@ -150,6 +150,7 @@ int falloc_noinstall(struct thread *td, struct file **resultfp);
|
||||
int finstall(struct thread *td, struct file *fp, int *resultfp, int flags,
|
||||
struct filecaps *fcaps);
|
||||
int fdalloc(struct thread *td, int minfd, int *result);
|
||||
int fdallocn(struct thread *td, int minfd, int *fds, int n);
|
||||
int fdavail(struct thread *td, int n);
|
||||
int fdcheckstd(struct thread *td);
|
||||
void fdclose(struct filedesc *fdp, struct file *fp, int idx, struct thread *td);
|
||||
|
Loading…
Reference in New Issue
Block a user