From b4354d10756ff35a0a7faabe8ae43c55f226b13d Mon Sep 17 00:00:00 2001 From: Matthew Dillon Date: Mon, 10 Nov 2008 18:16:52 +0000 Subject: [PATCH] Add required range checks prior to kmalloc()ing socket option buffer space. --- sys/kern/uipc_syscalls.c | 23 ++++++++++++++++------- sys/sys/socket.h | 7 ++++++- 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/sys/kern/uipc_syscalls.c b/sys/kern/uipc_syscalls.c index fa36e53a3b..52a90de5dc 100644 --- a/sys/kern/uipc_syscalls.c +++ b/sys/kern/uipc_syscalls.c @@ -35,7 +35,7 @@ * * @(#)uipc_syscalls.c 8.4 (Berkeley) 2/21/94 * $FreeBSD: src/sys/kern/uipc_syscalls.c,v 1.65.2.17 2003/04/04 17:11:16 tegge Exp $ - * $DragonFly: src/sys/kern/uipc_syscalls.c,v 1.90 2008/10/30 11:03:29 sephe Exp $ + * $DragonFly: src/sys/kern/uipc_syscalls.c,v 1.91 2008/11/10 18:16:52 dillon Exp $ */ #include "opt_ktrace.h" @@ -979,8 +979,9 @@ sys_recvmsg(struct recvmsg_args *uap) if (sa != NULL) { fromlen = MIN(msg.msg_namelen, sa->sa_len); error = copyout(sa, msg.msg_name, fromlen); - } else + } else { fromlen = 0; + } if (error == 0) error = copyout(&fromlen, ufromlenp, sizeof(*ufromlenp)); @@ -1042,7 +1043,7 @@ kern_setsockopt(int s, struct sockopt *sopt) struct file *fp; int error; - if (sopt->sopt_val == 0 && sopt->sopt_valsize != 0) + if (sopt->sopt_val == NULL && sopt->sopt_valsize != 0) return (EFAULT); if (sopt->sopt_valsize < 0) return (EINVAL); @@ -1071,6 +1072,11 @@ sys_setsockopt(struct setsockopt_args *uap) sopt.sopt_valsize = uap->valsize; sopt.sopt_td = td; + if (sopt.sopt_valsize < 0 || sopt.sopt_valsize > SOMAXOPT_SIZE) + return (EINVAL); + if (sopt.sopt_val == NULL && sopt.sopt_valsize) + return (EINVAL); + if (uap->val) { sopt.sopt_val = kmalloc(sopt.sopt_valsize, M_TEMP, M_WAITOK); error = copyin(uap->val, sopt.sopt_val, sopt.sopt_valsize); @@ -1103,9 +1109,9 @@ kern_getsockopt(int s, struct sockopt *sopt) struct file *fp; int error; - if (sopt->sopt_val == 0 && sopt->sopt_valsize != 0) + if (sopt->sopt_val == NULL && sopt->sopt_valsize != 0) return (EFAULT); - if (sopt->sopt_valsize < 0) + if (sopt->sopt_valsize < 0 || sopt->sopt_valsize > SOMAXOPT_SIZE) return (EINVAL); error = holdsock(p->p_fd, s, &fp); @@ -1142,6 +1148,9 @@ sys_getsockopt(struct getsockopt_args *uap) sopt.sopt_valsize = valsize; sopt.sopt_td = td; + if (valsize < 0 || valsize > SOMAXOPT_SIZE) + return (EINVAL); + if (uap->val) { sopt.sopt_val = kmalloc(sopt.sopt_valsize, M_TEMP, M_WAITOK); error = copyin(uap->val, sopt.sopt_val, sopt.sopt_valsize); @@ -1191,7 +1200,7 @@ kern_getsockname(int s, struct sockaddr **name, int *namelen) so = (struct socket *)fp->f_data; error = so_pru_sockaddr(so, &sa); if (error == 0) { - if (sa == 0) { + if (sa == NULL) { *namelen = 0; } else { *namelen = MIN(*namelen, sa->sa_len); @@ -1259,7 +1268,7 @@ kern_getpeername(int s, struct sockaddr **name, int *namelen) } error = so_pru_peeraddr(so, &sa); if (error == 0) { - if (sa == 0) { + if (sa == NULL) { *namelen = 0; } else { *namelen = MIN(*namelen, sa->sa_len); diff --git a/sys/sys/socket.h b/sys/sys/socket.h index 5ccdd2164c..2430e048b6 100644 --- a/sys/sys/socket.h +++ b/sys/sys/socket.h @@ -32,7 +32,7 @@ * * @(#)socket.h 8.4 (Berkeley) 2/21/94 * $FreeBSD: src/sys/sys/socket.h,v 1.39.2.7 2001/07/03 11:02:01 ume Exp $ - * $DragonFly: src/sys/sys/socket.h,v 1.22 2008/07/07 22:02:10 nant Exp $ + * $DragonFly: src/sys/sys/socket.h,v 1.23 2008/11/10 18:16:51 dillon Exp $ */ #ifndef _SYS_SOCKET_H_ @@ -330,6 +330,11 @@ struct sockaddr_storage { #define SOMAXCONN 128 /* + * Maximum setsockopt buffer size + */ +#define SOMAXOPT_SIZE 65536 + +/* * Message header for recvmsg and sendmsg calls. * Used value-result for recvmsg, value only for sendmsg. */ -- 2.11.4.GIT