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
This commit is contained in:
marcel 2000-07-23 16:54:18 +00:00
parent 232803be5c
commit a069944f46
6 changed files with 28 additions and 22 deletions

View File

@ -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;

View File

@ -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);
}

View File

@ -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 *,

View File

@ -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;

View File

@ -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);
}

View File

@ -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 *,