From a069944f46211cf481f1414ec35e8e264169f6f2 Mon Sep 17 00:00:00 2001 From: marcel Date: Sun, 23 Jul 2000 16:54:18 +0000 Subject: [PATCH] Add bounds checking to stackgap_alloc. Previously it was possible to construct a path that was long enough (ie longer than SPARE_USRSPACE bytes) and trash the stack. Note that SPARE_USRSPACE is much smaller than MAXPATHLEN so that the Linuxulator will now return ENAMETOOLONG even if the path is smaller than MAXPATHLEN. PR: 12749 --- sys/compat/linux/linux_misc.c | 2 ++ sys/compat/linux/linux_util.c | 5 ++++- sys/compat/linux/linux_util.h | 18 ++++++++---------- sys/i386/linux/linux_misc.c | 2 ++ sys/i386/linux/linux_util.c | 5 ++++- sys/i386/linux/linux_util.h | 18 ++++++++---------- 6 files changed, 28 insertions(+), 22 deletions(-) diff --git a/sys/compat/linux/linux_misc.c b/sys/compat/linux/linux_misc.c index 1adea544b05e..dcbff986303f 100644 --- a/sys/compat/linux/linux_misc.c +++ b/sys/compat/linux/linux_misc.c @@ -954,6 +954,8 @@ linux_utime(struct proc *p, struct linux_utime_args *args) tv[1].tv_usec = 0; /* so that utimes can copyin */ tvp = (struct timeval *)stackgap_alloc(&sg, sizeof(tv)); + if (tvp == NULL) + return (ENAMETOOLONG); if ((error = copyout(tv, tvp, sizeof(tv)))) return error; bsdutimes.tptr = tvp; diff --git a/sys/compat/linux/linux_util.c b/sys/compat/linux/linux_util.c index 8faf35e3d80e..e0ea0cb5fb07 100644 --- a/sys/compat/linux/linux_util.c +++ b/sys/compat/linux/linux_util.c @@ -162,7 +162,10 @@ linux_emul_find(p, sgp, prefix, path, pbuf, cflag) else { sz = &ptr[len] - buf; *pbuf = stackgap_alloc(sgp, sz + 1); - error = copyout(buf, *pbuf, sz); + if (*pbuf != NULL) + error = copyout(buf, *pbuf, sz); + else + error = ENAMETOOLONG; free(buf, M_TEMP); } diff --git a/sys/compat/linux/linux_util.h b/sys/compat/linux/linux_util.h index f8775fbf44c8..a54ddfd4a7a8 100644 --- a/sys/compat/linux/linux_util.h +++ b/sys/compat/linux/linux_util.h @@ -56,30 +56,28 @@ static __inline caddr_t stackgap_init(void); static __inline void *stackgap_alloc(caddr_t *, size_t); +#define szsigcode (*(curproc->p_sysent->sv_szsigcode)) + static __inline caddr_t stackgap_init() { -#define szsigcode (*(curproc->p_sysent->sv_szsigcode)) return (caddr_t)(PS_STRINGS - szsigcode - SPARE_USRSPACE); } - static __inline void * stackgap_alloc(sgp, sz) caddr_t *sgp; size_t sz; { - void *p = (void *) *sgp; - *sgp += ALIGN(sz); + void *p = (void *) *sgp; + + sz = ALIGN(sz); + if (*sgp + sz > (caddr_t)(PS_STRINGS - szsigcode)) + return NULL; + *sgp += sz; return p; } -#ifdef DEBUG_LINUX -#define DPRINTF(a) printf a; -#else -#define DPRINTF(a) -#endif - extern const char linux_emul_path[]; int linux_emul_find __P((struct proc *, caddr_t *, const char *, char *, diff --git a/sys/i386/linux/linux_misc.c b/sys/i386/linux/linux_misc.c index 1adea544b05e..dcbff986303f 100644 --- a/sys/i386/linux/linux_misc.c +++ b/sys/i386/linux/linux_misc.c @@ -954,6 +954,8 @@ linux_utime(struct proc *p, struct linux_utime_args *args) tv[1].tv_usec = 0; /* so that utimes can copyin */ tvp = (struct timeval *)stackgap_alloc(&sg, sizeof(tv)); + if (tvp == NULL) + return (ENAMETOOLONG); if ((error = copyout(tv, tvp, sizeof(tv)))) return error; bsdutimes.tptr = tvp; diff --git a/sys/i386/linux/linux_util.c b/sys/i386/linux/linux_util.c index 8faf35e3d80e..e0ea0cb5fb07 100644 --- a/sys/i386/linux/linux_util.c +++ b/sys/i386/linux/linux_util.c @@ -162,7 +162,10 @@ linux_emul_find(p, sgp, prefix, path, pbuf, cflag) else { sz = &ptr[len] - buf; *pbuf = stackgap_alloc(sgp, sz + 1); - error = copyout(buf, *pbuf, sz); + if (*pbuf != NULL) + error = copyout(buf, *pbuf, sz); + else + error = ENAMETOOLONG; free(buf, M_TEMP); } diff --git a/sys/i386/linux/linux_util.h b/sys/i386/linux/linux_util.h index f8775fbf44c8..a54ddfd4a7a8 100644 --- a/sys/i386/linux/linux_util.h +++ b/sys/i386/linux/linux_util.h @@ -56,30 +56,28 @@ static __inline caddr_t stackgap_init(void); static __inline void *stackgap_alloc(caddr_t *, size_t); +#define szsigcode (*(curproc->p_sysent->sv_szsigcode)) + static __inline caddr_t stackgap_init() { -#define szsigcode (*(curproc->p_sysent->sv_szsigcode)) return (caddr_t)(PS_STRINGS - szsigcode - SPARE_USRSPACE); } - static __inline void * stackgap_alloc(sgp, sz) caddr_t *sgp; size_t sz; { - void *p = (void *) *sgp; - *sgp += ALIGN(sz); + void *p = (void *) *sgp; + + sz = ALIGN(sz); + if (*sgp + sz > (caddr_t)(PS_STRINGS - szsigcode)) + return NULL; + *sgp += sz; return p; } -#ifdef DEBUG_LINUX -#define DPRINTF(a) printf a; -#else -#define DPRINTF(a) -#endif - extern const char linux_emul_path[]; int linux_emul_find __P((struct proc *, caddr_t *, const char *, char *,