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 <fangxinyong@xiaomi.com>
This commit is contained in:
fangxinyong 2023-08-11 20:09:21 +08:00 committed by Xiang Xiao
parent cd5ee3fb07
commit 2d73e86b47
5 changed files with 40 additions and 8 deletions

View File

@ -24,6 +24,7 @@
#include <nuttx/config.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <stdint.h>
#include <stdlib.h>
@ -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);

View File

@ -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;

View File

@ -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;
}

View File

@ -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 */

View File

@ -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 */