Skip to content

Commit 12bd27f

Browse files
feat: add ismodulerestarted parameter to DeviceFingerPrint section
Add a new read-only boolean TR-181 parameter 'ismodulerestarted' under Device.DeviceInfo.X_RDKCENTRAL-COM_DeviceFingerPrint that indicates whether the cujo-agent has been restarted since system boot. The parameter compares the cujo-agent process start time (from /proc/<pid>/stat) against the system uptime. If the agent started after boot (start time > 0 seconds after boot), it is considered restarted. Changes: - Add CosaAdvSecIsAgentRestarted() in cosa_adv_security_internal.c - Add declaration in cosa_adv_security_internal.h - Add ismodulerestarted case in DeviceFingerPrint_GetParamBoolValue - Add parameter definition in TR181-AdvSecurity.xml (read-only boolean) - Add unit tests for the new parameter Resolves #66
1 parent 57da2f9 commit 12bd27f

5 files changed

Lines changed: 154 additions & 0 deletions

File tree

config/TR181-AdvSecurity.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,12 @@
6666
<syntax>uint32</syntax>
6767
<writable>true</writable>
6868
</parameter>
69+
<parameter>
70+
<name>ismodulerestarted</name>
71+
<type>boolean</type>
72+
<syntax>bool</syntax>
73+
<writable>false</writable>
74+
</parameter>
6975
</parameters>
7076
</object>
7177
<object>

source/AdvSecurityDml/cosa_adv_security_dml.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,14 @@ DeviceFingerPrint_GetParamBoolValue
141141
return TRUE;
142142
}
143143

144+
rc = strcmp_s("ismodulerestarted", strlen("ismodulerestarted"), ParamName, &ind);
145+
ERR_CHK(rc);
146+
if((rc == EOK) && (!ind))
147+
{
148+
*pBool = CosaAdvSecIsAgentRestarted();
149+
return TRUE;
150+
}
151+
144152
CcspTraceWarning(("%s: Unsupported parameter '%s'\n", __FUNCTION__, ParamName));
145153
return FALSE;
146154
}

source/AdvSecurityDml/cosa_adv_security_internal.c

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3521,3 +3521,109 @@ ANSC_STATUS CosaAdvSecAgentRaptrDeInit(ANSC_HANDLE hThisObject)
35213521
CcspTraceWarning (("AdvSecAgentRaptr_RFCEnable:FALSE\n"));
35223522
return returnStatus;
35233523
}
3524+
3525+
BOOL CosaAdvSecIsAgentRestarted(void)
3526+
{
3527+
FILE *fp = NULL;
3528+
char pid_str[32] = {0};
3529+
char proc_path[64] = {0};
3530+
char stat_buf[512] = {0};
3531+
unsigned long long starttime = 0;
3532+
long uptime_sec = 0;
3533+
long agent_start_sec = 0;
3534+
long clk_tck = 0;
3535+
struct sysinfo si;
3536+
int i = 0;
3537+
char *token = NULL;
3538+
3539+
/* Read cujo-agent PID */
3540+
fp = fopen("/tmp/cujo-agent.pid", "r");
3541+
if (fp == NULL)
3542+
{
3543+
CcspTraceInfo(("%s: cujo-agent.pid not found, agent not running\n", __FUNCTION__));
3544+
return FALSE;
3545+
}
3546+
if (fgets(pid_str, sizeof(pid_str), fp) == NULL)
3547+
{
3548+
fclose(fp);
3549+
return FALSE;
3550+
}
3551+
fclose(fp);
3552+
3553+
/* Remove trailing newline */
3554+
pid_str[strcspn(pid_str, "\n")] = '\0';
3555+
if (pid_str[0] == '\0')
3556+
{
3557+
return FALSE;
3558+
}
3559+
3560+
/* Read /proc/<pid>/stat to get process start time */
3561+
snprintf(proc_path, sizeof(proc_path), "/proc/%s/stat", pid_str);
3562+
fp = fopen(proc_path, "r");
3563+
if (fp == NULL)
3564+
{
3565+
CcspTraceInfo(("%s: Cannot open %s, agent process not found\n", __FUNCTION__, proc_path));
3566+
return FALSE;
3567+
}
3568+
if (fgets(stat_buf, sizeof(stat_buf), fp) == NULL)
3569+
{
3570+
fclose(fp);
3571+
return FALSE;
3572+
}
3573+
fclose(fp);
3574+
3575+
/* Field 22 (1-indexed) in /proc/<pid>/stat is starttime in clock ticks.
3576+
* Skip past the comm field (enclosed in parentheses) first to avoid
3577+
* issues with spaces in the process name. */
3578+
token = strrchr(stat_buf, ')');
3579+
if (token == NULL)
3580+
{
3581+
return FALSE;
3582+
}
3583+
token++; /* move past ')' */
3584+
3585+
/* Now parse fields starting from field 3 (state). Field 22 is at index 20 from here. */
3586+
for (i = 0; i < 20 && token != NULL; i++)
3587+
{
3588+
token = strchr(token, ' ');
3589+
if (token != NULL)
3590+
{
3591+
token++;
3592+
}
3593+
}
3594+
if (token == NULL)
3595+
{
3596+
return FALSE;
3597+
}
3598+
starttime = strtoull(token, NULL, 10);
3599+
if (starttime == 0)
3600+
{
3601+
return FALSE;
3602+
}
3603+
3604+
/* Get system uptime */
3605+
if (sysinfo(&si) != 0)
3606+
{
3607+
CcspTraceError(("%s: sysinfo() failed\n", __FUNCTION__));
3608+
return FALSE;
3609+
}
3610+
uptime_sec = si.uptime;
3611+
3612+
/* Convert agent start time from clock ticks to seconds since boot */
3613+
clk_tck = sysconf(_SC_CLK_TCK);
3614+
if (clk_tck <= 0)
3615+
{
3616+
clk_tck = 100; /* default fallback */
3617+
}
3618+
agent_start_sec = (long)(starttime / (unsigned long long)clk_tck);
3619+
3620+
/* If agent started after boot (agent_start_sec > 0), it has been restarted */
3621+
if (agent_start_sec > 0)
3622+
{
3623+
CcspTraceInfo(("%s: Agent restarted. Agent start=%ld sec after boot, system uptime=%ld sec\n",
3624+
__FUNCTION__, agent_start_sec, uptime_sec));
3625+
return TRUE;
3626+
}
3627+
3628+
return FALSE;
3629+
}

source/AdvSecurityDml/cosa_adv_security_internal.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -564,4 +564,10 @@ CosaAdvSecFetchSbConfig
564564
ULONG* pUlSize,
565565
ULONG* puLong
566566
);
567+
568+
BOOL
569+
CosaAdvSecIsAgentRestarted
570+
(
571+
void
572+
);
567573
#endif

source/test/CcspAdvSecurityDmlTest/CcspAdvSecurityDmlTest.cpp

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,13 +133,41 @@ TEST_F(CcspAdvSecurityDmlTestFixture, CheckDeviceFingerPrint_GetParamBoolValue_U
133133
.Times(1)
134134
.WillOnce(DoAll(SetArgPointee<3>(comparisonResult), Return(EOK)));
135135

136+
EXPECT_CALL(*g_safecLibMock, _strcmp_s_chk(StrEq("ismodulerestarted"), strlen("ismodulerestarted"), StrEq(ParamName), _, _, _))
137+
.Times(1)
138+
.WillOnce(DoAll(SetArgPointee<3>(comparisonResult), Return(EOK)));
139+
136140
BOOL result = DeviceFingerPrint_GetParamBoolValue(NULL, (char*)ParamName, &resultBool);
137141

138142
EXPECT_FALSE(result);
139143

140144
delete pMyObject;
141145
}
142146

147+
TEST_F(CcspAdvSecurityDmlTestFixture, CheckDeviceFingerPrint_GetParamBoolValue_ismodulerestarted) {
148+
BOOL resultBool;
149+
PCOSA_DATAMODEL_AGENT pMyObject = new COSA_DATAMODEL_AGENT;
150+
g_pAdvSecAgent = pMyObject;
151+
152+
const char* ParamName = "ismodulerestarted";
153+
int enableComparisonResult = 1;
154+
int ismodulerestartedComparisonResult = 0;
155+
156+
EXPECT_CALL(*g_safecLibMock, _strcmp_s_chk(StrEq("Enable"), strlen("Enable"), StrEq(ParamName), _, _, _))
157+
.Times(1)
158+
.WillOnce(DoAll(SetArgPointee<3>(enableComparisonResult), Return(EOK)));
159+
160+
EXPECT_CALL(*g_safecLibMock, _strcmp_s_chk(StrEq("ismodulerestarted"), strlen("ismodulerestarted"), StrEq(ParamName), _, _, _))
161+
.Times(1)
162+
.WillOnce(DoAll(SetArgPointee<3>(ismodulerestartedComparisonResult), Return(EOK)));
163+
164+
BOOL result = DeviceFingerPrint_GetParamBoolValue(NULL, (char*)ParamName, &resultBool);
165+
166+
EXPECT_TRUE(result);
167+
168+
delete pMyObject;
169+
}
170+
143171
TEST_F(CcspAdvSecurityDmlTestFixture, CheckDeviceFingerPrint_SetParamBoolValue_Enable) {
144172

145173
const char *DeviceFingerPrintEnabled = "Advsecurity_DeviceFingerPrint";

0 commit comments

Comments
 (0)