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

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


The following commit(s) were added to refs/heads/master by this push:
     new 844e0ac6f4e binfmt: Report the error of the loader that knew the 
format.
844e0ac6f4e is described below

commit 844e0ac6f4e50ac7ef87bb646644b01373876430
Author: Marco Casaroli <[email protected]>
AuthorDate: Tue Nov 3 01:40:04 2026 +0100

    binfmt: Report the error of the loader that knew the format.
    
    load_absmodule() tries each binary format handler and returned the
    error of the last one.  This hid two errors:
    
    When the ELF loader recognized a program and failed for another reason,
    for example -ENOMEM for a program that does not fit, the next handler
    said "not my format" and exec() failed with ENOEXEC ("Exec format
    error").
    
    When a file was not a program and the builtin handler was the last one,
    exec() failed with ENOENT, as for a missing file.  The builtin handler
    said "not my format" with -ENOENT.  It now gives -ENOEXEC, as the other
    handlers do.
    
    load_absmodule() now keeps the first error that is not -ENOEXEC and
    returns it when no handler loads the file.  When every handler gives
    -ENOEXEC, it calls nx_stat(), because no handler may have looked at the
    file: only the builtin handler is there in some builds.  A file that no
    handler knows gives -ENOEXEC, a missing file -ENOENT, a script with a
    missing interpreter -ENOENT, and -EACCES still stops the search.
    
    Assisted-by: Claude Code:claude-opus-5-5
    Signed-off-by: Marco Casaroli <[email protected]>
---
 binfmt/binfmt_loadmodule.c | 37 +++++++++++++++++++++++++++++++++++--
 binfmt/builtin.c           |  4 ++--
 2 files changed, 37 insertions(+), 4 deletions(-)

diff --git a/binfmt/binfmt_loadmodule.c b/binfmt/binfmt_loadmodule.c
index 99480cef5f2..3cdbe142f10 100644
--- a/binfmt/binfmt_loadmodule.c
+++ b/binfmt/binfmt_loadmodule.c
@@ -26,6 +26,7 @@
 
 #include <nuttx/config.h>
 
+#include <sys/stat.h>
 #include <sched.h>
 #include <nuttx/debug.h>
 #include <errno.h>
@@ -36,6 +37,7 @@
 #include <nuttx/sched.h>
 #include <nuttx/kmalloc.h>
 #include <nuttx/binfmt/binfmt.h>
+#include <nuttx/fs/fs.h>
 
 #include "binfmt.h"
 
@@ -103,6 +105,8 @@ static int load_absmodule(FAR struct binary_s *bin, FAR 
const char *filename,
                           FAR const struct symtab_s *exports, int nexports)
 {
   FAR struct binfmt_s *binfmt;
+  struct stat buf;
+  int first = -ENOEXEC;
   int ret = -ENOENT;
 
   binfo("Loading %s\n", filename);
@@ -142,7 +146,18 @@ static int load_absmodule(FAR struct binary_s *bin, FAR 
const char *filename,
           binfmt_dumpmodule(bin);
           break;
         }
-      else if (ret == -EACCES)
+
+      /* -ENOEXEC is the "not my format" of a handler.  Keep the first other
+       * error (a missing file, or -ENOMEM from a handler that knew the
+       * format): the next handlers must not hide it.
+       */
+
+      if (first == -ENOEXEC && ret != -ENOEXEC)
+        {
+          first = ret;
+        }
+
+      if (ret == -EACCES)
         {
           /* Access explicitly denied -- stop here; do not let a fallback
            * loader bypass the execute-permission check that already ran.
@@ -152,7 +167,25 @@ static int load_absmodule(FAR struct binary_s *bin, FAR 
const char *filename,
         }
     }
 
-  return ret;
+  if (ret == OK)
+    {
+      return OK;
+    }
+
+  /* A handler that is not for this format need not look at the file, so
+   * only here do we know if a missing file is the reason.
+   */
+
+  if (first == -ENOEXEC)
+    {
+      ret = nx_stat(filename, &buf, 1);
+      if (ret < 0)
+        {
+          return ret;
+        }
+    }
+
+  return first;
 }
 
 /****************************************************************************
diff --git a/binfmt/builtin.c b/binfmt/builtin.c
index 04b5e4b3073..fa82eab54fb 100644
--- a/binfmt/builtin.c
+++ b/binfmt/builtin.c
@@ -92,8 +92,8 @@ static int builtin_loadbinary(FAR struct binary_s *binp,
   ret = builtin_isavail(filename);
   if (ret < 0)
     {
-      berr("ERROR: %s is not a builtin application\n", filename);
-      return ret;
+      binfo("%s is not a builtin application\n", filename);
+      return -ENOEXEC;
     }
 
   /* Return the load information.  NOTE: that there is no way to configure

Reply via email to