Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 377aecd

Browse files
fix(vfs): Fix TOCTOU vulnerability
1 parent 2d0b267 commit 377aecd

File tree

1 file changed

+73
-107
lines changed

1 file changed

+73
-107
lines changed

‎libraries/FS/src/vfs_api.cpp

Lines changed: 73 additions & 107 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@
1313
// limitations under the License.
1414

1515
#include "vfs_api.h"
16+
#include <errno.h>
17+
#include <stdlib.h>
18+
#include <string.h>
1619

1720
using namespace fs;
1821

@@ -38,67 +41,49 @@ FileImplPtr VFSImpl::open(const char *fpath, const char *mode, const bool create
3841
strcpy(temp, _mountpoint);
3942
strcat(temp, fpath);
4043

41-
struct stat st;
42-
//file found
43-
if (!stat(temp, &st)) {
44-
free(temp);
45-
if (S_ISREG(st.st_mode) || S_ISDIR(st.st_mode)) {
46-
return std::make_shared<VFSFileImpl>(this, fpath, mode);
47-
}
48-
log_e("%s has wrong mode 0x%08X", fpath, st.st_mode);
49-
return FileImplPtr();
50-
}
51-
52-
//try to open this as directory (might be mount point)
53-
DIR *d = opendir(temp);
54-
if (d) {
55-
closedir(d);
56-
free(temp);
57-
return std::make_shared<VFSFileImpl>(this, fpath, mode);
58-
}
59-
60-
//file not found but mode permits file creation without folder creation
61-
if ((mode && mode[0] != 'r') && (!create)) {
62-
free(temp);
63-
return std::make_shared<VFSFileImpl>(this, fpath, mode);
64-
}
65-
66-
////file not found but mode permits file creation and folder creation
67-
if ((mode && mode[0] != 'r') && create) {
68-
69-
char *token;
70-
char *folder = (char *)malloc(strlen(fpath) + 1);
71-
72-
int start_index = 0;
73-
int end_index = 0;
74-
75-
token = strchr(fpath + 1, '/');
76-
end_index = (token - fpath);
77-
78-
while (token != NULL) {
79-
memcpy(folder, fpath + start_index, end_index - start_index);
80-
folder[end_index - start_index] = '0円';
81-
82-
if (!VFSImpl::mkdir(folder)) {
83-
log_e("Creating folder: %s failed!", folder);
84-
return FileImplPtr();
44+
// Try to open as file first - let the file operation handle errors
45+
if (mode && mode[0] != 'r') {
46+
// For write modes, attempt to create directories if needed
47+
if (create) {
48+
char *token;
49+
char *folder = (char *)malloc(strlen(fpath) + 1);
50+
51+
int start_index = 0;
52+
int end_index = 0;
53+
54+
token = strchr(fpath + 1, '/');
55+
end_index = (token - fpath);
56+
57+
while (token != NULL) {
58+
memcpy(folder, fpath + start_index, end_index - start_index);
59+
folder[end_index - start_index] = '0円';
60+
61+
if (!VFSImpl::mkdir(folder)) {
62+
log_e("Creating folder: %s failed!", folder);
63+
free(folder);
64+
free(temp);
65+
return FileImplPtr();
66+
}
67+
68+
token = strchr(token + 1, '/');
69+
if (token != NULL) {
70+
end_index = (token - fpath);
71+
memset(folder, 0, strlen(folder));
72+
}
8573
}
8674

87-
token = strchr(token + 1, '/');
88-
if (token != NULL) {
89-
end_index = (token - fpath);
90-
memset(folder, 0, strlen(folder));
91-
}
75+
free(folder);
9276
}
9377

94-
free(folder);
78+
// Try to open the file directly - let fopen handle errors
9579
free(temp);
9680
return std::make_shared<VFSFileImpl>(this, fpath, mode);
9781
}
9882

99-
log_e("%s does not exist, no permits for creation", temp);
83+
// For read mode, let the VFSFileImpl constructor handle the file opening
84+
// This avoids the TOCTOU race condition while maintaining proper functionality
10085
free(temp);
101-
return FileImplPtr();
86+
return std::make_shared<VFSFileImpl>(this, fpath, mode);
10287
}
10388

10489
bool VFSImpl::exists(const char *fpath) {
@@ -125,10 +110,7 @@ bool VFSImpl::rename(const char *pathFrom, const char *pathTo) {
125110
log_e("bad arguments");
126111
return false;
127112
}
128-
if (!exists(pathFrom)) {
129-
log_e("%s does not exists", pathFrom);
130-
return false;
131-
}
113+
132114
size_t mountpointLen = strlen(_mountpoint);
133115
char *temp1 = (char *)malloc(strlen(pathFrom) + mountpointLen + 1);
134116
if (!temp1) {
@@ -148,6 +130,7 @@ bool VFSImpl::rename(const char *pathFrom, const char *pathTo) {
148130
strcpy(temp2, _mountpoint);
149131
strcat(temp2, pathTo);
150132

133+
// Let rename() handle the error if source doesn't exist
151134
auto rc = ::rename(temp1, temp2);
152135
free(temp1);
153136
free(temp2);
@@ -165,16 +148,6 @@ bool VFSImpl::remove(const char *fpath) {
165148
return false;
166149
}
167150

168-
VFSFileImpl f(this, fpath, "r");
169-
if (!f || f.isDirectory()) {
170-
if (f) {
171-
f.close();
172-
}
173-
log_e("%s does not exists or is directory", fpath);
174-
return false;
175-
}
176-
f.close();
177-
178151
char *temp = (char *)malloc(strlen(fpath) + strlen(_mountpoint) + 1);
179152
if (!temp) {
180153
log_e("malloc failed");
@@ -184,6 +157,7 @@ bool VFSImpl::remove(const char *fpath) {
184157
strcpy(temp, _mountpoint);
185158
strcat(temp, fpath);
186159

160+
// Let unlink() handle the error if file doesn't exist
187161
auto rc = unlink(temp);
188162
free(temp);
189163
return rc == 0;
@@ -231,16 +205,6 @@ bool VFSImpl::rmdir(const char *fpath) {
231205
return false;
232206
}
233207

234-
VFSFileImpl f(this, fpath, "r");
235-
if (!f || !f.isDirectory()) {
236-
if (f) {
237-
f.close();
238-
}
239-
log_e("%s does not exists or is a file", fpath);
240-
return false;
241-
}
242-
f.close();
243-
244208
char *temp = (char *)malloc(strlen(fpath) + strlen(_mountpoint) + 1);
245209
if (!temp) {
246210
log_e("malloc failed");
@@ -250,6 +214,7 @@ bool VFSImpl::rmdir(const char *fpath) {
250214
strcpy(temp, _mountpoint);
251215
strcat(temp, fpath);
252216

217+
// Let rmdir() handle the error if directory doesn't exist
253218
auto rc = ::rmdir(temp);
254219
free(temp);
255220
return rc == 0;
@@ -271,29 +236,30 @@ VFSFileImpl::VFSFileImpl(VFSImpl *fs, const char *fpath, const char *mode) : _fs
271236
return;
272237
}
273238

274-
if (!stat(temp, &_stat)) {
275-
//file found
276-
if (S_ISREG(_stat.st_mode)) {
277-
_isDirectory = false;
278-
_f = fopen(temp, mode);
279-
if (!_f) {
280-
log_e("fopen(%s) failed", temp);
281-
}
282-
if (_f && (_stat.st_blksize == 0)) {
283-
setvbuf(_f, NULL, _IOFBF, DEFAULT_FILE_BUFFER_SIZE);
284-
}
285-
} else if (S_ISDIR(_stat.st_mode)) {
286-
_isDirectory = true;
287-
_d = opendir(temp);
288-
if (!_d) {
289-
log_e("opendir(%s) failed", temp);
239+
// For read mode, check if file exists first to determine type
240+
if (!mode || mode[0] == 'r') {
241+
if (!stat(temp, &_stat)) {
242+
//file found
243+
if (S_ISREG(_stat.st_mode)) {
244+
_isDirectory = false;
245+
_f = fopen(temp, mode);
246+
if (!_f) {
247+
log_e("fopen(%s) failed", temp);
248+
}
249+
if (_f && (_stat.st_blksize == 0)) {
250+
setvbuf(_f, NULL, _IOFBF, DEFAULT_FILE_BUFFER_SIZE);
251+
}
252+
} else if (S_ISDIR(_stat.st_mode)) {
253+
_isDirectory = true;
254+
_d = opendir(temp);
255+
if (!_d) {
256+
log_e("opendir(%s) failed", temp);
257+
}
258+
} else {
259+
log_e("Unknown type 0x%08X for file %s", ((_stat.st_mode) & _IFMT), temp);
290260
}
291261
} else {
292-
log_e("Unknown type 0x%08X for file %s", ((_stat.st_mode) & _IFMT), temp);
293-
}
294-
} else {
295-
//file not found
296-
if (!mode || mode[0] == 'r') {
262+
//file not found
297263
//try to open as directory
298264
_d = opendir(temp);
299265
if (_d) {
@@ -302,16 +268,16 @@ VFSFileImpl::VFSFileImpl(VFSImpl *fs, const char *fpath, const char *mode) : _fs
302268
_isDirectory = false;
303269
//log_w("stat(%s) failed", temp);
304270
}
305-
}else {
306-
//lets create this new file
307-
_isDirectory = false;
308-
_f = fopen(temp, mode);
309-
if (!_f) {
310-
log_e("fopen(%s) failed", temp);
311-
}
312-
if (_f && (_stat.st_blksize == 0)) {
313-
setvbuf(_f, NULL, _IOFBF, DEFAULT_FILE_BUFFER_SIZE);
314-
}
271+
}
272+
} else {
273+
//lets create this new file
274+
_isDirectory = false;
275+
_f = fopen(temp, mode);
276+
if (!_f) {
277+
log_e("fopen(%s) failed", temp);
278+
}
279+
if(_f && (_stat.st_blksize == 0)) {
280+
setvbuf(_f, NULL, _IOFBF, DEFAULT_FILE_BUFFER_SIZE);
315281
}
316282
}
317283
free(temp);

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /