OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "base/file_util.h" | 5 #include "base/file_util.h" |
6 | 6 |
7 #include <dirent.h> | 7 #include <dirent.h> |
8 #include <errno.h> | 8 #include <errno.h> |
9 #include <fcntl.h> | 9 #include <fcntl.h> |
10 #include <fnmatch.h> | 10 #include <fnmatch.h> |
| 11 #include <grp.h> |
11 #include <libgen.h> | 12 #include <libgen.h> |
12 #include <limits.h> | 13 #include <limits.h> |
13 #include <stdio.h> | 14 #include <stdio.h> |
14 #include <stdlib.h> | 15 #include <stdlib.h> |
15 #include <string.h> | 16 #include <string.h> |
16 #include <sys/errno.h> | 17 #include <sys/errno.h> |
17 #include <sys/mman.h> | 18 #include <sys/mman.h> |
18 #include <sys/param.h> | 19 #include <sys/param.h> |
19 #include <sys/stat.h> | 20 #include <sys/stat.h> |
20 #include <sys/time.h> | 21 #include <sys/time.h> |
(...skipping 24 matching lines...) Expand all Loading... |
45 #include "base/utf_string_conversions.h" | 46 #include "base/utf_string_conversions.h" |
46 | 47 |
47 #if defined(OS_ANDROID) | 48 #if defined(OS_ANDROID) |
48 #include "base/os_compat_android.h" | 49 #include "base/os_compat_android.h" |
49 #endif | 50 #endif |
50 | 51 |
51 namespace file_util { | 52 namespace file_util { |
52 | 53 |
53 namespace { | 54 namespace { |
54 | 55 |
55 // Helper for NormalizeFilePath(), defined below. | |
56 bool RealPath(const FilePath& path, FilePath* real_path) { | |
57 base::ThreadRestrictions::AssertIOAllowed(); // For realpath(). | |
58 FilePath::CharType buf[PATH_MAX]; | |
59 if (!realpath(path.value().c_str(), buf)) | |
60 return false; | |
61 | |
62 *real_path = FilePath(buf); | |
63 return true; | |
64 } | |
65 | |
66 } // namespace | |
67 | |
68 #if defined(OS_OPENBSD) || defined(OS_FREEBSD) || \ | 56 #if defined(OS_OPENBSD) || defined(OS_FREEBSD) || \ |
69 (defined(OS_MACOSX) && \ | 57 (defined(OS_MACOSX) && \ |
70 MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5) | 58 MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5) |
71 typedef struct stat stat_wrapper_t; | 59 typedef struct stat stat_wrapper_t; |
72 static int CallStat(const char *path, stat_wrapper_t *sb) { | 60 static int CallStat(const char *path, stat_wrapper_t *sb) { |
73 base::ThreadRestrictions::AssertIOAllowed(); | 61 base::ThreadRestrictions::AssertIOAllowed(); |
74 return stat(path, sb); | 62 return stat(path, sb); |
75 } | 63 } |
| 64 static int CallLstat(const char *path, stat_wrapper_t *sb) { |
| 65 base::ThreadRestrictions::AssertIOAllowed(); |
| 66 return lstat(path, sb); |
| 67 } |
76 #else | 68 #else |
77 typedef struct stat64 stat_wrapper_t; | 69 typedef struct stat64 stat_wrapper_t; |
78 static int CallStat(const char *path, stat_wrapper_t *sb) { | 70 static int CallStat(const char *path, stat_wrapper_t *sb) { |
79 base::ThreadRestrictions::AssertIOAllowed(); | 71 base::ThreadRestrictions::AssertIOAllowed(); |
80 return stat64(path, sb); | 72 return stat64(path, sb); |
81 } | 73 } |
| 74 static int CallLstat(const char *path, stat_wrapper_t *sb) { |
| 75 base::ThreadRestrictions::AssertIOAllowed(); |
| 76 return lstat64(path, sb); |
| 77 } |
82 #endif | 78 #endif |
83 | 79 |
| 80 // Helper for NormalizeFilePath(), defined below. |
| 81 bool RealPath(const FilePath& path, FilePath* real_path) { |
| 82 base::ThreadRestrictions::AssertIOAllowed(); // For realpath(). |
| 83 FilePath::CharType buf[PATH_MAX]; |
| 84 if (!realpath(path.value().c_str(), buf)) |
| 85 return false; |
| 86 |
| 87 *real_path = FilePath(buf); |
| 88 return true; |
| 89 } |
| 90 |
| 91 // Helper for VerifyPathControlledByUser. |
| 92 bool VerifySpecificPathControlledByUser(const FilePath& path, |
| 93 uid_t owner_uid, |
| 94 gid_t group_gid) { |
| 95 stat_wrapper_t stat_info; |
| 96 if (CallLstat(path.value().c_str(), &stat_info) != 0) { |
| 97 PLOG(ERROR) << "Failed to get information on path " |
| 98 << path.value(); |
| 99 return false; |
| 100 } |
| 101 |
| 102 if (S_ISLNK(stat_info.st_mode)) { |
| 103 LOG(ERROR) << "Path " << path.value() |
| 104 << " is a symbolic link."; |
| 105 return false; |
| 106 } |
| 107 |
| 108 if (stat_info.st_uid != owner_uid) { |
| 109 LOG(ERROR) << "Path " << path.value() |
| 110 << " is owned by the wrong user."; |
| 111 return false; |
| 112 } |
| 113 |
| 114 if (stat_info.st_gid != group_gid) { |
| 115 LOG(ERROR) << "Path " << path.value() |
| 116 << " is owned by the wrong group."; |
| 117 return false; |
| 118 } |
| 119 |
| 120 if (stat_info.st_mode & S_IWOTH) { |
| 121 LOG(ERROR) << "Path " << path.value() |
| 122 << " is writable by any user."; |
| 123 return false; |
| 124 } |
| 125 |
| 126 return true; |
| 127 } |
| 128 |
| 129 } // namespace |
| 130 |
84 static std::string TempFileName() { | 131 static std::string TempFileName() { |
85 #if defined(OS_MACOSX) | 132 #if defined(OS_MACOSX) |
86 return StringPrintf(".%s.XXXXXX", base::mac::BaseBundleID()); | 133 return StringPrintf(".%s.XXXXXX", base::mac::BaseBundleID()); |
87 #endif | 134 #endif |
88 | 135 |
89 #if defined(GOOGLE_CHROME_BUILD) | 136 #if defined(GOOGLE_CHROME_BUILD) |
90 return std::string(".com.google.Chrome.XXXXXX"); | 137 return std::string(".com.google.Chrome.XXXXXX"); |
91 #else | 138 #else |
92 return std::string(".org.chromium.Chromium.XXXXXX"); | 139 return std::string(".org.chromium.Chromium.XXXXXX"); |
93 #endif | 140 #endif |
(...skipping 839 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
933 | 980 |
934 if (HANDLE_EINTR(close(infile)) < 0) | 981 if (HANDLE_EINTR(close(infile)) < 0) |
935 result = false; | 982 result = false; |
936 if (HANDLE_EINTR(close(outfile)) < 0) | 983 if (HANDLE_EINTR(close(outfile)) < 0) |
937 result = false; | 984 result = false; |
938 | 985 |
939 return result; | 986 return result; |
940 } | 987 } |
941 #endif // defined(OS_MACOSX) | 988 #endif // defined(OS_MACOSX) |
942 | 989 |
| 990 bool VerifyPathControlledByUser(const FilePath& base, |
| 991 const FilePath& path, |
| 992 uid_t owner_uid, |
| 993 gid_t group_gid) { |
| 994 if (base != path && !base.IsParent(path)) { |
| 995 LOG(ERROR) << "|base| must be a subdirectory of |path|. base = \"" |
| 996 << base.value() << "\", path = \"" << path.value() << "\""; |
| 997 return false; |
| 998 } |
| 999 |
| 1000 std::vector<FilePath::StringType> base_components; |
| 1001 std::vector<FilePath::StringType> path_components; |
| 1002 |
| 1003 base.GetComponents(&base_components); |
| 1004 path.GetComponents(&path_components); |
| 1005 |
| 1006 std::vector<FilePath::StringType>::const_iterator ib, ip; |
| 1007 for (ib = base_components.begin(), ip = path_components.begin(); |
| 1008 ib != base_components.end(); ++ib, ++ip) { |
| 1009 // |base| must be a subpath of |path|, so all components should match. |
| 1010 // If these CHECKs fail, look at the test that base is a parent of |
| 1011 // path at the top of this function. |
| 1012 CHECK(ip != path_components.end()); |
| 1013 CHECK(*ip == *ib); |
| 1014 } |
| 1015 |
| 1016 FilePath current_path = base; |
| 1017 if (!VerifySpecificPathControlledByUser(current_path, owner_uid, group_gid)) |
| 1018 return false; |
| 1019 |
| 1020 for (; ip != path_components.end(); ++ip) { |
| 1021 current_path = current_path.Append(*ip); |
| 1022 if (!VerifySpecificPathControlledByUser(current_path, owner_uid, group_gid)) |
| 1023 return false; |
| 1024 } |
| 1025 return true; |
| 1026 } |
| 1027 |
| 1028 #if defined(OS_MACOSX) |
| 1029 bool VerifyPathControlledByAdmin(const FilePath& path) { |
| 1030 const unsigned kRootUid = 0; |
| 1031 const FilePath kFileSystemRoot("/"); |
| 1032 |
| 1033 // The name of the administrator group on mac os. |
| 1034 const char kAdminGroupName[] = "admin"; |
| 1035 |
| 1036 // Reading the groups database may touch the file system. |
| 1037 base::ThreadRestrictions::AssertIOAllowed(); |
| 1038 |
| 1039 struct group *group_record = getgrnam(kAdminGroupName); |
| 1040 if (!group_record) { |
| 1041 PLOG(ERROR) << "Could not get the group ID of group \"" |
| 1042 << kAdminGroupName << "\"."; |
| 1043 return false; |
| 1044 } |
| 1045 |
| 1046 return VerifyPathControlledByUser( |
| 1047 kFileSystemRoot, path, kRootUid, group_record->gr_gid); |
| 1048 } |
| 1049 #endif // defined(OS_MACOSX) |
| 1050 |
943 } // namespace file_util | 1051 } // namespace file_util |
OLD | NEW |