From ed6876e407e6bac44fcd2714919ad6e6602787ac Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Wed, 17 Jun 2026 20:38:07 -0400 Subject: [PATCH] Support clients running in AT_SECURE context When a client application runs in a secure execution context (e.g., setuid, where getauxval(AT_SECURE) is non-zero), environment variables like GSSPROXY_SOCKET are ignored to prevent security issues. This change allows these clients to work by automatically constructing a program-specific socket name (e.g., .) when AT_SECURE is detected. The mechanism interposer now checks if this socket is accessible to decide whether to enable gssproxy. Documentation is updated to guide users on configuring the service for this specific socket. Assisted-by: Gemini Signed-off-by: Simo Sorce --- docs/README.md | 19 ++++++++++++ src/client/gpm_common.c | 65 +++++++++++++++++++++++++++++++++++---- src/client/gssapi_gpm.h | 1 + src/mechglue/gss_plugin.c | 15 +++++++++ 4 files changed, 94 insertions(+), 6 deletions(-) diff --git a/docs/README.md b/docs/README.md index 63471b250..b6deec157 100644 --- a/docs/README.md +++ b/docs/README.md @@ -127,6 +127,25 @@ To configure the client, we need to set another environment variable: `GSSPROXY_SOCKET`. So, we set that in the same way we set `GSS_USE_PROXY` (i.e., `GSSPROXY_SOCKET=/var/lib/gssproxy/my_app.sock`), and launch. +## Clients running in AT_SECURE context + +When a client application is running in a secure execution context (e.g., setuid/setgid programs where `getauxval(AT_SECURE)` returns non-zero), standard environment variables such as `GSSPROXY_SOCKET` are ignored by the gssproxy client to prevent security issues. + +In this case, the gssproxy client automatically constructs the socket name based on the default socket and the program name. For instance, if the program is called `my_app`, the client will try to connect to a socket named `/var/lib/gssproxy/default.sock.my_app` (assuming the default socket path is `/var/lib/gssproxy/default.sock`). + +To provide access to these clients, you can configure your gssproxy service to listen on this specific socket. In your configuration file, add or modify the `socket` directive: + +```INI +[service/my_app] + mechs = krb5 + cred_store = keytab:/etc/path/to.keytab + euid = appuser + program = /usr/local/bin/my_app + socket = /var/lib/gssproxy/default.sock.my_app +``` + +Then reload the gssproxy configuration: `systemctl try-reload-or-restart gssproxy`. This ensures that even in an `AT_SECURE` context, the application can securely communicate with gssproxy using the expected socket. + ## How to know it's working By far the easiest way to tell is to have a configuration working *without* diff --git a/src/client/gpm_common.c b/src/client/gpm_common.c index 2c0925d05..928b9c187 100644 --- a/src/client/gpm_common.c +++ b/src/client/gpm_common.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include @@ -64,17 +65,51 @@ static void gpm_init_once(void) gpm_display_status_init_once(); } +static int get_program_name(char *name, size_t size) +{ + ssize_t ret; + char *p; + + ret = readlink("/proc/self/exe", name, size - 1); + if (ret == -1) { + return errno; + } + name[ret] = '\0'; + + p = strrchr(name, '/'); + if (p) { + p++; + memmove(name, p, ret + 1 - (p - name)); + } + + return 0; +} + static int get_pipe_name(char *name) { const char *socket; - int ret; + unsigned long auxval; + int ret = 1; - socket = gp_getenv("GSSPROXY_SOCKET"); - if (!socket) { - socket = GP_SOCKET_NAME; - } + /* check if this is a "secure" client */ + auxval = getauxval(AT_SECURE); - ret = snprintf(name, PATH_MAX, "%s", socket); + if (auxval == 0) { + /* default case */ + socket = gp_getenv("GSSPROXY_SOCKET"); + if (!socket) { + socket = GP_SOCKET_NAME; + } + + ret = snprintf(name, PATH_MAX, "%s", socket); + } else { + char proc[PATH_MAX]; + ret = get_program_name(proc, sizeof(proc)); + if (ret) { + return ret; + } + ret = snprintf(name, PATH_MAX, "%s.%s", GP_SOCKET_NAME, proc); + } if (ret < 0 || ret >= PATH_MAX) { return ENAMETOOLONG; } @@ -670,6 +705,24 @@ struct gpm_rpc_fn_set { } }; +int gpm_sock_check(void) +{ + struct gpm_ctx *gpmctx; + int ret; + + gpmctx = gpm_get_ctx(); + if (!gpmctx) { + return EFAULT; + } + + ret = gpm_grab_sock(gpmctx); + if (ret == 0) { + gpm_release_sock(gpmctx); + } + + return ret; +} + int gpm_make_call(int proc, union gp_rpc_arg *arg, union gp_rpc_res *res) { struct gpm_ctx *gpmctx; diff --git a/src/client/gssapi_gpm.h b/src/client/gssapi_gpm.h index 164e85e2e..4f6d48df2 100644 --- a/src/client/gssapi_gpm.h +++ b/src/client/gssapi_gpm.h @@ -16,6 +16,7 @@ #include "src/gp_common.h" #include "src/gp_conv.h" +int gpm_sock_check(void); int gpm_make_call(int proc, union gp_rpc_arg *arg, union gp_rpc_res *res); void gpm_free_xdrs(int proc, union gp_rpc_arg *arg, union gp_rpc_res *res); diff --git a/src/mechglue/gss_plugin.c b/src/mechglue/gss_plugin.c index c7982d1f8..0e423dd44 100644 --- a/src/mechglue/gss_plugin.c +++ b/src/mechglue/gss_plugin.c @@ -2,6 +2,7 @@ #include "gss_plugin.h" #include +#include #include #include @@ -76,8 +77,22 @@ const gss_OID_desc gssproxy_mech_interposer = { static bool enabled(void) { char *envval; + unsigned long auxval; bool ret = GSS_ALWAYS_INTERPOSE; + /* check if this is a "secure" client */ + auxval = getauxval(AT_SECURE); + + /* in "secure" clients gp_getenv(0 always fails (it uses secure_getenv), + * therefore for "secure" clients we check if we can access the per + * client secure socket if available */ + if (auxval != 0) { + int check = gpm_sock_check(); + if (check == 0) { + return true; + } + } + /* avoid looping in the gssproxy daemon by avoiding to interpose * any mechanism */ envval = gp_getenv("GSS_USE_PROXY");