From 2c775bb0c9e0ebdbdac4af717c49a55525cc2e1f Mon Sep 17 00:00:00 2001 From: ligd Date: Wed, 14 Apr 2021 22:37:52 +0800 Subject: [PATCH] fs/procfs: fix heap overflow when snprintf meet long string Change-Id: I90f2d9fab55b6e69f159855af3d6dbcb81142eb8 Signed-off-by: ligd --- fs/procfs/fs_procfs.c | 2 +- fs/procfs/fs_procfscpuload.c | 6 +- fs/procfs/fs_procfscritmon.c | 12 +-- fs/procfs/fs_procfsiobinfo.c | 24 +++--- fs/procfs/fs_procfsmeminfo.c | 43 ++++++----- fs/procfs/fs_procfsproc.c | 143 +++++++++++++++++++---------------- fs/procfs/fs_procfsuptime.c | 11 +-- fs/procfs/fs_procfsutil.c | 29 +++++++ fs/procfs/fs_procfsversion.c | 5 +- include/nuttx/fs/procfs.h | 20 +++++ 10 files changed, 178 insertions(+), 117 deletions(-) diff --git a/fs/procfs/fs_procfs.c b/fs/procfs/fs_procfs.c index 0c227b5df6..3376a24e32 100644 --- a/fs/procfs/fs_procfs.c +++ b/fs/procfs/fs_procfs.c @@ -830,7 +830,7 @@ static int procfs_readdir(struct inode *mountpt, struct fs_dirent_s *dir) /* Save the filename=pid and file type=directory */ dir->fd_dir.d_type = DTYPE_DIRECTORY; - snprintf(dir->fd_dir.d_name, NAME_MAX + 1, "%d", (int)pid); + procfs_snprintf(dir->fd_dir.d_name, NAME_MAX + 1, "%d", (int)pid); /* Set up the next directory entry offset. NOTE that we could use * the standard f_pos instead of our own private index. diff --git a/fs/procfs/fs_procfscpuload.c b/fs/procfs/fs_procfscpuload.c index 6cf8af374c..5602c9570c 100644 --- a/fs/procfs/fs_procfscpuload.c +++ b/fs/procfs/fs_procfscpuload.c @@ -238,9 +238,9 @@ static ssize_t cpuload_read(FAR struct file *filep, FAR char *buffer, fracpart = 0; } - linesize = snprintf(attr->line, CPULOAD_LINELEN, - "%3" PRId32 ".%01" PRId32 "%%\n", - intpart, fracpart); + linesize = procfs_snprintf(attr->line, CPULOAD_LINELEN, + "%3" PRId32 ".%01" PRId32 "%%\n", + intpart, fracpart); /* Save the linesize in case we are re-entered with f_pos > 0 */ diff --git a/fs/procfs/fs_procfscritmon.c b/fs/procfs/fs_procfscritmon.c index cb65bbf856..305024818c 100644 --- a/fs/procfs/fs_procfscritmon.c +++ b/fs/procfs/fs_procfscritmon.c @@ -215,9 +215,9 @@ static ssize_t critmon_read_cpu(FAR struct critmon_file_s *attr, /* Generate output for maximum time pre-emption disabled */ - linesize = snprintf(attr->line, CRITMON_LINELEN, "%d,%lu.%09lu,", - cpu, (unsigned long)maxtime.tv_sec, - (unsigned long)maxtime.tv_nsec); + linesize = procfs_snprintf(attr->line, CRITMON_LINELEN, "%d,%lu.%09lu,", + cpu, (unsigned long)maxtime.tv_sec, + (unsigned long)maxtime.tv_nsec); copysize = procfs_memcpy(attr->line, linesize, buffer, buflen, offset); totalsize += copysize; @@ -247,9 +247,9 @@ static ssize_t critmon_read_cpu(FAR struct critmon_file_s *attr, /* Generate output for maximum time in a critical section */ - linesize = snprintf(attr->line, CRITMON_LINELEN, "%lu.%09lu\n", - (unsigned long)maxtime.tv_sec, - (unsigned long)maxtime.tv_nsec); + linesize = procfs_snprintf(attr->line, CRITMON_LINELEN, "%lu.%09lu\n", + (unsigned long)maxtime.tv_sec, + (unsigned long)maxtime.tv_nsec); copysize = procfs_memcpy(attr->line, linesize, buffer, buflen, offset); totalsize += copysize; diff --git a/fs/procfs/fs_procfsiobinfo.c b/fs/procfs/fs_procfsiobinfo.c index b7da24a0fa..48d7902444 100644 --- a/fs/procfs/fs_procfsiobinfo.c +++ b/fs/procfs/fs_procfsiobinfo.c @@ -280,7 +280,7 @@ static ssize_t iobinfo_read(FAR struct file *filep, FAR char *buffer, /* The first line is the headers */ - linesize = snprintf(iobfile->line, IOBINFO_LINELEN, + linesize = procfs_snprintf(iobfile->line, IOBINFO_LINELEN, " TOTAL TOTAL\n"); copysize = procfs_memcpy(iobfile->line, linesize, buffer, buflen, @@ -292,7 +292,7 @@ static ssize_t iobinfo_read(FAR struct file *filep, FAR char *buffer, buffer += copysize; buflen -= copysize; - linesize = snprintf(iobfile->line, IOBINFO_LINELEN, + linesize = procfs_snprintf(iobfile->line, IOBINFO_LINELEN, " USER CONSUMED " "PRODUCED\n"); @@ -311,11 +311,11 @@ static ssize_t iobinfo_read(FAR struct file *filep, FAR char *buffer, buflen -= copysize; userstats = iob_getuserstats(i); - linesize = snprintf(iobfile->line, IOBINFO_LINELEN, - "%-16s%16lu%16lu\n", - g_iob_user_names[i], - (unsigned long)userstats->totalconsumed, - (unsigned long)userstats->totalproduced); + linesize = procfs_snprintf(iobfile->line, IOBINFO_LINELEN, + "%-16s%16lu%16lu\n", + g_iob_user_names[i], + (unsigned long)userstats->totalconsumed, + (unsigned long)userstats->totalproduced); copysize = procfs_memcpy(iobfile->line, linesize, buffer, buflen, &offset); @@ -329,11 +329,11 @@ static ssize_t iobinfo_read(FAR struct file *filep, FAR char *buffer, buflen -= copysize; userstats = iob_getuserstats(IOBUSER_GLOBAL); - linesize = snprintf(iobfile->line, IOBINFO_LINELEN, - "\n%-16s%16lu%16lu\n", - g_iob_user_names[IOBUSER_GLOBAL], - (unsigned long)userstats->totalconsumed, - (unsigned long)userstats->totalproduced); + linesize = procfs_snprintf(iobfile->line, IOBINFO_LINELEN, + "\n%-16s%16lu%16lu\n", + g_iob_user_names[IOBUSER_GLOBAL], + (unsigned long)userstats->totalconsumed, + (unsigned long)userstats->totalproduced); copysize = procfs_memcpy(iobfile->line, linesize, buffer, buflen, &offset); diff --git a/fs/procfs/fs_procfsmeminfo.c b/fs/procfs/fs_procfsmeminfo.c index ebef16a7bd..3f2d1a4579 100644 --- a/fs/procfs/fs_procfsmeminfo.c +++ b/fs/procfs/fs_procfsmeminfo.c @@ -287,7 +287,7 @@ static ssize_t meminfo_read(FAR struct file *filep, FAR char *buffer, /* The first line is the headers */ linesize = - snprintf(procfile->line, MEMINFO_LINELEN, + procfs_snprintf(procfile->line, MEMINFO_LINELEN, " " "total used free largest nused nfree\n"); @@ -311,15 +311,16 @@ static ssize_t meminfo_read(FAR struct file *filep, FAR char *buffer, /* Show heap information */ entry->mallinfo(entry->user_data, &minfo); - linesize = snprintf(procfile->line, MEMINFO_LINELEN, - "%12s: %11lu%11lu%11lu%11lu%7lu%7lu\n", - entry->name, - (unsigned long)minfo.arena, - (unsigned long)minfo.uordblks, - (unsigned long)minfo.fordblks, - (unsigned long)minfo.mxordblk, - (unsigned long)minfo.aordblks, - (unsigned long)minfo.ordblks); + linesize = procfs_snprintf(procfile->line, MEMINFO_LINELEN, + "%12s: " + "%11lu%11lu%11lu%11lu%7lu%7lu\n", + entry->name, + (unsigned long)minfo.arena, + (unsigned long)minfo.uordblks, + (unsigned long)minfo.fordblks, + (unsigned long)minfo.mxordblk, + (unsigned long)minfo.aordblks, + (unsigned long)minfo.ordblks); copysize = procfs_memcpy(procfile->line, linesize, buffer, buflen, &offset); totalsize += copysize; @@ -347,9 +348,9 @@ static ssize_t meminfo_read(FAR struct file *filep, FAR char *buffer, allocated = total - available; max = (unsigned long)pginfo.mxfree << MM_PGSHIFT; - linesize = snprintf(procfile->line, MEMINFO_LINELEN, - "Page: %11lu%11lu%11lu%11lu\n", - total, allocated, available, max); + linesize = procfs_snprintf(procfile->line, MEMINFO_LINELEN, + "Page: %11lu%11lu%11lu%11lu\n", + total, allocated, available, max); copysize = procfs_memcpy(procfile->line, linesize, buffer, buflen, &offset); @@ -369,14 +370,14 @@ static ssize_t meminfo_read(FAR struct file *filep, FAR char *buffer, meminfo_progmem(&progmem); - linesize = snprintf(procfile->line, MEMINFO_LINELEN, - "Prog: %11lu%11lu%11lu%11lu%7lu%7lu\n", - (unsigned long)progmem.arena, - (unsigned long)progmem.uordblks, - (unsigned long)progmem.fordblks, - (unsigned long)progmem.mxordblk, - (unsigned long)progmem.aordblks, - (unsigned long)progmem.ordblks); + linesize = procfs_snprintf(procfile->line, MEMINFO_LINELEN, + "Prog: %11lu%11lu%11lu%11lu%7lu%7lu\n", + (unsigned long)progmem.arena, + (unsigned long)progmem.uordblks, + (unsigned long)progmem.fordblks, + (unsigned long)progmem.mxordblk, + (unsigned long)progmem.aordblks, + (unsigned long)progmem.ordblks); copysize = procfs_memcpy(procfile->line, linesize, buffer, buflen, &offset); totalsize += copysize; diff --git a/fs/procfs/fs_procfsproc.c b/fs/procfs/fs_procfsproc.c index c6d0d45ad6..47d062af22 100644 --- a/fs/procfs/fs_procfsproc.c +++ b/fs/procfs/fs_procfsproc.c @@ -459,8 +459,8 @@ static ssize_t proc_status(FAR struct proc_file_s *procfile, #else name = ""; #endif - linesize = snprintf(procfile->line, STATUS_LINELEN, "%-12s%s\n", - "Name:", name); + linesize = procfs_snprintf(procfile->line, STATUS_LINELEN, "%-12s%s\n", + "Name:", name); copysize = procfs_memcpy(procfile->line, linesize, buffer, remaining, &offset); @@ -475,11 +475,12 @@ static ssize_t proc_status(FAR struct proc_file_s *procfile, /* Show the thread type */ - linesize = snprintf(procfile->line, STATUS_LINELEN, "%-12s%s\n", "Type:", - g_ttypenames[(tcb->flags & TCB_FLAG_TTYPE_MASK) >> - TCB_FLAG_TTYPE_SHIFT]); - copysize = procfs_memcpy(procfile->line, linesize, buffer, remaining, - &offset); + linesize = procfs_snprintf(procfile->line, STATUS_LINELEN, "%-12s%s\n", + "Type:", + g_ttypenames[(tcb->flags & TCB_FLAG_TTYPE_MASK) + >> TCB_FLAG_TTYPE_SHIFT]); + copysize = procfs_memcpy(procfile->line, linesize, buffer, remaining, + &offset); totalsize += copysize; buffer += copysize; @@ -493,8 +494,9 @@ static ssize_t proc_status(FAR struct proc_file_s *procfile, group = tcb->group; DEBUGASSERT(group != NULL); - linesize = snprintf(procfile->line, STATUS_LINELEN, "%-12s%d\n", "PPID:", - group->tg_ppid); + linesize = procfs_snprintf(procfile->line, STATUS_LINELEN, + "%-12s%d\n", "PPID:", + group->tg_ppid); copysize = procfs_memcpy(procfile->line, linesize, buffer, remaining, &offset); @@ -511,13 +513,13 @@ static ssize_t proc_status(FAR struct proc_file_s *procfile, if (tcb->task_state >= FIRST_ASSIGNED_STATE && tcb->task_state <= LAST_ASSIGNED_STATE) { - linesize = snprintf(procfile->line, STATUS_LINELEN, "%-12s%d\n", - "CPU:", tcb->cpu); + linesize = procfs_snprintf(procfile->line, STATUS_LINELEN, + "%-12s%d\n", "CPU:", tcb->cpu); } else { - linesize = snprintf(procfile->line, STATUS_LINELEN, "%-12s---\n", - "CPU:"); + linesize = procfs_snprintf(procfile->line, STATUS_LINELEN, + "%-12s---\n", "CPU:"); } copysize = procfs_memcpy(procfile->line, linesize, buffer, remaining, @@ -535,8 +537,9 @@ static ssize_t proc_status(FAR struct proc_file_s *procfile, /* Show the thread state */ - linesize = snprintf(procfile->line, STATUS_LINELEN, "%-12s%s\n", - "State:", g_statenames[tcb->task_state]); + linesize = procfs_snprintf(procfile->line, STATUS_LINELEN, + "%-12s%s\n", "State:", + g_statenames[tcb->task_state]); copysize = procfs_memcpy(procfile->line, linesize, buffer, remaining, &offset); @@ -551,11 +554,11 @@ static ssize_t proc_status(FAR struct proc_file_s *procfile, /* Show task flags */ - linesize = snprintf(procfile->line, STATUS_LINELEN, - "%-12s%c%c%c\n", "Flags:", - tcb->flags & TCB_FLAG_NONCANCELABLE ? 'N' : '-', - tcb->flags & TCB_FLAG_CANCEL_PENDING ? 'P' : '-', - tcb->flags & TCB_FLAG_EXIT_PROCESSING ? 'P' : '-'); + linesize = procfs_snprintf(procfile->line, STATUS_LINELEN, + "%-12s%c%c%c\n", "Flags:", + tcb->flags & TCB_FLAG_NONCANCELABLE ? 'N' : '-', + tcb->flags & TCB_FLAG_CANCEL_PENDING ? 'P' : '-', + tcb->flags & TCB_FLAG_EXIT_PROCESSING ? 'P' : '-'); copysize = procfs_memcpy(procfile->line, linesize, buffer, remaining, &offset); @@ -572,12 +575,12 @@ static ssize_t proc_status(FAR struct proc_file_s *procfile, /* Show the thread priority */ #ifdef CONFIG_PRIORITY_INHERITANCE - linesize = snprintf(procfile->line, STATUS_LINELEN, - "%-12s%d (%d)\n", "Priority:", - tcb->sched_priority, tcb->base_priority); + linesize = procfs_snprintf(procfile->line, STATUS_LINELEN, + "%-12s%d (%d)\n", "Priority:", + tcb->sched_priority, tcb->base_priority); #else - linesize = snprintf(procfile->line, STATUS_LINELEN, "%-12s%d\n", - "Priority:", tcb->sched_priority); + linesize = procfs_snprintf(procfile->line, STATUS_LINELEN, "%-12s%d\n", + "Priority:", tcb->sched_priority); #endif copysize = procfs_memcpy(procfile->line, linesize, buffer, remaining, &offset); @@ -595,8 +598,8 @@ static ssize_t proc_status(FAR struct proc_file_s *procfile, policy = g_policy[(tcb->flags & TCB_FLAG_POLICY_MASK) >> TCB_FLAG_POLICY_SHIFT]; - linesize = snprintf(procfile->line, STATUS_LINELEN, "%-12s%s\n", - "Scheduler:", policy); + linesize = procfs_snprintf(procfile->line, STATUS_LINELEN, "%-12s%s\n", + "Scheduler:", policy); copysize = procfs_memcpy(procfile->line, linesize, buffer, remaining, &offset); @@ -611,8 +614,9 @@ static ssize_t proc_status(FAR struct proc_file_s *procfile, /* Show the signal mask. Note: sigset_t is uint32_t on NuttX. */ - linesize = snprintf(procfile->line, STATUS_LINELEN, "%-12s%08" PRIx32 "\n", - "SigMask:", tcb->sigprocmask); + linesize = procfs_snprintf(procfile->line, STATUS_LINELEN, + "%-12s%08" PRIx32 "\n", + "SigMask:", tcb->sigprocmask); copysize = procfs_memcpy(procfile->line, linesize, buffer, remaining, &offset); @@ -667,8 +671,8 @@ static ssize_t proc_cmdline(FAR struct proc_file_s *procfile, { FAR struct pthread_tcb_s *ptcb = (FAR struct pthread_tcb_s *)tcb; - linesize = snprintf(procfile->line, STATUS_LINELEN, " %p\n", - ptcb->arg); + linesize = procfs_snprintf(procfile->line, STATUS_LINELEN, " %p\n", + ptcb->arg); copysize = procfs_memcpy(procfile->line, linesize, buffer, remaining, &offset); @@ -686,7 +690,8 @@ static ssize_t proc_cmdline(FAR struct proc_file_s *procfile, for (argv = ttcb->argv + 1; *argv; argv++) { - linesize = snprintf(procfile->line, STATUS_LINELEN, " %s", *argv); + linesize = procfs_snprintf(procfile->line, STATUS_LINELEN, + " %s", *argv); copysize = procfs_memcpy(procfile->line, linesize, buffer, remaining, &offset); @@ -700,7 +705,7 @@ static ssize_t proc_cmdline(FAR struct proc_file_s *procfile, } } - linesize = snprintf(procfile->line, STATUS_LINELEN, "\n"); + linesize = procfs_snprintf(procfile->line, STATUS_LINELEN, "\n"); copysize = procfs_memcpy(procfile->line, linesize, buffer, remaining, &offset); @@ -748,9 +753,9 @@ static ssize_t proc_loadavg(FAR struct proc_file_s *procfile, fracpart = 0; } - linesize = snprintf(procfile->line, STATUS_LINELEN, - "%3" PRId32 ".%01" PRId32 "%%", - intpart, fracpart); + linesize = procfs_snprintf(procfile->line, STATUS_LINELEN, + "%3" PRId32 ".%01" PRId32 "%%", + intpart, fracpart); copysize = procfs_memcpy(procfile->line, linesize, buffer, buflen, &offset); @@ -794,9 +799,9 @@ static ssize_t proc_critmon(FAR struct proc_file_s *procfile, /* Generate output for maximum time pre-emption disabled */ - linesize = snprintf(procfile->line, STATUS_LINELEN, "%lu.%09lu,", - (unsigned long)maxtime.tv_sec, - (unsigned long)maxtime.tv_nsec); + linesize = procfs_snprintf(procfile->line, STATUS_LINELEN, "%lu.%09lu,", + (unsigned long)maxtime.tv_sec, + (unsigned long)maxtime.tv_nsec); copysize = procfs_memcpy(procfile->line, linesize, buffer, buflen, &offset); @@ -827,9 +832,9 @@ static ssize_t proc_critmon(FAR struct proc_file_s *procfile, /* Generate output for maximum time in a critical section */ - linesize = snprintf(procfile->line, STATUS_LINELEN, "%lu.%09lu\n", - (unsigned long)maxtime.tv_sec, - (unsigned long)maxtime.tv_nsec); + linesize = procfs_snprintf(procfile->line, STATUS_LINELEN, "%lu.%09lu\n", + (unsigned long)maxtime.tv_sec, + (unsigned long)maxtime.tv_nsec); copysize = procfs_memcpy(procfile->line, linesize, buffer, buflen, &offset); @@ -872,8 +877,8 @@ static ssize_t proc_stack(FAR struct proc_file_s *procfile, /* Show the stack base address */ - linesize = snprintf(procfile->line, STATUS_LINELEN, "%-12s%p\n", - "StackBase:", tcb->stack_base_ptr); + linesize = procfs_snprintf(procfile->line, STATUS_LINELEN, "%-12s%p\n", + "StackBase:", tcb->stack_base_ptr); copysize = procfs_memcpy(procfile->line, linesize, buffer, remaining, &offset); @@ -888,8 +893,8 @@ static ssize_t proc_stack(FAR struct proc_file_s *procfile, /* Show the stack size */ - linesize = snprintf(procfile->line, STATUS_LINELEN, "%-12s%ld\n", - "StackSize:", (long)tcb->adj_stack_size); + linesize = procfs_snprintf(procfile->line, STATUS_LINELEN, "%-12s%ld\n", + "StackSize:", (long)tcb->adj_stack_size); copysize = procfs_memcpy(procfile->line, linesize, buffer, remaining, &offset); @@ -905,8 +910,8 @@ static ssize_t proc_stack(FAR struct proc_file_s *procfile, /* Show the stack size */ - linesize = snprintf(procfile->line, STATUS_LINELEN, "%-12s%ld\n", - "StackUsed:", (long)up_check_tcbstack(tcb)); + linesize = procfs_snprintf(procfile->line, STATUS_LINELEN, "%-12s%ld\n", + "StackUsed:", (long)up_check_tcbstack(tcb)); copysize = procfs_memcpy(procfile->line, linesize, buffer, remaining, &offset); @@ -940,8 +945,8 @@ static ssize_t proc_groupstatus(FAR struct proc_file_s *procfile, remaining = buflen; totalsize = 0; - linesize = snprintf(procfile->line, STATUS_LINELEN, "%-12s%d\n", - "Main task:", group->tg_pid); + linesize = procfs_snprintf(procfile->line, STATUS_LINELEN, "%-12s%d\n", + "Main task:", group->tg_pid); copysize = procfs_memcpy(procfile->line, linesize, buffer, remaining, &offset); @@ -954,8 +959,9 @@ static ssize_t proc_groupstatus(FAR struct proc_file_s *procfile, return totalsize; } - linesize = snprintf(procfile->line, STATUS_LINELEN, "%-12s0x%02x\n", - "Flags:", group->tg_flags); + linesize = procfs_snprintf(procfile->line, STATUS_LINELEN, + "%-12s0x%02x\n", + "Flags:", group->tg_flags); copysize = procfs_memcpy(procfile->line, linesize, buffer, remaining, &offset); @@ -968,8 +974,8 @@ static ssize_t proc_groupstatus(FAR struct proc_file_s *procfile, return totalsize; } - linesize = snprintf(procfile->line, STATUS_LINELEN, "%-12s%d\n", - "Members:", group->tg_nmembers); + linesize = procfs_snprintf(procfile->line, STATUS_LINELEN, "%-12s%d\n", + "Members:", group->tg_nmembers); copysize = procfs_memcpy(procfile->line, linesize, buffer, remaining, &offset); @@ -983,7 +989,8 @@ static ssize_t proc_groupstatus(FAR struct proc_file_s *procfile, return totalsize; } - linesize = snprintf(procfile->line, STATUS_LINELEN, "Member IDs:"); + linesize = procfs_snprintf(procfile->line, STATUS_LINELEN, + "Member IDs:"); copysize = procfs_memcpy(procfile->line, linesize, buffer, remaining, &offset); @@ -998,8 +1005,8 @@ static ssize_t proc_groupstatus(FAR struct proc_file_s *procfile, for (i = 0; i < group->tg_nmembers; i++) { - linesize = snprintf(procfile->line, STATUS_LINELEN, " %d", - group->tg_members[i]); + linesize = procfs_snprintf(procfile->line, STATUS_LINELEN, " %d", + group->tg_members[i]); copysize = procfs_memcpy(procfile->line, linesize, buffer, remaining, &offset); @@ -1013,7 +1020,7 @@ static ssize_t proc_groupstatus(FAR struct proc_file_s *procfile, } } - linesize = snprintf(procfile->line, STATUS_LINELEN, "\n"); + linesize = procfs_snprintf(procfile->line, STATUS_LINELEN, "\n"); copysize = procfs_memcpy(procfile->line, linesize, buffer, remaining, &offset); @@ -1047,8 +1054,9 @@ static ssize_t proc_groupfd(FAR struct proc_file_s *procfile, remaining = buflen; totalsize = 0; - linesize = snprintf(procfile->line, STATUS_LINELEN, "\n%-3s %-8s %s\n", - "FD", "POS", "OFLAGS"); + linesize = procfs_snprintf(procfile->line, STATUS_LINELEN, + "\n%-3s %-8s %s\n", + "FD", "POS", "OFLAGS"); copysize = procfs_memcpy(procfile->line, linesize, buffer, remaining, &offset); @@ -1073,7 +1081,7 @@ static ssize_t proc_groupfd(FAR struct proc_file_s *procfile, if (file->f_inode && !INODE_IS_SOCKET(file->f_inode)) { - linesize = snprintf(procfile->line, STATUS_LINELEN, + linesize = procfs_snprintf(procfile->line, STATUS_LINELEN, "%3d %8ld %04x\n", i * CONFIG_NFILE_DESCRIPTORS_PER_BLOCK + j, (long)file->f_pos, @@ -1094,9 +1102,9 @@ static ssize_t proc_groupfd(FAR struct proc_file_s *procfile, } #ifdef CONFIG_NET - linesize = snprintf(procfile->line, STATUS_LINELEN, - "\n%-3s %-2s %-3s %s\n", - "SD", "RF", "TYP", "FLAGS"); + linesize = procfs_snprintf(procfile->line, STATUS_LINELEN, + "\n%-3s %-2s %-3s %s\n", + "SD", "RF", "TYP", "FLAGS"); copysize = procfs_memcpy(procfile->line, linesize, buffer, remaining, &offset); @@ -1122,7 +1130,7 @@ static ssize_t proc_groupfd(FAR struct proc_file_s *procfile, if (file->f_inode && INODE_IS_SOCKET(file->f_inode)) { FAR struct socket *socket = file->f_priv; - linesize = snprintf(procfile->line, STATUS_LINELEN, + linesize = procfs_snprintf(procfile->line, STATUS_LINELEN, "%3d %3d %02x", i * CONFIG_NFILE_DESCRIPTORS_PER_BLOCK + j, socket->s_type, @@ -1195,8 +1203,9 @@ static int proc_groupenv_callback(FAR void *arg, FAR const char *pair) /* Output the header */ - linesize = snprintf(info->procfile->line, STATUS_LINELEN, "%s=%s\n", - name, value); + linesize = procfs_snprintf(info->procfile->line, + STATUS_LINELEN, "%s=%s\n", + name, value); copysize = procfs_memcpy(info->procfile->line, linesize, info->buffer, info->remaining, &info->offset); diff --git a/fs/procfs/fs_procfsuptime.c b/fs/procfs/fs_procfsuptime.c index c17a95aec3..c7181d1163 100644 --- a/fs/procfs/fs_procfsuptime.c +++ b/fs/procfs/fs_procfsuptime.c @@ -231,7 +231,8 @@ static ssize_t uptime_read(FAR struct file *filep, FAR char *buffer, /* Convert the up time to a seconds + hundredths of seconds string */ now = (double)ticktime / (double)CLOCKS_PER_SEC; - linesize = snprintf(attr->line, UPTIME_LINELEN, "%10.2f\n", now); + linesize = procfs_snprintf(attr->line, UPTIME_LINELEN, + "%10.2f\n", now); #else /* Convert the system up time to seconds + hundredths of seconds */ @@ -253,11 +254,11 @@ static ssize_t uptime_read(FAR struct file *filep, FAR char *buffer, /* Convert the seconds + hundredths of seconds to a string */ #ifdef CONFIG_SYSTEM_TIME64 - linesize = snprintf(attr->line, UPTIME_LINELEN, "%7" PRIu64 ".%02u\n", - sec, csec); + linesize = procfs_snprintf(attr->line, UPTIME_LINELEN, + "%7" PRIu64 ".%02u\n", sec, csec); #else - linesize = snprintf(attr->line, UPTIME_LINELEN, "%7lu.%02u\n", - (unsigned long)sec, csec); + linesize = procfs_snprintf(attr->line, UPTIME_LINELEN, + "%7lu.%02u\n", (unsigned long)sec, csec); #endif #endif diff --git a/fs/procfs/fs_procfsutil.c b/fs/procfs/fs_procfsutil.c index 0dd52a7137..87c91d2c5b 100644 --- a/fs/procfs/fs_procfsutil.c +++ b/fs/procfs/fs_procfsutil.c @@ -25,6 +25,7 @@ #include #include +#include #include #include @@ -116,4 +117,32 @@ size_t procfs_memcpy(FAR const char *src, size_t srclen, return copysize; } +/**************************************************************************** + * Name: procfs_snprintf + * + * Description: + * This function is same with snprintf, except return values. + * If buf has no enough space and output was truncated due to size limit, + * snprintf: return formated string len. + * procfs_snprintf: return string len which has written to buf. + * + * Input Parameters: + * Same with snprintf + * + * Returned Value: + * See Description. + * + ****************************************************************************/ + +int procfs_snprintf(FAR char *buf, size_t size, + FAR const IPTR char *format, ...) +{ + va_list ap; + int n; + va_start(ap, format); + n = vsnprintf(buf, size, format, ap); + va_end(ap); + return n < size - 1 ? n : size - 1; +} + #endif /* !CONFIG_DISABLE_MOUNTPOINT && CONFIG_FS_PROCFS */ diff --git a/fs/procfs/fs_procfsversion.c b/fs/procfs/fs_procfsversion.c index 5b1dae43aa..a3ad22502d 100644 --- a/fs/procfs/fs_procfsversion.c +++ b/fs/procfs/fs_procfsversion.c @@ -207,8 +207,9 @@ static ssize_t version_read(FAR struct file *filep, FAR char *buffer, if (filep->f_pos == 0) { uname(&name); - linesize = snprintf(attr->line, VERSION_LINELEN, "%s version %s %s\n", - name.sysname, name.release, name.version); + linesize = procfs_snprintf(attr->line, VERSION_LINELEN, + "%s version %s %s\n", + name.sysname, name.release, name.version); /* Save the linesize in case we are re-entered with f_pos > 0 */ diff --git a/include/nuttx/fs/procfs.h b/include/nuttx/fs/procfs.h index dbedab4a86..b826560132 100644 --- a/include/nuttx/fs/procfs.h +++ b/include/nuttx/fs/procfs.h @@ -194,6 +194,26 @@ size_t procfs_memcpy(FAR const char *src, size_t srclen, FAR char *dest, size_t destlen, off_t *offset); +/**************************************************************************** + * Name: procfs_snprintf + * + * Description: + * This function is same with snprintf, except return values. + * If buf has no enough space and output was truncated due to size limit, + * snprintf: return formated string len. + * procfs_snprintf: return string len which has written to buf. + * + * Input Parameters: + * Same with snprintf + * + * Returned Value: + * See Description. + * + ****************************************************************************/ + +int procfs_snprintf(FAR char *buf, size_t size, + FAR const IPTR char *format, ...); + /**************************************************************************** * Name: procfs_register *