2002-07-20 02:56:12 +00:00
|
|
|
/*-
|
|
|
|
* Copyright (c) 2002 Doug Rabson
|
|
|
|
* All rights reserved.
|
|
|
|
*
|
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
* modification, are permitted provided that the following conditions
|
|
|
|
* are met:
|
|
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer.
|
|
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
|
|
* documentation and/or other materials provided with the distribution.
|
|
|
|
*
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
|
|
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
|
|
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
|
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
|
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
|
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
|
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
|
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
|
|
* SUCH DAMAGE.
|
|
|
|
*/
|
|
|
|
|
2003-07-25 21:19:19 +00:00
|
|
|
#include <sys/cdefs.h>
|
|
|
|
__FBSDID("$FreeBSD$");
|
|
|
|
|
2002-10-09 22:27:24 +00:00
|
|
|
#include "opt_compat.h"
|
2009-04-29 21:14:15 +00:00
|
|
|
#include "opt_inet.h"
|
|
|
|
#include "opt_inet6.h"
|
2002-10-09 22:27:24 +00:00
|
|
|
|
2010-03-11 14:49:06 +00:00
|
|
|
#define __ELF_WORD_SIZE 32
|
|
|
|
|
2002-07-20 02:56:12 +00:00
|
|
|
#include <sys/param.h>
|
|
|
|
#include <sys/bus.h>
|
2006-10-02 12:59:59 +00:00
|
|
|
#include <sys/clock.h>
|
2002-07-20 02:56:12 +00:00
|
|
|
#include <sys/exec.h>
|
|
|
|
#include <sys/fcntl.h>
|
|
|
|
#include <sys/filedesc.h>
|
|
|
|
#include <sys/imgact.h>
|
MFp4:
Bring in updated jail support from bz_jail branch.
This enhances the current jail implementation to permit multiple
addresses per jail. In addtion to IPv4, IPv6 is supported as well.
Due to updated checks it is even possible to have jails without
an IP address at all, which basically gives one a chroot with
restricted process view, no networking,..
SCTP support was updated and supports IPv6 in jails as well.
Cpuset support permits jails to be bound to specific processor
sets after creation.
Jails can have an unrestricted (no duplicate protection, etc.) name
in addition to the hostname. The jail name cannot be changed from
within a jail and is considered to be used for management purposes
or as audit-token in the future.
DDB 'show jails' command was added to aid debugging.
Proper compat support permits 32bit jail binaries to be used on 64bit
systems to manage jails. Also backward compatibility was preserved where
possible: for jail v1 syscalls, as well as with user space management
utilities.
Both jail as well as prison version were updated for the new features.
A gap was intentionally left as the intermediate versions had been
used by various patches floating around the last years.
Bump __FreeBSD_version for the afore mentioned and in kernel changes.
Special thanks to:
- Pawel Jakub Dawidek (pjd) for his multi-IPv4 patches
and Olivier Houchard (cognet) for initial single-IPv6 patches.
- Jeff Roberson (jeff) and Randall Stewart (rrs) for their
help, ideas and review on cpuset and SCTP support.
- Robert Watson (rwatson) for lots and lots of help, discussions,
suggestions and review of most of the patch at various stages.
- John Baldwin (jhb) for his help.
- Simon L. Nielsen (simon) as early adopter testing changes
on cluster machines as well as all the testers and people
who provided feedback the last months on freebsd-jail and
other channels.
- My employer, CK Software GmbH, for the support so I could work on this.
Reviewed by: (see above)
MFC after: 3 months (this is just so that I get the mail)
X-MFC Before: 7.2-RELEASE if possible
2008-11-29 14:32:14 +00:00
|
|
|
#include <sys/jail.h>
|
2002-07-20 02:56:12 +00:00
|
|
|
#include <sys/kernel.h>
|
2006-08-16 00:02:36 +00:00
|
|
|
#include <sys/limits.h>
|
2011-03-30 14:46:12 +00:00
|
|
|
#include <sys/linker.h>
|
2002-07-20 02:56:12 +00:00
|
|
|
#include <sys/lock.h>
|
|
|
|
#include <sys/malloc.h>
|
|
|
|
#include <sys/file.h> /* Must come after sys/malloc.h */
|
2010-03-11 14:49:06 +00:00
|
|
|
#include <sys/imgact.h>
|
2005-10-31 21:09:56 +00:00
|
|
|
#include <sys/mbuf.h>
|
2002-07-20 02:56:12 +00:00
|
|
|
#include <sys/mman.h>
|
|
|
|
#include <sys/module.h>
|
|
|
|
#include <sys/mount.h>
|
|
|
|
#include <sys/mutex.h>
|
2008-09-15 17:39:40 +00:00
|
|
|
#include <sys/namei.h>
|
2002-07-20 02:56:12 +00:00
|
|
|
#include <sys/proc.h>
|
|
|
|
#include <sys/reboot.h>
|
|
|
|
#include <sys/resource.h>
|
|
|
|
#include <sys/resourcevar.h>
|
|
|
|
#include <sys/selinfo.h>
|
2005-06-03 23:15:01 +00:00
|
|
|
#include <sys/eventvar.h> /* Must come after sys/selinfo.h */
|
2002-07-20 02:56:12 +00:00
|
|
|
#include <sys/pipe.h> /* Must come after sys/selinfo.h */
|
|
|
|
#include <sys/signal.h>
|
|
|
|
#include <sys/signalvar.h>
|
|
|
|
#include <sys/socket.h>
|
|
|
|
#include <sys/socketvar.h>
|
|
|
|
#include <sys/stat.h>
|
2005-10-03 18:34:17 +00:00
|
|
|
#include <sys/syscall.h>
|
2003-04-22 18:23:49 +00:00
|
|
|
#include <sys/syscallsubr.h>
|
2002-07-20 02:56:12 +00:00
|
|
|
#include <sys/sysctl.h>
|
|
|
|
#include <sys/sysent.h>
|
|
|
|
#include <sys/sysproto.h>
|
2008-09-15 17:39:40 +00:00
|
|
|
#include <sys/systm.h>
|
2006-09-22 15:04:28 +00:00
|
|
|
#include <sys/thr.h>
|
2002-07-20 02:56:12 +00:00
|
|
|
#include <sys/unistd.h>
|
2006-09-22 15:04:28 +00:00
|
|
|
#include <sys/ucontext.h>
|
2002-07-20 02:56:12 +00:00
|
|
|
#include <sys/vnode.h>
|
2004-03-17 20:00:00 +00:00
|
|
|
#include <sys/wait.h>
|
2006-03-30 07:42:32 +00:00
|
|
|
#include <sys/ipc.h>
|
2007-12-06 23:35:29 +00:00
|
|
|
#include <sys/msg.h>
|
|
|
|
#include <sys/sem.h>
|
2006-03-30 07:42:32 +00:00
|
|
|
#include <sys/shm.h>
|
2002-07-20 02:56:12 +00:00
|
|
|
|
2009-04-29 21:14:15 +00:00
|
|
|
#ifdef INET
|
|
|
|
#include <netinet/in.h>
|
|
|
|
#endif
|
|
|
|
|
2002-07-20 02:56:12 +00:00
|
|
|
#include <vm/vm.h>
|
|
|
|
#include <vm/vm_param.h>
|
|
|
|
#include <vm/pmap.h>
|
|
|
|
#include <vm/vm_map.h>
|
|
|
|
#include <vm/vm_object.h>
|
|
|
|
#include <vm/vm_extern.h>
|
|
|
|
|
2005-10-23 10:43:14 +00:00
|
|
|
#include <machine/cpu.h>
|
2010-03-11 14:49:06 +00:00
|
|
|
#include <machine/elf.h>
|
2005-10-23 10:43:14 +00:00
|
|
|
|
2008-09-19 15:17:32 +00:00
|
|
|
#include <security/audit/audit.h>
|
|
|
|
|
2003-08-22 23:07:28 +00:00
|
|
|
#include <compat/freebsd32/freebsd32_util.h>
|
|
|
|
#include <compat/freebsd32/freebsd32.h>
|
2007-12-06 23:23:16 +00:00
|
|
|
#include <compat/freebsd32/freebsd32_ipc.h>
|
2006-10-05 01:56:11 +00:00
|
|
|
#include <compat/freebsd32/freebsd32_signal.h>
|
2003-08-22 23:07:28 +00:00
|
|
|
#include <compat/freebsd32/freebsd32_proto.h>
|
|
|
|
|
2013-05-31 21:43:17 +00:00
|
|
|
FEATURE(compat_freebsd_32bit, "Compatible with 32-bit FreeBSD");
|
|
|
|
|
2012-03-03 08:19:18 +00:00
|
|
|
#ifndef __mips__
|
2003-10-30 02:40:30 +00:00
|
|
|
CTASSERT(sizeof(struct timeval32) == 8);
|
|
|
|
CTASSERT(sizeof(struct timespec32) == 8);
|
2007-12-06 23:11:27 +00:00
|
|
|
CTASSERT(sizeof(struct itimerval32) == 16);
|
2012-03-03 08:19:18 +00:00
|
|
|
#endif
|
2003-10-30 02:40:30 +00:00
|
|
|
CTASSERT(sizeof(struct statfs32) == 256);
|
2012-03-03 08:19:18 +00:00
|
|
|
#ifndef __mips__
|
2003-10-30 02:40:30 +00:00
|
|
|
CTASSERT(sizeof(struct rusage32) == 72);
|
2012-03-03 08:19:18 +00:00
|
|
|
#endif
|
2007-12-06 23:11:27 +00:00
|
|
|
CTASSERT(sizeof(struct sigaltstack32) == 12);
|
|
|
|
CTASSERT(sizeof(struct kevent32) == 20);
|
|
|
|
CTASSERT(sizeof(struct iovec32) == 8);
|
|
|
|
CTASSERT(sizeof(struct msghdr32) == 28);
|
2012-03-03 08:19:18 +00:00
|
|
|
#ifndef __mips__
|
2007-12-06 23:11:27 +00:00
|
|
|
CTASSERT(sizeof(struct stat32) == 96);
|
2012-03-03 08:19:18 +00:00
|
|
|
#endif
|
2007-12-06 23:11:27 +00:00
|
|
|
CTASSERT(sizeof(struct sigaction32) == 24);
|
|
|
|
|
|
|
|
static int freebsd32_kevent_copyout(void *arg, struct kevent *kevp, int count);
|
|
|
|
static int freebsd32_kevent_copyin(void *arg, struct kevent *kevp, int count);
|
2003-10-30 02:40:30 +00:00
|
|
|
|
2010-03-11 14:49:06 +00:00
|
|
|
#if BYTE_ORDER == BIG_ENDIAN
|
|
|
|
#define PAIR32TO64(type, name) ((name ## 2) | ((type)(name ## 1) << 32))
|
|
|
|
#define RETVAL_HI 0
|
|
|
|
#define RETVAL_LO 1
|
|
|
|
#else
|
|
|
|
#define PAIR32TO64(type, name) ((name ## 1) | ((type)(name ## 2) << 32))
|
|
|
|
#define RETVAL_HI 1
|
|
|
|
#define RETVAL_LO 0
|
|
|
|
#endif
|
|
|
|
|
2010-04-21 19:28:01 +00:00
|
|
|
void
|
|
|
|
freebsd32_rusage_out(const struct rusage *s, struct rusage32 *s32)
|
|
|
|
{
|
|
|
|
|
|
|
|
TV_CP(*s, *s32, ru_utime);
|
|
|
|
TV_CP(*s, *s32, ru_stime);
|
|
|
|
CP(*s, *s32, ru_maxrss);
|
|
|
|
CP(*s, *s32, ru_ixrss);
|
|
|
|
CP(*s, *s32, ru_idrss);
|
|
|
|
CP(*s, *s32, ru_isrss);
|
|
|
|
CP(*s, *s32, ru_minflt);
|
|
|
|
CP(*s, *s32, ru_majflt);
|
|
|
|
CP(*s, *s32, ru_nswap);
|
|
|
|
CP(*s, *s32, ru_inblock);
|
|
|
|
CP(*s, *s32, ru_oublock);
|
|
|
|
CP(*s, *s32, ru_msgsnd);
|
|
|
|
CP(*s, *s32, ru_msgrcv);
|
|
|
|
CP(*s, *s32, ru_nsignals);
|
|
|
|
CP(*s, *s32, ru_nvcsw);
|
|
|
|
CP(*s, *s32, ru_nivcsw);
|
|
|
|
}
|
|
|
|
|
2002-07-20 02:56:12 +00:00
|
|
|
int
|
2003-08-22 23:07:28 +00:00
|
|
|
freebsd32_wait4(struct thread *td, struct freebsd32_wait4_args *uap)
|
2002-07-20 02:56:12 +00:00
|
|
|
{
|
2004-03-17 20:00:00 +00:00
|
|
|
int error, status;
|
|
|
|
struct rusage32 ru32;
|
2004-10-05 18:51:11 +00:00
|
|
|
struct rusage ru, *rup;
|
2002-07-20 02:56:12 +00:00
|
|
|
|
2004-10-05 18:51:11 +00:00
|
|
|
if (uap->rusage != NULL)
|
|
|
|
rup = &ru;
|
|
|
|
else
|
|
|
|
rup = NULL;
|
|
|
|
error = kern_wait(td, uap->pid, &status, uap->options, rup);
|
2002-07-20 02:56:12 +00:00
|
|
|
if (error)
|
|
|
|
return (error);
|
2004-03-17 20:00:00 +00:00
|
|
|
if (uap->status != NULL)
|
|
|
|
error = copyout(&status, uap->status, sizeof(status));
|
|
|
|
if (uap->rusage != NULL && error == 0) {
|
2010-04-21 19:28:01 +00:00
|
|
|
freebsd32_rusage_out(&ru, &ru32);
|
2004-03-17 20:00:00 +00:00
|
|
|
error = copyout(&ru32, uap->rusage, sizeof(ru32));
|
2002-07-20 02:56:12 +00:00
|
|
|
}
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
2012-11-13 12:52:31 +00:00
|
|
|
int
|
|
|
|
freebsd32_wait6(struct thread *td, struct freebsd32_wait6_args *uap)
|
|
|
|
{
|
|
|
|
struct wrusage32 wru32;
|
|
|
|
struct __wrusage wru, *wrup;
|
|
|
|
struct siginfo32 si32;
|
|
|
|
struct __siginfo si, *sip;
|
|
|
|
int error, status;
|
|
|
|
|
|
|
|
if (uap->wrusage != NULL)
|
|
|
|
wrup = &wru;
|
|
|
|
else
|
|
|
|
wrup = NULL;
|
|
|
|
if (uap->info != NULL) {
|
|
|
|
sip = &si;
|
|
|
|
bzero(sip, sizeof(*sip));
|
|
|
|
} else
|
|
|
|
sip = NULL;
|
2013-05-21 11:40:16 +00:00
|
|
|
error = kern_wait6(td, uap->idtype, PAIR32TO64(id_t, uap->id),
|
|
|
|
&status, uap->options, wrup, sip);
|
2012-11-13 12:52:31 +00:00
|
|
|
if (error != 0)
|
|
|
|
return (error);
|
|
|
|
if (uap->status != NULL)
|
|
|
|
error = copyout(&status, uap->status, sizeof(status));
|
|
|
|
if (uap->wrusage != NULL && error == 0) {
|
|
|
|
freebsd32_rusage_out(&wru.wru_self, &wru32.wru_self);
|
|
|
|
freebsd32_rusage_out(&wru.wru_children, &wru32.wru_children);
|
|
|
|
error = copyout(&wru32, uap->wrusage, sizeof(wru32));
|
|
|
|
}
|
|
|
|
if (uap->info != NULL && error == 0) {
|
|
|
|
siginfo_to_siginfo32 (&si, &si32);
|
|
|
|
error = copyout(&si32, uap->info, sizeof(si32));
|
|
|
|
}
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
2004-04-24 04:31:59 +00:00
|
|
|
#ifdef COMPAT_FREEBSD4
|
2007-12-10 19:42:23 +00:00
|
|
|
static void
|
2002-07-20 02:56:12 +00:00
|
|
|
copy_statfs(struct statfs *in, struct statfs32 *out)
|
|
|
|
{
|
2007-08-28 20:28:12 +00:00
|
|
|
|
2007-12-07 22:32:09 +00:00
|
|
|
statfs_scale_blocks(in, INT32_MAX);
|
2006-03-04 00:09:09 +00:00
|
|
|
bzero(out, sizeof(*out));
|
2002-07-20 02:56:12 +00:00
|
|
|
CP(*in, *out, f_bsize);
|
2007-08-28 20:28:12 +00:00
|
|
|
out->f_iosize = MIN(in->f_iosize, INT32_MAX);
|
2002-07-20 02:56:12 +00:00
|
|
|
CP(*in, *out, f_blocks);
|
|
|
|
CP(*in, *out, f_bfree);
|
|
|
|
CP(*in, *out, f_bavail);
|
2007-08-28 20:28:12 +00:00
|
|
|
out->f_files = MIN(in->f_files, INT32_MAX);
|
2007-12-10 19:42:23 +00:00
|
|
|
out->f_ffree = MIN(in->f_ffree, INT32_MAX);
|
2002-07-20 02:56:12 +00:00
|
|
|
CP(*in, *out, f_fsid);
|
|
|
|
CP(*in, *out, f_owner);
|
|
|
|
CP(*in, *out, f_type);
|
|
|
|
CP(*in, *out, f_flags);
|
2007-12-10 19:42:23 +00:00
|
|
|
out->f_syncwrites = MIN(in->f_syncwrites, INT32_MAX);
|
|
|
|
out->f_asyncwrites = MIN(in->f_asyncwrites, INT32_MAX);
|
2006-03-04 00:09:09 +00:00
|
|
|
strlcpy(out->f_fstypename,
|
|
|
|
in->f_fstypename, MFSNAMELEN);
|
|
|
|
strlcpy(out->f_mntonname,
|
|
|
|
in->f_mntonname, min(MNAMELEN, FREEBSD4_MNAMELEN));
|
2007-12-10 19:42:23 +00:00
|
|
|
out->f_syncreads = MIN(in->f_syncreads, INT32_MAX);
|
|
|
|
out->f_asyncreads = MIN(in->f_asyncreads, INT32_MAX);
|
2006-03-04 00:09:09 +00:00
|
|
|
strlcpy(out->f_mntfromname,
|
|
|
|
in->f_mntfromname, min(MNAMELEN, FREEBSD4_MNAMELEN));
|
2002-07-20 02:56:12 +00:00
|
|
|
}
|
2004-04-24 04:31:59 +00:00
|
|
|
#endif
|
2002-07-20 02:56:12 +00:00
|
|
|
|
2004-04-24 04:31:59 +00:00
|
|
|
#ifdef COMPAT_FREEBSD4
|
2002-07-20 02:56:12 +00:00
|
|
|
int
|
2004-04-14 23:17:37 +00:00
|
|
|
freebsd4_freebsd32_getfsstat(struct thread *td, struct freebsd4_freebsd32_getfsstat_args *uap)
|
2002-07-20 02:56:12 +00:00
|
|
|
{
|
2005-06-09 17:44:46 +00:00
|
|
|
struct statfs *buf, *sp;
|
|
|
|
struct statfs32 stat32;
|
|
|
|
size_t count, size;
|
2002-07-20 02:56:12 +00:00
|
|
|
int error;
|
|
|
|
|
2005-06-09 17:44:46 +00:00
|
|
|
count = uap->bufsize / sizeof(struct statfs32);
|
|
|
|
size = count * sizeof(struct statfs);
|
2005-06-11 14:58:20 +00:00
|
|
|
error = kern_getfsstat(td, &buf, size, UIO_SYSSPACE, uap->flags);
|
|
|
|
if (size > 0) {
|
2002-07-20 02:56:12 +00:00
|
|
|
count = td->td_retval[0];
|
2005-06-09 17:44:46 +00:00
|
|
|
sp = buf;
|
|
|
|
while (count > 0 && error == 0) {
|
2007-12-10 19:42:23 +00:00
|
|
|
copy_statfs(sp, &stat32);
|
2005-06-09 17:44:46 +00:00
|
|
|
error = copyout(&stat32, uap->buf, sizeof(stat32));
|
|
|
|
sp++;
|
|
|
|
uap->buf++;
|
|
|
|
count--;
|
2002-07-20 02:56:12 +00:00
|
|
|
}
|
2005-06-09 17:44:46 +00:00
|
|
|
free(buf, M_TEMP);
|
2002-07-20 02:56:12 +00:00
|
|
|
}
|
|
|
|
return (error);
|
|
|
|
}
|
2004-04-24 04:31:59 +00:00
|
|
|
#endif
|
2002-07-20 02:56:12 +00:00
|
|
|
|
|
|
|
int
|
2003-08-22 23:07:28 +00:00
|
|
|
freebsd32_sigaltstack(struct thread *td,
|
|
|
|
struct freebsd32_sigaltstack_args *uap)
|
2002-07-20 02:56:12 +00:00
|
|
|
{
|
2003-04-22 18:23:49 +00:00
|
|
|
struct sigaltstack32 s32;
|
|
|
|
struct sigaltstack ss, oss, *ssp;
|
2002-07-20 02:56:12 +00:00
|
|
|
int error;
|
|
|
|
|
2003-04-22 18:23:49 +00:00
|
|
|
if (uap->ss != NULL) {
|
|
|
|
error = copyin(uap->ss, &s32, sizeof(s32));
|
2002-07-20 02:56:12 +00:00
|
|
|
if (error)
|
|
|
|
return (error);
|
2003-04-22 18:23:49 +00:00
|
|
|
PTRIN_CP(s32, ss, ss_sp);
|
|
|
|
CP(s32, ss, ss_size);
|
|
|
|
CP(s32, ss, ss_flags);
|
|
|
|
ssp = &ss;
|
|
|
|
} else
|
|
|
|
ssp = NULL;
|
|
|
|
error = kern_sigaltstack(td, ssp, &oss);
|
|
|
|
if (error == 0 && uap->oss != NULL) {
|
|
|
|
PTROUT_CP(oss, s32, ss_sp);
|
|
|
|
CP(oss, s32, ss_size);
|
|
|
|
CP(oss, s32, ss_flags);
|
|
|
|
error = copyout(&s32, uap->oss, sizeof(s32));
|
2002-07-20 02:56:12 +00:00
|
|
|
}
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
- Add a custom version of exec_copyin_args() to deal with the 32-bit
pointers in argv and envv in userland and use that together with
kern_execve() and exec_free_args() to implement freebsd32_execve()
without using the stackgap.
- Fix freebsd32_adjtime() to call adjtime() rather than utimes(). Still
uses stackgap for now.
- Use kern_setitimer(), kern_getitimer(), kern_select(), kern_utimes(),
kern_statfs(), kern_fstatfs(), kern_fhstatfs(), kern_stat(),
kern_fstat(), and kern_lstat().
Tested by: cokane (amd64)
Silence on: amd64, ia64
2005-02-18 18:56:04 +00:00
|
|
|
/*
|
|
|
|
* Custom version of exec_copyin_args() so that we can translate
|
|
|
|
* the pointers.
|
|
|
|
*/
|
2010-07-23 21:30:33 +00:00
|
|
|
int
|
- Add a custom version of exec_copyin_args() to deal with the 32-bit
pointers in argv and envv in userland and use that together with
kern_execve() and exec_free_args() to implement freebsd32_execve()
without using the stackgap.
- Fix freebsd32_adjtime() to call adjtime() rather than utimes(). Still
uses stackgap for now.
- Use kern_setitimer(), kern_getitimer(), kern_select(), kern_utimes(),
kern_statfs(), kern_fstatfs(), kern_fhstatfs(), kern_stat(),
kern_fstat(), and kern_lstat().
Tested by: cokane (amd64)
Silence on: amd64, ia64
2005-02-18 18:56:04 +00:00
|
|
|
freebsd32_exec_copyin_args(struct image_args *args, char *fname,
|
|
|
|
enum uio_seg segflg, u_int32_t *argv, u_int32_t *envv)
|
2002-07-20 02:56:12 +00:00
|
|
|
{
|
- Add a custom version of exec_copyin_args() to deal with the 32-bit
pointers in argv and envv in userland and use that together with
kern_execve() and exec_free_args() to implement freebsd32_execve()
without using the stackgap.
- Fix freebsd32_adjtime() to call adjtime() rather than utimes(). Still
uses stackgap for now.
- Use kern_setitimer(), kern_getitimer(), kern_select(), kern_utimes(),
kern_statfs(), kern_fstatfs(), kern_fhstatfs(), kern_stat(),
kern_fstat(), and kern_lstat().
Tested by: cokane (amd64)
Silence on: amd64, ia64
2005-02-18 18:56:04 +00:00
|
|
|
char *argp, *envp;
|
2002-07-20 02:56:12 +00:00
|
|
|
u_int32_t *p32, arg;
|
- Add a custom version of exec_copyin_args() to deal with the 32-bit
pointers in argv and envv in userland and use that together with
kern_execve() and exec_free_args() to implement freebsd32_execve()
without using the stackgap.
- Fix freebsd32_adjtime() to call adjtime() rather than utimes(). Still
uses stackgap for now.
- Use kern_setitimer(), kern_getitimer(), kern_select(), kern_utimes(),
kern_statfs(), kern_fstatfs(), kern_fhstatfs(), kern_stat(),
kern_fstat(), and kern_lstat().
Tested by: cokane (amd64)
Silence on: amd64, ia64
2005-02-18 18:56:04 +00:00
|
|
|
size_t length;
|
|
|
|
int error;
|
2002-07-20 02:56:12 +00:00
|
|
|
|
- Add a custom version of exec_copyin_args() to deal with the 32-bit
pointers in argv and envv in userland and use that together with
kern_execve() and exec_free_args() to implement freebsd32_execve()
without using the stackgap.
- Fix freebsd32_adjtime() to call adjtime() rather than utimes(). Still
uses stackgap for now.
- Use kern_setitimer(), kern_getitimer(), kern_select(), kern_utimes(),
kern_statfs(), kern_fstatfs(), kern_fhstatfs(), kern_stat(),
kern_fstat(), and kern_lstat().
Tested by: cokane (amd64)
Silence on: amd64, ia64
2005-02-18 18:56:04 +00:00
|
|
|
bzero(args, sizeof(*args));
|
|
|
|
if (argv == NULL)
|
|
|
|
return (EFAULT);
|
2002-07-20 02:56:12 +00:00
|
|
|
|
- Add a custom version of exec_copyin_args() to deal with the 32-bit
pointers in argv and envv in userland and use that together with
kern_execve() and exec_free_args() to implement freebsd32_execve()
without using the stackgap.
- Fix freebsd32_adjtime() to call adjtime() rather than utimes(). Still
uses stackgap for now.
- Use kern_setitimer(), kern_getitimer(), kern_select(), kern_utimes(),
kern_statfs(), kern_fstatfs(), kern_fhstatfs(), kern_stat(),
kern_fstat(), and kern_lstat().
Tested by: cokane (amd64)
Silence on: amd64, ia64
2005-02-18 18:56:04 +00:00
|
|
|
/*
|
2010-07-27 17:31:03 +00:00
|
|
|
* Allocate demand-paged memory for the file name, argument, and
|
|
|
|
* environment strings.
|
- Add a custom version of exec_copyin_args() to deal with the 32-bit
pointers in argv and envv in userland and use that together with
kern_execve() and exec_free_args() to implement freebsd32_execve()
without using the stackgap.
- Fix freebsd32_adjtime() to call adjtime() rather than utimes(). Still
uses stackgap for now.
- Use kern_setitimer(), kern_getitimer(), kern_select(), kern_utimes(),
kern_statfs(), kern_fstatfs(), kern_fhstatfs(), kern_stat(),
kern_fstat(), and kern_lstat().
Tested by: cokane (amd64)
Silence on: amd64, ia64
2005-02-18 18:56:04 +00:00
|
|
|
*/
|
2010-07-27 17:31:03 +00:00
|
|
|
error = exec_alloc_args(args);
|
|
|
|
if (error != 0)
|
|
|
|
return (error);
|
- Add a custom version of exec_copyin_args() to deal with the 32-bit
pointers in argv and envv in userland and use that together with
kern_execve() and exec_free_args() to implement freebsd32_execve()
without using the stackgap.
- Fix freebsd32_adjtime() to call adjtime() rather than utimes(). Still
uses stackgap for now.
- Use kern_setitimer(), kern_getitimer(), kern_select(), kern_utimes(),
kern_statfs(), kern_fstatfs(), kern_fhstatfs(), kern_stat(),
kern_fstat(), and kern_lstat().
Tested by: cokane (amd64)
Silence on: amd64, ia64
2005-02-18 18:56:04 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Copy the file name.
|
|
|
|
*/
|
2008-03-31 12:08:30 +00:00
|
|
|
if (fname != NULL) {
|
2010-07-27 17:31:03 +00:00
|
|
|
args->fname = args->buf;
|
2008-03-31 12:08:30 +00:00
|
|
|
error = (segflg == UIO_SYSSPACE) ?
|
|
|
|
copystr(fname, args->fname, PATH_MAX, &length) :
|
|
|
|
copyinstr(fname, args->fname, PATH_MAX, &length);
|
|
|
|
if (error != 0)
|
|
|
|
goto err_exit;
|
|
|
|
} else
|
Change the order in which the file name, arguments, environment, and
shell command are stored in exec*()'s demand-paged string buffer. For
a "buildworld" on an 8GB amd64 multiprocessor, the new order reduces
the number of global TLB shootdowns by 31%. It also eliminates about
330k page faults on the kernel address space.
Change exec_shell_imgact() to use "args->begin_argv" consistently as
the start of the argument and environment strings. Previously, it
would sometimes use "args->buf", which is the start of the overall
buffer, but no longer the start of the argument and environment
strings. While I'm here, eliminate unnecessary passing of "&length"
to copystr(), where we don't actually care about the length of the
copied string.
Clean up the initialization of the exec map. In particular, use the
correct size for an entry, and express that size in the same way that
is used when an entry is allocated. The old size was one page too
large. (This discrepancy originated in 2004 when I rewrote
exec_map_first_page() to use sf_buf_alloc() instead of the exec map
for mapping the first page of the executable.)
Reviewed by: kib
2010-07-25 17:43:38 +00:00
|
|
|
length = 0;
|
|
|
|
|
2010-07-27 17:31:03 +00:00
|
|
|
args->begin_argv = args->buf + length;
|
Change the order in which the file name, arguments, environment, and
shell command are stored in exec*()'s demand-paged string buffer. For
a "buildworld" on an 8GB amd64 multiprocessor, the new order reduces
the number of global TLB shootdowns by 31%. It also eliminates about
330k page faults on the kernel address space.
Change exec_shell_imgact() to use "args->begin_argv" consistently as
the start of the argument and environment strings. Previously, it
would sometimes use "args->buf", which is the start of the overall
buffer, but no longer the start of the argument and environment
strings. While I'm here, eliminate unnecessary passing of "&length"
to copystr(), where we don't actually care about the length of the
copied string.
Clean up the initialization of the exec map. In particular, use the
correct size for an entry, and express that size in the same way that
is used when an entry is allocated. The old size was one page too
large. (This discrepancy originated in 2004 when I rewrote
exec_map_first_page() to use sf_buf_alloc() instead of the exec map
for mapping the first page of the executable.)
Reviewed by: kib
2010-07-25 17:43:38 +00:00
|
|
|
args->endp = args->begin_argv;
|
|
|
|
args->stringspace = ARG_MAX;
|
- Add a custom version of exec_copyin_args() to deal with the 32-bit
pointers in argv and envv in userland and use that together with
kern_execve() and exec_free_args() to implement freebsd32_execve()
without using the stackgap.
- Fix freebsd32_adjtime() to call adjtime() rather than utimes(). Still
uses stackgap for now.
- Use kern_setitimer(), kern_getitimer(), kern_select(), kern_utimes(),
kern_statfs(), kern_fstatfs(), kern_fhstatfs(), kern_stat(),
kern_fstat(), and kern_lstat().
Tested by: cokane (amd64)
Silence on: amd64, ia64
2005-02-18 18:56:04 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* extract arguments first
|
|
|
|
*/
|
|
|
|
p32 = argv;
|
|
|
|
for (;;) {
|
|
|
|
error = copyin(p32++, &arg, sizeof(arg));
|
|
|
|
if (error)
|
2006-03-08 20:21:54 +00:00
|
|
|
goto err_exit;
|
- Add a custom version of exec_copyin_args() to deal with the 32-bit
pointers in argv and envv in userland and use that together with
kern_execve() and exec_free_args() to implement freebsd32_execve()
without using the stackgap.
- Fix freebsd32_adjtime() to call adjtime() rather than utimes(). Still
uses stackgap for now.
- Use kern_setitimer(), kern_getitimer(), kern_select(), kern_utimes(),
kern_statfs(), kern_fstatfs(), kern_fhstatfs(), kern_stat(),
kern_fstat(), and kern_lstat().
Tested by: cokane (amd64)
Silence on: amd64, ia64
2005-02-18 18:56:04 +00:00
|
|
|
if (arg == 0)
|
|
|
|
break;
|
|
|
|
argp = PTRIN(arg);
|
|
|
|
error = copyinstr(argp, args->endp, args->stringspace, &length);
|
|
|
|
if (error) {
|
|
|
|
if (error == ENAMETOOLONG)
|
2006-03-08 20:21:54 +00:00
|
|
|
error = E2BIG;
|
|
|
|
goto err_exit;
|
- Add a custom version of exec_copyin_args() to deal with the 32-bit
pointers in argv and envv in userland and use that together with
kern_execve() and exec_free_args() to implement freebsd32_execve()
without using the stackgap.
- Fix freebsd32_adjtime() to call adjtime() rather than utimes(). Still
uses stackgap for now.
- Use kern_setitimer(), kern_getitimer(), kern_select(), kern_utimes(),
kern_statfs(), kern_fstatfs(), kern_fhstatfs(), kern_stat(),
kern_fstat(), and kern_lstat().
Tested by: cokane (amd64)
Silence on: amd64, ia64
2005-02-18 18:56:04 +00:00
|
|
|
}
|
|
|
|
args->stringspace -= length;
|
|
|
|
args->endp += length;
|
|
|
|
args->argc++;
|
2002-07-20 02:56:12 +00:00
|
|
|
}
|
- Add a custom version of exec_copyin_args() to deal with the 32-bit
pointers in argv and envv in userland and use that together with
kern_execve() and exec_free_args() to implement freebsd32_execve()
without using the stackgap.
- Fix freebsd32_adjtime() to call adjtime() rather than utimes(). Still
uses stackgap for now.
- Use kern_setitimer(), kern_getitimer(), kern_select(), kern_utimes(),
kern_statfs(), kern_fstatfs(), kern_fhstatfs(), kern_stat(),
kern_fstat(), and kern_lstat().
Tested by: cokane (amd64)
Silence on: amd64, ia64
2005-02-18 18:56:04 +00:00
|
|
|
|
|
|
|
args->begin_envv = args->endp;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* extract environment strings
|
|
|
|
*/
|
|
|
|
if (envv) {
|
|
|
|
p32 = envv;
|
|
|
|
for (;;) {
|
2002-07-20 02:56:12 +00:00
|
|
|
error = copyin(p32++, &arg, sizeof(arg));
|
|
|
|
if (error)
|
2006-03-08 20:21:54 +00:00
|
|
|
goto err_exit;
|
- Add a custom version of exec_copyin_args() to deal with the 32-bit
pointers in argv and envv in userland and use that together with
kern_execve() and exec_free_args() to implement freebsd32_execve()
without using the stackgap.
- Fix freebsd32_adjtime() to call adjtime() rather than utimes(). Still
uses stackgap for now.
- Use kern_setitimer(), kern_getitimer(), kern_select(), kern_utimes(),
kern_statfs(), kern_fstatfs(), kern_fhstatfs(), kern_stat(),
kern_fstat(), and kern_lstat().
Tested by: cokane (amd64)
Silence on: amd64, ia64
2005-02-18 18:56:04 +00:00
|
|
|
if (arg == 0)
|
|
|
|
break;
|
|
|
|
envp = PTRIN(arg);
|
|
|
|
error = copyinstr(envp, args->endp, args->stringspace,
|
|
|
|
&length);
|
|
|
|
if (error) {
|
|
|
|
if (error == ENAMETOOLONG)
|
2006-03-08 20:21:54 +00:00
|
|
|
error = E2BIG;
|
|
|
|
goto err_exit;
|
- Add a custom version of exec_copyin_args() to deal with the 32-bit
pointers in argv and envv in userland and use that together with
kern_execve() and exec_free_args() to implement freebsd32_execve()
without using the stackgap.
- Fix freebsd32_adjtime() to call adjtime() rather than utimes(). Still
uses stackgap for now.
- Use kern_setitimer(), kern_getitimer(), kern_select(), kern_utimes(),
kern_statfs(), kern_fstatfs(), kern_fhstatfs(), kern_stat(),
kern_fstat(), and kern_lstat().
Tested by: cokane (amd64)
Silence on: amd64, ia64
2005-02-18 18:56:04 +00:00
|
|
|
}
|
|
|
|
args->stringspace -= length;
|
|
|
|
args->endp += length;
|
|
|
|
args->envc++;
|
|
|
|
}
|
2002-07-20 02:56:12 +00:00
|
|
|
}
|
|
|
|
|
- Add a custom version of exec_copyin_args() to deal with the 32-bit
pointers in argv and envv in userland and use that together with
kern_execve() and exec_free_args() to implement freebsd32_execve()
without using the stackgap.
- Fix freebsd32_adjtime() to call adjtime() rather than utimes(). Still
uses stackgap for now.
- Use kern_setitimer(), kern_getitimer(), kern_select(), kern_utimes(),
kern_statfs(), kern_fstatfs(), kern_fhstatfs(), kern_stat(),
kern_fstat(), and kern_lstat().
Tested by: cokane (amd64)
Silence on: amd64, ia64
2005-02-18 18:56:04 +00:00
|
|
|
return (0);
|
2006-03-08 20:21:54 +00:00
|
|
|
|
|
|
|
err_exit:
|
2010-07-23 18:58:27 +00:00
|
|
|
exec_free_args(args);
|
2006-03-08 20:21:54 +00:00
|
|
|
return (error);
|
- Add a custom version of exec_copyin_args() to deal with the 32-bit
pointers in argv and envv in userland and use that together with
kern_execve() and exec_free_args() to implement freebsd32_execve()
without using the stackgap.
- Fix freebsd32_adjtime() to call adjtime() rather than utimes(). Still
uses stackgap for now.
- Use kern_setitimer(), kern_getitimer(), kern_select(), kern_utimes(),
kern_statfs(), kern_fstatfs(), kern_fhstatfs(), kern_stat(),
kern_fstat(), and kern_lstat().
Tested by: cokane (amd64)
Silence on: amd64, ia64
2005-02-18 18:56:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
freebsd32_execve(struct thread *td, struct freebsd32_execve_args *uap)
|
|
|
|
{
|
|
|
|
struct image_args eargs;
|
|
|
|
int error;
|
|
|
|
|
|
|
|
error = freebsd32_exec_copyin_args(&eargs, uap->fname, UIO_USERSPACE,
|
|
|
|
uap->argv, uap->envv);
|
|
|
|
if (error == 0)
|
|
|
|
error = kern_execve(td, &eargs, NULL);
|
|
|
|
return (error);
|
2002-07-20 02:56:12 +00:00
|
|
|
}
|
|
|
|
|
2008-03-31 12:08:30 +00:00
|
|
|
int
|
|
|
|
freebsd32_fexecve(struct thread *td, struct freebsd32_fexecve_args *uap)
|
|
|
|
{
|
|
|
|
struct image_args eargs;
|
|
|
|
int error;
|
|
|
|
|
|
|
|
error = freebsd32_exec_copyin_args(&eargs, NULL, UIO_SYSSPACE,
|
|
|
|
uap->argv, uap->envv);
|
|
|
|
if (error == 0) {
|
|
|
|
eargs.fd = uap->fd;
|
|
|
|
error = kern_execve(td, &eargs, NULL);
|
|
|
|
}
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
2003-05-14 04:10:49 +00:00
|
|
|
#ifdef __ia64__
|
2002-07-20 02:56:12 +00:00
|
|
|
static int
|
2003-08-22 23:07:28 +00:00
|
|
|
freebsd32_mmap_partial(struct thread *td, vm_offset_t start, vm_offset_t end,
|
|
|
|
int prot, int fd, off_t pos)
|
2002-07-20 02:56:12 +00:00
|
|
|
{
|
|
|
|
vm_map_t map;
|
|
|
|
vm_map_entry_t entry;
|
|
|
|
int rv;
|
|
|
|
|
|
|
|
map = &td->td_proc->p_vmspace->vm_map;
|
|
|
|
if (fd != -1)
|
|
|
|
prot |= VM_PROT_WRITE;
|
|
|
|
|
|
|
|
if (vm_map_lookup_entry(map, start, &entry)) {
|
|
|
|
if ((entry->protection & prot) != prot) {
|
|
|
|
rv = vm_map_protect(map,
|
|
|
|
trunc_page(start),
|
|
|
|
round_page(end),
|
|
|
|
entry->protection | prot,
|
|
|
|
FALSE);
|
|
|
|
if (rv != KERN_SUCCESS)
|
|
|
|
return (EINVAL);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
vm_offset_t addr = trunc_page(start);
|
|
|
|
rv = vm_map_find(map, 0, 0,
|
|
|
|
&addr, PAGE_SIZE, FALSE, prot,
|
|
|
|
VM_PROT_ALL, 0);
|
|
|
|
if (rv != KERN_SUCCESS)
|
|
|
|
return (EINVAL);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (fd != -1) {
|
|
|
|
struct pread_args r;
|
2002-12-14 01:56:26 +00:00
|
|
|
r.fd = fd;
|
|
|
|
r.buf = (void *) start;
|
|
|
|
r.nbyte = end - start;
|
|
|
|
r.offset = pos;
|
2011-09-16 13:58:51 +00:00
|
|
|
return (sys_pread(td, &r));
|
2002-07-20 02:56:12 +00:00
|
|
|
} else {
|
|
|
|
while (start < end) {
|
|
|
|
subyte((void *) start, 0);
|
|
|
|
start++;
|
|
|
|
}
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
}
|
2003-05-14 04:10:49 +00:00
|
|
|
#endif
|
2002-07-20 02:56:12 +00:00
|
|
|
|
2011-10-13 18:25:10 +00:00
|
|
|
int
|
|
|
|
freebsd32_mprotect(struct thread *td, struct freebsd32_mprotect_args *uap)
|
|
|
|
{
|
|
|
|
struct mprotect_args ap;
|
|
|
|
|
2011-10-13 22:33:03 +00:00
|
|
|
ap.addr = PTRIN(uap->addr);
|
2011-10-13 18:25:10 +00:00
|
|
|
ap.len = uap->len;
|
|
|
|
ap.prot = uap->prot;
|
|
|
|
#if defined(__amd64__) || defined(__ia64__)
|
2011-10-15 12:35:18 +00:00
|
|
|
if (i386_read_exec && (ap.prot & PROT_READ) != 0)
|
2011-10-13 18:25:10 +00:00
|
|
|
ap.prot |= PROT_EXEC;
|
|
|
|
#endif
|
|
|
|
return (sys_mprotect(td, &ap));
|
|
|
|
}
|
|
|
|
|
2002-07-20 02:56:12 +00:00
|
|
|
int
|
2003-08-22 23:07:28 +00:00
|
|
|
freebsd32_mmap(struct thread *td, struct freebsd32_mmap_args *uap)
|
2002-07-20 02:56:12 +00:00
|
|
|
{
|
|
|
|
struct mmap_args ap;
|
2002-12-14 01:56:26 +00:00
|
|
|
vm_offset_t addr = (vm_offset_t) uap->addr;
|
|
|
|
vm_size_t len = uap->len;
|
|
|
|
int prot = uap->prot;
|
|
|
|
int flags = uap->flags;
|
|
|
|
int fd = uap->fd;
|
2010-03-11 14:49:06 +00:00
|
|
|
off_t pos = PAIR32TO64(off_t,uap->pos);
|
2003-05-14 04:10:49 +00:00
|
|
|
#ifdef __ia64__
|
2002-07-20 02:56:12 +00:00
|
|
|
vm_size_t pageoff;
|
|
|
|
int error;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Attempt to handle page size hassles.
|
|
|
|
*/
|
|
|
|
pageoff = (pos & PAGE_MASK);
|
|
|
|
if (flags & MAP_FIXED) {
|
|
|
|
vm_offset_t start, end;
|
|
|
|
start = addr;
|
|
|
|
end = addr + len;
|
|
|
|
|
|
|
|
if (start != trunc_page(start)) {
|
2003-08-22 23:07:28 +00:00
|
|
|
error = freebsd32_mmap_partial(td, start,
|
|
|
|
round_page(start), prot,
|
|
|
|
fd, pos);
|
2002-07-20 02:56:12 +00:00
|
|
|
if (fd != -1)
|
|
|
|
pos += round_page(start) - start;
|
|
|
|
start = round_page(start);
|
|
|
|
}
|
|
|
|
if (end != round_page(end)) {
|
|
|
|
vm_offset_t t = trunc_page(end);
|
2003-08-22 23:07:28 +00:00
|
|
|
error = freebsd32_mmap_partial(td, t, end,
|
2002-07-20 02:56:12 +00:00
|
|
|
prot, fd,
|
|
|
|
pos + t - start);
|
|
|
|
end = trunc_page(end);
|
|
|
|
}
|
|
|
|
if (end > start && fd != -1 && (pos & PAGE_MASK)) {
|
|
|
|
/*
|
|
|
|
* We can't map this region at all. The specified
|
|
|
|
* address doesn't have the same alignment as the file
|
|
|
|
* position. Fake the mapping by simply reading the
|
|
|
|
* entire region into memory. First we need to make
|
|
|
|
* sure the region exists.
|
|
|
|
*/
|
|
|
|
vm_map_t map;
|
|
|
|
struct pread_args r;
|
|
|
|
int rv;
|
|
|
|
|
|
|
|
prot |= VM_PROT_WRITE;
|
|
|
|
map = &td->td_proc->p_vmspace->vm_map;
|
|
|
|
rv = vm_map_remove(map, start, end);
|
2007-05-01 17:10:01 +00:00
|
|
|
if (rv != KERN_SUCCESS)
|
2002-07-20 02:56:12 +00:00
|
|
|
return (EINVAL);
|
|
|
|
rv = vm_map_find(map, 0, 0,
|
|
|
|
&start, end - start, FALSE,
|
|
|
|
prot, VM_PROT_ALL, 0);
|
|
|
|
if (rv != KERN_SUCCESS)
|
|
|
|
return (EINVAL);
|
2002-12-14 01:56:26 +00:00
|
|
|
r.fd = fd;
|
|
|
|
r.buf = (void *) start;
|
|
|
|
r.nbyte = end - start;
|
|
|
|
r.offset = pos;
|
2011-09-16 13:58:51 +00:00
|
|
|
error = sys_pread(td, &r);
|
2002-07-20 02:56:12 +00:00
|
|
|
if (error)
|
|
|
|
return (error);
|
|
|
|
|
|
|
|
td->td_retval[0] = addr;
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
if (end == start) {
|
|
|
|
/*
|
|
|
|
* After dealing with the ragged ends, there
|
|
|
|
* might be none left.
|
|
|
|
*/
|
|
|
|
td->td_retval[0] = addr;
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
addr = start;
|
|
|
|
len = end - start;
|
|
|
|
}
|
2003-05-14 04:10:49 +00:00
|
|
|
#endif
|
2002-07-20 02:56:12 +00:00
|
|
|
|
2011-10-13 18:18:42 +00:00
|
|
|
#if defined(__amd64__) || defined(__ia64__)
|
2011-10-15 12:35:18 +00:00
|
|
|
if (i386_read_exec && (prot & PROT_READ))
|
2011-10-13 18:18:42 +00:00
|
|
|
prot |= PROT_EXEC;
|
|
|
|
#endif
|
|
|
|
|
2002-12-14 01:56:26 +00:00
|
|
|
ap.addr = (void *) addr;
|
|
|
|
ap.len = len;
|
|
|
|
ap.prot = prot;
|
|
|
|
ap.flags = flags;
|
|
|
|
ap.fd = fd;
|
|
|
|
ap.pos = pos;
|
2002-07-20 02:56:12 +00:00
|
|
|
|
2011-09-16 13:58:51 +00:00
|
|
|
return (sys_mmap(td, &ap));
|
2002-07-20 02:56:12 +00:00
|
|
|
}
|
|
|
|
|
2007-07-04 23:04:41 +00:00
|
|
|
#ifdef COMPAT_FREEBSD6
|
|
|
|
int
|
|
|
|
freebsd6_freebsd32_mmap(struct thread *td, struct freebsd6_freebsd32_mmap_args *uap)
|
|
|
|
{
|
|
|
|
struct freebsd32_mmap_args ap;
|
|
|
|
|
|
|
|
ap.addr = uap->addr;
|
|
|
|
ap.len = uap->len;
|
|
|
|
ap.prot = uap->prot;
|
|
|
|
ap.flags = uap->flags;
|
|
|
|
ap.fd = uap->fd;
|
2010-03-11 14:49:06 +00:00
|
|
|
ap.pos1 = uap->pos1;
|
|
|
|
ap.pos2 = uap->pos2;
|
2007-07-04 23:04:41 +00:00
|
|
|
|
|
|
|
return (freebsd32_mmap(td, &ap));
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2002-07-20 02:56:12 +00:00
|
|
|
int
|
2003-08-22 23:07:28 +00:00
|
|
|
freebsd32_setitimer(struct thread *td, struct freebsd32_setitimer_args *uap)
|
2002-07-20 02:56:12 +00:00
|
|
|
{
|
- Add a custom version of exec_copyin_args() to deal with the 32-bit
pointers in argv and envv in userland and use that together with
kern_execve() and exec_free_args() to implement freebsd32_execve()
without using the stackgap.
- Fix freebsd32_adjtime() to call adjtime() rather than utimes(). Still
uses stackgap for now.
- Use kern_setitimer(), kern_getitimer(), kern_select(), kern_utimes(),
kern_statfs(), kern_fstatfs(), kern_fhstatfs(), kern_stat(),
kern_fstat(), and kern_lstat().
Tested by: cokane (amd64)
Silence on: amd64, ia64
2005-02-18 18:56:04 +00:00
|
|
|
struct itimerval itv, oitv, *itvp;
|
|
|
|
struct itimerval32 i32;
|
2002-07-20 02:56:12 +00:00
|
|
|
int error;
|
|
|
|
|
- Add a custom version of exec_copyin_args() to deal with the 32-bit
pointers in argv and envv in userland and use that together with
kern_execve() and exec_free_args() to implement freebsd32_execve()
without using the stackgap.
- Fix freebsd32_adjtime() to call adjtime() rather than utimes(). Still
uses stackgap for now.
- Use kern_setitimer(), kern_getitimer(), kern_select(), kern_utimes(),
kern_statfs(), kern_fstatfs(), kern_fhstatfs(), kern_stat(),
kern_fstat(), and kern_lstat().
Tested by: cokane (amd64)
Silence on: amd64, ia64
2005-02-18 18:56:04 +00:00
|
|
|
if (uap->itv != NULL) {
|
|
|
|
error = copyin(uap->itv, &i32, sizeof(i32));
|
2002-07-20 02:56:12 +00:00
|
|
|
if (error)
|
|
|
|
return (error);
|
- Add a custom version of exec_copyin_args() to deal with the 32-bit
pointers in argv and envv in userland and use that together with
kern_execve() and exec_free_args() to implement freebsd32_execve()
without using the stackgap.
- Fix freebsd32_adjtime() to call adjtime() rather than utimes(). Still
uses stackgap for now.
- Use kern_setitimer(), kern_getitimer(), kern_select(), kern_utimes(),
kern_statfs(), kern_fstatfs(), kern_fhstatfs(), kern_stat(),
kern_fstat(), and kern_lstat().
Tested by: cokane (amd64)
Silence on: amd64, ia64
2005-02-18 18:56:04 +00:00
|
|
|
TV_CP(i32, itv, it_interval);
|
|
|
|
TV_CP(i32, itv, it_value);
|
|
|
|
itvp = &itv;
|
|
|
|
} else
|
|
|
|
itvp = NULL;
|
|
|
|
error = kern_setitimer(td, uap->which, itvp, &oitv);
|
|
|
|
if (error || uap->oitv == NULL)
|
2002-07-20 02:56:12 +00:00
|
|
|
return (error);
|
- Add a custom version of exec_copyin_args() to deal with the 32-bit
pointers in argv and envv in userland and use that together with
kern_execve() and exec_free_args() to implement freebsd32_execve()
without using the stackgap.
- Fix freebsd32_adjtime() to call adjtime() rather than utimes(). Still
uses stackgap for now.
- Use kern_setitimer(), kern_getitimer(), kern_select(), kern_utimes(),
kern_statfs(), kern_fstatfs(), kern_fhstatfs(), kern_stat(),
kern_fstat(), and kern_lstat().
Tested by: cokane (amd64)
Silence on: amd64, ia64
2005-02-18 18:56:04 +00:00
|
|
|
TV_CP(oitv, i32, it_interval);
|
|
|
|
TV_CP(oitv, i32, it_value);
|
|
|
|
return (copyout(&i32, uap->oitv, sizeof(i32)));
|
2002-07-20 02:56:12 +00:00
|
|
|
}
|
|
|
|
|
2004-01-28 23:45:48 +00:00
|
|
|
int
|
|
|
|
freebsd32_getitimer(struct thread *td, struct freebsd32_getitimer_args *uap)
|
|
|
|
{
|
- Add a custom version of exec_copyin_args() to deal with the 32-bit
pointers in argv and envv in userland and use that together with
kern_execve() and exec_free_args() to implement freebsd32_execve()
without using the stackgap.
- Fix freebsd32_adjtime() to call adjtime() rather than utimes(). Still
uses stackgap for now.
- Use kern_setitimer(), kern_getitimer(), kern_select(), kern_utimes(),
kern_statfs(), kern_fstatfs(), kern_fhstatfs(), kern_stat(),
kern_fstat(), and kern_lstat().
Tested by: cokane (amd64)
Silence on: amd64, ia64
2005-02-18 18:56:04 +00:00
|
|
|
struct itimerval itv;
|
|
|
|
struct itimerval32 i32;
|
2004-01-28 23:45:48 +00:00
|
|
|
int error;
|
|
|
|
|
- Add a custom version of exec_copyin_args() to deal with the 32-bit
pointers in argv and envv in userland and use that together with
kern_execve() and exec_free_args() to implement freebsd32_execve()
without using the stackgap.
- Fix freebsd32_adjtime() to call adjtime() rather than utimes(). Still
uses stackgap for now.
- Use kern_setitimer(), kern_getitimer(), kern_select(), kern_utimes(),
kern_statfs(), kern_fstatfs(), kern_fhstatfs(), kern_stat(),
kern_fstat(), and kern_lstat().
Tested by: cokane (amd64)
Silence on: amd64, ia64
2005-02-18 18:56:04 +00:00
|
|
|
error = kern_getitimer(td, uap->which, &itv);
|
|
|
|
if (error || uap->itv == NULL)
|
2004-01-28 23:45:48 +00:00
|
|
|
return (error);
|
- Add a custom version of exec_copyin_args() to deal with the 32-bit
pointers in argv and envv in userland and use that together with
kern_execve() and exec_free_args() to implement freebsd32_execve()
without using the stackgap.
- Fix freebsd32_adjtime() to call adjtime() rather than utimes(). Still
uses stackgap for now.
- Use kern_setitimer(), kern_getitimer(), kern_select(), kern_utimes(),
kern_statfs(), kern_fstatfs(), kern_fhstatfs(), kern_stat(),
kern_fstat(), and kern_lstat().
Tested by: cokane (amd64)
Silence on: amd64, ia64
2005-02-18 18:56:04 +00:00
|
|
|
TV_CP(itv, i32, it_interval);
|
|
|
|
TV_CP(itv, i32, it_value);
|
|
|
|
return (copyout(&i32, uap->itv, sizeof(i32)));
|
2004-01-28 23:45:48 +00:00
|
|
|
}
|
|
|
|
|
2002-07-20 02:56:12 +00:00
|
|
|
int
|
2003-08-22 23:07:28 +00:00
|
|
|
freebsd32_select(struct thread *td, struct freebsd32_select_args *uap)
|
2002-07-20 02:56:12 +00:00
|
|
|
{
|
- Add a custom version of exec_copyin_args() to deal with the 32-bit
pointers in argv and envv in userland and use that together with
kern_execve() and exec_free_args() to implement freebsd32_execve()
without using the stackgap.
- Fix freebsd32_adjtime() to call adjtime() rather than utimes(). Still
uses stackgap for now.
- Use kern_setitimer(), kern_getitimer(), kern_select(), kern_utimes(),
kern_statfs(), kern_fstatfs(), kern_fhstatfs(), kern_stat(),
kern_fstat(), and kern_lstat().
Tested by: cokane (amd64)
Silence on: amd64, ia64
2005-02-18 18:56:04 +00:00
|
|
|
struct timeval32 tv32;
|
|
|
|
struct timeval tv, *tvp;
|
2002-07-20 02:56:12 +00:00
|
|
|
int error;
|
|
|
|
|
- Add a custom version of exec_copyin_args() to deal with the 32-bit
pointers in argv and envv in userland and use that together with
kern_execve() and exec_free_args() to implement freebsd32_execve()
without using the stackgap.
- Fix freebsd32_adjtime() to call adjtime() rather than utimes(). Still
uses stackgap for now.
- Use kern_setitimer(), kern_getitimer(), kern_select(), kern_utimes(),
kern_statfs(), kern_fstatfs(), kern_fhstatfs(), kern_stat(),
kern_fstat(), and kern_lstat().
Tested by: cokane (amd64)
Silence on: amd64, ia64
2005-02-18 18:56:04 +00:00
|
|
|
if (uap->tv != NULL) {
|
|
|
|
error = copyin(uap->tv, &tv32, sizeof(tv32));
|
2002-07-20 02:56:12 +00:00
|
|
|
if (error)
|
|
|
|
return (error);
|
- Add a custom version of exec_copyin_args() to deal with the 32-bit
pointers in argv and envv in userland and use that together with
kern_execve() and exec_free_args() to implement freebsd32_execve()
without using the stackgap.
- Fix freebsd32_adjtime() to call adjtime() rather than utimes(). Still
uses stackgap for now.
- Use kern_setitimer(), kern_getitimer(), kern_select(), kern_utimes(),
kern_statfs(), kern_fstatfs(), kern_fhstatfs(), kern_stat(),
kern_fstat(), and kern_lstat().
Tested by: cokane (amd64)
Silence on: amd64, ia64
2005-02-18 18:56:04 +00:00
|
|
|
CP(tv32, tv, tv_sec);
|
|
|
|
CP(tv32, tv, tv_usec);
|
|
|
|
tvp = &tv;
|
|
|
|
} else
|
|
|
|
tvp = NULL;
|
2002-07-20 02:56:12 +00:00
|
|
|
/*
|
- Add a custom version of exec_copyin_args() to deal with the 32-bit
pointers in argv and envv in userland and use that together with
kern_execve() and exec_free_args() to implement freebsd32_execve()
without using the stackgap.
- Fix freebsd32_adjtime() to call adjtime() rather than utimes(). Still
uses stackgap for now.
- Use kern_setitimer(), kern_getitimer(), kern_select(), kern_utimes(),
kern_statfs(), kern_fstatfs(), kern_fhstatfs(), kern_stat(),
kern_fstat(), and kern_lstat().
Tested by: cokane (amd64)
Silence on: amd64, ia64
2005-02-18 18:56:04 +00:00
|
|
|
* XXX Do pointers need PTRIN()?
|
2002-07-20 02:56:12 +00:00
|
|
|
*/
|
2009-09-09 20:59:01 +00:00
|
|
|
return (kern_select(td, uap->nd, uap->in, uap->ou, uap->ex, tvp,
|
|
|
|
sizeof(int32_t) * 8));
|
2002-07-20 02:56:12 +00:00
|
|
|
}
|
|
|
|
|
2009-10-27 10:55:34 +00:00
|
|
|
int
|
|
|
|
freebsd32_pselect(struct thread *td, struct freebsd32_pselect_args *uap)
|
|
|
|
{
|
|
|
|
struct timespec32 ts32;
|
|
|
|
struct timespec ts;
|
|
|
|
struct timeval tv, *tvp;
|
|
|
|
sigset_t set, *uset;
|
|
|
|
int error;
|
|
|
|
|
|
|
|
if (uap->ts != NULL) {
|
|
|
|
error = copyin(uap->ts, &ts32, sizeof(ts32));
|
|
|
|
if (error != 0)
|
|
|
|
return (error);
|
|
|
|
CP(ts32, ts, tv_sec);
|
|
|
|
CP(ts32, ts, tv_nsec);
|
|
|
|
TIMESPEC_TO_TIMEVAL(&tv, &ts);
|
|
|
|
tvp = &tv;
|
|
|
|
} else
|
|
|
|
tvp = NULL;
|
|
|
|
if (uap->sm != NULL) {
|
|
|
|
error = copyin(uap->sm, &set, sizeof(set));
|
|
|
|
if (error != 0)
|
|
|
|
return (error);
|
|
|
|
uset = &set;
|
|
|
|
} else
|
|
|
|
uset = NULL;
|
|
|
|
/*
|
|
|
|
* XXX Do pointers need PTRIN()?
|
|
|
|
*/
|
|
|
|
error = kern_pselect(td, uap->nd, uap->in, uap->ou, uap->ex, tvp,
|
|
|
|
uset, sizeof(int32_t) * 8);
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
2005-06-03 23:15:01 +00:00
|
|
|
/*
|
|
|
|
* Copy 'count' items into the destination list pointed to by uap->eventlist.
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
freebsd32_kevent_copyout(void *arg, struct kevent *kevp, int count)
|
|
|
|
{
|
|
|
|
struct freebsd32_kevent_args *uap;
|
|
|
|
struct kevent32 ks32[KQ_NEVENTS];
|
|
|
|
int i, error = 0;
|
|
|
|
|
|
|
|
KASSERT(count <= KQ_NEVENTS, ("count (%d) > KQ_NEVENTS", count));
|
|
|
|
uap = (struct freebsd32_kevent_args *)arg;
|
|
|
|
|
|
|
|
for (i = 0; i < count; i++) {
|
|
|
|
CP(kevp[i], ks32[i], ident);
|
|
|
|
CP(kevp[i], ks32[i], filter);
|
|
|
|
CP(kevp[i], ks32[i], flags);
|
|
|
|
CP(kevp[i], ks32[i], fflags);
|
|
|
|
CP(kevp[i], ks32[i], data);
|
|
|
|
PTROUT_CP(kevp[i], ks32[i], udata);
|
|
|
|
}
|
|
|
|
error = copyout(ks32, uap->eventlist, count * sizeof *ks32);
|
|
|
|
if (error == 0)
|
|
|
|
uap->eventlist += count;
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Copy 'count' items from the list pointed to by uap->changelist.
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
freebsd32_kevent_copyin(void *arg, struct kevent *kevp, int count)
|
|
|
|
{
|
|
|
|
struct freebsd32_kevent_args *uap;
|
|
|
|
struct kevent32 ks32[KQ_NEVENTS];
|
|
|
|
int i, error = 0;
|
|
|
|
|
|
|
|
KASSERT(count <= KQ_NEVENTS, ("count (%d) > KQ_NEVENTS", count));
|
|
|
|
uap = (struct freebsd32_kevent_args *)arg;
|
|
|
|
|
|
|
|
error = copyin(uap->changelist, ks32, count * sizeof *ks32);
|
|
|
|
if (error)
|
|
|
|
goto done;
|
|
|
|
uap->changelist += count;
|
|
|
|
|
|
|
|
for (i = 0; i < count; i++) {
|
|
|
|
CP(ks32[i], kevp[i], ident);
|
|
|
|
CP(ks32[i], kevp[i], filter);
|
|
|
|
CP(ks32[i], kevp[i], flags);
|
|
|
|
CP(ks32[i], kevp[i], fflags);
|
|
|
|
CP(ks32[i], kevp[i], data);
|
|
|
|
PTRIN_CP(ks32[i], kevp[i], udata);
|
|
|
|
}
|
|
|
|
done:
|
|
|
|
return (error);
|
|
|
|
}
|
2003-10-30 02:40:30 +00:00
|
|
|
|
2003-05-14 04:10:49 +00:00
|
|
|
int
|
2003-08-22 23:07:28 +00:00
|
|
|
freebsd32_kevent(struct thread *td, struct freebsd32_kevent_args *uap)
|
2003-05-14 04:10:49 +00:00
|
|
|
{
|
|
|
|
struct timespec32 ts32;
|
2005-03-01 17:45:55 +00:00
|
|
|
struct timespec ts, *tsp;
|
2005-06-03 23:15:01 +00:00
|
|
|
struct kevent_copyops k_ops = { uap,
|
|
|
|
freebsd32_kevent_copyout,
|
|
|
|
freebsd32_kevent_copyin};
|
|
|
|
int error;
|
2003-05-14 04:10:49 +00:00
|
|
|
|
|
|
|
|
|
|
|
if (uap->timeout) {
|
|
|
|
error = copyin(uap->timeout, &ts32, sizeof(ts32));
|
|
|
|
if (error)
|
|
|
|
return (error);
|
|
|
|
CP(ts32, ts, tv_sec);
|
|
|
|
CP(ts32, ts, tv_nsec);
|
2005-03-01 17:45:55 +00:00
|
|
|
tsp = &ts;
|
|
|
|
} else
|
|
|
|
tsp = NULL;
|
2005-06-03 23:15:01 +00:00
|
|
|
error = kern_kevent(td, uap->fd, uap->nchanges, uap->nevents,
|
|
|
|
&k_ops, tsp);
|
2005-03-01 17:45:55 +00:00
|
|
|
return (error);
|
2003-05-14 04:10:49 +00:00
|
|
|
}
|
|
|
|
|
2002-07-20 02:56:12 +00:00
|
|
|
int
|
2003-08-22 23:07:28 +00:00
|
|
|
freebsd32_gettimeofday(struct thread *td,
|
|
|
|
struct freebsd32_gettimeofday_args *uap)
|
2002-07-20 02:56:12 +00:00
|
|
|
{
|
2003-12-11 02:34:49 +00:00
|
|
|
struct timeval atv;
|
|
|
|
struct timeval32 atv32;
|
|
|
|
struct timezone rtz;
|
|
|
|
int error = 0;
|
|
|
|
|
|
|
|
if (uap->tp) {
|
|
|
|
microtime(&atv);
|
|
|
|
CP(atv, atv32, tv_sec);
|
|
|
|
CP(atv, atv32, tv_usec);
|
|
|
|
error = copyout(&atv32, uap->tp, sizeof (atv32));
|
2002-07-20 02:56:12 +00:00
|
|
|
}
|
2003-12-11 02:34:49 +00:00
|
|
|
if (error == 0 && uap->tzp != NULL) {
|
|
|
|
rtz.tz_minuteswest = tz_minuteswest;
|
|
|
|
rtz.tz_dsttime = tz_dsttime;
|
|
|
|
error = copyout(&rtz, uap->tzp, sizeof (rtz));
|
2002-07-20 02:56:12 +00:00
|
|
|
}
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2003-08-22 23:07:28 +00:00
|
|
|
freebsd32_getrusage(struct thread *td, struct freebsd32_getrusage_args *uap)
|
2002-07-20 02:56:12 +00:00
|
|
|
{
|
2004-10-05 18:51:11 +00:00
|
|
|
struct rusage32 s32;
|
|
|
|
struct rusage s;
|
2002-07-20 02:56:12 +00:00
|
|
|
int error;
|
|
|
|
|
2004-10-05 18:51:11 +00:00
|
|
|
error = kern_getrusage(td, uap->who, &s);
|
2002-07-20 02:56:12 +00:00
|
|
|
if (error)
|
|
|
|
return (error);
|
2004-10-05 18:51:11 +00:00
|
|
|
if (uap->rusage != NULL) {
|
2010-04-21 19:28:01 +00:00
|
|
|
freebsd32_rusage_out(&s, &s32);
|
2004-10-05 18:51:11 +00:00
|
|
|
error = copyout(&s32, uap->rusage, sizeof(s32));
|
2002-07-20 02:56:12 +00:00
|
|
|
}
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
2005-03-31 22:58:13 +00:00
|
|
|
static int
|
|
|
|
freebsd32_copyinuio(struct iovec32 *iovp, u_int iovcnt, struct uio **uiop)
|
2002-07-20 02:56:12 +00:00
|
|
|
{
|
2005-03-31 22:58:13 +00:00
|
|
|
struct iovec32 iov32;
|
|
|
|
struct iovec *iov;
|
|
|
|
struct uio *uio;
|
|
|
|
u_int iovlen;
|
|
|
|
int error, i;
|
2002-07-20 02:56:12 +00:00
|
|
|
|
2005-03-31 22:58:13 +00:00
|
|
|
*uiop = NULL;
|
|
|
|
if (iovcnt > UIO_MAXIOV)
|
2002-07-20 02:56:12 +00:00
|
|
|
return (EINVAL);
|
2005-03-31 22:58:13 +00:00
|
|
|
iovlen = iovcnt * sizeof(struct iovec);
|
|
|
|
uio = malloc(iovlen + sizeof *uio, M_IOV, M_WAITOK);
|
|
|
|
iov = (struct iovec *)(uio + 1);
|
|
|
|
for (i = 0; i < iovcnt; i++) {
|
|
|
|
error = copyin(&iovp[i], &iov32, sizeof(struct iovec32));
|
|
|
|
if (error) {
|
|
|
|
free(uio, M_IOV);
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
iov[i].iov_base = PTRIN(iov32.iov_base);
|
|
|
|
iov[i].iov_len = iov32.iov_len;
|
2002-07-20 02:56:12 +00:00
|
|
|
}
|
2005-03-31 22:58:13 +00:00
|
|
|
uio->uio_iov = iov;
|
|
|
|
uio->uio_iovcnt = iovcnt;
|
|
|
|
uio->uio_segflg = UIO_USERSPACE;
|
|
|
|
uio->uio_offset = -1;
|
|
|
|
uio->uio_resid = 0;
|
|
|
|
for (i = 0; i < iovcnt; i++) {
|
|
|
|
if (iov->iov_len > INT_MAX - uio->uio_resid) {
|
|
|
|
free(uio, M_IOV);
|
|
|
|
return (EINVAL);
|
|
|
|
}
|
|
|
|
uio->uio_resid += iov->iov_len;
|
|
|
|
iov++;
|
|
|
|
}
|
|
|
|
*uiop = uio;
|
|
|
|
return (0);
|
|
|
|
}
|
2002-07-20 02:56:12 +00:00
|
|
|
|
2005-03-31 22:58:13 +00:00
|
|
|
int
|
|
|
|
freebsd32_readv(struct thread *td, struct freebsd32_readv_args *uap)
|
|
|
|
{
|
|
|
|
struct uio *auio;
|
|
|
|
int error;
|
2002-07-20 02:56:12 +00:00
|
|
|
|
2005-03-31 22:58:13 +00:00
|
|
|
error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
|
|
|
|
if (error)
|
|
|
|
return (error);
|
|
|
|
error = kern_readv(td, uap->fd, auio);
|
|
|
|
free(auio, M_IOV);
|
2002-07-20 02:56:12 +00:00
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2003-08-22 23:07:28 +00:00
|
|
|
freebsd32_writev(struct thread *td, struct freebsd32_writev_args *uap)
|
2002-07-20 02:56:12 +00:00
|
|
|
{
|
2005-03-31 22:58:13 +00:00
|
|
|
struct uio *auio;
|
|
|
|
int error;
|
2002-07-20 02:56:12 +00:00
|
|
|
|
2005-03-31 22:58:13 +00:00
|
|
|
error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
|
|
|
|
if (error)
|
|
|
|
return (error);
|
|
|
|
error = kern_writev(td, uap->fd, auio);
|
|
|
|
free(auio, M_IOV);
|
2002-07-20 02:56:12 +00:00
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
2005-07-07 18:17:55 +00:00
|
|
|
int
|
|
|
|
freebsd32_preadv(struct thread *td, struct freebsd32_preadv_args *uap)
|
|
|
|
{
|
|
|
|
struct uio *auio;
|
|
|
|
int error;
|
|
|
|
|
|
|
|
error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
|
|
|
|
if (error)
|
|
|
|
return (error);
|
2010-03-11 14:49:06 +00:00
|
|
|
error = kern_preadv(td, uap->fd, auio, PAIR32TO64(off_t,uap->offset));
|
2005-07-07 18:17:55 +00:00
|
|
|
free(auio, M_IOV);
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
freebsd32_pwritev(struct thread *td, struct freebsd32_pwritev_args *uap)
|
|
|
|
{
|
|
|
|
struct uio *auio;
|
|
|
|
int error;
|
|
|
|
|
|
|
|
error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
|
|
|
|
if (error)
|
|
|
|
return (error);
|
2010-03-11 14:49:06 +00:00
|
|
|
error = kern_pwritev(td, uap->fd, auio, PAIR32TO64(off_t,uap->offset));
|
2005-07-07 18:17:55 +00:00
|
|
|
free(auio, M_IOV);
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
2010-03-19 10:49:03 +00:00
|
|
|
int
|
2005-10-31 21:09:56 +00:00
|
|
|
freebsd32_copyiniov(struct iovec32 *iovp32, u_int iovcnt, struct iovec **iovp,
|
2005-10-15 05:57:06 +00:00
|
|
|
int error)
|
|
|
|
{
|
|
|
|
struct iovec32 iov32;
|
2005-10-31 21:09:56 +00:00
|
|
|
struct iovec *iov;
|
2005-10-15 05:57:06 +00:00
|
|
|
u_int iovlen;
|
2005-10-31 21:09:56 +00:00
|
|
|
int i;
|
2005-10-15 05:57:06 +00:00
|
|
|
|
2005-10-31 21:09:56 +00:00
|
|
|
*iovp = NULL;
|
2005-10-15 05:57:06 +00:00
|
|
|
if (iovcnt > UIO_MAXIOV)
|
|
|
|
return (error);
|
|
|
|
iovlen = iovcnt * sizeof(struct iovec);
|
2005-10-31 21:09:56 +00:00
|
|
|
iov = malloc(iovlen, M_IOV, M_WAITOK);
|
2005-10-15 05:57:06 +00:00
|
|
|
for (i = 0; i < iovcnt; i++) {
|
2005-10-31 21:09:56 +00:00
|
|
|
error = copyin(&iovp32[i], &iov32, sizeof(struct iovec32));
|
2005-10-15 05:57:06 +00:00
|
|
|
if (error) {
|
2005-10-31 21:09:56 +00:00
|
|
|
free(iov, M_IOV);
|
2005-10-15 05:57:06 +00:00
|
|
|
return (error);
|
|
|
|
}
|
2005-10-31 21:09:56 +00:00
|
|
|
iov[i].iov_base = PTRIN(iov32.iov_base);
|
|
|
|
iov[i].iov_len = iov32.iov_len;
|
|
|
|
}
|
|
|
|
*iovp = iov;
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
2005-10-15 05:57:06 +00:00
|
|
|
static int
|
|
|
|
freebsd32_copyinmsghdr(struct msghdr32 *msg32, struct msghdr *msg)
|
|
|
|
{
|
|
|
|
struct msghdr32 m32;
|
|
|
|
int error;
|
|
|
|
|
|
|
|
error = copyin(msg32, &m32, sizeof(m32));
|
|
|
|
if (error)
|
|
|
|
return (error);
|
|
|
|
msg->msg_name = PTRIN(m32.msg_name);
|
|
|
|
msg->msg_namelen = m32.msg_namelen;
|
|
|
|
msg->msg_iov = PTRIN(m32.msg_iov);
|
|
|
|
msg->msg_iovlen = m32.msg_iovlen;
|
|
|
|
msg->msg_control = PTRIN(m32.msg_control);
|
|
|
|
msg->msg_controllen = m32.msg_controllen;
|
|
|
|
msg->msg_flags = m32.msg_flags;
|
2005-10-31 21:09:56 +00:00
|
|
|
return (0);
|
2005-10-15 05:57:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
freebsd32_copyoutmsghdr(struct msghdr *msg, struct msghdr32 *msg32)
|
|
|
|
{
|
|
|
|
struct msghdr32 m32;
|
|
|
|
int error;
|
|
|
|
|
|
|
|
m32.msg_name = PTROUT(msg->msg_name);
|
|
|
|
m32.msg_namelen = msg->msg_namelen;
|
|
|
|
m32.msg_iov = PTROUT(msg->msg_iov);
|
|
|
|
m32.msg_iovlen = msg->msg_iovlen;
|
|
|
|
m32.msg_control = PTROUT(msg->msg_control);
|
|
|
|
m32.msg_controllen = msg->msg_controllen;
|
|
|
|
m32.msg_flags = msg->msg_flags;
|
|
|
|
error = copyout(&m32, msg32, sizeof(m32));
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
2012-03-03 21:39:12 +00:00
|
|
|
#ifndef __mips__
|
2005-10-31 21:09:56 +00:00
|
|
|
#define FREEBSD32_ALIGNBYTES (sizeof(int) - 1)
|
2012-03-03 21:39:12 +00:00
|
|
|
#else
|
|
|
|
#define FREEBSD32_ALIGNBYTES (sizeof(long) - 1)
|
|
|
|
#endif
|
2005-10-31 21:09:56 +00:00
|
|
|
#define FREEBSD32_ALIGN(p) \
|
|
|
|
(((u_long)(p) + FREEBSD32_ALIGNBYTES) & ~FREEBSD32_ALIGNBYTES)
|
|
|
|
#define FREEBSD32_CMSG_SPACE(l) \
|
|
|
|
(FREEBSD32_ALIGN(sizeof(struct cmsghdr)) + FREEBSD32_ALIGN(l))
|
|
|
|
|
|
|
|
#define FREEBSD32_CMSG_DATA(cmsg) ((unsigned char *)(cmsg) + \
|
|
|
|
FREEBSD32_ALIGN(sizeof(struct cmsghdr)))
|
|
|
|
static int
|
|
|
|
freebsd32_copy_msg_out(struct msghdr *msg, struct mbuf *control)
|
|
|
|
{
|
|
|
|
struct cmsghdr *cm;
|
|
|
|
void *data;
|
|
|
|
socklen_t clen, datalen;
|
|
|
|
int error;
|
|
|
|
caddr_t ctlbuf;
|
|
|
|
int len, maxlen, copylen;
|
|
|
|
struct mbuf *m;
|
|
|
|
error = 0;
|
|
|
|
|
|
|
|
len = msg->msg_controllen;
|
|
|
|
maxlen = msg->msg_controllen;
|
|
|
|
msg->msg_controllen = 0;
|
|
|
|
|
|
|
|
m = control;
|
|
|
|
ctlbuf = msg->msg_control;
|
|
|
|
|
|
|
|
while (m && len > 0) {
|
|
|
|
cm = mtod(m, struct cmsghdr *);
|
|
|
|
clen = m->m_len;
|
|
|
|
|
|
|
|
while (cm != NULL) {
|
|
|
|
|
|
|
|
if (sizeof(struct cmsghdr) > clen ||
|
|
|
|
cm->cmsg_len > clen) {
|
|
|
|
error = EINVAL;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
data = CMSG_DATA(cm);
|
|
|
|
datalen = (caddr_t)cm + cm->cmsg_len - (caddr_t)data;
|
|
|
|
|
|
|
|
/* Adjust message length */
|
|
|
|
cm->cmsg_len = FREEBSD32_ALIGN(sizeof(struct cmsghdr)) +
|
|
|
|
datalen;
|
|
|
|
|
|
|
|
|
|
|
|
/* Copy cmsghdr */
|
|
|
|
copylen = sizeof(struct cmsghdr);
|
|
|
|
if (len < copylen) {
|
|
|
|
msg->msg_flags |= MSG_CTRUNC;
|
|
|
|
copylen = len;
|
|
|
|
}
|
|
|
|
|
|
|
|
error = copyout(cm,ctlbuf,copylen);
|
|
|
|
if (error)
|
|
|
|
goto exit;
|
|
|
|
|
|
|
|
ctlbuf += FREEBSD32_ALIGN(copylen);
|
|
|
|
len -= FREEBSD32_ALIGN(copylen);
|
|
|
|
|
|
|
|
if (len <= 0)
|
|
|
|
break;
|
|
|
|
|
|
|
|
/* Copy data */
|
|
|
|
copylen = datalen;
|
|
|
|
if (len < copylen) {
|
|
|
|
msg->msg_flags |= MSG_CTRUNC;
|
|
|
|
copylen = len;
|
|
|
|
}
|
|
|
|
|
|
|
|
error = copyout(data,ctlbuf,copylen);
|
|
|
|
if (error)
|
|
|
|
goto exit;
|
|
|
|
|
|
|
|
ctlbuf += FREEBSD32_ALIGN(copylen);
|
|
|
|
len -= FREEBSD32_ALIGN(copylen);
|
|
|
|
|
|
|
|
if (CMSG_SPACE(datalen) < clen) {
|
|
|
|
clen -= CMSG_SPACE(datalen);
|
|
|
|
cm = (struct cmsghdr *)
|
|
|
|
((caddr_t)cm + CMSG_SPACE(datalen));
|
|
|
|
} else {
|
|
|
|
clen = 0;
|
|
|
|
cm = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
m = m->m_next;
|
|
|
|
}
|
|
|
|
|
|
|
|
msg->msg_controllen = (len <= 0) ? maxlen : ctlbuf - (caddr_t)msg->msg_control;
|
|
|
|
|
|
|
|
exit:
|
|
|
|
return (error);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2005-10-15 05:57:06 +00:00
|
|
|
int
|
|
|
|
freebsd32_recvmsg(td, uap)
|
|
|
|
struct thread *td;
|
|
|
|
struct freebsd32_recvmsg_args /* {
|
|
|
|
int s;
|
|
|
|
struct msghdr32 *msg;
|
|
|
|
int flags;
|
|
|
|
} */ *uap;
|
|
|
|
{
|
|
|
|
struct msghdr msg;
|
|
|
|
struct msghdr32 m32;
|
|
|
|
struct iovec *uiov, *iov;
|
2005-10-31 21:09:56 +00:00
|
|
|
struct mbuf *control = NULL;
|
|
|
|
struct mbuf **controlp;
|
2005-10-15 05:57:06 +00:00
|
|
|
|
2005-10-31 21:09:56 +00:00
|
|
|
int error;
|
2005-10-15 05:57:06 +00:00
|
|
|
error = copyin(uap->msg, &m32, sizeof(m32));
|
|
|
|
if (error)
|
|
|
|
return (error);
|
|
|
|
error = freebsd32_copyinmsghdr(uap->msg, &msg);
|
|
|
|
if (error)
|
|
|
|
return (error);
|
2006-07-10 19:37:43 +00:00
|
|
|
error = freebsd32_copyiniov(PTRIN(m32.msg_iov), m32.msg_iovlen, &iov,
|
|
|
|
EMSGSIZE);
|
2005-10-15 05:57:06 +00:00
|
|
|
if (error)
|
|
|
|
return (error);
|
|
|
|
msg.msg_flags = uap->flags;
|
|
|
|
uiov = msg.msg_iov;
|
|
|
|
msg.msg_iov = iov;
|
2005-10-31 21:09:56 +00:00
|
|
|
|
|
|
|
controlp = (msg.msg_control != NULL) ? &control : NULL;
|
2006-07-10 21:38:17 +00:00
|
|
|
error = kern_recvit(td, uap->s, &msg, UIO_USERSPACE, controlp);
|
2005-10-15 05:57:06 +00:00
|
|
|
if (error == 0) {
|
|
|
|
msg.msg_iov = uiov;
|
2005-10-31 21:09:56 +00:00
|
|
|
|
|
|
|
if (control != NULL)
|
|
|
|
error = freebsd32_copy_msg_out(&msg, control);
|
2010-08-03 11:23:44 +00:00
|
|
|
else
|
|
|
|
msg.msg_controllen = 0;
|
2005-10-31 21:09:56 +00:00
|
|
|
|
|
|
|
if (error == 0)
|
|
|
|
error = freebsd32_copyoutmsghdr(&msg, uap->msg);
|
2005-10-15 05:57:06 +00:00
|
|
|
}
|
|
|
|
free(iov, M_IOV);
|
2005-10-31 21:09:56 +00:00
|
|
|
|
|
|
|
if (control != NULL)
|
|
|
|
m_freem(control);
|
|
|
|
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
freebsd32_convert_msg_in(struct mbuf **controlp)
|
|
|
|
{
|
|
|
|
struct mbuf *control = *controlp;
|
|
|
|
struct cmsghdr *cm = mtod(control, struct cmsghdr *);
|
|
|
|
void *data;
|
|
|
|
socklen_t clen = control->m_len, datalen;
|
|
|
|
int error;
|
|
|
|
|
|
|
|
error = 0;
|
|
|
|
*controlp = NULL;
|
|
|
|
|
|
|
|
while (cm != NULL) {
|
|
|
|
if (sizeof(struct cmsghdr) > clen || cm->cmsg_len > clen) {
|
|
|
|
error = EINVAL;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
data = FREEBSD32_CMSG_DATA(cm);
|
|
|
|
datalen = (caddr_t)cm + cm->cmsg_len - (caddr_t)data;
|
|
|
|
|
|
|
|
*controlp = sbcreatecontrol(data, datalen, cm->cmsg_type,
|
|
|
|
cm->cmsg_level);
|
|
|
|
controlp = &(*controlp)->m_next;
|
|
|
|
|
|
|
|
if (FREEBSD32_CMSG_SPACE(datalen) < clen) {
|
|
|
|
clen -= FREEBSD32_CMSG_SPACE(datalen);
|
|
|
|
cm = (struct cmsghdr *)
|
|
|
|
((caddr_t)cm + FREEBSD32_CMSG_SPACE(datalen));
|
|
|
|
} else {
|
|
|
|
clen = 0;
|
|
|
|
cm = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
m_freem(control);
|
2005-10-15 05:57:06 +00:00
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
2005-10-31 21:09:56 +00:00
|
|
|
|
2005-10-15 05:57:06 +00:00
|
|
|
int
|
|
|
|
freebsd32_sendmsg(struct thread *td,
|
|
|
|
struct freebsd32_sendmsg_args *uap)
|
|
|
|
{
|
|
|
|
struct msghdr msg;
|
|
|
|
struct msghdr32 m32;
|
|
|
|
struct iovec *iov;
|
2005-10-31 21:09:56 +00:00
|
|
|
struct mbuf *control = NULL;
|
|
|
|
struct sockaddr *to = NULL;
|
2005-10-15 05:57:06 +00:00
|
|
|
int error;
|
|
|
|
|
|
|
|
error = copyin(uap->msg, &m32, sizeof(m32));
|
|
|
|
if (error)
|
|
|
|
return (error);
|
|
|
|
error = freebsd32_copyinmsghdr(uap->msg, &msg);
|
|
|
|
if (error)
|
|
|
|
return (error);
|
2006-07-10 19:37:43 +00:00
|
|
|
error = freebsd32_copyiniov(PTRIN(m32.msg_iov), m32.msg_iovlen, &iov,
|
|
|
|
EMSGSIZE);
|
2005-10-15 05:57:06 +00:00
|
|
|
if (error)
|
|
|
|
return (error);
|
|
|
|
msg.msg_iov = iov;
|
2005-10-31 21:09:56 +00:00
|
|
|
if (msg.msg_name != NULL) {
|
|
|
|
error = getsockaddr(&to, msg.msg_name, msg.msg_namelen);
|
|
|
|
if (error) {
|
|
|
|
to = NULL;
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
msg.msg_name = to;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (msg.msg_control) {
|
|
|
|
if (msg.msg_controllen < sizeof(struct cmsghdr)) {
|
|
|
|
error = EINVAL;
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
error = sockargs(&control, msg.msg_control,
|
|
|
|
msg.msg_controllen, MT_CONTROL);
|
|
|
|
if (error)
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
error = freebsd32_convert_msg_in(&control);
|
|
|
|
if (error)
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
error = kern_sendit(td, uap->s, &msg, uap->flags, control,
|
|
|
|
UIO_USERSPACE);
|
|
|
|
|
|
|
|
out:
|
2005-10-15 05:57:06 +00:00
|
|
|
free(iov, M_IOV);
|
2005-10-31 21:09:56 +00:00
|
|
|
if (to)
|
|
|
|
free(to, M_SONAME);
|
2005-10-15 05:57:06 +00:00
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
freebsd32_recvfrom(struct thread *td,
|
|
|
|
struct freebsd32_recvfrom_args *uap)
|
|
|
|
{
|
|
|
|
struct msghdr msg;
|
|
|
|
struct iovec aiov;
|
|
|
|
int error;
|
|
|
|
|
|
|
|
if (uap->fromlenaddr) {
|
2006-07-10 19:37:43 +00:00
|
|
|
error = copyin(PTRIN(uap->fromlenaddr), &msg.msg_namelen,
|
|
|
|
sizeof(msg.msg_namelen));
|
2005-10-15 05:57:06 +00:00
|
|
|
if (error)
|
|
|
|
return (error);
|
|
|
|
} else {
|
|
|
|
msg.msg_namelen = 0;
|
|
|
|
}
|
|
|
|
|
2006-07-10 19:37:43 +00:00
|
|
|
msg.msg_name = PTRIN(uap->from);
|
2005-10-15 05:57:06 +00:00
|
|
|
msg.msg_iov = &aiov;
|
|
|
|
msg.msg_iovlen = 1;
|
2006-07-10 19:37:43 +00:00
|
|
|
aiov.iov_base = PTRIN(uap->buf);
|
2005-10-15 05:57:06 +00:00
|
|
|
aiov.iov_len = uap->len;
|
2006-07-10 19:37:43 +00:00
|
|
|
msg.msg_control = NULL;
|
2005-10-15 05:57:06 +00:00
|
|
|
msg.msg_flags = uap->flags;
|
2006-07-10 21:38:17 +00:00
|
|
|
error = kern_recvit(td, uap->s, &msg, UIO_USERSPACE, NULL);
|
|
|
|
if (error == 0 && uap->fromlenaddr)
|
|
|
|
error = copyout(&msg.msg_namelen, PTRIN(uap->fromlenaddr),
|
|
|
|
sizeof (msg.msg_namelen));
|
2005-10-15 05:57:06 +00:00
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
2002-07-20 02:56:12 +00:00
|
|
|
int
|
2003-08-22 23:07:28 +00:00
|
|
|
freebsd32_settimeofday(struct thread *td,
|
|
|
|
struct freebsd32_settimeofday_args *uap)
|
2002-07-20 02:56:12 +00:00
|
|
|
{
|
2005-03-31 22:58:13 +00:00
|
|
|
struct timeval32 tv32;
|
|
|
|
struct timeval tv, *tvp;
|
|
|
|
struct timezone tz, *tzp;
|
2002-07-20 02:56:12 +00:00
|
|
|
int error;
|
|
|
|
|
2005-03-31 22:58:13 +00:00
|
|
|
if (uap->tv) {
|
|
|
|
error = copyin(uap->tv, &tv32, sizeof(tv32));
|
2002-07-20 02:56:12 +00:00
|
|
|
if (error)
|
|
|
|
return (error);
|
2005-03-31 22:58:13 +00:00
|
|
|
CP(tv32, tv, tv_sec);
|
|
|
|
CP(tv32, tv, tv_usec);
|
|
|
|
tvp = &tv;
|
|
|
|
} else
|
|
|
|
tvp = NULL;
|
|
|
|
if (uap->tzp) {
|
|
|
|
error = copyin(uap->tzp, &tz, sizeof(tz));
|
2002-07-20 02:56:12 +00:00
|
|
|
if (error)
|
|
|
|
return (error);
|
2005-03-31 22:58:13 +00:00
|
|
|
tzp = &tz;
|
|
|
|
} else
|
|
|
|
tzp = NULL;
|
|
|
|
return (kern_settimeofday(td, tvp, tzp));
|
2002-07-20 02:56:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2003-08-22 23:07:28 +00:00
|
|
|
freebsd32_utimes(struct thread *td, struct freebsd32_utimes_args *uap)
|
2002-07-20 02:56:12 +00:00
|
|
|
{
|
- Add a custom version of exec_copyin_args() to deal with the 32-bit
pointers in argv and envv in userland and use that together with
kern_execve() and exec_free_args() to implement freebsd32_execve()
without using the stackgap.
- Fix freebsd32_adjtime() to call adjtime() rather than utimes(). Still
uses stackgap for now.
- Use kern_setitimer(), kern_getitimer(), kern_select(), kern_utimes(),
kern_statfs(), kern_fstatfs(), kern_fhstatfs(), kern_stat(),
kern_fstat(), and kern_lstat().
Tested by: cokane (amd64)
Silence on: amd64, ia64
2005-02-18 18:56:04 +00:00
|
|
|
struct timeval32 s32[2];
|
|
|
|
struct timeval s[2], *sp;
|
2002-07-20 02:56:12 +00:00
|
|
|
int error;
|
|
|
|
|
- Add a custom version of exec_copyin_args() to deal with the 32-bit
pointers in argv and envv in userland and use that together with
kern_execve() and exec_free_args() to implement freebsd32_execve()
without using the stackgap.
- Fix freebsd32_adjtime() to call adjtime() rather than utimes(). Still
uses stackgap for now.
- Use kern_setitimer(), kern_getitimer(), kern_select(), kern_utimes(),
kern_statfs(), kern_fstatfs(), kern_fhstatfs(), kern_stat(),
kern_fstat(), and kern_lstat().
Tested by: cokane (amd64)
Silence on: amd64, ia64
2005-02-18 18:56:04 +00:00
|
|
|
if (uap->tptr != NULL) {
|
|
|
|
error = copyin(uap->tptr, s32, sizeof(s32));
|
2002-07-20 02:56:12 +00:00
|
|
|
if (error)
|
|
|
|
return (error);
|
|
|
|
CP(s32[0], s[0], tv_sec);
|
|
|
|
CP(s32[0], s[0], tv_usec);
|
|
|
|
CP(s32[1], s[1], tv_sec);
|
|
|
|
CP(s32[1], s[1], tv_usec);
|
- Add a custom version of exec_copyin_args() to deal with the 32-bit
pointers in argv and envv in userland and use that together with
kern_execve() and exec_free_args() to implement freebsd32_execve()
without using the stackgap.
- Fix freebsd32_adjtime() to call adjtime() rather than utimes(). Still
uses stackgap for now.
- Use kern_setitimer(), kern_getitimer(), kern_select(), kern_utimes(),
kern_statfs(), kern_fstatfs(), kern_fhstatfs(), kern_stat(),
kern_fstat(), and kern_lstat().
Tested by: cokane (amd64)
Silence on: amd64, ia64
2005-02-18 18:56:04 +00:00
|
|
|
sp = s;
|
|
|
|
} else
|
|
|
|
sp = NULL;
|
|
|
|
return (kern_utimes(td, uap->path, UIO_USERSPACE, sp, UIO_SYSSPACE));
|
2006-01-20 16:22:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
freebsd32_lutimes(struct thread *td, struct freebsd32_lutimes_args *uap)
|
|
|
|
{
|
|
|
|
struct timeval32 s32[2];
|
|
|
|
struct timeval s[2], *sp;
|
|
|
|
int error;
|
|
|
|
|
|
|
|
if (uap->tptr != NULL) {
|
|
|
|
error = copyin(uap->tptr, s32, sizeof(s32));
|
|
|
|
if (error)
|
|
|
|
return (error);
|
|
|
|
CP(s32[0], s[0], tv_sec);
|
|
|
|
CP(s32[0], s[0], tv_usec);
|
|
|
|
CP(s32[1], s[1], tv_sec);
|
|
|
|
CP(s32[1], s[1], tv_usec);
|
|
|
|
sp = s;
|
|
|
|
} else
|
|
|
|
sp = NULL;
|
|
|
|
return (kern_lutimes(td, uap->path, UIO_USERSPACE, sp, UIO_SYSSPACE));
|
2002-07-20 02:56:12 +00:00
|
|
|
}
|
|
|
|
|
2005-12-08 22:14:25 +00:00
|
|
|
int
|
|
|
|
freebsd32_futimes(struct thread *td, struct freebsd32_futimes_args *uap)
|
|
|
|
{
|
|
|
|
struct timeval32 s32[2];
|
|
|
|
struct timeval s[2], *sp;
|
|
|
|
int error;
|
|
|
|
|
|
|
|
if (uap->tptr != NULL) {
|
|
|
|
error = copyin(uap->tptr, s32, sizeof(s32));
|
|
|
|
if (error)
|
|
|
|
return (error);
|
|
|
|
CP(s32[0], s[0], tv_sec);
|
|
|
|
CP(s32[0], s[0], tv_usec);
|
|
|
|
CP(s32[1], s[1], tv_sec);
|
|
|
|
CP(s32[1], s[1], tv_usec);
|
|
|
|
sp = s;
|
|
|
|
} else
|
|
|
|
sp = NULL;
|
|
|
|
return (kern_futimes(td, uap->fd, sp, UIO_SYSSPACE));
|
|
|
|
}
|
|
|
|
|
2008-03-31 12:08:30 +00:00
|
|
|
int
|
|
|
|
freebsd32_futimesat(struct thread *td, struct freebsd32_futimesat_args *uap)
|
|
|
|
{
|
|
|
|
struct timeval32 s32[2];
|
|
|
|
struct timeval s[2], *sp;
|
|
|
|
int error;
|
|
|
|
|
|
|
|
if (uap->times != NULL) {
|
|
|
|
error = copyin(uap->times, s32, sizeof(s32));
|
|
|
|
if (error)
|
|
|
|
return (error);
|
|
|
|
CP(s32[0], s[0], tv_sec);
|
|
|
|
CP(s32[0], s[0], tv_usec);
|
|
|
|
CP(s32[1], s[1], tv_sec);
|
|
|
|
CP(s32[1], s[1], tv_usec);
|
|
|
|
sp = s;
|
|
|
|
} else
|
|
|
|
sp = NULL;
|
|
|
|
return (kern_utimesat(td, uap->fd, uap->path, UIO_USERSPACE,
|
|
|
|
sp, UIO_SYSSPACE));
|
|
|
|
}
|
2005-12-08 22:14:25 +00:00
|
|
|
|
2002-07-20 02:56:12 +00:00
|
|
|
int
|
2003-08-22 23:07:28 +00:00
|
|
|
freebsd32_adjtime(struct thread *td, struct freebsd32_adjtime_args *uap)
|
2002-07-20 02:56:12 +00:00
|
|
|
{
|
2005-03-31 22:58:13 +00:00
|
|
|
struct timeval32 tv32;
|
|
|
|
struct timeval delta, olddelta, *deltap;
|
2002-07-20 02:56:12 +00:00
|
|
|
int error;
|
|
|
|
|
2005-03-31 22:58:13 +00:00
|
|
|
if (uap->delta) {
|
|
|
|
error = copyin(uap->delta, &tv32, sizeof(tv32));
|
2002-07-20 02:56:12 +00:00
|
|
|
if (error)
|
|
|
|
return (error);
|
2005-03-31 22:58:13 +00:00
|
|
|
CP(tv32, delta, tv_sec);
|
|
|
|
CP(tv32, delta, tv_usec);
|
|
|
|
deltap = δ
|
|
|
|
} else
|
|
|
|
deltap = NULL;
|
|
|
|
error = kern_adjtime(td, deltap, &olddelta);
|
|
|
|
if (uap->olddelta && error == 0) {
|
|
|
|
CP(olddelta, tv32, tv_sec);
|
|
|
|
CP(olddelta, tv32, tv_usec);
|
|
|
|
error = copyout(&tv32, uap->olddelta, sizeof(tv32));
|
2002-07-20 02:56:12 +00:00
|
|
|
}
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
2004-04-24 04:31:59 +00:00
|
|
|
#ifdef COMPAT_FREEBSD4
|
2002-07-20 02:56:12 +00:00
|
|
|
int
|
2004-04-14 23:17:37 +00:00
|
|
|
freebsd4_freebsd32_statfs(struct thread *td, struct freebsd4_freebsd32_statfs_args *uap)
|
2002-07-20 02:56:12 +00:00
|
|
|
{
|
- Add a custom version of exec_copyin_args() to deal with the 32-bit
pointers in argv and envv in userland and use that together with
kern_execve() and exec_free_args() to implement freebsd32_execve()
without using the stackgap.
- Fix freebsd32_adjtime() to call adjtime() rather than utimes(). Still
uses stackgap for now.
- Use kern_setitimer(), kern_getitimer(), kern_select(), kern_utimes(),
kern_statfs(), kern_fstatfs(), kern_fhstatfs(), kern_stat(),
kern_fstat(), and kern_lstat().
Tested by: cokane (amd64)
Silence on: amd64, ia64
2005-02-18 18:56:04 +00:00
|
|
|
struct statfs32 s32;
|
|
|
|
struct statfs s;
|
2002-07-20 02:56:12 +00:00
|
|
|
int error;
|
|
|
|
|
- Add a custom version of exec_copyin_args() to deal with the 32-bit
pointers in argv and envv in userland and use that together with
kern_execve() and exec_free_args() to implement freebsd32_execve()
without using the stackgap.
- Fix freebsd32_adjtime() to call adjtime() rather than utimes(). Still
uses stackgap for now.
- Use kern_setitimer(), kern_getitimer(), kern_select(), kern_utimes(),
kern_statfs(), kern_fstatfs(), kern_fhstatfs(), kern_stat(),
kern_fstat(), and kern_lstat().
Tested by: cokane (amd64)
Silence on: amd64, ia64
2005-02-18 18:56:04 +00:00
|
|
|
error = kern_statfs(td, uap->path, UIO_USERSPACE, &s);
|
2002-07-20 02:56:12 +00:00
|
|
|
if (error)
|
|
|
|
return (error);
|
2007-12-10 19:42:23 +00:00
|
|
|
copy_statfs(&s, &s32);
|
- Add a custom version of exec_copyin_args() to deal with the 32-bit
pointers in argv and envv in userland and use that together with
kern_execve() and exec_free_args() to implement freebsd32_execve()
without using the stackgap.
- Fix freebsd32_adjtime() to call adjtime() rather than utimes(). Still
uses stackgap for now.
- Use kern_setitimer(), kern_getitimer(), kern_select(), kern_utimes(),
kern_statfs(), kern_fstatfs(), kern_fhstatfs(), kern_stat(),
kern_fstat(), and kern_lstat().
Tested by: cokane (amd64)
Silence on: amd64, ia64
2005-02-18 18:56:04 +00:00
|
|
|
return (copyout(&s32, uap->buf, sizeof(s32)));
|
2002-07-20 02:56:12 +00:00
|
|
|
}
|
2004-04-24 04:31:59 +00:00
|
|
|
#endif
|
2002-07-20 02:56:12 +00:00
|
|
|
|
2004-04-24 04:31:59 +00:00
|
|
|
#ifdef COMPAT_FREEBSD4
|
2002-07-20 02:56:12 +00:00
|
|
|
int
|
2004-04-14 23:17:37 +00:00
|
|
|
freebsd4_freebsd32_fstatfs(struct thread *td, struct freebsd4_freebsd32_fstatfs_args *uap)
|
2002-07-20 02:56:12 +00:00
|
|
|
{
|
- Add a custom version of exec_copyin_args() to deal with the 32-bit
pointers in argv and envv in userland and use that together with
kern_execve() and exec_free_args() to implement freebsd32_execve()
without using the stackgap.
- Fix freebsd32_adjtime() to call adjtime() rather than utimes(). Still
uses stackgap for now.
- Use kern_setitimer(), kern_getitimer(), kern_select(), kern_utimes(),
kern_statfs(), kern_fstatfs(), kern_fhstatfs(), kern_stat(),
kern_fstat(), and kern_lstat().
Tested by: cokane (amd64)
Silence on: amd64, ia64
2005-02-18 18:56:04 +00:00
|
|
|
struct statfs32 s32;
|
|
|
|
struct statfs s;
|
2002-07-20 02:56:12 +00:00
|
|
|
int error;
|
|
|
|
|
- Add a custom version of exec_copyin_args() to deal with the 32-bit
pointers in argv and envv in userland and use that together with
kern_execve() and exec_free_args() to implement freebsd32_execve()
without using the stackgap.
- Fix freebsd32_adjtime() to call adjtime() rather than utimes(). Still
uses stackgap for now.
- Use kern_setitimer(), kern_getitimer(), kern_select(), kern_utimes(),
kern_statfs(), kern_fstatfs(), kern_fhstatfs(), kern_stat(),
kern_fstat(), and kern_lstat().
Tested by: cokane (amd64)
Silence on: amd64, ia64
2005-02-18 18:56:04 +00:00
|
|
|
error = kern_fstatfs(td, uap->fd, &s);
|
2002-07-20 02:56:12 +00:00
|
|
|
if (error)
|
|
|
|
return (error);
|
2007-12-10 19:42:23 +00:00
|
|
|
copy_statfs(&s, &s32);
|
- Add a custom version of exec_copyin_args() to deal with the 32-bit
pointers in argv and envv in userland and use that together with
kern_execve() and exec_free_args() to implement freebsd32_execve()
without using the stackgap.
- Fix freebsd32_adjtime() to call adjtime() rather than utimes(). Still
uses stackgap for now.
- Use kern_setitimer(), kern_getitimer(), kern_select(), kern_utimes(),
kern_statfs(), kern_fstatfs(), kern_fhstatfs(), kern_stat(),
kern_fstat(), and kern_lstat().
Tested by: cokane (amd64)
Silence on: amd64, ia64
2005-02-18 18:56:04 +00:00
|
|
|
return (copyout(&s32, uap->buf, sizeof(s32)));
|
2004-04-14 23:17:37 +00:00
|
|
|
}
|
2004-04-24 04:31:59 +00:00
|
|
|
#endif
|
2004-04-14 23:17:37 +00:00
|
|
|
|
2004-04-24 04:31:59 +00:00
|
|
|
#ifdef COMPAT_FREEBSD4
|
2004-04-14 23:17:37 +00:00
|
|
|
int
|
|
|
|
freebsd4_freebsd32_fhstatfs(struct thread *td, struct freebsd4_freebsd32_fhstatfs_args *uap)
|
|
|
|
{
|
- Add a custom version of exec_copyin_args() to deal with the 32-bit
pointers in argv and envv in userland and use that together with
kern_execve() and exec_free_args() to implement freebsd32_execve()
without using the stackgap.
- Fix freebsd32_adjtime() to call adjtime() rather than utimes(). Still
uses stackgap for now.
- Use kern_setitimer(), kern_getitimer(), kern_select(), kern_utimes(),
kern_statfs(), kern_fstatfs(), kern_fhstatfs(), kern_stat(),
kern_fstat(), and kern_lstat().
Tested by: cokane (amd64)
Silence on: amd64, ia64
2005-02-18 18:56:04 +00:00
|
|
|
struct statfs32 s32;
|
|
|
|
struct statfs s;
|
|
|
|
fhandle_t fh;
|
2004-04-14 23:17:37 +00:00
|
|
|
int error;
|
|
|
|
|
- Add a custom version of exec_copyin_args() to deal with the 32-bit
pointers in argv and envv in userland and use that together with
kern_execve() and exec_free_args() to implement freebsd32_execve()
without using the stackgap.
- Fix freebsd32_adjtime() to call adjtime() rather than utimes(). Still
uses stackgap for now.
- Use kern_setitimer(), kern_getitimer(), kern_select(), kern_utimes(),
kern_statfs(), kern_fstatfs(), kern_fhstatfs(), kern_stat(),
kern_fstat(), and kern_lstat().
Tested by: cokane (amd64)
Silence on: amd64, ia64
2005-02-18 18:56:04 +00:00
|
|
|
if ((error = copyin(uap->u_fhp, &fh, sizeof(fhandle_t))) != 0)
|
|
|
|
return (error);
|
|
|
|
error = kern_fhstatfs(td, fh, &s);
|
2004-04-14 23:17:37 +00:00
|
|
|
if (error)
|
|
|
|
return (error);
|
2007-12-10 19:42:23 +00:00
|
|
|
copy_statfs(&s, &s32);
|
- Add a custom version of exec_copyin_args() to deal with the 32-bit
pointers in argv and envv in userland and use that together with
kern_execve() and exec_free_args() to implement freebsd32_execve()
without using the stackgap.
- Fix freebsd32_adjtime() to call adjtime() rather than utimes(). Still
uses stackgap for now.
- Use kern_setitimer(), kern_getitimer(), kern_select(), kern_utimes(),
kern_statfs(), kern_fstatfs(), kern_fhstatfs(), kern_stat(),
kern_fstat(), and kern_lstat().
Tested by: cokane (amd64)
Silence on: amd64, ia64
2005-02-18 18:56:04 +00:00
|
|
|
return (copyout(&s32, uap->buf, sizeof(s32)));
|
2002-07-20 02:56:12 +00:00
|
|
|
}
|
2004-04-24 04:31:59 +00:00
|
|
|
#endif
|
2002-07-20 02:56:12 +00:00
|
|
|
|
|
|
|
int
|
2003-08-22 23:07:28 +00:00
|
|
|
freebsd32_pread(struct thread *td, struct freebsd32_pread_args *uap)
|
2002-07-20 02:56:12 +00:00
|
|
|
{
|
|
|
|
struct pread_args ap;
|
|
|
|
|
2002-12-14 01:56:26 +00:00
|
|
|
ap.fd = uap->fd;
|
|
|
|
ap.buf = uap->buf;
|
|
|
|
ap.nbyte = uap->nbyte;
|
2010-03-11 14:49:06 +00:00
|
|
|
ap.offset = PAIR32TO64(off_t,uap->offset);
|
2011-09-16 13:58:51 +00:00
|
|
|
return (sys_pread(td, &ap));
|
2002-07-20 02:56:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2003-08-22 23:07:28 +00:00
|
|
|
freebsd32_pwrite(struct thread *td, struct freebsd32_pwrite_args *uap)
|
2002-07-20 02:56:12 +00:00
|
|
|
{
|
|
|
|
struct pwrite_args ap;
|
|
|
|
|
2002-12-14 01:56:26 +00:00
|
|
|
ap.fd = uap->fd;
|
|
|
|
ap.buf = uap->buf;
|
|
|
|
ap.nbyte = uap->nbyte;
|
2010-03-11 14:49:06 +00:00
|
|
|
ap.offset = PAIR32TO64(off_t,uap->offset);
|
2011-09-16 13:58:51 +00:00
|
|
|
return (sys_pwrite(td, &ap));
|
2002-07-20 02:56:12 +00:00
|
|
|
}
|
|
|
|
|
2011-06-16 22:05:56 +00:00
|
|
|
#ifdef COMPAT_43
|
|
|
|
int
|
|
|
|
ofreebsd32_lseek(struct thread *td, struct ofreebsd32_lseek_args *uap)
|
|
|
|
{
|
|
|
|
struct lseek_args nuap;
|
|
|
|
|
|
|
|
nuap.fd = uap->fd;
|
|
|
|
nuap.offset = uap->offset;
|
|
|
|
nuap.whence = uap->whence;
|
2011-09-16 13:58:51 +00:00
|
|
|
return (sys_lseek(td, &nuap));
|
2011-06-16 22:05:56 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2002-07-20 02:56:12 +00:00
|
|
|
int
|
2003-08-22 23:07:28 +00:00
|
|
|
freebsd32_lseek(struct thread *td, struct freebsd32_lseek_args *uap)
|
2002-07-20 02:56:12 +00:00
|
|
|
{
|
|
|
|
int error;
|
|
|
|
struct lseek_args ap;
|
|
|
|
off_t pos;
|
|
|
|
|
2002-12-14 01:56:26 +00:00
|
|
|
ap.fd = uap->fd;
|
2010-03-11 14:49:06 +00:00
|
|
|
ap.offset = PAIR32TO64(off_t,uap->offset);
|
2002-12-14 01:56:26 +00:00
|
|
|
ap.whence = uap->whence;
|
2011-09-16 13:58:51 +00:00
|
|
|
error = sys_lseek(td, &ap);
|
2002-07-20 02:56:12 +00:00
|
|
|
/* Expand the quad return into two parts for eax and edx */
|
|
|
|
pos = *(off_t *)(td->td_retval);
|
2010-03-11 14:49:06 +00:00
|
|
|
td->td_retval[RETVAL_LO] = pos & 0xffffffff; /* %eax */
|
|
|
|
td->td_retval[RETVAL_HI] = pos >> 32; /* %edx */
|
2002-07-20 02:56:12 +00:00
|
|
|
return error;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2003-08-22 23:07:28 +00:00
|
|
|
freebsd32_truncate(struct thread *td, struct freebsd32_truncate_args *uap)
|
2002-07-20 02:56:12 +00:00
|
|
|
{
|
|
|
|
struct truncate_args ap;
|
|
|
|
|
2002-12-14 01:56:26 +00:00
|
|
|
ap.path = uap->path;
|
2010-03-11 14:49:06 +00:00
|
|
|
ap.length = PAIR32TO64(off_t,uap->length);
|
2011-09-16 13:58:51 +00:00
|
|
|
return (sys_truncate(td, &ap));
|
2002-07-20 02:56:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2003-08-22 23:07:28 +00:00
|
|
|
freebsd32_ftruncate(struct thread *td, struct freebsd32_ftruncate_args *uap)
|
2002-07-20 02:56:12 +00:00
|
|
|
{
|
|
|
|
struct ftruncate_args ap;
|
|
|
|
|
2002-12-14 01:56:26 +00:00
|
|
|
ap.fd = uap->fd;
|
2010-03-11 14:49:06 +00:00
|
|
|
ap.length = PAIR32TO64(off_t,uap->length);
|
2011-09-16 13:58:51 +00:00
|
|
|
return (sys_ftruncate(td, &ap));
|
2002-07-20 02:56:12 +00:00
|
|
|
}
|
|
|
|
|
2011-04-01 11:16:29 +00:00
|
|
|
#ifdef COMPAT_43
|
|
|
|
int
|
|
|
|
ofreebsd32_getdirentries(struct thread *td,
|
|
|
|
struct ofreebsd32_getdirentries_args *uap)
|
|
|
|
{
|
|
|
|
struct ogetdirentries_args ap;
|
|
|
|
int error;
|
|
|
|
long loff;
|
|
|
|
int32_t loff_cut;
|
|
|
|
|
|
|
|
ap.fd = uap->fd;
|
|
|
|
ap.buf = uap->buf;
|
|
|
|
ap.count = uap->count;
|
|
|
|
ap.basep = NULL;
|
|
|
|
error = kern_ogetdirentries(td, &ap, &loff);
|
|
|
|
if (error == 0) {
|
|
|
|
loff_cut = loff;
|
|
|
|
error = copyout(&loff_cut, uap->basep, sizeof(int32_t));
|
|
|
|
}
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2008-10-22 21:55:48 +00:00
|
|
|
int
|
|
|
|
freebsd32_getdirentries(struct thread *td,
|
|
|
|
struct freebsd32_getdirentries_args *uap)
|
|
|
|
{
|
|
|
|
long base;
|
|
|
|
int32_t base32;
|
|
|
|
int error;
|
|
|
|
|
2012-05-24 08:00:26 +00:00
|
|
|
error = kern_getdirentries(td, uap->fd, uap->buf, uap->count, &base,
|
|
|
|
NULL, UIO_USERSPACE);
|
2008-10-22 21:55:48 +00:00
|
|
|
if (error)
|
|
|
|
return (error);
|
|
|
|
if (uap->basep != NULL) {
|
|
|
|
base32 = base;
|
|
|
|
error = copyout(&base32, uap->basep, sizeof(int32_t));
|
|
|
|
}
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
2007-07-04 23:04:41 +00:00
|
|
|
#ifdef COMPAT_FREEBSD6
|
|
|
|
/* versions with the 'int pad' argument */
|
|
|
|
int
|
|
|
|
freebsd6_freebsd32_pread(struct thread *td, struct freebsd6_freebsd32_pread_args *uap)
|
|
|
|
{
|
|
|
|
struct pread_args ap;
|
|
|
|
|
|
|
|
ap.fd = uap->fd;
|
|
|
|
ap.buf = uap->buf;
|
|
|
|
ap.nbyte = uap->nbyte;
|
2010-03-11 14:49:06 +00:00
|
|
|
ap.offset = PAIR32TO64(off_t,uap->offset);
|
2011-09-16 13:58:51 +00:00
|
|
|
return (sys_pread(td, &ap));
|
2007-07-04 23:04:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
freebsd6_freebsd32_pwrite(struct thread *td, struct freebsd6_freebsd32_pwrite_args *uap)
|
|
|
|
{
|
|
|
|
struct pwrite_args ap;
|
|
|
|
|
|
|
|
ap.fd = uap->fd;
|
|
|
|
ap.buf = uap->buf;
|
|
|
|
ap.nbyte = uap->nbyte;
|
2010-03-11 14:49:06 +00:00
|
|
|
ap.offset = PAIR32TO64(off_t,uap->offset);
|
2011-09-16 13:58:51 +00:00
|
|
|
return (sys_pwrite(td, &ap));
|
2007-07-04 23:04:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
freebsd6_freebsd32_lseek(struct thread *td, struct freebsd6_freebsd32_lseek_args *uap)
|
|
|
|
{
|
|
|
|
int error;
|
|
|
|
struct lseek_args ap;
|
|
|
|
off_t pos;
|
|
|
|
|
|
|
|
ap.fd = uap->fd;
|
2010-03-11 14:49:06 +00:00
|
|
|
ap.offset = PAIR32TO64(off_t,uap->offset);
|
2007-07-04 23:04:41 +00:00
|
|
|
ap.whence = uap->whence;
|
2011-09-16 13:58:51 +00:00
|
|
|
error = sys_lseek(td, &ap);
|
2007-07-04 23:04:41 +00:00
|
|
|
/* Expand the quad return into two parts for eax and edx */
|
|
|
|
pos = *(off_t *)(td->td_retval);
|
2010-03-11 14:49:06 +00:00
|
|
|
td->td_retval[RETVAL_LO] = pos & 0xffffffff; /* %eax */
|
|
|
|
td->td_retval[RETVAL_HI] = pos >> 32; /* %edx */
|
2007-07-04 23:04:41 +00:00
|
|
|
return error;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
freebsd6_freebsd32_truncate(struct thread *td, struct freebsd6_freebsd32_truncate_args *uap)
|
|
|
|
{
|
|
|
|
struct truncate_args ap;
|
|
|
|
|
|
|
|
ap.path = uap->path;
|
2010-03-11 14:49:06 +00:00
|
|
|
ap.length = PAIR32TO64(off_t,uap->length);
|
2011-09-16 13:58:51 +00:00
|
|
|
return (sys_truncate(td, &ap));
|
2007-07-04 23:04:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
freebsd6_freebsd32_ftruncate(struct thread *td, struct freebsd6_freebsd32_ftruncate_args *uap)
|
|
|
|
{
|
|
|
|
struct ftruncate_args ap;
|
|
|
|
|
|
|
|
ap.fd = uap->fd;
|
2010-03-11 14:49:06 +00:00
|
|
|
ap.length = PAIR32TO64(off_t,uap->length);
|
2011-09-16 13:58:51 +00:00
|
|
|
return (sys_ftruncate(td, &ap));
|
2007-07-04 23:04:41 +00:00
|
|
|
}
|
|
|
|
#endif /* COMPAT_FREEBSD6 */
|
|
|
|
|
2006-02-28 19:39:18 +00:00
|
|
|
struct sf_hdtr32 {
|
|
|
|
uint32_t headers;
|
|
|
|
int hdr_cnt;
|
|
|
|
uint32_t trailers;
|
|
|
|
int trl_cnt;
|
|
|
|
};
|
|
|
|
|
|
|
|
static int
|
|
|
|
freebsd32_do_sendfile(struct thread *td,
|
|
|
|
struct freebsd32_sendfile_args *uap, int compat)
|
2002-10-09 22:27:24 +00:00
|
|
|
{
|
2006-02-28 19:39:18 +00:00
|
|
|
struct sendfile_args ap;
|
|
|
|
struct sf_hdtr32 hdtr32;
|
|
|
|
struct sf_hdtr hdtr;
|
|
|
|
struct uio *hdr_uio, *trl_uio;
|
|
|
|
struct iovec32 *iov32;
|
|
|
|
int error;
|
|
|
|
|
|
|
|
hdr_uio = trl_uio = NULL;
|
2002-10-09 22:27:24 +00:00
|
|
|
|
2002-12-14 01:56:26 +00:00
|
|
|
ap.fd = uap->fd;
|
|
|
|
ap.s = uap->s;
|
2010-03-11 14:49:06 +00:00
|
|
|
ap.offset = PAIR32TO64(off_t,uap->offset);
|
2006-02-28 19:39:18 +00:00
|
|
|
ap.nbytes = uap->nbytes;
|
|
|
|
ap.hdtr = (struct sf_hdtr *)uap->hdtr; /* XXX not used */
|
|
|
|
ap.sbytes = uap->sbytes;
|
2002-12-14 01:56:26 +00:00
|
|
|
ap.flags = uap->flags;
|
2006-02-28 19:39:18 +00:00
|
|
|
|
|
|
|
if (uap->hdtr != NULL) {
|
|
|
|
error = copyin(uap->hdtr, &hdtr32, sizeof(hdtr32));
|
|
|
|
if (error)
|
|
|
|
goto out;
|
|
|
|
PTRIN_CP(hdtr32, hdtr, headers);
|
|
|
|
CP(hdtr32, hdtr, hdr_cnt);
|
|
|
|
PTRIN_CP(hdtr32, hdtr, trailers);
|
|
|
|
CP(hdtr32, hdtr, trl_cnt);
|
|
|
|
|
|
|
|
if (hdtr.headers != NULL) {
|
2006-07-10 19:37:43 +00:00
|
|
|
iov32 = PTRIN(hdtr32.headers);
|
2006-02-28 19:39:18 +00:00
|
|
|
error = freebsd32_copyinuio(iov32,
|
|
|
|
hdtr32.hdr_cnt, &hdr_uio);
|
|
|
|
if (error)
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
if (hdtr.trailers != NULL) {
|
2006-07-10 19:37:43 +00:00
|
|
|
iov32 = PTRIN(hdtr32.trailers);
|
2006-02-28 19:39:18 +00:00
|
|
|
error = freebsd32_copyinuio(iov32,
|
|
|
|
hdtr32.trl_cnt, &trl_uio);
|
|
|
|
if (error)
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
error = kern_sendfile(td, &ap, hdr_uio, trl_uio, compat);
|
|
|
|
out:
|
|
|
|
if (hdr_uio)
|
|
|
|
free(hdr_uio, M_IOV);
|
|
|
|
if (trl_uio)
|
|
|
|
free(trl_uio, M_IOV);
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef COMPAT_FREEBSD4
|
|
|
|
int
|
|
|
|
freebsd4_freebsd32_sendfile(struct thread *td,
|
|
|
|
struct freebsd4_freebsd32_sendfile_args *uap)
|
|
|
|
{
|
|
|
|
return (freebsd32_do_sendfile(td,
|
|
|
|
(struct freebsd32_sendfile_args *)uap, 1));
|
2002-10-09 22:27:24 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2002-07-20 02:56:12 +00:00
|
|
|
int
|
2003-08-22 23:07:28 +00:00
|
|
|
freebsd32_sendfile(struct thread *td, struct freebsd32_sendfile_args *uap)
|
2002-07-20 02:56:12 +00:00
|
|
|
{
|
|
|
|
|
2006-02-28 19:39:18 +00:00
|
|
|
return (freebsd32_do_sendfile(td, uap, 0));
|
2002-07-20 02:56:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2010-08-04 14:35:05 +00:00
|
|
|
copy_stat(struct stat *in, struct stat32 *out)
|
2002-07-20 02:56:12 +00:00
|
|
|
{
|
2010-08-04 14:35:05 +00:00
|
|
|
|
2002-07-20 02:56:12 +00:00
|
|
|
CP(*in, *out, st_dev);
|
|
|
|
CP(*in, *out, st_ino);
|
|
|
|
CP(*in, *out, st_mode);
|
|
|
|
CP(*in, *out, st_nlink);
|
|
|
|
CP(*in, *out, st_uid);
|
|
|
|
CP(*in, *out, st_gid);
|
|
|
|
CP(*in, *out, st_rdev);
|
2010-03-28 13:13:22 +00:00
|
|
|
TS_CP(*in, *out, st_atim);
|
|
|
|
TS_CP(*in, *out, st_mtim);
|
|
|
|
TS_CP(*in, *out, st_ctim);
|
2002-07-20 02:56:12 +00:00
|
|
|
CP(*in, *out, st_size);
|
|
|
|
CP(*in, *out, st_blocks);
|
|
|
|
CP(*in, *out, st_blksize);
|
|
|
|
CP(*in, *out, st_flags);
|
|
|
|
CP(*in, *out, st_gen);
|
2010-08-04 14:38:20 +00:00
|
|
|
TS_CP(*in, *out, st_birthtim);
|
2002-07-20 02:56:12 +00:00
|
|
|
}
|
|
|
|
|
2011-04-01 11:16:29 +00:00
|
|
|
#ifdef COMPAT_43
|
|
|
|
static void
|
|
|
|
copy_ostat(struct stat *in, struct ostat32 *out)
|
|
|
|
{
|
|
|
|
|
|
|
|
CP(*in, *out, st_dev);
|
|
|
|
CP(*in, *out, st_ino);
|
|
|
|
CP(*in, *out, st_mode);
|
|
|
|
CP(*in, *out, st_nlink);
|
|
|
|
CP(*in, *out, st_uid);
|
|
|
|
CP(*in, *out, st_gid);
|
|
|
|
CP(*in, *out, st_rdev);
|
|
|
|
CP(*in, *out, st_size);
|
|
|
|
TS_CP(*in, *out, st_atim);
|
|
|
|
TS_CP(*in, *out, st_mtim);
|
|
|
|
TS_CP(*in, *out, st_ctim);
|
|
|
|
CP(*in, *out, st_blksize);
|
|
|
|
CP(*in, *out, st_blocks);
|
|
|
|
CP(*in, *out, st_flags);
|
|
|
|
CP(*in, *out, st_gen);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2002-07-20 02:56:12 +00:00
|
|
|
int
|
2003-08-22 23:07:28 +00:00
|
|
|
freebsd32_stat(struct thread *td, struct freebsd32_stat_args *uap)
|
2002-07-20 02:56:12 +00:00
|
|
|
{
|
2003-12-23 03:20:49 +00:00
|
|
|
struct stat sb;
|
|
|
|
struct stat32 sb32;
|
2002-07-20 02:56:12 +00:00
|
|
|
int error;
|
- Add a custom version of exec_copyin_args() to deal with the 32-bit
pointers in argv and envv in userland and use that together with
kern_execve() and exec_free_args() to implement freebsd32_execve()
without using the stackgap.
- Fix freebsd32_adjtime() to call adjtime() rather than utimes(). Still
uses stackgap for now.
- Use kern_setitimer(), kern_getitimer(), kern_select(), kern_utimes(),
kern_statfs(), kern_fstatfs(), kern_fhstatfs(), kern_stat(),
kern_fstat(), and kern_lstat().
Tested by: cokane (amd64)
Silence on: amd64, ia64
2005-02-18 18:56:04 +00:00
|
|
|
|
|
|
|
error = kern_stat(td, uap->path, UIO_USERSPACE, &sb);
|
2002-07-20 02:56:12 +00:00
|
|
|
if (error)
|
|
|
|
return (error);
|
2003-12-23 03:20:49 +00:00
|
|
|
copy_stat(&sb, &sb32);
|
|
|
|
error = copyout(&sb32, uap->ub, sizeof (sb32));
|
2002-07-20 02:56:12 +00:00
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
2011-04-01 11:16:29 +00:00
|
|
|
#ifdef COMPAT_43
|
|
|
|
int
|
|
|
|
ofreebsd32_stat(struct thread *td, struct ofreebsd32_stat_args *uap)
|
|
|
|
{
|
|
|
|
struct stat sb;
|
|
|
|
struct ostat32 sb32;
|
|
|
|
int error;
|
|
|
|
|
|
|
|
error = kern_stat(td, uap->path, UIO_USERSPACE, &sb);
|
|
|
|
if (error)
|
|
|
|
return (error);
|
|
|
|
copy_ostat(&sb, &sb32);
|
|
|
|
error = copyout(&sb32, uap->ub, sizeof (sb32));
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2002-07-20 02:56:12 +00:00
|
|
|
int
|
2003-08-22 23:07:28 +00:00
|
|
|
freebsd32_fstat(struct thread *td, struct freebsd32_fstat_args *uap)
|
2002-07-20 02:56:12 +00:00
|
|
|
{
|
2003-12-23 03:20:49 +00:00
|
|
|
struct stat ub;
|
|
|
|
struct stat32 ub32;
|
2002-07-20 02:56:12 +00:00
|
|
|
int error;
|
|
|
|
|
- Add a custom version of exec_copyin_args() to deal with the 32-bit
pointers in argv and envv in userland and use that together with
kern_execve() and exec_free_args() to implement freebsd32_execve()
without using the stackgap.
- Fix freebsd32_adjtime() to call adjtime() rather than utimes(). Still
uses stackgap for now.
- Use kern_setitimer(), kern_getitimer(), kern_select(), kern_utimes(),
kern_statfs(), kern_fstatfs(), kern_fhstatfs(), kern_stat(),
kern_fstat(), and kern_lstat().
Tested by: cokane (amd64)
Silence on: amd64, ia64
2005-02-18 18:56:04 +00:00
|
|
|
error = kern_fstat(td, uap->fd, &ub);
|
2002-07-20 02:56:12 +00:00
|
|
|
if (error)
|
|
|
|
return (error);
|
2003-12-23 03:20:49 +00:00
|
|
|
copy_stat(&ub, &ub32);
|
|
|
|
error = copyout(&ub32, uap->ub, sizeof(ub32));
|
2002-07-20 02:56:12 +00:00
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
2011-04-01 11:16:29 +00:00
|
|
|
#ifdef COMPAT_43
|
|
|
|
int
|
|
|
|
ofreebsd32_fstat(struct thread *td, struct ofreebsd32_fstat_args *uap)
|
|
|
|
{
|
|
|
|
struct stat ub;
|
|
|
|
struct ostat32 ub32;
|
|
|
|
int error;
|
|
|
|
|
|
|
|
error = kern_fstat(td, uap->fd, &ub);
|
|
|
|
if (error)
|
|
|
|
return (error);
|
|
|
|
copy_ostat(&ub, &ub32);
|
|
|
|
error = copyout(&ub32, uap->ub, sizeof(ub32));
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2008-03-31 12:08:30 +00:00
|
|
|
int
|
|
|
|
freebsd32_fstatat(struct thread *td, struct freebsd32_fstatat_args *uap)
|
|
|
|
{
|
|
|
|
struct stat ub;
|
|
|
|
struct stat32 ub32;
|
|
|
|
int error;
|
|
|
|
|
|
|
|
error = kern_statat(td, uap->flag, uap->fd, uap->path, UIO_USERSPACE, &ub);
|
|
|
|
if (error)
|
|
|
|
return (error);
|
|
|
|
copy_stat(&ub, &ub32);
|
|
|
|
error = copyout(&ub32, uap->buf, sizeof(ub32));
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
2002-07-20 02:56:12 +00:00
|
|
|
int
|
2003-08-22 23:07:28 +00:00
|
|
|
freebsd32_lstat(struct thread *td, struct freebsd32_lstat_args *uap)
|
2002-07-20 02:56:12 +00:00
|
|
|
{
|
2003-12-23 03:20:49 +00:00
|
|
|
struct stat sb;
|
|
|
|
struct stat32 sb32;
|
- Add a custom version of exec_copyin_args() to deal with the 32-bit
pointers in argv and envv in userland and use that together with
kern_execve() and exec_free_args() to implement freebsd32_execve()
without using the stackgap.
- Fix freebsd32_adjtime() to call adjtime() rather than utimes(). Still
uses stackgap for now.
- Use kern_setitimer(), kern_getitimer(), kern_select(), kern_utimes(),
kern_statfs(), kern_fstatfs(), kern_fhstatfs(), kern_stat(),
kern_fstat(), and kern_lstat().
Tested by: cokane (amd64)
Silence on: amd64, ia64
2005-02-18 18:56:04 +00:00
|
|
|
int error;
|
2003-12-23 03:20:49 +00:00
|
|
|
|
- Add a custom version of exec_copyin_args() to deal with the 32-bit
pointers in argv and envv in userland and use that together with
kern_execve() and exec_free_args() to implement freebsd32_execve()
without using the stackgap.
- Fix freebsd32_adjtime() to call adjtime() rather than utimes(). Still
uses stackgap for now.
- Use kern_setitimer(), kern_getitimer(), kern_select(), kern_utimes(),
kern_statfs(), kern_fstatfs(), kern_fhstatfs(), kern_stat(),
kern_fstat(), and kern_lstat().
Tested by: cokane (amd64)
Silence on: amd64, ia64
2005-02-18 18:56:04 +00:00
|
|
|
error = kern_lstat(td, uap->path, UIO_USERSPACE, &sb);
|
2002-07-20 02:56:12 +00:00
|
|
|
if (error)
|
|
|
|
return (error);
|
2003-12-23 03:20:49 +00:00
|
|
|
copy_stat(&sb, &sb32);
|
|
|
|
error = copyout(&sb32, uap->ub, sizeof (sb32));
|
2002-07-20 02:56:12 +00:00
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
2011-04-01 11:16:29 +00:00
|
|
|
#ifdef COMPAT_43
|
|
|
|
int
|
|
|
|
ofreebsd32_lstat(struct thread *td, struct ofreebsd32_lstat_args *uap)
|
|
|
|
{
|
|
|
|
struct stat sb;
|
|
|
|
struct ostat32 sb32;
|
|
|
|
int error;
|
|
|
|
|
|
|
|
error = kern_lstat(td, uap->path, UIO_USERSPACE, &sb);
|
|
|
|
if (error)
|
|
|
|
return (error);
|
|
|
|
copy_ostat(&sb, &sb32);
|
|
|
|
error = copyout(&sb32, uap->ub, sizeof (sb32));
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2002-07-20 02:56:12 +00:00
|
|
|
int
|
2003-08-22 23:07:28 +00:00
|
|
|
freebsd32_sysctl(struct thread *td, struct freebsd32_sysctl_args *uap)
|
2002-07-20 02:56:12 +00:00
|
|
|
{
|
|
|
|
int error, name[CTL_MAXNAME];
|
|
|
|
size_t j, oldlen;
|
|
|
|
|
|
|
|
if (uap->namelen > CTL_MAXNAME || uap->namelen < 2)
|
|
|
|
return (EINVAL);
|
2004-10-11 22:04:16 +00:00
|
|
|
error = copyin(uap->name, name, uap->namelen * sizeof(int));
|
2002-07-20 02:56:12 +00:00
|
|
|
if (error)
|
|
|
|
return (error);
|
|
|
|
if (uap->oldlenp)
|
|
|
|
oldlen = fuword32(uap->oldlenp);
|
|
|
|
else
|
|
|
|
oldlen = 0;
|
|
|
|
error = userland_sysctl(td, name, uap->namelen,
|
|
|
|
uap->old, &oldlen, 1,
|
2004-10-11 22:04:16 +00:00
|
|
|
uap->new, uap->newlen, &j, SCTL_MASK32);
|
2002-07-20 02:56:12 +00:00
|
|
|
if (error && error != ENOMEM)
|
2008-12-29 12:58:45 +00:00
|
|
|
return (error);
|
2004-10-11 22:04:16 +00:00
|
|
|
if (uap->oldlenp)
|
2002-07-20 02:56:12 +00:00
|
|
|
suword32(uap->oldlenp, j);
|
2008-12-29 12:58:45 +00:00
|
|
|
return (0);
|
2002-07-20 02:56:12 +00:00
|
|
|
}
|
|
|
|
|
MFp4:
Bring in updated jail support from bz_jail branch.
This enhances the current jail implementation to permit multiple
addresses per jail. In addtion to IPv4, IPv6 is supported as well.
Due to updated checks it is even possible to have jails without
an IP address at all, which basically gives one a chroot with
restricted process view, no networking,..
SCTP support was updated and supports IPv6 in jails as well.
Cpuset support permits jails to be bound to specific processor
sets after creation.
Jails can have an unrestricted (no duplicate protection, etc.) name
in addition to the hostname. The jail name cannot be changed from
within a jail and is considered to be used for management purposes
or as audit-token in the future.
DDB 'show jails' command was added to aid debugging.
Proper compat support permits 32bit jail binaries to be used on 64bit
systems to manage jails. Also backward compatibility was preserved where
possible: for jail v1 syscalls, as well as with user space management
utilities.
Both jail as well as prison version were updated for the new features.
A gap was intentionally left as the intermediate versions had been
used by various patches floating around the last years.
Bump __FreeBSD_version for the afore mentioned and in kernel changes.
Special thanks to:
- Pawel Jakub Dawidek (pjd) for his multi-IPv4 patches
and Olivier Houchard (cognet) for initial single-IPv6 patches.
- Jeff Roberson (jeff) and Randall Stewart (rrs) for their
help, ideas and review on cpuset and SCTP support.
- Robert Watson (rwatson) for lots and lots of help, discussions,
suggestions and review of most of the patch at various stages.
- John Baldwin (jhb) for his help.
- Simon L. Nielsen (simon) as early adopter testing changes
on cluster machines as well as all the testers and people
who provided feedback the last months on freebsd-jail and
other channels.
- My employer, CK Software GmbH, for the support so I could work on this.
Reviewed by: (see above)
MFC after: 3 months (this is just so that I get the mail)
X-MFC Before: 7.2-RELEASE if possible
2008-11-29 14:32:14 +00:00
|
|
|
int
|
|
|
|
freebsd32_jail(struct thread *td, struct freebsd32_jail_args *uap)
|
|
|
|
{
|
|
|
|
uint32_t version;
|
|
|
|
int error;
|
2009-05-27 14:11:23 +00:00
|
|
|
struct jail j;
|
MFp4:
Bring in updated jail support from bz_jail branch.
This enhances the current jail implementation to permit multiple
addresses per jail. In addtion to IPv4, IPv6 is supported as well.
Due to updated checks it is even possible to have jails without
an IP address at all, which basically gives one a chroot with
restricted process view, no networking,..
SCTP support was updated and supports IPv6 in jails as well.
Cpuset support permits jails to be bound to specific processor
sets after creation.
Jails can have an unrestricted (no duplicate protection, etc.) name
in addition to the hostname. The jail name cannot be changed from
within a jail and is considered to be used for management purposes
or as audit-token in the future.
DDB 'show jails' command was added to aid debugging.
Proper compat support permits 32bit jail binaries to be used on 64bit
systems to manage jails. Also backward compatibility was preserved where
possible: for jail v1 syscalls, as well as with user space management
utilities.
Both jail as well as prison version were updated for the new features.
A gap was intentionally left as the intermediate versions had been
used by various patches floating around the last years.
Bump __FreeBSD_version for the afore mentioned and in kernel changes.
Special thanks to:
- Pawel Jakub Dawidek (pjd) for his multi-IPv4 patches
and Olivier Houchard (cognet) for initial single-IPv6 patches.
- Jeff Roberson (jeff) and Randall Stewart (rrs) for their
help, ideas and review on cpuset and SCTP support.
- Robert Watson (rwatson) for lots and lots of help, discussions,
suggestions and review of most of the patch at various stages.
- John Baldwin (jhb) for his help.
- Simon L. Nielsen (simon) as early adopter testing changes
on cluster machines as well as all the testers and people
who provided feedback the last months on freebsd-jail and
other channels.
- My employer, CK Software GmbH, for the support so I could work on this.
Reviewed by: (see above)
MFC after: 3 months (this is just so that I get the mail)
X-MFC Before: 7.2-RELEASE if possible
2008-11-29 14:32:14 +00:00
|
|
|
|
|
|
|
error = copyin(uap->jail, &version, sizeof(uint32_t));
|
|
|
|
if (error)
|
|
|
|
return (error);
|
2009-03-27 13:13:59 +00:00
|
|
|
|
MFp4:
Bring in updated jail support from bz_jail branch.
This enhances the current jail implementation to permit multiple
addresses per jail. In addtion to IPv4, IPv6 is supported as well.
Due to updated checks it is even possible to have jails without
an IP address at all, which basically gives one a chroot with
restricted process view, no networking,..
SCTP support was updated and supports IPv6 in jails as well.
Cpuset support permits jails to be bound to specific processor
sets after creation.
Jails can have an unrestricted (no duplicate protection, etc.) name
in addition to the hostname. The jail name cannot be changed from
within a jail and is considered to be used for management purposes
or as audit-token in the future.
DDB 'show jails' command was added to aid debugging.
Proper compat support permits 32bit jail binaries to be used on 64bit
systems to manage jails. Also backward compatibility was preserved where
possible: for jail v1 syscalls, as well as with user space management
utilities.
Both jail as well as prison version were updated for the new features.
A gap was intentionally left as the intermediate versions had been
used by various patches floating around the last years.
Bump __FreeBSD_version for the afore mentioned and in kernel changes.
Special thanks to:
- Pawel Jakub Dawidek (pjd) for his multi-IPv4 patches
and Olivier Houchard (cognet) for initial single-IPv6 patches.
- Jeff Roberson (jeff) and Randall Stewart (rrs) for their
help, ideas and review on cpuset and SCTP support.
- Robert Watson (rwatson) for lots and lots of help, discussions,
suggestions and review of most of the patch at various stages.
- John Baldwin (jhb) for his help.
- Simon L. Nielsen (simon) as early adopter testing changes
on cluster machines as well as all the testers and people
who provided feedback the last months on freebsd-jail and
other channels.
- My employer, CK Software GmbH, for the support so I could work on this.
Reviewed by: (see above)
MFC after: 3 months (this is just so that I get the mail)
X-MFC Before: 7.2-RELEASE if possible
2008-11-29 14:32:14 +00:00
|
|
|
switch (version) {
|
2009-03-27 13:13:59 +00:00
|
|
|
case 0:
|
MFp4:
Bring in updated jail support from bz_jail branch.
This enhances the current jail implementation to permit multiple
addresses per jail. In addtion to IPv4, IPv6 is supported as well.
Due to updated checks it is even possible to have jails without
an IP address at all, which basically gives one a chroot with
restricted process view, no networking,..
SCTP support was updated and supports IPv6 in jails as well.
Cpuset support permits jails to be bound to specific processor
sets after creation.
Jails can have an unrestricted (no duplicate protection, etc.) name
in addition to the hostname. The jail name cannot be changed from
within a jail and is considered to be used for management purposes
or as audit-token in the future.
DDB 'show jails' command was added to aid debugging.
Proper compat support permits 32bit jail binaries to be used on 64bit
systems to manage jails. Also backward compatibility was preserved where
possible: for jail v1 syscalls, as well as with user space management
utilities.
Both jail as well as prison version were updated for the new features.
A gap was intentionally left as the intermediate versions had been
used by various patches floating around the last years.
Bump __FreeBSD_version for the afore mentioned and in kernel changes.
Special thanks to:
- Pawel Jakub Dawidek (pjd) for his multi-IPv4 patches
and Olivier Houchard (cognet) for initial single-IPv6 patches.
- Jeff Roberson (jeff) and Randall Stewart (rrs) for their
help, ideas and review on cpuset and SCTP support.
- Robert Watson (rwatson) for lots and lots of help, discussions,
suggestions and review of most of the patch at various stages.
- John Baldwin (jhb) for his help.
- Simon L. Nielsen (simon) as early adopter testing changes
on cluster machines as well as all the testers and people
who provided feedback the last months on freebsd-jail and
other channels.
- My employer, CK Software GmbH, for the support so I could work on this.
Reviewed by: (see above)
MFC after: 3 months (this is just so that I get the mail)
X-MFC Before: 7.2-RELEASE if possible
2008-11-29 14:32:14 +00:00
|
|
|
{
|
|
|
|
/* FreeBSD single IPv4 jails. */
|
|
|
|
struct jail32_v0 j32_v0;
|
|
|
|
|
2009-05-27 14:11:23 +00:00
|
|
|
bzero(&j, sizeof(struct jail));
|
MFp4:
Bring in updated jail support from bz_jail branch.
This enhances the current jail implementation to permit multiple
addresses per jail. In addtion to IPv4, IPv6 is supported as well.
Due to updated checks it is even possible to have jails without
an IP address at all, which basically gives one a chroot with
restricted process view, no networking,..
SCTP support was updated and supports IPv6 in jails as well.
Cpuset support permits jails to be bound to specific processor
sets after creation.
Jails can have an unrestricted (no duplicate protection, etc.) name
in addition to the hostname. The jail name cannot be changed from
within a jail and is considered to be used for management purposes
or as audit-token in the future.
DDB 'show jails' command was added to aid debugging.
Proper compat support permits 32bit jail binaries to be used on 64bit
systems to manage jails. Also backward compatibility was preserved where
possible: for jail v1 syscalls, as well as with user space management
utilities.
Both jail as well as prison version were updated for the new features.
A gap was intentionally left as the intermediate versions had been
used by various patches floating around the last years.
Bump __FreeBSD_version for the afore mentioned and in kernel changes.
Special thanks to:
- Pawel Jakub Dawidek (pjd) for his multi-IPv4 patches
and Olivier Houchard (cognet) for initial single-IPv6 patches.
- Jeff Roberson (jeff) and Randall Stewart (rrs) for their
help, ideas and review on cpuset and SCTP support.
- Robert Watson (rwatson) for lots and lots of help, discussions,
suggestions and review of most of the patch at various stages.
- John Baldwin (jhb) for his help.
- Simon L. Nielsen (simon) as early adopter testing changes
on cluster machines as well as all the testers and people
who provided feedback the last months on freebsd-jail and
other channels.
- My employer, CK Software GmbH, for the support so I could work on this.
Reviewed by: (see above)
MFC after: 3 months (this is just so that I get the mail)
X-MFC Before: 7.2-RELEASE if possible
2008-11-29 14:32:14 +00:00
|
|
|
error = copyin(uap->jail, &j32_v0, sizeof(struct jail32_v0));
|
|
|
|
if (error)
|
|
|
|
return (error);
|
2009-05-27 14:11:23 +00:00
|
|
|
CP(j32_v0, j, version);
|
|
|
|
PTRIN_CP(j32_v0, j, path);
|
|
|
|
PTRIN_CP(j32_v0, j, hostname);
|
|
|
|
j.ip4s = j32_v0.ip_number;
|
MFp4:
Bring in updated jail support from bz_jail branch.
This enhances the current jail implementation to permit multiple
addresses per jail. In addtion to IPv4, IPv6 is supported as well.
Due to updated checks it is even possible to have jails without
an IP address at all, which basically gives one a chroot with
restricted process view, no networking,..
SCTP support was updated and supports IPv6 in jails as well.
Cpuset support permits jails to be bound to specific processor
sets after creation.
Jails can have an unrestricted (no duplicate protection, etc.) name
in addition to the hostname. The jail name cannot be changed from
within a jail and is considered to be used for management purposes
or as audit-token in the future.
DDB 'show jails' command was added to aid debugging.
Proper compat support permits 32bit jail binaries to be used on 64bit
systems to manage jails. Also backward compatibility was preserved where
possible: for jail v1 syscalls, as well as with user space management
utilities.
Both jail as well as prison version were updated for the new features.
A gap was intentionally left as the intermediate versions had been
used by various patches floating around the last years.
Bump __FreeBSD_version for the afore mentioned and in kernel changes.
Special thanks to:
- Pawel Jakub Dawidek (pjd) for his multi-IPv4 patches
and Olivier Houchard (cognet) for initial single-IPv6 patches.
- Jeff Roberson (jeff) and Randall Stewart (rrs) for their
help, ideas and review on cpuset and SCTP support.
- Robert Watson (rwatson) for lots and lots of help, discussions,
suggestions and review of most of the patch at various stages.
- John Baldwin (jhb) for his help.
- Simon L. Nielsen (simon) as early adopter testing changes
on cluster machines as well as all the testers and people
who provided feedback the last months on freebsd-jail and
other channels.
- My employer, CK Software GmbH, for the support so I could work on this.
Reviewed by: (see above)
MFC after: 3 months (this is just so that I get the mail)
X-MFC Before: 7.2-RELEASE if possible
2008-11-29 14:32:14 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case 1:
|
|
|
|
/*
|
|
|
|
* Version 1 was used by multi-IPv4 jail implementations
|
|
|
|
* that never made it into the official kernel.
|
|
|
|
*/
|
|
|
|
return (EINVAL);
|
|
|
|
|
|
|
|
case 2: /* JAIL_API_VERSION */
|
|
|
|
{
|
|
|
|
/* FreeBSD multi-IPv4/IPv6,noIP jails. */
|
|
|
|
struct jail32 j32;
|
|
|
|
|
|
|
|
error = copyin(uap->jail, &j32, sizeof(struct jail32));
|
|
|
|
if (error)
|
|
|
|
return (error);
|
2009-05-27 14:11:23 +00:00
|
|
|
CP(j32, j, version);
|
|
|
|
PTRIN_CP(j32, j, path);
|
|
|
|
PTRIN_CP(j32, j, hostname);
|
|
|
|
PTRIN_CP(j32, j, jailname);
|
|
|
|
CP(j32, j, ip4s);
|
|
|
|
CP(j32, j, ip6s);
|
|
|
|
PTRIN_CP(j32, j, ip4);
|
|
|
|
PTRIN_CP(j32, j, ip6);
|
MFp4:
Bring in updated jail support from bz_jail branch.
This enhances the current jail implementation to permit multiple
addresses per jail. In addtion to IPv4, IPv6 is supported as well.
Due to updated checks it is even possible to have jails without
an IP address at all, which basically gives one a chroot with
restricted process view, no networking,..
SCTP support was updated and supports IPv6 in jails as well.
Cpuset support permits jails to be bound to specific processor
sets after creation.
Jails can have an unrestricted (no duplicate protection, etc.) name
in addition to the hostname. The jail name cannot be changed from
within a jail and is considered to be used for management purposes
or as audit-token in the future.
DDB 'show jails' command was added to aid debugging.
Proper compat support permits 32bit jail binaries to be used on 64bit
systems to manage jails. Also backward compatibility was preserved where
possible: for jail v1 syscalls, as well as with user space management
utilities.
Both jail as well as prison version were updated for the new features.
A gap was intentionally left as the intermediate versions had been
used by various patches floating around the last years.
Bump __FreeBSD_version for the afore mentioned and in kernel changes.
Special thanks to:
- Pawel Jakub Dawidek (pjd) for his multi-IPv4 patches
and Olivier Houchard (cognet) for initial single-IPv6 patches.
- Jeff Roberson (jeff) and Randall Stewart (rrs) for their
help, ideas and review on cpuset and SCTP support.
- Robert Watson (rwatson) for lots and lots of help, discussions,
suggestions and review of most of the patch at various stages.
- John Baldwin (jhb) for his help.
- Simon L. Nielsen (simon) as early adopter testing changes
on cluster machines as well as all the testers and people
who provided feedback the last months on freebsd-jail and
other channels.
- My employer, CK Software GmbH, for the support so I could work on this.
Reviewed by: (see above)
MFC after: 3 months (this is just so that I get the mail)
X-MFC Before: 7.2-RELEASE if possible
2008-11-29 14:32:14 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
default:
|
|
|
|
/* Sci-Fi jails are not supported, sorry. */
|
|
|
|
return (EINVAL);
|
|
|
|
}
|
2009-05-27 14:11:23 +00:00
|
|
|
return (kern_jail(td, &j));
|
2009-04-29 21:14:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
freebsd32_jail_set(struct thread *td, struct freebsd32_jail_set_args *uap)
|
|
|
|
{
|
|
|
|
struct uio *auio;
|
|
|
|
int error;
|
|
|
|
|
|
|
|
/* Check that we have an even number of iovecs. */
|
|
|
|
if (uap->iovcnt & 1)
|
|
|
|
return (EINVAL);
|
|
|
|
|
|
|
|
error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
|
|
|
|
if (error)
|
|
|
|
return (error);
|
|
|
|
error = kern_jail_set(td, auio, uap->flags);
|
|
|
|
free(auio, M_IOV);
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
freebsd32_jail_get(struct thread *td, struct freebsd32_jail_get_args *uap)
|
|
|
|
{
|
|
|
|
struct iovec32 iov32;
|
|
|
|
struct uio *auio;
|
|
|
|
int error, i;
|
|
|
|
|
|
|
|
/* Check that we have an even number of iovecs. */
|
|
|
|
if (uap->iovcnt & 1)
|
|
|
|
return (EINVAL);
|
|
|
|
|
|
|
|
error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
|
|
|
|
if (error)
|
|
|
|
return (error);
|
|
|
|
error = kern_jail_get(td, auio, uap->flags);
|
|
|
|
if (error == 0)
|
|
|
|
for (i = 0; i < uap->iovcnt; i++) {
|
|
|
|
PTROUT_CP(auio->uio_iov[i], iov32, iov_base);
|
|
|
|
CP(auio->uio_iov[i], iov32, iov_len);
|
|
|
|
error = copyout(&iov32, uap->iovp + i, sizeof(iov32));
|
|
|
|
if (error != 0)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
free(auio, M_IOV);
|
|
|
|
return (error);
|
MFp4:
Bring in updated jail support from bz_jail branch.
This enhances the current jail implementation to permit multiple
addresses per jail. In addtion to IPv4, IPv6 is supported as well.
Due to updated checks it is even possible to have jails without
an IP address at all, which basically gives one a chroot with
restricted process view, no networking,..
SCTP support was updated and supports IPv6 in jails as well.
Cpuset support permits jails to be bound to specific processor
sets after creation.
Jails can have an unrestricted (no duplicate protection, etc.) name
in addition to the hostname. The jail name cannot be changed from
within a jail and is considered to be used for management purposes
or as audit-token in the future.
DDB 'show jails' command was added to aid debugging.
Proper compat support permits 32bit jail binaries to be used on 64bit
systems to manage jails. Also backward compatibility was preserved where
possible: for jail v1 syscalls, as well as with user space management
utilities.
Both jail as well as prison version were updated for the new features.
A gap was intentionally left as the intermediate versions had been
used by various patches floating around the last years.
Bump __FreeBSD_version for the afore mentioned and in kernel changes.
Special thanks to:
- Pawel Jakub Dawidek (pjd) for his multi-IPv4 patches
and Olivier Houchard (cognet) for initial single-IPv6 patches.
- Jeff Roberson (jeff) and Randall Stewart (rrs) for their
help, ideas and review on cpuset and SCTP support.
- Robert Watson (rwatson) for lots and lots of help, discussions,
suggestions and review of most of the patch at various stages.
- John Baldwin (jhb) for his help.
- Simon L. Nielsen (simon) as early adopter testing changes
on cluster machines as well as all the testers and people
who provided feedback the last months on freebsd-jail and
other channels.
- My employer, CK Software GmbH, for the support so I could work on this.
Reviewed by: (see above)
MFC after: 3 months (this is just so that I get the mail)
X-MFC Before: 7.2-RELEASE if possible
2008-11-29 14:32:14 +00:00
|
|
|
}
|
|
|
|
|
2002-07-20 02:56:12 +00:00
|
|
|
int
|
2003-08-22 23:07:28 +00:00
|
|
|
freebsd32_sigaction(struct thread *td, struct freebsd32_sigaction_args *uap)
|
2002-07-20 02:56:12 +00:00
|
|
|
{
|
2003-04-22 18:23:49 +00:00
|
|
|
struct sigaction32 s32;
|
|
|
|
struct sigaction sa, osa, *sap;
|
2002-07-20 02:56:12 +00:00
|
|
|
int error;
|
|
|
|
|
2003-04-22 18:23:49 +00:00
|
|
|
if (uap->act) {
|
|
|
|
error = copyin(uap->act, &s32, sizeof(s32));
|
2002-07-20 02:56:12 +00:00
|
|
|
if (error)
|
|
|
|
return (error);
|
2003-04-22 18:23:49 +00:00
|
|
|
sa.sa_handler = PTRIN(s32.sa_u);
|
|
|
|
CP(s32, sa, sa_flags);
|
|
|
|
CP(s32, sa, sa_mask);
|
|
|
|
sap = &sa;
|
|
|
|
} else
|
|
|
|
sap = NULL;
|
|
|
|
error = kern_sigaction(td, uap->sig, sap, &osa, 0);
|
2005-05-24 17:52:14 +00:00
|
|
|
if (error == 0 && uap->oact != NULL) {
|
2003-04-22 18:23:49 +00:00
|
|
|
s32.sa_u = PTROUT(osa.sa_handler);
|
|
|
|
CP(osa, s32, sa_flags);
|
|
|
|
CP(osa, s32, sa_mask);
|
|
|
|
error = copyout(&s32, uap->oact, sizeof(s32));
|
2002-07-20 02:56:12 +00:00
|
|
|
}
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
2003-05-14 04:10:49 +00:00
|
|
|
#ifdef COMPAT_FREEBSD4
|
|
|
|
int
|
2003-08-22 23:07:28 +00:00
|
|
|
freebsd4_freebsd32_sigaction(struct thread *td,
|
|
|
|
struct freebsd4_freebsd32_sigaction_args *uap)
|
2003-05-14 04:10:49 +00:00
|
|
|
{
|
|
|
|
struct sigaction32 s32;
|
|
|
|
struct sigaction sa, osa, *sap;
|
|
|
|
int error;
|
|
|
|
|
|
|
|
if (uap->act) {
|
|
|
|
error = copyin(uap->act, &s32, sizeof(s32));
|
|
|
|
if (error)
|
|
|
|
return (error);
|
|
|
|
sa.sa_handler = PTRIN(s32.sa_u);
|
|
|
|
CP(s32, sa, sa_flags);
|
|
|
|
CP(s32, sa, sa_mask);
|
|
|
|
sap = &sa;
|
|
|
|
} else
|
|
|
|
sap = NULL;
|
|
|
|
error = kern_sigaction(td, uap->sig, sap, &osa, KSA_FREEBSD4);
|
2005-05-24 17:52:14 +00:00
|
|
|
if (error == 0 && uap->oact != NULL) {
|
2003-05-14 04:10:49 +00:00
|
|
|
s32.sa_u = PTROUT(osa.sa_handler);
|
|
|
|
CP(osa, s32, sa_flags);
|
|
|
|
CP(osa, s32, sa_mask);
|
|
|
|
error = copyout(&s32, uap->oact, sizeof(s32));
|
|
|
|
}
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2005-10-23 10:43:14 +00:00
|
|
|
#ifdef COMPAT_43
|
2005-10-26 22:19:51 +00:00
|
|
|
struct osigaction32 {
|
2005-10-23 10:43:14 +00:00
|
|
|
u_int32_t sa_u;
|
|
|
|
osigset_t sa_mask;
|
|
|
|
int sa_flags;
|
|
|
|
};
|
|
|
|
|
|
|
|
#define ONSIG 32
|
|
|
|
|
|
|
|
int
|
2005-10-26 22:19:51 +00:00
|
|
|
ofreebsd32_sigaction(struct thread *td,
|
|
|
|
struct ofreebsd32_sigaction_args *uap)
|
2005-10-23 10:43:14 +00:00
|
|
|
{
|
2005-10-26 22:19:51 +00:00
|
|
|
struct osigaction32 s32;
|
2005-10-23 10:43:14 +00:00
|
|
|
struct sigaction sa, osa, *sap;
|
|
|
|
int error;
|
|
|
|
|
|
|
|
if (uap->signum <= 0 || uap->signum >= ONSIG)
|
|
|
|
return (EINVAL);
|
|
|
|
|
|
|
|
if (uap->nsa) {
|
|
|
|
error = copyin(uap->nsa, &s32, sizeof(s32));
|
|
|
|
if (error)
|
|
|
|
return (error);
|
|
|
|
sa.sa_handler = PTRIN(s32.sa_u);
|
|
|
|
CP(s32, sa, sa_flags);
|
|
|
|
OSIG2SIG(s32.sa_mask, sa.sa_mask);
|
|
|
|
sap = &sa;
|
|
|
|
} else
|
|
|
|
sap = NULL;
|
|
|
|
error = kern_sigaction(td, uap->signum, sap, &osa, KSA_OSIGSET);
|
|
|
|
if (error == 0 && uap->osa != NULL) {
|
|
|
|
s32.sa_u = PTROUT(osa.sa_handler);
|
|
|
|
CP(osa, s32, sa_flags);
|
|
|
|
SIG2OSIG(osa.sa_mask, s32.sa_mask);
|
|
|
|
error = copyout(&s32, uap->osa, sizeof(s32));
|
|
|
|
}
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2005-10-26 22:19:51 +00:00
|
|
|
ofreebsd32_sigprocmask(struct thread *td,
|
|
|
|
struct ofreebsd32_sigprocmask_args *uap)
|
2005-10-23 10:43:14 +00:00
|
|
|
{
|
|
|
|
sigset_t set, oset;
|
|
|
|
int error;
|
|
|
|
|
|
|
|
OSIG2SIG(uap->mask, set);
|
2009-10-27 10:47:58 +00:00
|
|
|
error = kern_sigprocmask(td, uap->how, &set, &oset, SIGPROCMASK_OLD);
|
2005-10-23 10:43:14 +00:00
|
|
|
SIG2OSIG(oset, td->td_retval[0]);
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2005-10-26 22:19:51 +00:00
|
|
|
ofreebsd32_sigpending(struct thread *td,
|
|
|
|
struct ofreebsd32_sigpending_args *uap)
|
2005-10-23 10:43:14 +00:00
|
|
|
{
|
|
|
|
struct proc *p = td->td_proc;
|
|
|
|
sigset_t siglist;
|
|
|
|
|
|
|
|
PROC_LOCK(p);
|
|
|
|
siglist = p->p_siglist;
|
|
|
|
SIGSETOR(siglist, td->td_siglist);
|
|
|
|
PROC_UNLOCK(p);
|
|
|
|
SIG2OSIG(siglist, td->td_retval[0]);
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
struct sigvec32 {
|
|
|
|
u_int32_t sv_handler;
|
|
|
|
int sv_mask;
|
|
|
|
int sv_flags;
|
|
|
|
};
|
|
|
|
|
|
|
|
int
|
2005-10-26 22:19:51 +00:00
|
|
|
ofreebsd32_sigvec(struct thread *td,
|
|
|
|
struct ofreebsd32_sigvec_args *uap)
|
2005-10-23 10:43:14 +00:00
|
|
|
{
|
|
|
|
struct sigvec32 vec;
|
|
|
|
struct sigaction sa, osa, *sap;
|
|
|
|
int error;
|
|
|
|
|
|
|
|
if (uap->signum <= 0 || uap->signum >= ONSIG)
|
|
|
|
return (EINVAL);
|
|
|
|
|
|
|
|
if (uap->nsv) {
|
|
|
|
error = copyin(uap->nsv, &vec, sizeof(vec));
|
|
|
|
if (error)
|
|
|
|
return (error);
|
|
|
|
sa.sa_handler = PTRIN(vec.sv_handler);
|
|
|
|
OSIG2SIG(vec.sv_mask, sa.sa_mask);
|
|
|
|
sa.sa_flags = vec.sv_flags;
|
|
|
|
sa.sa_flags ^= SA_RESTART;
|
|
|
|
sap = &sa;
|
|
|
|
} else
|
|
|
|
sap = NULL;
|
|
|
|
error = kern_sigaction(td, uap->signum, sap, &osa, KSA_OSIGSET);
|
|
|
|
if (error == 0 && uap->osv != NULL) {
|
|
|
|
vec.sv_handler = PTROUT(osa.sa_handler);
|
|
|
|
SIG2OSIG(osa.sa_mask, vec.sv_mask);
|
|
|
|
vec.sv_flags = osa.sa_flags;
|
|
|
|
vec.sv_flags &= ~SA_NOCLDWAIT;
|
|
|
|
vec.sv_flags ^= SA_RESTART;
|
|
|
|
error = copyout(&vec, uap->osv, sizeof(vec));
|
|
|
|
}
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2005-10-26 22:19:51 +00:00
|
|
|
ofreebsd32_sigblock(struct thread *td,
|
|
|
|
struct ofreebsd32_sigblock_args *uap)
|
2005-10-23 10:43:14 +00:00
|
|
|
{
|
2009-10-27 10:47:58 +00:00
|
|
|
sigset_t set, oset;
|
2005-10-23 10:43:14 +00:00
|
|
|
|
|
|
|
OSIG2SIG(uap->mask, set);
|
2009-10-27 10:47:58 +00:00
|
|
|
kern_sigprocmask(td, SIG_BLOCK, &set, &oset, 0);
|
|
|
|
SIG2OSIG(oset, td->td_retval[0]);
|
2005-10-23 10:43:14 +00:00
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2005-10-26 22:19:51 +00:00
|
|
|
ofreebsd32_sigsetmask(struct thread *td,
|
|
|
|
struct ofreebsd32_sigsetmask_args *uap)
|
2005-10-23 10:43:14 +00:00
|
|
|
{
|
2009-10-27 10:47:58 +00:00
|
|
|
sigset_t set, oset;
|
2005-10-23 10:43:14 +00:00
|
|
|
|
|
|
|
OSIG2SIG(uap->mask, set);
|
2009-10-27 10:47:58 +00:00
|
|
|
kern_sigprocmask(td, SIG_SETMASK, &set, &oset, 0);
|
|
|
|
SIG2OSIG(oset, td->td_retval[0]);
|
2005-10-23 10:43:14 +00:00
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2005-10-26 22:19:51 +00:00
|
|
|
ofreebsd32_sigsuspend(struct thread *td,
|
|
|
|
struct ofreebsd32_sigsuspend_args *uap)
|
2005-10-23 10:43:14 +00:00
|
|
|
{
|
|
|
|
sigset_t mask;
|
|
|
|
|
|
|
|
OSIG2SIG(uap->mask, mask);
|
2009-10-27 10:42:24 +00:00
|
|
|
return (kern_sigsuspend(td, mask));
|
2005-10-23 10:43:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
struct sigstack32 {
|
|
|
|
u_int32_t ss_sp;
|
|
|
|
int ss_onstack;
|
|
|
|
};
|
|
|
|
|
|
|
|
int
|
2005-10-26 22:19:51 +00:00
|
|
|
ofreebsd32_sigstack(struct thread *td,
|
|
|
|
struct ofreebsd32_sigstack_args *uap)
|
2005-10-23 10:43:14 +00:00
|
|
|
{
|
|
|
|
struct sigstack32 s32;
|
|
|
|
struct sigstack nss, oss;
|
2007-06-17 04:37:57 +00:00
|
|
|
int error = 0, unss;
|
2005-10-23 10:43:14 +00:00
|
|
|
|
|
|
|
if (uap->nss != NULL) {
|
|
|
|
error = copyin(uap->nss, &s32, sizeof(s32));
|
|
|
|
if (error)
|
|
|
|
return (error);
|
|
|
|
nss.ss_sp = PTRIN(s32.ss_sp);
|
|
|
|
CP(s32, nss, ss_onstack);
|
2007-06-17 04:37:57 +00:00
|
|
|
unss = 1;
|
|
|
|
} else {
|
|
|
|
unss = 0;
|
2005-10-23 10:43:14 +00:00
|
|
|
}
|
|
|
|
oss.ss_sp = td->td_sigstk.ss_sp;
|
|
|
|
oss.ss_onstack = sigonstack(cpu_getstack(td));
|
2007-06-17 04:37:57 +00:00
|
|
|
if (unss) {
|
2005-10-23 10:43:14 +00:00
|
|
|
td->td_sigstk.ss_sp = nss.ss_sp;
|
|
|
|
td->td_sigstk.ss_size = 0;
|
2007-06-17 04:37:57 +00:00
|
|
|
td->td_sigstk.ss_flags |= (nss.ss_onstack & SS_ONSTACK);
|
2005-10-23 10:43:14 +00:00
|
|
|
td->td_pflags |= TDP_ALTSTACK;
|
|
|
|
}
|
|
|
|
if (uap->oss != NULL) {
|
|
|
|
s32.ss_sp = PTROUT(oss.ss_sp);
|
|
|
|
CP(oss, s32, ss_onstack);
|
|
|
|
error = copyout(&s32, uap->oss, sizeof(s32));
|
|
|
|
}
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2005-01-19 17:44:59 +00:00
|
|
|
int
|
|
|
|
freebsd32_nanosleep(struct thread *td, struct freebsd32_nanosleep_args *uap)
|
|
|
|
{
|
|
|
|
struct timespec32 rmt32, rqt32;
|
|
|
|
struct timespec rmt, rqt;
|
|
|
|
int error;
|
|
|
|
|
2005-10-15 02:40:10 +00:00
|
|
|
error = copyin(uap->rqtp, &rqt32, sizeof(rqt32));
|
2005-01-19 17:44:59 +00:00
|
|
|
if (error)
|
|
|
|
return (error);
|
|
|
|
|
|
|
|
CP(rqt32, rqt, tv_sec);
|
|
|
|
CP(rqt32, rqt, tv_nsec);
|
|
|
|
|
|
|
|
if (uap->rmtp &&
|
|
|
|
!useracc((caddr_t)uap->rmtp, sizeof(rmt), VM_PROT_WRITE))
|
|
|
|
return (EFAULT);
|
|
|
|
error = kern_nanosleep(td, &rqt, &rmt);
|
|
|
|
if (error && uap->rmtp) {
|
|
|
|
int error2;
|
|
|
|
|
|
|
|
CP(rmt, rmt32, tv_sec);
|
|
|
|
CP(rmt, rmt32, tv_nsec);
|
|
|
|
|
2005-10-15 02:40:10 +00:00
|
|
|
error2 = copyout(&rmt32, uap->rmtp, sizeof(rmt32));
|
2005-01-19 17:44:59 +00:00
|
|
|
if (error2)
|
|
|
|
error = error2;
|
|
|
|
}
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
2005-10-15 02:54:18 +00:00
|
|
|
int
|
|
|
|
freebsd32_clock_gettime(struct thread *td,
|
|
|
|
struct freebsd32_clock_gettime_args *uap)
|
|
|
|
{
|
|
|
|
struct timespec ats;
|
|
|
|
struct timespec32 ats32;
|
|
|
|
int error;
|
|
|
|
|
|
|
|
error = kern_clock_gettime(td, uap->clock_id, &ats);
|
|
|
|
if (error == 0) {
|
|
|
|
CP(ats, ats32, tv_sec);
|
|
|
|
CP(ats, ats32, tv_nsec);
|
|
|
|
error = copyout(&ats32, uap->tp, sizeof(ats32));
|
|
|
|
}
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
freebsd32_clock_settime(struct thread *td,
|
|
|
|
struct freebsd32_clock_settime_args *uap)
|
|
|
|
{
|
|
|
|
struct timespec ats;
|
|
|
|
struct timespec32 ats32;
|
|
|
|
int error;
|
|
|
|
|
|
|
|
error = copyin(uap->tp, &ats32, sizeof(ats32));
|
|
|
|
if (error)
|
|
|
|
return (error);
|
|
|
|
CP(ats32, ats, tv_sec);
|
|
|
|
CP(ats32, ats, tv_nsec);
|
|
|
|
|
|
|
|
return (kern_clock_settime(td, uap->clock_id, &ats));
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
freebsd32_clock_getres(struct thread *td,
|
|
|
|
struct freebsd32_clock_getres_args *uap)
|
|
|
|
{
|
|
|
|
struct timespec ts;
|
|
|
|
struct timespec32 ts32;
|
|
|
|
int error;
|
|
|
|
|
|
|
|
if (uap->tp == NULL)
|
|
|
|
return (0);
|
|
|
|
error = kern_clock_getres(td, uap->clock_id, &ts);
|
|
|
|
if (error == 0) {
|
|
|
|
CP(ts, ts32, tv_sec);
|
|
|
|
CP(ts, ts32, tv_nsec);
|
|
|
|
error = copyout(&ts32, uap->tp, sizeof(ts32));
|
|
|
|
}
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
2006-09-22 15:04:28 +00:00
|
|
|
int
|
|
|
|
freebsd32_thr_new(struct thread *td,
|
|
|
|
struct freebsd32_thr_new_args *uap)
|
|
|
|
{
|
|
|
|
struct thr_param32 param32;
|
|
|
|
struct thr_param param;
|
|
|
|
int error;
|
|
|
|
|
|
|
|
if (uap->param_size < 0 ||
|
|
|
|
uap->param_size > sizeof(struct thr_param32))
|
|
|
|
return (EINVAL);
|
|
|
|
bzero(¶m, sizeof(struct thr_param));
|
|
|
|
bzero(¶m32, sizeof(struct thr_param32));
|
|
|
|
error = copyin(uap->param, ¶m32, uap->param_size);
|
|
|
|
if (error != 0)
|
|
|
|
return (error);
|
|
|
|
param.start_func = PTRIN(param32.start_func);
|
|
|
|
param.arg = PTRIN(param32.arg);
|
|
|
|
param.stack_base = PTRIN(param32.stack_base);
|
|
|
|
param.stack_size = param32.stack_size;
|
|
|
|
param.tls_base = PTRIN(param32.tls_base);
|
|
|
|
param.tls_size = param32.tls_size;
|
|
|
|
param.child_tid = PTRIN(param32.child_tid);
|
|
|
|
param.parent_tid = PTRIN(param32.parent_tid);
|
|
|
|
param.flags = param32.flags;
|
|
|
|
param.rtp = PTRIN(param32.rtp);
|
|
|
|
param.spare[0] = PTRIN(param32.spare[0]);
|
|
|
|
param.spare[1] = PTRIN(param32.spare[1]);
|
|
|
|
param.spare[2] = PTRIN(param32.spare[2]);
|
|
|
|
|
|
|
|
return (kern_thr_new(td, ¶m));
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
freebsd32_thr_suspend(struct thread *td, struct freebsd32_thr_suspend_args *uap)
|
|
|
|
{
|
|
|
|
struct timespec32 ts32;
|
|
|
|
struct timespec ts, *tsp;
|
|
|
|
int error;
|
|
|
|
|
|
|
|
error = 0;
|
|
|
|
tsp = NULL;
|
|
|
|
if (uap->timeout != NULL) {
|
|
|
|
error = copyin((const void *)uap->timeout, (void *)&ts32,
|
|
|
|
sizeof(struct timespec32));
|
|
|
|
if (error != 0)
|
|
|
|
return (error);
|
|
|
|
ts.tv_sec = ts32.tv_sec;
|
|
|
|
ts.tv_nsec = ts32.tv_nsec;
|
|
|
|
tsp = &ts;
|
|
|
|
}
|
|
|
|
return (kern_thr_suspend(td, tsp));
|
|
|
|
}
|
|
|
|
|
2006-10-05 01:56:11 +00:00
|
|
|
void
|
2010-07-04 11:43:53 +00:00
|
|
|
siginfo_to_siginfo32(const siginfo_t *src, struct siginfo32 *dst)
|
2006-10-05 01:56:11 +00:00
|
|
|
{
|
|
|
|
bzero(dst, sizeof(*dst));
|
|
|
|
dst->si_signo = src->si_signo;
|
|
|
|
dst->si_errno = src->si_errno;
|
|
|
|
dst->si_code = src->si_code;
|
|
|
|
dst->si_pid = src->si_pid;
|
|
|
|
dst->si_uid = src->si_uid;
|
|
|
|
dst->si_status = src->si_status;
|
2008-11-10 23:36:20 +00:00
|
|
|
dst->si_addr = (uintptr_t)src->si_addr;
|
2006-10-05 01:56:11 +00:00
|
|
|
dst->si_value.sigval_int = src->si_value.sival_int;
|
|
|
|
dst->si_timerid = src->si_timerid;
|
|
|
|
dst->si_overrun = src->si_overrun;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
freebsd32_sigtimedwait(struct thread *td, struct freebsd32_sigtimedwait_args *uap)
|
|
|
|
{
|
|
|
|
struct timespec32 ts32;
|
|
|
|
struct timespec ts;
|
|
|
|
struct timespec *timeout;
|
|
|
|
sigset_t set;
|
|
|
|
ksiginfo_t ksi;
|
|
|
|
struct siginfo32 si32;
|
|
|
|
int error;
|
|
|
|
|
|
|
|
if (uap->timeout) {
|
|
|
|
error = copyin(uap->timeout, &ts32, sizeof(ts32));
|
|
|
|
if (error)
|
|
|
|
return (error);
|
|
|
|
ts.tv_sec = ts32.tv_sec;
|
|
|
|
ts.tv_nsec = ts32.tv_nsec;
|
|
|
|
timeout = &ts;
|
|
|
|
} else
|
|
|
|
timeout = NULL;
|
|
|
|
|
|
|
|
error = copyin(uap->set, &set, sizeof(set));
|
|
|
|
if (error)
|
|
|
|
return (error);
|
|
|
|
|
|
|
|
error = kern_sigtimedwait(td, set, &ksi, timeout);
|
|
|
|
if (error)
|
|
|
|
return (error);
|
|
|
|
|
|
|
|
if (uap->info) {
|
|
|
|
siginfo_to_siginfo32(&ksi.ksi_info, &si32);
|
|
|
|
error = copyout(&si32, uap->info, sizeof(struct siginfo32));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (error == 0)
|
|
|
|
td->td_retval[0] = ksi.ksi_signo;
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* MPSAFE
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
freebsd32_sigwaitinfo(struct thread *td, struct freebsd32_sigwaitinfo_args *uap)
|
|
|
|
{
|
|
|
|
ksiginfo_t ksi;
|
|
|
|
struct siginfo32 si32;
|
|
|
|
sigset_t set;
|
|
|
|
int error;
|
|
|
|
|
|
|
|
error = copyin(uap->set, &set, sizeof(set));
|
|
|
|
if (error)
|
|
|
|
return (error);
|
|
|
|
|
|
|
|
error = kern_sigtimedwait(td, set, &ksi, NULL);
|
|
|
|
if (error)
|
|
|
|
return (error);
|
|
|
|
|
|
|
|
if (uap->info) {
|
|
|
|
siginfo_to_siginfo32(&ksi.ksi_info, &si32);
|
|
|
|
error = copyout(&si32, uap->info, sizeof(struct siginfo32));
|
|
|
|
}
|
|
|
|
if (error == 0)
|
|
|
|
td->td_retval[0] = ksi.ksi_signo;
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
2008-07-10 17:45:57 +00:00
|
|
|
int
|
|
|
|
freebsd32_cpuset_setid(struct thread *td,
|
|
|
|
struct freebsd32_cpuset_setid_args *uap)
|
|
|
|
{
|
|
|
|
struct cpuset_setid_args ap;
|
|
|
|
|
|
|
|
ap.which = uap->which;
|
2010-03-11 14:49:06 +00:00
|
|
|
ap.id = PAIR32TO64(id_t,uap->id);
|
2008-07-10 17:45:57 +00:00
|
|
|
ap.setid = uap->setid;
|
|
|
|
|
2011-09-16 13:58:51 +00:00
|
|
|
return (sys_cpuset_setid(td, &ap));
|
2008-07-10 17:45:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
freebsd32_cpuset_getid(struct thread *td,
|
|
|
|
struct freebsd32_cpuset_getid_args *uap)
|
|
|
|
{
|
|
|
|
struct cpuset_getid_args ap;
|
|
|
|
|
|
|
|
ap.level = uap->level;
|
|
|
|
ap.which = uap->which;
|
2010-03-11 14:49:06 +00:00
|
|
|
ap.id = PAIR32TO64(id_t,uap->id);
|
2008-07-10 17:45:57 +00:00
|
|
|
ap.setid = uap->setid;
|
|
|
|
|
2011-09-16 13:58:51 +00:00
|
|
|
return (sys_cpuset_getid(td, &ap));
|
2008-07-10 17:45:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
freebsd32_cpuset_getaffinity(struct thread *td,
|
|
|
|
struct freebsd32_cpuset_getaffinity_args *uap)
|
|
|
|
{
|
|
|
|
struct cpuset_getaffinity_args ap;
|
|
|
|
|
|
|
|
ap.level = uap->level;
|
|
|
|
ap.which = uap->which;
|
2010-03-11 14:49:06 +00:00
|
|
|
ap.id = PAIR32TO64(id_t,uap->id);
|
2008-07-10 17:45:57 +00:00
|
|
|
ap.cpusetsize = uap->cpusetsize;
|
|
|
|
ap.mask = uap->mask;
|
|
|
|
|
2011-09-16 13:58:51 +00:00
|
|
|
return (sys_cpuset_getaffinity(td, &ap));
|
2008-07-10 17:45:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
freebsd32_cpuset_setaffinity(struct thread *td,
|
|
|
|
struct freebsd32_cpuset_setaffinity_args *uap)
|
|
|
|
{
|
|
|
|
struct cpuset_setaffinity_args ap;
|
|
|
|
|
|
|
|
ap.level = uap->level;
|
|
|
|
ap.which = uap->which;
|
2010-03-11 14:49:06 +00:00
|
|
|
ap.id = PAIR32TO64(id_t,uap->id);
|
2008-07-10 17:45:57 +00:00
|
|
|
ap.cpusetsize = uap->cpusetsize;
|
|
|
|
ap.mask = uap->mask;
|
|
|
|
|
2011-09-16 13:58:51 +00:00
|
|
|
return (sys_cpuset_setaffinity(td, &ap));
|
2008-07-10 17:45:57 +00:00
|
|
|
}
|
|
|
|
|
2008-09-19 15:17:32 +00:00
|
|
|
int
|
|
|
|
freebsd32_nmount(struct thread *td,
|
|
|
|
struct freebsd32_nmount_args /* {
|
|
|
|
struct iovec *iovp;
|
|
|
|
unsigned int iovcnt;
|
|
|
|
int flags;
|
|
|
|
} */ *uap)
|
|
|
|
{
|
|
|
|
struct uio *auio;
|
2012-01-17 01:08:01 +00:00
|
|
|
uint64_t flags;
|
2009-03-02 23:26:30 +00:00
|
|
|
int error;
|
2008-09-19 15:17:32 +00:00
|
|
|
|
2012-01-17 01:08:01 +00:00
|
|
|
/*
|
|
|
|
* Mount flags are now 64-bits. On 32-bit archtectures only
|
|
|
|
* 32-bits are passed in, but from here on everything handles
|
|
|
|
* 64-bit flags correctly.
|
|
|
|
*/
|
|
|
|
flags = uap->flags;
|
|
|
|
|
|
|
|
AUDIT_ARG_FFLAGS(flags);
|
2008-09-19 15:17:32 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Filter out MNT_ROOTFS. We do not want clients of nmount() in
|
|
|
|
* userspace to set this flag, but we must filter it out if we want
|
|
|
|
* MNT_UPDATE on the root file system to work.
|
2010-11-23 13:49:15 +00:00
|
|
|
* MNT_ROOTFS should only be set by the kernel when mounting its
|
|
|
|
* root file system.
|
2008-09-19 15:17:32 +00:00
|
|
|
*/
|
2012-01-17 01:08:01 +00:00
|
|
|
flags &= ~MNT_ROOTFS;
|
2008-09-19 15:17:32 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* check that we have an even number of iovec's
|
|
|
|
* and that we have at least two options.
|
|
|
|
*/
|
|
|
|
if ((uap->iovcnt & 1) || (uap->iovcnt < 4))
|
|
|
|
return (EINVAL);
|
2002-07-20 02:56:12 +00:00
|
|
|
|
2008-09-19 15:17:32 +00:00
|
|
|
error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
|
|
|
|
if (error)
|
|
|
|
return (error);
|
2012-01-17 01:08:01 +00:00
|
|
|
error = vfs_donmount(td, flags, auio);
|
2009-03-02 23:26:30 +00:00
|
|
|
|
2008-09-19 15:17:32 +00:00
|
|
|
free(auio, M_IOV);
|
|
|
|
return error;
|
|
|
|
}
|
|
|
|
|
|
|
|
#if 0
|
2002-07-20 02:56:12 +00:00
|
|
|
int
|
2003-08-22 23:07:28 +00:00
|
|
|
freebsd32_xxx(struct thread *td, struct freebsd32_xxx_args *uap)
|
2002-07-20 02:56:12 +00:00
|
|
|
{
|
|
|
|
struct yyy32 *p32, s32;
|
|
|
|
struct yyy *p = NULL, s;
|
2008-09-15 17:39:40 +00:00
|
|
|
struct xxx_arg ap;
|
|
|
|
int error;
|
2002-07-20 02:56:12 +00:00
|
|
|
|
2005-06-29 15:16:20 +00:00
|
|
|
if (uap->zzz) {
|
|
|
|
error = copyin(uap->zzz, &s32, sizeof(s32));
|
2002-07-20 02:56:12 +00:00
|
|
|
if (error)
|
|
|
|
return (error);
|
|
|
|
/* translate in */
|
2005-06-29 15:16:20 +00:00
|
|
|
p = &s;
|
2002-07-20 02:56:12 +00:00
|
|
|
}
|
2005-06-29 15:16:20 +00:00
|
|
|
error = kern_xxx(td, p);
|
2002-07-20 02:56:12 +00:00
|
|
|
if (error)
|
|
|
|
return (error);
|
2005-06-29 15:16:20 +00:00
|
|
|
if (uap->zzz) {
|
2002-07-20 02:56:12 +00:00
|
|
|
/* translate out */
|
|
|
|
error = copyout(&s32, p32, sizeof(s32));
|
|
|
|
}
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
#endif
|
2008-09-25 20:50:21 +00:00
|
|
|
|
|
|
|
int
|
|
|
|
syscall32_register(int *offset, struct sysent *new_sysent,
|
|
|
|
struct sysent *old_sysent)
|
|
|
|
{
|
|
|
|
if (*offset == NO_SYSCALL) {
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 1; i < SYS_MAXSYSCALL; ++i)
|
|
|
|
if (freebsd32_sysent[i].sy_call ==
|
|
|
|
(sy_call_t *)lkmnosys)
|
|
|
|
break;
|
|
|
|
if (i == SYS_MAXSYSCALL)
|
|
|
|
return (ENFILE);
|
|
|
|
*offset = i;
|
|
|
|
} else if (*offset < 0 || *offset >= SYS_MAXSYSCALL)
|
|
|
|
return (EINVAL);
|
|
|
|
else if (freebsd32_sysent[*offset].sy_call != (sy_call_t *)lkmnosys &&
|
|
|
|
freebsd32_sysent[*offset].sy_call != (sy_call_t *)lkmressys)
|
|
|
|
return (EEXIST);
|
|
|
|
|
|
|
|
*old_sysent = freebsd32_sysent[*offset];
|
|
|
|
freebsd32_sysent[*offset] = *new_sysent;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
syscall32_deregister(int *offset, struct sysent *old_sysent)
|
|
|
|
{
|
|
|
|
|
|
|
|
if (*offset)
|
|
|
|
freebsd32_sysent[*offset] = *old_sysent;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
syscall32_module_handler(struct module *mod, int what, void *arg)
|
|
|
|
{
|
|
|
|
struct syscall_module_data *data = (struct syscall_module_data*)arg;
|
|
|
|
modspecific_t ms;
|
|
|
|
int error;
|
|
|
|
|
|
|
|
switch (what) {
|
|
|
|
case MOD_LOAD:
|
|
|
|
error = syscall32_register(data->offset, data->new_sysent,
|
|
|
|
&data->old_sysent);
|
|
|
|
if (error) {
|
|
|
|
/* Leave a mark so we know to safely unload below. */
|
|
|
|
data->offset = NULL;
|
|
|
|
return error;
|
|
|
|
}
|
|
|
|
ms.intval = *data->offset;
|
|
|
|
MOD_XLOCK;
|
|
|
|
module_setspecific(mod, &ms);
|
|
|
|
MOD_XUNLOCK;
|
|
|
|
if (data->chainevh)
|
|
|
|
error = data->chainevh(mod, what, data->chainarg);
|
|
|
|
return (error);
|
|
|
|
case MOD_UNLOAD:
|
|
|
|
/*
|
|
|
|
* MOD_LOAD failed, so just return without calling the
|
|
|
|
* chained handler since we didn't pass along the MOD_LOAD
|
|
|
|
* event.
|
|
|
|
*/
|
|
|
|
if (data->offset == NULL)
|
|
|
|
return (0);
|
|
|
|
if (data->chainevh) {
|
|
|
|
error = data->chainevh(mod, what, data->chainarg);
|
|
|
|
if (error)
|
|
|
|
return (error);
|
|
|
|
}
|
2008-12-03 18:45:38 +00:00
|
|
|
error = syscall32_deregister(data->offset, &data->old_sysent);
|
2008-09-25 20:50:21 +00:00
|
|
|
return (error);
|
|
|
|
default:
|
|
|
|
error = EOPNOTSUPP;
|
|
|
|
if (data->chainevh)
|
|
|
|
error = data->chainevh(mod, what, data->chainarg);
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
}
|
2010-03-11 14:49:06 +00:00
|
|
|
|
2010-03-19 10:56:30 +00:00
|
|
|
int
|
|
|
|
syscall32_helper_register(struct syscall_helper_data *sd)
|
|
|
|
{
|
|
|
|
struct syscall_helper_data *sd1;
|
|
|
|
int error;
|
|
|
|
|
|
|
|
for (sd1 = sd; sd1->syscall_no != NO_SYSCALL; sd1++) {
|
|
|
|
error = syscall32_register(&sd1->syscall_no, &sd1->new_sysent,
|
|
|
|
&sd1->old_sysent);
|
|
|
|
if (error != 0) {
|
|
|
|
syscall32_helper_unregister(sd);
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
sd1->registered = 1;
|
|
|
|
}
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
syscall32_helper_unregister(struct syscall_helper_data *sd)
|
|
|
|
{
|
|
|
|
struct syscall_helper_data *sd1;
|
|
|
|
|
|
|
|
for (sd1 = sd; sd1->registered != 0; sd1++) {
|
|
|
|
syscall32_deregister(&sd1->syscall_no, &sd1->old_sysent);
|
|
|
|
sd1->registered = 0;
|
|
|
|
}
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
2010-03-11 14:49:06 +00:00
|
|
|
register_t *
|
|
|
|
freebsd32_copyout_strings(struct image_params *imgp)
|
|
|
|
{
|
2010-08-17 08:55:45 +00:00
|
|
|
int argc, envc, i;
|
2010-03-11 14:49:06 +00:00
|
|
|
u_int32_t *vectp;
|
|
|
|
char *stringp, *destp;
|
|
|
|
u_int32_t *stack_base;
|
|
|
|
struct freebsd32_ps_strings *arginfo;
|
2010-08-17 08:55:45 +00:00
|
|
|
char canary[sizeof(long) * 8];
|
|
|
|
int32_t pagesizes32[MAXPAGESIZES];
|
2010-03-11 14:49:06 +00:00
|
|
|
size_t execpath_len;
|
|
|
|
int szsigcode;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Calculate string base and vector table pointers.
|
|
|
|
* Also deal with signal trampoline code for this exec type.
|
|
|
|
*/
|
|
|
|
if (imgp->execpath != NULL && imgp->auxargs != NULL)
|
|
|
|
execpath_len = strlen(imgp->execpath) + 1;
|
|
|
|
else
|
|
|
|
execpath_len = 0;
|
2010-08-07 11:57:13 +00:00
|
|
|
arginfo = (struct freebsd32_ps_strings *)curproc->p_sysent->
|
|
|
|
sv_psstrings;
|
2011-01-08 16:13:44 +00:00
|
|
|
if (imgp->proc->p_sysent->sv_sigcode_base == 0)
|
|
|
|
szsigcode = *(imgp->proc->p_sysent->sv_szsigcode);
|
|
|
|
else
|
|
|
|
szsigcode = 0;
|
2010-03-11 14:49:06 +00:00
|
|
|
destp = (caddr_t)arginfo - szsigcode - SPARE_USRSPACE -
|
2010-08-17 08:55:45 +00:00
|
|
|
roundup(execpath_len, sizeof(char *)) -
|
|
|
|
roundup(sizeof(canary), sizeof(char *)) -
|
|
|
|
roundup(sizeof(pagesizes32), sizeof(char *)) -
|
|
|
|
roundup((ARG_MAX - imgp->args->stringspace), sizeof(char *));
|
2010-03-11 14:49:06 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* install sigcode
|
|
|
|
*/
|
2011-01-08 16:13:44 +00:00
|
|
|
if (szsigcode != 0)
|
2010-03-11 14:49:06 +00:00
|
|
|
copyout(imgp->proc->p_sysent->sv_sigcode,
|
|
|
|
((caddr_t)arginfo - szsigcode), szsigcode);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Copy the image path for the rtld.
|
|
|
|
*/
|
|
|
|
if (execpath_len != 0) {
|
|
|
|
imgp->execpathp = (uintptr_t)arginfo - szsigcode - execpath_len;
|
|
|
|
copyout(imgp->execpath, (void *)imgp->execpathp,
|
|
|
|
execpath_len);
|
|
|
|
}
|
|
|
|
|
2010-08-17 08:55:45 +00:00
|
|
|
/*
|
|
|
|
* Prepare the canary for SSP.
|
|
|
|
*/
|
|
|
|
arc4rand(canary, sizeof(canary), 0);
|
|
|
|
imgp->canary = (uintptr_t)arginfo - szsigcode - execpath_len -
|
|
|
|
sizeof(canary);
|
|
|
|
copyout(canary, (void *)imgp->canary, sizeof(canary));
|
|
|
|
imgp->canarylen = sizeof(canary);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Prepare the pagesizes array.
|
|
|
|
*/
|
|
|
|
for (i = 0; i < MAXPAGESIZES; i++)
|
|
|
|
pagesizes32[i] = (uint32_t)pagesizes[i];
|
|
|
|
imgp->pagesizes = (uintptr_t)arginfo - szsigcode - execpath_len -
|
|
|
|
roundup(sizeof(canary), sizeof(char *)) - sizeof(pagesizes32);
|
|
|
|
copyout(pagesizes32, (void *)imgp->pagesizes, sizeof(pagesizes32));
|
|
|
|
imgp->pagesizeslen = sizeof(pagesizes32);
|
|
|
|
|
2010-03-11 14:49:06 +00:00
|
|
|
/*
|
|
|
|
* If we have a valid auxargs ptr, prepare some room
|
|
|
|
* on the stack.
|
|
|
|
*/
|
|
|
|
if (imgp->auxargs) {
|
|
|
|
/*
|
|
|
|
* 'AT_COUNT*2' is size for the ELF Auxargs data. This is for
|
|
|
|
* lower compatibility.
|
|
|
|
*/
|
|
|
|
imgp->auxarg_size = (imgp->auxarg_size) ? imgp->auxarg_size
|
|
|
|
: (AT_COUNT * 2);
|
|
|
|
/*
|
|
|
|
* The '+ 2' is for the null pointers at the end of each of
|
|
|
|
* the arg and env vector sets,and imgp->auxarg_size is room
|
|
|
|
* for argument of Runtime loader.
|
|
|
|
*/
|
|
|
|
vectp = (u_int32_t *) (destp - (imgp->args->argc +
|
|
|
|
imgp->args->envc + 2 + imgp->auxarg_size + execpath_len) *
|
|
|
|
sizeof(u_int32_t));
|
|
|
|
} else
|
|
|
|
/*
|
|
|
|
* The '+ 2' is for the null pointers at the end of each of
|
|
|
|
* the arg and env vector sets
|
|
|
|
*/
|
|
|
|
vectp = (u_int32_t *)
|
|
|
|
(destp - (imgp->args->argc + imgp->args->envc + 2) * sizeof(u_int32_t));
|
|
|
|
|
|
|
|
/*
|
|
|
|
* vectp also becomes our initial stack base
|
|
|
|
*/
|
|
|
|
stack_base = vectp;
|
|
|
|
|
|
|
|
stringp = imgp->args->begin_argv;
|
|
|
|
argc = imgp->args->argc;
|
|
|
|
envc = imgp->args->envc;
|
|
|
|
/*
|
|
|
|
* Copy out strings - arguments and environment.
|
|
|
|
*/
|
|
|
|
copyout(stringp, destp, ARG_MAX - imgp->args->stringspace);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Fill in "ps_strings" struct for ps, w, etc.
|
|
|
|
*/
|
|
|
|
suword32(&arginfo->ps_argvstr, (u_int32_t)(intptr_t)vectp);
|
|
|
|
suword32(&arginfo->ps_nargvstr, argc);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Fill in argument portion of vector table.
|
|
|
|
*/
|
|
|
|
for (; argc > 0; --argc) {
|
|
|
|
suword32(vectp++, (u_int32_t)(intptr_t)destp);
|
|
|
|
while (*stringp++ != 0)
|
|
|
|
destp++;
|
|
|
|
destp++;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* a null vector table pointer separates the argp's from the envp's */
|
|
|
|
suword32(vectp++, 0);
|
|
|
|
|
|
|
|
suword32(&arginfo->ps_envstr, (u_int32_t)(intptr_t)vectp);
|
|
|
|
suword32(&arginfo->ps_nenvstr, envc);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Fill in environment portion of vector table.
|
|
|
|
*/
|
|
|
|
for (; envc > 0; --envc) {
|
|
|
|
suword32(vectp++, (u_int32_t)(intptr_t)destp);
|
|
|
|
while (*stringp++ != 0)
|
|
|
|
destp++;
|
|
|
|
destp++;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* end of vector table is a null pointer */
|
|
|
|
suword32(vectp, 0);
|
|
|
|
|
|
|
|
return ((register_t *)stack_base);
|
|
|
|
}
|
|
|
|
|
2011-03-30 14:46:12 +00:00
|
|
|
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));
|
|
|
|
}
|
2011-04-18 16:32:22 +00:00
|
|
|
|
|
|
|
int
|
|
|
|
freebsd32_posix_fallocate(struct thread *td,
|
|
|
|
struct freebsd32_posix_fallocate_args *uap)
|
|
|
|
{
|
|
|
|
|
2011-11-14 18:00:15 +00:00
|
|
|
return (kern_posix_fallocate(td, uap->fd,
|
|
|
|
PAIR32TO64(off_t, uap->offset), PAIR32TO64(off_t, uap->len)));
|
2011-04-18 16:32:22 +00:00
|
|
|
}
|
2011-11-04 04:02:50 +00:00
|
|
|
|
|
|
|
int
|
|
|
|
freebsd32_posix_fadvise(struct thread *td,
|
|
|
|
struct freebsd32_posix_fadvise_args *uap)
|
|
|
|
{
|
|
|
|
|
2011-11-14 18:00:15 +00:00
|
|
|
return (kern_posix_fadvise(td, uap->fd, PAIR32TO64(off_t, uap->offset),
|
|
|
|
PAIR32TO64(off_t, uap->len), uap->advice));
|
2011-11-04 04:02:50 +00:00
|
|
|
}
|