From 86665509728b1cbdf5d0da8009d847020d7206c8 Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Wed, 30 Mar 2011 14:46:12 +0000 Subject: [PATCH] Provide compat32 shims for kldstat(2). Requested and tested by: jpaetzel MFC after: 1 week --- sys/compat/freebsd32/freebsd32.h | 19 ++++++++++ sys/compat/freebsd32/freebsd32_misc.c | 27 ++++++++++++++ sys/compat/freebsd32/syscalls.master | 4 +- sys/kern/kern_linker.c | 53 +++++++++++++++------------ sys/sys/syscallsubr.h | 2 + 5 files changed, 80 insertions(+), 25 deletions(-) diff --git a/sys/compat/freebsd32/freebsd32.h b/sys/compat/freebsd32/freebsd32.h index e04d202f2200..560db7214802 100644 --- a/sys/compat/freebsd32/freebsd32.h +++ b/sys/compat/freebsd32/freebsd32.h @@ -336,4 +336,23 @@ struct kinfo_proc32 { int ki_tdflags; }; +struct kld32_file_stat_1 { + int version; /* set to sizeof(struct kld_file_stat_1) */ + char name[MAXPATHLEN]; + int refs; + int id; + uint32_t address; /* load address */ + uint32_t size; /* size in bytes */ +}; + +struct kld32_file_stat { + int version; /* set to sizeof(struct kld_file_stat) */ + char name[MAXPATHLEN]; + int refs; + int id; + uint32_t address; /* load address */ + uint32_t size; /* size in bytes */ + char pathname[MAXPATHLEN]; +}; + #endif /* !_COMPAT_FREEBSD32_FREEBSD32_H_ */ diff --git a/sys/compat/freebsd32/freebsd32_misc.c b/sys/compat/freebsd32/freebsd32_misc.c index cf3af87aa979..e7511479bf7f 100644 --- a/sys/compat/freebsd32/freebsd32_misc.c +++ b/sys/compat/freebsd32/freebsd32_misc.c @@ -43,6 +43,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include /* Must come after sys/malloc.h */ @@ -2669,3 +2670,29 @@ freebsd32_copyout_strings(struct image_params *imgp) return ((register_t *)stack_base); } +int +freebsd32_kldstat(struct thread *td, struct freebsd32_kldstat_args *uap) +{ + struct kld_file_stat stat; + struct kld32_file_stat stat32; + int error, version; + + if ((error = copyin(&uap->stat->version, &version, sizeof(version))) + != 0) + return (error); + if (version != sizeof(struct kld32_file_stat_1) && + version != sizeof(struct kld32_file_stat)) + return (EINVAL); + + error = kern_kldstat(td, uap->fileid, &stat); + if (error != 0) + return (error); + + bcopy(&stat.name[0], &stat32.name[0], sizeof(stat.name)); + CP(stat, stat32, refs); + CP(stat, stat32, id); + PTROUT_CP(stat, stat32, address); + CP(stat, stat32, size); + bcopy(&stat.pathname[0], &stat32.pathname[0], sizeof(stat.pathname)); + return (copyout(&stat32, uap->stat, version)); +} diff --git a/sys/compat/freebsd32/syscalls.master b/sys/compat/freebsd32/syscalls.master index 26c0f6e55692..31a67b631905 100644 --- a/sys/compat/freebsd32/syscalls.master +++ b/sys/compat/freebsd32/syscalls.master @@ -533,8 +533,8 @@ 305 AUE_MODUNLOAD NOPROTO { int kldunload(int fileid); } 306 AUE_NULL NOPROTO { int kldfind(const char *file); } 307 AUE_NULL NOPROTO { int kldnext(int fileid); } -308 AUE_NULL NOPROTO { int kldstat(int fileid, \ - struct kld_file_stat* stat); } +308 AUE_NULL STD { int freebsd32_kldstat(int fileid, \ + struct kld32_file_stat* stat); } 309 AUE_NULL NOPROTO { int kldfirstmod(int fileid); } 310 AUE_GETSID NOPROTO { int getsid(pid_t pid); } 311 AUE_SETRESUID NOPROTO { int setresuid(uid_t ruid, uid_t euid, \ diff --git a/sys/kern/kern_linker.c b/sys/kern/kern_linker.c index e4837d1eb0ec..86a14ae4d612 100644 --- a/sys/kern/kern_linker.c +++ b/sys/kern/kern_linker.c @@ -1201,29 +1201,39 @@ int kldstat(struct thread *td, struct kldstat_args *uap) { struct kld_file_stat stat; - linker_file_t lf; - int error, namelen, version, version_num; + int error, version; /* * Check the version of the user's structure. */ - if ((error = copyin(&uap->stat->version, &version, sizeof(version))) != 0) + if ((error = copyin(&uap->stat->version, &version, sizeof(version))) + != 0) return (error); - if (version == sizeof(struct kld_file_stat_1)) - version_num = 1; - else if (version == sizeof(struct kld_file_stat)) - version_num = 2; - else + if (version != sizeof(struct kld_file_stat_1) && + version != sizeof(struct kld_file_stat)) return (EINVAL); + error = kern_kldstat(td, uap->fileid, &stat); + if (error != 0) + return (error); + return (copyout(&stat, uap->stat, version)); +} + +int +kern_kldstat(struct thread *td, int fileid, struct kld_file_stat *stat) +{ + linker_file_t lf; + int namelen; #ifdef MAC + int error; + error = mac_kld_check_stat(td->td_ucred); if (error) return (error); #endif KLD_LOCK(); - lf = linker_find_file_by_id(uap->fileid); + lf = linker_find_file_by_id(fileid); if (lf == NULL) { KLD_UNLOCK(); return (ENOENT); @@ -1233,23 +1243,20 @@ kldstat(struct thread *td, struct kldstat_args *uap) namelen = strlen(lf->filename) + 1; if (namelen > MAXPATHLEN) namelen = MAXPATHLEN; - bcopy(lf->filename, &stat.name[0], namelen); - stat.refs = lf->refs; - stat.id = lf->id; - stat.address = lf->address; - stat.size = lf->size; - if (version_num > 1) { - /* Version 2 fields: */ - namelen = strlen(lf->pathname) + 1; - if (namelen > MAXPATHLEN) - namelen = MAXPATHLEN; - bcopy(lf->pathname, &stat.pathname[0], namelen); - } + bcopy(lf->filename, &stat->name[0], namelen); + stat->refs = lf->refs; + stat->id = lf->id; + stat->address = lf->address; + stat->size = lf->size; + /* Version 2 fields: */ + namelen = strlen(lf->pathname) + 1; + if (namelen > MAXPATHLEN) + namelen = MAXPATHLEN; + bcopy(lf->pathname, &stat->pathname[0], namelen); KLD_UNLOCK(); td->td_retval[0] = 0; - - return (copyout(&stat, uap->stat, version)); + return (0); } int diff --git a/sys/sys/syscallsubr.h b/sys/sys/syscallsubr.h index 7524cf52d83c..d4006331fd09 100644 --- a/sys/sys/syscallsubr.h +++ b/sys/sys/syscallsubr.h @@ -48,6 +48,7 @@ struct sockaddr; struct stat; struct kevent; struct kevent_copyops; +struct kld_file_stat; struct ksiginfo; struct sendfile_args; struct thr_param; @@ -113,6 +114,7 @@ int kern_jail_set(struct thread *td, struct uio *options, int flags); int kern_kevent(struct thread *td, int fd, int nchanges, int nevents, struct kevent_copyops *k_ops, const struct timespec *timeout); int kern_kldload(struct thread *td, const char *file, int *fileid); +int kern_kldstat(struct thread *td, int fileid, struct kld_file_stat *stat); int kern_kldunload(struct thread *td, int fileid, int flags); int kern_lchown(struct thread *td, char *path, enum uio_seg pathseg, int uid, int gid);