From cf53c06d8c89926284a15f6c27d60cf31761e622 Mon Sep 17 00:00:00 2001 From: David Goulet Date: Wed, 16 Jul 2014 15:50:31 -0400 Subject: [PATCH] Fix: validate file path creds in autoload mode Validate the credentials only when in auto load mode for the auto/ directory. The lttng load command now checks the session file creds and validate if it's readable before trying to do so. Thus with this, a user can load a session from the system wide directory as long as she/he has the rights to read it. Signed-off-by: David Goulet --- doc/man/lttng-sessiond.8 | 2 +- doc/man/lttng.1 | 7 ++- src/common/config/config.c | 90 +++++++++++++++++++++++++++++--------- 3 files changed, 76 insertions(+), 23 deletions(-) diff --git a/doc/man/lttng-sessiond.8 b/doc/man/lttng-sessiond.8 index bc03fb0b3..782a9bb18 100644 --- a/doc/man/lttng-sessiond.8 +++ b/doc/man/lttng-sessiond.8 @@ -130,7 +130,7 @@ Specify path from which to automatically load session configuration(s). .PP By default, the session daemon tries to load session configuration(s) located in the user default directory \fB~/.lttng/sessions/auto/\fP and in the system -wide one in \fB/etc/lttng/sessions/auto\fP. Note that the directory containing +wide one in \fB/etc/lttng/sessions/auto/\fP. Note that the directory containing the session's configuration and lttng-sessiond MUST have the same UID for them to be automatically loaded. diff --git a/doc/man/lttng.1 b/doc/man/lttng.1 index cd0aae294..12ca33d6f 100644 --- a/doc/man/lttng.1 +++ b/doc/man/lttng.1 @@ -750,7 +750,9 @@ Load tracing session configuration If NAME is omitted, all session configurations found in both the user's session configuration directory (default: ~/.lttng/sessions/) and the system session -configuration directory (default: /etc/lttng/sessions/) will be loaded. +configuration directory (default: /etc/lttng/sessions/) will be loaded. Note +that the sessions in the user directory are loaded first and then the system +wide directory are loaded. .B OPTIONS: @@ -781,6 +783,9 @@ If SESSION is omitted, all session configurations will be saved to individual ~/.lttng/sessions/). The default session configuration file naming scheme is \fBSESSION.lttng\fP. +For instance, a user in the tracing group saving a session from a root session +daemon will save it in her/his user directory. + .B OPTIONS: .TP diff --git a/src/common/config/config.c b/src/common/config/config.c index 8c926b53e..bfb2576f4 100644 --- a/src/common/config/config.c +++ b/src/common/config/config.c @@ -2338,6 +2338,31 @@ error: return ret; } +/* + * Return 1 if the given path is readable by the current UID or 0 if not. + * Return -1 if the path is EPERM. + */ +static int validate_file_read_creds(const char *path) +{ + int ret; + + assert(path); + + /* Can we read the file. */ + ret = access(path, R_OK); + if (!ret) { + goto valid; + } + if (errno == EACCES) { + return -1; + } else { + /* Invalid. */ + return 0; + } +valid: + return 1; +} + static int load_session_from_file(const char *path, const char *session_name, struct session_config_validation_ctx *validation_ctx, int override) @@ -2346,14 +2371,17 @@ int load_session_from_file(const char *path, const char *session_name, xmlDocPtr doc = NULL; xmlNodePtr sessions_node; xmlNodePtr session_node; - struct stat sb; assert(path); assert(validation_ctx); - ret = stat(path, &sb); - if (ret) { - ret = -LTTNG_ERR_LOAD_SESSION_NOENT; + ret = validate_file_read_creds(path); + if (ret != 1) { + if (ret == -1) { + ret = -LTTNG_ERR_EPERM; + } else { + ret = -LTTNG_ERR_LOAD_SESSION_NOENT; + } goto end; } @@ -2506,7 +2534,7 @@ end: /* * Validate that the given path's credentials and the current process have the - * same UID. If so, return 0 else return 1 if it does NOT match. + * same UID. If so, return 1 else return 0 if it does NOT match. */ static int validate_path_creds(const char *path) { @@ -2515,7 +2543,7 @@ static int validate_path_creds(const char *path) assert(path); - if (uid != 0) { + if (uid == 0) { goto valid; } @@ -2533,9 +2561,9 @@ static int validate_path_creds(const char *path) } valid: - return 0; -invalid: return 1; +invalid: + return 0; } LTTNG_HIDDEN @@ -2543,6 +2571,7 @@ int config_load_session(const char *path, const char *session_name, int override, unsigned int autoload) { int ret; + const char *path_ptr = NULL; struct session_config_validation_ctx validation_ctx = { 0 }; ret = init_session_config_validation_ctx(&validation_ctx); @@ -2567,18 +2596,31 @@ int config_load_session(const char *path, const char *session_name, ret = snprintf(path, sizeof(path), DEFAULT_SESSION_HOME_CONFIGPATH "/" DEFAULT_SESSION_CONFIG_AUTOLOAD, home_path); + if (ret < 0) { + PERROR("snprintf session autoload home config path"); + goto end; + } + + /* + * Credentials are only validated for the autoload in order to + * avoid any user session daemon to try to load kernel sessions + * automatically and failing all the times. + */ + ret = validate_path_creds(path); + if (ret) { + path_ptr = path; + } } else { ret = snprintf(path, sizeof(path), DEFAULT_SESSION_HOME_CONFIGPATH, home_path); + if (ret < 0) { + PERROR("snprintf session home config path"); + goto end; + } + path_ptr = path; } - if (ret < 0) { - PERROR("snprintf session home config path"); - goto end; - } - - ret = validate_path_creds(path); - if (!ret && autoload) { - ret = load_session_from_path(path, session_name, + if (path_ptr) { + ret = load_session_from_path(path_ptr, session_name, &validation_ctx, override); if (ret && ret != -LTTNG_ERR_LOAD_SESSION_NOENT) { goto end; @@ -2590,19 +2632,25 @@ int config_load_session(const char *path, const char *session_name, } } + /* Reset path pointer for the system wide dir. */ + path_ptr = NULL; + /* Try system wide configuration directory. */ if (autoload) { sys_path = DEFAULT_SESSION_SYSTEM_CONFIGPATH "/" DEFAULT_SESSION_CONFIG_AUTOLOAD; + ret = validate_path_creds(sys_path); + if (ret) { + path_ptr = sys_path; + } } else { - sys_path = DEFAULT_SESSION_HOME_CONFIGPATH; + sys_path = DEFAULT_SESSION_SYSTEM_CONFIGPATH; + path_ptr = sys_path; } - ret = validate_path_creds(sys_path); - if (!ret && autoload) { - ret = load_session_from_path(sys_path, session_name, + if (path_ptr) { + ret = load_session_from_path(path_ptr, session_name, &validation_ctx, override); - goto end; } } else { ret = access(path, F_OK); -- 2.34.1