From: Stacey Son <s...@freebsd.org> Signed-off-by: Stacey Son <s...@freebsd.org> Signed-off-by: Karim Taha <kariem.taha...@gmail.com> Reviewed-by: Warner Losh <i...@bsdimp.com> --- bsd-user/bsd-proc.h | 44 +++++++++++++++++++++++++++++++++++ bsd-user/freebsd/os-syscall.c | 9 +++++++ 2 files changed, 53 insertions(+)
diff --git a/bsd-user/bsd-proc.h b/bsd-user/bsd-proc.h index b6225e520e..7b25aa1982 100644 --- a/bsd-user/bsd-proc.h +++ b/bsd-user/bsd-proc.h @@ -41,4 +41,48 @@ static inline abi_long do_bsd_exit(void *cpu_env, abi_long arg1) return 0; } +/* getgroups(2) */ +static inline abi_long do_bsd_getgroups(abi_long gidsetsize, abi_long arg2) +{ + abi_long ret; + uint32_t *target_grouplist; + g_autofree gid_t *grouplist; + int i; + + grouplist = g_try_new(gid_t, gidsetsize); + ret = get_errno(getgroups(gidsetsize, grouplist)); + if (gidsetsize != 0) { + if (!is_error(ret)) { + target_grouplist = lock_user(VERIFY_WRITE, arg2, gidsetsize * 2, 0); + if (!target_grouplist) { + return -TARGET_EFAULT; + } + for (i = 0; i < ret; i++) { + target_grouplist[i] = tswap32(grouplist[i]); + } + unlock_user(target_grouplist, arg2, gidsetsize * 2); + } + } + return ret; +} + +/* setgroups(2) */ +static inline abi_long do_bsd_setgroups(abi_long gidsetsize, abi_long arg2) +{ + uint32_t *target_grouplist; + g_autofree gid_t *grouplist; + int i; + + grouplist = g_try_new(gid_t, gidsetsize); + target_grouplist = lock_user(VERIFY_READ, arg2, gidsetsize * 2, 1); + if (!target_grouplist) { + return -TARGET_EFAULT; + } + for (i = 0; i < gidsetsize; i++) { + grouplist[i] = tswap32(target_grouplist[i]); + } + unlock_user(target_grouplist, arg2, 0); + return get_errno(setgroups(gidsetsize, grouplist)); +} + #endif /* !BSD_PROC_H_ */ diff --git a/bsd-user/freebsd/os-syscall.c b/bsd-user/freebsd/os-syscall.c index fa60df529e..535e6287bd 100644 --- a/bsd-user/freebsd/os-syscall.c +++ b/bsd-user/freebsd/os-syscall.c @@ -223,6 +223,15 @@ static abi_long freebsd_syscall(void *cpu_env, int num, abi_long arg1, ret = do_bsd_exit(cpu_env, arg1); break; + case TARGET_FREEBSD_NR_getgroups: /* getgroups(2) */ + ret = do_bsd_getgroups(arg1, arg2); + break; + + case TARGET_FREEBSD_NR_setgroups: /* setgroups(2) */ + ret = do_bsd_setgroups(arg1, arg2); + break; + + /* * File system calls. */ -- 2.42.0