mirror of
https://github.com/genodelabs/genode.git
synced 2025-01-18 18:56:29 +00:00
Noux: add user information support (struct passwd)
There are certain programs which need the information that is stored in 'struct passwd'. This commit introduces configurable user information support to NOUX. One can set the user information via <user> in NOUX config: ! <config> ! <user name="baron" uid="1" gid="1"> ! <shell name="/bin/bash" /> ! <home name="/home" /> ! </user> ! [...] ! </config> When <user> is not specified default values are used. Currently these are 'root', 0, 0, '/bin/bash', '/'. Note: this is just a single user implementation because each Noux instance has only one user or rather one identity and there will be no complete multi-user support in Noux. If you need different users, just start new Noux instances for each of them.
This commit is contained in:
parent
f2299abab5
commit
a77c3dffd0
@ -72,6 +72,7 @@ namespace Noux {
|
||||
SYSCALL_SHUTDOWN,
|
||||
SYSCALL_CONNECT,
|
||||
SYSCALL_GETADDRINFO,
|
||||
SYSCALL_USERINFO,
|
||||
SYSCALL_INVALID = -1
|
||||
};
|
||||
|
||||
@ -116,6 +117,7 @@ namespace Noux {
|
||||
NOUX_DECL_SYSCALL_NAME(SHUTDOWN)
|
||||
NOUX_DECL_SYSCALL_NAME(CONNECT)
|
||||
NOUX_DECL_SYSCALL_NAME(GETADDRINFO)
|
||||
NOUX_DECL_SYSCALL_NAME(USERINFO)
|
||||
case SYSCALL_INVALID: return 0;
|
||||
}
|
||||
return 0;
|
||||
|
@ -271,6 +271,18 @@ namespace Noux {
|
||||
char ai_canonname[255];
|
||||
};
|
||||
|
||||
/**
|
||||
* user info defintions
|
||||
*/
|
||||
enum { USERINFO_GET_ALL = 0, USERINFO_GET_UID, USERINFO_GET_GID };
|
||||
enum { MAX_USERNAME_LEN = 32 };
|
||||
typedef char User[MAX_USERNAME_LEN];
|
||||
enum { MAX_SHELL_LEN = 16 };
|
||||
typedef char Shell[MAX_SHELL_LEN];
|
||||
enum { MAX_HOME_LEN = 128 };
|
||||
typedef char Home[MAX_HOME_LEN];
|
||||
typedef unsigned int Uid;
|
||||
|
||||
enum General_error { ERR_FD_INVALID, NUM_GENERAL_ERRORS };
|
||||
enum Stat_error { STAT_ERR_NO_ENTRY = NUM_GENERAL_ERRORS };
|
||||
enum Fchdir_error { FCHDIR_ERR_NOT_DIR = NUM_GENERAL_ERRORS };
|
||||
@ -400,6 +412,10 @@ namespace Noux {
|
||||
Addrinfo hints;
|
||||
Addrinfo res[MAX_ADDRINFO_RESULTS]; },
|
||||
{ int addr_num; });
|
||||
|
||||
SYSIO_DECL(userinfo, { int request; Uid uid; },
|
||||
{ User name; Uid uid; Uid gid; Shell shell;
|
||||
Home home; });
|
||||
};
|
||||
};
|
||||
};
|
||||
|
@ -37,6 +37,7 @@
|
||||
#include <sys/mman.h>
|
||||
#include <unistd.h>
|
||||
#include <termios.h>
|
||||
#include <pwd.h>
|
||||
|
||||
/* libc-internal includes */
|
||||
#include <libc_mem_alloc.h>
|
||||
@ -93,6 +94,85 @@ enum { FS_BLOCK_SIZE = 1024 };
|
||||
** Overrides of libc default implementations **
|
||||
***********************************************/
|
||||
|
||||
/**
|
||||
* User information related functions
|
||||
*/
|
||||
extern "C" struct passwd *getpwuid(uid_t uid)
|
||||
{
|
||||
static char name[Noux::Sysio::MAX_USERNAME_LEN];
|
||||
static char shell[Noux::Sysio::MAX_SHELL_LEN];
|
||||
static char home[Noux::Sysio::MAX_HOME_LEN];
|
||||
|
||||
static struct passwd pw = {
|
||||
/* .pw_name = */ name,
|
||||
/* .pw_passwd = */ "",
|
||||
/* .pw_uid = */ 0,
|
||||
/* .pw_gid = */ 0,
|
||||
/* .pw_change = */ 0,
|
||||
/* .pw_class = */ "",
|
||||
/* .pw_gecos = */ "",
|
||||
/* .pw_dir = */ home,
|
||||
/* .pw_shell = */ shell,
|
||||
/* .pw_expire = */ 0,
|
||||
/* .pw_fields = */ 0
|
||||
};
|
||||
|
||||
sysio()->userinfo_in.uid = uid;
|
||||
sysio()->userinfo_in.request = Noux::Sysio::USERINFO_GET_ALL;
|
||||
|
||||
if (!noux()->syscall(Noux::Session::SYSCALL_USERINFO)) {
|
||||
return (struct passwd *)0;
|
||||
}
|
||||
|
||||
/* SYSCALL_USERINFO assures that strings are always '\0' terminated */
|
||||
Genode::memcpy(name, sysio()->userinfo_out.name, sizeof (sysio()->userinfo_out.name));
|
||||
Genode::memcpy(home, sysio()->userinfo_out.home, sizeof (sysio()->userinfo_out.home));
|
||||
Genode::memcpy(shell, sysio()->userinfo_out.shell, sizeof (sysio()->userinfo_out.shell));
|
||||
|
||||
pw.pw_uid = sysio()->userinfo_out.uid;
|
||||
pw.pw_gid = sysio()->userinfo_out.gid;
|
||||
|
||||
return &pw;
|
||||
}
|
||||
|
||||
|
||||
extern "C" uid_t getgid()
|
||||
{
|
||||
sysio()->userinfo_in.request = Noux::Sysio::USERINFO_GET_GID;
|
||||
|
||||
if (!noux()->syscall(Noux::Session::SYSCALL_USERINFO))
|
||||
return 0;
|
||||
|
||||
uid_t gid = sysio()->userinfo_out.gid;
|
||||
return gid;
|
||||
}
|
||||
|
||||
|
||||
extern "C" uid_t getegid()
|
||||
{
|
||||
return getgid();
|
||||
}
|
||||
|
||||
|
||||
extern "C" uid_t getuid()
|
||||
{
|
||||
sysio()->userinfo_in.request = Noux::Sysio::USERINFO_GET_UID;
|
||||
|
||||
if (!noux()->syscall(Noux::Session::SYSCALL_USERINFO))
|
||||
return 0;
|
||||
|
||||
uid_t uid = sysio()->userinfo_out.uid;
|
||||
PDBG("getuid(): %d", uid);
|
||||
return uid;
|
||||
}
|
||||
|
||||
|
||||
extern "C" uid_t geteuid()
|
||||
{
|
||||
return getuid();
|
||||
}
|
||||
|
||||
|
||||
extern "C" int __getcwd(char *dst, Genode::size_t dst_size)
|
||||
{
|
||||
noux()->syscall(Noux::Session::SYSCALL_GETCWD);
|
||||
|
@ -66,6 +66,12 @@ namespace Noux {
|
||||
class Timeout_scheduler;
|
||||
Timeout_scheduler *timeout_scheduler();
|
||||
|
||||
/**
|
||||
* Return singleton instance of user information
|
||||
*/
|
||||
class User_info;
|
||||
User_info *user_info();
|
||||
|
||||
|
||||
class Child;
|
||||
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include <dummy_input_io_channel.h>
|
||||
#include <pipe_io_channel.h>
|
||||
#include <dir_file_system.h>
|
||||
#include <user_info.h>
|
||||
|
||||
|
||||
static bool trace_syscalls = false;
|
||||
@ -562,6 +563,33 @@ bool Noux::Child::syscall(Noux::Session::Syscall sc)
|
||||
return _root_dir->mkdir(_sysio, Absolute_path(_sysio->mkdir_in.path,
|
||||
_env.pwd()).base());
|
||||
|
||||
case SYSCALL_USERINFO:
|
||||
{
|
||||
if (_sysio->userinfo_in.request == Sysio::USERINFO_GET_UID
|
||||
|| _sysio->userinfo_in.request == Sysio::USERINFO_GET_GID) {
|
||||
_sysio->userinfo_out.uid = Noux::user_info()->uid;
|
||||
_sysio->userinfo_out.gid = Noux::user_info()->gid;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Since NOUX supports exactly one user, return false if we
|
||||
* got a unknown uid.
|
||||
*/
|
||||
if (_sysio->userinfo_in.uid != Noux::user_info()->uid)
|
||||
return false;
|
||||
|
||||
Genode::memcpy(_sysio->userinfo_out.name, Noux::user_info()->name, sizeof(Noux::user_info()->name));
|
||||
Genode::memcpy(_sysio->userinfo_out.shell, Noux::user_info()->shell, sizeof(Noux::user_info()->shell));
|
||||
Genode::memcpy(_sysio->userinfo_out.home, Noux::user_info()->home, sizeof(Noux::user_info()->home));
|
||||
|
||||
_sysio->userinfo_out.uid = user_info()->uid;
|
||||
_sysio->userinfo_out.gid = user_info()->gid;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
case SYSCALL_SOCKET:
|
||||
case SYSCALL_GETSOCKOPT:
|
||||
case SYSCALL_SETSOCKOPT:
|
||||
@ -697,12 +725,21 @@ Noux::Pid_allocator *Noux::pid_allocator()
|
||||
return &inst;
|
||||
}
|
||||
|
||||
|
||||
Noux::Timeout_scheduler *Noux::timeout_scheduler()
|
||||
{
|
||||
static Noux::Timeout_scheduler inst;
|
||||
return &inst;
|
||||
}
|
||||
|
||||
|
||||
Noux::User_info* Noux::user_info()
|
||||
{
|
||||
static Noux::User_info inst;
|
||||
return &inst;
|
||||
}
|
||||
|
||||
|
||||
void *operator new (Genode::size_t size) {
|
||||
return Genode::env()->heap()->alloc(size); }
|
||||
|
||||
@ -735,6 +772,12 @@ int main(int argc, char **argv)
|
||||
static Dir_file_system
|
||||
root_dir(config()->xml_node().sub_node("fstab"));
|
||||
|
||||
/* set user information */
|
||||
try {
|
||||
user_info()->set_info(config()->xml_node().sub_node("user"));
|
||||
}
|
||||
catch (...) { }
|
||||
|
||||
/* initialize network */
|
||||
init_network();
|
||||
|
||||
|
@ -163,6 +163,7 @@ bool Noux::Child::_syscall_net(Noux::Session::Syscall sc)
|
||||
case SYSCALL_RENAME:
|
||||
case SYSCALL_MKDIR:
|
||||
case SYSCALL_FTRUNCATE:
|
||||
case SYSCALL_USERINFO:
|
||||
break;
|
||||
case SYSCALL_SOCKET:
|
||||
{
|
||||
|
78
ports/src/noux/user_info.h
Normal file
78
ports/src/noux/user_info.h
Normal file
@ -0,0 +1,78 @@
|
||||
/*
|
||||
* \brief User information
|
||||
* \author Josef Soentgen
|
||||
* \date 2012-07-23
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2011-2012 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _NOUX__USER_INFO_H_
|
||||
#define _NOUX__USER_INFO_H_
|
||||
|
||||
/* Genode includes */
|
||||
#include <util/string.h>
|
||||
#include <util/xml_node.h>
|
||||
|
||||
/* Noux includes */
|
||||
#include <noux_session/sysio.h>
|
||||
|
||||
namespace Noux {
|
||||
|
||||
struct User_info {
|
||||
public:
|
||||
|
||||
char name[Sysio::MAX_USERNAME_LEN];
|
||||
char shell[Sysio::MAX_SHELL_LEN];
|
||||
char home[Sysio::MAX_HOME_LEN];
|
||||
|
||||
unsigned int uid;
|
||||
unsigned int gid;
|
||||
|
||||
private:
|
||||
|
||||
void _dup_str(char *dest, const char *src)
|
||||
{
|
||||
Genode::size_t len = Genode::strlen(src);
|
||||
Genode::memcpy(dest, src, len);
|
||||
dest[len] = '\0';
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
User_info() : uid(0), gid(0)
|
||||
{
|
||||
_dup_str(name, "root");
|
||||
_dup_str(home, "/");
|
||||
_dup_str(shell, "/bin/bash");
|
||||
}
|
||||
|
||||
void set_info(Genode::Xml_node user_info_node)
|
||||
{
|
||||
try {
|
||||
user_info_node.attribute("name").value(name, sizeof(name));
|
||||
user_info_node.attribute("uid").value(&uid);
|
||||
user_info_node.attribute("gid").value(&gid);
|
||||
|
||||
for (unsigned i = 0; i < user_info_node.num_sub_nodes(); i++) {
|
||||
Xml_node sub_node = user_info_node.sub_node(i);
|
||||
|
||||
if (sub_node.has_type("shell")) {
|
||||
sub_node.attribute("name").value(shell, sizeof(shell));
|
||||
}
|
||||
|
||||
if (sub_node.has_type("home")) {
|
||||
sub_node.attribute("name").value(home, sizeof(home));
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (...) { }
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif /* _NOUX__USER_INFO_H_ */
|
Loading…
Reference in New Issue
Block a user