forked from Imagelibrary/rtems
Add supplementary groups to user environment
This commit is contained in:
@@ -25,6 +25,7 @@
|
|||||||
* limits.h is supposed to provide _POSIX_LOGIN_NAME_MAX
|
* limits.h is supposed to provide _POSIX_LOGIN_NAME_MAX
|
||||||
* XXX: We do not rely on this.
|
* XXX: We do not rely on this.
|
||||||
*/
|
*/
|
||||||
|
#include <sys/param.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
|
|
||||||
#include <rtems.h>
|
#include <rtems.h>
|
||||||
@@ -52,18 +53,64 @@ extern "C" {
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief User environment.
|
||||||
|
*/
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
/**
|
||||||
|
* @brief The anchor directory for relative paths.
|
||||||
|
*/
|
||||||
rtems_filesystem_global_location_t *current_directory;
|
rtems_filesystem_global_location_t *current_directory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The anchor directory for absolute paths.
|
||||||
|
*/
|
||||||
rtems_filesystem_global_location_t *root_directory;
|
rtems_filesystem_global_location_t *root_directory;
|
||||||
/* Default mode for all files. */
|
|
||||||
mode_t umask;
|
/**
|
||||||
/* _POSIX_types */
|
* @brief The file mode creation mask.
|
||||||
uid_t uid;
|
*/
|
||||||
gid_t gid;
|
mode_t umask;
|
||||||
uid_t euid;
|
|
||||||
gid_t egid;
|
/**
|
||||||
char login_buffer[LOGIN_NAME_MAX];
|
* @brief The real user ID.
|
||||||
pid_t pgrp; /* process group id */
|
*/
|
||||||
|
uid_t uid;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The real group ID.
|
||||||
|
*/
|
||||||
|
gid_t gid;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The effective user ID.
|
||||||
|
*/
|
||||||
|
uid_t euid;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The effective group ID.
|
||||||
|
*/
|
||||||
|
gid_t egid;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The login buffer.
|
||||||
|
*/
|
||||||
|
char login_buffer[LOGIN_NAME_MAX];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The process group ID.
|
||||||
|
*/
|
||||||
|
pid_t pgrp;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The count of supplementary group IDs.
|
||||||
|
*/
|
||||||
|
size_t ngroups;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The list of supplementary group IDs.
|
||||||
|
*/
|
||||||
|
gid_t groups[NGROUPS];
|
||||||
} rtems_user_env_t;
|
} rtems_user_env_t;
|
||||||
|
|
||||||
extern rtems_user_env_t rtems_global_user_env;
|
extern rtems_user_env_t rtems_global_user_env;
|
||||||
@@ -116,6 +163,15 @@ rtems_status_code rtems_libio_set_private_env(void);
|
|||||||
*/
|
*/
|
||||||
void rtems_libio_use_global_env(void);
|
void rtems_libio_use_global_env(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Gets the supplementary group IDs using the current user ID and
|
||||||
|
* updates the table of supplementary group IDs in the current user
|
||||||
|
* environment.
|
||||||
|
*
|
||||||
|
* In case of an error, the count of supplementary group IDs is set to zero.
|
||||||
|
*/
|
||||||
|
void rtems_current_user_env_getgroups(void);
|
||||||
|
|
||||||
/** @} */
|
/** @} */
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|||||||
@@ -58,6 +58,7 @@ BASE_FS_C_FILES = src/base_fs.c src/mount.c src/unmount.c src/libio.c \
|
|||||||
src/libio_helper_null.c \
|
src/libio_helper_null.c \
|
||||||
src/libio_exit.c \
|
src/libio_exit.c \
|
||||||
src/open_dev_console.c src/__usrenv.c src/rtems_mkdir.c
|
src/open_dev_console.c src/__usrenv.c src/rtems_mkdir.c
|
||||||
|
BASE_FS_C_FILES += src/uenvgetgroups.c
|
||||||
|
|
||||||
TERMIOS_C_FILES = src/cfgetispeed.c src/cfgetospeed.c src/cfsetispeed.c \
|
TERMIOS_C_FILES = src/cfgetispeed.c src/cfgetospeed.c src/cfsetispeed.c \
|
||||||
src/cfsetospeed.c src/tcgetattr.c src/tcsetattr.c src/tcdrain.c \
|
src/cfsetospeed.c src/tcgetattr.c src/tcsetattr.c src/tcdrain.c \
|
||||||
|
|||||||
@@ -810,11 +810,30 @@ int rtems_filesystem_location_exists_in_same_instance_as(
|
|||||||
const rtems_filesystem_location_info_t *b
|
const rtems_filesystem_location_info_t *b
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Checks if access to an object is allowed for the current user.
|
||||||
|
*
|
||||||
|
* If the effective UID is zero or equals the UID of the object, then the user
|
||||||
|
* permission flags of the object will be used. Otherwise if the effective GID
|
||||||
|
* is zero or equals the GID of the object or one of the supplementary group
|
||||||
|
* IDs is equal to the GID of the object, then the group permission flags of
|
||||||
|
* the object will be used. Otherwise the other permission flags of the object
|
||||||
|
* will be used.
|
||||||
|
*
|
||||||
|
* @param[in] flags The flags determining the access type. It can be
|
||||||
|
* RTEMS_FS_PERMS_READ, RTEMS_FS_PERMS_WRITE or RTEMS_FS_PERMS_EXEC.
|
||||||
|
* @param[in] object_mode The mode of the object specifying the permission flags.
|
||||||
|
* @param[in] object_uid The UID of the object.
|
||||||
|
* @param[in] object_gid The GID of the object.
|
||||||
|
*
|
||||||
|
* @retval true Access is allowed.
|
||||||
|
* @retval false Otherwise.
|
||||||
|
*/
|
||||||
bool rtems_filesystem_check_access(
|
bool rtems_filesystem_check_access(
|
||||||
int eval_flags,
|
int flags,
|
||||||
mode_t node_mode,
|
mode_t object_mode,
|
||||||
uid_t node_uid,
|
uid_t object_uid,
|
||||||
gid_t node_gid
|
gid_t object_gid
|
||||||
);
|
);
|
||||||
|
|
||||||
bool rtems_filesystem_eval_path_check_access(
|
bool rtems_filesystem_eval_path_check_access(
|
||||||
|
|||||||
@@ -70,29 +70,50 @@ RTEMS_STATIC_ASSERT(
|
|||||||
S_IXOTH
|
S_IXOTH
|
||||||
);
|
);
|
||||||
|
|
||||||
bool rtems_filesystem_check_access(
|
static bool equals_supplementary_group(
|
||||||
int eval_flags,
|
const rtems_user_env_t *uenv,
|
||||||
mode_t node_mode,
|
gid_t object_gid
|
||||||
uid_t node_uid,
|
|
||||||
gid_t node_gid
|
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
mode_t perm_flags = eval_flags & RTEMS_FS_PERMS_RWX;
|
size_t i;
|
||||||
uid_t task_uid = geteuid();
|
|
||||||
|
|
||||||
if (task_uid == 0 || task_uid == node_uid) {
|
for (i = 0; i < uenv->ngroups; ++i) {
|
||||||
perm_flags <<= RTEMS_FS_USR_SHIFT;
|
if (uenv->groups[i] == object_gid) {
|
||||||
} else {
|
return true;
|
||||||
gid_t task_gid = getegid();
|
|
||||||
|
|
||||||
if (task_gid == 0 || task_gid == node_gid) {
|
|
||||||
perm_flags <<= RTEMS_FS_GRP_SHIFT;
|
|
||||||
} else {
|
|
||||||
perm_flags <<= RTEMS_FS_OTH_SHIFT;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return (perm_flags & node_mode) == perm_flags;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool rtems_filesystem_check_access(
|
||||||
|
int flags,
|
||||||
|
mode_t object_mode,
|
||||||
|
uid_t object_uid,
|
||||||
|
gid_t object_gid
|
||||||
|
)
|
||||||
|
{
|
||||||
|
const rtems_user_env_t *uenv = rtems_current_user_env_get();
|
||||||
|
mode_t access_flags = flags & RTEMS_FS_PERMS_RWX;
|
||||||
|
uid_t task_uid = uenv->euid;
|
||||||
|
|
||||||
|
if (task_uid == 0 || task_uid == object_uid) {
|
||||||
|
access_flags <<= RTEMS_FS_USR_SHIFT;
|
||||||
|
} else {
|
||||||
|
gid_t task_gid = uenv->egid;
|
||||||
|
|
||||||
|
if (
|
||||||
|
task_gid == 0
|
||||||
|
|| task_gid == object_gid
|
||||||
|
|| equals_supplementary_group(uenv, object_gid)
|
||||||
|
) {
|
||||||
|
access_flags <<= RTEMS_FS_GRP_SHIFT;
|
||||||
|
} else {
|
||||||
|
access_flags <<= RTEMS_FS_OTH_SHIFT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (access_flags & object_mode) == access_flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool rtems_filesystem_eval_path_check_access(
|
bool rtems_filesystem_eval_path_check_access(
|
||||||
|
|||||||
36
cpukit/libcsupport/src/uenvgetgroups.c
Normal file
36
cpukit/libcsupport/src/uenvgetgroups.c
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2014 embedded brains GmbH. All rights reserved.
|
||||||
|
*
|
||||||
|
* embedded brains GmbH
|
||||||
|
* Dornierstr. 4
|
||||||
|
* D-82178 Puchheim
|
||||||
|
* Germany
|
||||||
|
* <rtems@embedded-brains.de>
|
||||||
|
*
|
||||||
|
* The license and distribution terms for this file may be
|
||||||
|
* found in the file LICENSE in this distribution or at
|
||||||
|
* http://www.rtems.org/license/LICENSE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <rtems/userenv.h>
|
||||||
|
#include <rtems.h>
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
void rtems_current_user_env_getgroups(void)
|
||||||
|
{
|
||||||
|
rtems_user_env_t *uenv = rtems_current_user_env_get();
|
||||||
|
int ngroups = (int) RTEMS_ARRAY_SIZE( uenv->groups );
|
||||||
|
|
||||||
|
ngroups = getgroups( ngroups, &uenv->groups[ 0 ] );
|
||||||
|
if ( ngroups > 0 ) {
|
||||||
|
uenv->ngroups = (size_t) ngroups;
|
||||||
|
} else {
|
||||||
|
uenv->ngroups = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -16,6 +16,7 @@
|
|||||||
#include "config.h"
|
#include "config.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define TESTS_USE_PRINTK
|
||||||
#include "tmacros.h"
|
#include "tmacros.h"
|
||||||
|
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
@@ -321,6 +322,175 @@ static void test_user_env(void)
|
|||||||
rtems_test_assert(null_loc->reference_count == 4);
|
rtems_test_assert(null_loc->reference_count == 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int flags;
|
||||||
|
mode_t object_mode;
|
||||||
|
uid_t object_uid;
|
||||||
|
gid_t object_gid;
|
||||||
|
bool expected_ok;
|
||||||
|
} check_access_case;
|
||||||
|
|
||||||
|
#define FR RTEMS_FS_PERMS_READ
|
||||||
|
#define FW RTEMS_FS_PERMS_WRITE
|
||||||
|
#define FX RTEMS_FS_PERMS_EXEC
|
||||||
|
|
||||||
|
#define UR S_IRUSR
|
||||||
|
#define UW S_IWUSR
|
||||||
|
#define UX S_IXUSR
|
||||||
|
|
||||||
|
#define GR S_IRGRP
|
||||||
|
#define GW S_IWGRP
|
||||||
|
#define GX S_IXGRP
|
||||||
|
|
||||||
|
#define OR S_IROTH
|
||||||
|
#define OW S_IWOTH
|
||||||
|
#define OX S_IXOTH
|
||||||
|
|
||||||
|
static const check_access_case check_access_euid_0_cases[] = {
|
||||||
|
{ 0, 0, 6, 7, true },
|
||||||
|
{ FR, 0, 6, 7, false },
|
||||||
|
{ FW, 0, 6, 7, false },
|
||||||
|
{ FX, 0, 6, 7, false },
|
||||||
|
{ FR, UR, 6, 7, true },
|
||||||
|
{ FW, UW, 6, 7, true },
|
||||||
|
{ FX, UX, 6, 7, true },
|
||||||
|
{ FR, GR, 6, 7, false },
|
||||||
|
{ FW, GW, 6, 7, false },
|
||||||
|
{ FX, GX, 6, 7, false },
|
||||||
|
{ FR, OR, 6, 7, false },
|
||||||
|
{ FW, OW, 6, 7, false },
|
||||||
|
{ FX, OX, 6, 7, false }
|
||||||
|
};
|
||||||
|
|
||||||
|
static const check_access_case check_access_egid_0_cases[] = {
|
||||||
|
{ 0, 0, 6, 7, true },
|
||||||
|
{ FR, 0, 6, 7, false },
|
||||||
|
{ FW, 0, 6, 7, false },
|
||||||
|
{ FX, 0, 6, 7, false },
|
||||||
|
{ FR, UR, 6, 7, false },
|
||||||
|
{ FW, UW, 6, 7, false },
|
||||||
|
{ FX, UX, 6, 7, false },
|
||||||
|
{ FR, GR, 6, 7, true },
|
||||||
|
{ FW, GW, 6, 7, true },
|
||||||
|
{ FX, GX, 6, 7, true },
|
||||||
|
{ FR, OR, 6, 7, false },
|
||||||
|
{ FW, OW, 6, 7, false },
|
||||||
|
{ FX, OX, 6, 7, false }
|
||||||
|
};
|
||||||
|
|
||||||
|
static const check_access_case check_access_other_cases[] = {
|
||||||
|
{ 0, 0, 3, 7, true },
|
||||||
|
{ FR, 0, 3, 7, false },
|
||||||
|
{ FW, 0, 3, 7, false },
|
||||||
|
{ FX, 0, 3, 7, false },
|
||||||
|
{ FR, UR, 3, 7, true },
|
||||||
|
{ FW, UW, 3, 7, true },
|
||||||
|
{ FX, UX, 3, 7, true },
|
||||||
|
{ FR, GR, 3, 7, false },
|
||||||
|
{ FW, GW, 3, 7, false },
|
||||||
|
{ FX, GX, 3, 7, false },
|
||||||
|
{ FR, OR, 3, 7, false },
|
||||||
|
{ FW, OW, 3, 7, false },
|
||||||
|
{ FX, OX, 3, 7, false },
|
||||||
|
{ 0, 0, 6, 4, true },
|
||||||
|
{ FR, 0, 6, 4, false },
|
||||||
|
{ FW, 0, 6, 4, false },
|
||||||
|
{ FX, 0, 6, 4, false },
|
||||||
|
{ FR, UR, 6, 4, false },
|
||||||
|
{ FW, UW, 6, 4, false },
|
||||||
|
{ FX, UX, 6, 4, false },
|
||||||
|
{ FR, GR, 6, 4, true },
|
||||||
|
{ FW, GW, 6, 4, true },
|
||||||
|
{ FX, GX, 6, 4, true },
|
||||||
|
{ FR, OR, 6, 4, false },
|
||||||
|
{ FW, OW, 6, 4, false },
|
||||||
|
{ FX, OX, 6, 4, false },
|
||||||
|
{ 0, 0, 6, 5, true },
|
||||||
|
{ FR, 0, 6, 5, false },
|
||||||
|
{ FW, 0, 6, 5, false },
|
||||||
|
{ FX, 0, 6, 5, false },
|
||||||
|
{ FR, UR, 6, 5, false },
|
||||||
|
{ FW, UW, 6, 5, false },
|
||||||
|
{ FX, UX, 6, 5, false },
|
||||||
|
{ FR, GR, 6, 5, true },
|
||||||
|
{ FW, GW, 6, 5, true },
|
||||||
|
{ FX, GX, 6, 5, true },
|
||||||
|
{ FR, OR, 6, 5, false },
|
||||||
|
{ FW, OW, 6, 5, false },
|
||||||
|
{ FX, OX, 6, 5, false },
|
||||||
|
{ 0, 0, 6, 7, true },
|
||||||
|
{ FR, 0, 6, 7, false },
|
||||||
|
{ FW, 0, 6, 7, false },
|
||||||
|
{ FX, 0, 6, 7, false },
|
||||||
|
{ FR, UR, 6, 7, false },
|
||||||
|
{ FW, UW, 6, 7, false },
|
||||||
|
{ FX, UX, 6, 7, false },
|
||||||
|
{ FR, GR, 6, 7, false },
|
||||||
|
{ FW, GW, 6, 7, false },
|
||||||
|
{ FX, GX, 6, 7, false },
|
||||||
|
{ FR, OR, 6, 7, true },
|
||||||
|
{ FW, OW, 6, 7, true },
|
||||||
|
{ FX, OX, 6, 7, true }
|
||||||
|
};
|
||||||
|
|
||||||
|
static void check_access(const check_access_case *table, size_t n)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
for (i = 0; i < n; ++i) {
|
||||||
|
const check_access_case *cac = &table[i];
|
||||||
|
bool ok = rtems_filesystem_check_access(
|
||||||
|
cac->flags,
|
||||||
|
cac->object_mode,
|
||||||
|
cac->object_uid,
|
||||||
|
cac->object_gid
|
||||||
|
);
|
||||||
|
|
||||||
|
rtems_test_assert(ok == cac->expected_ok);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_check_access(void)
|
||||||
|
{
|
||||||
|
rtems_user_env_t *uenv = rtems_current_user_env_get();
|
||||||
|
|
||||||
|
rtems_test_assert(uenv->uid == 0);
|
||||||
|
rtems_test_assert(uenv->gid == 0);
|
||||||
|
rtems_test_assert(uenv->euid == 0);
|
||||||
|
rtems_test_assert(uenv->egid == 0);
|
||||||
|
rtems_test_assert(uenv->ngroups == 0);
|
||||||
|
|
||||||
|
uenv->uid = 1;
|
||||||
|
uenv->gid = 2;
|
||||||
|
|
||||||
|
check_access(
|
||||||
|
&check_access_euid_0_cases[0],
|
||||||
|
RTEMS_ARRAY_SIZE(check_access_euid_0_cases)
|
||||||
|
);
|
||||||
|
|
||||||
|
uenv->euid = 3;
|
||||||
|
|
||||||
|
check_access(
|
||||||
|
&check_access_egid_0_cases[0],
|
||||||
|
RTEMS_ARRAY_SIZE(check_access_egid_0_cases)
|
||||||
|
);
|
||||||
|
|
||||||
|
uenv->egid = 4;
|
||||||
|
uenv->ngroups = 1;
|
||||||
|
uenv->groups[0] = 5;
|
||||||
|
|
||||||
|
check_access(
|
||||||
|
&check_access_other_cases[0],
|
||||||
|
RTEMS_ARRAY_SIZE(check_access_other_cases)
|
||||||
|
);
|
||||||
|
|
||||||
|
uenv->uid = 0;
|
||||||
|
uenv->gid = 0;
|
||||||
|
uenv->euid = 0;
|
||||||
|
uenv->egid = 0;
|
||||||
|
uenv->ngroups = 0;
|
||||||
|
}
|
||||||
|
|
||||||
static void Init(rtems_task_argument arg)
|
static void Init(rtems_task_argument arg)
|
||||||
{
|
{
|
||||||
rtems_test_begink();
|
rtems_test_begink();
|
||||||
@@ -334,6 +504,7 @@ static void Init(rtems_task_argument arg)
|
|||||||
test_null_location_get_and_replace();
|
test_null_location_get_and_replace();
|
||||||
test_path_ops();
|
test_path_ops();
|
||||||
test_user_env();
|
test_user_env();
|
||||||
|
test_check_access();
|
||||||
|
|
||||||
rtems_test_endk();
|
rtems_test_endk();
|
||||||
exit(0);
|
exit(0);
|
||||||
|
|||||||
Reference in New Issue
Block a user