pf: Improve input validation
If we pass an anchor name which doesn't exist pfr_table_count() returns -1, which leads to an overflow in mallocarray() and thus a panic. Explicitly check that pfr_table_count() does not return an error. Reported-by: syzbot+bd09d55d897d63d5f4f4@syzkaller.appspotmail.com Reviewed by: melifaro MFC after: 1 week Differential Revision: https://reviews.freebsd.org/D24539
This commit is contained in:
parent
ab62894faf
commit
4cc4938336
@ -3008,7 +3008,8 @@ pfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct thread *td
|
||||
case DIOCRGETTABLES: {
|
||||
struct pfioc_table *io = (struct pfioc_table *)addr;
|
||||
struct pfr_table *pfrts;
|
||||
size_t totlen, n;
|
||||
size_t totlen;
|
||||
int n;
|
||||
|
||||
if (io->pfrio_esize != sizeof(struct pfr_table)) {
|
||||
error = ENODEV;
|
||||
@ -3016,6 +3017,11 @@ pfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct thread *td
|
||||
}
|
||||
PF_RULES_RLOCK();
|
||||
n = pfr_table_count(&io->pfrio_table, io->pfrio_flags);
|
||||
if (n < 0) {
|
||||
PF_RULES_RUNLOCK();
|
||||
error = EINVAL;
|
||||
break;
|
||||
}
|
||||
io->pfrio_size = min(io->pfrio_size, n);
|
||||
|
||||
totlen = io->pfrio_size * sizeof(struct pfr_table);
|
||||
@ -3039,7 +3045,8 @@ pfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct thread *td
|
||||
case DIOCRGETTSTATS: {
|
||||
struct pfioc_table *io = (struct pfioc_table *)addr;
|
||||
struct pfr_tstats *pfrtstats;
|
||||
size_t totlen, n;
|
||||
size_t totlen;
|
||||
int n;
|
||||
|
||||
if (io->pfrio_esize != sizeof(struct pfr_tstats)) {
|
||||
error = ENODEV;
|
||||
@ -3047,6 +3054,11 @@ pfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct thread *td
|
||||
}
|
||||
PF_RULES_WLOCK();
|
||||
n = pfr_table_count(&io->pfrio_table, io->pfrio_flags);
|
||||
if (n < 0) {
|
||||
PF_RULES_WUNLOCK();
|
||||
error = EINVAL;
|
||||
break;
|
||||
}
|
||||
io->pfrio_size = min(io->pfrio_size, n);
|
||||
|
||||
totlen = io->pfrio_size * sizeof(struct pfr_tstats);
|
||||
@ -3069,7 +3081,8 @@ pfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct thread *td
|
||||
case DIOCRCLRTSTATS: {
|
||||
struct pfioc_table *io = (struct pfioc_table *)addr;
|
||||
struct pfr_table *pfrts;
|
||||
size_t totlen, n;
|
||||
size_t totlen;
|
||||
int n;
|
||||
|
||||
if (io->pfrio_esize != sizeof(struct pfr_table)) {
|
||||
error = ENODEV;
|
||||
@ -3078,6 +3091,11 @@ pfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct thread *td
|
||||
|
||||
PF_RULES_WLOCK();
|
||||
n = pfr_table_count(&io->pfrio_table, io->pfrio_flags);
|
||||
if (n < 0) {
|
||||
PF_RULES_WUNLOCK();
|
||||
error = EINVAL;
|
||||
break;
|
||||
}
|
||||
io->pfrio_size = min(io->pfrio_size, n);
|
||||
|
||||
totlen = io->pfrio_size * sizeof(struct pfr_table);
|
||||
@ -3104,7 +3122,8 @@ pfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct thread *td
|
||||
case DIOCRSETTFLAGS: {
|
||||
struct pfioc_table *io = (struct pfioc_table *)addr;
|
||||
struct pfr_table *pfrts;
|
||||
size_t totlen, n;
|
||||
size_t totlen;
|
||||
int n;
|
||||
|
||||
if (io->pfrio_esize != sizeof(struct pfr_table)) {
|
||||
error = ENODEV;
|
||||
@ -3113,6 +3132,12 @@ pfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct thread *td
|
||||
|
||||
PF_RULES_RLOCK();
|
||||
n = pfr_table_count(&io->pfrio_table, io->pfrio_flags);
|
||||
if (n < 0) {
|
||||
PF_RULES_RUNLOCK();
|
||||
error = EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
io->pfrio_size = min(io->pfrio_size, n);
|
||||
PF_RULES_RUNLOCK();
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user