Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 12 additions & 15 deletions backup_logs/src/backup_engine.c
Original file line number Diff line number Diff line change
Expand Up @@ -402,29 +402,26 @@
continue;
}

/* Check if it's a regular file (match shell script -type f).
* Use open(O_NOFOLLOW) + fstat() to eliminate TOCTOU (CWE-367):
* opening with O_NOFOLLOW refuses symlinks, and fstat() on the
* resulting fd operates on the same inode already held open,
* so no race window exists between the check and the use. */
/* Check if it's a regular file or a symlink to a regular file.
* Log files may be symlinks (e.g. last.log, rdk_shell.log).
* Use lstat() to get the link info, then stat() to verify
* the target is a regular file before copying. */
struct stat file_stat;
int check_fd = open(source_file, O_RDONLY | O_NOFOLLOW);
if (check_fd < 0) {
/* Skip if file cannot be opened (e.g. symlink or permission denied) */
if (lstat(source_file, &file_stat) != 0) {
continue;
}
if (fstat(check_fd, &file_stat) != 0) {
close(check_fd);
continue;
}
close(check_fd);
if (S_ISDIR(file_stat.st_mode)) {
/* Skip directories - we don't want to backup directories to PreviousLogs */
RDK_LOG(RDK_LOG_DEBUG, LOG_BACKUP_LOGS, "Skipping directory: %s\n", source_file);
continue;
}
if (!S_ISREG(file_stat.st_mode)) {
/* Skip non-regular files (symlinks, devices, etc.) */
if (S_ISLNK(file_stat.st_mode)) {
/* For symlinks, check the target is a regular file */
if (stat(source_file, &file_stat) != 0 || !S_ISREG(file_stat.st_mode)) {
continue;
}
} else if (!S_ISREG(file_stat.st_mode)) {
/* Skip non-regular, non-symlink files (devices, etc.) */
continue;
}

Expand Down Expand Up @@ -475,7 +472,7 @@
result = copyFiles(source_file, dest_file);
if (result == 0) {
/* Remove source file only if copy succeeded */
if (remove(source_file) != 0) {

Check failure

Code scanning / CodeQL

Time-of-check time-of-use filesystem race condition High

The
filename
being operated upon was previously
checked
, but the underlying file may have been changed since then.
The
filename
being operated upon was previously
checked
, but the underlying file may have been changed since then.
The
filename
being operated upon was previously
checked
, but the underlying file may have been changed since then.
result = -1;
}
}
Expand Down
12 changes: 5 additions & 7 deletions uploadstblogs/src/archive_manager.c
Original file line number Diff line number Diff line change
Expand Up @@ -528,14 +528,12 @@ static int add_file_to_tar(gzFile gz, const char* filepath, const char* arcname)
{
struct stat st;

// Open file first with O_NOFOLLOW to prevent symlink attacks (TOCTOU fix)
int fd = open(filepath, O_RDONLY | O_NOFOLLOW);
// Open file for reading - follow symlinks as log files may be symlinked
int fd = open(filepath, O_RDONLY);
if (fd < 0) {
if (errno != ELOOP) { // ELOOP = symlink detected
RDK_LOG(RDK_LOG_ERROR, LOG_UPLOADSTB,
"[%s:%d] Failed to open file: %s (errno=%d)\n",
__FUNCTION__, __LINE__, filepath, errno);
}
RDK_LOG(RDK_LOG_ERROR, LOG_UPLOADSTB,
"[%s:%d] Failed to open file: %s (errno=%d)\n",
__FUNCTION__, __LINE__, filepath, errno);
return -1;
}

Expand Down
Loading