fd: tighten seq protected areas to not contain malloc/free
This commit is contained in:
parent
2f68cdb944
commit
179da98f71
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=331657
@ -111,6 +111,11 @@ static void fdgrowtable_exp(struct filedesc *fdp, int nfd);
|
||||
static void fdunused(struct filedesc *fdp, int fd);
|
||||
static void fdused(struct filedesc *fdp, int fd);
|
||||
static int getmaxfd(struct thread *td);
|
||||
static u_long *filecaps_copy_prep(const struct filecaps *src);
|
||||
static void filecaps_copy_finish(const struct filecaps *src,
|
||||
struct filecaps *dst, u_long *ioctls);
|
||||
static u_long *filecaps_free_prep(struct filecaps *fcaps);
|
||||
static void filecaps_free_finish(u_long *ioctls);
|
||||
|
||||
/*
|
||||
* Each process has:
|
||||
@ -302,12 +307,12 @@ fdfree(struct filedesc *fdp, int fd)
|
||||
#ifdef CAPABILITIES
|
||||
seq_write_begin(&fde->fde_seq);
|
||||
#endif
|
||||
fdefree_last(fde);
|
||||
fde->fde_file = NULL;
|
||||
fdunused(fdp, fd);
|
||||
#ifdef CAPABILITIES
|
||||
seq_write_end(&fde->fde_seq);
|
||||
#endif
|
||||
fdefree_last(fde);
|
||||
fdunused(fdp, fd);
|
||||
}
|
||||
|
||||
void
|
||||
@ -813,6 +818,7 @@ kern_dup(struct thread *td, u_int mode, int flags, int old, int new)
|
||||
struct filedescent *oldfde, *newfde;
|
||||
struct proc *p;
|
||||
struct file *delfp;
|
||||
u_long *oioctls, *nioctls;
|
||||
int error, maxfd;
|
||||
|
||||
p = td->td_proc;
|
||||
@ -902,15 +908,18 @@ kern_dup(struct thread *td, u_int mode, int flags, int old, int new)
|
||||
newfde = &fdp->fd_ofiles[new];
|
||||
delfp = newfde->fde_file;
|
||||
|
||||
oioctls = filecaps_free_prep(&newfde->fde_caps);
|
||||
nioctls = filecaps_copy_prep(&oldfde->fde_caps);
|
||||
|
||||
/*
|
||||
* Duplicate the source descriptor.
|
||||
*/
|
||||
#ifdef CAPABILITIES
|
||||
seq_write_begin(&newfde->fde_seq);
|
||||
#endif
|
||||
filecaps_free(&newfde->fde_caps);
|
||||
memcpy(newfde, oldfde, fde_change_size);
|
||||
filecaps_copy(&oldfde->fde_caps, &newfde->fde_caps, true);
|
||||
filecaps_copy_finish(&oldfde->fde_caps, &newfde->fde_caps,
|
||||
nioctls);
|
||||
if ((flags & FDDUP_FLAG_CLOEXEC) != 0)
|
||||
newfde->fde_flags = oldfde->fde_flags | UF_EXCLOSE;
|
||||
else
|
||||
@ -918,6 +927,7 @@ kern_dup(struct thread *td, u_int mode, int flags, int old, int new)
|
||||
#ifdef CAPABILITIES
|
||||
seq_write_end(&newfde->fde_seq);
|
||||
#endif
|
||||
filecaps_free_finish(oioctls);
|
||||
td->td_retval[0] = new;
|
||||
|
||||
error = 0;
|
||||
@ -1503,6 +1513,40 @@ filecaps_copy(const struct filecaps *src, struct filecaps *dst, bool locked)
|
||||
return (0);
|
||||
}
|
||||
|
||||
static u_long *
|
||||
filecaps_copy_prep(const struct filecaps *src)
|
||||
{
|
||||
u_long *ioctls;
|
||||
size_t size;
|
||||
|
||||
if (src->fc_ioctls == NULL)
|
||||
return (NULL);
|
||||
|
||||
KASSERT(src->fc_nioctls > 0,
|
||||
("fc_ioctls != NULL, but fc_nioctls=%hd", src->fc_nioctls));
|
||||
|
||||
size = sizeof(src->fc_ioctls[0]) * src->fc_nioctls;
|
||||
ioctls = malloc(size, M_FILECAPS, M_WAITOK);
|
||||
return (ioctls);
|
||||
}
|
||||
|
||||
static void
|
||||
filecaps_copy_finish(const struct filecaps *src, struct filecaps *dst,
|
||||
u_long *ioctls)
|
||||
{
|
||||
size_t size;
|
||||
|
||||
*dst = *src;
|
||||
if (src->fc_ioctls == NULL) {
|
||||
MPASS(ioctls == NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
size = sizeof(src->fc_ioctls[0]) * src->fc_nioctls;
|
||||
dst->fc_ioctls = ioctls;
|
||||
bcopy(src->fc_ioctls, dst->fc_ioctls, size);
|
||||
}
|
||||
|
||||
/*
|
||||
* Move filecaps structure to the new place and clear the old place.
|
||||
*/
|
||||
@ -1538,6 +1582,23 @@ filecaps_free(struct filecaps *fcaps)
|
||||
bzero(fcaps, sizeof(*fcaps));
|
||||
}
|
||||
|
||||
static u_long *
|
||||
filecaps_free_prep(struct filecaps *fcaps)
|
||||
{
|
||||
u_long *ioctls;
|
||||
|
||||
ioctls = fcaps->fc_ioctls;
|
||||
bzero(fcaps, sizeof(*fcaps));
|
||||
return (ioctls);
|
||||
}
|
||||
|
||||
static void
|
||||
filecaps_free_finish(u_long *ioctls)
|
||||
{
|
||||
|
||||
free(ioctls, M_FILECAPS);
|
||||
}
|
||||
|
||||
/*
|
||||
* Validate the given filecaps structure.
|
||||
*/
|
||||
@ -2963,6 +3024,7 @@ dupfdopen(struct thread *td, struct filedesc *fdp, int dfd, int mode,
|
||||
{
|
||||
struct filedescent *newfde, *oldfde;
|
||||
struct file *fp;
|
||||
u_long *ioctls;
|
||||
int error, indx;
|
||||
|
||||
KASSERT(openerror == ENODEV || openerror == ENXIO,
|
||||
@ -3007,11 +3069,13 @@ dupfdopen(struct thread *td, struct filedesc *fdp, int dfd, int mode,
|
||||
fhold(fp);
|
||||
newfde = &fdp->fd_ofiles[indx];
|
||||
oldfde = &fdp->fd_ofiles[dfd];
|
||||
ioctls = filecaps_copy_prep(&oldfde->fde_caps);
|
||||
#ifdef CAPABILITIES
|
||||
seq_write_begin(&newfde->fde_seq);
|
||||
#endif
|
||||
memcpy(newfde, oldfde, fde_change_size);
|
||||
filecaps_copy(&oldfde->fde_caps, &newfde->fde_caps, true);
|
||||
filecaps_copy_finish(&oldfde->fde_caps, &newfde->fde_caps,
|
||||
ioctls);
|
||||
#ifdef CAPABILITIES
|
||||
seq_write_end(&newfde->fde_seq);
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user