Implement Linux personality() system call mainly due to READ_IMPLIES_EXEC flag.
In Linux if this flag is set, PROT_READ implies PROT_EXEC for mmap(). Linux/i386 set this flag automatically if the binary requires executable stack. READ_IMPLIES_EXEC flag will be used in the next Linux mmap() commit.
This commit is contained in:
parent
51d1f69069
commit
23e8912c60
@ -270,7 +270,7 @@
|
||||
133 AUE_MKNOD STD { int linux_mknod(char *path, l_int mode, \
|
||||
l_dev_t dev); }
|
||||
134 AUE_USELIB UNIMPL uselib
|
||||
135 AUE_PERSONALITY STD { int linux_personality(l_ulong per); }
|
||||
135 AUE_PERSONALITY STD { int linux_personality(l_uint per); }
|
||||
136 AUE_NULL STD { int linux_ustat(l_dev_t dev, \
|
||||
struct l_ustat *ubuf); }
|
||||
137 AUE_STATFS STD { int linux_statfs(char *path, \
|
||||
|
@ -238,7 +238,7 @@
|
||||
134 AUE_BDFLUSH STD { int linux_bdflush(void); }
|
||||
135 AUE_NULL STD { int linux_sysfs(l_int option, \
|
||||
l_ulong arg1, l_ulong arg2); }
|
||||
136 AUE_PERSONALITY STD { int linux_personality(l_ulong per); }
|
||||
136 AUE_PERSONALITY STD { int linux_personality(l_uint per); }
|
||||
137 AUE_NULL UNIMPL afs_syscall
|
||||
138 AUE_SETFSUID STD { int linux_setfsuid16(l_uid16_t uid); }
|
||||
139 AUE_SETFSGID STD { int linux_setfsgid16(l_gid16_t gid); }
|
||||
|
@ -45,6 +45,7 @@ __FBSDID("$FreeBSD$");
|
||||
|
||||
#include <compat/linux/linux_emul.h>
|
||||
#include <compat/linux/linux_misc.h>
|
||||
#include <compat/linux/linux_persona.h>
|
||||
#include <compat/linux/linux_util.h>
|
||||
|
||||
|
||||
@ -127,7 +128,7 @@ linux_proc_init(struct thread *td, struct thread *newtd, int flags)
|
||||
/* epoll should be destroyed in a case of exec. */
|
||||
pem = pem_find(p);
|
||||
KASSERT(pem != NULL, ("proc_exit: proc emuldata not found.\n"));
|
||||
|
||||
pem->persona = 0;
|
||||
if (pem->epoll != NULL) {
|
||||
emd = pem->epoll;
|
||||
pem->epoll = NULL;
|
||||
@ -220,6 +221,9 @@ linux_proc_exec(void *arg __unused, struct proc *p, struct image_params *imgp)
|
||||
{
|
||||
struct thread *td = curthread;
|
||||
struct thread *othertd;
|
||||
#if defined(__amd64__)
|
||||
struct linux_pemuldata *pem;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* In a case of execing from linux binary properly detach
|
||||
@ -243,6 +247,17 @@ linux_proc_exec(void *arg __unused, struct proc *p, struct image_params *imgp)
|
||||
linux_proc_init(td, NULL, 0);
|
||||
else
|
||||
linux_proc_init(td, td, 0);
|
||||
#if defined(__amd64__)
|
||||
/*
|
||||
* An IA32 executable which has executable stack will have the
|
||||
* READ_IMPLIES_EXEC personality flag set automatically.
|
||||
*/
|
||||
if (SV_PROC_FLAG(td->td_proc, SV_ILP32) &&
|
||||
imgp->stack_prot & VM_PROT_EXECUTE) {
|
||||
pem = pem_find(p);
|
||||
pem->persona |= LINUX_READ_IMPLIES_EXEC;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -67,6 +67,7 @@ struct linux_pemuldata {
|
||||
uint32_t flags; /* process emuldata flags */
|
||||
struct sx pem_sx; /* lock for this struct */
|
||||
void *epoll; /* epoll data */
|
||||
uint32_t persona; /* process execution domain */
|
||||
};
|
||||
|
||||
#define LINUX_PEM_XLOCK(p) sx_xlock(&(p)->pem_sx)
|
||||
|
@ -1200,15 +1200,23 @@ linux_mknodat(struct thread *td, struct linux_mknodat_args *args)
|
||||
int
|
||||
linux_personality(struct thread *td, struct linux_personality_args *args)
|
||||
{
|
||||
struct linux_pemuldata *pem;
|
||||
struct proc *p = td->td_proc;
|
||||
uint32_t old;
|
||||
|
||||
#ifdef DEBUG
|
||||
if (ldebug(personality))
|
||||
printf(ARGS(personality, "%lu"), (unsigned long)args->per);
|
||||
printf(ARGS(personality, "%u"), args->per);
|
||||
#endif
|
||||
if (args->per != 0)
|
||||
return (EINVAL);
|
||||
|
||||
/* Yes Jim, it's still a Linux... */
|
||||
td->td_retval[0] = 0;
|
||||
PROC_LOCK(p);
|
||||
pem = pem_find(p);
|
||||
old = pem->persona;
|
||||
if (args->per != 0xffffffff)
|
||||
pem->persona = args->per;
|
||||
PROC_UNLOCK(p);
|
||||
|
||||
td->td_retval[0] = old;
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
56
sys/compat/linux/linux_persona.h
Normal file
56
sys/compat/linux/linux_persona.h
Normal file
@ -0,0 +1,56 @@
|
||||
/*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef LINUX_PERSONALITY_H
|
||||
#define LINUX_PERSONALITY_H
|
||||
|
||||
/*
|
||||
* Flags for bug emulation.
|
||||
*
|
||||
* These occupy the top three bytes.
|
||||
*/
|
||||
enum {
|
||||
LINUX_UNAME26 = 0x0020000,
|
||||
LINUX_ADDR_NO_RANDOMIZE = 0x0040000, /* disable randomization
|
||||
* of VA space
|
||||
*/
|
||||
LINUX_FDPIC_FUNCPTRS = 0x0080000, /* userspace function
|
||||
* ptrs point to descriptors
|
||||
* (signal handling)
|
||||
*/
|
||||
LINUX_MMAP_PAGE_ZERO = 0x0100000,
|
||||
LINUX_ADDR_COMPAT_LAYOUT = 0x0200000,
|
||||
LINUX_READ_IMPLIES_EXEC = 0x0400000,
|
||||
LINUX_ADDR_LIMIT_32BIT = 0x0800000,
|
||||
LINUX_SHORT_INODE = 0x1000000,
|
||||
LINUX_WHOLE_SECONDS = 0x2000000,
|
||||
LINUX_STICKY_TIMEOUTS = 0x4000000,
|
||||
LINUX_ADDR_LIMIT_3GB = 0x8000000,
|
||||
};
|
||||
|
||||
/*
|
||||
* Security-relevant compatibility flags that must be
|
||||
* cleared upon setuid or setgid exec:
|
||||
*/
|
||||
#define LINUX_PER_CLEAR_ON_SETID (LINUX_READ_IMPLIES_EXEC | \
|
||||
LINUX_ADDR_NO_RANDOMIZE | \
|
||||
LINUX_ADDR_COMPAT_LAYOUT | \
|
||||
LINUX_MMAP_PAGE_ZERO)
|
||||
|
||||
/*
|
||||
* Personality types.
|
||||
*
|
||||
* These go in the low byte. Avoid using the top bit, it will
|
||||
* conflict with error returns.
|
||||
*/
|
||||
enum {
|
||||
LINUX_PER_LINUX = 0x0000,
|
||||
LINUX_PER_LINUX_32BIT = 0x0000 | LINUX_ADDR_LIMIT_32BIT,
|
||||
LINUX_PER_LINUX_FDPIC = 0x0000 | LINUX_FDPIC_FUNCPTRS,
|
||||
LINUX_PER_LINUX32 = 0x0008,
|
||||
LINUX_PER_LINUX32_3GB = 0x0008 | LINUX_ADDR_LIMIT_3GB,
|
||||
LINUX_PER_MASK = 0x00ff,
|
||||
};
|
||||
|
||||
#endif /* LINUX_PERSONALITY_H */
|
@ -240,7 +240,7 @@
|
||||
134 AUE_BDFLUSH STD { int linux_bdflush(void); }
|
||||
135 AUE_NULL STD { int linux_sysfs(l_int option, \
|
||||
l_ulong arg1, l_ulong arg2); }
|
||||
136 AUE_PERSONALITY STD { int linux_personality(l_ulong per); }
|
||||
136 AUE_PERSONALITY STD { int linux_personality(l_uint per); }
|
||||
137 AUE_NULL UNIMPL afs_syscall
|
||||
138 AUE_SETFSUID STD { int linux_setfsuid16(l_uid16_t uid); }
|
||||
139 AUE_SETFSGID STD { int linux_setfsgid16(l_gid16_t gid); }
|
||||
|
Loading…
x
Reference in New Issue
Block a user