Messages in this thread Patch in this message | | | Date | Mon, 26 Apr 1999 17:07:44 -0700 (PDT) | From | Y2K <> | Subject | Again more work on binfmt_elf.c |
| |
In responce to Jeremy's earlier patch. Mostly just added function do_elfcap_restrict() . Patch is off of standard clean 2.2.6 but needs other patches such as earlier ones to work right.
--- binfmt_elf.c.old Mon Apr 26 16:51:10 1999 +++ binfmt_elf.c Mon Apr 26 16:48:32 1999 @@ -396,6 +396,68 @@ #define INTERPRETER_AOUT 1 #define INTERPRETER_ELF 2 +#define roundup(x, y) ((((x)+((y)-1))/(y))*(y)) + +/* Given a pointer to a set of notes, find the first with the given + name and type */ +static void *find_note(char *buf, int bufsz, const char *notename, int type) +{ + while(bufsz > sizeof(Elf32_Nhdr)) { + Elf32_Nhdr *nhdr = (Elf32_Nhdr *)buf; + char *name; + void *desc; + int sz; + + sz = sizeof(Elf32_Nhdr) + + roundup(nhdr->n_namesz, 4) + + roundup(nhdr->n_descsz, 4); + if (bufsz < sz) + break; + name = buf + sizeof(Elf32_Nhdr); + desc = name + roundup(nhdr->n_namesz, 4); + + if (strncmp(name, notename, nhdr->n_namesz) == 0 && + type == nhdr->n_type) + return desc; + + buf += sz; + bufsz -= sz; + } + + return NULL; +} + +static inline int +do_elfcap_restrict(struct linux_binprm *bprm, struct elf_capability_note *note) +{ + /* check version */ + if (note.cap.signature!=0xca5ab1e || note.cap.version) + return 0; + /* You may want to loose owner's uid */ + if (note.cap.flags & ECF_MAKE_EUID_UID) + bprm->e_uid = current->uid; + /* We only honour random uid changes for root */ + /* we also care about CAP_SETUID here */ + if (!bprm->e_uid&&(note.cap.flags&ECF_MAKE_EUID_XUID)&& + (capable(CAP_SETUID)|| cap_raised(bprm->permitted,CAP_SETUID)) ) + bprm->e_uid = note.cap.xuid; + + cap_mask( bprm->cap_effective, note.cap.effective ); + cap_mask( bprm->cap_permitted, note.cap.permitted ); + cap_mask( bprm->cap_inheritable, note.cap.inheritable ); + + /* required needs more work */ + if (!cap_issubset(note.cap.required,bprm->cap_inheritable) ) + return -EPERM; + + if (note.cap.securebits&&capable(CAP_LINUX_SECUREBITS) ) + SECUREBITS_SET(bprm->securebits, note.cap.securebits); + else if (note.cap.securebits) + return -EPERM; + + return 0; + +} static inline int do_load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs) @@ -425,8 +487,10 @@ 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) @@ -473,7 +537,48 @@ end_data = 0; for (i = 0; i < elf_ex.e_phnum; i++) { - if (elf_ppnt->p_type == PT_INTERP) { + switch(elf_ppnt->p_type) { + case PT_NOTE: { + struct elf_capabilities_note *caps; + char *buf; + int subret = 0; + + retval = -ENOMEM; + buf = kmalloc(elf_ppnt->p_filesz, GFP_KERNEL); + + if (buf == NULL) + goto out_free_dentry; + + retval = read_exec(bprm->dentry, elf_ppnt->p_offset, + buf, elf_ppnt->p_filesz, 1); + + if (retval < 0) { + kfree(buf); + goto out_free_dentry; + } + + caps = (struct elf_capabilities_note *)find_note(buf, + elf_ppnt->p_filesz, "CAPS", NT_ELF_CAP); + + if (caps != NULL) { + /* what to do with multiple CAPS notes? + Find the most restrictive union? */ + + /* process caps here */ + subret=do_elfcap_restrict(bprm, caps); + + printk("found CAPS note!\n"); + } + + kfree(buf); + if (subret) { + retval=subret; + goto out_free_ph; + } + } + break; + + case PT_INTERP: { retval = -EINVAL; if (elf_interpreter) goto out_free_interp; @@ -533,6 +638,8 @@ interp_ex = *((struct exec *) bprm->buf); interp_elf_ex = *((struct elfhdr *) bprm->buf); } + break; + } elf_ppnt++; } @@ -777,7 +884,8 @@ /* error cleanup */ out_free_dentry: - dput(interpreter_dentry); + if (interpreter_dentry) + dput(interpreter_dentry); out_free_interp: if (elf_interpreter) kfree(elf_interpreter); -- Warning: When I mention capabilites I mean "soiled" capabilities not "pure draft". Any caps I mention are *derived* from a withdrawn draft posix document.
- 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/
| |