#include <errno.h>
#include <fcntl.h>
#include <dirent.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <unistd.h>
#include <thread.h>
#include <sys/auxv.h>
#include <sys/brand.h>
#include <sys/inttypes.h>
#include <sys/lwp.h>
#include <sys/syscall.h>
#include <sys/systm.h>
#include <sys/utsname.h>
#include <sys/sysconfig.h>
#include <sys/systeminfo.h>
#include <sys/zone.h>
#include <sys/stat.h>
#include <sys/mntent.h>
#include <sys/ctfs.h>
#include <sys/priv.h>
#include <sys/acctctl.h>
#include <libgen.h>
#include <bsm/audit.h>
#include <sys/crypto/ioctl.h>
#include <sys/fs/zfs.h>
#include <sys/zfs_ioctl.h>
#include <sys/ucontext.h>
#include <sys/mntio.h>
#include <sys/mnttab.h>
#include <sys/attr.h>
#include <sys/lofi.h>
#include <atomic.h>
#include <sys/acl.h>
#include <sys/socket.h>
#include <sys/fdsync.h>
#include <s10_brand.h>
#include <brand_misc.h>
#include <s10_misc.h>
#include <s10_signal.h>
static zoneid_t zoneid;
static boolean_t emul_global_zone = B_FALSE;
static s10_emul_bitmap_t emul_bitmap;
pid_t zone_init_pid;
#define S10_FEATURE_IS_PRESENT(s10_emulated_features_constant) \
((emul_bitmap[(s10_emulated_features_constant) >> 3] & \
(1 << ((s10_emulated_features_constant) & 0x7))) != 0)
brand_sysent_table_t brand_sysent_table[];
#define S10_UTS_RELEASE "5.10"
#define S10_UTS_VERSION "Generic_Virtual"
static int
passthru_otherdev_ioctl(dev_t *majordev, const char *devname, int *err,
sysret_t *rval, int fdes, int cmd, intptr_t arg)
{
struct stat sbuf;
if (*majordev == (dev_t)-1) {
if ((*err = __systemcall(rval, SYS_fstatat + 1024,
AT_FDCWD, devname, &sbuf, 0) != 0) != 0)
goto doioctl;
*majordev = major(sbuf.st_rdev);
}
if ((*err = __systemcall(rval, SYS_fstatat + 1024, fdes,
NULL, &sbuf, 0)) != 0)
goto doioctl;
if (major(sbuf.st_rdev) == *majordev)
return (0);
doioctl:
*err = (__systemcall(rval, SYS_ioctl + 1024, fdes, cmd, arg));
return (1);
}
static boolean_t
get_initpid_info(void)
{
pid_t pid;
sysret_t rval;
int err;
if ((err = __systemcall(&rval, SYS_brand,
B_S10_PIDINFO, &pid, &zone_init_pid)) != 0) {
brand_abort(err, "Failed to get init's pid");
}
if (pid == zone_init_pid)
return (B_TRUE);
return (B_FALSE);
}
static void
mntfs_free_mntentbuf(void *arg)
{
struct mntentbuf *embufp = arg;
if (embufp == NULL)
return;
if (embufp->mbuf_emp)
free(embufp->mbuf_emp);
if (embufp->mbuf_buf)
free(embufp->mbuf_buf);
bzero(embufp, sizeof (struct mntentbuf));
free(embufp);
}
static struct mntentbuf *
mntfs_get_mntentbuf(size_t size)
{
static mutex_t keylock;
static thread_key_t key;
static int once_per_keyname = 0;
void *tsd = NULL;
struct mntentbuf *embufp;
if (!once_per_keyname) {
(void) mutex_lock(&keylock);
if (!once_per_keyname) {
if (thr_keycreate(&key, mntfs_free_mntentbuf)) {
(void) mutex_unlock(&keylock);
return (NULL);
} else {
once_per_keyname++;
}
}
(void) mutex_unlock(&keylock);
}
if (thr_getspecific(key, &tsd))
return (NULL);
if (tsd == NULL) {
if (!(embufp = calloc(1, sizeof (struct mntentbuf))) ||
!(embufp->mbuf_emp = malloc(sizeof (struct extmnttab))) ||
thr_setspecific(key, embufp)) {
mntfs_free_mntentbuf(embufp);
return (NULL);
}
} else {
embufp = tsd;
}
if (size > embufp->mbuf_bufsize) {
if (embufp->mbuf_buf)
free(embufp->mbuf_buf);
if ((embufp->mbuf_buf = malloc(size)) == NULL) {
embufp->mbuf_bufsize = 0;
return (NULL);
} else {
embufp->mbuf_bufsize = size;
}
}
return (embufp);
}
int
mntfs_ioctl(sysret_t *rval, int fdes, int cmd, intptr_t arg)
{
int err;
struct stat statbuf;
struct mntentbuf *embufp;
static size_t bufsize = MNT_LINE_MAX;
if (S10_FEATURE_IS_PRESENT(S10_FEATURE_ALTERED_MNTFS_IOCTL))
return (__systemcall(rval, SYS_ioctl + 1024, fdes, cmd, arg));
if ((err = __systemcall(rval, SYS_fstatat + 1024,
fdes, NULL, &statbuf, 0)) != 0)
return (err);
if (strcmp(statbuf.st_fstype, MNTTYPE_MNTFS) != 0)
return (__systemcall(rval, SYS_ioctl + 1024, fdes, cmd, arg));
if (cmd == MNTIOC_GETEXTMNTENT || cmd == MNTIOC_GETMNTANY)
return (EINVAL);
if ((embufp = mntfs_get_mntentbuf(bufsize)) == NULL)
return (ENOMEM);
if (brand_uucopy(&embufp->mbuf_emp, (void *)arg, sizeof (void *)) != 0)
return (EFAULT);
for (;;) {
if ((err = __systemcall(rval, SYS_ioctl + 1024, fdes,
MNTIOC_GETEXTMNTENT, embufp)) != 0)
return (err);
if (rval->sys_rval1 == MNTFS_TOOLONG) {
(void) atomic_swap_ulong((unsigned long *)&bufsize,
2 * embufp->mbuf_bufsize);
if ((embufp = mntfs_get_mntentbuf(bufsize)) == NULL)
return (ENOMEM);
} else {
break;
}
}
if (brand_uucopy(&embufp->mbuf_emp, (void *)arg, sizeof (void *)) != 0)
return (EFAULT);
return (0);
}
#define struct_assign(d, s, val) (((d).val) = ((s).val))
typedef struct s10_crypto_function_list {
boolean_t fl_digest_init;
boolean_t fl_digest;
boolean_t fl_digest_update;
boolean_t fl_digest_key;
boolean_t fl_digest_final;
boolean_t fl_encrypt_init;
boolean_t fl_encrypt;
boolean_t fl_encrypt_update;
boolean_t fl_encrypt_final;
boolean_t fl_decrypt_init;
boolean_t fl_decrypt;
boolean_t fl_decrypt_update;
boolean_t fl_decrypt_final;
boolean_t fl_mac_init;
boolean_t fl_mac;
boolean_t fl_mac_update;
boolean_t fl_mac_final;
boolean_t fl_sign_init;
boolean_t fl_sign;
boolean_t fl_sign_update;
boolean_t fl_sign_final;
boolean_t fl_sign_recover_init;
boolean_t fl_sign_recover;
boolean_t fl_verify_init;
boolean_t fl_verify;
boolean_t fl_verify_update;
boolean_t fl_verify_final;
boolean_t fl_verify_recover_init;
boolean_t fl_verify_recover;
boolean_t fl_digest_encrypt_update;
boolean_t fl_decrypt_digest_update;
boolean_t fl_sign_encrypt_update;
boolean_t fl_decrypt_verify_update;
boolean_t fl_seed_random;
boolean_t fl_generate_random;
boolean_t fl_session_open;
boolean_t fl_session_close;
boolean_t fl_session_login;
boolean_t fl_session_logout;
boolean_t fl_object_create;
boolean_t fl_object_copy;
boolean_t fl_object_destroy;
boolean_t fl_object_get_size;
boolean_t fl_object_get_attribute_value;
boolean_t fl_object_set_attribute_value;
boolean_t fl_object_find_init;
boolean_t fl_object_find;
boolean_t fl_object_find_final;
boolean_t fl_key_generate;
boolean_t fl_key_generate_pair;
boolean_t fl_key_wrap;
boolean_t fl_key_unwrap;
boolean_t fl_key_derive;
boolean_t fl_init_token;
boolean_t fl_init_pin;
boolean_t fl_set_pin;
boolean_t prov_is_hash_limited;
uint32_t prov_hash_threshold;
uint32_t prov_hash_limit;
} s10_crypto_function_list_t;
typedef struct s10_crypto_get_function_list {
uint_t fl_return_value;
crypto_provider_id_t fl_provider_id;
s10_crypto_function_list_t fl_list;
} s10_crypto_get_function_list_t;
static int
crypto_ioctl(sysret_t *rval, int fdes, int cmd, intptr_t arg)
{
int err;
s10_crypto_get_function_list_t s10_param;
crypto_get_function_list_t native_param;
static dev_t crypto_dev = (dev_t)-1;
if (passthru_otherdev_ioctl(&crypto_dev, "/dev/crypto", &err,
rval, fdes, cmd, arg) == 1)
return (err);
if (brand_uucopy((const void *)arg, &s10_param, sizeof (s10_param))
!= 0)
return (EFAULT);
struct_assign(native_param, s10_param, fl_provider_id);
if ((err = __systemcall(rval, SYS_ioctl + 1024, fdes, cmd,
&native_param)) != 0)
return (err);
struct_assign(s10_param, native_param, fl_return_value);
struct_assign(s10_param, native_param, fl_provider_id);
struct_assign(s10_param, native_param, fl_list.fl_digest_init);
struct_assign(s10_param, native_param, fl_list.fl_digest);
struct_assign(s10_param, native_param, fl_list.fl_digest_update);
struct_assign(s10_param, native_param, fl_list.fl_digest_key);
struct_assign(s10_param, native_param, fl_list.fl_digest_final);
struct_assign(s10_param, native_param, fl_list.fl_encrypt_init);
struct_assign(s10_param, native_param, fl_list.fl_encrypt);
struct_assign(s10_param, native_param, fl_list.fl_encrypt_update);
struct_assign(s10_param, native_param, fl_list.fl_encrypt_final);
struct_assign(s10_param, native_param, fl_list.fl_decrypt_init);
struct_assign(s10_param, native_param, fl_list.fl_decrypt);
struct_assign(s10_param, native_param, fl_list.fl_decrypt_update);
struct_assign(s10_param, native_param, fl_list.fl_decrypt_final);
struct_assign(s10_param, native_param, fl_list.fl_mac_init);
struct_assign(s10_param, native_param, fl_list.fl_mac);
struct_assign(s10_param, native_param, fl_list.fl_mac_update);
struct_assign(s10_param, native_param, fl_list.fl_mac_final);
struct_assign(s10_param, native_param, fl_list.fl_sign_init);
struct_assign(s10_param, native_param, fl_list.fl_sign);
struct_assign(s10_param, native_param, fl_list.fl_sign_update);
struct_assign(s10_param, native_param, fl_list.fl_sign_final);
struct_assign(s10_param, native_param, fl_list.fl_sign_recover_init);
struct_assign(s10_param, native_param, fl_list.fl_sign_recover);
struct_assign(s10_param, native_param, fl_list.fl_verify_init);
struct_assign(s10_param, native_param, fl_list.fl_verify);
struct_assign(s10_param, native_param, fl_list.fl_verify_update);
struct_assign(s10_param, native_param, fl_list.fl_verify_final);
struct_assign(s10_param, native_param, fl_list.fl_verify_recover_init);
struct_assign(s10_param, native_param, fl_list.fl_verify_recover);
struct_assign(s10_param, native_param,
fl_list.fl_digest_encrypt_update);
struct_assign(s10_param, native_param,
fl_list.fl_decrypt_digest_update);
struct_assign(s10_param, native_param, fl_list.fl_sign_encrypt_update);
struct_assign(s10_param, native_param,
fl_list.fl_decrypt_verify_update);
struct_assign(s10_param, native_param, fl_list.fl_seed_random);
struct_assign(s10_param, native_param, fl_list.fl_generate_random);
struct_assign(s10_param, native_param, fl_list.fl_session_open);
struct_assign(s10_param, native_param, fl_list.fl_session_close);
struct_assign(s10_param, native_param, fl_list.fl_session_login);
struct_assign(s10_param, native_param, fl_list.fl_session_logout);
struct_assign(s10_param, native_param, fl_list.fl_object_create);
struct_assign(s10_param, native_param, fl_list.fl_object_copy);
struct_assign(s10_param, native_param, fl_list.fl_object_destroy);
struct_assign(s10_param, native_param, fl_list.fl_object_get_size);
struct_assign(s10_param, native_param,
fl_list.fl_object_get_attribute_value);
struct_assign(s10_param, native_param,
fl_list.fl_object_set_attribute_value);
struct_assign(s10_param, native_param, fl_list.fl_object_find_init);
struct_assign(s10_param, native_param, fl_list.fl_object_find);
struct_assign(s10_param, native_param, fl_list.fl_object_find_final);
struct_assign(s10_param, native_param, fl_list.fl_key_generate);
struct_assign(s10_param, native_param, fl_list.fl_key_generate_pair);
struct_assign(s10_param, native_param, fl_list.fl_key_wrap);
struct_assign(s10_param, native_param, fl_list.fl_key_unwrap);
struct_assign(s10_param, native_param, fl_list.fl_key_derive);
struct_assign(s10_param, native_param, fl_list.fl_init_token);
struct_assign(s10_param, native_param, fl_list.fl_init_pin);
struct_assign(s10_param, native_param, fl_list.fl_set_pin);
struct_assign(s10_param, native_param, fl_list.prov_is_hash_limited);
struct_assign(s10_param, native_param, fl_list.prov_hash_threshold);
struct_assign(s10_param, native_param, fl_list.prov_hash_limit);
return (brand_uucopy(&s10_param, (void *)arg, sizeof (s10_param)));
}
typedef struct s10_ct_param {
uint32_t ctpm_id;
uint32_t ctpm_pad;
uint64_t ctpm_value;
} s10_ct_param_t;
static int
ctfs_ioctl(sysret_t *rval, int fdes, int cmd, intptr_t arg)
{
int err;
s10_ct_param_t s10param;
ct_param_t param;
struct stat statbuf;
if ((err = __systemcall(rval, SYS_fstatat + 1024,
fdes, NULL, &statbuf, 0)) != 0)
return (err);
if (strcmp(statbuf.st_fstype, MNTTYPE_CTFS) != 0)
return (__systemcall(rval, SYS_ioctl + 1024, fdes, cmd, arg));
if (brand_uucopy((const void *)arg, &s10param, sizeof (s10param)) != 0)
return (EFAULT);
param.ctpm_id = s10param.ctpm_id;
param.ctpm_size = sizeof (uint64_t);
param.ctpm_value = &s10param.ctpm_value;
if ((err = __systemcall(rval, SYS_ioctl + 1024, fdes, cmd, ¶m))
!= 0)
return (err);
if (cmd == CT_TGET)
return (brand_uucopy(&s10param, (void *)arg,
sizeof (s10param)));
return (0);
}
static int
zfs_ioctl(sysret_t *rval, int fdes, int cmd, intptr_t arg)
{
static dev_t zfs_dev = (dev_t)-1;
int err;
if (passthru_otherdev_ioctl(&zfs_dev, ZFS_DEV, &err,
rval, fdes, cmd, arg) == 1)
return (err);
brand_abort(0, "ZFS ioctl!");
return (0);
}
struct s10_lofi_ioctl {
uint32_t li_id;
boolean_t li_force;
char li_filename[MAXPATHLEN + 1];
};
static int
lofi_ioctl(sysret_t *rval, int fdes, int cmd, intptr_t arg)
{
static dev_t lofi_dev = (dev_t)-1;
struct s10_lofi_ioctl s10_param;
struct lofi_ioctl native_param;
int err;
if (passthru_otherdev_ioctl(&lofi_dev, "/dev/lofictl", &err,
rval, fdes, cmd, arg) == 1)
return (err);
if (brand_uucopy((const void *)arg, &s10_param,
sizeof (s10_param)) != 0)
return (EFAULT);
if (cmd >= LOFI_CHECK_COMPRESSED)
return (EIO);
bzero(&native_param, sizeof (native_param));
struct_assign(native_param, s10_param, li_id);
struct_assign(native_param, s10_param, li_force);
bcopy(s10_param.li_filename, native_param.li_filename,
sizeof (native_param.li_filename));
native_param.li_filename[MAXPATHLEN - 1] = '\0';
err = __systemcall(rval, SYS_ioctl + 1024, fdes, cmd, &native_param);
struct_assign(s10_param, native_param, li_id);
bcopy(native_param.li_filename, s10_param.li_filename,
sizeof (native_param.li_filename));
(void) brand_uucopy(&s10_param, (void *)arg, sizeof (s10_param));
return (err);
}
int
s10_ioctl(sysret_t *rval, int fdes, int cmd, intptr_t arg)
{
switch (cmd) {
case CRYPTO_GET_FUNCTION_LIST:
return (crypto_ioctl(rval, fdes, cmd, arg));
case CT_TGET:
case CT_TSET:
return (ctfs_ioctl(rval, fdes, cmd, arg));
case MNTIOC_GETMNTENT:
case MNTIOC_GETEXTMNTENT:
case MNTIOC_GETMNTANY:
return (mntfs_ioctl(rval, fdes, cmd, arg));
}
switch (cmd & ~0xff) {
case ZFS_IOC:
return (zfs_ioctl(rval, fdes, cmd, arg));
case LOFI_IOC_BASE:
return (lofi_ioctl(rval, fdes, cmd, arg));
default:
break;
}
return (__systemcall(rval, SYS_ioctl + 1024, fdes, cmd, arg));
}
static int
s10_pwrite(sysret_t *rval, int fd, const void *bufferp, size_t num_bytes,
off_t offset)
{
int err;
if ((err = __systemcall(rval, SYS_fcntl + 1024, fd, F_GETFL, 0, 0)) !=
0) {
return (err);
}
if (rval->sys_rval1 & O_APPEND)
return (__systemcall(rval, SYS_write + 1024, fd, bufferp,
num_bytes));
return (__systemcall(rval, SYS_pwrite + 1024, fd, bufferp, num_bytes,
offset));
}
#if !defined(_LP64)
static int
s10_pwrite64(sysret_t *rval, int fd, const void *bufferp, size32_t num_bytes,
uint32_t offset_1, uint32_t offset_2)
{
int err;
if ((err = __systemcall(rval, SYS_fcntl + 1024, fd, F_GETFL, 0, 0)) !=
0) {
return (err);
}
if (rval->sys_rval1 & O_APPEND)
return (__systemcall(rval, SYS_write + 1024, fd, bufferp,
num_bytes));
return (__systemcall(rval, SYS_pwrite64 + 1024, fd, bufferp,
num_bytes, offset_1, offset_2));
}
#endif
#define dirent_name(charptr) ((charptr) + name_offset)
#define dirent_reclen(charptr) \
(*(unsigned short *)(uintptr_t)((charptr) + reclen_offset))
static int
s10_getdents_common(sysret_t *rval, int fd, char *buf, size_t nbyte,
int getdents_syscall_id, size_t name_offset, size_t reclen_offset)
{
int err;
size_t buf_size;
char *local_buf;
char *buf_current;
if ((err = __systemcall(rval, SYS_brand + 1024, B_S10_ISFDXATTRDIR,
fd)) != 0)
return (err);
if (rval->sys_rval1 == 0)
return (__systemcall(rval, getdents_syscall_id + 1024, fd, buf,
nbyte));
if (nbyte > MAXGETDENTS_SIZE)
nbyte = MAXGETDENTS_SIZE;
local_buf = (char *)malloc(nbyte);
if (local_buf == NULL) {
(void) B_TRUSS_POINT_3(rval, getdents_syscall_id, ENOMEM, fd,
buf, nbyte);
rval->sys_rval1 = -1;
rval->sys_rval2 = 0;
return (EIO);
}
if ((err = __systemcall(rval, getdents_syscall_id + 1024, fd, local_buf,
nbyte)) != 0) {
free(local_buf);
return (err);
}
buf_size = rval->sys_rval1;
if (buf_size == 0) {
free(local_buf);
return (0);
}
for (buf_current = local_buf;
(size_t)(buf_current - local_buf) < buf_size; ) {
if (strcmp(dirent_name(buf_current), VIEW_READONLY) != 0 &&
strcmp(dirent_name(buf_current), VIEW_READWRITE) != 0) {
buf_current += dirent_reclen(buf_current);
} else {
buf_size -= dirent_reclen(buf_current);
(void) memmove(buf_current, buf_current +
dirent_reclen(buf_current), buf_size -
(size_t)(buf_current - local_buf));
}
}
if ((err = brand_uucopy(local_buf, buf, buf_size)) != 0) {
free(local_buf);
rval->sys_rval1 = -1;
rval->sys_rval2 = 0;
return (err);
}
rval->sys_rval1 = buf_size;
free(local_buf);
return (0);
}
static int
s10_getdents(sysret_t *rval, int fd, struct dirent *buf, size_t nbyte)
{
return (s10_getdents_common(rval, fd, (char *)buf, nbyte, SYS_getdents,
offsetof(struct dirent, d_name),
offsetof(struct dirent, d_reclen)));
}
#ifndef _LP64
static int
s10_getdents64(sysret_t *rval, int fd, struct dirent64 *buf, size_t nbyte)
{
return (s10_getdents_common(rval, fd, (char *)buf, nbyte,
SYS_getdents64, offsetof(struct dirent64, d_name),
offsetof(struct dirent64, d_reclen)));
}
#endif
#define S10_TRIVIAL_ACL_CNT 6
#define NATIVE_TRIVIAL_ACL_CNT 3
static boolean_t
has_trivial_native_acl(int cmd, int cnt, const char *fname, int fd)
{
int i, err;
sysret_t rval;
ace_t buf[NATIVE_TRIVIAL_ACL_CNT];
if (fname != NULL)
err = __systemcall(&rval, SYS_pathconf + 1024, fname,
_PC_ACL_ENABLED);
else
err = __systemcall(&rval, SYS_fpathconf + 1024, fd,
_PC_ACL_ENABLED);
if (err != 0 || rval.sys_rval1 != _ACL_ACE_ENABLED)
return (B_FALSE);
if (cmd != ACE_GETACLCNT) {
if (fname != NULL) {
if (__systemcall(&rval, SYS_acl + 1024, fname,
ACE_GETACLCNT, 0, NULL) != 0)
return (B_FALSE);
} else {
if (__systemcall(&rval, SYS_facl + 1024, fd,
ACE_GETACLCNT, 0, NULL) != 0)
return (B_FALSE);
}
cnt = rval.sys_rval1;
}
if (cnt != NATIVE_TRIVIAL_ACL_CNT)
return (B_FALSE);
if (fname != NULL) {
if (__systemcall(&rval, SYS_acl + 1024, fname, ACE_GETACL, cnt,
buf) != 0)
return (B_FALSE);
} else {
if (__systemcall(&rval, SYS_facl + 1024, fd, ACE_GETACL, cnt,
buf) != 0)
return (B_FALSE);
}
for (i = 0; i < cnt; i++) {
switch (buf[i].a_flags & ACE_TYPE_FLAGS) {
case ACE_OWNER:
case ACE_GROUP|ACE_IDENTIFIER_GROUP:
case ACE_EVERYONE:
break;
default:
return (B_FALSE);
}
if (buf[i].a_flags & (ACE_FILE_INHERIT_ACE|
ACE_DIRECTORY_INHERIT_ACE|ACE_NO_PROPAGATE_INHERIT_ACE|
ACE_INHERIT_ONLY_ACE))
return (B_FALSE);
if (buf[i].a_access_mask & (ACE_READ_ACL|ACE_READ_ATTRIBUTES) &&
buf[i].a_type == ACE_ACCESS_DENIED_ACE_TYPE)
return (B_FALSE);
if (buf[i].a_access_mask & (ACE_DELETE|ACE_DELETE_CHILD))
return (B_FALSE);
if (buf[i].a_type == ACE_ACCESS_ALLOWED_ACE_TYPE &&
(!(buf[i].a_flags & ACE_OWNER) && (buf[i].a_access_mask &
(ACE_WRITE_OWNER|ACE_WRITE_ACL| ACE_WRITE_ATTRIBUTES|
ACE_WRITE_NAMED_ATTRS))))
return (B_FALSE);
}
return (B_TRUE);
}
static void
s10_adjust_ace_mask(void *pair, size_t access_off, size_t pairsize, mode_t mode)
{
char *datap = (char *)pair;
uint32_t *amask0 = (uint32_t *)(uintptr_t)(datap + access_off);
uint32_t *amask1 = (uint32_t *)(uintptr_t)(datap + pairsize +
access_off);
if (mode & S_IROTH)
*amask1 |= ACE_READ_DATA;
else
*amask0 |= ACE_READ_DATA;
if (mode & S_IWOTH)
*amask1 |= ACE_WRITE_DATA|ACE_APPEND_DATA;
else
*amask0 |= ACE_WRITE_DATA|ACE_APPEND_DATA;
if (mode & S_IXOTH)
*amask1 |= ACE_EXECUTE;
else
*amask0 |= ACE_EXECUTE;
}
static int
make_trivial_s10_acl(const char *fname, int fd, ace_t *bp)
{
int err;
sysret_t rval;
struct stat64 buf;
ace_t trivial_s10_acl[] = {
{(uint_t)-1, 0, ACE_OWNER, ACE_ACCESS_DENIED_ACE_TYPE},
{(uint_t)-1, ACE_WRITE_ACL|ACE_WRITE_OWNER|ACE_WRITE_ATTRIBUTES|
ACE_WRITE_NAMED_ATTRS, ACE_OWNER,
ACE_ACCESS_ALLOWED_ACE_TYPE},
{(uint_t)-1, 0, ACE_GROUP|ACE_IDENTIFIER_GROUP,
ACE_ACCESS_DENIED_ACE_TYPE},
{(uint_t)-1, 0, ACE_GROUP|ACE_IDENTIFIER_GROUP,
ACE_ACCESS_ALLOWED_ACE_TYPE},
{(uint_t)-1, ACE_WRITE_ACL|ACE_WRITE_OWNER|ACE_WRITE_ATTRIBUTES|
ACE_WRITE_NAMED_ATTRS, ACE_EVERYONE,
ACE_ACCESS_DENIED_ACE_TYPE},
{(uint_t)-1, ACE_READ_ACL|ACE_READ_ATTRIBUTES|
ACE_READ_NAMED_ATTRS|ACE_SYNCHRONIZE, ACE_EVERYONE,
ACE_ACCESS_ALLOWED_ACE_TYPE}
};
if (fname != NULL) {
if ((err = __systemcall(&rval, SYS_fstatat64 + 1024, AT_FDCWD,
fname, &buf, 0)) != 0)
return (err);
} else {
if ((err = __systemcall(&rval, SYS_fstatat64 + 1024, fd,
NULL, &buf, 0)) != 0)
return (err);
}
s10_adjust_ace_mask(&trivial_s10_acl[0], offsetof(ace_t, a_access_mask),
sizeof (ace_t), (buf.st_mode & 0700) >> 6);
s10_adjust_ace_mask(&trivial_s10_acl[2], offsetof(ace_t, a_access_mask),
sizeof (ace_t), (buf.st_mode & 0070) >> 3);
s10_adjust_ace_mask(&trivial_s10_acl[4], offsetof(ace_t, a_access_mask),
sizeof (ace_t), buf.st_mode & 0007);
if (brand_uucopy(&trivial_s10_acl, bp, sizeof (trivial_s10_acl)) != 0)
return (EFAULT);
return (0);
}
int
s10_acl(sysret_t *rval, const char *fname, int cmd, int nentries, void *aclbufp)
{
int res;
res = __systemcall(rval, SYS_acl + 1024, fname, cmd, nentries, aclbufp);
switch (cmd) {
case ACE_GETACLCNT:
if (res == 0 && has_trivial_native_acl(ACE_GETACLCNT,
rval->sys_rval1, fname, 0)) {
rval->sys_rval1 = S10_TRIVIAL_ACL_CNT;
}
break;
case ACE_GETACL:
if (res == 0 &&
has_trivial_native_acl(ACE_GETACL, 0, fname, 0) &&
nentries >= S10_TRIVIAL_ACL_CNT) {
res = make_trivial_s10_acl(fname, 0, aclbufp);
rval->sys_rval1 = S10_TRIVIAL_ACL_CNT;
}
break;
}
return (res);
}
int
s10_facl(sysret_t *rval, int fdes, int cmd, int nentries, void *aclbufp)
{
int res;
res = __systemcall(rval, SYS_facl + 1024, fdes, cmd, nentries, aclbufp);
switch (cmd) {
case ACE_GETACLCNT:
if (res == 0 && has_trivial_native_acl(ACE_GETACLCNT,
rval->sys_rval1, NULL, fdes)) {
rval->sys_rval1 = S10_TRIVIAL_ACL_CNT;
}
break;
case ACE_GETACL:
if (res == 0 &&
has_trivial_native_acl(ACE_GETACL, 0, NULL, fdes) &&
nentries >= S10_TRIVIAL_ACL_CNT) {
res = make_trivial_s10_acl(NULL, fdes, aclbufp);
rval->sys_rval1 = S10_TRIVIAL_ACL_CNT;
}
break;
}
return (res);
}
#define S10_AC_PROC (0x1 << 28)
#define S10_AC_TASK (0x2 << 28)
#define S10_AC_FLOW (0x4 << 28)
#define S10_AC_MODE(x) ((x) & 0xf0000000)
#define S10_AC_OPTION(x) ((x) & 0x0fffffff)
int
s10_acctctl(sysret_t *rval, int cmd, void *buf, size_t bufsz)
{
int mode = S10_AC_MODE(cmd);
int option = S10_AC_OPTION(cmd);
switch (mode) {
case S10_AC_PROC:
mode = AC_PROC;
break;
case S10_AC_TASK:
mode = AC_TASK;
break;
case S10_AC_FLOW:
mode = AC_FLOW;
break;
default:
return (B_TRUSS_POINT_3(rval, SYS_acctctl, EINVAL, cmd, buf,
bufsz));
}
return (__systemcall(rval, SYS_acctctl + 1024, mode | option, buf,
bufsz));
}
#define S10_AUDIT_HMASK 0xffffffc0
#define S10_AUDIT_LMASK 0x3f
#define S10_AUC_NOSPACE 0x3
int
s10_auditsys(sysret_t *rval, int bsmcmd, intptr_t a0, intptr_t a1, intptr_t a2)
{
int err;
uint32_t m;
if (bsmcmd != BSM_AUDITCTL)
return (__systemcall(rval, SYS_auditsys + 1024, bsmcmd, a0, a1,
a2));
if ((int)a0 == A_GETPOLICY) {
if ((err = __systemcall(rval, SYS_auditsys + 1024, bsmcmd, a0,
&m, a2)) != 0)
return (err);
m = ((m & S10_AUDIT_HMASK) << 1) | (m & S10_AUDIT_LMASK);
if (brand_uucopy(&m, (void *)a1, sizeof (m)) != 0)
return (EFAULT);
return (0);
} else if ((int)a0 == A_SETPOLICY) {
if (brand_uucopy((const void *)a1, &m, sizeof (m)) != 0)
return (EFAULT);
m = ((m >> 1) & S10_AUDIT_HMASK) | (m & S10_AUDIT_LMASK);
return (__systemcall(rval, SYS_auditsys + 1024, bsmcmd, a0, &m,
a2));
} else if ((int)a0 == A_GETCOND) {
if ((err = __systemcall(rval, SYS_auditsys + 1024, bsmcmd, a0,
&m, a2)) != 0)
return (err);
if (m == AUC_NOSPACE)
m = S10_AUC_NOSPACE;
if (brand_uucopy(&m, (void *)a1, sizeof (m)) != 0)
return (EFAULT);
return (0);
} else if ((int)a0 == A_SETCOND) {
if (brand_uucopy((const void *)a1, &m, sizeof (m)) != 0)
return (EFAULT);
if (m == S10_AUC_NOSPACE)
m = AUC_NOSPACE;
return (__systemcall(rval, SYS_auditsys + 1024, bsmcmd, a0, &m,
a2));
}
return (__systemcall(rval, SYS_auditsys + 1024, bsmcmd, a0, a1, a2));
}
static int
s10_exec_native(sysret_t *rval, const char *fname, const char **argp,
const char **envp)
{
const char *filename = fname;
char path[64];
int err;
path[0] = '\0';
(void) brand_uucopystr(filename, path, sizeof (path));
if (strncmp(path, "/.SUNWnative/usr/lib/brand/solaris10/s10_native",
sizeof (path)) != 0)
return (0);
argp++;
if (brand_uucopy(argp, &filename, sizeof (char *)) != 0)
return (EFAULT);
err = __systemcall(rval, SYS_brand + 1024, B_EXEC_NATIVE, filename,
argp, envp, NULL, NULL, NULL);
brand_assert(err != 0);
return (err);
}
int
s10_exec(sysret_t *rval, const char *fname, const char **argp)
{
int err;
if ((err = s10_exec_native(rval, fname, argp, NULL)) != 0)
return (err);
err = __systemcall(rval, SYS_execve + 1024, fname, argp, NULL, 0);
brand_assert(err != 0);
return (err);
}
int
s10_execve(sysret_t *rval, const char *fname, const char **argp,
const char **envp)
{
int err;
if ((err = s10_exec_native(rval, fname, argp, envp)) != 0)
return (err);
err = __systemcall(rval, SYS_execve + 1024, fname, argp, envp, 0);
brand_assert(err != 0);
return (err);
}
int
s10_fcntl(sysret_t *rval, int fd, int cmd, intptr_t arg)
{
return (__systemcall(rval, SYS_fcntl + 1024, fd, cmd, arg, 0));
}
static int
s10_fdsync(sysret_t *rval, int fd, int flag)
{
uint32_t level;
if ((flag & FSYNC) != 0) {
level = FDSYNC_FILE;
} else if ((flag & FDSYNC) != 0) {
level = FDSYNC_DATA;
} else {
level = FDSYNC_FILE;
}
return (__systemcall(rval, SYS_fdsync + 1024, fd, level));
}
static int
s10_issetugid(sysret_t *rval)
{
return (__systemcall(rval, SYS_privsys + 1024, PRIVSYS_ISSETUGID,
0, 0, 0, 0, 0));
}
static int
s10_so_socket(sysret_t *rval, int domain, int type, int protocol,
char *devpath, int version)
{
if ((type & ~SOCK_TYPE_MASK) != 0) {
errno = EINVAL;
return (-1);
}
return (__systemcall(rval, SYS_so_socket + 1024, domain, type,
protocol, devpath, version));
}
static int
s10_pipe(sysret_t *rval)
{
int fds[2], err;
if ((err = __systemcall(rval, SYS_pipe + 1024, fds, 0)) != 0)
return (err);
rval->sys_rval1 = fds[0];
rval->sys_rval2 = fds[1];
return (0);
}
static int
s10_accept(sysret_t *rval, int sock, struct sockaddr *addr, uint_t *addrlen,
int version)
{
return (__systemcall(rval, SYS_accept + 1024, sock, addr, addrlen,
version, 0));
}
static long
s10_uname(sysret_t *rv, uintptr_t p1)
{
struct utsname un, *unp = (struct utsname *)p1;
int rev, err;
if ((err = __systemcall(rv, SYS_uname + 1024, &un)) != 0)
return (err);
rev = atoi(&un.release[2]);
brand_assert(rev >= 11);
bzero(un.release, _SYS_NMLN);
(void) strlcpy(un.release, S10_UTS_RELEASE, _SYS_NMLN);
bzero(un.version, _SYS_NMLN);
(void) strlcpy(un.version, S10_UTS_VERSION, _SYS_NMLN);
return (brand_uucopy(&un, unp, sizeof (un)));
}
int
s10_sysconfig(sysret_t *rv, int which)
{
long value;
switch (which) {
case _CONFIG_RTSIG_MAX:
value = S10_SIGRTMAX - S10_SIGRTMIN + 1;
break;
case _CONFIG_SIGRT_MIN:
value = S10_SIGRTMIN;
break;
case _CONFIG_SIGRT_MAX:
value = S10_SIGRTMAX;
break;
default:
return (__systemcall(rv, SYS_sysconfig + 1024, which));
}
(void) B_TRUSS_POINT_1(rv, SYS_sysconfig, 0, which);
rv->sys_rval1 = value;
rv->sys_rval2 = 0;
return (0);
}
int
s10_sysinfo(sysret_t *rv, int command, char *buf, long count)
{
char *value;
int len;
switch (command) {
case SI_RELEASE:
value = S10_UTS_RELEASE;
break;
case SI_VERSION:
value = S10_UTS_VERSION;
break;
default:
return (__systemcall(rv, SYS_systeminfo + 1024,
command, buf, count));
}
len = strlen(value) + 1;
if (count > 0) {
if (brand_uucopystr(value, buf, count) != 0)
return (EFAULT);
if (len > count && brand_uucopy("\0", buf + (count - 1), 1)
!= 0)
return (EFAULT);
}
(void) B_TRUSS_POINT_3(rv, SYS_systeminfo, 0, command, buf, count);
rv->sys_rval1 = len;
rv->sys_rval2 = 0;
return (0);
}
#if defined(__x86)
#if defined(__amd64)
static void
s10_lwp_create_entry_point(void *ulwp_structp)
{
sysret_t rval;
(void) __systemcall(&rval, SYS_brand + 1024, B_S10_FSREGCORRECTION);
__asm__ __volatile__(
"movq %0, %%rdi\n\t"
"movq %%rbp, %%rsp\n\t"
"popq %%rbp\n\t"
"jmp *%%r14\n\t"
: : "r" (ulwp_structp));
}
static int
s10_lwp_create_correct_fs(sysret_t *rval, ucontext_t *ucp, int flags,
id_t *new_lwp)
{
ucontext_t s10_uc;
if (brand_uucopy(ucp, &s10_uc, sizeof (s10_uc)) != 0)
return (EFAULT);
s10_uc.uc_mcontext.gregs[REG_R14] = s10_uc.uc_mcontext.gregs[REG_RIP];
s10_uc.uc_mcontext.gregs[REG_RIP] = (greg_t)s10_lwp_create_entry_point;
if (s10_uc.uc_flags & UC_SIGMASK)
(void) s10sigset_to_native(&s10_uc.uc_sigmask,
&s10_uc.uc_sigmask);
return (__systemcall(rval, SYS_lwp_create + 1024, &s10_uc,
flags, new_lwp));
}
#endif
static int
s10_lwp_private(sysret_t *rval, int cmd, int which, uintptr_t base)
{
#if defined(__amd64)
int err;
if ((err = __systemcall(rval, SYS_lwp_private + 1024, cmd, which,
base)) != 0)
return (err);
if (thr_main() == -1) {
brand_sysent_table[SYS_lwp_create].st_callc =
(sysent_cb_t)(uintptr_t)s10_lwp_create_correct_fs;
return (__systemcall(rval, SYS_brand + 1024,
B_S10_FSREGCORRECTION));
}
return (0);
#else
return (__systemcall(rval, SYS_lwp_private + 1024, cmd, which, base));
#endif
}
#endif
static int
s10_lwp_mutex_timedlock(sysret_t *rval, lwp_mutex_t *lp, timespec_t *tsp)
{
return (__systemcall(rval, SYS_lwp_mutex_timedlock + 1024, lp, tsp, 0));
}
static int
s10_lwp_mutex_trylock(sysret_t *rval, lwp_mutex_t *lp)
{
return (__systemcall(rval, SYS_lwp_mutex_trylock + 1024, lp, 0));
}
int
s10_zone(sysret_t *rval, int cmd, void *arg1, void *arg2, void *arg3,
void *arg4)
{
char *aval;
int len;
zoneid_t zid;
int attr;
char *buf;
size_t bufsize;
if (!emul_global_zone)
return (__systemcall(rval, SYS_zone + 1024, cmd, arg1, arg2,
arg3, arg4));
switch (cmd) {
case ZONE_LOOKUP:
(void) B_TRUSS_POINT_1(rval, SYS_zone, 0, cmd);
rval->sys_rval1 = GLOBAL_ZONEID;
rval->sys_rval2 = 0;
return (0);
case ZONE_GETATTR:
zid = (zoneid_t)(uintptr_t)arg1;
attr = (int)(uintptr_t)arg2;
buf = (char *)arg3;
bufsize = (size_t)arg4;
if (zid != GLOBAL_ZONEID)
goto passthru;
switch (attr) {
case ZONE_ATTR_NAME:
aval = GLOBAL_ZONENAME;
break;
case ZONE_ATTR_BRAND:
aval = NATIVE_BRAND_NAME;
break;
default:
arg1 = (void *)(uintptr_t)zoneid;
goto passthru;
}
(void) B_TRUSS_POINT_5(rval, SYS_zone, 0, cmd, zid, attr,
buf, bufsize);
len = strlen(aval) + 1;
if (len > bufsize)
return (ENAMETOOLONG);
if (buf != NULL) {
if (len == 1) {
if (brand_uucopy("\0", buf, 1) != 0)
return (EFAULT);
} else {
if (brand_uucopystr(aval, buf, len) != 0)
return (EFAULT);
if (brand_uucopy("\0", buf + (len - 1), 1) != 0)
return (EFAULT);
}
}
rval->sys_rval1 = len;
rval->sys_rval2 = 0;
return (0);
default:
break;
}
passthru:
return (__systemcall(rval, SYS_zone + 1024, cmd, arg1, arg2, arg3,
arg4));
}
int
brand_init(int argc, char *argv[], char *envp[])
{
sysret_t rval;
ulong_t ldentry;
int err;
char *bname;
brand_pre_init();
(void) get_initpid_info();
err = __systemcall(&rval, SYS_zone, ZONE_LOOKUP, NULL);
brand_assert(err == 0);
zoneid = (zoneid_t)rval.sys_rval1;
if ((err = __systemcall(&rval, SYS_zone, ZONE_GETATTR, zoneid,
S10_EMUL_BITMAP, emul_bitmap, sizeof (emul_bitmap))) != 0) {
brand_abort(err, "The zone's patch level is unsupported");
}
bname = basename(argv[0]);
if (strcmp("pkgadd", bname) == 0 || strcmp("pkgrm", bname) == 0 ||
strcmp("patchadd", bname) == 0 || strcmp("patchrm", bname) == 0)
emul_global_zone = B_TRUE;
ldentry = brand_post_init(S10_VERSION, argc, argv, envp);
brand_runexe(argv, ldentry);
brand_abort(0, "brand_runexe() returned");
return (-1);
}
brand_sysent_table_t brand_sysent_table[] = {
#if defined(__sparc) && !defined(__sparcv9)
EMULATE(brand_indir, 9 | RV_64RVAL),
#else
NOSYS,
#endif
NOSYS,
EMULATE(s10_forkall, 0 | RV_32RVAL2),
NOSYS,
NOSYS,
EMULATE(s10_open, 3 | RV_DEFAULT),
NOSYS,
EMULATE(s10_wait, 0 | RV_32RVAL2),
EMULATE(s10_creat, 2 | RV_DEFAULT),
EMULATE(s10_link, 2 | RV_DEFAULT),
EMULATE(s10_unlink, 1 | RV_DEFAULT),
EMULATE(s10_exec, 2 | RV_DEFAULT),
NOSYS,
NOSYS,
EMULATE(s10_mknod, 3 | RV_DEFAULT),
EMULATE(s10_chmod, 2 | RV_DEFAULT),
EMULATE(s10_chown, 3 | RV_DEFAULT),
NOSYS,
EMULATE(s10_stat, 2 | RV_DEFAULT),
NOSYS,
NOSYS,
NOSYS,
EMULATE(s10_umount, 1 | RV_DEFAULT),
NOSYS,
NOSYS,
NOSYS,
NOSYS,
NOSYS,
EMULATE(s10_fstat, 2 | RV_DEFAULT),
NOSYS,
EMULATE(s10_utime, 2 | RV_DEFAULT),
NOSYS,
NOSYS,
EMULATE(s10_access, 2 | RV_DEFAULT),
NOSYS,
NOSYS,
NOSYS,
EMULATE(s10_kill, 2 | RV_DEFAULT),
NOSYS,
NOSYS,
NOSYS,
EMULATE(s10_dup, 1 | RV_DEFAULT),
EMULATE(s10_pipe, 0 | RV_32RVAL2),
NOSYS,
NOSYS,
NOSYS,
NOSYS,
NOSYS,
NOSYS,
NOSYS,
NOSYS,
NOSYS,
NOSYS,
NOSYS,
EMULATE(s10_ioctl, 3 | RV_DEFAULT),
NOSYS,
NOSYS,
NOSYS,
EMULATE(s10_fdsync, 2 | RV_DEFAULT),
EMULATE(s10_execve, 3 | RV_DEFAULT),
NOSYS,
NOSYS,
EMULATE(s10_fcntl, 3 | RV_DEFAULT),
NOSYS,
NOSYS,
NOSYS,
NOSYS,
NOSYS,
NOSYS,
NOSYS,
NOSYS,
EMULATE(s10_acctctl, 3 | RV_DEFAULT),
NOSYS,
NOSYS,
NOSYS,
EMULATE(s10_issetugid, 0 | RV_DEFAULT),
EMULATE(s10_fsat, 6 | RV_DEFAULT),
NOSYS,
NOSYS,
EMULATE(s10_rmdir, 1 | RV_DEFAULT),
EMULATE(s10_mkdir, 2 | RV_DEFAULT),
EMULATE(s10_getdents, 3 | RV_DEFAULT),
NOSYS,
NOSYS,
NOSYS,
NOSYS,
NOSYS,
EMULATE(s10_poll, 3 | RV_DEFAULT),
EMULATE(s10_lstat, 2 | RV_DEFAULT),
EMULATE(s10_symlink, 2 | RV_DEFAULT),
EMULATE(s10_readlink, 3 | RV_DEFAULT),
NOSYS,
NOSYS,
EMULATE(s10_fchmod, 2 | RV_DEFAULT),
EMULATE(s10_fchown, 3 | RV_DEFAULT),
EMULATE(s10_sigprocmask, 3 | RV_DEFAULT),
EMULATE(s10_sigsuspend, 1 | RV_DEFAULT),
NOSYS,
EMULATE(s10_sigaction, 3 | RV_DEFAULT),
EMULATE(s10_sigpending, 2 | RV_DEFAULT),
NOSYS,
NOSYS,
NOSYS,
NOSYS,
NOSYS,
NOSYS,
NOSYS,
EMULATE(s10_waitid, 4 | RV_DEFAULT),
EMULATE(s10_sigsendsys, 2 | RV_DEFAULT),
NOSYS,
NOSYS,
NOSYS,
NOSYS,
NOSYS,
NOSYS,
NOSYS,
NOSYS,
NOSYS,
NOSYS,
NOSYS,
NOSYS,
NOSYS,
NOSYS,
#if defined(__x86)
EMULATE(s10_xstat, 3 | RV_DEFAULT),
EMULATE(s10_lxstat, 3 | RV_DEFAULT),
EMULATE(s10_fxstat, 3 | RV_DEFAULT),
EMULATE(s10_xmknod, 4 | RV_DEFAULT),
#else
NOSYS,
NOSYS,
NOSYS,
NOSYS,
#endif
NOSYS,
NOSYS,
NOSYS,
EMULATE(s10_lchown, 3 | RV_DEFAULT),
NOSYS,
NOSYS,
NOSYS,
EMULATE(s10_rename, 2 | RV_DEFAULT),
EMULATE(s10_uname, 1 | RV_DEFAULT),
NOSYS,
EMULATE(s10_sysconfig, 1 | RV_DEFAULT),
NOSYS,
EMULATE(s10_sysinfo, 3 | RV_DEFAULT),
NOSYS,
NOSYS,
NOSYS,
EMULATE(s10_fork1, 0 | RV_32RVAL2),
EMULATE(s10_sigtimedwait, 3 | RV_DEFAULT),
NOSYS,
NOSYS,
EMULATE(s10_lwp_sema_wait, 1 | RV_DEFAULT),
NOSYS,
NOSYS,
NOSYS,
NOSYS,
NOSYS,
NOSYS,
EMULATE(s10_utimes, 2 | RV_DEFAULT),
NOSYS,
NOSYS,
NOSYS,
NOSYS,
EMULATE(s10_lwp_create, 3 | RV_DEFAULT),
NOSYS,
NOSYS,
NOSYS,
EMULATE(s10_lwp_kill, 2 | RV_DEFAULT),
NOSYS,
EMULATE(s10_lwp_sigmask, 3 | RV_32RVAL2),
#if defined(__x86)
EMULATE(s10_lwp_private, 3 | RV_DEFAULT),
#else
NOSYS,
#endif
NOSYS,
NOSYS,
EMULATE(s10_lwp_mutex_lock, 1 | RV_DEFAULT),
NOSYS,
NOSYS,
NOSYS,
NOSYS,
EMULATE(s10_pwrite, 4 | RV_DEFAULT),
NOSYS,
NOSYS,
NOSYS,
NOSYS,
NOSYS,
NOSYS,
NOSYS,
NOSYS,
NOSYS,
NOSYS,
EMULATE(s10_acl, 4 | RV_DEFAULT),
EMULATE(s10_auditsys, 4 | RV_64RVAL),
NOSYS,
NOSYS,
NOSYS,
EMULATE(s10_sigqueue, 4 | RV_DEFAULT),
NOSYS,
NOSYS,
NOSYS,
NOSYS,
NOSYS,
NOSYS,
NOSYS,
NOSYS,
NOSYS,
EMULATE(s10_facl, 4 | RV_DEFAULT),
NOSYS,
NOSYS,
NOSYS,
NOSYS,
EMULATE(s10_signotify, 3 | RV_DEFAULT),
NOSYS,
NOSYS,
NOSYS,
NOSYS,
EMULATE(s10_lwp_mutex_timedlock, 2 | RV_DEFAULT),
NOSYS,
NOSYS,
#if defined(_LP64)
NOSYS,
#else
EMULATE(s10_getdents64, 3 | RV_DEFAULT),
#endif
NOSYS,
#if defined(_LP64)
NOSYS,
NOSYS,
NOSYS,
#else
EMULATE(s10_stat64, 2 | RV_DEFAULT),
EMULATE(s10_lstat64, 2 | RV_DEFAULT),
EMULATE(s10_fstat64, 2 | RV_DEFAULT),
#endif
NOSYS,
NOSYS,
NOSYS,
NOSYS,
NOSYS,
#if defined(_LP64)
NOSYS,
NOSYS,
NOSYS,
#else
EMULATE(s10_pwrite64, 5 | RV_DEFAULT),
EMULATE(s10_creat64, 2 | RV_DEFAULT),
EMULATE(s10_open64, 3 | RV_DEFAULT),
#endif
NOSYS,
EMULATE(s10_zone, 5 | RV_DEFAULT),
NOSYS,
NOSYS,
EMULATE(s10_so_socket, 5 | RV_DEFAULT),
NOSYS,
NOSYS,
NOSYS,
EMULATE(s10_accept, 4 | RV_DEFAULT),
NOSYS,
NOSYS,
NOSYS,
NOSYS,
NOSYS,
NOSYS,
NOSYS,
NOSYS,
NOSYS,
NOSYS,
NOSYS,
NOSYS,
NOSYS,
NOSYS,
NOSYS,
NOSYS,
EMULATE(s10_lwp_mutex_trylock, 1 | RV_DEFAULT),
NOSYS,
NOSYS,
NOSYS,
NOSYS
};