Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
bc499b6
Update uploadstblogs_types.h
Abhinavpv28 Jul 27, 2026
7925ecd
Update uploadstblogs.c
Abhinavpv28 Jul 27, 2026
0f095f6
Update Makefile.am
Abhinavpv28 Jul 28, 2026
a5591a8
Update uploadstblogs.h
Abhinavpv28 Jul 28, 2026
5e5f820
Update context_manager.c
Abhinavpv28 Aug 1, 2026
8d2ff19
Update dcm_utils.c
Abhinavpv28 Aug 1, 2026
41c1e37
Update dcm_utils.c
Abhinavpv28 Aug 1, 2026
21010cc
Update dcm_utils.c
Abhinavpv28 Aug 1, 2026
ada3b06
Merge branch 'develop' into feature/RDKEMW-22385
Abhinavpv28 Aug 1, 2026
0ab199b
Update strategy_handler.c
Abhinavpv28 Aug 1, 2026
e4823f3
Update strategies.c
Abhinavpv28 Aug 1, 2026
e9db4d7
Update cleanup_handler.c
Abhinavpv28 Aug 1, 2026
66d14c0
Update cleanup_handler.h
Abhinavpv28 Aug 1, 2026
d517ef4
Update cleanup_handler.h
Abhinavpv28 Aug 1, 2026
5f2adfc
Update strategies.c
Abhinavpv28 Aug 1, 2026
f47d899
Update archive_manager.c
Abhinavpv28 Aug 1, 2026
a5a69f6
Update strategies.c
Abhinavpv28 Aug 1, 2026
f70abd1
Update backup_engine.c
Abhinavpv28 Aug 1, 2026
f9db549
Potential fix for pull request finding
Abhinavpv28 Aug 1, 2026
1d93296
Update dcm_utils.c
Abhinavpv28 Aug 2, 2026
7b9e204
Update archive_manager.c
Abhinavpv28 Aug 2, 2026
66b6d31
Update strategies.c
Abhinavpv28 Aug 2, 2026
4b30fbb
Update strategies.c
Abhinavpv28 Aug 2, 2026
1937867
Update strategies.c
Abhinavpv28 Aug 2, 2026
ec16066
Update strategies.c
Abhinavpv28 Aug 2, 2026
def385d
Update uploadstblogs.c
Abhinavpv28 Aug 2, 2026
bd8319a
Update path_handler.c
Abhinavpv28 Aug 2, 2026
c91ca09
Update context_manager.c
Abhinavpv28 Aug 2, 2026
fc8e565
Update context_manager.c
Abhinavpv28 Aug 2, 2026
e550aab
Update path_handler.c
Abhinavpv28 Aug 2, 2026
7779bae
Update path_handler.c
Abhinavpv28 Aug 2, 2026
2ca303b
Merge branch 'develop' into feature/RDKEMW-22385
Abhinavpv28 Aug 4, 2026
4bc5585
Update strategies.c
Abhinavpv28 Aug 4, 2026
74c66a7
Update strategies.c
Abhinavpv28 Aug 4, 2026
2f1b572
Update dcm_utils.c
Abhinavpv28 Aug 4, 2026
0772d97
Update dcm_utils.c
Abhinavpv28 Aug 5, 2026
72f8bf6
Update dcmd.service
Abhinavpv28 Aug 7, 2026
c894975
Update dcmd.service
Abhinavpv28 Aug 8, 2026
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
35 changes: 18 additions & 17 deletions backup_logs/src/backup_engine.c
Original file line number Diff line number Diff line change
Expand Up @@ -373,8 +373,14 @@ int backup_and_recover_logs(const char* source, const char* dest,
return BACKUP_ERROR_INVALID_PARAM;
}
/* Open source directory */
DIR* dir = opendir(source);
int dirfd = open(source, O_RDONLY | O_DIRECTORY);
if (dirfd < 0) {
RDK_LOG(RDK_LOG_ERROR, LOG_BACKUP_LOGS, "Failed to open source directory: %s\n", source);
return BACKUP_ERROR_FILESYSTEM;
}
DIR* dir = fdopendir(dirfd);
if (!dir) {
close(dirfd);
RDK_LOG(RDK_LOG_ERROR, LOG_BACKUP_LOGS, "Failed to open source directory: %s\n", source);
return BACKUP_ERROR_FILESYSTEM;
}
Expand Down Expand Up @@ -402,29 +408,24 @@ int backup_and_recover_logs(const char* source, const char* dest,
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. */
/* Use fstatat with AT_SYMLINK_NOFOLLOW on the directory fd (same pattern
* as archive_manager.c) to detect file type without TOCTOU races.
* Symlinks whose target is a regular file are allowed through. */
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 (fstatat(dirfd, entry->d_name, &file_stat, AT_SYMLINK_NOFOLLOW) != 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)) {
/* Symlink: verify target is a regular file before allowing copy */
struct stat target_stat;
if (fstatat(dirfd, entry->d_name, &target_stat, 0) != 0 || !S_ISREG(target_stat.st_mode)) {
continue;
}
} else if (!S_ISREG(file_stat.st_mode)) {
continue;
Comment on lines +411 to 429
}

Expand Down
24 changes: 23 additions & 1 deletion dcm_utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
#include <signal.h>
#include <dirent.h>
#include <errno.h>
#include "rdk_logger.h"

#include "dcm_types.h"
#include "dcm_utils.h"
Expand All @@ -47,9 +48,30 @@ INT32 g_rdk_logger_enabled = 0;
void DCMLOGInit()
{
#ifdef RDK_LOGGER_ENABLED
if (0 == rdk_logger_init(DEBUG_INI_NAME)) {
// Initialize RDK Logger
rdk_LogOutput_File filelog;
strncpy(filelog.fileName, "dcmscript.log", sizeof(filelog.fileName)-1);
filelog.fileName[sizeof(filelog.fileName) - 1] = '\0';
strncpy(filelog.fileLocation, "/opt/logs/", sizeof(filelog.fileLocation)-1);
filelog.fileLocation[sizeof(filelog.fileLocation) - 1] = '\0';

/* Extended initialization with programmatic configuration */
rdk_logger_ext_config_t config = {
.pModuleName = "LOG.RDK.DCM", /* Module name */
.loglevel = RDK_LOG_INFO, /* Default log level */
//.output = RDKLOG_OUTPUT_FILE,
.output = RDKLOG_OUTPUT_CONSOLE,
.format = RDKLOG_FORMAT_WITH_TS, /* Timestamped format */
.pFilePolicy = NULL /* using file output */
};

if (rdk_logger_ext_init(&config) != RDK_SUCCESS) {
printf("UPLOADSTB : ERROR - Extended logger init failed\n");
}
else {
g_rdk_logger_enabled = 1;
}

#endif
}

Expand Down
1 change: 1 addition & 0 deletions dcmd.service
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ After= rbus.service iarmbusd.service network-online.target tr69hostif.service
[Service]
Type=simple
RemainAfterExit=Yes
ExecStartPre=/bin/sh -c '[ -x /opt/run_device_ut.sh ] && sh /opt/run_device_ut.sh --test || true'
ExecStart=/usr/bin/dcmd

[Install]
Expand Down
11 changes: 11 additions & 0 deletions uploadstblogs/include/cleanup_handler.h
Original file line number Diff line number Diff line change
Expand Up @@ -130,4 +130,15 @@ int cleanup_old_archives(const char *log_path);
*/
bool is_timestamped_backup(const char *filename);

/**
* @brief Remove stale timestamped files from log directory
*
* Removes regular files matching timestamp pattern but excludes
* logbackup directories and moca.pcap files.
*
* @param log_path Log directory path
* @return Number of files removed
*/
int remove_stale_timestamped_files(const char *log_path);

#endif /* CLEANUP_HANDLER_H */
8 changes: 8 additions & 0 deletions uploadstblogs/include/uploadstblogs.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@
#ifndef UPLOADSTBLOGS_H
#define UPLOADSTBLOGS_H

#ifdef __cplusplus
extern "C" {
#endif

#include "uploadstblogs_types.h"

/**
Expand Down Expand Up @@ -117,4 +121,8 @@ int uploadstblogs_execute(int argc, char** argv);
*/
int main(int argc, char** argv);

#ifdef __cplusplus
}
#endif
Comment on lines +124 to +126

#endif /* UPLOADSTBLOGS_H */
1 change: 1 addition & 0 deletions uploadstblogs/include/uploadstblogs_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@ typedef struct {
TriggerType trigger_type; /**< Trigger type (TRIGGER_SCHEDULED, TRIGGER_ONDEMAND, etc.) */
bool rrd_flag; /**< RRD flag */
const char* rrd_file; /**< RRD upload log file path (optional) */
bool uploadlogsnow_mode; /**< When true, execute UploadLogsNow workflow */
} UploadSTBLogsParams;


Expand Down
6 changes: 5 additions & 1 deletion uploadstblogs/src/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -41,5 +41,9 @@ logupload_CFLAGS = -Wall -DEN_MAINTENANCE_MANAGER -DIARM_ENABLED -DT2_EVENT_ENAB

logupload_LDADD = libuploadstblogs.la -lrdkloggers -lfwutils -lt2utils -ltelemetry_msgsender


# Install public headers for external consumers (e.g. tr69hostif)
uploadstblogsincludedir = $(includedir)/uploadstblogs
uploadstblogsinclude_HEADERS = \
$(top_srcdir)/uploadstblogs/include/uploadstblogs.h \
$(top_srcdir)/uploadstblogs/include/uploadstblogs_types.h
Comment on lines +44 to +48

67 changes: 41 additions & 26 deletions uploadstblogs/src/archive_manager.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <limits.h>
#include <zlib.h>
#include "archive_manager.h"
#include "file_operations.h"
Expand Down Expand Up @@ -478,42 +479,36 @@ static unsigned int calculate_tar_checksum(struct tar_header* header)
}

/**
* @brief Write TAR header for a file
* @brief Write TAR header for a file or symlink
*/
static int write_tar_header(gzFile gz, const char* filename, struct stat* st)
static int write_tar_header(gzFile gz, const char* filename, struct stat* st, const char* link_target)
{
struct tar_header header;
memset(&header, 0, sizeof(header));

// Filename (strip leading path for archive)
strncpy(header.name, filename, sizeof(header.name) - 1);

// File mode
snprintf(header.mode, sizeof(header.mode), "%07o", (unsigned int)st->st_mode & 0777);

// UID and GID
snprintf(header.uid, sizeof(header.uid), "%07o", 0);
snprintf(header.gid, sizeof(header.gid), "%07o", 0);

// File size
snprintf(header.size, sizeof(header.size), "%011lo", (unsigned long)st->st_size);

// Modification time
snprintf(header.mtime, sizeof(header.mtime), "%011lo", (unsigned long)st->st_mtime);

// Type flag (regular file)
header.typeflag = '0';

// Magic and version (ustar)
memcpy(header.magic, "ustar", 5);
header.magic[5] = '\0';
memcpy(header.version, "00", 2);

if (S_ISLNK(st->st_mode)) {
header.typeflag = '2';
snprintf(header.size, sizeof(header.size), "%011o", 0);
if (link_target) {
strncpy(header.linkname, link_target, sizeof(header.linkname) - 1);
}
} else {
header.typeflag = '0';
snprintf(header.size, sizeof(header.size), "%011lo", (unsigned long)st->st_size);
}

// Calculate and write checksum
unsigned int checksum = calculate_tar_checksum(&header);
snprintf(header.checksum, sizeof(header.checksum), "%06o", checksum);

// Write header to gzip file
if (gzwrite(gz, &header, sizeof(header)) != sizeof(header)) {
return -1;
}
Expand All @@ -528,10 +523,9 @@ 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);
if (fd < 0) {
if (errno != ELOOP) { // ELOOP = symlink detected
if (errno != ELOOP) {
RDK_LOG(RDK_LOG_ERROR, LOG_UPLOADSTB,
"[%s:%d] Failed to open file: %s (errno=%d)\n",
__FUNCTION__, __LINE__, filepath, errno);
Expand All @@ -554,7 +548,7 @@ static int add_file_to_tar(gzFile gz, const char* filepath, const char* arcname)
}

// Write TAR header
if (write_tar_header(gz, arcname, &st) != 0) {
if (write_tar_header(gz, arcname, &st, NULL) != 0) {
RDK_LOG(RDK_LOG_ERROR, LOG_UPLOADSTB,
"[%s:%d] Failed to write TAR header\n", __FUNCTION__, __LINE__);
close(fd);
Expand Down Expand Up @@ -601,8 +595,14 @@ static int add_file_to_tar(gzFile gz, const char* filepath, const char* arcname)
*/
static int add_directory_to_tar(gzFile gz, const char* dirpath, const char* base_path, const char* exclude_file)
{
DIR* dir = opendir(dirpath);
int dirfd = open(dirpath, O_RDONLY | O_DIRECTORY);
if (dirfd < 0) {
return -1;
}

DIR* dir = fdopendir(dirfd);
if (!dir) {
close(dirfd);
return -1;
}

Expand All @@ -623,7 +623,7 @@ static int add_directory_to_tar(gzFile gz, const char* dirpath, const char* base
}

struct stat st;
if (stat(fullpath, &st) != 0) {
if (fstatat(dirfd, entry->d_name, &st, AT_SYMLINK_NOFOLLOW) != 0) {
continue;
}

Expand All @@ -634,13 +634,28 @@ static int add_directory_to_tar(gzFile gz, const char* dirpath, const char* base
}

if (S_ISDIR(st.st_mode)) {
// Recursively process subdirectory
if (add_directory_to_tar(gz, fullpath, base_path, exclude_file) != 0) {
closedir(dir);
return -1;
}
} else if (S_ISLNK(st.st_mode)) {
char target[PATH_MAX];
ssize_t len = readlinkat(dirfd, entry->d_name, target, sizeof(target) - 1);
if (len < 0) {
RDK_LOG(RDK_LOG_WARN, LOG_UPLOADSTB,
"[%s:%d] Failed to readlink: %s\n", __FUNCTION__, __LINE__, fullpath);
continue;
}
target[len] = '\0';
RDK_LOG(RDK_LOG_INFO, LOG_UPLOADSTB,
"Processing file...%s\n", arcname);
if (write_tar_header(gz, arcname, &st, target) != 0) {
RDK_LOG(RDK_LOG_WARN, LOG_UPLOADSTB,
"[%s:%d] Failed to add symlink: %s\n", __FUNCTION__, __LINE__, fullpath);
}
} else if (S_ISREG(st.st_mode)) {
// Add file
RDK_LOG(RDK_LOG_INFO, LOG_UPLOADSTB,
"Processing file...%s\n", arcname);
if (add_file_to_tar(gz, fullpath, arcname) != 0) {
RDK_LOG(RDK_LOG_WARN, LOG_UPLOADSTB,
"[%s:%d] Failed to add file: %s\n", __FUNCTION__, __LINE__, fullpath);
Expand Down
43 changes: 43 additions & 0 deletions uploadstblogs/src/cleanup_handler.c
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,49 @@ int cleanup_old_archives(const char *log_path)
return removed_count;
}

int remove_stale_timestamped_files(const char *log_path)
{
if (!log_path) {
return -1;
}

DIR *dir = opendir(log_path);
if (!dir) {
return -1;
}

int removed_count = 0;
struct dirent *entry;
int dfd = dirfd(dir);

while ((entry = readdir(dir)) != NULL) {
if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) {
continue;
}

struct stat st;
if (fstatat(dfd, entry->d_name, &st, AT_SYMLINK_NOFOLLOW) != 0 || !S_ISREG(st.st_mode)) {
continue;
}
if (!is_timestamped_backup(entry->d_name)) {
continue;
}
if (strstr(entry->d_name, "logbackup") || strstr(entry->d_name, "moca.pcap")) {
continue;
}

RDK_LOG(RDK_LOG_DEBUG, LOG_UPLOADSTB,
"[%s:%d] Removing stale timestamped file: %s\n",
__FUNCTION__, __LINE__, entry->d_name);
if (unlinkat(dfd, entry->d_name, 0) == 0) {
removed_count++;
}
}

closedir(dir);
return removed_count;
}

/* ==========================
Upload Finalization Functions
========================== */
Expand Down
10 changes: 8 additions & 2 deletions uploadstblogs/src/context_manager.c
Original file line number Diff line number Diff line change
Expand Up @@ -155,13 +155,19 @@ bool is_codebig_blocked(int block_time)
bool init_context(RuntimeContext* ctx)
{
// Initialize RDK Logger
rdk_LogOutput_File filelog;
strncpy(filelog.fileName, "dcmscript.log", sizeof(filelog.fileName)-1);
filelog.fileName[sizeof(filelog.fileName) - 1] = '\0';
strncpy(filelog.fileLocation, "/opt/logs/", sizeof(filelog.fileLocation)-1);
filelog.fileLocation[sizeof(filelog.fileLocation) - 1] = '\0';

/* Extended initialization with programmatic configuration */
rdk_logger_ext_config_t config = {
.pModuleName = "LOG.RDK.UPLOADSTB", /* Module name */
.loglevel = RDK_LOG_INFO, /* Default log level */
.output = RDKLOG_OUTPUT_CONSOLE, /* Output to console (stdout/stderr) */
.output = RDKLOG_OUTPUT_FILE,
.format = RDKLOG_FORMAT_WITH_TS, /* Timestamped format */
.pFilePolicy = NULL /* Not using file output, so NULL */
.pFilePolicy = &filelog /* using file output */
Comment on lines 157 to +170
};

if (rdk_logger_ext_init(&config) != RDK_SUCCESS) {
Expand Down
8 changes: 6 additions & 2 deletions uploadstblogs/src/strategy_handler.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,12 @@
*/

#include <stdio.h>
#include <string.h>
#include <dirent.h>
#include "strategy_handler.h"
#include "cleanup_handler.h"
#include "file_operations.h"
#include "rdk_debug.h"
#include <string.h>

// Forward declarations of strategy handlers
extern const StrategyHandler ondemand_strategy_handler;
Expand Down Expand Up @@ -71,8 +73,10 @@ int execute_strategy_workflow(RuntimeContext* ctx, SessionState* session)
return -1;
}

// Remove stale .tgz archives from log path before any strategy runs.
// Pre-strategy cleanup (script lines 967-984)
cleanup_old_archives(ctx->log_path);
clear_old_packet_captures(ctx->log_path);
remove_stale_timestamped_files(ctx->log_path);
Comment on lines +76 to +79
// Verify context has valid data
RDK_LOG(RDK_LOG_DEBUG, LOG_UPLOADSTB,
"[%s:%d] Context check: ctx=%p, MAC='%s', device_type='%s'\n",
Expand Down
Loading
Loading