freebsd32: fix getfsstat sign extension bugs
Add freebsd32 versions of getfsstat and freebsd11_getfsstat so that bufsize is properly sign-extended if a negative value is passed. Reject negative values before passing to kern_getfsstat as a size_t. Reviewed by: kevans
This commit is contained in:
parent
f19e3fd206
commit
2b9d052d3e
@ -292,6 +292,21 @@ copy_statfs(struct statfs *in, struct ostatfs32 *out)
|
||||
}
|
||||
#endif
|
||||
|
||||
int
|
||||
freebsd32_getfsstat(struct thread *td, struct freebsd32_getfsstat_args *uap)
|
||||
{
|
||||
size_t count;
|
||||
int error;
|
||||
|
||||
if (uap->bufsize < 0 || uap->bufsize > SIZE_MAX)
|
||||
return (EINVAL);
|
||||
error = kern_getfsstat(td, &uap->buf, uap->bufsize, &count,
|
||||
UIO_USERSPACE, uap->mode);
|
||||
if (error == 0)
|
||||
td->td_retval[0] = count;
|
||||
return (error);
|
||||
}
|
||||
|
||||
#ifdef COMPAT_FREEBSD4
|
||||
int
|
||||
freebsd4_freebsd32_getfsstat(struct thread *td,
|
||||
@ -323,6 +338,16 @@ freebsd4_freebsd32_getfsstat(struct thread *td,
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef COMPAT_FREEBSD11
|
||||
int
|
||||
freebsd11_freebsd32_getfsstat(struct thread *td,
|
||||
struct freebsd11_freebsd32_getfsstat_args *uap)
|
||||
{
|
||||
return(kern_freebsd11_getfsstat(td, uap->buf, uap->bufsize,
|
||||
uap->mode));
|
||||
}
|
||||
#endif
|
||||
|
||||
int
|
||||
freebsd32_sigaltstack(struct thread *td,
|
||||
struct freebsd32_sigaltstack_args *uap)
|
||||
|
@ -709,6 +709,11 @@ struct freebsd32_fhstat_args {
|
||||
char u_fhp_l_[PADL_(const struct fhandle *)]; const struct fhandle * u_fhp; char u_fhp_r_[PADR_(const struct fhandle *)];
|
||||
char sb_l_[PADL_(struct stat32 *)]; struct stat32 * sb; char sb_r_[PADR_(struct stat32 *)];
|
||||
};
|
||||
struct freebsd32_getfsstat_args {
|
||||
char buf_l_[PADL_(struct statfs *)]; struct statfs * buf; char buf_r_[PADR_(struct statfs *)];
|
||||
char bufsize_l_[PADL_(int32_t)]; int32_t bufsize; char bufsize_r_[PADR_(int32_t)];
|
||||
char mode_l_[PADL_(int)]; int mode; char mode_r_[PADR_(int)];
|
||||
};
|
||||
#ifdef PAD64_REQUIRED
|
||||
struct freebsd32_mknodat_args {
|
||||
char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)];
|
||||
@ -912,6 +917,7 @@ int freebsd32_utimensat(struct thread *, struct freebsd32_utimensat_args *);
|
||||
int freebsd32_fstat(struct thread *, struct freebsd32_fstat_args *);
|
||||
int freebsd32_fstatat(struct thread *, struct freebsd32_fstatat_args *);
|
||||
int freebsd32_fhstat(struct thread *, struct freebsd32_fhstat_args *);
|
||||
int freebsd32_getfsstat(struct thread *, struct freebsd32_getfsstat_args *);
|
||||
#ifdef PAD64_REQUIRED
|
||||
int freebsd32_mknodat(struct thread *, struct freebsd32_mknodat_args *);
|
||||
#else
|
||||
@ -1317,6 +1323,11 @@ struct freebsd11_freebsd32_kevent_args {
|
||||
char nevents_l_[PADL_(int)]; int nevents; char nevents_r_[PADR_(int)];
|
||||
char timeout_l_[PADL_(const struct timespec32 *)]; const struct timespec32 * timeout; char timeout_r_[PADR_(const struct timespec32 *)];
|
||||
};
|
||||
struct freebsd11_freebsd32_getfsstat_args {
|
||||
char buf_l_[PADL_(struct freebsd11_statfs *)]; struct freebsd11_statfs * buf; char buf_r_[PADR_(struct freebsd11_statfs *)];
|
||||
char bufsize_l_[PADL_(int32_t)]; int32_t bufsize; char bufsize_r_[PADR_(int32_t)];
|
||||
char mode_l_[PADL_(int)]; int mode; char mode_r_[PADR_(int)];
|
||||
};
|
||||
#ifdef PAD64_REQUIRED
|
||||
#else
|
||||
#endif
|
||||
@ -1344,6 +1355,7 @@ int freebsd11_freebsd32_lstat(struct thread *, struct freebsd11_freebsd32_lstat_
|
||||
int freebsd11_freebsd32_getdirentries(struct thread *, struct freebsd11_freebsd32_getdirentries_args *);
|
||||
int freebsd11_freebsd32_fhstat(struct thread *, struct freebsd11_freebsd32_fhstat_args *);
|
||||
int freebsd11_freebsd32_kevent(struct thread *, struct freebsd11_freebsd32_kevent_args *);
|
||||
int freebsd11_freebsd32_getfsstat(struct thread *, struct freebsd11_freebsd32_getfsstat_args *);
|
||||
int freebsd11_freebsd32_fstatat(struct thread *, struct freebsd11_freebsd32_fstatat_args *);
|
||||
|
||||
#endif /* COMPAT_FREEBSD11 */
|
||||
@ -1474,6 +1486,7 @@ int freebsd11_freebsd32_fstatat(struct thread *, struct freebsd11_freebsd32_fsta
|
||||
#define FREEBSD32_SYS_AUE_freebsd11_freebsd32_kevent AUE_KEVENT
|
||||
#define FREEBSD32_SYS_AUE_freebsd32_nmount AUE_NMOUNT
|
||||
#define FREEBSD32_SYS_AUE_freebsd32_sendfile AUE_SENDFILE
|
||||
#define FREEBSD32_SYS_AUE_freebsd11_freebsd32_getfsstat AUE_GETFSSTAT
|
||||
#define FREEBSD32_SYS_AUE_freebsd32_ksem_init AUE_SEMINIT
|
||||
#define FREEBSD32_SYS_AUE_freebsd32_ksem_open AUE_SEMOPEN
|
||||
#define FREEBSD32_SYS_AUE_freebsd32_sigaction AUE_SIGACTION
|
||||
@ -1538,6 +1551,7 @@ int freebsd11_freebsd32_fstatat(struct thread *, struct freebsd11_freebsd32_fsta
|
||||
#define FREEBSD32_SYS_AUE_freebsd32_fstat AUE_FSTAT
|
||||
#define FREEBSD32_SYS_AUE_freebsd32_fstatat AUE_FSTATAT
|
||||
#define FREEBSD32_SYS_AUE_freebsd32_fhstat AUE_FHSTAT
|
||||
#define FREEBSD32_SYS_AUE_freebsd32_getfsstat AUE_GETFSSTAT
|
||||
#define FREEBSD32_SYS_AUE_freebsd32_mknodat AUE_MKNODAT
|
||||
#define FREEBSD32_SYS_AUE_freebsd32_mknodat AUE_MKNODAT
|
||||
#define FREEBSD32_SYS_AUE_freebsd32_kevent AUE_KEVENT
|
||||
|
@ -329,7 +329,7 @@
|
||||
#define FREEBSD32_SYS_lchflags 391
|
||||
#define FREEBSD32_SYS_uuidgen 392
|
||||
#define FREEBSD32_SYS_freebsd32_sendfile 393
|
||||
#define FREEBSD32_SYS_freebsd11_getfsstat 395
|
||||
#define FREEBSD32_SYS_freebsd11_freebsd32_getfsstat 395
|
||||
#define FREEBSD32_SYS_freebsd11_statfs 396
|
||||
#define FREEBSD32_SYS_freebsd11_fstatfs 397
|
||||
#define FREEBSD32_SYS_freebsd11_fhstatfs 398
|
||||
@ -488,7 +488,7 @@
|
||||
#define FREEBSD32_SYS_getdirentries 554
|
||||
#define FREEBSD32_SYS_statfs 555
|
||||
#define FREEBSD32_SYS_fstatfs 556
|
||||
#define FREEBSD32_SYS_getfsstat 557
|
||||
#define FREEBSD32_SYS_freebsd32_getfsstat 557
|
||||
#define FREEBSD32_SYS_fhstatfs 558
|
||||
#define FREEBSD32_SYS_freebsd32_mknodat 559
|
||||
#define FREEBSD32_SYS_freebsd32_mknodat 559
|
||||
|
@ -409,7 +409,7 @@ const char *freebsd32_syscallnames[] = {
|
||||
"uuidgen", /* 392 = uuidgen */
|
||||
"freebsd32_sendfile", /* 393 = freebsd32_sendfile */
|
||||
"#394", /* 394 = mac_syscall */
|
||||
"compat11.getfsstat", /* 395 = freebsd11 getfsstat */
|
||||
"compat11.freebsd32_getfsstat", /* 395 = freebsd11 freebsd32_getfsstat */
|
||||
"compat11.statfs", /* 396 = freebsd11 statfs */
|
||||
"compat11.fstatfs", /* 397 = freebsd11 fstatfs */
|
||||
"compat11.fhstatfs", /* 398 = freebsd11 fhstatfs */
|
||||
@ -594,7 +594,7 @@ const char *freebsd32_syscallnames[] = {
|
||||
"getdirentries", /* 554 = getdirentries */
|
||||
"statfs", /* 555 = statfs */
|
||||
"fstatfs", /* 556 = fstatfs */
|
||||
"getfsstat", /* 557 = getfsstat */
|
||||
"freebsd32_getfsstat", /* 557 = freebsd32_getfsstat */
|
||||
"fhstatfs", /* 558 = fhstatfs */
|
||||
#ifdef PAD64_REQUIRED
|
||||
"freebsd32_mknodat", /* 559 = freebsd32_mknodat */
|
||||
|
@ -462,7 +462,7 @@ struct sysent freebsd32_sysent[] = {
|
||||
{ .sy_narg = AS(uuidgen_args), .sy_call = (sy_call_t *)sys_uuidgen, .sy_auevent = AUE_NULL, .sy_flags = SYF_CAPENABLED, .sy_thrcnt = SY_THR_STATIC }, /* 392 = uuidgen */
|
||||
{ .sy_narg = AS(freebsd32_sendfile_args), .sy_call = (sy_call_t *)freebsd32_sendfile, .sy_auevent = AUE_SENDFILE, .sy_flags = SYF_CAPENABLED, .sy_thrcnt = SY_THR_STATIC }, /* 393 = freebsd32_sendfile */
|
||||
{ .sy_narg = 0, .sy_call = (sy_call_t *)nosys, .sy_auevent = AUE_NULL, .sy_flags = 0, .sy_thrcnt = SY_THR_ABSENT }, /* 394 = mac_syscall */
|
||||
{ compat11(AS(freebsd11_getfsstat_args),getfsstat), .sy_auevent = AUE_GETFSSTAT, .sy_flags = 0, .sy_thrcnt = SY_THR_STATIC }, /* 395 = freebsd11 getfsstat */
|
||||
{ compat11(AS(freebsd11_freebsd32_getfsstat_args),freebsd32_getfsstat), .sy_auevent = AUE_GETFSSTAT, .sy_flags = 0, .sy_thrcnt = SY_THR_STATIC }, /* 395 = freebsd11 freebsd32_getfsstat */
|
||||
{ compat11(AS(freebsd11_statfs_args),statfs), .sy_auevent = AUE_STATFS, .sy_flags = 0, .sy_thrcnt = SY_THR_STATIC }, /* 396 = freebsd11 statfs */
|
||||
{ compat11(AS(freebsd11_fstatfs_args),fstatfs), .sy_auevent = AUE_FSTATFS, .sy_flags = SYF_CAPENABLED, .sy_thrcnt = SY_THR_STATIC }, /* 397 = freebsd11 fstatfs */
|
||||
{ compat11(AS(freebsd11_fhstatfs_args),fhstatfs), .sy_auevent = AUE_FHSTATFS, .sy_flags = 0, .sy_thrcnt = SY_THR_STATIC }, /* 398 = freebsd11 fhstatfs */
|
||||
@ -647,7 +647,7 @@ struct sysent freebsd32_sysent[] = {
|
||||
{ .sy_narg = AS(getdirentries_args), .sy_call = (sy_call_t *)sys_getdirentries, .sy_auevent = AUE_GETDIRENTRIES, .sy_flags = SYF_CAPENABLED, .sy_thrcnt = SY_THR_STATIC }, /* 554 = getdirentries */
|
||||
{ .sy_narg = AS(statfs_args), .sy_call = (sy_call_t *)sys_statfs, .sy_auevent = AUE_STATFS, .sy_flags = 0, .sy_thrcnt = SY_THR_STATIC }, /* 555 = statfs */
|
||||
{ .sy_narg = AS(fstatfs_args), .sy_call = (sy_call_t *)sys_fstatfs, .sy_auevent = AUE_FSTATFS, .sy_flags = SYF_CAPENABLED, .sy_thrcnt = SY_THR_STATIC }, /* 556 = fstatfs */
|
||||
{ .sy_narg = AS(getfsstat_args), .sy_call = (sy_call_t *)sys_getfsstat, .sy_auevent = AUE_GETFSSTAT, .sy_flags = 0, .sy_thrcnt = SY_THR_STATIC }, /* 557 = getfsstat */
|
||||
{ .sy_narg = AS(freebsd32_getfsstat_args), .sy_call = (sy_call_t *)freebsd32_getfsstat, .sy_auevent = AUE_GETFSSTAT, .sy_flags = 0, .sy_thrcnt = SY_THR_STATIC }, /* 557 = freebsd32_getfsstat */
|
||||
{ .sy_narg = AS(fhstatfs_args), .sy_call = (sy_call_t *)sys_fhstatfs, .sy_auevent = AUE_FHSTATFS, .sy_flags = 0, .sy_thrcnt = SY_THR_STATIC }, /* 558 = fhstatfs */
|
||||
#ifdef PAD64_REQUIRED
|
||||
{ .sy_narg = AS(freebsd32_mknodat_args), .sy_call = (sy_call_t *)freebsd32_mknodat, .sy_auevent = AUE_MKNODAT, .sy_flags = SYF_CAPENABLED, .sy_thrcnt = SY_THR_STATIC }, /* 559 = freebsd32_mknodat */
|
||||
|
@ -3207,9 +3207,9 @@ systrace_args(int sysnum, void *params, uint64_t *uarg, int *n_args)
|
||||
*n_args = 2;
|
||||
break;
|
||||
}
|
||||
/* getfsstat */
|
||||
/* freebsd32_getfsstat */
|
||||
case 557: {
|
||||
struct getfsstat_args *p = params;
|
||||
struct freebsd32_getfsstat_args *p = params;
|
||||
uarg[0] = (intptr_t)p->buf; /* struct statfs * */
|
||||
iarg[1] = p->bufsize; /* int32_t */
|
||||
iarg[2] = p->mode; /* int */
|
||||
@ -8858,7 +8858,7 @@ systrace_entry_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)
|
||||
break;
|
||||
};
|
||||
break;
|
||||
/* getfsstat */
|
||||
/* freebsd32_getfsstat */
|
||||
case 557:
|
||||
switch (ndx) {
|
||||
case 0:
|
||||
@ -11149,7 +11149,7 @@ systrace_return_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)
|
||||
if (ndx == 0 || ndx == 1)
|
||||
p = "int";
|
||||
break;
|
||||
/* getfsstat */
|
||||
/* freebsd32_getfsstat */
|
||||
case 557:
|
||||
if (ndx == 0 || ndx == 1)
|
||||
p = "int";
|
||||
|
@ -746,7 +746,7 @@
|
||||
size_t nbytes, struct sf_hdtr32 *hdtr, \
|
||||
off_t *sbytes, int flags); }
|
||||
394 AUE_NULL UNIMPL mac_syscall
|
||||
395 AUE_GETFSSTAT COMPAT11|NOPROTO { int getfsstat( \
|
||||
395 AUE_GETFSSTAT COMPAT11 { int freebsd32_getfsstat( \
|
||||
struct freebsd11_statfs *buf, \
|
||||
int32_t bufsize, int mode); }
|
||||
396 AUE_STATFS COMPAT11|NOPROTO { int statfs(const char *path, \
|
||||
@ -1140,7 +1140,7 @@
|
||||
555 AUE_STATFS NOPROTO { int statfs(const char *path, \
|
||||
struct statfs *buf); }
|
||||
556 AUE_FSTATFS NOPROTO { int fstatfs(int fd, struct statfs *buf); }
|
||||
557 AUE_GETFSSTAT NOPROTO { int getfsstat(struct statfs *buf, \
|
||||
557 AUE_GETFSSTAT STD { int freebsd32_getfsstat(struct statfs *buf, \
|
||||
int32_t bufsize, int mode); }
|
||||
558 AUE_FHSTATFS NOPROTO { int fhstatfs(const struct fhandle *u_fhp, \
|
||||
struct statfs *buf); }
|
||||
|
@ -789,25 +789,34 @@ freebsd11_fstatfs(struct thread *td, struct freebsd11_fstatfs_args *uap)
|
||||
*/
|
||||
int
|
||||
freebsd11_getfsstat(struct thread *td, struct freebsd11_getfsstat_args *uap)
|
||||
{
|
||||
return (kern_freebsd11_getfsstat(td, uap->buf, uap->bufsize, uap->mode));
|
||||
}
|
||||
|
||||
int
|
||||
kern_freebsd11_getfsstat(struct thread *td, struct freebsd11_statfs * ubuf,
|
||||
long bufsize, int mode)
|
||||
{
|
||||
struct freebsd11_statfs osb;
|
||||
struct statfs *buf, *sp;
|
||||
size_t count, size;
|
||||
int error;
|
||||
|
||||
count = uap->bufsize / sizeof(struct ostatfs);
|
||||
if (bufsize < 0)
|
||||
return (EINVAL);
|
||||
|
||||
count = bufsize / sizeof(struct ostatfs);
|
||||
size = count * sizeof(struct statfs);
|
||||
error = kern_getfsstat(td, &buf, size, &count, UIO_SYSSPACE,
|
||||
uap->mode);
|
||||
error = kern_getfsstat(td, &buf, size, &count, UIO_SYSSPACE, mode);
|
||||
if (error == 0)
|
||||
td->td_retval[0] = count;
|
||||
if (size > 0) {
|
||||
sp = buf;
|
||||
while (count > 0 && error == 0) {
|
||||
freebsd11_cvtstatfs(sp, &osb);
|
||||
error = copyout(&osb, uap->buf, sizeof(osb));
|
||||
error = copyout(&osb, ubuf, sizeof(osb));
|
||||
sp++;
|
||||
uap->buf++;
|
||||
ubuf++;
|
||||
count--;
|
||||
}
|
||||
free(buf, M_STATFS);
|
||||
|
@ -145,6 +145,8 @@ int kern_fhopen(struct thread *td, const struct fhandle *u_fhp, int flags);
|
||||
int kern_fhstat(struct thread *td, fhandle_t fh, struct stat *buf);
|
||||
int kern_fhstatfs(struct thread *td, fhandle_t fh, struct statfs *buf);
|
||||
int kern_fpathconf(struct thread *td, int fd, int name, long *valuep);
|
||||
int kern_freebsd11_getfsstat(struct thread *td,
|
||||
struct freebsd11_statfs *ubuf, long bufsize, int mode);
|
||||
int kern_fstat(struct thread *td, int fd, struct stat *sbp);
|
||||
int kern_fstatfs(struct thread *td, int fd, struct statfs *buf);
|
||||
int kern_fsync(struct thread *td, int fd, bool fullsync);
|
||||
|
Loading…
Reference in New Issue
Block a user