mirror of
https://github.com/opnsense/src.git
synced 2026-06-11 01:30:30 -04:00
Split the copyout of *base at the end of getdirentries() out leaving the
rest in kern_getdirentries(). Use kern_getdirentries() to implement freebsd32_getdirentries(). This fixes a bug where calls to getdirentries() in 32-bit binaries would trash the 4 bytes after the 'long base' in userland. Submitted by: ups MFC after: 1 week
This commit is contained in:
parent
e4bb8c6423
commit
63f8fe9e8b
4 changed files with 45 additions and 12 deletions
|
|
@ -1762,6 +1762,24 @@ freebsd32_ftruncate(struct thread *td, struct freebsd32_ftruncate_args *uap)
|
|||
return (ftruncate(td, &ap));
|
||||
}
|
||||
|
||||
int
|
||||
freebsd32_getdirentries(struct thread *td,
|
||||
struct freebsd32_getdirentries_args *uap)
|
||||
{
|
||||
long base;
|
||||
int32_t base32;
|
||||
int error;
|
||||
|
||||
error = kern_getdirentries(td, uap->fd, uap->buf, uap->count, &base);
|
||||
if (error)
|
||||
return (error);
|
||||
if (uap->basep != NULL) {
|
||||
base32 = base;
|
||||
error = copyout(&base32, uap->basep, sizeof(int32_t));
|
||||
}
|
||||
return (error);
|
||||
}
|
||||
|
||||
#ifdef COMPAT_FREEBSD6
|
||||
/* versions with the 'int pad' argument */
|
||||
int
|
||||
|
|
|
|||
|
|
@ -350,8 +350,8 @@
|
|||
195 AUE_SETRLIMIT NOPROTO { int setrlimit(u_int which, \
|
||||
struct rlimit *rlp); } setrlimit \
|
||||
__setrlimit_args int
|
||||
196 AUE_GETDIRENTRIES NOPROTO { int getdirentries(int fd, char *buf, \
|
||||
u_int count, long *basep); }
|
||||
196 AUE_GETDIRENTRIES STD { int freebsd32_getdirentries(int fd, \
|
||||
char *buf, u_int count, int32_t *basep); }
|
||||
197 AUE_MMAP COMPAT6 { caddr_t freebsd32_mmap(caddr_t addr, \
|
||||
size_t len, int prot, int flags, int fd, \
|
||||
int pad, u_int32_t poslo, \
|
||||
|
|
|
|||
|
|
@ -4015,6 +4015,21 @@ getdirentries(td, uap)
|
|||
u_int count;
|
||||
long *basep;
|
||||
} */ *uap;
|
||||
{
|
||||
long base;
|
||||
int error;
|
||||
|
||||
error = kern_getdirentries(td, uap->fd, uap->buf, uap->count, &base);
|
||||
if (error)
|
||||
return (error);
|
||||
if (uap->basep != NULL)
|
||||
error = copyout(&base, uap->basep, sizeof(long));
|
||||
return (error);
|
||||
}
|
||||
|
||||
int
|
||||
kern_getdirentries(struct thread *td, int fd, char *buf, u_int count,
|
||||
long *basep)
|
||||
{
|
||||
struct vnode *vp;
|
||||
struct file *fp;
|
||||
|
|
@ -4024,8 +4039,8 @@ getdirentries(td, uap)
|
|||
long loff;
|
||||
int error, eofflag;
|
||||
|
||||
AUDIT_ARG(fd, uap->fd);
|
||||
if ((error = getvnode(td->td_proc->p_fd, uap->fd, &fp)) != 0)
|
||||
AUDIT_ARG(fd, fd);
|
||||
if ((error = getvnode(td->td_proc->p_fd, fd, &fp)) != 0)
|
||||
return (error);
|
||||
if ((fp->f_flag & FREAD) == 0) {
|
||||
fdrop(fp, td);
|
||||
|
|
@ -4039,14 +4054,14 @@ unionread:
|
|||
error = EINVAL;
|
||||
goto fail;
|
||||
}
|
||||
aiov.iov_base = uap->buf;
|
||||
aiov.iov_len = uap->count;
|
||||
aiov.iov_base = buf;
|
||||
aiov.iov_len = count;
|
||||
auio.uio_iov = &aiov;
|
||||
auio.uio_iovcnt = 1;
|
||||
auio.uio_rw = UIO_READ;
|
||||
auio.uio_segflg = UIO_USERSPACE;
|
||||
auio.uio_td = td;
|
||||
auio.uio_resid = uap->count;
|
||||
auio.uio_resid = count;
|
||||
/* vn_lock(vp, LK_SHARED | LK_RETRY); */
|
||||
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
|
||||
AUDIT_ARG(vnode, vp, ARG_VNODE1);
|
||||
|
|
@ -4063,7 +4078,7 @@ unionread:
|
|||
VFS_UNLOCK_GIANT(vfslocked);
|
||||
goto fail;
|
||||
}
|
||||
if (uap->count == auio.uio_resid &&
|
||||
if (count == auio.uio_resid &&
|
||||
(vp->v_vflag & VV_ROOT) &&
|
||||
(vp->v_mount->mnt_flag & MNT_UNION)) {
|
||||
struct vnode *tvp = vp;
|
||||
|
|
@ -4078,10 +4093,8 @@ unionread:
|
|||
}
|
||||
VOP_UNLOCK(vp, 0);
|
||||
VFS_UNLOCK_GIANT(vfslocked);
|
||||
if (uap->basep != NULL) {
|
||||
error = copyout(&loff, uap->basep, sizeof(long));
|
||||
}
|
||||
td->td_retval[0] = uap->count - auio.uio_resid;
|
||||
*basep = loff;
|
||||
td->td_retval[0] = count - auio.uio_resid;
|
||||
fail:
|
||||
fdrop(fp, td);
|
||||
return (error);
|
||||
|
|
|
|||
|
|
@ -91,6 +91,8 @@ int kern_fstatfs(struct thread *td, int fd, struct statfs *buf);
|
|||
int kern_ftruncate(struct thread *td, int fd, off_t length);
|
||||
int kern_futimes(struct thread *td, int fd, struct timeval *tptr,
|
||||
enum uio_seg tptrseg);
|
||||
int kern_getdirentries(struct thread *td, int fd, char *buf, u_int count,
|
||||
long *basep);
|
||||
int kern_getfsstat(struct thread *td, struct statfs **buf, size_t bufsize,
|
||||
enum uio_seg bufseg, int flags);
|
||||
int kern_getgroups(struct thread *td, u_int *ngrp, gid_t *groups);
|
||||
|
|
|
|||
Loading…
Reference in a new issue