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:
parent
232803be5c
commit
a069944f46
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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 *,
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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 *,
|
||||
|
Loading…
x
Reference in New Issue
Block a user