diff options
author | Chris Liddell <chris.liddell@artifex.com> | 2023-06-07 10:23:06 +0100 |
---|---|---|
committer | Chris Liddell <chris.liddell@artifex.com> | 2023-06-21 09:51:54 +0100 |
commit | 5e65eeae225c7d02d447de5abaf4a8e6d234fcea (patch) | |
tree | 3dc47d157f565958a54e7233e2b7e75ddcbe9582 | |
parent | 8d53dad731e5c35276f79760f6b16ac75a333a39 (diff) |
Bug 706761: Don't "reduce" %pipe% file names for permission validation
For regular file names, we try to simplfy relative paths before we use them.
Because the %pipe% device can, effectively, accept command line calls, we
shouldn't be simplifying that string, because the command line syntax can end
up confusing the path simplifying code. That can result in permitting a pipe
command which does not match what was originally permitted.
Special case "%pipe" in the validation code so we always deal with the entire
string.
-rw-r--r-- | base/gpmisc.c | 31 | ||||
-rw-r--r-- | base/gslibctx.c | 56 |
2 files changed, 64 insertions, 23 deletions
diff --git a/base/gpmisc.c b/base/gpmisc.c index 38d6d60e2..cad018219 100644 --- a/base/gpmisc.c +++ b/base/gpmisc.c | |||
@@ -1076,16 +1076,29 @@ gp_validate_path_len(const gs_memory_t *mem, | |||
1076 | && !memcmp(path + cdirstrl, dirsepstr, dirsepstrl)) { | 1076 | && !memcmp(path + cdirstrl, dirsepstr, dirsepstrl)) { |
1077 | prefix_len = 0; | 1077 | prefix_len = 0; |
1078 | } | 1078 | } |
1079 | rlen = len+1; | ||
1080 | bufferfull = (char *)gs_alloc_bytes(mem->thread_safe_memory, rlen + prefix_len, "gp_validate_path"); | ||
1081 | if (bufferfull == NULL) | ||
1082 | return gs_error_VMerror; | ||
1083 | |||
1084 | buffer = bufferfull + prefix_len; | ||
1085 | if (gp_file_name_reduce(path, (uint)len, buffer, &rlen) != gp_combine_success) | ||
1086 | return gs_error_invalidfileaccess; | ||
1087 | buffer[rlen] = 0; | ||
1088 | 1079 | ||
1080 | /* "%pipe%" do not follow the normal rules for path definitions, so we | ||
1081 | don't "reduce" them to avoid unexpected results | ||
1082 | */ | ||
1083 | if (len > 5 && memcmp(path, "%pipe", 5) != 0) { | ||
1084 | bufferfull = buffer = (char *)gs_alloc_bytes(mem->thread_safe_memory, len + 1, "gp_validate_path"); | ||
1085 | if (buffer == NULL) | ||
1086 | return gs_error_VMerror; | ||
1087 | memcpy(buffer, path, len); | ||
1088 | buffer[len] = 0; | ||
1089 | rlen = len; | ||
1090 | } | ||
1091 | else { | ||
1092 | rlen = len+1; | ||
1093 | bufferfull = (char *)gs_alloc_bytes(mem->thread_safe_memory, rlen + prefix_len, "gp_validate_path"); | ||
1094 | if (bufferfull == NULL) | ||
1095 | return gs_error_VMerror; | ||
1096 | |||
1097 | buffer = bufferfull + prefix_len; | ||
1098 | if (gp_file_name_reduce(path, (uint)len, buffer, &rlen) != gp_combine_success) | ||
1099 | return gs_error_invalidfileaccess; | ||
1100 | buffer[rlen] = 0; | ||
1101 | } | ||
1089 | while (1) { | 1102 | while (1) { |
1090 | switch (mode[0]) | 1103 | switch (mode[0]) |
1091 | { | 1104 | { |
diff --git a/base/gslibctx.c b/base/gslibctx.c index 186248211..3b737df4b 100644 --- a/base/gslibctx.c +++ b/base/gslibctx.c | |||
@@ -740,14 +740,28 @@ gs_add_control_path_len_flags(const gs_memory_t *mem, gs_path_control_t type, co | |||
740 | return gs_error_rangecheck; | 740 | return gs_error_rangecheck; |
741 | } | 741 | } |
742 | 742 | ||
743 | rlen = len+1; | 743 | /* "%pipe%" do not follow the normal rules for path definitions, so we |
744 | buffer = (char *)gs_alloc_bytes(core->memory, rlen, "gp_validate_path"); | 744 | don't "reduce" them to avoid unexpected results |
745 | if (buffer == NULL) | 745 | */ |
746 | return gs_error_VMerror; | 746 | if (len > 5 && memcmp(path, "%pipe", 5) != 0) { |
747 | buffer = (char *)gs_alloc_bytes(core->memory, len + 1, "gs_add_control_path_len"); | ||
748 | if (buffer == NULL) | ||
749 | return gs_error_VMerror; | ||
750 | memcpy(buffer, path, len); | ||
751 | buffer[len] = 0; | ||
752 | rlen = len; | ||
753 | } | ||
754 | else { | ||
755 | rlen = len + 1; | ||
747 | 756 | ||
748 | if (gp_file_name_reduce(path, (uint)len, buffer, &rlen) != gp_combine_success) | 757 | buffer = (char *)gs_alloc_bytes(core->memory, rlen, "gs_add_control_path_len"); |
749 | return gs_error_invalidfileaccess; | 758 | if (buffer == NULL) |
750 | buffer[rlen] = 0; | 759 | return gs_error_VMerror; |
760 | |||
761 | if (gp_file_name_reduce(path, (uint)len, buffer, &rlen) != gp_combine_success) | ||
762 | return gs_error_invalidfileaccess; | ||
763 | buffer[rlen] = 0; | ||
764 | } | ||
751 | 765 | ||
752 | n = control->num; | 766 | n = control->num; |
753 | for (i = 0; i < n; i++) | 767 | for (i = 0; i < n; i++) |
@@ -833,14 +847,28 @@ gs_remove_control_path_len_flags(const gs_memory_t *mem, gs_path_control_t type, | |||
833 | return gs_error_rangecheck; | 847 | return gs_error_rangecheck; |
834 | } | 848 | } |
835 | 849 | ||
836 | rlen = len+1; | 850 | /* "%pipe%" do not follow the normal rules for path definitions, so we |
837 | buffer = (char *)gs_alloc_bytes(core->memory, rlen, "gp_validate_path"); | 851 | don't "reduce" them to avoid unexpected results |
838 | if (buffer == NULL) | 852 | */ |
839 | return gs_error_VMerror; | 853 | if (len > 5 && memcmp(path, "%pipe", 5) != 0) { |
854 | buffer = (char *)gs_alloc_bytes(core->memory, len + 1, "gs_remove_control_path_len"); | ||
855 | if (buffer == NULL) | ||
856 | return gs_error_VMerror; | ||
857 | memcpy(buffer, path, len); | ||
858 | buffer[len] = 0; | ||
859 | rlen = len; | ||
860 | } | ||
861 | else { | ||
862 | rlen = len+1; | ||
840 | 863 | ||
841 | if (gp_file_name_reduce(path, (uint)len, buffer, &rlen) != gp_combine_success) | 864 | buffer = (char *)gs_alloc_bytes(core->memory, rlen, "gs_remove_control_path_len"); |
842 | return gs_error_invalidfileaccess; | 865 | if (buffer == NULL) |
843 | buffer[rlen] = 0; | 866 | return gs_error_VMerror; |
867 | |||
868 | if (gp_file_name_reduce(path, (uint)len, buffer, &rlen) != gp_combine_success) | ||
869 | return gs_error_invalidfileaccess; | ||
870 | buffer[rlen] = 0; | ||
871 | } | ||
844 | 872 | ||
845 | n = control->num; | 873 | n = control->num; |
846 | for (i = 0; i < n; i++) { | 874 | for (i = 0; i < n; i++) { |