passenger 5.3.1 → 5.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +19 -0
  3. data/build/cxx_tests.rb +3 -1
  4. data/build/support/cxx_dependency_map.rb +120 -27
  5. data/dev/configkit-schemas/index.json +15 -3
  6. data/src/agent/Core/AdminPanelConnector.h +5 -2
  7. data/src/agent/Core/ApplicationPool/Group/StateInspection.cpp +2 -0
  8. data/src/agent/Core/Config.h +2 -1
  9. data/src/agent/Core/Controller/Config.h +6 -1
  10. data/src/agent/Core/Controller/InitRequest.cpp +6 -1
  11. data/src/agent/Core/CoreMain.cpp +26 -60
  12. data/src/agent/Core/SpawningKit/DirectSpawner.h +18 -6
  13. data/src/agent/Core/SpawningKit/ErrorRenderer.h +8 -8
  14. data/src/agent/Core/SpawningKit/Handshake/Perform.h +217 -61
  15. data/src/agent/Core/SpawningKit/Handshake/Prepare.h +57 -8
  16. data/src/agent/Core/SpawningKit/Handshake/Session.h +34 -1
  17. data/src/agent/Core/SpawningKit/Handshake/WorkDir.h +20 -4
  18. data/src/agent/Core/SpawningKit/SmartSpawner.h +90 -27
  19. data/src/agent/ExecHelper/ExecHelperMain.cpp +3 -0
  20. data/src/agent/Shared/ApiAccountUtils.h +2 -2
  21. data/src/agent/SpawnEnvSetupper/SpawnEnvSetupperMain.cpp +14 -4
  22. data/src/agent/Watchdog/Config.h +2 -1
  23. data/src/agent/Watchdog/WatchdogMain.cpp +38 -0
  24. data/src/apache2_module/Hooks.cpp +1 -0
  25. data/src/cxx_supportlib/ConfigKit/IN_PRACTICE.md +1 -1
  26. data/src/cxx_supportlib/ConfigKit/README.md +1 -1
  27. data/src/cxx_supportlib/Constants.h +6 -1
  28. data/src/cxx_supportlib/FileTools/FileManip.cpp +34 -2
  29. data/src/cxx_supportlib/FileTools/FileManip.h +58 -1
  30. data/src/cxx_supportlib/FileTools/PathManip.cpp +3 -2
  31. data/src/cxx_supportlib/FileTools/PathSecurityCheck.cpp +99 -0
  32. data/src/cxx_supportlib/FileTools/PathSecurityCheck.h +69 -0
  33. data/src/cxx_supportlib/Utils.cpp +37 -6
  34. data/src/cxx_supportlib/Utils.h +6 -0
  35. data/src/cxx_supportlib/Utils/AsyncSignalSafeUtils.h +14 -0
  36. data/src/cxx_supportlib/Utils/IOUtils.cpp +10 -18
  37. data/src/cxx_supportlib/Utils/IOUtils.h +10 -9
  38. data/src/cxx_supportlib/Utils/JsonUtils.h +12 -8
  39. data/src/cxx_supportlib/Utils/SystemMetricsCollector.h +4 -4
  40. data/src/cxx_supportlib/Utils/SystemTime.h +1 -1
  41. data/src/cxx_supportlib/WebSocketCommandReverseServer.h +3 -3
  42. data/src/cxx_supportlib/oxt/system_calls.cpp +25 -1
  43. data/src/cxx_supportlib/oxt/system_calls.hpp +3 -1
  44. data/src/helper-scripts/meteor-loader.rb +115 -28
  45. data/src/helper-scripts/rack-preloader.rb +1 -1
  46. data/src/nginx_module/ConfigGeneral/AutoGeneratedDefinitions.c +4 -4
  47. data/src/nginx_module/ConfigGeneral/AutoGeneratedSetterFuncs.c +4 -4
  48. data/src/nginx_module/LocationConfig/AutoGeneratedCreateFunction.c +0 -10
  49. data/src/nginx_module/LocationConfig/AutoGeneratedHeaderSerialization.c +0 -42
  50. data/src/nginx_module/LocationConfig/AutoGeneratedMergeFunction.c +0 -6
  51. data/src/nginx_module/LocationConfig/AutoGeneratedStruct.h +0 -8
  52. data/src/nginx_module/MainConfig/AutoGeneratedCreateFunction.c +10 -0
  53. data/src/nginx_module/MainConfig/AutoGeneratedManifestGeneration.c +22 -0
  54. data/src/nginx_module/MainConfig/AutoGeneratedStruct.h +8 -0
  55. data/src/nginx_module/ngx_http_passenger_module.c +6 -5
  56. data/src/ruby_supportlib/phusion_passenger.rb +1 -1
  57. data/src/ruby_supportlib/phusion_passenger/apache2/config_options.rb +0 -1
  58. data/src/ruby_supportlib/phusion_passenger/common_library.rb +3 -0
  59. data/src/ruby_supportlib/phusion_passenger/config/installation_utils.rb +3 -3
  60. data/src/ruby_supportlib/phusion_passenger/constants.rb +5 -0
  61. data/src/ruby_supportlib/phusion_passenger/nginx/config_options.rb +4 -2
  62. data/src/ruby_supportlib/phusion_passenger/platform_info.rb +3 -3
  63. data/src/ruby_supportlib/phusion_passenger/request_handler.rb +1 -1
  64. data/src/ruby_supportlib/phusion_passenger/vendor/daemon_controller.rb +1 -1
  65. metadata +4 -2
@@ -0,0 +1,69 @@
1
+ /*
2
+ * Phusion Passenger - https://www.phusionpassenger.com/
3
+ * Copyright (c) 2018 Phusion Holding B.V.
4
+ *
5
+ * "Passenger", "Phusion Passenger" and "Union Station" are registered
6
+ * trademarks of Phusion Holding B.V.
7
+ *
8
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
9
+ * of this software and associated documentation files (the "Software"), to deal
10
+ * in the Software without restriction, including without limitation the rights
11
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12
+ * copies of the Software, and to permit persons to whom the Software is
13
+ * furnished to do so, subject to the following conditions:
14
+ *
15
+ * The above copyright notice and this permission notice shall be included in
16
+ * all copies or substantial portions of the Software.
17
+ *
18
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24
+ * THE SOFTWARE.
25
+ */
26
+ #ifndef _PASSENGER_FILE_TOOLS_PATH_SECURITY_CHECK_H_
27
+ #define _PASSENGER_FILE_TOOLS_PATH_SECURITY_CHECK_H_
28
+
29
+ #include <vector>
30
+ #include <string>
31
+ #include <StaticString.h>
32
+
33
+ namespace Passenger {
34
+
35
+ using namespace std;
36
+
37
+
38
+ /**
39
+ * Checks whether the given path is secure for use by a root process.
40
+ * This is done by checking whether the path itself, as well as any of the
41
+ * parent directories, can only be written to by root. Returns whether the
42
+ * path is deemed secure.
43
+ *
44
+ * If a non-root user can write to any of the directories in the path then that
45
+ * user can cause the root proces to read an arbitrary file. That file can even
46
+ * be one that is not owned by said user, through the use of symlinks.
47
+ *
48
+ * Checking is done according to normal Unix permissions. ACLs and systems like
49
+ * SELinux are not taken into consideration. Also, if this function fails to
50
+ * check a part of the path (e.g. because stat() failed) then this function
51
+ * simply skips that part. Therefore this function does not perform a full check
52
+ * and its result (which *can* be a false positive or a false negative) should be
53
+ * taken with a grain of salt.
54
+ *
55
+ * Error messages that can be used to inform the user which parts of the path
56
+ * are insecure, are outputted into `errors`. This vector becomes non-empty
57
+ * only if result is false.
58
+ *
59
+ * Any errors that occur w.r.t. checking itself (e.g. stat() errors) are
60
+ * outputted into `checkErrors`. This vector may become non-empty no matter
61
+ * the result.
62
+ */
63
+ bool isPathProbablySecureForRootUse(const StaticString &path,
64
+ vector<string> &errors, vector<string> &checkErrors);
65
+
66
+
67
+ } // namespace Passenger
68
+
69
+ #endif /* _PASSENGER_FILE_TOOLS_PATH_SECURITY_CHECK_H_ */
@@ -186,9 +186,37 @@ getProcessUsername(bool fallback) {
186
186
  }
187
187
  }
188
188
 
189
+ string
190
+ getUserName(uid_t uid) {
191
+ struct passwd pwd, *result;
192
+ int ret;
193
+ long bufSize;
194
+ shared_array<char> strings;
195
+
196
+ // _SC_GETPW_R_SIZE_MAX is not a maximum:
197
+ // http://tomlee.co/2012/10/problems-with-large-linux-unix-groups-and-getgrgid_r-getgrnam_r/
198
+ bufSize = std::max<long>(1024 * 128, sysconf(_SC_GETPW_R_SIZE_MAX));
199
+ strings.reset(new char[bufSize]);
200
+
201
+ result = (struct passwd *) NULL;
202
+ do {
203
+ ret = getpwuid_r(uid, &pwd, strings.get(), bufSize, &result);
204
+ } while (ret == EAGAIN);
205
+ if (ret != 0) {
206
+ result = (struct passwd *) NULL;
207
+ }
208
+
209
+ if (result == (struct passwd *) NULL || result->pw_name == NULL || result->pw_name[0] == '\0') {
210
+ return toString(uid);
211
+ } else {
212
+ return result->pw_name;
213
+ }
214
+ }
215
+
189
216
  string
190
217
  getGroupName(gid_t gid) {
191
- struct group grp, *groupEntry;
218
+ struct group grp, *result;
219
+ int ret;
192
220
  long bufSize;
193
221
  shared_array<char> strings;
194
222
 
@@ -197,15 +225,18 @@ getGroupName(gid_t gid) {
197
225
  bufSize = std::max<long>(1024 * 128, sysconf(_SC_GETGR_R_SIZE_MAX));
198
226
  strings.reset(new char[bufSize]);
199
227
 
200
- groupEntry = (struct group *) NULL;
201
- if (getgrgid_r(gid, &grp, strings.get(), bufSize, &groupEntry) != 0) {
202
- groupEntry = (struct group *) NULL;
228
+ result = (struct group *) NULL;
229
+ do {
230
+ ret = getgrgid_r(gid, &grp, strings.get(), bufSize, &result);
231
+ } while (ret == EAGAIN);
232
+ if (ret != 0) {
233
+ result = (struct group *) NULL;
203
234
  }
204
235
 
205
- if (groupEntry == (struct group *) NULL) {
236
+ if (result == (struct group *) NULL || result->gr_name == NULL || result->gr_name[0] == '\0') {
206
237
  return toString(gid);
207
238
  } else {
208
- return groupEntry->gr_name;
239
+ return result->gr_name;
209
240
  }
210
241
  }
211
242
 
@@ -100,6 +100,12 @@ string escapeShell(const StaticString &input);
100
100
  */
101
101
  string getProcessUsername(bool fallback = true);
102
102
 
103
+ /**
104
+ * Returns either the user name for the given UID, or (if the user name
105
+ * couldn't be looked up) a string representation of the given UID.
106
+ */
107
+ string getUserName(uid_t uid);
108
+
103
109
  /**
104
110
  * Returns either the group name for the given GID, or (if the group name
105
111
  * couldn't be looked up) a string representation of the given GID.
@@ -159,12 +159,24 @@ limitedStrerror(int e, const char *defaultResult = "Unknown error") {
159
159
  return "Permission denied";
160
160
  case EFAULT:
161
161
  return "Bad address";
162
+ case EINVAL:
163
+ return "Invalid argument";
162
164
  case EIO:
163
165
  return "Input/output error";
166
+ case EISDIR:
167
+ return "Is a directory";
168
+ #ifdef ELIBBAD
169
+ case ELIBBAD:
170
+ return "Accessing a corrupted shared library";
171
+ #endif
164
172
  case ELOOP:
165
173
  return "Too many levels of symbolic links";
174
+ case EMFILE:
175
+ return "Too many open files";
166
176
  case ENAMETOOLONG:
167
177
  return "File name too long";
178
+ case ENFILE:
179
+ return "Too many open files in system";
168
180
  case ENOENT:
169
181
  return "No such file or directory";
170
182
  case ENOEXEC:
@@ -173,6 +185,8 @@ limitedStrerror(int e, const char *defaultResult = "Unknown error") {
173
185
  return "Cannot allocate memory";
174
186
  case ENOTDIR:
175
187
  return "Not a directory";
188
+ case EPERM:
189
+ return "Operation not permitted";
176
190
  case ETXTBSY:
177
191
  return "Text file busy";
178
192
  default:
@@ -1,6 +1,6 @@
1
1
  /*
2
2
  * Phusion Passenger - https://www.phusionpassenger.com/
3
- * Copyright (c) 2010-2017 Phusion Holding B.V.
3
+ * Copyright (c) 2010-2018 Phusion Holding B.V.
4
4
  *
5
5
  * "Passenger", "Phusion Passenger" and "Union Station" are registered
6
6
  * trademarks of Phusion Holding B.V.
@@ -1354,32 +1354,23 @@ safelyClose(int fd, bool ignoreErrors) {
1354
1354
  }
1355
1355
  }
1356
1356
 
1357
- string
1358
- readAll(const string &filename) {
1359
- FILE *f = fopen(filename.c_str(), "rb");
1360
- if (f != NULL) {
1361
- StdioGuard guard(f, NULL, 0);
1362
- return readAll(fileno(f));
1363
- } else {
1364
- int e = errno;
1365
- throw FileSystemException("Cannot open '" + filename + "' for reading",
1366
- e, filename);
1367
- }
1368
- }
1369
-
1370
- string
1371
- readAll(int fd) {
1357
+ pair<string, bool>
1358
+ readAll(int fd, size_t maxSize) {
1372
1359
  string result;
1373
1360
  char buf[1024 * 32];
1374
1361
  ssize_t ret;
1375
- while (true) {
1362
+ bool eofReached = false;
1363
+
1364
+ while (result.size() < maxSize) {
1376
1365
  do {
1377
1366
  ret = read(fd, buf, sizeof(buf));
1378
1367
  } while (ret == -1 && errno == EINTR);
1379
1368
  if (ret == 0) {
1369
+ eofReached = true;
1380
1370
  break;
1381
1371
  } else if (ret == -1) {
1382
1372
  if (errno == ECONNRESET) {
1373
+ eofReached = true;
1383
1374
  break;
1384
1375
  } else {
1385
1376
  int e = errno;
@@ -1389,7 +1380,8 @@ readAll(int fd) {
1389
1380
  result.append(buf, ret);
1390
1381
  }
1391
1382
  }
1392
- return result;
1383
+
1384
+ return make_pair(result, eofReached);
1393
1385
  }
1394
1386
 
1395
1387
 
@@ -1,6 +1,6 @@
1
1
  /*
2
2
  * Phusion Passenger - https://www.phusionpassenger.com/
3
- * Copyright (c) 2010-2017 Phusion Holding B.V.
3
+ * Copyright (c) 2010-2018 Phusion Holding B.V.
4
4
  *
5
5
  * "Passenger", "Phusion Passenger" and "Union Station" are registered
6
6
  * trademarks of Phusion Holding B.V.
@@ -34,6 +34,7 @@
34
34
  #include <unistd.h>
35
35
  #include <netdb.h>
36
36
  #include <string>
37
+ #include <utility>
37
38
  #include <vector>
38
39
  #include <oxt/macros.hpp>
39
40
  #include <StaticString.h>
@@ -642,18 +643,18 @@ void readPeerCredentials(int sock, uid_t *uid, gid_t *gid);
642
643
  #endif
643
644
 
644
645
  /**
645
- * Read all data from the given file until EOF.
646
+ * Read all data from the given file descriptor until EOF, or until `maxSize`
647
+ * is reached.
646
648
  *
647
- * @throws SystemException
648
- */
649
- string readAll(const string &filename);
650
-
651
- /**
652
- * Read all data from the given file descriptor until EOF.
649
+ * Returns a pair `(contents, eof)`.
650
+ *
651
+ * - `contents` is the read file contents, which is at most `maxSize` bytes.
652
+ * - `eof` indicates whether the entire file has been read. If false, then it
653
+ * means the amount of data is larger than `maxSize`.
653
654
  *
654
655
  * @throws SystemException
655
656
  */
656
- string readAll(int fd);
657
+ pair<string, bool> readAll(int fd, size_t maxSize);
657
658
 
658
659
  } // namespace Passenger
659
660
 
@@ -1,6 +1,6 @@
1
1
  /*
2
2
  * Phusion Passenger - https://www.phusionpassenger.com/
3
- * Copyright (c) 2014-2017 Phusion Holding B.V.
3
+ * Copyright (c) 2014-2018 Phusion Holding B.V.
4
4
  *
5
5
  * "Passenger", "Phusion Passenger" and "Union Station" are registered
6
6
  * trademarks of Phusion Holding B.V.
@@ -321,18 +321,22 @@ monoTimeToJson(MonotonicTimeUsec t, MonotonicTimeUsec monoNow, unsigned long lon
321
321
  }
322
322
 
323
323
  time_t wallClockTime = (time_t) (wallClockTimeUsec / 1000000ull);
324
- char timeStr[32];
324
+ char timeStr[32], *ctimeResult;
325
325
  size_t len;
326
- ctime_r(&wallClockTime, timeStr);
327
- len = strlen(timeStr);
328
- if (len > 0) {
329
- // Get rid of trailing newline
330
- timeStr[len - 1] = '\0';
326
+ ctimeResult = ctime_r(&wallClockTime, timeStr);
327
+ if (ctimeResult != NULL) {
328
+ len = strlen(timeStr);
329
+ if (len > 0) {
330
+ // Get rid of trailing newline
331
+ timeStr[len - 1] = '\0';
332
+ }
331
333
  }
332
334
 
333
335
  Json::Value doc;
334
336
  doc["timestamp"] = wallClockTimeUsec / 1000000.0;
335
- doc["local"] = timeStr;
337
+ if (ctimeResult != NULL) {
338
+ doc["local"] = timeStr;
339
+ }
336
340
  if (t > monoNow) {
337
341
  doc["relative_timestamp"] = (t - monoNow) / 1000000.0;
338
342
  doc["relative"] = distanceOfTimeInWords(t / 1000000ull, monoNow / 1000000ull) + " from now";
@@ -45,8 +45,8 @@
45
45
  #ifdef __linux__
46
46
  #include <sys/sysinfo.h>
47
47
  #include <Exceptions.h>
48
+ #include <FileTools/FileManip.h>
48
49
  #include <Utils/StringScanning.h>
49
- #include <Utils/IOUtils.h>
50
50
  #endif
51
51
  #ifdef __APPLE__
52
52
  #include <mach/mach.h>
@@ -912,7 +912,7 @@ private:
912
912
  string contents;
913
913
  bool hasContents = false;
914
914
  try {
915
- contents = readAll("/proc/meminfo");
915
+ contents = unsafeReadFile("/proc/meminfo");
916
916
  hasContents = true;
917
917
  } catch (const SystemException &) {
918
918
  }
@@ -987,7 +987,7 @@ private:
987
987
  string contents;
988
988
  bool hasContents = false;
989
989
  try {
990
- contents = readAll("/proc/stat");
990
+ contents = unsafeReadFile("/proc/stat");
991
991
  hasContents = true;
992
992
  } catch (const SystemException &) {
993
993
  }
@@ -1066,7 +1066,7 @@ private:
1066
1066
  string contents;
1067
1067
  bool hasContents = false;
1068
1068
  try {
1069
- contents = readAll("/proc/vmstat");
1069
+ contents = unsafeReadFile("/proc/vmstat");
1070
1070
  hasContents = true;
1071
1071
  } catch (const SystemException &) {
1072
1072
  }
@@ -116,7 +116,7 @@ private:
116
116
  template<Granularity granularityNs>
117
117
  static MonotonicTimeUsec _getMonotonicUsec() {
118
118
  if (OXT_UNLIKELY(SystemTimeData::hasForcedUsecValue)) {
119
- return SystemTimeData::hasForcedValue;
119
+ return SystemTimeData::forcedUsecValue;
120
120
  }
121
121
 
122
122
  #if BOOST_OS_MACOS
@@ -1,6 +1,6 @@
1
1
  /*
2
2
  * Phusion Passenger - https://www.phusionpassenger.com/
3
- * Copyright (c) 2017 Phusion Holding B.V.
3
+ * Copyright (c) 2017-2018 Phusion Holding B.V.
4
4
  *
5
5
  * "Passenger", "Phusion Passenger" and "Union Station" are registered
6
6
  * trademarks of Phusion Holding B.V.
@@ -47,9 +47,9 @@
47
47
  #include <ConfigKit/AsyncUtils.h>
48
48
  #include <Exceptions.h>
49
49
  #include <FileTools/PathManip.h>
50
+ #include <FileTools/FileManip.h>
50
51
  #include <Utils.h>
51
52
  #include <Utils/StrIntUtils.h>
52
- #include <Utils/IOUtils.h>
53
53
 
54
54
  namespace Passenger {
55
55
 
@@ -497,7 +497,7 @@ private:
497
497
  if (config["password_file"].isNull()) {
498
498
  password = config["password"].asString();
499
499
  } else {
500
- password = strip(readAll(config["password_file"].asString()));
500
+ password = strip(unsafeReadFile(config["password_file"].asString()));
501
501
  }
502
502
  string data = modp::b64_encode(username + ":" + password);
503
503
  conn->append_header("Authorization", "Basic " + data);
@@ -2,7 +2,7 @@
2
2
  * OXT - OS eXtensions for boosT
3
3
  * Provides important functionality necessary for writing robust server software.
4
4
  *
5
- * Copyright (c) 2010-2017 Phusion Holding B.V.
5
+ * Copyright (c) 2010-2018 Phusion Holding B.V.
6
6
  *
7
7
  * Permission is hereby granted, free of charge, to any person obtaining a copy
8
8
  * of this software and associated documentation files (the "Software"), to deal
@@ -171,6 +171,30 @@ syscalls::open(const char *path, int oflag, mode_t mode) {
171
171
  return ret;
172
172
  }
173
173
 
174
+ int
175
+ syscalls::openat(int dirfd, const char *path, int oflag) {
176
+ int ret;
177
+ CHECK_INTERRUPTION(
178
+ ret == -1,
179
+ true,
180
+ ret = -1,
181
+ ret = ::openat(dirfd, path, oflag)
182
+ );
183
+ return ret;
184
+ }
185
+
186
+ int
187
+ syscalls::openat(int dirfd, const char *path, int oflag, mode_t mode) {
188
+ int ret;
189
+ CHECK_INTERRUPTION(
190
+ ret == -1,
191
+ true,
192
+ ret = -1,
193
+ ret = ::openat(dirfd, path, oflag, mode)
194
+ );
195
+ return ret;
196
+ }
197
+
174
198
  ssize_t
175
199
  syscalls::read(int fd, void *buf, size_t count) {
176
200
  ssize_t ret;
@@ -2,7 +2,7 @@
2
2
  * OXT - OS eXtensions for boosT
3
3
  * Provides important functionality necessary for writing robust server software.
4
4
  *
5
- * Copyright (c) 2010-2017 Phusion Holding B.V.
5
+ * Copyright (c) 2010-2018 Phusion Holding B.V.
6
6
  *
7
7
  * Permission is hereby granted, free of charge, to any person obtaining a copy
8
8
  * of this software and associated documentation files (the "Software"), to deal
@@ -136,6 +136,8 @@ namespace oxt {
136
136
 
137
137
  int open(const char *path, int oflag);
138
138
  int open(const char *path, int oflag, mode_t mode);
139
+ int openat(int dirfd, const char *path, int oflag);
140
+ int openat(int dirfd, const char *path, int oflag, mode_t mode);
139
141
  ssize_t read(int fd, void *buf, size_t count);
140
142
  ssize_t write(int fd, const void *buf, size_t count);
141
143
  ssize_t writev(int fd, const struct iovec *iov, int iovcnt);