From 2ea778eb55be426f0362acfed746b21923f4fd68 Mon Sep 17 00:00:00 2001 From: Oleg Girko Date: Thu, 24 Jul 2014 00:58:12 +0100 Subject: [PATCH 01/11] Don't use pmc_dont_resolve_final_symlink flag for ".." removal. The pmc_dont_resolve_final_symlink flag is stored in path mapping context (path_mapping_context_t type) and is set to true when resolving pathnames for symlink-reading functions (like lstat(), for example). However, we want to resolve the final symlink on parts of pathname before ".." path component when cleaning such components from the pathname. This change makes clean_dotdots_from_path() function to pass context with cleared pmc_dont_resolve_final_symlink flag to recursive calls to sb_path_resolution() function. Signed-off-by: Oleg Girko --- scratchbox2/pathmapping/pathresolution.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/scratchbox2/pathmapping/pathresolution.c b/scratchbox2/pathmapping/pathresolution.c index 28d9504..85ec43a 100644 --- a/scratchbox2/pathmapping/pathresolution.c +++ b/scratchbox2/pathmapping/pathresolution.c @@ -175,6 +175,17 @@ void clean_dotdots_from_path( { struct path_entry *work; int path_has_nontrivial_dotdots = 0; + path_mapping_context_t ctx2; + + /* Don't propagate pmc_dont_resolve_final_symlink flag + * to further recursive path resolution: + * we need to resolve final symlink before ".." component. + */ + if (ctx->pmc_dont_resolve_final_symlink) { + ctx2 = *ctx; + ctx2.pmc_dont_resolve_final_symlink = 0; + ctx = &ctx2; + } if (SB_LOG_IS_ACTIVE(SB_LOGLEVEL_NOISE)) { char *tmp_path_buf = path_list_to_string(abs_path); From d740e1ffef0414610a303bcd4e2f5053419349af Mon Sep 17 00:00:00 2001 From: Oleg Girko Date: Fri, 25 Jul 2014 01:40:02 +0100 Subject: [PATCH 02/11] Don't ignore path resolution errors when cleaning ".." from paths. The clean_dotdots_from_path() function was ignoring path resolution errors when calling sb_path_resolution() function. The reason for that was that clean_dotdots_from_path() function was returning void and had no way to report failure to the caller. This change makes clean_dotdots_from_path() return int to report errors. Zero result means that there was no error. Otherwise, errno code is returned. All calling functions were modified to use this error code and report errors to their respective callers. Signed-off-by: Oleg Girko --- scratchbox2/include/mapping.h | 3 +- scratchbox2/pathmapping/pathlistutils.c | 7 ++- scratchbox2/pathmapping/pathmapping.h | 2 +- scratchbox2/pathmapping/pathresolution.c | 52 ++++++++++++++++--- .../pathmapping/paths_ruletree_mapping.c | 6 +++ scratchbox2/preload/chrootgate.c | 9 +++- 6 files changed, 68 insertions(+), 11 deletions(-) diff --git a/scratchbox2/include/mapping.h b/scratchbox2/include/mapping.h index 94dea88..abdbc43 100644 --- a/scratchbox2/include/mapping.h +++ b/scratchbox2/include/mapping.h @@ -84,7 +84,8 @@ extern char *sbox_virtual_path_to_abs_virtual_path( const char *binary_name, const char *func_name, uint32_t fn_class, - const char *virtual_orig_path); + const char *virtual_orig_path, + int *res_errno); extern void sbox_map_path_for_sb2show(const char *binary_name, const char *func_name, const char *path, mapping_results_t *res); diff --git a/scratchbox2/pathmapping/pathlistutils.c b/scratchbox2/pathmapping/pathlistutils.c index 1cc3fe6..0aac091 100644 --- a/scratchbox2/pathmapping/pathlistutils.c +++ b/scratchbox2/pathmapping/pathlistutils.c @@ -400,7 +400,12 @@ char *clean_and_log_fs_mapping_result( * recursive calls to sb_path_resolution. */ remove_dots_from_path_list(&list); - clean_dotdots_from_path(ctx, &list); + if (clean_dotdots_from_path(ctx, &list)) { + SB_LOG(result_log_level, "fail: %s '%s'", + ctx->pmc_func_name, abs_clean_virtual_path); + free_path_list(&list); + return(NULL); + } break; } cleaned_host_path = path_list_to_string(&list); diff --git a/scratchbox2/pathmapping/pathmapping.h b/scratchbox2/pathmapping/pathmapping.h index 8f14414..95da52f 100644 --- a/scratchbox2/pathmapping/pathmapping.h +++ b/scratchbox2/pathmapping/pathmapping.h @@ -151,7 +151,7 @@ extern ruletree_object_offset_t ruletree_get_mapping_requirements( extern void remove_dots_from_path_list(struct path_entry_list *listp); /* "complex" path cleaning (may call path resolution recursively): */ -extern void clean_dotdots_from_path( +extern int clean_dotdots_from_path( const path_mapping_context_t *ctx, struct path_entry_list *abs_path); diff --git a/scratchbox2/pathmapping/pathresolution.c b/scratchbox2/pathmapping/pathresolution.c index 85ec43a..a499d42 100644 --- a/scratchbox2/pathmapping/pathresolution.c +++ b/scratchbox2/pathmapping/pathresolution.c @@ -169,7 +169,7 @@ static ruletree_object_offset_t sb_path_resolution( * by accident. * Can be used for both virtual paths and host paths. */ -void clean_dotdots_from_path( +int clean_dotdots_from_path( const path_mapping_context_t *ctx, struct path_entry_list *abs_path) { @@ -326,6 +326,16 @@ void clean_dotdots_from_path( } free_path_list(&abs_path_to_parent); + if (resolved_parent_location.mres_errno) { + int err = resolved_parent_location.mres_errno; + SB_LOG(SB_LOGLEVEL_NOISE, + "clean_dotdots_from_path: <3>:errno=%d", + err); + free(orig_path_to_parent); + free_mapping_results(&resolved_parent_location); + return(err); + } + /* mres_result_buf contains an absolute path, * unless the result was longer than PATH_MAX */ if (strcmp(orig_path_to_parent, @@ -366,8 +376,7 @@ void clean_dotdots_from_path( free_mapping_results(&resolved_parent_location); /* restart from the beginning of the new path: */ - clean_dotdots_from_path(ctx, abs_path); - return; + return(clean_dotdots_from_path(ctx, abs_path)); } SB_LOG(SB_LOGLEVEL_NOISE, @@ -395,6 +404,7 @@ void clean_dotdots_from_path( "clean_dotdots_from_path: result->'%s'", tmp_path_buf); free(tmp_path_buf); } + return(0); } /* ========== ========== */ @@ -742,6 +752,7 @@ static ruletree_object_offset_t sb_path_resolution_resolve_symlink( ruletree_object_offset_t rule_offs; struct path_entry *rest_of_virtual_path = NULL; struct path_entry_list new_abs_virtual_link_dest_path_list; + int err; new_abs_virtual_link_dest_path_list.pl_first = NULL; @@ -888,7 +899,15 @@ static ruletree_object_offset_t sb_path_resolution_resolve_symlink( break; case 2: /* .. */ remove_dots_from_path_list(&new_abs_virtual_link_dest_path_list); - clean_dotdots_from_path(ctx, &new_abs_virtual_link_dest_path_list); + err = clean_dotdots_from_path(ctx, &new_abs_virtual_link_dest_path_list); + if (err) { + SB_LOG(SB_LOGLEVEL_DEBUG, + "unable to clean \"..\" from path, errno=%d", + err); + free_path_list(&new_abs_virtual_link_dest_path_list); + resolved_virtual_path_res->mres_errno = err; + return(0); + } break; } @@ -1029,12 +1048,14 @@ char *sbox_virtual_path_to_abs_virtual_path( const char *binary_name, const char *func_name, uint32_t fn_class, - const char *virtual_orig_path) + const char *virtual_orig_path, + int *res_errno) { path_mapping_context_t ctx; struct path_entry_list abs_virtual_path_list; char *result = NULL; char host_cwd[PATH_MAX + 1]; + int err; clear_path_entry_list(&abs_virtual_path_list); @@ -1104,7 +1125,16 @@ char *sbox_virtual_path_to_abs_virtual_path( break; case 2: /* .. */ remove_dots_from_path_list(&abs_virtual_path_list); - clean_dotdots_from_path(&ctx, &abs_virtual_path_list); + err = clean_dotdots_from_path(&ctx, &abs_virtual_path_list); + if (err) { + SB_LOG(SB_LOGLEVEL_DEBUG, + "unable to clean \"..\" from path, errno=%d", + err); + free_path_list(&abs_virtual_path_list); + *res_errno = err; + result = NULL; + goto out; + } break; } @@ -1164,6 +1194,7 @@ void sbox_map_path_internal__c_engine( path_mapping_context_t ctx; char host_cwd[PATH_MAX + 1]; /* used only if virtual_orig_path is relative */ struct path_entry_list abs_virtual_path_for_rule_selection_list; + int err; clear_path_entry_list(&abs_virtual_path_for_rule_selection_list); clear_path_mapping_context(&ctx); @@ -1279,7 +1310,14 @@ void sbox_map_path_internal__c_engine( break; case 2: /* .. */ remove_dots_from_path_list(&abs_virtual_path_for_rule_selection_list); - clean_dotdots_from_path(&ctx, &abs_virtual_path_for_rule_selection_list); + err = clean_dotdots_from_path(&ctx, &abs_virtual_path_for_rule_selection_list); + if (err) { + SB_LOG(SB_LOGLEVEL_DEBUG, + "unable to clean \"..\" from path, errno=%d", + err); + res->mres_errno = err; + return; + } break; } diff --git a/scratchbox2/pathmapping/paths_ruletree_mapping.c b/scratchbox2/pathmapping/paths_ruletree_mapping.c index 24e41ae..cdf8490 100644 --- a/scratchbox2/pathmapping/paths_ruletree_mapping.c +++ b/scratchbox2/pathmapping/paths_ruletree_mapping.c @@ -826,6 +826,12 @@ char *ruletree_translate_path( } else { char *new_host_path = clean_and_log_fs_mapping_result(ctx, abs_clean_virtual_path, result_log_level, host_path, *flagsp); + if (new_host_path == NULL) { + SB_LOG(result_log_level, + "Mapping failed ('%s')", + abs_clean_virtual_path); + *errormsgp = "Mapping failed"; + } free(host_path); host_path = new_host_path; } diff --git a/scratchbox2/preload/chrootgate.c b/scratchbox2/preload/chrootgate.c index 4f70218..a42f508 100644 --- a/scratchbox2/preload/chrootgate.c +++ b/scratchbox2/preload/chrootgate.c @@ -62,12 +62,19 @@ int chroot_gate(int *result_errno_ptr, /* sbox_virtual_path_to_abs_virtual_path() will clean it */ new_chroot_path = sbox_virtual_path_to_abs_virtual_path( sbox_binary_name, realfnname, SB2_INTERFACE_CLASS_CHROOT, - path2); + path2, result_errno_ptr); } else { /* "path" is relative to CWD. */ new_chroot_path = sbox_virtual_path_to_abs_virtual_path( sbox_binary_name, realfnname, SB2_INTERFACE_CLASS_CHROOT, + path, result_errno_ptr); + } + + if (new_chroot_path == NULL) { + SB_LOG(SB_LOGLEVEL_DEBUG, + "chroot: unable to make virtual path absolute: %s", path); + goto free_mapping_results_and_return_minus1; } if (!strcmp(new_chroot_path, "/")) { From 3070dc3274ab2df6dc01d90a961099252ab2b17b Mon Sep 17 00:00:00 2001 From: Oleg Girko Date: Sat, 26 Jul 2014 01:02:39 +0100 Subject: [PATCH 03/11] Don't ignore path mapping error in preparation for exec. This change adds check for path mapping error in prepare_exec(). Result of path mapping makes no sense if mapping failed. In this case, returning error immediately is more reasonable than trying to perform further steps, like inspecting binary file, which should fail anyway, but possibly with misleading errno. Signed-off-by: Oleg Girko --- scratchbox2/execs/sb_exec.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/scratchbox2/execs/sb_exec.c b/scratchbox2/execs/sb_exec.c index 61ae917..75a61ac 100644 --- a/scratchbox2/execs/sb_exec.c +++ b/scratchbox2/execs/sb_exec.c @@ -1462,6 +1462,17 @@ static int prepare_exec(const char *exec_fn_name, exec_policy_name = (mapping_result.mres_exec_policy_name ? strdup(mapping_result.mres_exec_policy_name) : NULL); STOP_AND_REPORT_PROCESSCLOCK(SB_LOGLEVEL_INFO, &clk3, mapped_file); + + if (mapping_result.mres_errno) { + int saved_errno = mapping_result.mres_errno; + SB_LOG(SB_LOGLEVEL_DEBUG, + "Mapping failed (%s) => errno=%d", + my_file, mapping_result.mres_errno); + free_mapping_results(&mapping_result); + errno = saved_errno; + ret = -1; + goto out; + } free_mapping_results(&mapping_result); From c9c6d56819e42b2d4196dba88e5f8cc650e48f5b Mon Sep 17 00:00:00 2001 From: Oleg Girko Date: Fri, 25 Jul 2014 02:22:37 +0100 Subject: [PATCH 04/11] Fail path resolution early on symlink detection error. This change makes path resolution return error if check whether a path component is a symlink returns any error except EINVAL (not a symlink). Last component check is also allowed to fail with ENOENT (file doesn't exist) unless it's required to exist (last component before ".." is required to exist). This is needed to make cleaning ".." components from path fail on nonexistent files preceding ".." part. For example, "/nonexistent/../bin" was resolving the same way as "/bin" without this change, but it should fail instead. See https://bugs.merproject.org/show_bug.cgi?id=834 for details. Signed-off-by: Oleg Girko --- scratchbox2/pathmapping/pathmapping.h | 1 + scratchbox2/pathmapping/pathresolution.c | 30 +++++++++++++++++++----- 2 files changed, 25 insertions(+), 6 deletions(-) diff --git a/scratchbox2/pathmapping/pathmapping.h b/scratchbox2/pathmapping/pathmapping.h index 95da52f..dd3bdda 100644 --- a/scratchbox2/pathmapping/pathmapping.h +++ b/scratchbox2/pathmapping/pathmapping.h @@ -86,6 +86,7 @@ typedef struct path_mapping_context_s { uint32_t pmc_fn_class; const char *pmc_virtual_orig_path; int pmc_dont_resolve_final_symlink; + int pmc_file_must_exist; struct sb2context *pmc_sb2ctx; /* for paths_ruletree_mapping.c: */ diff --git a/scratchbox2/pathmapping/pathresolution.c b/scratchbox2/pathmapping/pathresolution.c index a499d42..0e5c672 100644 --- a/scratchbox2/pathmapping/pathresolution.c +++ b/scratchbox2/pathmapping/pathresolution.c @@ -180,12 +180,12 @@ int clean_dotdots_from_path( /* Don't propagate pmc_dont_resolve_final_symlink flag * to further recursive path resolution: * we need to resolve final symlink before ".." component. + * Also, path before ".." must be an existing directory. */ - if (ctx->pmc_dont_resolve_final_symlink) { - ctx2 = *ctx; - ctx2.pmc_dont_resolve_final_symlink = 0; - ctx = &ctx2; - } + ctx2 = *ctx; + ctx2.pmc_dont_resolve_final_symlink = 0; + ctx2.pmc_file_must_exist = 1; + ctx = &ctx2; if (SB_LOG_IS_ACTIVE(SB_LOGLEVEL_NOISE)) { char *tmp_path_buf = path_list_to_string(abs_path); @@ -634,8 +634,26 @@ static ruletree_object_offset_t sb_path_resolution( link_dest[link_len] = '\0'; virtual_path_work_ptr->pe_link_dest = strdup(link_dest); virtual_path_work_ptr->pe_flags |= PATH_FLAGS_IS_SYMLINK; - } else { + } else if (errno == EINVAL) { + /* was not a symlink */ virtual_path_work_ptr->pe_flags |= PATH_FLAGS_NOT_SYMLINK; + } else if (errno == ENOENT && + !ctx->pmc_file_must_exist && + (virtual_path_work_ptr->pe_next == NULL)) { + /* this is last component, + * and it's not required to exist. + */ + SB_LOG(SB_LOGLEVEL_NOISE2, + "Last component doesn't exist [%d] '%s'", + component_index, virtual_path_work_ptr->pe_path_component); + } else { + /* any other errno valus is error */ + resolved_virtual_path_res->mres_errno = errno; + SB_LOG(SB_LOGLEVEL_NOISE, + "Path resolution failed, errno=%d", + resolved_virtual_path_res->mres_errno); + free(prefix_mapping_result_host_path); + return(0); } } From 0b84b1f2533979deb216d80b90f3590de163070c Mon Sep 17 00:00:00 2001 From: Oleg Girko Date: Sat, 26 Jul 2014 01:33:49 +0100 Subject: [PATCH 05/11] Handle errno more carefully if path mapping failed preparing for exec. Avoid possible errno overwriting when printing debug output. Signed-off-by: Oleg Girko --- scratchbox2/execs/sb_exec.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/scratchbox2/execs/sb_exec.c b/scratchbox2/execs/sb_exec.c index 75a61ac..635e1b4 100644 --- a/scratchbox2/execs/sb_exec.c +++ b/scratchbox2/execs/sb_exec.c @@ -1675,8 +1675,10 @@ static int prepare_exec(const char *exec_fn_name, *new_file = mapped_file; *new_argv = my_argv; *new_envp = my_envp; + err = errno; STOP_AND_REPORT_PROCESSCLOCK(SB_LOGLEVEL_INFO, &clk1, orig_file); if (info.pt_interp) free(info.pt_interp); + errno = err; return(ret); } @@ -1723,15 +1725,17 @@ int do_exec(int *result_errno_ptr, &type, &new_file, &new_argv, &new_envp); if (SB_LOG_IS_ACTIVE(SB_LOGLEVEL_DEBUG)) { + int saved_errno = errno; /* find out and log if preprocessing did something */ compare_and_log_strvec_changes("argv", orig_argv, new_argv); compare_and_log_strvec_changes("envp", my_envp_copy, new_envp); + errno = saved_errno; } if (r < 0) { + *result_errno_ptr = errno; SB_LOG(SB_LOGLEVEL_DEBUG, "EXEC denied by prepare_exec(), %s", orig_file); - *result_errno_ptr = errno; STOP_AND_REPORT_PROCESSCLOCK(SB_LOGLEVEL_INFO, &clk1, "Exec denied"); return(r); /* exec denied */ } From bd03e81688b0e37ed966aff620003fd947be76ed Mon Sep 17 00:00:00 2001 From: Oleg Girko Date: Mon, 28 Jul 2014 21:53:36 +0100 Subject: [PATCH 06/11] Fix path splitting algorithm to handle multiple trailing slashes. The old algorithm was detecting just a single trailing slash correctly, creating bogus empty path entry at the end of path entry list in case of multiple trailing slashes. Signed-off-by: Oleg Girko --- scratchbox2/pathmapping/pathlistutils.c | 27 +++++++++++++------------ 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/scratchbox2/pathmapping/pathlistutils.c b/scratchbox2/pathmapping/pathlistutils.c index 0aac091..ce79a7e 100644 --- a/scratchbox2/pathmapping/pathlistutils.c +++ b/scratchbox2/pathmapping/pathlistutils.c @@ -188,23 +188,24 @@ struct path_entry *split_path_to_path_entries( } do { + int len; + next_slash = strchr(start, '/'); + if (next_slash) { + len = next_slash - start; + } else { + /* no more slashes */ + len = strlen(start); + } /* ignore empty strings resulting from // */ - if (next_slash != start) { + if (len == 0) { + /* but notice if there is trailing slash */ + if (!next_slash) + flags |= PATH_FLAGS_HAS_TRAILING_SLASH; + } else { struct path_entry *new; - int len; - - if (next_slash) { - len = next_slash - start; - if (!next_slash[1]) { - flags |= PATH_FLAGS_HAS_TRAILING_SLASH; - next_slash = NULL; - } - } else { - /* no more slashes */ - len = strlen(start); - } + new = malloc(sizeof(struct path_entry) + len); if(!first) first = new; if (!new) abort(); From 1a119500c60e0b97cb0a083c9a5ab481f794bdf4 Mon Sep 17 00:00:00 2001 From: Oleg Girko Date: Tue, 29 Jul 2014 00:14:31 +0100 Subject: [PATCH 07/11] Fix relative path resolution inheriting trailing slash flag from cwd. This fixes a bug in resolving relative pathnames when current working directory is target's root: cwd is resolved to "/" which has trailing slash flag, and this flag was inherited by the full resolved pathname, which led to adding trailing slash to resolved pathname. Signed-off-by: Oleg Girko --- scratchbox2/pathmapping/pathresolution.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scratchbox2/pathmapping/pathresolution.c b/scratchbox2/pathmapping/pathresolution.c index 0e5c672..67613a3 100644 --- a/scratchbox2/pathmapping/pathresolution.c +++ b/scratchbox2/pathmapping/pathresolution.c @@ -1041,7 +1041,7 @@ static int relative_virtual_path_to_abs_path( set_flags_in_path_entries(cwd_entries, PATH_FLAGS_NOT_SYMLINK); path_list->pl_first = append_path_entries( cwd_entries, path_list->pl_first); - path_list->pl_flags |= cwd_flags; + path_list->pl_flags |= cwd_flags & ~PATH_FLAGS_HAS_TRAILING_SLASH; #if 0 SB_LOG(SB_LOGLEVEL_DEBUG, "relative_virtual_path_to_abs_path: abs.path is '%s'", From 6d87c141c94c2f941ca3939cd13a9c1acc8a7c84 Mon Sep 17 00:00:00 2001 From: Oleg Girko Date: Wed, 30 Jul 2014 18:21:42 +0100 Subject: [PATCH 08/11] Check whether last path component before ".." is a directory. This change makes path resolution fail when a path component before ".." is not a directory (or symlink pointing to a directory, but this is covered by a different code path). Signed-off-by: Oleg Girko --- scratchbox2/pathmapping/pathmapping.h | 1 + scratchbox2/pathmapping/pathresolution.c | 22 ++++++++++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/scratchbox2/pathmapping/pathmapping.h b/scratchbox2/pathmapping/pathmapping.h index dd3bdda..928ce16 100644 --- a/scratchbox2/pathmapping/pathmapping.h +++ b/scratchbox2/pathmapping/pathmapping.h @@ -87,6 +87,7 @@ typedef struct path_mapping_context_s { const char *pmc_virtual_orig_path; int pmc_dont_resolve_final_symlink; int pmc_file_must_exist; + int pmc_must_be_directory; struct sb2context *pmc_sb2ctx; /* for paths_ruletree_mapping.c: */ diff --git a/scratchbox2/pathmapping/pathresolution.c b/scratchbox2/pathmapping/pathresolution.c index 67613a3..184250f 100644 --- a/scratchbox2/pathmapping/pathresolution.c +++ b/scratchbox2/pathmapping/pathresolution.c @@ -84,6 +84,7 @@ #include "libsb2.h" #include "exported.h" #include "sb2_vperm.h" +#include "sb2_stat.h" #ifdef EXTREME_DEBUGGING #include @@ -185,6 +186,7 @@ int clean_dotdots_from_path( ctx2 = *ctx; ctx2.pmc_dont_resolve_final_symlink = 0; ctx2.pmc_file_must_exist = 1; + ctx2.pmc_must_be_directory = 1; ctx = &ctx2; if (SB_LOG_IS_ACTIVE(SB_LOGLEVEL_NOISE)) { @@ -636,6 +638,26 @@ static ruletree_object_offset_t sb_path_resolution( virtual_path_work_ptr->pe_flags |= PATH_FLAGS_IS_SYMLINK; } else if (errno == EINVAL) { /* was not a symlink */ + if (ctx->pmc_must_be_directory && + virtual_path_work_ptr->pe_next == NULL) { + /* must be a directory, check it */ + struct stat statbuf; + if (real_stat(prefix_mapping_result_host_path, &statbuf) < 0) { + resolved_virtual_path_res->mres_errno = errno; + SB_LOG(SB_LOGLEVEL_NOISE, + "Path resolution failed, unable to stat directory, errno=%d", + resolved_virtual_path_res->mres_errno); + free(prefix_mapping_result_host_path); + return(0); + } + if (!S_ISDIR(statbuf.st_mode)) { + resolved_virtual_path_res->mres_errno = ENOTDIR; + SB_LOG(SB_LOGLEVEL_NOISE, + "Path resolution failed, last component is not a directory"); + free(prefix_mapping_result_host_path); + return(0); + } + } virtual_path_work_ptr->pe_flags |= PATH_FLAGS_NOT_SYMLINK; } else if (errno == ENOENT && !ctx->pmc_file_must_exist && From 413e09e637f13823f5c2348d4387e5bcc86af694 Mon Sep 17 00:00:00 2001 From: Oleg Girko Date: Fri, 3 Oct 2014 14:44:48 +0100 Subject: [PATCH 09/11] Change dont_resolve_final_symlink argument of sbox_map_path() to flags. This refactoring changes a single dont_resolve_final_symlink flag into more generic flags argument, allowing more flags to be added later. SBOX_MAP_PATH_DONT_RESOLVE_FINAL_SYMLINK value of flags argument is used instead of non-zero dont_resolve_final_symlink argument. Signed-off-by: Oleg Girko --- scratchbox2/include/mapping.h | 8 ++++--- scratchbox2/pathmapping/pathmapping.h | 4 ++-- scratchbox2/pathmapping/pathmapping_interf.c | 22 ++++++++++---------- scratchbox2/pathmapping/pathresolution.c | 5 +++-- scratchbox2/preload/gen-interface.pl | 14 +++++++++++-- scratchbox2/preload/miscgates.c | 4 ++-- scratchbox2/preload/network.c | 2 +- 7 files changed, 36 insertions(+), 23 deletions(-) diff --git a/scratchbox2/include/mapping.h b/scratchbox2/include/mapping.h index abdbc43..dc0b6ec 100644 --- a/scratchbox2/include/mapping.h +++ b/scratchbox2/include/mapping.h @@ -73,11 +73,13 @@ extern void free_mapping_results(mapping_results_t *res); extern void force_path_to_mapping_result(mapping_results_t *res, const char *path); +#define SBOX_MAP_PATH_DONT_RESOLVE_FINAL_SYMLINK 0x01 + extern void sbox_map_path(const char *func_name, const char *path, - int dont_resolve_final_symlink, mapping_results_t *res, uint32_t classmask); + uint32_t flags, mapping_results_t *res, uint32_t classmask); extern void sbox_map_path_at(const char *func_name, int dirfd, - const char *path, int dont_resolve_final_symlink, + const char *path, uint32_t flags, mapping_results_t *res, uint32_t classmask); extern char *sbox_virtual_path_to_abs_virtual_path( @@ -95,7 +97,7 @@ extern void sbox_map_path_for_exec(const char *func_name, const char *path, extern void custom_map_path(const char *binary_name, const char *func_name, const char *virtual_path, - int dont_resolve_final_symlink, uint32_t fn_class, + uint32_t flags, uint32_t fn_class, mapping_results_t *res, ruletree_object_offset_t rule_list_offset); extern char *custom_map_abstract_path( diff --git a/scratchbox2/pathmapping/pathmapping.h b/scratchbox2/pathmapping/pathmapping.h index 928ce16..053c537 100644 --- a/scratchbox2/pathmapping/pathmapping.h +++ b/scratchbox2/pathmapping/pathmapping.h @@ -162,7 +162,7 @@ extern void sbox_map_path_internal__lua_engine( const char *binary_name, const char *func_name, const char *virtual_orig_path, - int dont_resolve_final_symlink, + uint32_t flags, int process_path_for_exec, uint32_t fn_class, mapping_results_t *res); @@ -172,7 +172,7 @@ extern void sbox_map_path_internal__c_engine( const char *binary_name, const char *func_name, const char *virtual_orig_path, - int dont_resolve_final_symlink, + uint32_t flags, int process_path_for_exec, uint32_t fn_class, mapping_results_t *res, diff --git a/scratchbox2/pathmapping/pathmapping_interf.c b/scratchbox2/pathmapping/pathmapping_interf.c index 095f697..fdc0c90 100644 --- a/scratchbox2/pathmapping/pathmapping_interf.c +++ b/scratchbox2/pathmapping/pathmapping_interf.c @@ -29,7 +29,7 @@ static void fwd_map_path( const char *binary_name, const char *func_name, const char *virtual_path, - int dont_resolve_final_symlink, + uint32_t flags, int exec_mode, uint32_t fn_class, mapping_results_t *res) @@ -49,7 +49,7 @@ static void fwd_map_path( START_PROCESSCLOCK(SB_LOGLEVEL_INFO, &clk1, "fwd_map_path"); sbox_map_path_internal__c_engine(sb2ctx, binary_name, func_name, virtual_path, - dont_resolve_final_symlink, 0, fn_class, res, 0); + flags, 0, fn_class, res, 0); if (res->mres_errormsg) { SB_LOG(SB_LOGLEVEL_NOTICE, "C path mapping engine failed (%s) (%s)", @@ -70,7 +70,7 @@ void custom_map_path( const char *binary_name, const char *func_name, const char *virtual_path, - int dont_resolve_final_symlink, + uint32_t flags, uint32_t fn_class, mapping_results_t *res, ruletree_object_offset_t rule_list_offset) @@ -91,7 +91,7 @@ void custom_map_path( sbox_map_path_internal__c_engine(sb2ctx, binary_name, func_name, virtual_path, - dont_resolve_final_symlink, 0, fn_class, res, rule_list_offset); + flags, 0, fn_class, res, rule_list_offset); if (res->mres_fallback_to_lua_mapping_engine && (res->mres_fallback_to_lua_mapping_engine[0] == '#')) { @@ -217,20 +217,20 @@ void sbox_map_path_for_sb2show( } fwd_map_path(binary_name, func_name, virtual_path, - 0/*dont_resolve_final_symlink*/, 0/*exec_mode*/, fn_class, res); + 0/*flags*/, 0/*exec_mode*/, fn_class, res); } void sbox_map_path( const char *func_name, const char *virtual_path, - int dont_resolve_final_symlink, + uint32_t flags, mapping_results_t *res, uint32_t classmask) { fwd_map_path( (sbox_binary_name ? sbox_binary_name : "UNKNOWN"), func_name, virtual_path, - dont_resolve_final_symlink, 0/*exec_mode*/, classmask, res); + flags, 0/*exec_mode*/, classmask, res); } @@ -238,7 +238,7 @@ void sbox_map_path_at( const char *func_name, int dirfd, const char *virtual_path, - int dont_resolve_final_symlink, + uint32_t flags, mapping_results_t *res, uint32_t classmask) { @@ -259,7 +259,7 @@ void sbox_map_path_at( fwd_map_path( (sbox_binary_name ? sbox_binary_name : "UNKNOWN"), func_name, virtual_path, - dont_resolve_final_symlink, 0/*exec_mode*/, classmask, res); + flags, 0/*exec_mode*/, classmask, res); return; } @@ -281,7 +281,7 @@ void sbox_map_path_at( fwd_map_path( (sbox_binary_name ? sbox_binary_name : "UNKNOWN"), func_name, - virtual_abs_path_at_fd, dont_resolve_final_symlink, 0/*exec_mode*/, classmask, res); + virtual_abs_path_at_fd, flags, 0/*exec_mode*/, classmask, res); free(virtual_abs_path_at_fd); return; @@ -307,7 +307,7 @@ void sbox_map_path_for_exec( fwd_map_path( (sbox_binary_name ? sbox_binary_name : "UNKNOWN"), func_name, - virtual_path, 0/*dont_resolve_final_symlink*/, 1/*exec mode*/, + virtual_path, 0/*flags*/, 1/*exec mode*/, SB2_INTERFACE_CLASS_EXEC, res); } diff --git a/scratchbox2/pathmapping/pathresolution.c b/scratchbox2/pathmapping/pathresolution.c index 184250f..8ed7a91 100644 --- a/scratchbox2/pathmapping/pathresolution.c +++ b/scratchbox2/pathmapping/pathresolution.c @@ -1224,7 +1224,7 @@ void sbox_map_path_internal__c_engine( const char *binary_name, const char *func_name, const char *virtual_orig_path, - int dont_resolve_final_symlink, + uint32_t flags, int process_path_for_exec, uint32_t fn_class, mapping_results_t *res, @@ -1242,7 +1242,8 @@ void sbox_map_path_internal__c_engine( ctx.pmc_func_name = func_name; ctx.pmc_fn_class = fn_class; ctx.pmc_virtual_orig_path = virtual_orig_path; - ctx.pmc_dont_resolve_final_symlink = dont_resolve_final_symlink; + ctx.pmc_dont_resolve_final_symlink = + flags & SBOX_MAP_PATH_DONT_RESOLVE_FINAL_SYMLINK; ctx.pmc_sb2ctx = sb2ctx; #if 0 /* see comment at pathmapping_interf.c/custom_map_path() */ ctx.pmc_rule_list_offset = rule_list_offset; diff --git a/scratchbox2/preload/gen-interface.pl b/scratchbox2/preload/gen-interface.pl index f231dd1..e2c1c9c 100755 --- a/scratchbox2/preload/gen-interface.pl +++ b/scratchbox2/preload/gen-interface.pl @@ -485,6 +485,14 @@ sub class_list_to_expr { return ('('.join(' | ',@class_arr).')'); } +sub expr_to_flagexpr { + my $expr = shift; + my $flag = shift; + return "0" if ($expr eq "0"); + return $flag if $expr eq "1"; + return "($expr ? $flag : 0)"; +} + # Process the modifier section coming from the original input line. # This returns undef if failed, or a structure containing code fragments # and other information for the actual code generation phase. @@ -563,7 +571,8 @@ sub process_wrap_or_gate_modifiers { my $param_to_be_mapped = $1; my $new_name = "mapped__".$param_to_be_mapped; - my $no_symlink_resolve = $mods->{'dont_resolve_final_symlink'}; + my $no_symlink_resolve = + expr_to_flagexpr($mods->{'dont_resolve_final_symlink'}, "SBOX_MAP_PATH_DONT_RESOLVE_FINAL_SYMLINK"); $mods->{'mapped_params_by_orig_name'}->{$param_to_be_mapped} = "res_$new_name.mres_result_path"; $mods->{'mapping_results_by_orig_name'}->{$param_to_be_mapped} = "res_$new_name"; @@ -615,7 +624,8 @@ sub process_wrap_or_gate_modifiers { my $new_name = "mapped__".$param_to_be_mapped; my $ro_flag = $param_to_be_mapped."_is_readonly"; - my $no_symlink_resolve = $mods->{'dont_resolve_final_symlink'}; + my $no_symlink_resolve = + expr_to_flagexpr($mods->{'dont_resolve_final_symlink'}, "SBOX_MAP_PATH_DONT_RESOLVE_FINAL_SYMLINK"); $mods->{'mapped_params_by_orig_name'}->{$param_to_be_mapped} = "res_$new_name.mres_result_path"; $mods->{'mapping_results_by_orig_name'}->{$param_to_be_mapped} = "res_$new_name"; diff --git a/scratchbox2/preload/miscgates.c b/scratchbox2/preload/miscgates.c index 36f34cf..2cfacdb 100644 --- a/scratchbox2/preload/miscgates.c +++ b/scratchbox2/preload/miscgates.c @@ -63,7 +63,7 @@ FTS * fts_open_gate( clear_mapping_results_struct(&res); path = *p; sbox_map_path(realfnname, path, - 0/*dont_resolve_final_symlink*/, &res, + 0/*flags*/, &res, SB2_INTERFACE_CLASS_FTSOPEN); if (res.mres_result_path) { /* Mapped OK */ @@ -354,7 +354,7 @@ static char *check_and_prepare_glob_pattern( */ if (*pattern == '/') { /* if absolute path in pattern.. */ mapped__pattern = sbox_map_path(realfnname, pattern, - NULL/*RO-flag*/, 0/*dont_resolve_final_symlink*/, + NULL/*RO-flag*/, 0/*flags*/, SB2_INTERFACE_CLASS_GLOB); if (!strcmp(mapped__pattern, pattern)) { /* no change */ diff --git a/scratchbox2/preload/network.c b/scratchbox2/preload/network.c index 7ea3017..16da514 100644 --- a/scratchbox2/preload/network.c +++ b/scratchbox2/preload/network.c @@ -84,7 +84,7 @@ static void map_sockaddr_un( clear_mapping_results_struct(&res); /* FIXME: implement if(pathname_is_readonly!=0)... */ sbox_map_path(realfnname, orig_serv_addr_un->sun_path, - 0/*dont_resolve_final_symlink*/, &res, SB2_INTERFACE_CLASS_SOCKADDR); + 0/*flags*/, &res, SB2_INTERFACE_CLASS_SOCKADDR); if (res.mres_result_path == NULL) { SB_LOG(SB_LOGLEVEL_ERROR, "%s: Failed to map AF_UNIX address '%s'", From 319629aaa99c89e3f02bb1624d709d3bd48075d4 Mon Sep 17 00:00:00 2001 From: Oleg Girko Date: Fri, 3 Oct 2014 18:02:10 +0100 Subject: [PATCH 10/11] Add SBOX_MAP_PATH_ALLOW_NONEXISTENT flag to sbox_map_path(). This flag allows path resolution to succeed even if non-final components in the pathname refer to nonexistent directories. This is needed for emulating bindtextdomain() function which can accept pathname refering to nonexistent directory without returning an error. Signed-off-by: Oleg Girko --- scratchbox2/include/mapping.h | 1 + scratchbox2/pathmapping/pathmapping.h | 1 + scratchbox2/pathmapping/pathresolution.c | 9 ++++++ scratchbox2/preload/gen-interface.pl | 40 ++++++++++++++++++++++-- scratchbox2/preload/sb_l10n.c | 4 ++- 5 files changed, 52 insertions(+), 3 deletions(-) diff --git a/scratchbox2/include/mapping.h b/scratchbox2/include/mapping.h index dc0b6ec..ca5c841 100644 --- a/scratchbox2/include/mapping.h +++ b/scratchbox2/include/mapping.h @@ -74,6 +74,7 @@ extern void free_mapping_results(mapping_results_t *res); extern void force_path_to_mapping_result(mapping_results_t *res, const char *path); #define SBOX_MAP_PATH_DONT_RESOLVE_FINAL_SYMLINK 0x01 +#define SBOX_MAP_PATH_ALLOW_NONEXISTENT 0x02 extern void sbox_map_path(const char *func_name, const char *path, uint32_t flags, mapping_results_t *res, uint32_t classmask); diff --git a/scratchbox2/pathmapping/pathmapping.h b/scratchbox2/pathmapping/pathmapping.h index 053c537..089ee3c 100644 --- a/scratchbox2/pathmapping/pathmapping.h +++ b/scratchbox2/pathmapping/pathmapping.h @@ -88,6 +88,7 @@ typedef struct path_mapping_context_s { int pmc_dont_resolve_final_symlink; int pmc_file_must_exist; int pmc_must_be_directory; + int pmc_allow_nonexistent; struct sb2context *pmc_sb2ctx; /* for paths_ruletree_mapping.c: */ diff --git a/scratchbox2/pathmapping/pathresolution.c b/scratchbox2/pathmapping/pathresolution.c index 8ed7a91..b1a0fc2 100644 --- a/scratchbox2/pathmapping/pathresolution.c +++ b/scratchbox2/pathmapping/pathresolution.c @@ -668,6 +668,14 @@ static ruletree_object_offset_t sb_path_resolution( SB_LOG(SB_LOGLEVEL_NOISE2, "Last component doesn't exist [%d] '%s'", component_index, virtual_path_work_ptr->pe_path_component); + } else if (errno == ENOENT && + ctx->pmc_allow_nonexistent) { + /* this is not last component, + * but it's still not required to exist. + */ + SB_LOG(SB_LOGLEVEL_NOISE3, + "Component doesn't exist [%d] '%s'", + component_index, virtual_path_work_ptr->pe_path_component); } else { /* any other errno valus is error */ resolved_virtual_path_res->mres_errno = errno; @@ -1244,6 +1252,7 @@ void sbox_map_path_internal__c_engine( ctx.pmc_virtual_orig_path = virtual_orig_path; ctx.pmc_dont_resolve_final_symlink = flags & SBOX_MAP_PATH_DONT_RESOLVE_FINAL_SYMLINK; + ctx.pmc_allow_nonexistent = flags & SBOX_MAP_PATH_ALLOW_NONEXISTENT; ctx.pmc_sb2ctx = sb2ctx; #if 0 /* see comment at pathmapping_interf.c/custom_map_path() */ ctx.pmc_rule_list_offset = rule_list_offset; diff --git a/scratchbox2/preload/gen-interface.pl b/scratchbox2/preload/gen-interface.pl index e2c1c9c..fbc35ba 100755 --- a/scratchbox2/preload/gen-interface.pl +++ b/scratchbox2/preload/gen-interface.pl @@ -63,6 +63,14 @@ # NOTE: THIS MUST BE USED BEFORE THE map() OR map_at() MODIFIERS! # - "resolve_final_symlink" is the opposite of "dont_resolve_final_symlink" # (and it is on by default) +# - "allow_nonexistent" is used to prefix "map" modifiers where the +# whole pathname (not just the last component) is allowed to refer +# to nonexistent file in nonexistent directory. +# NOTE: THIS MUST BE USED BEFORE THE map() OR map_at() MODIFIERS! +# - "allow_nonexistent_if(condition)" conditionally +# allows the pathname to refer to nonexistent file in nonexistent directory +# (see "allow_nonexistent") +# NOTE: THIS MUST BE USED BEFORE THE map() OR map_at() MODIFIERS! # - "postprocess(varname)" can be used to call postprocessor functions for # mapped variables. # - "return(expr)" can be used to alter the return value. @@ -493,6 +501,22 @@ sub expr_to_flagexpr { return "($expr ? $flag : 0)"; } +sub flagexpr_join { + my $result = "0"; + foreach my $flagexpr (@_) { + if ($flagexpr eq "0") { + # zero flag, leave result as is + } elsif ($result eq "0") { + # zero result, replace with flag + $result = $flagexpr; + } else { + # non-zero result and flag, join with | + $result .= " | $flagexpr"; + } + } + return $result; +} + # Process the modifier section coming from the original input line. # This returns undef if failed, or a structure containing code fragments # and other information for the actual code generation phase. @@ -521,6 +545,7 @@ sub process_wrap_or_gate_modifiers { 'mapped_params_by_orig_name' => {}, 'mapping_results_by_orig_name' => {}, 'dont_resolve_final_symlink' => 0, + 'allow_nonexistent' => 0, 'postprocess_vars' => [], 'return_expr' => undef, @@ -573,6 +598,9 @@ sub process_wrap_or_gate_modifiers { my $new_name = "mapped__".$param_to_be_mapped; my $no_symlink_resolve = expr_to_flagexpr($mods->{'dont_resolve_final_symlink'}, "SBOX_MAP_PATH_DONT_RESOLVE_FINAL_SYMLINK"); + my $allow_nonexistent = + expr_to_flagexpr($mods->{'allow_nonexistent'}, "SBOX_MAP_PATH_ALLOW_NONEXISTENT"); + my $flags = flagexpr_join($no_symlink_resolve, $allow_nonexistent); $mods->{'mapped_params_by_orig_name'}->{$param_to_be_mapped} = "res_$new_name.mres_result_path"; $mods->{'mapping_results_by_orig_name'}->{$param_to_be_mapped} = "res_$new_name"; @@ -583,7 +611,7 @@ sub process_wrap_or_gate_modifiers { "\tclear_mapping_results_struct(&res_$new_name);\n". "\tsbox_map_path(__func__, ". "$param_to_be_mapped, ". - "$no_symlink_resolve, ". + "$flags, ". "&res_$new_name, classmask);\n". "\tif (res_$new_name.mres_errno) {\n". "\t\tSB_LOG(SB_LOGLEVEL_DEBUG, \"mapping failed, errno %d\",". @@ -626,6 +654,9 @@ sub process_wrap_or_gate_modifiers { my $ro_flag = $param_to_be_mapped."_is_readonly"; my $no_symlink_resolve = expr_to_flagexpr($mods->{'dont_resolve_final_symlink'}, "SBOX_MAP_PATH_DONT_RESOLVE_FINAL_SYMLINK"); + my $allow_nonexistent = + expr_to_flagexpr($mods->{'allow_nonexistent'}, "SBOX_MAP_PATH_ALLOW_NONEXISTENT"); + my $flags = flagexpr_join($no_symlink_resolve, $allow_nonexistent); $mods->{'mapped_params_by_orig_name'}->{$param_to_be_mapped} = "res_$new_name.mres_result_path"; $mods->{'mapping_results_by_orig_name'}->{$param_to_be_mapped} = "res_$new_name"; @@ -636,7 +667,7 @@ sub process_wrap_or_gate_modifiers { "\tsbox_map_path_at(__func__, ". "$fd_param, ". "$param_to_be_mapped, ". - "$no_symlink_resolve, ". + "$flags, ". "&res_$new_name, classmask);\n". "\tif (res_$new_name.mres_errno) {\n". "\t\terrno = res_$new_name.mres_errno;\n". @@ -692,6 +723,11 @@ sub process_wrap_or_gate_modifiers { } elsif($modifiers[$i] =~ m/^dont_resolve_final_symlink_if\((.*)\)$/) { my $condition = $1; $mods->{'dont_resolve_final_symlink'} = "($condition)"; + } elsif($modifiers[$i] eq 'allow_nonexistent') { + $mods->{'allow_nonexistent'} = 1; + } elsif($modifiers[$i] =~ m/^allow_nonexistent_if\((.*)\)$/) { + my $condition = $1; + $mods->{'allow_nonexistent'} = "($condition)"; } elsif(($modifiers[$i] =~ m/^optional_arg_is_create_mode\((.*)\)$/) && ($fn->{'has_varargs'})) { my $va_list_condition = $1; diff --git a/scratchbox2/preload/sb_l10n.c b/scratchbox2/preload/sb_l10n.c index b7a303e..971b1a2 100644 --- a/scratchbox2/preload/sb_l10n.c +++ b/scratchbox2/preload/sb_l10n.c @@ -37,7 +37,9 @@ char *bindtextdomain_gate(int *result_errno_ptr, clear_mapping_results_struct(&res); if (dirname != NULL) { - sbox_map_path(realfn_name, dirname, 0, &res, SB2_INTERFACE_CLASS_L10N); + sbox_map_path(realfn_name, dirname, + SBOX_MAP_PATH_ALLOW_NONEXISTENT, &res, + SB2_INTERFACE_CLASS_L10N); assert(res.mres_result_path != NULL); mapped_dirname = res.mres_result_path; From 744d2cb72b038375911e0c251559fafcba2f1cd4 Mon Sep 17 00:00:00 2001 From: Oleg Girko Date: Fri, 3 Oct 2014 22:58:26 +0100 Subject: [PATCH 11/11] Return proper errno code when mapping UNIX socket address. Path mapping now can fail if pathname component doesn't exist, so this condition must be handled correctly when mapping UNIX socket address. Signed-off-by: Oleg Girko --- scratchbox2/preload/network.c | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/scratchbox2/preload/network.c b/scratchbox2/preload/network.c index 16da514..74e2a06 100644 --- a/scratchbox2/preload/network.c +++ b/scratchbox2/preload/network.c @@ -52,12 +52,13 @@ typedef struct { char mapped_printable_dst_addr[200]; } mapped_sockaddr_t; -static void map_sockaddr_un( +static int map_sockaddr_un( const char *realfnname, const struct sockaddr_un *orig_serv_addr_un, mapped_sockaddr_t *output_addr) { mapping_results_t res; + int result = 0; if (!*orig_serv_addr_un->sun_path) { /* an "abstract" local domain socket. @@ -71,7 +72,7 @@ static void map_sockaddr_un( snprintf(output_addr->mapped_printable_dst_addr, sizeof(output_addr->mapped_printable_dst_addr), ""); - return; + return(0); } SB_LOG(SB_LOGLEVEL_DEBUG, "%s: checking AF_UNIX addr '%s'", @@ -85,7 +86,13 @@ static void map_sockaddr_un( /* FIXME: implement if(pathname_is_readonly!=0)... */ sbox_map_path(realfnname, orig_serv_addr_un->sun_path, 0/*flags*/, &res, SB2_INTERFACE_CLASS_SOCKADDR); - if (res.mres_result_path == NULL) { + if (res.mres_errno != 0) { + result = res.mres_errno; + SB_LOG(SB_LOGLEVEL_DEBUG, + "%s: Failed to map AF_UNIX address '%s': errno=%d", + realfnname, orig_serv_addr_un->sun_path, result); + } else if (res.mres_result_path == NULL) { + result = EINVAL; SB_LOG(SB_LOGLEVEL_ERROR, "%s: Failed to map AF_UNIX address '%s'", realfnname, orig_serv_addr_un->sun_path); @@ -96,6 +103,7 @@ static void map_sockaddr_un( output_addr->mapped_sockaddr_un = *orig_serv_addr_un; if (sizeof(output_addr->mapped_sockaddr_un.sun_path) <= strlen(res.mres_result_path)) { + result = ENAMETOOLONG; SB_LOG(SB_LOGLEVEL_ERROR, "%s: Mapped AF_UNIX address (%s) is too long", realfnname, res.mres_result_path); @@ -114,6 +122,7 @@ static void map_sockaddr_un( } } free_mapping_results(&res); + return(result); } /* returns 0 if success, errno code if failed */ @@ -358,9 +367,18 @@ static int map_sockaddr( case AF_UNIX: output_addr->mapped_addrlen = input_addrlen; - map_sockaddr_un(realfnname, + inet_mapping_result = map_sockaddr_un(realfnname, (const struct sockaddr_un*)input_addr, output_addr); + if (inet_mapping_result != 0) { + /* return error */ + *result_errno_ptr = inet_mapping_result; + SB_LOG(SB_LOGLEVEL_NETWORK, + "%s: denied (%s), errno=%d", + realfnname, output_addr->orig_printable_dst_addr, + inet_mapping_result); + return(MAP_SOCKADDR_OPERATION_DENIED); + } SB_LOG(SB_LOGLEVEL_DEBUG, "%s: orig addr.len=%d, mapped_addrlen=%d", __func__, input_addrlen, output_addr->mapped_addrlen); return (MAP_SOCKADDR_MAPPED);