[PATCH] Capabilities in elf

Pavel Machek (pavel@bug.ucw.cz)
Wed, 14 Apr 1999 23:12:29 +0200


Hi!

Here is next version, this one is believed NOT to contain security
hole. Please take a look, and comment i.e. post me things like "GREAT!
this is going to be included in 2.2.6".

Pavel

--- clean//fs/binfmt_elf.c Fri Mar 26 17:46:23 1999
+++ linux/fs/binfmt_elf.c Tue Apr 13 20:50:54 1999
@@ -152,14 +152,14 @@
__put_user ((id), sp+(nr*2)); \
__put_user ((val), sp+(nr*2+1)); \

- sp -= 2;
+ sp -= 6;
NEW_AUX_ENT(0, AT_NULL, 0);
+ NEW_AUX_ENT(1, AT_HWCAP, hwcap);
+ NEW_AUX_ENT(2, AT_LINUX_FPUCW, 0 /* FPUCW_DEFAULT */ );
if (k_platform) {
sp -= 2;
NEW_AUX_ENT(0, AT_PLATFORM, (elf_addr_t)(unsigned long) u_platform);
}
- sp -= 2;
- NEW_AUX_ENT(0, AT_HWCAP, hwcap);

if (exec) {
sp -= 11*2;
@@ -425,8 +425,11 @@

retval = -ENOEXEC;
/* First of all, some simple consistency checks */
- if (elf_ex.e_ident[0] != 0x7f ||
- strncmp(&elf_ex.e_ident[1], "ELF", 3) != 0)
+ if (elf_ex.e_ident[0] != 0x7f)
+ goto out;
+
+ if (strncmp(&elf_ex.e_ident[1], "ELF", 3) &&
+ strncmp(&elf_ex.e_ident[1], "FLE", 3))
goto out;

if (elf_ex.e_type != ET_EXEC && elf_ex.e_type != ET_DYN)
@@ -471,6 +474,53 @@
start_code = ~0UL;
end_code = 0;
end_data = 0;
+
+ {
+ int size = elf_ex.e_shnum * sizeof(Elf32_Shdr);
+ char *buf = kmalloc(size, GFP_KERNEL);
+ Elf32_Shdr *shdr = buf;
+ int i;
+
+ retval = read_exec(bprm->dentry, elf_ex.e_shoff,
+ buf, size, 1);
+
+ for (i=0; i<elf_ex.e_shnum; i++) {
+ Elf32_Shdr *hdr = shdr+i;
+ struct elf_capabilities cap;
+
+ if (hdr->sh_type != 0xca)
+ continue;
+
+ printk( "Before: " );
+ printk( "uid = %d, effective = %x, permitted = %x, inheritable = %x\n", bprm->e_uid, bprm->cap_effective, bprm->cap_permitted, bprm->cap_inheritable );
+ printk( "Capabilities: " );
+
+ printk( "read: " );
+ read_exec(bprm->dentry, hdr->sh_offset, (void *) &cap, sizeof(struct elf_capabilities), 1);
+ printk( "ok, " );
+
+ printk( "read, " );
+ retval = -ENOEXEC;
+ if (cap.signature != 0xca5ab1e) {
+ printk( "signature = %x\n", cap.signature );
+ goto out;
+ }
+ printk( "sig ok, " );
+ if (!bprm->e_uid) { /* We only honour uid changes for root */
+ if (cap.flags & ECF_MAKE_EUID_UID)
+ bprm->e_uid = current->uid;
+ if (cap.flags & ECF_MAKE_EUID_XUID)
+ bprm->e_uid = cap.xuid;
+ }
+ cap_mask( bprm->cap_effective, cap.capabilities );
+ cap_mask( bprm->cap_permitted, cap.capabilities );
+#if 0
+ cap_mask( current->cap_inheritable, cap.capabilities );
+#endif
+ printk( "uid = %d, effective = %x, permitted = %x, inheritable = %x\n", bprm->e_uid, bprm->cap_effective, bprm->cap_permitted, bprm->cap_inheritable );
+
+ }
+ }

for (i = 0; i < elf_ex.e_phnum; i++) {
if (elf_ppnt->p_type == PT_INTERP) {
--- clean//include/linux/elf.h Thu Jun 25 17:38:14 1998
+++ linux/include/linux/elf.h Thu Apr 8 16:53:45 1999
@@ -27,6 +27,7 @@
#define PT_NOTE 4
#define PT_SHLIB 5
#define PT_PHDR 6
+#define PT_CAPABIL 7
#define PT_LOPROC 0x70000000
#define PT_HIPROC 0x7fffffff

@@ -130,6 +131,8 @@
#define AT_PLATFORM 15 /* string identifying CPU for optimizations */
#define AT_HWCAP 16 /* arch dependent hints at CPU capabilities */

+#define AT_LINUX_FPUCW 2134
+
typedef struct dynamic{
Elf32_Sword d_tag;
union{
@@ -275,6 +278,7 @@
/* Legal values for e_flags field of Elf64_Ehdr. */

#define EF_ALPHA_32BIT 1 /* All addresses are below 2GB */
+#define EF_CAPABLE 2 /* Includes capabilities header */


typedef struct elf32_rel {
@@ -322,19 +326,20 @@

typedef struct elf32_hdr{
unsigned char e_ident[EI_NIDENT];
- Elf32_Half e_type;
+/*16*/ Elf32_Half e_type;
Elf32_Half e_machine;
Elf32_Word e_version;
Elf32_Addr e_entry; /* Entry point */
Elf32_Off e_phoff;
- Elf32_Off e_shoff;
+/*32*/ Elf32_Off e_shoff;
Elf32_Word e_flags;
- Elf32_Half e_ehsize;
+/*40*/ Elf32_Half e_ehsize;
Elf32_Half e_phentsize;
Elf32_Half e_phnum;
Elf32_Half e_shentsize;
Elf32_Half e_shnum;
Elf32_Half e_shstrndx;
+/*52 == 0x34 */
} Elf32_Ehdr;

typedef struct elf64_hdr {
@@ -369,6 +374,7 @@
Elf32_Word p_memsz;
Elf32_Word p_flags;
Elf32_Word p_align;
+/*32 == 0x20*/
} Elf32_Phdr;

typedef struct elf64_phdr {
@@ -495,6 +501,17 @@
Elf32_Word n_descsz; /* Content size */
Elf32_Word n_type; /* Content type */
} Elf64_Nhdr;
+
+/* Capabilities support
+ */
+struct elf_capabilities {
+ Elf32_Word signature;
+ Elf32_Word capabilities;
+ Elf32_Word flags;
+#define ECF_MAKE_EUID_UID 1
+#define ECF_MAKE_EUID_XUID 2
+ Elf32_Word xuid;
+};

#if ELF_CLASS == ELFCLASS32

-- 
I'm really pavel@atrey.karlin.mff.cuni.cz. 	   Pavel
Look at http://atrey.karlin.mff.cuni.cz/~pavel/ ;-).

- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.rutgers.edu Please read the FAQ at http://www.tux.org/lkml/