Add getgroups and setgroups (#619)

This commit is contained in:
Gavin Hayes 2022-09-18 05:48:53 -04:00 committed by GitHub
parent 3665232d66
commit 4c40c500b8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
17 changed files with 280 additions and 29 deletions

View file

@ -98,9 +98,10 @@ int fork(void);
int fsync(int);
int ftruncate(int, int64_t);
int getdomainname(char *, size_t);
int getegid(void) nosideeffect;
int geteuid(void) nosideeffect;
int getgid(void) nosideeffect;
uint32_t getegid(void) nosideeffect;
uint32_t geteuid(void) nosideeffect;
uint32_t getgid(void) nosideeffect;
int getgroups(int size, uint32_t list[]);
int gethostname(char *, size_t);
int getloadavg(double *, int);
int getpgid(int) libcesque;
@ -112,7 +113,7 @@ int getresgid(uint32_t *, uint32_t *, uint32_t *);
int getresuid(uint32_t *, uint32_t *, uint32_t *);
int getsid(int) nosideeffect libcesque;
int gettid(void) libcesque;
int getuid(void) libcesque;
uint32_t getuid(void) libcesque;
int sys_iopl(int);
int ioprio_get(int, int);
int ioprio_set(int, int, int);
@ -163,6 +164,7 @@ int seteuid(uint32_t);
int setfsgid(int);
int setfsuid(int);
int setgid(int);
int setgroups(size_t size, const uint32_t list[]);
int setpgid(int, int);
int setpgrp(void);
int setpriority(int, unsigned, int);

View file

@ -17,22 +17,22 @@
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/calls/calls.h"
#include "libc/intrin/strace.internal.h"
#include "libc/calls/syscall-sysv.internal.h"
#include "libc/dce.h"
#include "libc/intrin/strace.internal.h"
#include "libc/runtime/runtime.h"
/**
* Returns effective group ID of calling process.
* @return group id
*/
int getegid(void) {
int rc;
uint32_t getegid(void) {
uint32_t rc;
if (!IsWindows()) {
rc = sys_getegid();
} else {
rc = getgid();
}
STRACE("%s() → %d% m", "getegid", rc);
STRACE("%s() → %u% m", "getegid", rc);
return rc;
}

View file

@ -17,21 +17,21 @@
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/calls/calls.h"
#include "libc/intrin/strace.internal.h"
#include "libc/calls/syscall-sysv.internal.h"
#include "libc/dce.h"
#include "libc/intrin/strace.internal.h"
/**
* Returns effective user ID of calling process.
* @return user id
*/
int geteuid(void) {
int rc;
uint32_t geteuid(void) {
uint32_t rc;
if (!IsWindows()) {
rc = sys_geteuid();
} else {
rc = getuid();
}
STRACE("%s() → %d% m", "geteuid", rc);
STRACE("%s() → %u% m", "geteuid", rc);
return rc;
}

45
libc/calls/getgroups.c Normal file
View file

@ -0,0 +1,45 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/calls/calls.h"
#include "libc/calls/groups.internal.h"
#include "libc/dce.h"
#include "libc/intrin/asan.internal.h"
#include "libc/intrin/describeflags.internal.h"
#include "libc/intrin/strace.internal.h"
#include "libc/sysv/errfuns.h"
/**
* Get list of supplementary group IDs
*
* @param size - maximum number of items that can be stored in list
* @param list - buffer to store output gid_t
* @return -1 w/ EFAULT
*/
int getgroups(int size, uint32_t list[]) {
int rc;
if (IsAsan() && size && !__asan_is_valid(list, size * sizeof(list[0]))) {
rc = efault();
} else if (IsLinux() || IsNetbsd() || IsOpenbsd() || IsFreebsd() || IsXnu()) {
rc = sys_getgroups(size, list);
} else {
rc = enosys();
}
STRACE("getgroups(%d, %s) → %d% m", size, DescribeGidList(rc, rc, list), rc);
return rc;
}

View file

@ -17,9 +17,9 @@
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/calls/calls.h"
#include "libc/intrin/strace.internal.h"
#include "libc/calls/syscall-sysv.internal.h"
#include "libc/dce.h"
#include "libc/intrin/strace.internal.h"
#include "libc/macros.internal.h"
#include "libc/nt/accounting.h"
#include "libc/runtime/runtime.h"
@ -50,15 +50,15 @@ static textwindows dontinline uint32_t GetUserNameHash(void) {
* @asyncsignalsafe
* @vforksafe
*/
int getuid(void) {
int rc;
uint32_t getuid(void) {
uint32_t rc;
if (!IsWindows()) {
rc = sys_getuid();
} else {
rc = GetUserNameHash();
}
STRACE("%s() → %d% m", "getuid", rc);
STRACE("%s() → %u% m", "getuid", rc);
return rc;
}
@ -71,13 +71,13 @@ int getuid(void) {
* @asyncsignalsafe
* @vforksafe
*/
int getgid(void) {
int rc;
uint32_t getgid(void) {
uint32_t rc;
if (!IsWindows()) {
rc = sys_getgid();
} else {
rc = GetUserNameHash();
}
STRACE("%s() → %d% m", "getgid", rc);
STRACE("%s() → %u% m", "getgid", rc);
return rc;
}

View file

@ -0,0 +1,16 @@
#ifndef COSMOPOLITAN_LIBC_CALLS_GROUPS_INTERNAL_H_
#define COSMOPOLITAN_LIBC_CALLS_GROUPS_INTERNAL_H_
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
int sys_getgroups(int size, uint32_t list[]);
int sys_setgroups(size_t size, uint32_t list[]);
const char *DescribeGidList(char[128], int, int, const uint32_t list[]);
#define DescribeGidList(rc, length, gidlist) \
DescribeGidList(alloca(128), rc, length, gidlist)
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_CALLS_GROUPS_INTERNAL_H_ */

46
libc/calls/setgroups.c Normal file
View file

@ -0,0 +1,46 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/calls/calls.h"
#include "libc/calls/groups.internal.h"
#include "libc/dce.h"
#include "libc/intrin/asan.internal.h"
#include "libc/intrin/describeflags.internal.h"
#include "libc/intrin/strace.internal.h"
#include "libc/sysv/errfuns.h"
/**
* Set list of supplementary group IDs
*
* @param size - number of items in list
* @param list - input set of gid_t to set
* @return -1 w/ EFAULT
*/
int setgroups(size_t size, const uint32_t list[]) {
int rc;
if (IsAsan() && size && !__asan_is_valid(list, size * sizeof(list[0]))) {
rc = efault();
} else if (IsLinux() || IsNetbsd() || IsOpenbsd() || IsFreebsd() || IsXnu()) {
rc = sys_setgroups(size, list);
} else {
rc = enosys();
}
STRACE("setgroups(%u, %s) → %d% m", size, DescribeGidList(rc, size, list),
rc);
return rc;
}

View file

@ -0,0 +1,51 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2021 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/calls/groups.internal.h"
#include "libc/dce.h"
#include "libc/intrin/asan.internal.h"
#include "libc/intrin/kprintf.h"
#include "libc/intrin/popcnt.h"
#include "libc/macros.internal.h"
#include "libc/str/str.h"
#define N 128
const char *(DescribeGidList)(char buf[N], int rc, int size,
const uint32_t list[]) {
if ((rc == -1) || (size < 0)) return "n/a";
if (!size) return "{}";
if (!list) return "NULL";
if ((!IsAsan() && kisdangerous(list)) ||
(IsAsan() && !__asan_is_valid(list, size * sizeof(list[0])))) {
ksnprintf(buf, N, "%p", list);
return buf;
}
int i = 0, n = N;
i += ksnprintf(buf + i, MAX(0, n - i), "{");
unsigned c;
for (c = 0; c < size && MAX(0, n - i) > 0; c++) {
i += ksnprintf(buf + i, MAX(0, n - i), "%u, ", list[c]);
}
if (c == size) {
if (buf[i - 1] == ' ') i--;
if (buf[i - 1] == ',') i--;
i += ksnprintf(buf + i, MAX(0, n - i), "}");
}
return buf;
}

View file

@ -1,4 +1,5 @@
#ifndef LIBC_ISYSTEM_GRP_H_
#define LIBC_ISYSTEM_GRP_H_
#include "libc/calls/calls.h"
#include "third_party/musl/passwd.h"
#endif

View file

@ -84,7 +84,6 @@ int mprotect(void *, uint64_t, int) privileged;
int msync(void *, size_t, int);
void *sbrk(intptr_t);
int brk(void *);
int getgroups(int, uint32_t[]);
long gethostid(void);
int sethostid(long);
char *getlogin(void);

View file

@ -1,2 +1,2 @@
.include "o/libc/sysv/macros.internal.inc"
.scall sys_getgroups,0x04f04f04f204f073,globl
.scall sys_getgroups,0x04f04f04f204f073,globl,hidden

View file

@ -1,2 +1,2 @@
.include "o/libc/sysv/macros.internal.inc"
.scall sys_setgroups,0x0500500502050074,globl
.scall sys_setgroups,0x0500500502050074,globl,hidden

View file

@ -151,8 +151,8 @@ scall sys_getpgid 0x0cf0cf0cf2097079 globl hidden
scall sys_setpgid 0x052052052205206d globl hidden
scall sys_geteuid 0x019019019201906b globl hidden
scall sys_getegid 0x02b02b02b202b06c globl hidden
scall sys_getgroups 0x04f04f04f204f073 globl # no wrapper
scall sys_setgroups 0x0500500502050074 globl # no wrapper
scall sys_getgroups 0x04f04f04f204f073 globl hidden
scall sys_setgroups 0x0500500502050074 globl hidden
scall sys_setreuid 0x07e07e07e207e071 globl hidden
scall sys_setregid 0x07f07f07f207f072 globl hidden
scall sys_setuid 0x0170170172017069 globl hidden

View file

@ -0,0 +1,47 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2022 Gavin Arthur Hayes
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/calls/calls.h"
#include "libc/dce.h"
#include "libc/errno.h"
#include "libc/testlib/testlib.h"
TEST(getgroups, test) {
int rc;
uint32_t res[1000];
rc = getgroups(0, NULL);
if (IsLinux() || IsNetbsd() || IsOpenbsd() || IsFreebsd() || IsXnu()) {
EXPECT_NE(-1, rc);
EXPECT_NE(-1, getgroups(sizeof(res) / sizeof(res[0]), res));
} else {
EXPECT_EQ(-1, rc);
EXPECT_EQ(ENOSYS, errno);
}
}
TEST(setgroups, test) {
int rc;
uint32_t src[5];
EXPECT_EQ(-1, setgroups(0, NULL));
if (IsLinux() || IsNetbsd() || IsOpenbsd() || IsFreebsd() || IsXnu()) {
EXPECT_EQ(EPERM, errno);
EXPECT_EQ(-1, setgroups(sizeof(src) / sizeof(src[0]), src));
} else {
EXPECT_EQ(ENOSYS, errno);
}
}

View file

@ -0,0 +1,41 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2022 Gavin Arthur Hayes
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/calls/groups.internal.h"
#include "libc/intrin/describeflags.internal.h"
#include "libc/testlib/testlib.h"
TEST(DescribeGidList, test) {
uint32_t list[] = {8, 67, 530, 9};
uint32_t biglist[] = {8, 67, 530, 9, 8, 67, 530, 9, 8, 67, 530, 9,
8, 67, 530, 9, 8, 67, 530, 9, 8, 67, 530, 9,
8, 67, 530, 9, 8, 67, 530, 9, 8, 67, 530, 9};
EXPECT_STREQ("n/a",
DescribeGidList(-1, sizeof(list) / sizeof(list[0]), list));
EXPECT_STREQ("n/a", DescribeGidList(0, -1, list));
EXPECT_STREQ("{}", DescribeGidList(0, 0, list));
EXPECT_STREQ("NULL", DescribeGidList(0, 9001, NULL));
EXPECT_STREQ("{8, 67, 530, 9}",
DescribeGidList(0, sizeof(list) / sizeof(list[0]), list));
EXPECT_STREQ("{8, 67, 530}",
DescribeGidList(0, sizeof(list) / sizeof(list[0]) - 1, list));
EXPECT_STREQ(
"{8, 67, 530, 9, 8, 67, 530, 9, 8, 67, 530, 9, 8, 67, 530, 9, 8, 67, "
"530, 9, 8, 67, 530, 9, 8, 67, 530, 9, 8, 67, 530, 9, 8, ...",
DescribeGidList(0, sizeof(biglist) / sizeof(biglist[0]), biglist));
}

View file

@ -325,6 +325,10 @@ static dontinline int LuaUnixGetid(lua_State *L, int f(void)) {
return ReturnInteger(L, f());
}
static dontinline int LuaUnixGetUnsignedid(lua_State *L, unsigned f(void)) {
return ReturnInteger(L, f());
}
// unix.getpid()
// └─→ pid:int
static int LuaUnixGetpid(lua_State *L) {
@ -340,25 +344,25 @@ static int LuaUnixGetppid(lua_State *L) {
// unix.getuid()
// └─→ uid:int
static int LuaUnixGetuid(lua_State *L) {
return LuaUnixGetid(L, getuid);
return LuaUnixGetUnsignedid(L, getuid);
}
// unix.getgid()
// └─→ gid:int
static int LuaUnixGetgid(lua_State *L) {
return LuaUnixGetid(L, getgid);
return LuaUnixGetUnsignedid(L, getgid);
}
// unix.geteuid()
// └─→ uid:int
static int LuaUnixGeteuid(lua_State *L) {
return LuaUnixGetid(L, geteuid);
return LuaUnixGetUnsignedid(L, geteuid);
}
// unix.getegid()
// └─→ gid:int
static int LuaUnixGetegid(lua_State *L) {
return LuaUnixGetid(L, getegid);
return LuaUnixGetUnsignedid(L, getegid);
}
// unix.umask(newmask:int)

View file

@ -43,7 +43,6 @@ void setgrent(void);
struct group *fgetgrent(struct FILE *);
int putgrent(const struct group *, struct FILE *);
int getgrouplist(const char *, gid_t, gid_t *, int *);
int setgroups(size_t, const int32_t *);
int initgroups(const char *, int32_t);
COSMOPOLITAN_C_END_