Before executing a program, the kernel marks the executable file as immutable by setting the VTEXT flag in its vnode. This makes write operations return with ETXTBSY when attempted. However, no such flag is set for shared libraries mapped by rtld. This patch adds a new fcntl command, F_TXTBSY, which sets the VTEXT flag in the vnode associated with the file, and gets rtld-elf to make use of it. There may be security issues here, allowing user code to set this flag in contexts it wasn't designed for, but I don't think it allows you do anything that you couldn't already. You can't stop someone creating a custom executable in order to get VTEXT set on it anyway, and root can always kill any processes holding the object in memory to clear the flag if neccessary. Fix: Apply the following patch. How-To-Repeat: Write a program that depends on a shared library, and overwrite that library while the program is running. Bad Things happen. Trying the same on an executable results in the write operation returning ETXTBSY
Hm. This is possibly a nicer way to do it, and certainly a smaller, if more intrusive, patch. It changes the semantics of mmap() somewhat, but I think in a reasonable way, and it avoids all that ugliness in the run-time linker. Basically, a request for PROT_EXEC on a regular file will cause it to become immutable: --- vm_mmap.c 3 Nov 2001 01:41:10 -0000 1.108.2.5 +++ vm_mmap.c 13 Jun 2002 19:15:28 -0000 @@ -406,8 +406,17 @@ error = vm_mmap(&vms->vm_map, &addr, size, prot, maxprot, flags, handle, pos); - if (error == 0) + if (error == 0) { p->p_retval[0] = (register_t) (addr + pageoff); + /* + * A successful map for a regular file, with execute access: + * mark the vnode immutable. + * XXX: GCC warns, but (handle == 0 || handle == vp) + * I'm not sure of the "correct" way to avoid this. + */ + if (handle && vp->v_type == VREG && (prot & PROT_EXEC)) + vp->v_flag |= VTEXT; + } done: if (fp) fdrop(fp, p); Of course, the utility of all this is questionable: I just wanted the functionality for something locally. Cheers, Peter
Responsible Changed From-To: freebsd-bugs->jmg I'm going to take this, since I'm interested in it.
Responsible Changed From-To: jmg->freebsd-bugs no progress from jmg since 2003
For bugs matching the following criteria: Status: In Progress Changed: (is less than) 2014-06-01 Reset to default assignee and clear in-progress tags. Mail being skipped
Keyword: patch or patch-ready – in lieu of summary line prefix: [patch] * bulk change for the keyword * summary lines may be edited manually (not in bulk). Keyword descriptions and search interface: <https://bugs.freebsd.org/bugzilla/describekeywords.cgi>