Messages in this thread Patch in this message | | | Date | Fri, 11 Feb 2000 12:53:03 +0100 | From | Pavel Machek <> | Subject | [PATCH] Re: Capabilities |
| |
Hi!
> > > > I want setuid root programs not to have all capabilites. cap_bound is > > > > not the answer since I still want some programs that are started from > > > > the system initialisation scripts to run with all capabilities. > > > > > > Mmm.. I'd like that too. > > > > You'll get that when the filesystem support for capabilities goes in. > > > > Alternatively, tighten up the bounding set as part of your system > > initialisation scripts. > > Read what the man says, Chris. He wants to be able to decree that > setuid programs (for example) don't get CNBS without breaking inetd. > > I don't believe that this is functionality for its own sake. If > you think or it as a sysctl which allows you to turn off bits of > SECURE_NO_SETUID_FIXUP.
Look at http://atrey.karlin.mff.cuni.cz/~pavel/caps/elfcap.html for stuff like that. You can then select on one-by-one basis which file should get what permissions.
Pavel
Hi!
This is next try with capabilities; this is version 9 (wow!), this time against 2.3.3. It includes updated documentation. Please notice that it is possible to add elf note to existing executable (software for doing it is present at http://atrey.karlin.mff.cuni.cz/~pavel/elfcap.html), and enhancing security of your system could be as easy as running one script.
Please roll in, Pavel
--- clean//include/linux/elf.h Thu Jun 25 17:38:14 1998 +++ linux/include/linux/elf.h Tue May 18 22:34:21 1999 @@ -496,6 +496,27 @@ Elf32_Word n_type; /* Content type */ } Elf64_Nhdr; +/* Capabilities support + */ +struct elf_capabilities { + __u32 signature; + __u32 version; /* Currently 0; this is so that you can append on the end painlessly */ + __u32 flags; +#define ECF_MAKE_EUID_UID 1 +#define ECF_MAKE_EUID_XUID 2 + __u32 xuid; /* We want our set 128bit for future expansion */ + __u32 effective, effective1, effective2, effective3; + __u32 permitted, permitted1, permitted2, permitted3; + __u32 inheritable, inheritable1, inheritable2, inheritable3; + __u32 known, known1, known2, known3; +}; + +struct elf_capabilities_note { + Elf32_Nhdr nhdr; + __u32 note_signature; /* == "CAPS" */ + struct elf_capabilities cap; +}; + #if ELF_CLASS == ELFCLASS32 extern Elf32_Dyn _DYNAMIC []; --- clean//fs/binfmt_elf.c Thu May 13 22:41:36 1999 +++ linux/fs/binfmt_elf.c Thu May 13 22:32:54 1999 @@ -7,6 +7,7 @@ * Tools". * * Copyright 1993, 1994: Eric Youngdale (ericy@cais.com). + * Capabilities copyright 1999 Pavel Machek (pavel@ucw.cz). */ #include <linux/module.h> @@ -387,6 +388,26 @@ return elf_entry; } +static void +restrict( struct linux_binprm * bprm, struct elf_capabilities *cap ) +{ + if (cap->signature != 0xca5ab1e) + return; + + /* I do not check versions... That is because current version + is 0 and I expect all changes to be backward - compabtible */ + if (cap->flags & ECF_MAKE_EUID_UID) /* You may want to loose owner's uid */ + bprm->e_uid = current->uid; + if ((!bprm->e_uid) && (cap->flags & ECF_MAKE_EUID_XUID)) + bprm->e_uid = cap->xuid; /* We only honour random uid changes for root */ + cap_mask( bprm->cap_effective, cap->effective ); + cap_mask( bprm->cap_permitted, cap->permitted ); + cap_mask( bprm->cap_inheritable, cap->inheritable ); + + printk( KERN_DEBUG "Now: uid = %d, effective = %x, permitted = %x, inheritable = %x\n", bprm->e_uid, bprm->cap_effective, bprm->cap_permitted, bprm->cap_inheritable ); +} + + /* * These are the functions used to load ELF style executables and shared * libraries. There is no binary dependent code anywhere else. @@ -396,6 +417,7 @@ #define INTERPRETER_AOUT 1 #define INTERPRETER_ELF 2 +#define roundup(x, y) ((((x)+((y)-1))/(y))*(y)) static inline int do_load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs) @@ -473,6 +498,22 @@ end_data = 0; for (i = 0; i < elf_ex.e_phnum; i++) { + if (elf_ppnt->p_type == PT_NOTE) { + struct elf_capabilities_note note; + int offset = elf_ppnt->p_offset; + int maxoffset = offset + elf_ppnt->p_filesz; + + while (offset <= (maxoffset - sizeof(note))) { + int retval; + retval = read_exec(bprm->dentry, offset, (void *) ¬e, + sizeof(note), 1); + if (retval != sizeof(note)) + goto skip; + if (note.note_signature == be32_to_cpu(0x43415053)) /* "CAPS" */ + restrict(bprm, ¬e.cap); + offset += sizeof(Elf32_Nhdr) + roundup(note.nhdr.n_namesz, 4) + roundup(note.nhdr.n_descsz, 4); + } + } if (elf_ppnt->p_type == PT_INTERP) { retval = -EINVAL; if (elf_interpreter) @@ -533,6 +574,7 @@ interp_ex = *((struct exec *) bprm->buf); interp_elf_ex = *((struct elfhdr *) bprm->buf); } + skip: elf_ppnt++; } --- /dev/null Tue Jul 21 02:45:36 1998 +++ linux/Documentation/capabilities.txt Tue May 18 23:00:37 1999 @@ -0,0 +1,48 @@ +Elf capabilities hack + + From now on, there's support for capabilities in elf executable. Elf + executable now may contain "capabilities header", telling which + capabilities should be dropped on exec. This can not hurt: lowering + capabilities is not priviledged operation, and executable could do it + itself at beggining of main. + + Doing it in exec() time has certain advantages, through: you can + easily look and what capabilities are in use by what program and you + can set capabilities for existing executables without need to + recompile. (It is hard to create tool which insers elfcap header into + elf file. But it has been done. Inserting code to drop capabilities on + the beggining of main would be nightmare.) + + Notice that this system is very nice, but as described has limited + use. It only lowers capabilities, and raising capabilities is what + causes problems. (50% of security holes in unix are related to setuid0 + programs). But wait: elfcap can easily be used to limit damage done by + setuid0 programs. It needs only little trick: ability to set euid back + to ruid. By setuid0, process gets all capabilities, and elfcap is free + to drop that capabilities it does not want. + + So, along with existing setuid mechanism, this hack can be used to + grant subset of capabilities to executables. For example currently + ping has to be setuid0. With elfcap, ping still will be setuid0, but + most of its capabilities (and its euid) will be dropped at exec() + time, so breaking into ping will allow attacker to generate arbitrary + packets to network, but nothing more. + + Summary of what can elfcap do: + * mask inheritable, permitted and effective sets by arbitrary mask + * set euid back to ruid (effectivelly undoing result of setuid bit) + * set euid to arbitrary value if euid==0 (don't tell anyone, that's + really dirty piece of patch and may be dropped) + + For more info & utility programs, look at + http://atrey.karlin.mff.cuni.cz/~pavel/elfcap.html. + +Bad idea + + I should empatize that it is bad idea to give suid0 to any program + just because you have capabilities. If program did not have suid0 + yesterday, it probably should not have suid0 today. (Think about + booting old kernel, for example). + + Pavel Machek +
-- I'm pavel@ucw.cz. "In my country we have almost anarchy and I don't care." Panos Katsaloulis describing me w.r.t. patents me at discuss@linmodems.org
- 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/
| |