syscalls: improve nstat, nfstat, nlstat

Optionally return errors when truncating dev_t, ino_t, and nlink_t.
In the interest of code reuse, use freebsd11_cvtstat() to perform the
truncation and error handling and then convert the resulting struct
freebsd11_stat to struct nstat.

Add missing freebsd32 compat syscalls. These syscalls require
translation because struct nstat contains four instances of struct
timespec which in turn contains a time_t and a long.

Reviewed by:	kib
This commit is contained in:
Brooks Davis 2021-11-22 22:36:56 +00:00
parent 8460d3e9e6
commit 6eefabd4ca
6 changed files with 157 additions and 30 deletions

View File

@ -167,6 +167,31 @@ struct ostatfs32 {
int32_t f_spare[2];
};
struct nstat32 {
__uint32_t st_dev; /* inode's device */
__uint32_t st_ino; /* inode's number */
__uint32_t st_mode; /* inode protection mode */
__uint32_t st_nlink; /* number of hard links */
uid_t st_uid; /* user ID of the file's owner */
gid_t st_gid; /* group ID of the file's group */
__uint32_t st_rdev; /* device type */
struct timespec32 st_atim; /* time of last access */
struct timespec32 st_mtim; /* time of last data modification */
struct timespec32 st_ctim; /* time of last file status change */
off_t st_size; /* file size, in bytes */
blkcnt_t st_blocks; /* blocks allocated for file */
blksize_t st_blksize; /* optimal blocksize for I/O */
fflags_t st_flags; /* user defined flags for file */
__uint32_t st_gen; /* file generation number */
struct timespec32 st_birthtim; /* time of file creation */
/*
* See comment in the definition of struct freebsd11_stat
* in sys/stat.h about the following padding.
*/
unsigned int :(8 / 2) * (16 - (int)sizeof(struct timespec32));
unsigned int :(8 / 2) * (16 - (int)sizeof(struct timespec32));
};
struct iovec32 {
u_int32_t iov_base;
int iov_len;

View File

@ -2473,6 +2473,93 @@ freebsd11_freebsd32_fhstat(struct thread *td,
error = copyout(&sb32, uap->sb, sizeof (sb32));
return (error);
}
static int
freebsd11_cvtnstat32(struct stat *sb, struct nstat32 *nsb32)
{
struct nstat nsb;
int error;
error = freebsd11_cvtnstat(sb, &nsb);
if (error != 0)
return (error);
bzero(nsb32, sizeof(*nsb32));
CP(nsb, *nsb32, st_dev);
CP(nsb, *nsb32, st_ino);
CP(nsb, *nsb32, st_mode);
CP(nsb, *nsb32, st_nlink);
CP(nsb, *nsb32, st_uid);
CP(nsb, *nsb32, st_gid);
CP(nsb, *nsb32, st_rdev);
CP(nsb, *nsb32, st_atim.tv_sec);
CP(nsb, *nsb32, st_atim.tv_nsec);
CP(nsb, *nsb32, st_mtim.tv_sec);
CP(nsb, *nsb32, st_mtim.tv_nsec);
CP(nsb, *nsb32, st_ctim.tv_sec);
CP(nsb, *nsb32, st_ctim.tv_nsec);
CP(nsb, *nsb32, st_size);
CP(nsb, *nsb32, st_blocks);
CP(nsb, *nsb32, st_blksize);
CP(nsb, *nsb32, st_flags);
CP(nsb, *nsb32, st_gen);
CP(nsb, *nsb32, st_birthtim.tv_sec);
CP(nsb, *nsb32, st_birthtim.tv_nsec);
return (0);
}
int
freebsd11_freebsd32_nstat(struct thread *td,
struct freebsd11_freebsd32_nstat_args *uap)
{
struct stat sb;
struct nstat32 nsb;
int error;
error = kern_statat(td, 0, AT_FDCWD, uap->path, UIO_USERSPACE,
&sb, NULL);
if (error != 0)
return (error);
error = freebsd11_cvtnstat32(&sb, &nsb);
if (error != 0)
error = copyout(&nsb, uap->ub, sizeof (nsb));
return (error);
}
int
freebsd11_freebsd32_nlstat(struct thread *td,
struct freebsd11_freebsd32_nlstat_args *uap)
{
struct stat sb;
struct nstat32 nsb;
int error;
error = kern_statat(td, AT_SYMLINK_NOFOLLOW, AT_FDCWD, uap->path,
UIO_USERSPACE, &sb, NULL);
if (error != 0)
return (error);
error = freebsd11_cvtnstat32(&sb, &nsb);
if (error == 0)
error = copyout(&nsb, uap->ub, sizeof (nsb));
return (error);
}
int
freebsd11_freebsd32_nfstat(struct thread *td,
struct freebsd11_freebsd32_nfstat_args *uap)
{
struct nstat32 nub;
struct stat ub;
int error;
error = kern_fstat(td, uap->fd, &ub);
if (error != 0)
return (error);
error = freebsd11_cvtnstat32(&ub, &nub);
if (error == 0)
error = copyout(&nub, uap->sb, sizeof(nub));
return (error);
}
#endif
int

View File

@ -525,11 +525,11 @@
276 AUE_LUTIMES STD { int freebsd32_lutimes(const char *path, \
const struct timeval32 *tptr); }
277 AUE_NULL OBSOL netbsd_msync
278 AUE_STAT COMPAT11|NOPROTO { int nstat(const char *path, \
struct nstat *ub); }
279 AUE_FSTAT COMPAT11|NOPROTO { int nfstat(int fd, struct nstat *sb); }
280 AUE_LSTAT COMPAT11|NOPROTO { int nlstat(const char *path, \
struct nstat *ub); }
278 AUE_STAT COMPAT11 { int freebsd32_nstat(const char *path, \
struct nstat32 *ub); }
279 AUE_FSTAT COMPAT11 { int freebsd32_nfstat(int fd, struct nstat32 *sb); }
280 AUE_LSTAT COMPAT11 { int freebsd32_nlstat(const char *path, \
struct nstat32 *ub); }
281 AUE_NULL RESERVED
282 AUE_NULL RESERVED
283 AUE_NULL RESERVED

View File

@ -1561,10 +1561,11 @@ freebsd11_nfstat(struct thread *td, struct freebsd11_nfstat_args *uap)
int error;
error = kern_fstat(td, uap->fd, &ub);
if (error == 0) {
freebsd11_cvtnstat(&ub, &nub);
if (error != 0)
return (error);
error = freebsd11_cvtnstat(&ub, &nub);
if (error != 0)
error = copyout(&nub, uap->sb, sizeof(nub));
}
return (error);
}
#endif /* COMPAT_FREEBSD11 */

View File

@ -44,6 +44,9 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#ifdef COMPAT_FREEBSD11
#include <sys/abi_compat.h>
#endif
#include <sys/bio.h>
#include <sys/buf.h>
#include <sys/capsicum.h>
@ -2475,27 +2478,34 @@ kern_statat(struct thread *td, int flag, int fd, const char *path,
/*
* Implementation of the NetBSD [l]stat() functions.
*/
void
int
freebsd11_cvtnstat(struct stat *sb, struct nstat *nsb)
{
struct freebsd11_stat sb11;
int error;
error = freebsd11_cvtstat(sb, &sb11);
if (error != 0)
return (error);
bzero(nsb, sizeof(*nsb));
nsb->st_dev = sb->st_dev;
nsb->st_ino = sb->st_ino;
nsb->st_mode = sb->st_mode;
nsb->st_nlink = sb->st_nlink;
nsb->st_uid = sb->st_uid;
nsb->st_gid = sb->st_gid;
nsb->st_rdev = sb->st_rdev;
nsb->st_atim = sb->st_atim;
nsb->st_mtim = sb->st_mtim;
nsb->st_ctim = sb->st_ctim;
nsb->st_size = sb->st_size;
nsb->st_blocks = sb->st_blocks;
nsb->st_blksize = sb->st_blksize;
nsb->st_flags = sb->st_flags;
nsb->st_gen = sb->st_gen;
nsb->st_birthtim = sb->st_birthtim;
CP(sb11, *nsb, st_dev);
CP(sb11, *nsb, st_ino);
CP(sb11, *nsb, st_mode);
CP(sb11, *nsb, st_nlink);
CP(sb11, *nsb, st_uid);
CP(sb11, *nsb, st_gid);
CP(sb11, *nsb, st_rdev);
CP(sb11, *nsb, st_atim);
CP(sb11, *nsb, st_mtim);
CP(sb11, *nsb, st_ctim);
CP(sb11, *nsb, st_size);
CP(sb11, *nsb, st_blocks);
CP(sb11, *nsb, st_blksize);
CP(sb11, *nsb, st_flags);
CP(sb11, *nsb, st_gen);
CP(sb11, *nsb, st_birthtim);
return (0);
}
#ifndef _SYS_SYSPROTO_H_
@ -2515,8 +2525,10 @@ freebsd11_nstat(struct thread *td, struct freebsd11_nstat_args *uap)
&sb, NULL);
if (error != 0)
return (error);
freebsd11_cvtnstat(&sb, &nsb);
return (copyout(&nsb, uap->ub, sizeof (nsb)));
error = freebsd11_cvtnstat(&sb, &nsb);
if (error == 0)
error = copyout(&nsb, uap->ub, sizeof (nsb));
return (error);
}
/*
@ -2539,8 +2551,10 @@ freebsd11_nlstat(struct thread *td, struct freebsd11_nlstat_args *uap)
UIO_USERSPACE, &sb, NULL);
if (error != 0)
return (error);
freebsd11_cvtnstat(&sb, &nsb);
return (copyout(&nsb, uap->ub, sizeof (nsb)));
error = freebsd11_cvtnstat(&sb, &nsb);
if (error == 0)
error = copyout(&nsb, uap->ub, sizeof (nsb));
return (error);
}
#endif /* COMPAT_FREEBSD11 */

View File

@ -682,7 +682,7 @@ cache_validate(struct vnode *dvp, struct vnode *vp, struct componentname *cnp)
void cache_fast_lookup_enabled_recalc(void);
int change_dir(struct vnode *vp, struct thread *td);
void cvtstat(struct stat *st, struct ostat *ost);
void freebsd11_cvtnstat(struct stat *sb, struct nstat *nsb);
int freebsd11_cvtnstat(struct stat *sb, struct nstat *nsb);
int freebsd11_cvtstat(struct stat *st, struct freebsd11_stat *ost);
int getnewvnode(const char *tag, struct mount *mp, struct vop_vector *vops,
struct vnode **vpp);