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 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
66 } // namespace | 67 } // namespace |
67 | 68 |
68 #if defined(OS_OPENBSD) || defined(OS_FREEBSD) || \ | 69 #if defined(OS_OPENBSD) || defined(OS_FREEBSD) || \ |
69 (defined(OS_MACOSX) && \ | 70 (defined(OS_MACOSX) && \ |
70 MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5) | 71 MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5) |
71 typedef struct stat stat_wrapper_t; | 72 typedef struct stat stat_wrapper_t; |
72 static int CallStat(const char *path, stat_wrapper_t *sb) { | 73 static int CallStat(const char *path, stat_wrapper_t *sb) { |
73 base::ThreadRestrictions::AssertIOAllowed(); | 74 base::ThreadRestrictions::AssertIOAllowed(); |
74 return stat(path, sb); | 75 return stat(path, sb); |
75 } | 76 } |
77 static int CallLstat(const char *path, stat_wrapper_t *sb) { | |
78 base::ThreadRestrictions::AssertIOAllowed(); | |
79 return lstat(path, sb); | |
80 } | |
76 #else | 81 #else |
77 typedef struct stat64 stat_wrapper_t; | 82 typedef struct stat64 stat_wrapper_t; |
78 static int CallStat(const char *path, stat_wrapper_t *sb) { | 83 static int CallStat(const char *path, stat_wrapper_t *sb) { |
79 base::ThreadRestrictions::AssertIOAllowed(); | 84 base::ThreadRestrictions::AssertIOAllowed(); |
80 return stat64(path, sb); | 85 return stat64(path, sb); |
81 } | 86 } |
87 static int CallLstat(const char *path, stat_wrapper_t *sb) { | |
88 base::ThreadRestrictions::AssertIOAllowed(); | |
89 return lstat64(path, sb); | |
90 } | |
82 #endif | 91 #endif |
83 | 92 |
84 static std::string TempFileName() { | 93 static std::string TempFileName() { |
85 #if defined(OS_MACOSX) | 94 #if defined(OS_MACOSX) |
86 return StringPrintf(".%s.XXXXXX", base::mac::BaseBundleID()); | 95 return StringPrintf(".%s.XXXXXX", base::mac::BaseBundleID()); |
87 #endif | 96 #endif |
88 | 97 |
89 #if defined(GOOGLE_CHROME_BUILD) | 98 #if defined(GOOGLE_CHROME_BUILD) |
90 return std::string(".com.google.Chrome.XXXXXX"); | 99 return std::string(".com.google.Chrome.XXXXXX"); |
91 #else | 100 #else |
(...skipping 841 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
933 | 942 |
934 if (HANDLE_EINTR(close(infile)) < 0) | 943 if (HANDLE_EINTR(close(infile)) < 0) |
935 result = false; | 944 result = false; |
936 if (HANDLE_EINTR(close(outfile)) < 0) | 945 if (HANDLE_EINTR(close(outfile)) < 0) |
937 result = false; | 946 result = false; |
938 | 947 |
939 return result; | 948 return result; |
940 } | 949 } |
941 #endif // defined(OS_MACOSX) | 950 #endif // defined(OS_MACOSX) |
942 | 951 |
952 // Helper for IsPathControlledByUser. | |
953 bool SpecificPathControlledByUser(const FilePath& path, | |
Evan Martin
2011/08/30 17:26:38
Should be in the anon namespace if it's not part o
Sam Kerner (Chrome)
2011/09/16 18:12:59
Done.
| |
954 uid_t owner_uid, | |
955 gid_t group_gid) { | |
956 stat_wrapper_t stat_info; | |
957 if (CallLstat(path.value().c_str(), &stat_info) != 0) { | |
958 PLOG(ERROR) << "Failed to get information on path " | |
959 << path.value(); | |
960 return false; | |
961 } | |
962 | |
963 if (S_ISLNK(stat_info.st_mode)) { | |
964 LOG(ERROR) << "Path " << path.value() | |
965 << " is a symbolic link."; | |
966 return false; | |
967 } | |
968 | |
969 if (stat_info.st_uid != owner_uid) { | |
970 LOG(ERROR) << "Path " << path.value() | |
971 << " is owned by the wrong user."; | |
Evan Martin
2011/08/30 17:26:38
It seems you're reporting it as an error when thes
Sam Kerner (Chrome)
2011/09/16 18:12:59
Done.
| |
972 return false; | |
973 } | |
974 | |
975 if (stat_info.st_gid != group_gid) { | |
976 LOG(ERROR) << "Path " << path.value() | |
977 << " is owned by the wrong group."; | |
978 return false; | |
979 } | |
980 | |
981 if (stat_info.st_mode & S_IWOTH) { | |
982 LOG(ERROR) << "Path "<< path.value() | |
Evan Martin
2011/08/30 17:26:38
space before <<
Sam Kerner (Chrome)
2011/09/16 18:12:59
Done.
| |
983 << " is writable by any user."; | |
984 return false; | |
985 } | |
986 | |
987 return true; | |
988 } | |
989 | |
990 bool IsPathControlledByUser(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 (!SpecificPathControlledByUser(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 (!SpecificPathControlledByUser(current_path, owner_uid, group_gid)) | |
1023 return false; | |
1024 } | |
1025 return true; | |
1026 } | |
1027 | |
1028 bool IsPathControlledByAdmin(const FilePath& path) { | |
1029 const unsigned kRootUid = 0; | |
1030 const FilePath kFileSystemRoot("/"); | |
1031 | |
1032 // The name of the administrator group on mac os. | |
1033 const char kAdminGroupName[] = "admin"; | |
1034 | |
1035 // Reading the groups database may touch the file system. | |
1036 base::ThreadRestrictions::AssertIOAllowed(); | |
Evan Martin
2011/08/30 17:26:38
Thanks for doing this!
| |
1037 | |
1038 struct group *groupRecord = getgrnam(kAdminGroupName); | |
Evan Martin
2011/08/30 17:26:38
group_record, not groupRecord
Sam Kerner (Chrome)
2011/09/16 18:12:59
Done.
| |
1039 if (!groupRecord) { | |
1040 PLOG(ERROR) << "Could not get the group ID of group \"" | |
1041 << kAdminGroupName << "\"."; | |
1042 return false; | |
1043 } | |
1044 | |
1045 return IsPathControlledByUser( | |
1046 kFileSystemRoot, path, kRootUid, groupRecord->gr_gid); | |
1047 } | |
1048 | |
943 } // namespace file_util | 1049 } // namespace file_util |
OLD | NEW |