pf: Fix panic on invalid DIOCRSETTFLAGS
If during DIOCRSETTFLAGS pfrio_buffer is NULL copyin() will fault, which we're not allowed to do with a lock held. We must count the number of entries in the table and release the lock during copyin(). Only then can we re-acquire the lock. Note that this is safe, because pfr_set_tflags() will check if the table and entries exist. This was discovered by a local syzcaller instance. MFC after: 1 week Event: Aberdeen hackathon 2019
This commit is contained in:
parent
b6539d47bd
commit
f5e0d9fcb4
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=346319
@ -3103,24 +3103,24 @@ pfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct thread *td
|
||||
break;
|
||||
}
|
||||
|
||||
PF_RULES_WLOCK();
|
||||
PF_RULES_RLOCK();
|
||||
n = pfr_table_count(&io->pfrio_table, io->pfrio_flags);
|
||||
io->pfrio_size = min(io->pfrio_size, n);
|
||||
PF_RULES_RUNLOCK();
|
||||
|
||||
totlen = io->pfrio_size * sizeof(struct pfr_table);
|
||||
pfrts = mallocarray(io->pfrio_size, sizeof(struct pfr_table),
|
||||
M_TEMP, M_NOWAIT);
|
||||
if (pfrts == NULL) {
|
||||
error = ENOMEM;
|
||||
PF_RULES_WUNLOCK();
|
||||
break;
|
||||
}
|
||||
error = copyin(io->pfrio_buffer, pfrts, totlen);
|
||||
if (error) {
|
||||
free(pfrts, M_TEMP);
|
||||
PF_RULES_WUNLOCK();
|
||||
break;
|
||||
}
|
||||
PF_RULES_WLOCK();
|
||||
error = pfr_set_tflags(pfrts, io->pfrio_size,
|
||||
io->pfrio_setflag, io->pfrio_clrflag, &io->pfrio_nchange,
|
||||
&io->pfrio_ndel, io->pfrio_flags | PFR_FLAG_USERIOCTL);
|
||||
|
Loading…
Reference in New Issue
Block a user