context: add XKB_CONTEXT_NO_SECURE_GETENV flag (#312)
authorRonan Pigott <ronan@rjp.ie>
Fri, 16 Dec 2022 08:26:25 +0000 (01:26 -0700)
committerGitHub <noreply@github.com>
Fri, 16 Dec 2022 08:26:25 +0000 (10:26 +0200)
This flag is useful for clients that may have relatively benign capabilities
set, like CAP_SYS_NICE, that also want to use the xkb configuration from the
environment and user configs in XDG_CONFIG_HOME.

Fixes: https://github.com/xkbcommon/libxkbcommon/issues/308
Fixes: https://github.com/xkbcommon/libxkbcommon/issues/129
Signed-off-by: Ran Benita <ran@unusedvar.com>
include/xkbcommon/xkbcommon.h
include/xkbcommon/xkbregistry.h
src/compose/parser.c
src/compose/paths.c
src/compose/paths.h
src/compose/table.c
src/context-priv.c
src/context.c
src/context.h
src/registry.c
src/xkbcomp/rules.c

index c2b099f..7cb46f3 100644 (file)
@@ -580,9 +580,17 @@ enum xkb_context_flags {
     XKB_CONTEXT_NO_DEFAULT_INCLUDES = (1 << 0),
     /**
      * Don't take RMLVO names from the environment.
+     *
      * @since 0.3.0
      */
-    XKB_CONTEXT_NO_ENVIRONMENT_NAMES = (1 << 1)
+    XKB_CONTEXT_NO_ENVIRONMENT_NAMES = (1 << 1),
+    /**
+     * Disable the use of secure_getenv for this context, so that privileged
+     * processes can use environment variables. Client uses at their own risk.
+     *
+     * @since 1.5.0
+     */
+    XKB_CONTEXT_NO_SECURE_GETENV = (1 << 2)
 };
 
 /**
index 4e7e926..7be0c9b 100644 (file)
@@ -163,6 +163,13 @@ enum rxkb_context_flags {
      * on the lookup behavior.
      */
     RXKB_CONTEXT_LOAD_EXOTIC_RULES = (1 << 1),
+    /**
+     * Disable the use of secure_getenv for this context, so that privileged
+     * processes can use environment variables. Client uses at their own risk.
+     *
+     * @since 1.5.0
+     */
+    RXKB_CONTEXT_NO_SECURE_GETENV = (1 << 2)
 };
 
 /**
index 0bd4571..f84b314 100644 (file)
@@ -262,7 +262,7 @@ lex_include_string(struct scanner *s, struct xkb_compose_table *table,
                 scanner_buf_append(s, '%');
             }
             else if (scanner_chr(s, 'H')) {
-                const char *home = secure_getenv("HOME");
+                const char *home = xkb_context_getenv(table->ctx, "HOME");
                 if (!home) {
                     scanner_err(s, "%%H was used in an include statement, but the HOME environment variable is not set");
                     return TOK_ERROR;
@@ -273,7 +273,7 @@ lex_include_string(struct scanner *s, struct xkb_compose_table *table,
                 }
             }
             else if (scanner_chr(s, 'L')) {
-                char *path = get_locale_compose_file_path(table->locale);
+                char *path = get_locale_compose_file_path(table->ctx, table->locale);
                 if (!path) {
                     scanner_err(s, "failed to expand %%L to the locale Compose file");
                     return TOK_ERROR;
@@ -286,7 +286,7 @@ lex_include_string(struct scanner *s, struct xkb_compose_table *table,
                 free(path);
             }
             else if (scanner_chr(s, 'S')) {
-                const char *xlocaledir = get_xlocaledir_path();
+                const char *xlocaledir = get_xlocaledir_path(table->ctx);
                 if (!scanner_buf_appends(s, xlocaledir)) {
                     scanner_err(s, "include path after expanding %%S is too long");
                     return TOK_ERROR;
index dab71ac..fd88623 100644 (file)
 
 #include "config.h"
 
+#include "xkbcommon/xkbcommon.h"
 #include "utils.h"
+#include "context.h"
 #include "paths.h"
-#include "utils.h"
 
 enum resolve_name_direction {
     LEFT_TO_RIGHT,
@@ -33,9 +34,9 @@ enum resolve_name_direction {
 };
 
 const char *
-get_xlocaledir_path(void)
+get_xlocaledir_path(struct xkb_context *ctx)
 {
-    const char *dir = secure_getenv("XLOCALEDIR");
+    const char *dir = xkb_context_getenv(ctx, "XLOCALEDIR");
     if (!dir)
         dir = XLOCALEDIR;
     return dir;
@@ -47,8 +48,8 @@ get_xlocaledir_path(void)
  * @filename is relative to the xlocaledir.
  */
 static char *
-resolve_name(const char *filename, enum resolve_name_direction direction,
-             const char *name)
+resolve_name(struct xkb_context *ctx, const char *filename,
+             enum resolve_name_direction direction, const char *name)
 {
     int ret;
     bool ok;
@@ -62,7 +63,7 @@ resolve_name(const char *filename, enum resolve_name_direction direction,
     char *match;
     size_t left_len, right_len, name_len;
 
-    xlocaledir = get_xlocaledir_path();
+    xlocaledir = get_xlocaledir_path(ctx);
 
     ret = snprintf(path, sizeof(path), "%s/%s", xlocaledir, filename);
     if (ret < 0 || (size_t) ret >= sizeof(path))
@@ -137,27 +138,27 @@ resolve_name(const char *filename, enum resolve_name_direction direction,
 }
 
 char *
-resolve_locale(const char *locale)
+resolve_locale(struct xkb_context *ctx, const char *locale)
 {
-    char *alias = resolve_name("locale.alias", LEFT_TO_RIGHT, locale);
+    char *alias = resolve_name(ctx, "locale.alias", LEFT_TO_RIGHT, locale);
     return alias ? alias : strdup(locale);
 }
 
 char *
-get_xcomposefile_path(void)
+get_xcomposefile_path(struct xkb_context *ctx)
 {
-    return strdup_safe(secure_getenv("XCOMPOSEFILE"));
+    return strdup_safe(xkb_context_getenv(ctx, "XCOMPOSEFILE"));
 }
 
 char *
-get_xdg_xcompose_file_path(void)
+get_xdg_xcompose_file_path(struct xkb_context *ctx)
 {
     const char *xdg_config_home;
     const char *home;
 
-    xdg_config_home = secure_getenv("XDG_CONFIG_HOME");
+    xdg_config_home = xkb_context_getenv(ctx, "XDG_CONFIG_HOME");
     if (!xdg_config_home || xdg_config_home[0] != '/') {
-        home = secure_getenv("HOME");
+        home = xkb_context_getenv(ctx, "HOME");
         if (!home)
             return NULL;
         return asprintf_safe("%s/.config/XCompose", home);
@@ -167,11 +168,11 @@ get_xdg_xcompose_file_path(void)
 }
 
 char *
-get_home_xcompose_file_path(void)
+get_home_xcompose_file_path(struct xkb_context *ctx)
 {
     const char *home;
 
-    home = secure_getenv("HOME");
+    home = xkb_context_getenv(ctx, "HOME");
     if (!home)
         return NULL;
 
@@ -179,7 +180,7 @@ get_home_xcompose_file_path(void)
 }
 
 char *
-get_locale_compose_file_path(const char *locale)
+get_locale_compose_file_path(struct xkb_context *ctx, const char *locale)
 {
     char *resolved;
     char *path;
@@ -198,7 +199,7 @@ get_locale_compose_file_path(const char *locale)
     if (streq(locale, "C"))
         locale = "en_US.UTF-8";
 
-    resolved = resolve_name("compose.dir", RIGHT_TO_LEFT, locale);
+    resolved = resolve_name(ctx, "compose.dir", RIGHT_TO_LEFT, locale);
     if (!resolved)
         return NULL;
 
@@ -206,7 +207,7 @@ get_locale_compose_file_path(const char *locale)
         path = resolved;
     }
     else {
-        const char *xlocaledir = get_xlocaledir_path();
+        const char *xlocaledir = get_xlocaledir_path(ctx);
         path = asprintf_safe("%s/%s", xlocaledir, resolved);
         free(resolved);
     }
index bc5150f..8170aef 100644 (file)
 #define COMPOSE_RESOLVE_H
 
 char *
-resolve_locale(const char *locale);
+resolve_locale(struct xkb_context *ctx, const char *locale);
 
 const char *
-get_xlocaledir_path(void);
+get_xlocaledir_path(struct xkb_context *ctx);
 
 char *
-get_xcomposefile_path(void);
+get_xcomposefile_path(struct xkb_context *ctx);
 
 char *
-get_xdg_xcompose_file_path(void);
+get_xdg_xcompose_file_path(struct xkb_context *ctx);
 
 char *
-get_home_xcompose_file_path(void);
+get_home_xcompose_file_path(struct xkb_context *ctx);
 
 char *
-get_locale_compose_file_path(const char *locale);
+get_locale_compose_file_path(struct xkb_context *ctx, const char *locale);
 
 #endif
index 8a8d11f..ea5e45a 100644 (file)
@@ -38,7 +38,7 @@ xkb_compose_table_new(struct xkb_context *ctx,
     struct xkb_compose_table *table;
     struct compose_node dummy;
 
-    resolved_locale = resolve_locale(locale);
+    resolved_locale = resolve_locale(ctx, locale);
     if (!resolved_locale)
         return NULL;
 
@@ -174,7 +174,7 @@ xkb_compose_table_new_from_locale(struct xkb_context *ctx,
     if (!table)
         return NULL;
 
-    path = get_xcomposefile_path();
+    path = get_xcomposefile_path(ctx);
     if (path) {
         file = fopen(path, "rb");
         if (file)
@@ -182,7 +182,7 @@ xkb_compose_table_new_from_locale(struct xkb_context *ctx,
     }
     free(path);
 
-    path = get_xdg_xcompose_file_path();
+    path = get_xdg_xcompose_file_path(ctx);
     if (path) {
         file = fopen(path, "rb");
         if (file)
@@ -190,7 +190,7 @@ xkb_compose_table_new_from_locale(struct xkb_context *ctx,
     }
     free(path);
 
-    path = get_home_xcompose_file_path();
+    path = get_home_xcompose_file_path(ctx);
     if (path) {
         file = fopen(path, "rb");
         if (file)
@@ -198,7 +198,7 @@ xkb_compose_table_new_from_locale(struct xkb_context *ctx,
     }
     free(path);
 
-    path = get_locale_compose_file_path(table->locale);
+    path = get_locale_compose_file_path(ctx, table->locale);
     if (path) {
         file = fopen(path, "rb");
         if (file)
index 8eaa579..e94385f 100644 (file)
 #include "utils.h"
 #include "context.h"
 
+char *
+xkb_context_getenv(struct xkb_context *ctx, const char *name)
+{
+    if (ctx->use_secure_getenv) {
+        return secure_getenv(name);
+    } else {
+        return getenv(name);
+    }
+}
+
 unsigned int
 xkb_context_num_failed_include_paths(struct xkb_context *ctx)
 {
@@ -105,7 +115,7 @@ xkb_context_get_default_rules(struct xkb_context *ctx)
     const char *env = NULL;
 
     if (ctx->use_environment_names)
-        env = secure_getenv("XKB_DEFAULT_RULES");
+        env = xkb_context_getenv(ctx, "XKB_DEFAULT_RULES");
 
     return env ? env : DEFAULT_XKB_RULES;
 }
@@ -116,7 +126,7 @@ xkb_context_get_default_model(struct xkb_context *ctx)
     const char *env = NULL;
 
     if (ctx->use_environment_names)
-        env = secure_getenv("XKB_DEFAULT_MODEL");
+        env = xkb_context_getenv(ctx, "XKB_DEFAULT_MODEL");
 
     return env ? env : DEFAULT_XKB_MODEL;
 }
@@ -127,7 +137,7 @@ xkb_context_get_default_layout(struct xkb_context *ctx)
     const char *env = NULL;
 
     if (ctx->use_environment_names)
-        env = secure_getenv("XKB_DEFAULT_LAYOUT");
+        env = xkb_context_getenv(ctx, "XKB_DEFAULT_LAYOUT");
 
     return env ? env : DEFAULT_XKB_LAYOUT;
 }
@@ -136,12 +146,12 @@ static const char *
 xkb_context_get_default_variant(struct xkb_context *ctx)
 {
     const char *env = NULL;
-    const char *layout = secure_getenv("XKB_DEFAULT_LAYOUT");
+    const char *layout = xkb_context_getenv(ctx, "XKB_DEFAULT_LAYOUT");
 
     /* We don't want to inherit the variant if they haven't also set a
      * layout, since they're so closely paired. */
     if (layout && ctx->use_environment_names)
-        env = secure_getenv("XKB_DEFAULT_VARIANT");
+        env = xkb_context_getenv(ctx, "XKB_DEFAULT_VARIANT");
 
     return env ? env : DEFAULT_XKB_VARIANT;
 }
@@ -152,7 +162,7 @@ xkb_context_get_default_options(struct xkb_context *ctx)
     const char *env = NULL;
 
     if (ctx->use_environment_names)
-        env = secure_getenv("XKB_DEFAULT_OPTIONS");
+        env = xkb_context_getenv(ctx, "XKB_DEFAULT_OPTIONS");
 
     return env ? env : DEFAULT_XKB_OPTIONS;
 }
index 5701a74..b8b214b 100644 (file)
@@ -34,6 +34,7 @@
 #include "utils.h"
 #include "context.h"
 
+
 /**
  * Append one directory to the context's include path.
  */
@@ -77,14 +78,14 @@ err:
 const char *
 xkb_context_include_path_get_extra_path(struct xkb_context *ctx)
 {
-    const char *extra = secure_getenv("XKB_CONFIG_EXTRA_PATH");
+    const char *extra = xkb_context_getenv(ctx, "XKB_CONFIG_EXTRA_PATH");
     return extra ? extra : DFLT_XKB_CONFIG_EXTRA_PATH;
 }
 
 const char *
 xkb_context_include_path_get_system_path(struct xkb_context *ctx)
 {
-    const char *root = secure_getenv("XKB_CONFIG_ROOT");
+    const char *root = xkb_context_getenv(ctx, "XKB_CONFIG_ROOT");
     return root ? root : DFLT_XKB_CONFIG_ROOT;
 }
 
@@ -98,9 +99,9 @@ xkb_context_include_path_append_default(struct xkb_context *ctx)
     char *user_path;
     int ret = 0;
 
-    home = secure_getenv("HOME");
+    home = xkb_context_getenv(ctx, "HOME");
 
-    xdg = secure_getenv("XDG_CONFIG_HOME");
+    xdg = xkb_context_getenv(ctx, "XDG_CONFIG_HOME");
     if (xdg != NULL) {
         user_path = asprintf_safe("%s/xkb", xdg);
         if (user_path) {
@@ -289,13 +290,15 @@ xkb_context_new(enum xkb_context_flags flags)
     ctx->log_fn = default_log_fn;
     ctx->log_level = XKB_LOG_LEVEL_ERROR;
     ctx->log_verbosity = 0;
+    ctx->use_environment_names = !(flags & XKB_CONTEXT_NO_ENVIRONMENT_NAMES);
+    ctx->use_secure_getenv = !(flags & XKB_CONTEXT_NO_SECURE_GETENV);
 
     /* Environment overwrites defaults. */
-    env = secure_getenv("XKB_LOG_LEVEL");
+    env = xkb_context_getenv(ctx, "XKB_LOG_LEVEL");
     if (env)
         xkb_context_set_log_level(ctx, log_level(env));
 
-    env = secure_getenv("XKB_LOG_VERBOSITY");
+    env = xkb_context_getenv(ctx, "XKB_LOG_VERBOSITY");
     if (env)
         xkb_context_set_log_verbosity(ctx, log_verbosity(env));
 
@@ -307,8 +310,6 @@ xkb_context_new(enum xkb_context_flags flags)
         return NULL;
     }
 
-    ctx->use_environment_names = !(flags & XKB_CONTEXT_NO_ENVIRONMENT_NAMES);
-
     ctx->atom_table = atom_table_new();
     if (!ctx->atom_table) {
         xkb_context_unref(ctx);
index 44367cc..488bfad 100644 (file)
@@ -53,8 +53,12 @@ struct xkb_context {
     size_t text_next;
 
     unsigned int use_environment_names : 1;
+    unsigned int use_secure_getenv : 1;
 };
 
+char *
+xkb_context_getenv(struct xkb_context *ctx, const char *name);
+
 unsigned int
 xkb_context_num_failed_include_paths(struct xkb_context *ctx);
 
index dbaac2a..0c42a3b 100644 (file)
@@ -72,6 +72,7 @@ struct rxkb_context {
     enum context_state context_state;
 
     bool load_extra_rules_files;
+    bool use_secure_getenv;
 
     struct list models;         /* list of struct rxkb_models */
     struct list layouts;        /* list of struct rxkb_layouts */
@@ -437,6 +438,17 @@ DECLARE_REF_UNREF_FOR_TYPE(rxkb_context);
 DECLARE_CREATE_FOR_TYPE(rxkb_context);
 DECLARE_TYPED_GETTER_FOR_TYPE(rxkb_context, log_level, enum rxkb_log_level);
 
+static char *
+rxkb_context_getenv(struct rxkb_context *ctx, const char *name)
+{
+    if (ctx->use_secure_getenv) {
+        return secure_getenv(name);
+    } else {
+        return getenv(name);
+    }
+}
+
+
 XKB_EXPORT void
 rxkb_context_set_log_level(struct rxkb_context *ctx,
                            enum rxkb_log_level level)
@@ -508,11 +520,12 @@ rxkb_context_new(enum rxkb_context_flags flags)
 
     ctx->context_state = CONTEXT_NEW;
     ctx->load_extra_rules_files = flags & RXKB_CONTEXT_LOAD_EXOTIC_RULES;
+    ctx->use_secure_getenv = !(flags & RXKB_CONTEXT_NO_SECURE_GETENV);
     ctx->log_fn = default_log_fn;
     ctx->log_level = RXKB_LOG_LEVEL_ERROR;
 
     /* Environment overwrites defaults. */
-    env = secure_getenv("RXKB_LOG_LEVEL");
+    env = rxkb_context_getenv(ctx, "RXKB_LOG_LEVEL");
     if (env)
         rxkb_context_set_log_level(ctx, log_level(env));
 
@@ -593,9 +606,9 @@ rxkb_context_include_path_append_default(struct rxkb_context *ctx)
         return false;
     }
 
-    home = secure_getenv("HOME");
+    home = rxkb_context_getenv(ctx, "HOME");
 
-    xdg = secure_getenv("XDG_CONFIG_HOME");
+    xdg = rxkb_context_getenv(ctx, "XDG_CONFIG_HOME");
     if (xdg != NULL) {
         user_path = asprintf_safe("%s/xkb", xdg);
         if (user_path) {
@@ -619,13 +632,13 @@ rxkb_context_include_path_append_default(struct rxkb_context *ctx)
         }
     }
 
-    extra = secure_getenv("XKB_CONFIG_EXTRA_PATH");
+    extra = rxkb_context_getenv(ctx, "XKB_CONFIG_EXTRA_PATH");
     if (extra != NULL)
         ret |= rxkb_context_include_path_append(ctx, extra);
     else
         ret |= rxkb_context_include_path_append(ctx, DFLT_XKB_CONFIG_EXTRA_PATH);
 
-    root = secure_getenv("XKB_CONFIG_ROOT");
+    root = rxkb_context_getenv(ctx, "XKB_CONFIG_ROOT");
     if (root != NULL)
         ret |= rxkb_context_include_path_append(ctx, root);
     else
index 2d3d9d8..8029682 100644 (file)
@@ -382,7 +382,7 @@ matcher_include(struct matcher *m, struct scanner *parent_scanner,
                 scanner_buf_append(&s, '%');
             }
             else if (scanner_chr(&s, 'H')) {
-                const char *home = secure_getenv("HOME");
+                const char *home = xkb_context_getenv(m->ctx, "HOME");
                 if (!home) {
                     scanner_err(&s, "%%H was used in an include statement, but the HOME environment variable is not set");
                     return;