Compare commits

...

2 Commits

Author SHA1 Message Date
77560bbc3e
kernel+tools: Allow loading files with different owners + add a more dynamic install script
All checks were successful
continuous-integration/drone/push Build is passing
2023-05-06 12:11:35 +02:00
d7fee26aa2
initrd+libc: Add /etc/group and grp.h 2023-05-06 12:01:47 +02:00
19 changed files with 265 additions and 42 deletions

1
.gitignore vendored
View File

@ -6,3 +6,4 @@ env-local.sh
initrd/bin/**
initrd/tests/**
base/
.fakeroot

View File

@ -1,28 +1,24 @@
function(luna_app SOURCE_FILE APP_NAME SETUID)
function(luna_app SOURCE_FILE APP_NAME)
add_executable(${APP_NAME} ${SOURCE_FILE})
target_compile_options(${APP_NAME} PRIVATE -Os ${COMMON_FLAGS} -Wno-write-strings)
add_dependencies(${APP_NAME} libc)
target_include_directories(${APP_NAME} PRIVATE ${LUNA_BASE}/usr/include)
target_link_libraries(${APP_NAME} PRIVATE os)
if(${SETUID})
install(TARGETS ${APP_NAME} DESTINATION ${LUNA_ROOT}/initrd/bin PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE SETUID)
else()
install(TARGETS ${APP_NAME} DESTINATION ${LUNA_ROOT}/initrd/bin)
endif()
install(TARGETS ${APP_NAME} DESTINATION ${LUNA_ROOT}/initrd/bin)
endfunction()
luna_app(init.cpp init OFF)
luna_app(env.cpp env OFF)
luna_app(su.cpp su ON)
luna_app(sh.cpp sh OFF)
luna_app(cat.cpp cat OFF)
luna_app(date.cpp date OFF)
luna_app(edit.cpp edit OFF)
luna_app(ls.cpp ls OFF)
luna_app(chown.cpp chown OFF)
luna_app(chmod.cpp chmod OFF)
luna_app(mkdir.cpp mkdir OFF)
luna_app(rm.cpp rm OFF)
luna_app(stat.cpp stat OFF)
luna_app(uname.cpp uname OFF)
luna_app(base64.cpp base64 OFF)
luna_app(init.cpp init)
luna_app(env.cpp env)
luna_app(su.cpp su)
luna_app(sh.cpp sh)
luna_app(cat.cpp cat)
luna_app(date.cpp date)
luna_app(edit.cpp edit)
luna_app(ls.cpp ls)
luna_app(chown.cpp chown)
luna_app(chmod.cpp chmod)
luna_app(mkdir.cpp mkdir)
luna_app(rm.cpp rm)
luna_app(stat.cpp stat)
luna_app(uname.cpp uname)
luna_app(base64.cpp base64)

View File

@ -1,3 +1,4 @@
#include <grp.h>
#include <luna/String.h>
#include <os/ArgumentParser.h>
#include <pwd.h>
@ -31,8 +32,14 @@ Result<int> luna_main(int argc, char** argv)
if (rc.has_value()) { gid = (u32)rc.value(); }
else
{
fprintf(stderr, "FIXME: read entry from group file to determine GID for group %s\n", group.chars());
return 1;
struct group* grp = getgrnam(group.chars());
if (!grp)
{
fprintf(stderr, "%s: unknown group %s!\n", argv[0], group.chars());
return 1;
}
gid = grp->gr_gid;
}
}
}

3
initrd/etc/group Normal file
View File

@ -0,0 +1,3 @@
root:!:0:
users:!:1:
selene:!:1000:

View File

@ -18,7 +18,7 @@ void InitRD::initialize()
g_initrd.initialize((void*)virtual_initrd_address, bootboot.initrd_size);
}
static Result<void> vfs_create_dir_if_not_exists(const char* path, mode_t mode)
static Result<void> vfs_create_dir_if_not_exists(const char* path, mode_t mode, uid_t uid, gid_t gid)
{
auto rc = VFS::create_directory(path, Credentials {});
if (rc.has_error())
@ -26,7 +26,9 @@ static Result<void> vfs_create_dir_if_not_exists(const char* path, mode_t mode)
if (rc.error() == EEXIST) return {};
return rc.release_error();
}
rc.value()->chmod(mode & (mode_t)~S_IFMT);
auto dir = rc.value();
dir->chmod(mode & (mode_t)~S_IFMT);
dir->chown(uid, gid);
return {};
}
@ -40,10 +42,11 @@ Result<void> InitRD::populate_vfs()
auto file = TRY(VFS::create_file(entry.name.chars(), Credentials {}));
file->write(entry.data(), 0, entry.size);
file->chmod(entry.mode & (mode_t)~S_IFMT);
file->chown(entry.uid, entry.gid);
}
else if (entry.type == TarStream::EntryType::Directory)
{
TRY(vfs_create_dir_if_not_exists(entry.name.chars(), entry.mode));
TRY(vfs_create_dir_if_not_exists(entry.name.chars(), entry.mode, entry.uid, entry.gid));
}
}

View File

@ -18,6 +18,7 @@ set(SOURCES
src/setjmp.cpp
src/env.cpp
src/pwd.cpp
src/grp.cpp
src/sys/stat.cpp
src/sys/mman.cpp
src/sys/wait.cpp

40
libc/include/grp.h Normal file
View File

@ -0,0 +1,40 @@
/* grp.h: Group file parsing. */
#ifndef _GRP_H
#define _GRP_H
#include <sys/types.h>
struct group
{
char* gr_name;
char* gr_passwd;
gid_t gr_gid;
char** gr_mem;
};
#ifdef __cplusplus
extern "C"
{
#endif
/* Read the next entry from the group file. */
struct group* getgrent(void);
/* Find the entry with a matching group name in the group file. */
struct group* getgrnam(const char* name);
/* Find the entry with a matching group ID in the group file. */
struct group* getgrgid(gid_t gid);
/* Rewind the group file. */
void setgrent(void);
/* End group file parsing. */
void endgrent(void);
#ifdef __cplusplus
}
#endif
#endif

128
libc/src/grp.cpp Normal file
View File

@ -0,0 +1,128 @@
#include <errno.h>
#include <grp.h>
#include <luna/Vector.h>
#include <stdio.h>
#include <stdlib.h>
static struct group grp;
static FILE* f { nullptr };
static char buf[4096];
static Vector<char*> g_members;
extern char* _strtok_once(char* str, const char* delim);
extern "C"
{
static Result<struct group*> try_getgrent()
{
if (!f)
{
f = fopen("/etc/group", "r");
if (!f) return nullptr;
}
while (true)
{
char* rc = fgets(buf, sizeof(buf), f);
if (!rc) return nullptr;
char* name = _strtok_once(rc, ":\n");
if (!name) continue;
char* passwd = _strtok_once(nullptr, ":\n");
if (!passwd) continue;
char* gid = _strtok_once(nullptr, ":\n");
if (!gid) continue;
char* members = _strtok_once(nullptr, ":\n");
if (!members) continue;
g_members.clear();
char* member = strtok(members, ",");
TRY(g_members.try_append(member));
if (member)
{
while (true)
{
member = strtok(nullptr, ",");
TRY(g_members.try_append(member));
if (!member) break;
}
}
grp.gr_name = name;
grp.gr_passwd = passwd;
grp.gr_gid = (gid_t)strtoul(gid, NULL, 10);
grp.gr_mem = g_members.data();
return &grp;
}
}
struct group* getgrent()
{
auto rc = try_getgrent();
if (rc.has_error())
{
errno = rc.error();
return nullptr;
}
return rc.value();
}
struct group* getgrnam(const char* name)
{
setgrent();
struct group* entry;
while ((entry = getgrent()))
{
if (!strcmp(entry->gr_name, name))
{
endgrent();
return entry;
}
}
endgrent();
return entry;
}
struct group* getgrgid(gid_t gid)
{
setgrent();
struct group* entry;
while ((entry = getgrent()))
{
if (entry->gr_gid == gid)
{
endgrent();
return entry;
}
}
endgrent();
return entry;
}
void setgrent()
{
if (f) rewind(f);
}
void endgrent()
{
if (f)
{
fclose(f);
f = nullptr;
}
}
}

View File

@ -11,7 +11,7 @@ static char buf[4096];
// Example:
// strtok("hello:world::!:", ":") -> "hello", "world", "!"
// _strtok_once("hello:world::!:", ":") -> "hello", "world", "", "!"
static char* _strtok_once(char* str, const char* delim)
char* _strtok_once(char* str, const char* delim)
{
static char* s = nullptr;
if (str) s = str;

View File

@ -19,6 +19,8 @@ class TarStream
String name;
usize size;
mode_t mode;
uid_t uid;
gid_t gid;
EntryType type;
const u8* data() const

View File

@ -44,6 +44,8 @@ Result<TarStream::Entry> TarStream::parse_header(const TarStream::TarHeader* hdr
entry.size = parse_unsigned_integer(size, nullptr, 8);
entry.mode = (mode_t)parse_unsigned_integer(hdr->mode, nullptr, 8);
entry.uid = (mode_t)parse_unsigned_integer(hdr->uid, nullptr, 8);
entry.gid = (mode_t)parse_unsigned_integer(hdr->gid, nullptr, 8);
entry.m_data = (u8*)m_base + m_offset;

View File

@ -9,15 +9,11 @@ function(luna_test SOURCE_FILE APP_NAME SETUID)
add_dependencies(${APP_NAME} libc)
target_include_directories(${APP_NAME} PRIVATE ${LUNA_BASE}/usr/include)
target_link_libraries(${APP_NAME} PRIVATE test os)
if(${SETUID})
install(TARGETS ${APP_NAME} DESTINATION ${LUNA_ROOT}/initrd/tests PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE SETUID)
else()
install(TARGETS ${APP_NAME} DESTINATION ${LUNA_ROOT}/initrd/tests)
endif()
install(TARGETS ${APP_NAME} DESTINATION ${LUNA_ROOT}/initrd/tests)
endfunction()
if(BUILD_TESTS)
luna_test(libluna/TestVector.cpp TestVector OFF)
luna_test(libluna/TestBase64.cpp TestBase64 OFF)
luna_test(libluna/TestUtf8.cpp TestUtf8 OFF)
luna_test(libluna/TestVector.cpp TestVector)
luna_test(libluna/TestBase64.cpp TestBase64)
luna_test(libluna/TestUtf8.cpp TestUtf8)
endif()

View File

@ -13,6 +13,5 @@ tools/install-headers.sh
cmake -S . -B $LUNA_BUILD_DIR -DLUNA_NO_OPTIMIZATIONS=ON -DMOON_DEBUG=ON -G "$LUNA_CMAKE_GENERATOR_NAME"
cmake --build $LUNA_BUILD_DIR
cmake --install $LUNA_BUILD_DIR
mkbootimg luna.json Luna.iso
tools/make-iso.sh

View File

@ -12,6 +12,5 @@ tools/install-headers.sh
mkdir -p $LUNA_BUILD_DIR
cmake -S . -B $LUNA_BUILD_DIR -G "$LUNA_CMAKE_GENERATOR_NAME"
cmake --build $LUNA_BUILD_DIR
cmake --install $LUNA_BUILD_DIR
mkbootimg luna.json Luna.iso
tools/make-iso.sh

View File

@ -5,4 +5,24 @@ source $(dirname $0)/env.sh
cd $LUNA_ROOT
if [ "$(id -u)" -ne "0" ]
then
echo "This script must be run under fakeroot."
exit 1
fi
if [ "$USER" == "root" ]
then
echo "This script must be run under fakeroot instead of as root."
exit 1
fi
chown -R root:root initrd
cmake --install $LUNA_BUILD_DIR
chmod 400 initrd/boot/moon
chmod a+s initrd/bin/su
mkdir -p initrd/home/selene
chown 1000:1000 initrd/home/selene

10
tools/make-iso.sh Executable file
View File

@ -0,0 +1,10 @@
#!/usr/bin/env bash
set -e
source $(dirname $0)/env.sh
cd $LUNA_ROOT
fakeroot -u -s $LUNA_ROOT/.fakeroot -- tools/install.sh
fakeroot -u -i $LUNA_ROOT/.fakeroot -- mkbootimg luna.json Luna.iso

15
tools/mkbootimg.patch Normal file
View File

@ -0,0 +1,15 @@
diff --git a/mkbootimg/tar.c b/mkbootimg/tar.c
index dc17e00..ed9d38d 100644
--- a/mkbootimg/tar.c
+++ b/mkbootimg/tar.c
@@ -49,8 +49,8 @@ void tar_add(struct stat *st, char *name, unsigned char *content, int size)
memset(end, 0, 512);
strncpy((char*)end, name, 99);
sprintf((char*)end + 100, "%07o", st->st_mode & 077777);
- sprintf((char*)end + 108, "%07o", 0);
- sprintf((char*)end + 116, "%07o", 0);
+ sprintf((char*)end + 108, "%07o", st->st_uid);
+ sprintf((char*)end + 116, "%07o", st->st_gid);
sprintf((char*)end + 124, "%011o", size);
sprintf((char*)end + 136, "%011o", 0);
sprintf((char*)end + 148, "%06o", 0);

View File

@ -13,6 +13,5 @@ tools/install-headers.sh
cmake -S . -B $LUNA_BUILD_DIR -G "$LUNA_CMAKE_GENERATOR_NAME"
cmake --build $LUNA_BUILD_DIR
cmake --install $LUNA_BUILD_DIR
mkbootimg luna.json Luna.iso
tools/make-iso.sh

View File

@ -11,9 +11,11 @@ cd toolchain
git clone https://gitlab.com/bztsrc/bootboot.git
patch -u -i $LUNA_ROOT/tools/mkbootimg.patch -p 1 -d bootboot
cd bootboot/mkbootimg
make -j$(nproc)
cp ./mkbootimg ../../dist/mkbootimg
rm ../mkbootimg-*.zip
rm ../mkbootimg-*.zip