From b8bd90f68fb787cc321365c6de161d6b77c8353f Mon Sep 17 00:00:00 2001 From: Sebastian Huber Date: Mon, 17 Nov 2014 09:01:53 +0100 Subject: Add supplementary groups to user environment --- cpukit/include/rtems/userenv.h | 74 ++++++++++++++++++++--- cpukit/libcsupport/Makefile.am | 1 + cpukit/libcsupport/include/rtems/libio_.h | 27 +++++++-- cpukit/libcsupport/src/sup_fs_check_permissions.c | 47 ++++++++++---- cpukit/libcsupport/src/uenvgetgroups.c | 36 +++++++++++ 5 files changed, 159 insertions(+), 26 deletions(-) create mode 100644 cpukit/libcsupport/src/uenvgetgroups.c (limited to 'cpukit') diff --git a/cpukit/include/rtems/userenv.h b/cpukit/include/rtems/userenv.h index 631d773ae5..7d6ffb05a5 100644 --- a/cpukit/include/rtems/userenv.h +++ b/cpukit/include/rtems/userenv.h @@ -25,6 +25,7 @@ * limits.h is supposed to provide _POSIX_LOGIN_NAME_MAX * XXX: We do not rely on this. */ +#include #include #include @@ -52,18 +53,64 @@ extern "C" { #endif #endif +/** + * @brief User environment. + */ typedef struct { + /** + * @brief The anchor directory for relative paths. + */ rtems_filesystem_global_location_t *current_directory; + + /** + * @brief The anchor directory for absolute paths. + */ rtems_filesystem_global_location_t *root_directory; - /* Default mode for all files. */ - mode_t umask; - /* _POSIX_types */ - uid_t uid; - gid_t gid; - uid_t euid; - gid_t egid; - char login_buffer[LOGIN_NAME_MAX]; - pid_t pgrp; /* process group id */ + + /** + * @brief The file mode creation mask. + */ + mode_t umask; + + /** + * @brief The real user 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; 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); +/** + * @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 diff --git a/cpukit/libcsupport/Makefile.am b/cpukit/libcsupport/Makefile.am index 6803fe6036..bd3f90a648 100644 --- a/cpukit/libcsupport/Makefile.am +++ b/cpukit/libcsupport/Makefile.am @@ -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_exit.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 \ src/cfsetospeed.c src/tcgetattr.c src/tcsetattr.c src/tcdrain.c \ diff --git a/cpukit/libcsupport/include/rtems/libio_.h b/cpukit/libcsupport/include/rtems/libio_.h index c0f4432d0e..458201ea3f 100644 --- a/cpukit/libcsupport/include/rtems/libio_.h +++ b/cpukit/libcsupport/include/rtems/libio_.h @@ -810,11 +810,30 @@ int rtems_filesystem_location_exists_in_same_instance_as( 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( - int eval_flags, - mode_t node_mode, - uid_t node_uid, - gid_t node_gid + int flags, + mode_t object_mode, + uid_t object_uid, + gid_t object_gid ); bool rtems_filesystem_eval_path_check_access( diff --git a/cpukit/libcsupport/src/sup_fs_check_permissions.c b/cpukit/libcsupport/src/sup_fs_check_permissions.c index f6fd0e91c9..394f945b0b 100644 --- a/cpukit/libcsupport/src/sup_fs_check_permissions.c +++ b/cpukit/libcsupport/src/sup_fs_check_permissions.c @@ -70,29 +70,50 @@ RTEMS_STATIC_ASSERT( S_IXOTH ); +static bool equals_supplementary_group( + const rtems_user_env_t *uenv, + gid_t object_gid +) +{ + size_t i; + + for (i = 0; i < uenv->ngroups; ++i) { + if (uenv->groups[i] == object_gid) { + return true; + } + } + + return false; +} + bool rtems_filesystem_check_access( - int eval_flags, - mode_t node_mode, - uid_t node_uid, - gid_t node_gid + int flags, + mode_t object_mode, + uid_t object_uid, + gid_t object_gid ) { - mode_t perm_flags = eval_flags & RTEMS_FS_PERMS_RWX; - uid_t task_uid = geteuid(); + 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 == node_uid) { - perm_flags <<= RTEMS_FS_USR_SHIFT; + if (task_uid == 0 || task_uid == object_uid) { + access_flags <<= RTEMS_FS_USR_SHIFT; } else { - gid_t task_gid = getegid(); + gid_t task_gid = uenv->egid; - if (task_gid == 0 || task_gid == node_gid) { - perm_flags <<= RTEMS_FS_GRP_SHIFT; + if ( + task_gid == 0 + || task_gid == object_gid + || equals_supplementary_group(uenv, object_gid) + ) { + access_flags <<= RTEMS_FS_GRP_SHIFT; } else { - perm_flags <<= RTEMS_FS_OTH_SHIFT; + access_flags <<= RTEMS_FS_OTH_SHIFT; } } - return (perm_flags & node_mode) == perm_flags; + return (access_flags & object_mode) == access_flags; } bool rtems_filesystem_eval_path_check_access( diff --git a/cpukit/libcsupport/src/uenvgetgroups.c b/cpukit/libcsupport/src/uenvgetgroups.c new file mode 100644 index 0000000000..9645a9618b --- /dev/null +++ b/cpukit/libcsupport/src/uenvgetgroups.c @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2014 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * D-82178 Puchheim + * Germany + * + * + * 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 +#include + +#include +#include + +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; + } +} -- cgit v1.2.3