Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2023-07-31 17:35:12 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2023-07-31 17:35:24 +0300
commit1ebdda69d61ae26379f8fac27671103374031944 (patch)
tree3f91337bb928fa638e02b84a20a7568090d23bcb /lib/gitlab/import_export
parent3c93d74713f5a845429b4c19b046f57cc8ea325c (diff)
Add latest changes from gitlab-org/security/gitlab@16-2-stable-ee
Diffstat (limited to 'lib/gitlab/import_export')
-rw-r--r--lib/gitlab/import_export/command_line_util.rb33
-rw-r--r--lib/gitlab/import_export/decompressed_archive_size_validator.rb2
-rw-r--r--lib/gitlab/import_export/file_importer.rb4
-rw-r--r--lib/gitlab/import_export/json/ndjson_reader.rb6
-rw-r--r--lib/gitlab/import_export/recursive_merge_folders.rb2
5 files changed, 31 insertions, 16 deletions
diff --git a/lib/gitlab/import_export/command_line_util.rb b/lib/gitlab/import_export/command_line_util.rb
index d681f39f00b..e2f365fcbf8 100644
--- a/lib/gitlab/import_export/command_line_util.rb
+++ b/lib/gitlab/import_export/command_line_util.rb
@@ -5,8 +5,11 @@ module Gitlab
module CommandLineUtil
UNTAR_MASK = 'u+rwX,go+rX,go-w'
DEFAULT_DIR_MODE = 0700
+ CLEAN_DIR_IGNORE_FILE_NAMES = %w[. ..].freeze
- FileOversizedError = Class.new(StandardError)
+ CommandLineUtilError = Class.new(StandardError)
+ FileOversizedError = Class.new(CommandLineUtilError)
+ HardLinkError = Class.new(CommandLineUtilError)
def tar_czf(archive:, dir:)
tar_with_options(archive: archive, dir: dir, options: 'czf')
@@ -90,7 +93,7 @@ module Gitlab
def untar_with_options(archive:, dir:, options:)
execute_cmd(%W(tar -#{options} #{archive} -C #{dir}))
execute_cmd(%W(chmod -R #{UNTAR_MASK} #{dir}))
- remove_symlinks(dir)
+ clean_extraction_dir!(dir)
end
# rubocop:disable Gitlab/ModuleWithInstanceVariables
@@ -122,17 +125,27 @@ module Gitlab
true
end
- def remove_symlinks(dir)
- ignore_file_names = %w[. ..]
-
+ # Scans and cleans the directory tree.
+ # Symlinks are considered legal but are removed.
+ # Files sharing hard links are considered illegal and the directory will be removed
+ # and a `HardLinkError` exception will be raised.
+ #
+ # @raise [HardLinkError] if there multiple hard links to the same file detected.
+ # @return [Boolean] true
+ def clean_extraction_dir!(dir)
# Using File::FNM_DOTMATCH to also delete symlinks starting with "."
- Dir.glob("#{dir}/**/*", File::FNM_DOTMATCH)
- .reject { |f| ignore_file_names.include?(File.basename(f)) }
- .each do |filepath|
- FileUtils.rm(filepath) if File.lstat(filepath).symlink?
- end
+ Dir.glob("#{dir}/**/*", File::FNM_DOTMATCH).each do |filepath|
+ next if CLEAN_DIR_IGNORE_FILE_NAMES.include?(File.basename(filepath))
+
+ raise HardLinkError, 'File shares hard link' if Gitlab::Utils::FileInfo.shares_hard_link?(filepath)
+
+ FileUtils.rm(filepath) if Gitlab::Utils::FileInfo.linked?(filepath)
+ end
true
+ rescue HardLinkError
+ FileUtils.remove_dir(dir)
+ raise
end
end
end
diff --git a/lib/gitlab/import_export/decompressed_archive_size_validator.rb b/lib/gitlab/import_export/decompressed_archive_size_validator.rb
index 104c9e6c456..2e39f3f38c2 100644
--- a/lib/gitlab/import_export/decompressed_archive_size_validator.rb
+++ b/lib/gitlab/import_export/decompressed_archive_size_validator.rb
@@ -87,7 +87,7 @@ module Gitlab
def validate_archive_path
Gitlab::PathTraversal.check_path_traversal!(@archive_path)
- raise(ServiceError, 'Archive path is a symlink') if File.lstat(@archive_path).symlink?
+ raise(ServiceError, 'Archive path is a symlink or hard link') if Gitlab::Utils::FileInfo.linked?(@archive_path)
raise(ServiceError, 'Archive path is not a file') unless File.file?(@archive_path)
end
diff --git a/lib/gitlab/import_export/file_importer.rb b/lib/gitlab/import_export/file_importer.rb
index d2593289c23..37c83e88ef2 100644
--- a/lib/gitlab/import_export/file_importer.rb
+++ b/lib/gitlab/import_export/file_importer.rb
@@ -23,7 +23,7 @@ module Gitlab
mkdir_p(@shared.export_path)
mkdir_p(@shared.archive_path)
- remove_symlinks(@shared.export_path)
+ clean_extraction_dir!(@shared.export_path)
copy_archive
wait_for_archived_file do
@@ -35,7 +35,7 @@ module Gitlab
false
ensure
remove_import_file
- remove_symlinks(@shared.export_path)
+ clean_extraction_dir!(@shared.export_path)
end
private
diff --git a/lib/gitlab/import_export/json/ndjson_reader.rb b/lib/gitlab/import_export/json/ndjson_reader.rb
index 3de56aacf18..93a94716f8d 100644
--- a/lib/gitlab/import_export/json/ndjson_reader.rb
+++ b/lib/gitlab/import_export/json/ndjson_reader.rb
@@ -21,7 +21,9 @@ module Gitlab
# This reads from `tree/project.json`
path = file_path("#{importable_path}.json")
- raise Gitlab::ImportExport::Error, 'Invalid file' if !File.exist?(path) || File.symlink?(path)
+ if !File.exist?(path) || Gitlab::Utils::FileInfo.linked?(path)
+ raise Gitlab::ImportExport::Error, 'Invalid file'
+ end
data = File.read(path, MAX_JSON_DOCUMENT_SIZE)
json_decode(data)
@@ -34,7 +36,7 @@ module Gitlab
# This reads from `tree/project/merge_requests.ndjson`
path = file_path(importable_path, "#{key}.ndjson")
- next if !File.exist?(path) || File.symlink?(path)
+ next if !File.exist?(path) || Gitlab::Utils::FileInfo.linked?(path)
File.foreach(path, MAX_JSON_DOCUMENT_SIZE).with_index do |line, line_num|
documents << [json_decode(line), line_num]
diff --git a/lib/gitlab/import_export/recursive_merge_folders.rb b/lib/gitlab/import_export/recursive_merge_folders.rb
index 827385d4daf..e6eba60db93 100644
--- a/lib/gitlab/import_export/recursive_merge_folders.rb
+++ b/lib/gitlab/import_export/recursive_merge_folders.rb
@@ -57,7 +57,7 @@ module Gitlab
source_child = File.join(source_path, child)
target_child = File.join(target_path, child)
- next if File.lstat(source_child).symlink?
+ next if Gitlab::Utils::FileInfo.linked?(source_child)
if File.directory?(source_child)
FileUtils.mkdir_p(target_child, mode: DEFAULT_DIR_MODE) unless File.exist?(target_child)