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
db20acc029
commit
a7c8533634
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=360344
@ -3008,7 +3008,8 @@ pfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct thread *td
|
|||||||
case DIOCRGETTABLES: {
|
case DIOCRGETTABLES: {
|
||||||
struct pfioc_table *io = (struct pfioc_table *)addr;
|
struct pfioc_table *io = (struct pfioc_table *)addr;
|
||||||
struct pfr_table *pfrts;
|
struct pfr_table *pfrts;
|
||||||
size_t totlen, n;
|
size_t totlen;
|
||||||
|
int n;
|
||||||
|
|
||||||
if (io->pfrio_esize != sizeof(struct pfr_table)) {
|
if (io->pfrio_esize != sizeof(struct pfr_table)) {
|
||||||
error = ENODEV;
|
error = ENODEV;
|
||||||
@ -3016,6 +3017,11 @@ pfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct thread *td
|
|||||||
}
|
}
|
||||||
PF_RULES_RLOCK();
|
PF_RULES_RLOCK();
|
||||||
n = pfr_table_count(&io->pfrio_table, io->pfrio_flags);
|
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);
|
io->pfrio_size = min(io->pfrio_size, n);
|
||||||
|
|
||||||
totlen = io->pfrio_size * sizeof(struct pfr_table);
|
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: {
|
case DIOCRGETTSTATS: {
|
||||||
struct pfioc_table *io = (struct pfioc_table *)addr;
|
struct pfioc_table *io = (struct pfioc_table *)addr;
|
||||||
struct pfr_tstats *pfrtstats;
|
struct pfr_tstats *pfrtstats;
|
||||||
size_t totlen, n;
|
size_t totlen;
|
||||||
|
int n;
|
||||||
|
|
||||||
if (io->pfrio_esize != sizeof(struct pfr_tstats)) {
|
if (io->pfrio_esize != sizeof(struct pfr_tstats)) {
|
||||||
error = ENODEV;
|
error = ENODEV;
|
||||||
@ -3047,6 +3054,11 @@ pfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct thread *td
|
|||||||
}
|
}
|
||||||
PF_RULES_WLOCK();
|
PF_RULES_WLOCK();
|
||||||
n = pfr_table_count(&io->pfrio_table, io->pfrio_flags);
|
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);
|
io->pfrio_size = min(io->pfrio_size, n);
|
||||||
|
|
||||||
totlen = io->pfrio_size * sizeof(struct pfr_tstats);
|
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: {
|
case DIOCRCLRTSTATS: {
|
||||||
struct pfioc_table *io = (struct pfioc_table *)addr;
|
struct pfioc_table *io = (struct pfioc_table *)addr;
|
||||||
struct pfr_table *pfrts;
|
struct pfr_table *pfrts;
|
||||||
size_t totlen, n;
|
size_t totlen;
|
||||||
|
int n;
|
||||||
|
|
||||||
if (io->pfrio_esize != sizeof(struct pfr_table)) {
|
if (io->pfrio_esize != sizeof(struct pfr_table)) {
|
||||||
error = ENODEV;
|
error = ENODEV;
|
||||||
@ -3078,6 +3091,11 @@ pfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct thread *td
|
|||||||
|
|
||||||
PF_RULES_WLOCK();
|
PF_RULES_WLOCK();
|
||||||
n = pfr_table_count(&io->pfrio_table, io->pfrio_flags);
|
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);
|
io->pfrio_size = min(io->pfrio_size, n);
|
||||||
|
|
||||||
totlen = io->pfrio_size * sizeof(struct pfr_table);
|
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: {
|
case DIOCRSETTFLAGS: {
|
||||||
struct pfioc_table *io = (struct pfioc_table *)addr;
|
struct pfioc_table *io = (struct pfioc_table *)addr;
|
||||||
struct pfr_table *pfrts;
|
struct pfr_table *pfrts;
|
||||||
size_t totlen, n;
|
size_t totlen;
|
||||||
|
int n;
|
||||||
|
|
||||||
if (io->pfrio_esize != sizeof(struct pfr_table)) {
|
if (io->pfrio_esize != sizeof(struct pfr_table)) {
|
||||||
error = ENODEV;
|
error = ENODEV;
|
||||||
@ -3113,6 +3132,12 @@ pfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct thread *td
|
|||||||
|
|
||||||
PF_RULES_RLOCK();
|
PF_RULES_RLOCK();
|
||||||
n = pfr_table_count(&io->pfrio_table, io->pfrio_flags);
|
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);
|
io->pfrio_size = min(io->pfrio_size, n);
|
||||||
PF_RULES_RUNLOCK();
|
PF_RULES_RUNLOCK();
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user