Plug another overflow: refuse bogus sa_len from user.
This commit is contained in:
parent
befe278cf1
commit
cf6e54504a
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: smb_subr.c,v 1.37 2014/11/15 18:52:45 nakayama Exp $ */
|
||||
/* $NetBSD: smb_subr.c,v 1.38 2017/07/28 14:37:27 riastradh Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2000-2001 Boris Popov
|
||||
|
@ -35,7 +35,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: smb_subr.c,v 1.37 2014/11/15 18:52:45 nakayama Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: smb_subr.c,v 1.38 2017/07/28 14:37:27 riastradh Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
|
@ -380,3 +380,32 @@ dup_sockaddr(struct sockaddr *sa, int canwait)
|
|||
memcpy(sa2, sa, sa->sa_len);
|
||||
return sa2;
|
||||
}
|
||||
|
||||
int
|
||||
dup_sockaddr_copyin(struct sockaddr **ksap, struct sockaddr *usa,
|
||||
size_t usalen)
|
||||
{
|
||||
struct sockaddr *ksa;
|
||||
|
||||
/* Make sure user provided enough data for a generic sockaddr. */
|
||||
if (usalen < sizeof(*ksa))
|
||||
return EINVAL;
|
||||
|
||||
/* Don't let the user overfeed us. */
|
||||
usalen = MIN(usalen, sizeof(struct sockaddr_storage));
|
||||
|
||||
/* Copy the buffer in from userland. */
|
||||
ksa = smb_memdupin(usa, usalen);
|
||||
if (ksa == NULL)
|
||||
return ENOMEM;
|
||||
|
||||
/* Make sure the user's idea of sa_len is reasonable. */
|
||||
if (ksa->sa_len > usalen) {
|
||||
smb_memfree(ksa);
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
/* Success! */
|
||||
*ksap = ksa;
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: smb_subr.h,v 1.21 2012/03/13 18:41:01 elad Exp $ */
|
||||
/* $NetBSD: smb_subr.h,v 1.22 2017/07/28 14:37:27 riastradh Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2000-2001, Boris Popov
|
||||
|
@ -128,5 +128,6 @@ int smb_put_asunistring(struct smb_rq *rqp, const char *src);
|
|||
#endif
|
||||
|
||||
struct sockaddr *dup_sockaddr(struct sockaddr *, int);
|
||||
int dup_sockaddr_copyin(struct sockaddr **, struct sockaddr *, size_t);
|
||||
|
||||
#endif /* !_NETSMB_SMB_SUBR_H_ */
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: smb_usr.c,v 1.17 2017/07/28 14:20:46 riastradh Exp $ */
|
||||
/* $NetBSD: smb_usr.c,v 1.18 2017/07/28 14:37:27 riastradh Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2000-2001 Boris Popov
|
||||
|
@ -35,7 +35,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: smb_usr.c,v 1.17 2017/07/28 14:20:46 riastradh Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: smb_usr.c,v 1.18 2017/07/28 14:37:27 riastradh Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/malloc.h>
|
||||
|
@ -65,6 +65,7 @@ static int
|
|||
smb_usr_vc2spec(struct smbioc_ossn *dp, struct smb_vcspec *spec)
|
||||
{
|
||||
int flags = 0;
|
||||
int error;
|
||||
|
||||
memset(spec, 0, sizeof(*spec));
|
||||
if (dp->ioc_user[0] == 0)
|
||||
|
@ -75,21 +76,16 @@ smb_usr_vc2spec(struct smbioc_ossn *dp, struct smb_vcspec *spec)
|
|||
SMBERROR(("no local charset ?\n"));
|
||||
return EINVAL;
|
||||
}
|
||||
if (dp->ioc_svlen < sizeof(*spec->sap))
|
||||
return EINVAL;
|
||||
|
||||
spec->sap = smb_memdupin(dp->ioc_server, dp->ioc_svlen);
|
||||
if (spec->sap == NULL)
|
||||
return ENOMEM;
|
||||
error = dup_sockaddr_copyin(&spec->sap, dp->ioc_server, dp->ioc_svlen);
|
||||
if (error)
|
||||
return error;
|
||||
if (dp->ioc_local) {
|
||||
if (dp->ioc_lolen < sizeof(*spec->lap)) {
|
||||
error = dup_sockaddr_copyin(&spec->lap, dp->ioc_local,
|
||||
dp->ioc_lolen);
|
||||
if (error) {
|
||||
smb_usr_vcspec_free(spec);
|
||||
return ENOMEM;
|
||||
}
|
||||
spec->lap = smb_memdupin(dp->ioc_local, dp->ioc_lolen);
|
||||
if (spec->lap == NULL) {
|
||||
smb_usr_vcspec_free(spec);
|
||||
return ENOMEM;
|
||||
return error;
|
||||
}
|
||||
}
|
||||
spec->srvname = dp->ioc_srvname;
|
||||
|
|
Loading…
Reference in New Issue