You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by xi...@apache.org on 2021/07/02 13:25:09 UTC

[incubator-nuttx] 01/04: fs/procfs: fix heap overflow when snprintf meet long string

This is an automated email from the ASF dual-hosted git repository.

xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git

commit 2c775bb0c9e0ebdbdac4af717c49a55525cc2e1f
Author: ligd <li...@xiaomi.com>
AuthorDate: Wed Apr 14 22:37:52 2021 +0800

    fs/procfs: fix heap overflow when snprintf meet long string
    
    Change-Id: I90f2d9fab55b6e69f159855af3d6dbcb81142eb8
    Signed-off-by: ligd <li...@xiaomi.com>
---
 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 0c227b5..3376a24 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 6cf8af3..5602c95 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 cb65bbf..3050248 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 b7da24a..48d7902 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 ebef16a..3f2d1a4 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 c6d0d45..47d062a 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       = "<noname>";
 #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 c17a95a..c7181d1 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 0dd52a7..87c91d2 100644
--- a/fs/procfs/fs_procfsutil.c
+++ b/fs/procfs/fs_procfsutil.c
@@ -25,6 +25,7 @@
 #include <nuttx/config.h>
 
 #include <sys/types.h>
+#include <stdio.h>
 #include <string.h>
 
 #include <nuttx/fs/procfs.h>
@@ -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 5b1dae4..a3ad225 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 dbedab4..b826560 100644
--- a/include/nuttx/fs/procfs.h
+++ b/include/nuttx/fs/procfs.h
@@ -195,6 +195,26 @@ size_t procfs_memcpy(FAR const char *src, size_t srclen,
                      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
  *
  * Description: