From 2d73e86b474d821ac80e24f88c5034dabe679cb5 Mon Sep 17 00:00:00 2001 From: fangxinyong Date: Fri, 11 Aug 2023 20:09:21 +0800 Subject: [PATCH] binfmt: support euid of process set from the file system From posix spec, if set-user-ID bit is set in the file permissions, then the effective user ID of the new process shall be set to the user ID of the new process image file. Let's ignore whether ST_NOSUID is set on the mounted file system. https://pubs.opengroup.org/onlinepubs/007904875/functions/exec.html test step: hello example build as a module and call geteuid and getegid API. then set file binary set-user-ID bit on the host. $ chmod +s apps/bin/hello nsh> mount -t hostfs -o fs=. /data nsh> ls -l /data/apps/bin/hello -rwsrwsr-x 1000 1000 9264 /data/apps/bin/hello nsh> /data/apps/bin/hello geteuid:1000 getegid:1000 Signed-off-by: fangxinyong --- binfmt/binfmt_execmodule.c | 13 +++++++++++++ binfmt/elf.c | 8 ++++++++ binfmt/libelf/libelf_init.c | 19 +++++++++++-------- include/nuttx/binfmt/binfmt.h | 5 +++++ include/nuttx/binfmt/elf.h | 3 +++ 5 files changed, 40 insertions(+), 8 deletions(-) diff --git a/binfmt/binfmt_execmodule.c b/binfmt/binfmt_execmodule.c index 6ea8d6beaa6..b660e3eef26 100644 --- a/binfmt/binfmt_execmodule.c +++ b/binfmt/binfmt_execmodule.c @@ -24,6 +24,7 @@ #include +#include #include #include #include @@ -279,6 +280,18 @@ int exec_module(FAR struct binary_s *binp, pid = tcb->cmn.pid; +#ifdef CONFIG_SCHED_USER_IDENTITY + if (binp->mode & S_ISUID) + { + tcb->cmn.group->tg_euid = binp->uid; + } + + if (binp->mode & S_ISGID) + { + tcb->cmn.group->tg_egid = binp->gid; + } +#endif + /* Then activate the task at the provided priority */ nxtask_activate((FAR struct tcb_s *)tcb); diff --git a/binfmt/elf.c b/binfmt/elf.c index 708b05afbd8..81c5fdf8458 100644 --- a/binfmt/elf.c +++ b/binfmt/elf.c @@ -318,6 +318,14 @@ static int elf_loadbinary(FAR struct binary_s *binp, binp->ndtors = loadinfo.ndtors; #endif +#ifdef CONFIG_SCHED_USER_IDENTITY + /* Save IDs and mode from file system */ + + binp->uid = loadinfo.fileuid; + binp->gid = loadinfo.filegid; + binp->mode = loadinfo.filemode; +#endif + elf_dumpentrypt(binp, &loadinfo); elf_uninit(&loadinfo); return OK; diff --git a/binfmt/libelf/libelf_init.c b/binfmt/libelf/libelf_init.c index c355e34dfa5..95a7a0c91e5 100644 --- a/binfmt/libelf/libelf_init.c +++ b/binfmt/libelf/libelf_init.c @@ -64,10 +64,10 @@ ****************************************************************************/ /**************************************************************************** - * Name: elf_filelen + * Name: elf_fileinfo * * Description: - * Get the size of the ELF file + * Get some stats info of the ELF file * * Returned Value: * 0 (OK) is returned on success and a negated errno is returned on @@ -75,7 +75,7 @@ * ****************************************************************************/ -static inline int elf_filelen(FAR struct elf_loadinfo_s *loadinfo) +static inline int elf_fileinfo(FAR struct elf_loadinfo_s *loadinfo) { struct stat buf; int ret; @@ -89,9 +89,12 @@ static inline int elf_filelen(FAR struct elf_loadinfo_s *loadinfo) return ret; } - /* Return the size of the file in the loadinfo structure */ + /* Return some stats info of the file in the loadinfo structure */ - loadinfo->filelen = buf.st_size; + loadinfo->filelen = buf.st_size; + loadinfo->fileuid = buf.st_uid; + loadinfo->filegid = buf.st_gid; + loadinfo->filemode = buf.st_mode; return OK; } @@ -131,12 +134,12 @@ int elf_init(FAR const char *filename, FAR struct elf_loadinfo_s *loadinfo) return ret; } - /* Get the length of the file. */ + /* Get some stats info of the file. */ - ret = elf_filelen(loadinfo); + ret = elf_fileinfo(loadinfo); if (ret < 0) { - berr("elf_filelen failed: %d\n", ret); + berr("elf_fileinfo failed: %d\n", ret); return ret; } diff --git a/include/nuttx/binfmt/binfmt.h b/include/nuttx/binfmt/binfmt.h index 0e9d6d61ab4..1c90c60fe15 100644 --- a/include/nuttx/binfmt/binfmt.h +++ b/include/nuttx/binfmt/binfmt.h @@ -98,6 +98,11 @@ struct binary_s uint8_t priority; /* Task execution priority */ size_t stacksize; /* Size of the stack in bytes (unallocated) */ +#ifdef CONFIG_SCHED_USER_IDENTITY + uid_t uid; /* File owner user identity */ + gid_t gid; /* File owner group user identity */ + int mode; /* File mode added to */ +#endif #ifndef CONFIG_BUILD_KERNEL FAR void *stackaddr; /* Task stack address */ diff --git a/include/nuttx/binfmt/elf.h b/include/nuttx/binfmt/elf.h index 3f35f609c55..14d9e123392 100644 --- a/include/nuttx/binfmt/elf.h +++ b/include/nuttx/binfmt/elf.h @@ -97,6 +97,9 @@ struct elf_loadinfo_s size_t textalign; /* Necessary alignment of .text */ size_t dataalign; /* Necessary alignment of .bss/.data */ off_t filelen; /* Length of the entire ELF file */ + uid_t fileuid; /* Uid of the file system */ + gid_t filegid; /* Gid of the file system */ + int filemode; /* Mode of the file system */ Elf_Ehdr ehdr; /* Buffered ELF file header */ FAR Elf_Shdr *shdr; /* Buffered ELF section headers */